UNPKG

9.88 MBSource Map (JSON)View Raw
1{"version":3,"sources":["/ts/VisualsContracts/common/enums.ts","/ts/visualsExtensibility/telemetry/generateGuid.ts","/ts/visualsExtensibility/telemetry/events.ts","/ts/visualsExtensibility/decorators/VisualPlugin.ts","/ts/visualsExtensibility/components/selectionManager.ts","/ts/visualsExtensibility/components/selectionIdBuilder.ts","/ts/visualsExtensibility/versioning/VisualAdapter.ts","/source/VisualsExtensibility.js","/ts/visualsExtensibility/versioning/VisualSafeExecutionWrapper.ts","/ts/visualsExtensibility/versioning/versions/v1.0.0.ts","/ts/visualsExtensibility/versioning/versions/v1.1.0.ts","/ts/visualsCommon/DOMConstants.ts","/ts/visualsCommon/serviceError.ts","/source/VisualsCommon.js","/ts/visualsCommon/services/build.ts","/ts/visualsCommon/services/geoTaggingAnalyzerService.ts","/ts/visualsCommon/typedefs/buildConstants.ts","/ts/visualsCommon/clientError.ts","/ts/visualsCommon/arrayExtensions.ts","/ts/visualsCommon/Controls/DomFactory.ts","/ts/visualsCommon/Double.ts","/ts/visualsCommon/color.ts","/ts/visualsCommon/CssConstants.ts","/ts/visualsCommon/debug.ts","/ts/visualsCommon/Errors.ts","/ts/visualsCommon/JQueryExtensions.ts","/ts/visualsCommon/Lazy.ts","/ts/visualsCommon/Prototype.ts","/ts/visualsCommon/Formatting.ts","/ts/visualsCommon/services/requires.ts","/ts/visualsCommon/services/jqueryPromiseFactory.ts","/ts/visualsCommon/services/localStorageService.ts","/ts/visualsCommon/Utility/wordBreaker.ts","/ts/visualsCommon/services/textMeasurementService.ts","/ts/visualsCommon/Utility/keyUtils.ts","/ts/visualsCommon/Utility/ThrottleUtility.ts","/ts/visualsCommon/Utility/TimerPromiseFactory.ts","/ts/visualsCommon/Utility/Utility.ts","/ts/visualsCommon/tracing/traceItem.ts","/ts/visualsCommon/Utility/urlUtils.ts","/ts/visualsCommon/Utility/browserUtils.ts","/ts/visualsCommon/Utility/StandaloneUtility.ts","/ts/visualsCommon/Utility/styleUtils.ts","/ts/visualsCommon/tracing/trace.ts","/ts/visualsCommon/tracing/traceType.ts","/ts/visualsCommon/services/dependencies.ts","/ts/visualsCommon/TraceType.ts","/source/VisualsData.js","/ts/visualsData/semanticQuery/sqExprVisitor.ts","/ts/visualsData/types/enumType.ts","/ts/visualsData/types/fill.ts","/ts/visualsData/types/image.ts","/ts/visualsData/types/structuralType.ts","/ts/visualsData/types/valueType.ts","/ts/visualsData/contracts/dataShapeBinding.ts","/ts/visualsData/contracts/dataShapeBindingDataReduction.ts","/ts/visualsData/contracts/federatedConceptualSchema.ts","/ts/visualsData/contracts/selector.ts","/ts/visualsData/contracts/query.ts","/ts/visualsData/contracts/queryProjection.ts","/ts/visualsData/contracts/visualData.ts","/ts/visualsData/formatting/dateTimeSequence.ts","/ts/visualsData/formatting/displayUnitSystem.ts","/ts/visualsData/formatting/numericSequence.ts","/ts/visualsData/formatting/numericSequenceRange.ts","/ts/visualsData/formatting/valueFormatter.ts","/ts/visualsData/dataView/dataRoleHelper.ts","/ts/visualsData/dataView/dataViewCategoricalReader.ts","/ts/visualsData/dataView/dataViewConcatenateCategoricalColumns.ts","/ts/visualsData/dataView/dataViewMappingVisitor.ts","/ts/visualsData/dataView/dataViewNormalizeValues.ts","/ts/visualsData/dataView/dataViewObject.ts","/ts/visualsData/dataView/dataViewObjectDefinition.ts","/ts/visualsData/dataView/dataViewObjectDescriptor.ts","/ts/visualsData/dataView/dataViewObjectEvaluationUtils.ts","/ts/visualsData/dataView/dataViewObjectEvaluator.ts","/ts/visualsData/dataView/dataViewPivotCategorical.ts","/ts/visualsData/dataView/dataViewPivotMatrix.ts","/ts/visualsData/dataView/dataViewSelfCrossJoin.ts","/ts/visualsData/dataView/dataViewPivotCategoricalToPrimaryGroups.ts","/ts/visualsData/dataView/dataViewTransform.ts","/ts/visualsData/displayNameGetter.ts","/ts/visualsData/iFormattingService.ts","/ts/visualsData/semanticQuery/exprPatterns/fieldExprPattern.ts","/ts/visualsData/dataView/dataViewAnalysis.ts","/ts/visualsData/dataView/dataViewRoleWildcard.ts","/ts/visualsData/dataView/dataViewScopeIdentity.ts","/ts/visualsData/dataView/dataViewScopeWildcard.ts","/ts/visualsData/dataView/rules/colorAllocatorCache.ts","/ts/visualsData/dataView/dataViewRegression.ts","/ts/visualsData/dataView/dataViewSelectTransform.ts","/ts/visualsData/dataView/rules/categoricalEvalContext.ts","/ts/visualsData/dataView/rules/tableEvalContext.ts","/ts/visualsData/dataView/rules/ruleEvaluation.ts","/ts/visualsData/dataView/rules/colorRuleEvaluation.ts","/ts/visualsData/dataView/utils/dataViewMatrixUtils.ts","/ts/visualsData/dataView/utils/dataViewMetadataColumnUtils.ts","/ts/visualsData/contracts/conceptualSchema.ts","/ts/visualsData/dataView/scriptResultUtil.ts","/ts/visualsData/segmentation/dataViewMerger.ts","/ts/visualsData/semanticQuery/sqExprRewriter.ts","/ts/visualsData/semanticQuery/exprPatterns/equalsToInRewriter.ts","/ts/visualsData/semanticQuery/exprPatterns/filterScopeIdsCollector.ts","/ts/visualsData/semanticQuery/exprPatterns/scopeIdentityExtractor.ts","/ts/visualsData/semanticQuery/primitiveValueEncoding.ts","/ts/visualsData/semanticQuery/sqAggregationOperations.ts","/ts/visualsData/semanticQuery/sqHierarchyExprUtils.ts","/ts/visualsData/semanticQuery/sqExprGroupUtils.ts","/ts/visualsData/semanticQuery/sqExpr.ts","/ts/visualsData/semanticQuery/sqExprUtils.ts","/ts/visualsData/semanticQuery/semanticQueryRewriter.ts","/ts/visualsData/semanticQuery/semanticQuery.ts","/ts/visualsData/dataView/dataViewBuilder.ts","/ts/visualsData/dataView/rules/staticEvalContext.ts","/ts/visualsData/dataView/rules/matrixEvalContext.ts","/ts/visualsData/services/formattingService.ts","/ts/visualsData/services/serialization/sqExprShortSerializer.ts","/ts/visualsData/selection/selectionId.ts","/source/Visuals.js","/ts/visuals/common/point.ts","/ts/visuals/common/rect.ts","/ts/visuals/legend.ts","/ts/visuals/types/axisScale.ts","/ts/visuals/types/axisStyle.ts","/ts/visuals/types/axisType.ts","/ts/visuals/types/basicShapeType.ts","/ts/visuals/types/imageScalingType.ts","/ts/visuals/types/labelPosition.ts","/ts/visuals/types/labelStyle.ts","/ts/visuals/types/legendPosition.ts","/ts/visuals/types/kpi_direction_type.ts","/ts/visuals/types/lineStyle.ts","/ts/visuals/types/outline.ts","/ts/visuals/types/referenceLinePosition.ts","/ts/visuals/types/slicerOrientation.ts","/ts/visuals/types/yAxisPosition.ts","/ts/visuals/animators/animatorCommon.ts","/ts/visuals/animators/columnChartAnimator.ts","/ts/visuals/animators/donutChartAnimator.ts","/ts/visuals/animators/funnelChartAnimator.ts","/ts/visuals/animators/treemapAnimator.ts","/ts/visuals/capabilities/dataViewObjectProperties.ts","/ts/visuals/capabilities/animatedNumber.capabilities.ts","/ts/visuals/capabilities/basicShape.capabilities.ts","/ts/visuals/capabilities/columnChart.capabilities.ts","/ts/visuals/capabilities/comboChart.capabilities.ts","/ts/visuals/capabilities/donutChart.capabilities.ts","/ts/visuals/capabilities/dataDotChart.capabilities.ts","/ts/visuals/capabilities/filledMap.capabilities.ts","/ts/visuals/capabilities/funnelChart.capabilities.ts","/ts/visuals/capabilities/gauge.capabilities.ts","/ts/visuals/capabilities/imageVisual.capabilities.ts","/ts/visuals/capabilities/scriptVisual.capabilities.ts","/ts/visuals/capabilities/samples/consoleWriter.capabilities.ts","/ts/visuals/visuals/samples/consoleWriter.ts","/ts/visuals/capabilities/lineChart.capabilities.ts","/ts/visuals/capabilities/map.capabilities.ts","/ts/visuals/capabilities/multiRowCard.capabilities.ts","/ts/visuals/capabilities/textbox.capabilities.ts","/ts/visuals/capabilities/sampleVisual.capabilities.ts","/ts/visuals/capabilities/scatterChart.capabilities.ts","/ts/visuals/capabilities/slicer.capabilities.ts","/ts/visuals/capabilities/table.capabilities.ts","/ts/visuals/capabilities/matrix.capabilities.ts","/ts/visuals/capabilities/treemap.capabilities.ts","/ts/visuals/capabilities/card.capabilities.ts","/ts/visuals/capabilities/waterfallChart.capabilities.ts","/ts/visuals/capabilities/kpiStatusWithHistory.capabilities.ts","/ts/visuals/pluginsCapabilities.ts","/ts/visuals/behaviours/columnChartBehaviors.ts","/ts/visuals/behaviours/dataDotChartBehavior.ts","/ts/visuals/behaviours/donutChartBehaviors.ts","/ts/visuals/behaviours/funnelBehaviors.ts","/ts/visuals/behaviours/lineChartBehaviors.ts","/ts/visuals/behaviours/mapBehaviors.ts","/ts/visuals/behaviours/scatterChartBehaviors.ts","/ts/visuals/behaviours/horizontalSlicerBehaviors.ts","/ts/visuals/behaviours/verticalSlicerBehaviors.ts","/ts/visuals/behaviours/slicerBehaviors.ts","/ts/visuals/behaviours/legendBehaviors.ts","/ts/visuals/behaviours/treemapBehaviors.ts","/ts/visuals/behaviours/waterfallChartBehavior.ts","/ts/visuals/behaviours/LabelsBehavior.ts","/ts/visuals/behaviours/cartesianChartBehaviors.ts","/ts/visuals/common/axisHelper.ts","/ts/visuals/common/basicShapeUtils.ts","/ts/visuals/common/cartesianHelper.ts","/ts/visuals/common/colorHelper.ts","/ts/visuals/common/columnChartUtil.ts","/ts/visuals/common/converterHelper.ts","/ts/visuals/common/dataLabelUtils.ts","/ts/visuals/common/donutLabelUtils.ts","/ts/visuals/common/newDataLabelUtils.ts","/ts/visuals/common/kpiUtil.ts","/ts/visuals/common/referenceLineHelper.ts","/ts/visuals/common/interactivityUtils.ts","/ts/visuals/common/invalidDataValuesChecker.ts","/ts/visuals/common/listView.ts","/ts/visuals/common/mapUtil.ts","/ts/visuals/common/selectionManager.ts","/ts/visuals/common/shapes.ts","/ts/visuals/common/slicerUtil.ts","/ts/visuals/common/tooltipUtils.ts","/ts/visuals/common/svgUtil.ts","/ts/visuals/common/textUtil.ts","/ts/visuals/common/gradientHelper.ts","/ts/visuals/common/visualBackgroundHelper.ts","/ts/visuals/common/objectEnumerationBuilder.ts","/ts/visuals/common/visualBorderUtil.ts","/ts/visuals/common/transform.ts","/ts/visuals/common/trendLineHelper.ts","/ts/visuals/common/visibilityUtil.ts","/ts/visuals/common/visualObjectRepetition.ts","/ts/visuals/converter/slicer.converter.ts","/ts/visuals/formatting/dataLabelManager.ts","/ts/visuals/formatting/labelLayout.ts","/ts/visuals/formatting/donutLabelLayout.ts","/ts/visuals/formatting/filledMapLabelLayout.ts","/ts/visuals/services/colorAllocatorFactory.ts","/ts/visuals/services/defaultVisualHostService.ts","/ts/visuals/services/interactivityService.ts","/ts/visuals/services/geocoder.ts","/ts/visuals/services/geocodingCache.ts","/ts/visuals/services/geolocationService.ts","/ts/visuals/services/visualPluginService.ts","/ts/visuals/controls/scrollbar/scrollbar.ts","/ts/visuals/controls/tablix/internal/tablixGridPresenter.ts","/ts/visuals/controls/tablix/internal/tablixRealizationManager.ts","/ts/visuals/controls/tablix/internal/tablixGrid.ts","/ts/visuals/controls/tablix/internal/tablixLayoutManager.ts","/ts/visuals/controls/tablix/internal/tablixUtils.ts","/ts/visuals/controls/tablix/tablixControl.ts","/ts/visuals/controls/tablix/tablixDimension.ts","/ts/visuals/controls/tablix/tablixTouchDelegate.ts","/ts/visuals/controls/tablix/touchRegionAbstraction.ts","/ts/visuals/controls/tablix/ITablixFormatting.ts","/ts/visuals/controls/tablix/tablixColumnWidthManager.ts","/ts/visuals/visuals/animatedText.ts","/ts/visuals/visuals/animatedNumber.ts","/ts/visuals/visuals/basicShape.ts","/ts/visuals/cartesian/cartesianChart.ts","/ts/visuals/cartesian/columnChart.ts","/ts/visuals/cartesian/columnChartClustered.ts","/ts/visuals/cartesian/columnChartStacked.ts","/ts/visuals/visuals/samples/helloIVisual.ts","/ts/visuals/cartesian/comboChart.ts","/ts/visuals/dataColorPalette.ts","/ts/visuals/cartesian/dataDotChart.ts","/ts/visuals/visuals/funnelChart.ts","/ts/visuals/visuals/gauge.ts","/ts/visuals/visuals/imageVisual.ts","/ts/visuals/visuals/kpiStatusWithHistory.ts","/ts/visuals/cartesian/lineChart.ts","/ts/visuals/visuals/map.ts","/ts/visuals/visuals/multiRowCard.ts","/ts/visuals/visuals/textbox.ts","/ts/visuals/visuals/sampleVisual.ts","/ts/visuals/cartesian/scatterChart.ts","/ts/visuals/cartesian/playChart.ts","/ts/visuals/visuals/verticalSlicer.ts","/ts/visuals/visuals/horizontalSlicer.ts","/ts/visuals/visuals/slicer.ts","/ts/visuals/visuals/table.ts","/ts/visuals/visuals/matrix.ts","/ts/visuals/visuals/treemap.ts","/ts/visuals/visuals/card.ts","/ts/visuals/visuals/owlGauge.ts","/ts/visuals/warnings/visualWarnings.ts","/ts/visuals/cartesian/waterfallChart.ts","/ts/visuals/tooltip.ts","/ts/visuals/styles/visualStyles.ts","/ts/visuals/visuals/donutChart.ts","/ts/visuals/visuals/scriptVisual.ts","/ts/visuals/plugins.ts","/ts/visuals/common/canvasBackgroundHelper.ts"],"names":["powerbi","VisualDataRoleKind","VisualDataChangeOperationKind","VisualUpdateType","VisualPermissions","visuals","telemetry","ErrorSource","generateGuid","guid","idx","guidDigitsItem","Math","random","toString","ExtensibilityVisualApiUsage","name","apiVersion","custom","parentId","isError","errorSource","errorCode","undefined","info","event","category","time","Date","now","id","getFormattedInfoObject","formattedObject","privateFields","orgInfoFields","ExtensibilityVisualApiUsageLoggers","loggers","VisualException","visualType","isCustom","source","lineNumber","columnNumber","stack","message","VisualExceptionLoggers","extensibility","VisualPlugin","options","constructor","__capabilities__","capabilities","SelectionManager","this","hostServices","selectedIds","promiseFactory","prototype","select","selectionId","multiSelect","deferred","defer","shouldRetainSelection","sendSelectionToHost","selectInternal","resolve","promise","showContextMenu","position","sendContextMenuToHost","hasSelection","length","clear","getSelectionIds","ids","selectArgs","data","filter","value","hasIdentity","map","getSelector","data2","getSelectorsByColumn","_","isEmpty","onSelect","selectors","args","onContextMenu","selectionIds","compact","containsSelection","d","equals","push","list","some","SelectionIdBuilder","withCategory","categoryColumn","index","queryName","identity","ensureDataMap","withSeries","seriesColumn","valueColumn","withMeasure","measureId","measure","createSelectionId","SelectionId","createWithSelectorForColumnAndMeasure","dataMap","createVisualAdapter","visualPlugin","telemetryService","visualTelemetryInfo","VisualSafeExecutionWrapper","VisualAdapter","visualApiVersions","plugin","version","versionIndex","getVersionIndex","apiVersionIndex","legacy","logEvent","User","init","element","empty","visual","create","visualLegacy","host","hostAdapter","get","overloadMethods","update","type","Resize","visualHasMethod","onResizing","viewport","resizeMode","Data","onDataChanged","pick","ViewMode","onViewModeChanged","viewMode","destroy","enumerateObjectInstances","enumerateObjectRepetition","finalViewport","onClearSelection","canResizeTo","unwrap","Object","defineProperty","enumerable","configurable","methodName","visualNew","isFunction","versionCount","i","overloads","getCompiledOverloads","key","overloadFactory","assign","wrappedVisual","visualInfo","silent","_this","executeSafely","isCustomVisual","callback","exception","fileName","v100","ResizeEnd","dataViews","v110","createSelectionIdBuilder","createSelectionManager","jsCommon","DOMConstants","escKeyCode","enterKeyCode","tabKeyCode","upArrowKeyCode","downArrowKeyCode","leftArrowKeyCode","rightArrowKeyCode","homeKeyCode","endKeyCode","backSpaceKeyCode","deleteKeyCode","spaceKeyCode","shiftKeyCode","ctrlKeyCode","altKeyCode","aKeyCode","cKeyCode","sKeyCode","vKeyCode","wKeyCode","xKeyCode","yKeyCode","zKeyCode","DocumentBody","Anchor","EditableTextElements","EditableNumericElements","disabledAttributeOrValue","readonlyAttributeOrValue","idAttribute","styleAttribute","hrefAttribute","targetAttribute","blankValue","selfValue","classAttribute","titleAttribute","srcAttribute","contextmenuEventName","blurEventName","keyUpEventName","inputEventName","changeEventName","cutEventName","keyDownEventName","mouseMoveEventName","mouseDownEventName","mouseEnterEventName","mouseLeaveEventName","mouseOverEventName","mouseOutEventName","mouseClickEventName","pasteEventName","scrollEventName","dropEventName","focusEventName","focusInEventName","focusOutEventName","selectEventName","messageEventName","loadEventName","beforeUnload","inputAndSelectEventNames","PowerBIErrorResourceType","ServiceErrorToClientError","serviceError","m_serviceError","codeName","httpRequestId","set","getDetails","resourceProvider","errorDetails","statusCode","PowerBIErrorDetailHelper","GetDetailsFromTransformError","GetDetailsFromServerErrorStatusCode","addAdditionalInfo","addMessageAndStackTrace","stackTrace","pbiErrorDetails","localize","localizedCode","getOptional","serverErrorPrefix","code","additionErrorInfoKeyValuePair","errorInfoKey","errorInfoValue","detail","ResourceCodeReference","additionalErrorInfo","val","additionalInfo","createGeoTaggingAnalyzerService","getLocalized","GeoTaggingAnalyzerService","CategoryTypes","Address","City","Continent","CountryRegion","County","Longitude","Latitude","Place","PostalCode","StateOrProvince","EnglishBackup","GeotaggingString_Continent","GeotaggingString_Continents","GeotaggingString_Country","GeotaggingString_Countries","GeotaggingString_State","GeotaggingString_States","GeotaggingString_City","GeotaggingString_Cities","GeotaggingString_Town","GeotaggingString_Towns","GeotaggingString_Province","GeotaggingString_Provinces","GeotaggingString_County","GeotaggingString_Counties","GeotaggingString_Village","GeotaggingString_Villages","GeotaggingString_Post","GeotaggingString_Zip","GeotaggingString_Code","GeotaggingString_Place","GeotaggingString_Places","GeotaggingString_Address","GeotaggingString_Addresses","GeotaggingString_Street","GeotaggingString_Streets","GeotaggingString_Longitude","GeotaggingString_Longitude_Short","GeotaggingString_Latitude","GeotaggingString_Latitude_Short","GeotaggingString_PostalCode","GeotaggingString_PostalCodes","GeotaggingString_ZipCode","GeotaggingString_ZipCodes","GeotaggingString_Territory","GeotaggingString_Territories","GeotaggingString_VRMBackCompat_CountryRegion","GeotaggingString_VRMBackCompat_StateOrProvince","toLowerCase","isLongitudeOrLatitude","fieldRefName","isLongitude","isLatitude","isGeographic","isGeocodable","isAddress","isCity","isContinent","isCountry","isCounty","isStateOrProvince","isPlace","isPostalCode","isTerritory","isGeoshapable","isGeoshapableEnglish","isEnglishCity","isEnglishCountry","isEnglishCounty","isEnglishStateOrProvince","isEnglishPostalCode","isEnglishTerritory","hasMatches","result","whiteSpaceRegex","fieldNameWithoutWhitespace","replace","fieldName","possibleMatches","useStrict","nonWordRegex","len","possibleMatch","indexofpossibleMatch","indexOf","wordEndFlag","wordBeginFlag","test","getFieldType","getEnglishFieldType","isEnglishAddress","isEnglishPlace","isEnglishContinent","whiteSpaceRegexPattern","RegExp","isEnglishLongitude","isEnglishLatitude","DEBUG","UnknownClientError","details","HttpClientError","httpStatusCode","requestId","IgnorableClientError","ArrayExtensions","intersect","target","other","diff","distinct","union","unionSingle","range","startIndex","endIndex","take","count","copy","sequenceEqual","left","right","comparison","emptyToNull","array","predicate","rotate","offset","slice","rotated","Array","apply","createWithId","extendWithId","extended","withId","findWithId","item","createWithName","extendWithName","withName","findItemWithName","indexWithName","insertSorted","diff_1","splice","unshift","removeFirst","pop","isUndefinedOrEmpty","swap","firstIndex","secondIndex","temp","isInArray","lookupItem","compareCallback","any","isArrayOrInheritedArray","obj","nextPrototype","isArray","getPrototypeOf","InJs","DomFactory","div","$","span","checkbox","ul","li","button","textBox","img","iframe","applyDefault","defaultValue","Double","pow10","exp","POSITIVE_POWERS","Infinity","NEGATIVE_POWERS","log10","log","LOG_E_10","floorWithPrecision","getPrecision","x","decimalDigits","DEFAULT_PRECISION_IN_DECIMAL_DIGITS","abs","MIN_EXP","precisionExp","max","equalWithPrecision","y","precision","DEFAULT_PRECISION","lessWithPrecision","lessOrEqualWithPrecision","greaterWithPrecision","greaterOrEqualWithPrecision","roundX","round","floor","ceilWithPrecision","ceil","floorToPrecision","ceilToPrecision","roundToPrecision","parseFloat","toPrecision","ensureInRange","min","project","fromMin","fromSize","toMin","toSize","NaN","relativeX","projectedX","removeDecimalNoise","isInteger","toIncrement","increment","MIN_VALUE","Number","MAX_VALUE","MAX_EXP","EPSILON","Color","rgbString","rotateFactor","originalRgb","parseColorString","originalHsv","rgbToHsv","rotatedHsv","rotateHsv","rotatedRgb","hsvToRgb","hexString","normalizeToHexString","color","rgb","exec","R","parseInt","G","B","A","rgbColor","s","h","r","g","b","v","delta","H","S","V","hsvColor","p","q","t","fractionalSector","sectorNumber","sectorPos","newH","darken","flooredNumber","componentToHex","hexComponent","clamped","hex","toUpperCase","CssConstants","createClassAndSelector","className","class","selector","pixelUnits","heightProperty","widthProperty","topProperty","bottomProperty","leftProperty","rightProperty","marginTopProperty","marginLeftProperty","displayProperty","backgroundProperty","backgroundColorProperty","backgroundRepeatProperty","backgroundSizeProperty","backgroundImageProperty","textShadowProperty","textAlignProperty","borderTopWidthProperty","borderBottomWidthProperty","borderLeftWidthProperty","borderRightWidthProperty","fontSizeProperty","fontWeightProperty","colorProperty","opacityProperty","paddingLeftProperty","paddingRightProperty","positionProperty","maxWidthProperty","minWidthProperty","overflowProperty","overflowXProperty","overflowYProperty","transformProperty","webkitTransformProperty","cursorProperty","visibilityProperty","absoluteValue","zeroPixelValue","autoValue","hiddenValue","noneValue","blockValue","inlineBlockValue","transparentValue","boldValue","visibleValue","tableRowValue","coverValue","pointerValue","scrollValue","debug","assert","condition","assertFail","assertValue","assertNonEmpty","assertAnyValue","assertFailFunction","alert","getStackTrace","leadingFramesToRemove","stackSegments","Error","error","split","join","Errors","infoNavAppAlreadyPresent","getExceptionStackTrace","invalidOperation","argument","argumentName","argumentNull","argumentUndefined","argumentOutOfRange","pureVirtualMethodException","notImplementedException","fn","multiline","text","html","togglePanelControl","each","addClass","find","hover","toggleClass","prepend","click","end","next","slideToggle","hide","JQueryConstants","VisibleSelector","Lazy","factoryMethod","Utility","throwIfNullOrUndefined","getValue","Prototype","inherit","extension","wrapCtor","inherited","inheritSingle","proto","overrideArray","override","overwritten","Formatting","findDateFormat","format","cultureName","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","getUTCMilliseconds","fixDateTimeFormat","regexCache","requires","dependency","to","noop","loadStyleSheets","cssFiles","scriptsToRun","javaScriptFilesWithCallback","javaScriptFiles","javascriptFile","loadJavaScriptFiles","hrefList","forEach","href","styleSheetLoaded","loadStyleSheet","scripts","parseIfLoadingComplete","loadingCount","parseJavaScriptSourceCodes","sourceCodeList","makeCallbackIfParsingComplete","parsingCount","script","file","javaScriptFilesLoaded","javaScriptFilesLoading","isExternalUrl","loadJavaScriptSourceCode","sourceCode","link","linkElement","cloneNode","firstScriptInHeadElement","headElement","insertBefore","appendChild","src","onload","webGet","responseText","parseJavaScript","onComplete","sourceCodeOrFileName","targetCallback","onLoadCallback","promiseAsCallback","then","loadExternalJavaScriptFile","parseInternalJavaScriptCode","scriptElement","setAttribute","innerHTML","setTimeout","asyncLoop","listeners","listener","onerror","xhr","XMLHttpRequest","open","send","e","url","origin","location","protocol","_i","arguments","asyncSteps","steps","j","func","doc","document","head","getElementsByTagName","createElement","createJQueryPromiseFactory","JQueryPromiseFactory","JQueryDeferredWrapper","Deferred","reject","reason","all","promises","unwrappedPromises","jQuery","JQueryPromiseWrapper","when","unwrappedPromise","a","wrapCallback","always","arg","LocalStorageService","getData","localStorage","JSON","parse","setData","stringify","EphemeralStorageService","clearCacheInterval","cache","defaultClearCacheInterval","clearCache","clearCacheTimerId","localStorageService","ephemeralStorageService","WordBreaker","search","content","backward","hasBreakers","ilen","start","BREAKERS_REGEX","lastIndex","wordCount","getMaxWordWidth","textWidthMeasurer","properties","words","maxWidth","words_1","w","getWidth","truncate","truncator","splitByWidth","maxNumLines","usedWidth","wordsInLine","words_2","word","wordWidth","SPACE","TextMeasurementService","ensureDOM","spanElement","append","svgTextElement","d3","style","height","width","canvasCtx","getContext","fallbackFontFamily","window","getComputedStyle","node","fontFamily","removeSpanElement","remove","measureSvgTextWidth","textProperties","font","fontStyle","fontVariant","fontWeight","fontSize","measureText","measureSvgTextRect","attr","visibility","font-family","font-variant","font-size","font-weight","font-style","white-space","whiteSpace","getBBox","measureSvgTextHeight","estimateSvgTextRect","propertiesKey","rect","estimatedTextProperties","estimateSvgTextBaselineDelta","estimateSvgTextHeight","tightFightForNumeric","measureSvgTextElementWidth","svgElement","getSvgMeasurementProperties","getMeasurementProperties","css","textContent","getDivElementWidth","getTailoredTextOrDefault","strLength","copiedTextProperties","ellipsis","substr","svgEllipsis","textElement","originalText","tailoredText","wordBreak","maxHeight","linePadding","firstDY","labelText","dy","wordBreakOverflowingText","spanItem","selectAll","OverflowingText","inArray","enter","classed","PixelConverter","KeyUtils","isArrowKey","keyCode","ThrottleUtility","delay","timerFactory","TimerPromiseFactory","instance","run","done","timerComplete","delayInMs","HttpStatusCode","HttpConstants","ApplicationOctetStream","MultiPartFormData","StringExtensions","isNullOrUndefinedOrWhiteSpaceString","reg","equalIgnoreCase","normalizeCase","startsWithIgnoreCase","normalizedSearchString","startsWith","containsIgnoreCase","substring","isNullOrEmpty","str","trim","containsWhitespace","expr","isWhitespace","trimTrailingWhitespace","trimWhitespace","getLengthDifference","repeat","char","replaceAll","textToFind","textToReplace","pattern","escapeStringForRegex","ensureUniqueNames","names","usedNames","names_1","name_1","uniqueNames","_a","names_2","name_2","uniqueName","counter","findUniqueName","baseName","constructCommaSeparatedList","maxValue","replacedList","targetValue","replaceValue","commaSeparatedList","normalizeFileName","stringifyAsPrettyJSON","object","deriveClsCompliantName","input","fallback","stripTagDelimiters","HtmlTagRegex","context","parameterName","throwException","getComponentName","Undefined","throwIfNullOrEmpty","throwIfNullOrEmptyString","throwIfNullEmptyOrWhitespaceString","throwIfNotTrue","isString","isBoolean","isNumber","isDate","isObject","isNullOrUndefined","urlCombine","baseUrl","path","finalUrl","charAt","getAbsoluteUri","clusterUri","getStaticResourceUri","staticContentLocation","Trace","createClassSelector","createIdSelector","getCookieValue","keyValuePairs","cookie","keyValue","getDomainForUrl","hrefObject","getHrefObjectFromUrl","prop","getHostNameForUrl","getUrlWithoutQueryString","getProtocolFromUrl","aObject","convertWcfToJsDictionary","wcfDictionary","keyValuePair","getDateFromWcfJsonString","jsonDate","fromUtcMilliseconds","begIndex","milliseconds","retValue","setUTCMilliseconds","getOuterHtml","compareInt","getIndexOfMinValue","currentMinValue","extractUrlFromCssBackgroundImage","isValidImageDataUrl","regex","isLocalUrl","saveAsFile","contentBlob","Blob","URL","urlLink","createObjectURL","fileNameLink","navigator","msSaveOrOpenBlob","hyperlink","body","removeChild","getType","__type","parts","TypeNamespace","isEventSupported","eventName","isSupported","removeAttribute","toPixel","pixelAmount","getPropertyCount","getOwnPropertyNames","getFileExtension","filePath","lastIndexOf","extractFileNameFromPath","canUseClipboard","MSApp","is64BitOperatingSystem","userAgent","parseNumber","isFinite","isNaN","getURLParamValue","results","getLocalTimeZoneString","localTimeZoneString","timeSummer","UTC","summerOffset","getTimezoneOffset","timeWinter","winterOffset","JsonContentType","JpegContentType","XJavascriptContentType","JsonDataType","BlobDataType","HttpGetMethod","HttpPostMethod","HttpPutMethod","HttpDeleteMethod","HttpContentTypeHeader","HttpAcceptHeader","VersionUtility","compareVersions","versionA","versionB","versionParts","partA","partB","PerformanceUtil","PerfMarker","_name","_start","begin","performance","mark","console","timeEnd","DeferUtility","deferUntilNextFrame","isWaiting","requestAnimationFrame","TraceItem","sessionId","timeStamp","resultString","traceTypeStrings","toUTCString","UrlUtils","isValidUrl","match","RegExpExtensions","urlRegex","isValidImageUrl","findAllValidUrls","matches","urlRanges","getBase64ContentFromDataUri","uri","base64Token","indexBase64TokenStart","indexBase64Start","BrowserUtils","isChrome","vendorName","vendor","isInternetExplorerOrEdge","getInternetExplorerVersion","appName","re","EnumExtensions","hasFlag","flag","setFlag","resetFlag","enumType","endsWith","suffix","LogicExtensions","XOR","JsonComparer","TextSizeDefaults","getScale","textSize","TextSizeMin","TextSizeRange","TextSizeMax","px","PixelString","fromPoint","pt","fromPointToPixel","PxPtRatio","toPoint","utility","StyleUtils","getRotateAngleFromElement","rawElemStyle","transformString","transform","webkitTransform","getTranslateTransformFromElement","getPadding","top","bottom","ConsoleTracer","logTrace","trace","TraceType","Information","UnexpectedError","Fatal","ExpectedError","Warning","Verbose","warning","logTraceInternal","includeStackTrace","verbose","addListener","removeListener","resetListeners","defaultListener","reset","lastTraceIndex","getTraces","traces","disableDefaultListener","enableDefaultListener","traceMaxCount","ensurePowerView","action","PowerViewPackage","ensureMap","locale","mapPackageWithLocale","MapPackage","MSMapcontrol","concat","mapControlLoaded","MSMapcontrolLoaded","WaitForMSMapLoad","waitForMapControlLoaded","task","build","globalMapControlLoaded","__extends","__","hasOwnProperty","DefaultSQExprVisitorWithArg","visitEntity","visitDefault","visitColumnRef","visitMeasureRef","visitAggr","visitPercentile","visitHierarchy","visitHierarchyLevel","visitPropertyVariationSource","visitSelectRef","visitBetween","visitIn","visitAnd","visitOr","visitCompare","visitContains","visitExists","visitNot","visitStartsWith","visitConstant","visitDateSpan","visitDateAdd","visitNow","visitDefaultValue","visitAnyValue","visitArithmetic","visitFillRule","visitResourcePackageItem","visitScopedEval","DefaultSQExprVisitor","_super","DefaultSQExprVisitorWithTraversal","accept","lower","upper","values","valueTuple","jlen","rule","gradient2","linearGradient2","gradient3","linearGradient3","visitLinearGradient2","visitLinearGradient3","visitFillRuleStop","mid","expression","scope","scopeExpr","stop","createEnumType","members","EnumType","allMembers","validMembers","membersToReturn","allMembers_1","member","contains","FillSolidColorTypeDescriptor","nullable","descriptor","advancedDescriptor","ImageDefinition","urlType","misc","imageUrl","StructuralTypeDescriptor","isValid","fill","fillRule","image","paragraphs","getPrimitiveType","extendedType","PrimitiveTypeMask","isPrimitiveType","PrimitiveTypeWithFlagsMask","getCategoryFromExtendedType","ExtendedType","delimIdx","baseCategory","toExtendedType","primitiveType","primitiveString","PrimitiveType","Null","categoryType","categoryPrimitiveType","matchesExtendedTypeWithAnyPrimitive","PrimitiveTypeFlagsExcludedMask","ValueType","underlyingType","Temporal","temporalType","TemporalType","Geography","geographyType","GeographyType","Miscellaneous","miscType","MiscellaneousType","formattingType","FormattingType","Enumeration","Scripting","scriptingType","ScriptType","fromDescriptor","fromExtendedType","Text","integer","Integer","numeric","bool","Boolean","dateTime","DateTime","duration","Duration","binary","Binary","none","None","scripting","ScriptSource","enumeration","fromEnum","temporal","year","Year_Integer","month","Month_Integer","geography","address","city","continent","country","Country","county","region","Region","postalCode","PostalCode_Text","stateOrProvince","place","latitude","Latitude_Double","longitude","Longitude_Double","Image","ImageUrl","webUrl","WebUrl","barcode","Barcode_Text","formatting","formatString","FormatString","alignment","Alignment","labelDisplayUnits","LabelDisplayUnits","FontSize","labelDensity","LabelDensity","fromPrimitiveTypeAndCategory","typeCache","isCompatibleTo","otherTypes","valueType","otherTypes_1","otherType","otherValueType","isCompatibleFrom","otherPrimitiveType","isEqual","Numeric","Time","Year","Month","Barcode","DataShapeBindingLimitType","SubtotalType","DataShapeBindingDataReduction","createFrom","reduction","Top","Count","Bottom","sample","Sample","Window","FederatedConceptualSchema","schemas","links","schema","data_1","Selector","filterFromSelector","isNot","exprs","data_2","exprToAdd","SQExprBuilder","and","DataViewScopeIdentity","filterFromExprs","matchesData","identities","selectorData","dataItem","selectorDataItem","DataViewScopeWildcard","matchesKeys","keysList","selectorDataLength","selectorDataExprs","ScopeIdentityExtractor","getKeys","SQExprUtils","metadata","equalsDataArray","equalsData","selector1","selector2","roles","DataViewRoleWildcard","getKey","toStringify","data_3","containsWildcard","dataItems","dataItems_1","wildCard","hasRoleWildcard","dataItems_2","isRoleWildcard","getArithmeticOperatorName","arithmeticOperatorKind","EntitySourceType","TimeUnit","QueryAggregateFunction","QueryComparisonKind","SemanticType","FilterKind","QueryProjectionCollection","items","activeProjectionRefs","showAll","_activeProjectionRefs","_showAll","queryReferences","queryRefs","queryRef","queryReferences_1","queryReference","addActiveQueryReference","getLastActiveQueryReference","replaceQueryRef","oldQueryRef","newQueryRef","clone","cloneDeep","QueryProjectionsByRole","clonedRoles","roleName","getRole","DisplayUnitSystemType","DateTimeSequence","unit","sequence","add","date","extendToCover","addInterval","interval","moveToCover","getDelta","calculate","dataMin","dataMax","expectedCount","getIntervalUnit","DateTimeUnit","calculateYears","calculateMonths","Week","calculateWeeks","Day","calculateDays","Hour","calculateHours","Minute","calculateMinutes","Second","calculateSeconds","Millisecond","calculateMilliseconds","yearsRange","NumericSequenceRange","calculateDataRange","getFullYear","NumericSequence","newMinYear","fromNumericSequence","minYear","maxYear","minMonth","getMonth","maxMonth","calculateUnits","firstDayOfWeek","minDayOfWeek","getDay","dayOffset","minDay","getDate","getHours","getMinutes","getSeconds","DateUtils","addYears","addMonths","addWeeks","addDays","addHours","addMinutes","addSeconds","addMilliseconds","intervalOffset","getTime","maxCount","totalDays","totalHours","totalMinutes","totalSeconds","totalMilliseconds","getMilliseconds","MIN_COUNT","MAX_COUNT","isLeap","getMonthDays","MonthDaysLeap","MonthDays","yearDelta","day","isLeapDay","setFullYear","monthDelta","weeks","days","hours","minutes","seconds","createDisplayUnits","unitLookup","adjustMinBasedOnPreviousUnit","units","maxExponent","addUnitIfNonEmpty","title","labelFormat","previousUnit","applicableRangeMax","DisplayUnit","applicableRangeMin","defaultScientificBigNumbersBoundary","scientificSmallNumbersBoundary","PERCENTAGE_FORMAT","SCIENTIFIC_FORMAT","DEFAULT_SCIENTIFIC_FORMAT","SUPPORTED_SCIENTIFIC_FORMATS","reverseProject","isApplicableTo","isScaling","DisplayUnitSystem","displayUnit","unitBaseValue","findApplicableDisplayUnit","decimals","trailingZeros","isFormatSupported","getNumberOfDecimalsForFormatting","hasScientitifcFormat","formatHelper","isScalingUnit","shouldRespectScalingUnit","formattingService","formatValue","UNSUPPORTED_FORMATS","isPercentageFormat","nonScientificFormat","valueFormatter","DefaultNumericFormat","NumberFormat","addDecimalsToFormat","isStandardNumberFormat","formatNumberWithCustomOverride","formatSingleValue","shouldUseValuePrecision","isScientific","supportsScientificFormat","shouldFallbackToScientific","getScientificFormat","numericFormat","getNumericFormat","NoDisplayUnitSystem","call","DefaultDisplayUnitSystem","getUnits","previousUnitValue","WholeUnitsDisplayUnitSystem","DataLabelsDisplayUnitSystem","AUTO_DISPLAYUNIT_VALUE","NONE_DISPLAYUNIT_VALUE","maxAllowedMargin","minPower","useZeroRefPoint","forcedSingleStop","getSize","canExtendMin","hasFixedMin","canExtendMax","hasFixedMax","size","stepExp","expectedCountExp","power","roundMin","roundMax","roundRange","calculateFixedRange","shrinkByStep","dexp","stepsCount","stepPower","step","trimMinMax","stepCount","maxStepCount","minStepCount","minMargin","maxMargin","marginPrecision","_ensureIncludeZero","includeZero","_ensureNotEmpty","DEFAULT_MAX","_ensureDirection","oldCount","newCount","deltaCount","fixedMin","fixedMax","hasDataRange","ValueUtil","hasValue","MIN_SUPPORTED_DOUBLE","MAX_SUPPORTED_DOUBLE","beautify","BeautifiedFormat","defaultLocalizedStrings","describeUnit","exponent","exponentLookup","getLocalizedString","stringId","getFormatMetadata","getCustomFormatMetadata","setLocaleOptions","createDefaultFormatter","allowFormatBeautification","formatBeaut","formatCore","shouldUseNumericDisplayUnits","displayUnitSystem_1","createDisplayUnitSystem","displayUnitSystemType","singleValueFormattingMode_1","formatSingleValues","value2","decimals_1","forcePrecision_1","MaxScaledDecimalPlaces","detectAxisPrecision","axisValue","formattedValue","getStringFormat","MaxValueForDisplayUnitRounding","shouldUseDateUnits","tickCount","unit_1","dateFormatString","getValueFormat","columnType","getFormatString","DateTimeMetadataColumn","formatValueColumn","column","formatStringProp","valueFormat","describe","Default","WholeUnits","DataLabels","MinIntegerValueForDisplayUnits","isCustomFormat","isStandardFormat","MinPrecisionForDisplayUnits","formatStringProperty","suppressTypeFallback","propertyValue","DataViewObjects","objects","DefaultDateFormat","DefaultIntegerFormat","formatListCompound","strings","conjunction","restatementComma","formatListAnd","restatementCompoundAnd","formatListOr","restatementCompoundOr","nullsAreBlank","NEGATIVE_INFINITY","negativeInfinity","POSITIVE_INFINITY","infinity","getDisplayUnits","displayUnitSystem","0.00 %;-0.00 %;0.00 %","0.0 %;-0.0 %;0.0 %","NullValue","BooleanTrue","BooleanFalse","NaNValue","InfinityValue","NegativeInfinityValue","RestatementComma","RestatementCompoundAnd","RestatementCompoundOr","DisplayUnitSystem_EAuto_Title","DisplayUnitSystem_E0_Title","DisplayUnitSystem_E3_LabelFormat","DisplayUnitSystem_E3_Title","DisplayUnitSystem_E6_LabelFormat","DisplayUnitSystem_E6_Title","DisplayUnitSystem_E9_LabelFormat","DisplayUnitSystem_E9_Title","DisplayUnitSystem_E12_LabelFormat","DisplayUnitSystem_E12_Title","Percentage","Percentage1","TableTotalLabel","Tooltip_HighlightedValueDisplayName","Funnel_PercentOfFirst","Funnel_PercentOfPrevious","Funnel_PercentOfFirst_Highlight","Funnel_PercentOfPrevious_Highlight","null","true","false","displayName","DataRoleHelper","getMeasureIndexOfRole","grouped","firstGroup","hasRole","getCategoryIndexOfRole","categories","hasRoleInDataView","dataView","columns","c","hasRoleInValueColumn","createIDataViewCategoricalReader","DataViewCategoricalReader","categorical","hasValidCategories","hasAnyValidValues","valueRoleIndexMapping","firstGroupValues","valueIndex","valueCount","valueRoles","role","dataHasDynamicSeries","hasCategories","getCategoryCount","getCategoryValues","getCategoryFromRole","getCategoryValue","categoryIndex","getCategoryColumn","getCategoryMetadataColumn","getCategoryColumnIdentityFields","identityFields","getCategoryDisplayName","targetColumn","hasCompositeCategories","hasCategoryWithRole","getCategoryObjects","hasValues","seriesIndex","getValueInternal","getHighlight","getAllValuesForRole","valuesInRole","roleValueIndex","roleValueCount","getAllHighlightsForRole","groupIndex","valueColumnIndexInRole","valueColumnIndex","groupedValues","highlights","getFirstNonNullValueForCategory","seriesCount","getMeasureQueryName","getValueColumn","getValueMetadataColumn","getValueDisplayName","hasDynamicSeries","getSeriesCount","valueRoleName","getSeriesObjects","getSeriesValueColumns","getSeriesValueColumnGroup","getSeriesMetadataColumn","getSeriesColumnIdentityFields","getSeriesName","getSeriesDisplayName","DataViewConcatenateCategoricalColumns","detectAndApply","objectDescriptors","roleMappings","projectionOrdering","selects","projectionActiveItems","dataViewCategorical","concatenationSource","detectCategoricalRoleForHierarchicalGroup","columnsSortedByProjectionOrdering","sortColumnsByProjectionOrdering","activeItemsToIgnoreInConcatenation","chain","activeItemInfo","suppressConcat","applyConcatenation","applyToPlayChartCategorical","categoryRoleName","transformingColumns_1","transformingMetadata","m","transformingDataView","dataViewMappings","roleKinds","DataViewSelectTransform","createRoleKindFromMetadata","projections","projectionsFromSelects","supportedRoleMappings","DataViewAnalysis","chooseDataViewMappings","supportedMappings","isEveryRoleMappingForCategorical","every","roleMapping","targetRoleName_1","getSingleCategoryRoleNameInEveryRoleMapping","isVisualExpectingMaxOneCategoryColumn","categoryColumnsForTargetRole_1","areValuesCountsEqual","categoricalRoleMappings","uniqueCategoryRoles","categoryRoles","getAllRolesInCategories","uniq","isSameCategoryRoleNameInAllRoleMappings","isUndefined","categoricalRoleName","conditions","categoricalRoleMapping","roleNames","DataViewMapping","visitCategoricalCategories","visitRole","queryRefsToIgnore","formatStringPropId","DataViewObjectDescriptors","findFormatString","concatenatedValues","concatenateValues","columnsSourceSortedByProjectionOrdering","concatenatedColumnMetadata","createConcatenatedColumnMetadata","transformedDataView","addToMetadata","concatenatedCategoryColumn","createConcatenatedCategoryColumn","transformedCategoricalCategories","difference","transformedCategorical","columnsSortedByProjectionOrdering_1","columnsInProjectionOrdering","columnsByIndex_1","columns_1","columnIndicesInProjectionOrdering","columnIndex","sourceColumnsSortedByProjectionOrdering","concatenatedDisplayName","sourceColumnsSortedByProjectionOrdering_1","columnSource","newRoles","newColumnMetadata","columnSourceForCurrentDrillLevel","last","isMeasure","newColumn","transformedColumns","transformedMetadata","columnMetadata","newCategoryColumn","firstColumn","visitMapping","mapping","visitor","visitCategorical","table","visitTable","matrix","visitMatrix","tree","visitTree","single","visitSingle","visitCategoricalValues","visitBind","visitFor","visitList","visitReduction","groupedRoleMapping","visitGrouped","group","rows","visitMatrixItems","visitTreeNodes","nodes","visitTreeValues","bind","forValue","select_1","by","reductionAlgorithm","dataReductionAlgorithm","DataViewNormalizeValues","rolesToNormalize","dataRoles","requiredTypes","filterVariantMeasures","dataview","columnFilter","generateMetadataColumnFilter","valueFilter","generateValueFilter","usedMappings","dataViewMappings_1","dataViewMapping","dataViewMappingProp","filterVariantMeasuresCategorical","filterVariantMeasuresTable","filterVariantMeasuresTreeNode","root","filterVariantMeasuresMatrix","filterVariantMeasuresSingle","columnsToNormalize","columns_2","rolesToNormalize_1","columnValueFilters","columns_3","columnValueFilter","generateColumnValueFilter","getColumnRequiredTypes","doesValueMatchTypes","columnRoles","rolesToNormalize_2","_b","typeDescriptor","valuesGrouped","valuesGrouped_1","valueGroup","valuesInGroup","valuesInGroup_1","normalizeVariant","filteredColumns","columns_4","filteredColumns_1","children","child","filterVariantMeasuresMatrixRecursive","dataviewMatrix","nodeValue","valueSourceIndex","valueSources","rolesToNormalize_3","dataViewMappings_2","firstColumnByRoleName","types","types_1","columns_5","propertyId","objectOrMap","objectName","DataViewObject","propertyName","getObject","getUserDefinedObjects","getFillColor","defaultColor","solid","isUserDefined","getFillColorByPropertyName","DataViewObjectDefinitions","ensure","defns","defnsForObject","defn","newDefn","deleteProperty","getObjectDefinition","DataViewObjectDefinition","deleteSingleProperty","setValue","getPropertyContainer","propertiesAreEqual","SemanticFilter","isSameFilter","allPropertiesAreEqual","keys","property","encodePropertyValue","valueTypeDescriptor","isNumeric","imageValue","imageDefinition","scaling","original","cloned","originalDefns","clonedDefns","originalDefns_1","originalDefn","cloneProperties","descriptors","findProperty","propDesc","formattingTypeDesc","findFilterOutput","propType","findDefaultValue","propPredicate","objPropDescs","DataViewObjectEvaluationUtils","evaluateDataViewObjects","evalContext","objectDefns","objectDefinition","evaluatedObject","DataViewObjectEvaluator","groupObjectsBySelector","objectDefinitions","objectDefnList","objectDefn","ensureDefinitionListForSelector","metadataOnce","groupedObjects","userDefined","groupedObjects_1","item_1","addImplicitObjects","objectsForAllSelectors","selectTransforms","addDefaultFormatString","addDefaultValue","selectIdx","selectLen","selectTransform","applyFormatString","getColumnFormatForIndex","defaultValueProp","selectTransforms_1","applyDefaultValue","columnIdx","columnLen","formatStringValue","applyMetadataProperty","metadataObjects","targetObjectDefn","targetMetadataObject","findWithMatchingSelector","targetObjectDefns","findExistingObject","objectDescriptor","propertyDefinitions","propertyDescriptors","propertyDefinition","propertyDescriptor","evaluateProperty","structuralType","evaluateValue","RuleEvaluation","evaluateFill","evaluateFillRule","evaluateImage","evaluateParagraphs","fillDefn","fillType","fillRuleDefn","evaluateColorStop","colorStop","colorValueType","numericType","definition","textType","evaluateArrayCopyOnChange","evaluateParagraph","evaluated","definitionTextRuns","textRuns","evaluatedTextRuns","evaluateTextRun","definitionValue","evaluatedValue","definitions","evaluator","evaluatedValues","SQExpr","ExpressionEvaluator","evaluate","getExprValue","inputValue","colorAllocator","getColorAllocator","DataViewPivotCategorical","categoryIdentities","categoryValues","pivotedColumns","pivotedValues","rowIdx","rowCount","categoryValue","categoryIdentity","colIdx","colCount","pivotedColumn","groupName","pivotedValue","subtotal","pivotedMetadata","DataViewTransform","createValueColumns","DataViewPivotMatrix","dataViewMatrix","columnHierarchyRewritten","rowHierarchyRewritten","levels","pivotedRowNode","level","columnLeafNodes","measureCount","pivotResultMeasureHeaderLevel","index_1","measureHeaderLeaf","columnLeafNode","levelSourceIndex","isSubtotal","hierarchyTreesRewritten","forEachLeaf","cloneTreeExecuteOnLeaf","cloneTree","sources","updatedRowRoot","updatedNode","newChildren","updatedChild","createNullValues","inheritArrayWithValue","nullValues","DataViewSelfCrossJoin","applyCategorical","dataViewMetadata","categoryLength","valuesArray","createCategoricalDataViewBuilder","withCategories","withGroupedValues","createGroupedValues","nullValuesArray","valuesArrayLen","seriesData","seriesDataItem","originalValueColumn","originalHighlightValues","seriesDataItemCategory","groupColumn","identityFrom","fields","valueColumns","DataViewPivotCategoricalToPrimaryGroups","pivotBinding","binding","allMappings","finalMapping","defaultDataVolume","canPivotCategorical","Primary","Groupings","Secondary","DataReduction","DataVolume","dataVolume","isPivotableAxis","axis","Projections","Subtotal","SuppressedProjections","unpivotResult","oldDataView","inferUnpivotTransform","newDataView","newDataViewMatrix","unpivotMatrix","hasCompositeGroupInSeries","utils","DataViewMatrixUtils","containsCompositeGroup","categoricalFromUnpivotedMatrix","supportedDataViewMappings","categoricalMapping","matrixDataview","categoryGroups","valueGroups","addGroupingRole","groups","roleProjections","roleProjection","Grouping","_c","oldMatrix","oldRows","oldRoot","oldChildren","series","seriesIdLevel","seriesIdFields","childIdentityFields","categoryIdLevel","categoryIdFields","findCategory","addCategory","categoryNode","oldChildren_1","seriesNode","matrixValues","_d","newColumns","inheritedNode","newColChildren","srcnode","dstnode","newRows","row","rowValues","mvalues","k","l","newMatrix","measureMetadata","createCategoryColumnsFromUnpivotedMatrix","valueColumnMetadataSrc","valueColumnMetadataDst","groups_1","unpivotedMatrix","categoryIdentityFields","categorySourceColumns","groupLevelValues","levelValues","transforms","activeItems","colorAllocatorFactory","transformEmptyDataView","visualDataViews","transformQueryToVisualDataView","DataViewRegression","transformSelects","transformedDataViews","splits","transformDataView","splits_1","transformed","emptyDataView","transformObjects","selectsToInclude","targetKinds","getTargetKinds","ordering","roleMappings_1","targetDataViewKinds","columnRewrites","applyTransformsToColumns","applyRewritesToCategorical","pivotIfNecessary","matrixTransformationContext","applyRewritesToMatrix","shouldPivotMatrix","applyRewritesToTable","prototypeColumns","rewrites","prototypeColumn","getFormatForColumn","kpi","sort","discourageAggregationAcrossGroups","from","rewrittenSource","findOverride","rewritten","valuesOverride","rewrittenValuesSource","seriesGroups_1","isDynamicSeries_1","nextSeriesGroupIndex","currentSeriesGroup","currentValueColumn","newToOldPositions","createTableColumnPositionMapping","columnsClone","sourceColumn","newRow","originalOrder","rewrite","newOrder","createOrderMapping","overrideHierarchy","hierarchy","rewrittenHierarchy","newLevels","newLevel","levelSources","ensureRewritten","firstRoleMappingWithMatrix","matrixMapping","columnLevels","newToOldPositions_1","createMatrixValuesPositionMapping","keys_1","numKeys_1","reorderChildNodes","forEachNodeAtLevel","newValues","iterations","keysIndex","reorderMatrixCompositeGroups","numKeys","childrenClone","supportedDataViewMapping","projection","transformedRowsHierarchy_1","reorderMatrixHierarchyCompositeGroups","transformedColumnsHierarchy_1","matrixHierarchy","hierarchyRole","transformedHierarchy","selectIndicesInProjectionOrder","hasMultipleColumnsInProjection","hierarchyLevel","newToOldLevelSourceIndicesMapping","createMatrixHierarchyLevelSourcesPositionMapping","inheritMatrixNodeHierarchy","transformingHierarchyLevel","reorderMatrixHierarchyLevelColumnSources","reorderMatrixHierarchyLevelValues","levelSourceColumns","columnsForHierarchyRoleOrderedByLevelSourceIndex","DataViewMetadataColumnUtils","joinMetadataColumnsAndProjectionOrder","columnsForHierarchyRoleOrderedByProjection","sortBy","columnInfo","projectionOrderIndex","sourceIndex","originalLevelSources","newLevelSourceIndices","newLevelSourceIndex","oldLevelSourceIndex","transformingHierarchyRootNode","transformingHierarchyLevelIndex","oldToNewLevelSourceIndicesMapping","createReversedMapping","transformingMatrixNode","originalLevelValues","newlyOrderedLevelValues","levelValue","transformingLevelValue","newlyOrderedLastLevelValue","newPosition","reversed","keyAsNumber","targetLevel","columnRewrite","dataObjects","evaluateMetadataObjects","metadataObject","colorAllocatorCache","populateColorAllocatorCache","evaluateMetadataRepetition","dataObject","evaluateDataRepetition","rules","evaluateUserDefinedObjects","dataViewObjects","objectDefns_1","createStaticEvalContext","objectDesc","propertyDesc","ruleDesc","createRuleEvaluationInstance","ruleType","ruleOutput","output","selectorToCreate","findSelectorForRuleInput","createRuleEvaluationInstanceFillRule","tryCreateColorAllocatorForFillRule","inputRole","ColorRuleEvaluation","fillRuleProperties","identifier","identifierKind","createColorAllocatorLinearGradient2","createColorAllocatorLinearGradient3","propertyValueFillRule","inputRange","findRuleInputColumnNumberRange","splitScales","midValue","createColorAllocatorCache","staticEvalContext","objectDefnProperties","fillProperty","kind","fillRuleExpr","inputExprQueryName","findFirstQueryNameForExpr","fillRulePropertyDescriptor","register","evaluateDataRepetitionCategoricalCategory","evaluateDataRepetitionCategoricalValueGrouping","rewrittenMatrix","evaluateDataRepetitionMatrix","dataViewTable","rewrittenSelector","rewriteTableRoleSelector","rewrittenTable","evaluateDataRepetitionTable","findSelectorForRoleWildcard","resultingSelector","dataSelector","selectorRoles","allColumnsBelongToSelectorRole","allColumnsBelongToRole","fromExprs","isUniqueDataSelector","dataSelectors","newSelector","columns_6","selectorRole","findSelectedCategoricalColumn","foundMatch","createCategoricalEvalContext","setCurrentRowIndex","dataViewCategoricalValues","selectorMetadata","valueSource","valueSourceOverwrite","setGrouped","createMatrixEvalContext","rewrittenRows","evaluateDataRepetitionMatrixHierarchy","rewrittenCols","dataViewMatrixHierarchy","rewrittenRoot","evaluateDataRepetitionMatrixNode","dataViewNode","childNodes","rewrittenNode","shouldSearchChildren","childNode","rewrittenChildNode","inheritNodeAndChildren","createTableEvalContext","evaluateDataRepetitionTableRows","findIndex","col","inheritedRows","colLen","rowLen","inheritedRow","objectsForColumns","metadataId","categoricalColumn","selectedMetadataId","isSelectRef","expressionName","columnExpr","valueColRoles","aggregates","minLocal","maxLocal","valueIdentityFields","groupedResult","groupValues","currentGroup","determineCategoricalTransformation","vg","roleMappingCategorical","hasRolesGrouped","categoriesMapping","hasCategoryRole","hasRolesBind","hasRolesFor","rowLevels","rowRoles","roleMappingMatrix","createDisplayNameGetter","displayNameKey","getDisplayName","displayNameGetter","fieldExpr","sqExpr","FieldExprPattern","visit","FieldExprToSQExprVisitor","fromColumnAggr","columnAggr","aggregate","fromColumn","columnRef","fromEntity","entityPattern","entity","entityVar","fromEntityAggr","entityAggr","fromHierarchyLevelAggr","hierarchyLevelAggr","fromHierarchyLevel","hierarchyLevelPattern","fromHierarchy","hierarchyPattern","visitColumn","visitColumnAggr","visitColumnHierarchyLevelVariation","columnHierarchyLevelVariationPattern","propertyVariationSource","visitEntityAggr","visitHierarchyLevelAggr","visitMeasure","measureRef","percentile","exclusive","visitPercentOfGrandTotal","percentOfGrandTotal","baseSQExpr","baseExpr","arithmetic","scopedEval","selectRef","SQExprConverter","asFieldPattern","FieldExprPatternBuilder","sourceRef","SourceExprPatternBuilder","ref","entityRef","variable","fieldPattern","argAggr","sourcePattern","hierarchyRef","hierarchySourceExprPattern","HierarchyExprPatternBuiler","variation","columnHierarchyLevelVariation","variationName","percentOfGrandTotalPattern","entityExpr","SQEntityExpr","variationRef","exprPattern","fieldExprPattern","toColumnRefSQExpr","columnPattern","getAggregate","FieldExprPatternAggregateVisitor","isAggregation","FieldExprPatternIsAggregationVisitor","hasFieldExprName","getPropertyName","FieldExprPropertyNameVisitor","getHierarchyName","getColumnRef","getFieldExprName","toFieldExprEntityPattern","getSchema","toFieldExprEntityItemPattern","FieldExprToEntityExprPatternBuilder","SQExprInfo","toEntityItemExprPattern","validateAndReshape","dataViewMappings_3","supports","reshapeCategorical","reshapeTree","reshapeSingle","reshapeTable","ScriptResultUtil","findScriptResult","categoryRoleMapping","supported","updated","maxRowCount","originalLength","updatedCategories","updatedColumn","supportsCategorical","singleRoleMapping","treeRoleMapping","validateRange","countGroups","depth","tableRoleMapping","countMeasures","usePreferredDataViewSchema","scriptResult","supportsScriptResult","supportsTree","supportsSingle","supportsTable","preferred","dataViewSingle","scriptResultRoleMapping","imageBase64","roleCondition","ignoreMin","DataViewMappingMatchErrorCode","conditionRangeTooSmall","conditionRangeTooLarge","validateKind","roleKindByQueryRef","expectedKind","roleCollection","roleProjections_1","Measure","conditionKindExpectedMeasure","conditionKindExpectedGrouping","GroupingOrMeasure","conditionKindExpectedGroupingOrMeasure","mappings","errors","mappingIndex","mappingCount","mappingConditions","requiredProperties","allPropertiesValid","areAllPropertiesValid","conditionsMet","conditionIndex","conditionCount","currentConditionErrors","checkForConditionErrors","currentConditionErrors_1","supportedMapping","updatedConditions","mappingErrors","conditionRoles","isDrillable","roleCount","rangeError","kindError","requiredProperty","objectDescriptorValue","objectDescriptorProperty","objectDefinitionValue","useActiveIfAvailable","projectionsForRole","hasSameCategoryIdentity","dataView1","dataView2","dv1Categories","dv2Categories","dv1Identity","dv2Identity","dv1Length","getLengthOptional","areMetadataColumnsEquivalent","column1","column2","isMetadataEquivalent","metadata1","metadata2","previousColumnsLength","newColumnsLength","fromRoles","DataViewRoleWildcardImpl","firstRoleWildcard","secondRoleWildcard","role1","role2","_roles","_key","ignoreCase","filterFromIdentity","identities_1","orExprs","resultExpr","orExprs_1","orExpr","inExpr","getInExpr","or","not","fromSQExpr","createDataViewScopeIdentity","DataViewScopeIdentityImpl","_expr","SQExprShortSerializer","serialize","wildcard","instanceExprs","firstScopeWildcard","secondScopeWildcard","DataViewScopeWildcardImpl","_exprs","serializeArray","ColorAllocatorProvider","entry","allocator","applicableDataViewMappings","regressionDataViewMapping","usage","regression","regressionDataViews","visualDataViews_1","visualDataView","regressionDataView","linearRegressionTransform","sourceDataView","xColumns","getColumnsForCartesianRoleKind","yColumns","xColumnSource","yColumnSource","combineSeries","regressionUsage","combineSeriesPropertyId","highlightsLineDefSet","dataPointsBySeries","getDataPointsBySeries","lineDefSet","calculateLineDefinitions","xMin","xMax","shouldComputeHightlights","hasHighlightValues","highlightDataPointsBySeries","valuesByTrend","lineDefs","trend","computeLineYValues","highlightsByTrend","createRegressionDataView","dataPointsBySeries_1","dataPointSet","unsortedXValues","xValues","unsortedYValues","yValues","xDataType","getDataType","yDataType","sortedDataPointSet","sortValues","minCategoryValue","maxCategoryValue","lineDef","computeRegressionLine","roleKind","getColumnsWithRoleKind","_loop_1","cartesianKind","state_1","firstNonNull","dataType","zippedValues","zip","valuePair","unzip","xBar","sum","yBar","ssXX","pow","ssXY","slope","intercept","x1","x2","getValuesFromColumn","preferHighlights","xValueArray","seriesYValues","multipleXValueColumns","yRole","seriesRole","xRole","categoricalRoles","seriesRoles","valuesBySeries","regressionXQueryName","regressionSeriesQueryName","regressionYQueryName","selects_1","qp","activeItem","colorAllocatorProvider","CategoricalEvalContext","findRuleInputColumn","findRuleInputInColumns","columns_7","columnsByRole","getRoleValue","TableEvalContext","getExprValueFromTable","forEachLeafNode","rootNodes","isNodeArray","rootNodes_1","rootNode","forEachLeafNodeRecursive","nodeOrNodeArray","matrixNode","nextIndex","treePath","children_1","nextChild","deepestLevelToInherit","useInheritSingle","returnNode","isRootNode","shouldInheritCurrentNode","inheritFunc","shouldInheritChildNodes","matrixOrHierarchy","hasCompositeGroup","isMatrix","hierarchyLevels","hierarchyLevels_1","isMeasureHeadersLevel","isForRole","metadataColumn","targetRole","columnSources","jointResult","projectionOrderSelectIndices","selectIndexToProjectionIndexMap","selectIndex","jointColumnInfo","ConceptualSchema","entityName","entities","findHierarchy","hierarchies","findHierarchyByVariation","variationEntityName","variationColumnName","hierarchyName","variationEntity","variationProperty","variationColumn","variations","targetEntity","navigationProperty","findPropertyWithKpi","kpiProperty","status","goal","ConceptualDataCategory","extractScriptResult","provider","extractScriptResultFromVisualConfig","scriptSource","getScriptInput","scriptInput","VariableName","Columns","scriptInputColumnNames","scriptInputColumns","scriptInputColumn","QueryName","Name","ScriptInputColumnNameVisitor","federatedSchema","getNameForProperty","getVariationLevelName","getNameForHierarchy","federatedScheam","variations_1","defaultHierarchy","segmentation","DataViewMerger","mergeDataViews","segment","mergeTables","mergeCategorical","mergeTreeNodes","mergeIndex","lastMergeIndex","merge","segmentCategoriesLength","segmentCategory","sourceCategory","segmentValuesLength","segmentValue","sourceValue","sourceRoot","segmentRoot","allowDifferentStructure","firstAppendIndex","findFirstAppendIndex","lastSourceChild","mergedChildren","childSegment","isMerge","SQExprRewriter","origArg","rewrittenArg","SQColumnRefExpr","SQMeasureRefExpr","SQAggregationExpr","SQPercentileExpr","SQHierarchyExpr","SQHierarchyLevelExpr","SQPropertyVariationSourceExpr","orig","origLeft","rewrittenLeft","origRight","rewrittenRight","SQAndExpr","origLower","rewrittenLower","origUpper","rewrittenUpper","SQBetweenExpr","rewrittenValues","origArgs","rewrittenArgs","rewriteAll","origValues","origValueTuple","rewrittenValueTuple","SQInExpr","origExprs","rewrittenResult","origExpr","rewrittenExpr","SQOrExpr","SQCompareExpr","SQContainsExpr","SQExistsExpr","SQNotExpr","SQStartsWithExpr","SQDateSpanExpr","SQDateAddExpr","amount","SQArithmeticExpr","operator","origExpression","rewrittenExpression","origScope","rewrittenScope","SQScopedEvalExpr","origInput","rewrittenInput","origRule","origGradient2","rewrittenGradient2","origGradient3","rewrittenGradient3","rewrittenRule","SQFillRuleExpr","origMin","rewrittenMin","origMax","rewrittenMax","origMid","rewrittenMid","origColor","rewrittenColor","origValue","rewrittenValue","rewrittenStop","EqualsToInRewriter","Rewriter","Equal","visitUnsupported","leftIsComparand","isComparand","rightIsComparand","operand","current","InBuilder","complete","cancel","SQConstantExpr","cancelled","asScopeIdsContainer","fieldSQExprs","filterItems","filterItem","FilterScopeIdsCollectorVisitor","getResult","getFirstComparandValue","comparandExpr","FindComparandVisitor","isRoot","keyExprsCount","valueExprs","fieldExprs","fieldSQExprs_1","field","removeEntityVariables","scopeIds","scopeId","getScopeIdentity","compoundSQExpr","equalsExpr","equal","unsupportedSQExpr","values_1","valueTuple_1","fixedExpr","extractor","ScopeIdExtractorImpl","malformed","keyValues","PrimitiveValueEncoding","decimal","double","dateTimeString","toISOString","SingleQuoteRegex","nullEncoding","boolean","createSQAggregationOperations","datetimeMinMaxSupported","SQAggregationOperations","getMetadataForUnderlyingType","removeAggregate","getMetadata","Agg","getSupportedAggregates","targetTypes","fieldKind","isPropertyIdentity","idOnEntityKey","aggregates_1","Sum","Avg","Min","Max","CountNonNull","StandardDeviation","Variance","fieldExprItem","currentSchema","supportsMedian","Median","distinctCountAggExists","isSupportedAggregate","supportedAggregates","createExprWithAggregate","aggregateNonNumericFields","preferredAggregate","getDefaultAggregate","SQHierarchyExprUtils","getConceptualHierarchyLevelFromExpr","conceptualSchema","getConceptualHierarchyLevel","schemaName","conceptualHierarchy","getConceptualHierarchy","variationExpr","sourceEntityExpr","expandExpr","suppressHierarchyLevelExpansion","SQExprHierarchyToHierarchyLevelConverter","convert","SQExprVariationConverter","expand","SQExprHierarchyLevelConverter","isHierarchyOrVariation","conceptualProperty","getConceptualProperty","getSourceVariationExpr","hierarchyLevelExpr","getSourceHierarchy","getHierarchySourceAsVariationSource","areHierarchyLevelsOrdered","allLevels","firstExpr","secondExpr","firstLevel","secondLevel","indexOfExpr","getInsertionIndex","orderedSubsetOfLevels","insertIndex","hierarchyExpr","hierarchyLevels_2","SQExprGroupUtils","groupExprs","addChildToGroup","selectQueryIndex","shouldAddExpressionToNewGroup","exprSource","lastGroup","expandedExpr","allHierarchyLevels","defaultAggregateForDataType","defaultAggregateToQueryAggregateFunction","_kind","SQExprEqualityVisitor","validate","aggrUtils","validator","SQExprValidationVisitor","isColumn","isConstant","isEntity","isHierarchy","isHierarchyLevel","isResourcePackageItem","getMetadataForProperty","getMetadataForHierarchyLevel","getMetadataForVariation","getMetadataForPercentOfGrandTotal","getMetadataForEntity","forceAggregation","getHierarchyLevelConceptualProperty","propertyDefaultAggregate","defaultAggregate","getKeyColumns","columnRefExpr","SQExprColumnRefInfoVisitor","getColumnRefSQExpr","keySQExprs","getPropertyKeys","hasGroupOnKeys","keySqExpr","getTargetEntityForVariation","variations_2","getTargetEntity","SQEntityExprInfoVisitor","getEntityExpr","fieldExprHierachyLevel","fieldExprEntity","sourceProperty","getPropertyMetadata","columnAggregate","SQPropRefExpr","argMetadata","SQSelectRefExpr","valueEncoded","SQNowExpr","SQDefaultValueExpr","SQAnyValueExpr","SQResourcePackageItemExpr","packageName","packageType","itemName","between","inExpr_1","tryUseInExprs","leftArgLen","rightArgLen","combinedValues","compare","exists","nullConstant","anyValue","dateAdd","dateSpan","Decimal","typedConstant","setAggregate","FieldExprChangeAggregateRewriter","FieldExprRemoveAggregateRewriter","setPercentOfGrandTotal","SQExprSetPercentOfGrandTotalRewriter","removePercentOfGrandTotal","SQExprRemovePercentOfGrandTotalRewriter","SQExprRemoveEntityVariablesRewriter","resourcePackageItem","SQExprAggregateInfoVisitor","ignoreCaseInstance","comparand","equalsAll","compareValues","optionalEqual","leftRule","rightRule","leftLinearGradient2","rightLinearGradient2","leftLinearGradient3","rightLinearGradient3","left2","right2","equalsFillRuleStop","left3","right3","stop1","stop2","SQExprRootRewriter","values_2","validateCompatibleType","compareExpr","validateEntity","isQueryable","aggregateExpr","validateHierarchy","hierarchyLevelFieldExprItem","validateHierarchyLevel","validateOperandsAndTypeForStartOrContains","validateArithmeticTypes","supportsArithmetic","leftMetadata","leftType","rightMetadata","rightType","levelName","hierarchyLevelConceptualProperty","queryable","sourceExpr","targetEntityExpr","schemaHierarchy","hierarchyLevelRef","getEntity","SQExprChangeAggregateRewriter","rewriter","defaultRewrite","SQExprRemoveAggregateRewriter","searchElement","namedItems","exprDefaultName","defaultName","SQExprDefaultNameGenerator","IsMeasureVisitor","isAnyValue","IsAnyValueVisitor","isDefaultValue","IsDefaultValueVisitor","discourageAggregation","getSchemaCapabilities","discourageQueryAggregateUsage","getAggregateBehavior","getConceptualColumn","aggregateBehavior","getKpiMetadata","kpiStatusProperty","getKpiStatusProperty","kpiValue","statusMetadata","kpiTrendProperty","getKpiTrendProperty","trendMetadata","getConceptualEntity","conceptualEntity","getDefaultValue","fieldSQExpr","sqField","hierarchyLevelField","getDefaultValues","fieldSQExprs_2","getDataViewScopeIdentityComparisonExpr","fieldsExpr","compareExprs","compareExprs_1","getActiveTablesNames","queryDefn","tables","selectedItems","entityObj","isRelatedToMany","targetExpr","isRelated","isRelatedToOne","sourceMultiplicity","targetMultiplicity","navigationProperties","queue","shift","navProperties","navProperties_1","navProperty","isActive","isRelatedOneToOne","sourceNavigations","targetNavigations","hasOneToOneNavigation","navigationProperties_1","concatUnique","leftExprs","rightExprs","concatExprs","rightExprs_1","SemanticQueryRewriter","exprRewriter","rewriteFrom","fromValue","fromContents","originalFrom","originalFromKeys","keyName","originalEntityRef","originalEntityExpr","updatedEntityExpr","SQFrom","rewriteSelect","selectItems","rewriteNamedSQExpressions","rewriteGroupBy","groupByitems","expressions","SQExprRewriterWithSourceRenames","rewriteOrderBy","orderByItems","orderBy","updatedExpr","direction","rewriteWhere","whereItems","where","originalWhere","updatedWhere","SemanticQuery","groupBy","groupByItems","createWithTrimmedFrom","unreferencedKeyFinder","UnreferencedKeyFinder","filterTarget","unreferencedKeys","getSelect","setSelect","createNamedExpressionArray","rewriteExpressionsWithSourceRenames","removeSelect","originalItems","originalExpr","removeOrderBy","sorts","selectNameOf","setSelectAt","originalName","addSelect","exprName","createNamedExpr","currentNames","getGroupBy","setGroupBy","addGroupBy","getOrderBy","setOrderBy","clause","updatedOrderBy","getWhere","setWhere","updatedFilter","updatedTarget","addWhere","incomingWhere","updatedClause","contract","rewrittenContract","getDefaultValueFilter","getDataViewScopeIdentityComparisonFilters","getAnyValueFilter","filters","firstFilter","applyFilter","isDefaultFilter","isAnyFilter","leftFilter","rightFilter","filterWhereItems","filterWhereItem","updatedWhereItem","ensureEntity","desiredVariableName","i_1","candidateName","new","extend","renames","updatedName","rewriteFilter","updatedTargets","rewriteArray","updatedCondition","updatedExprs","QuerySourceRenameDetector","detector","existingEntity","actualEntity","CategoricalDataViewBuilder","pushIfNotExists","itemToAdd","applySeriesData","staticMeasureColumns","dynamicMeasureColumns","withValues","columns_8","staticSeriesValues","dynamicSeriesMetadata","valueColumns_1","dynamicSeriesValues","fillData","dataViewValues","first","seriesMeasures","measureIndex","measuresLen","hasStaticSeries","staticColumnsStartingIndex","metadataColumns","categoryMetadata","categoryMetadata_1","seriesValues","seriesValue","seriesIdentity","dynamicSeriesGroups_1","appendStaticMeasureColumns","isLegalDataView","isVisualDataView","StaticEvalContext","getTargetExpr","cols","selectTransforms_2","powerbi_1","FormattingEncoder","preserveEscaped","specialChars","oldText","newText","String","fromCharCode","restoreEscaped","preserveLiterals","literals","fromIndex","toIndex","literal","token","restoreLiterals","DateTimeFormat","IndexedTokensRegex","ZeroPlaceholder","DigitPlaceholder","ExponentialFormatChar","NumericPlaceholders","NumericPlaceholderRegex","FormattingService","culture","gculture","getCulture","canFormat","formatWithIndexedTokens","argToken","argIndex","argFormat","nonScientificOverrideFormat","formatWithCustomOverride","_dateTimeScaleFormatInfo","initialize","setCurrentCulture","cultureSelector","_currentCultureSelector","_currentCulture","DateTimeScaleFormatInfo","Globalize","findClosestCulture","getCurrentCulture","calendarName","getUrlParam","calendars","calendar","urlParam","common","cultureInfo","userLanguage","param","isStandard","formatDateStandard","formatDateCustom","patterns","ensurePatterns","processCustomDateTimeFormat","_currentCachedFormat","_currentCachedProcessedFormat","dictionary","timeSeparator","getNonScientificFormatWithPrecision","baseFormat","newFormat","hasFormatComponents","getComponents","positive","negative","zero","getNumericFormatFromComponent","NumericFormatRegex","formats","addDecimalsToFormatComponent","NumberFormatComponentsDelimeter","placeholder","decimalPlaceholders","DecimalFormatRegex","beforeDecimal","formatDecimal","afterDecimal","decimalChange","DecimalFormatCharacter","LastNumericPlaceholderRegex","signFormat","hasNegative","signSpecificFormats","formatCount","StandardFormatRegex","formatNumberStandard","formatNumberCustom","numberFormatInfo","numberFormat","formatChar","mantissaDecimalDigits","toFixed","toExponential","actualPrecision","isNegative","paddingZerosCount","paddingZeros","formatComponents","formatMeta","hasEscapes","hasQuotes","hasE","scientificMatch","ScientificFormatRegex","formatM","formatE","getCustomFormatPrecision","scale","getCustomFormatScale","indexOfE","mantissa","resultM","fuseNumberWithCustomFormat","resultE","valueFormatted","isValueGlobalized","toNonScientific","_lastCustomFormatMeta","precisionZeros","digitsBeforeDecimalPoint","maxPrecision","indexOfDot","powerZeros","calculatePrecision","calculateScale","hasCommas","hasDots","hasPercent","hasPermile","length_1","dotIndex","suppressModifyValue","formatParts","wholeFormat","fractionFormat","NumericalPlaceHolderRegex","globalizedDecimalSeparator","decimalSeparator","valueParts","wholeValue","fractionValue","TrailingZerosRegex","wholeFormattedValue","fuseNumberWithCustomFormatLeft","fractionFormattedValue","fuseNumberWithCustomFormatRight","fmtOnly","groupSymbolIndex","enableGroups","groupDigitCount","groupSizes","groupSize","groupSeparator","sign","firstChar","isZero","leftBuffer","vi","fi","fCount","vCount","lastChar","plus","minus","dot","comma","monthAbbreviations","cultureHasMonthAbbr","yearMonthPattern","monthDayPattern","fullPattern","longTimePattern","shortTimePattern","separator","hasYearSymbol","YearPattern","yearPos","monthPos","MonthPattern","DayPattern","minutePos","pmPos","shortHourPattern","HourPattern","MinutePattern","SecondPattern","MillisecondPattern","SQExprSerializer","agg","f","n","comp","const","o","highlight","keyWithoutHighlight","includes","ignoreHighlight","thisSelector","otherSelector","thisData","otherData","thisValue","otherValue","getKeyWithoutHighlight","selectorsByColumn","createNull","createWithMeasure","createWithIdAndMeasure","createWithIdAndMeasureAndCategory","createWithIds","id1","id2","idArray","createWithIdsAndMeasure","createWithHighlight","newId","data_4","builder","Point","Rect","createLegend","legendParentElement","interactive","interactivityService","isScrollable","legendPosition","LegendPosition","CartesianChartInteractiveLegend","SVGLegend","LegendIcon","legendProps","show","titleText","showTitle","labelColor","Legend","isLeft","orientation","Left","LeftCenter","isTop","TopCenter","positionChartArea","chartArea","legend","legendMargins","getMargins","legendOrientation","getOrientation","margin-left","margin-top","legendDataStartIndex","arrowPosWindow","lastCalculatedWidth","visibleLegendWidth","visibleLegendHeight","legendFontSizeMarginDifference","legendFontSizeMarginValue","svg","clearCatcher","appendClearCatcher","changeOrientation","parentViewport","calculateViewport","updateLayout","legendViewport","isRight","Right","RightCenter","isBottom","BottomCenter","pixelHeight","DefaultFontSizeInPt","fontHeightSize","TopLegendHeight","LegendMaxWidthFactor","isVisible","drawLegend","clonedData","newDataPoints","dataPoints","dp","setTooltipToLegendItems","drawLegendInternal","autoWidth","applySelectionStateToData","mapControl","isTopOrBottom","layout","calculateLayout","titleLayout","titleData","dataHasSelection","isCentered","centerOffset","SVGUtil","translate","legendTitle","LegendTitle","DefaultTitleFontFamily","exit","virtualizedDataPoints","numberOfItems","iconRadius","getTextProperties","LegendIconRadiusFactor","DefaultTextMargin","LegendIconRadius","legendItems","LegendItem","layerNumber","itemsEnter","LegendText","tooltip","DefaultFontFamily","cx","glyphPosition","cy","selected","LegendBehavior","dimmedLegendColor","textPosition","label","iconsSelection","behaviorOptions","legendIcons","isLegend","drawNavigationArrows","navigationArrows","normalizePosition","points","calculateTitleLayout","hasTitle","isHorizontal","maxMeasureLength","fontSizeMargin","TextAndIconPadding","fixedHorizontalIconShift","fixedHorizontalTextShift","LegendEdgeMariginWidth","MaxTitleLength","DefaultMaxLegendFactor","TitlePadding","navArrows","calculateHorizontalNavigationArrowsLayout","calculateHorizontalLayout","calculateVerticalNavigationArrowsLayout","calculateVerticalLayout","updateNavigationArrowLayout","remainingDataLength","visibleDataLength","lastWindow","LegendArrowHeight","LegendArrowWidth","translateY","rightShift","arrowLeft","createArrow","arrowRight","rotateTransform","verticalCenter","arrowTop","arrowBottom","titleHeight","calculateHorizontalLegendItemsWidths","availableWidth","iconPadding","dataPointsLength","maxItemWidth","maxItemTextWidth","MaxTextLength","occupiedWidth","dataPoints_1","dataPoint","itemTextWidth","desiredWidth","overMaxWidth","actualWidth","desiredOverMaxWidth","itemsOverMax","numItemsOverMax","extraWidth","itemsOverMax_1","extraWidthPerItem","newMaxItemWidth","usedExtraWidth","HorizontalTextShift","fontSizeBiggerThanDefault","fixedTextShift","iconTotalItemPadding","defaultTextProperties","textYCoordinate","LegendArrowOffset","legendItems_1","legendItem","LegendIconYRatio","textWidth","fontSizeBiggerThenDefault","fontFactor","verticalLegendHeight","spaceNeededByTitle","extraShiftForTextAlignmentToIcon","totalSpaceOccupiedThusFar","maxHorizontalSpaceAvaliable","maxHorizontalSpaceUsed","parentHeight","arrows","NavigationArrow","on","pos","isTitle","LegendData","legendContainerParent","LegendHeight","legendData","legendContainerDiv","LegendContainerSelector","divToPrepend","LegendContainerClass","drawTitle","drawLegendItems","titleDiv","LegendTitleClass","itemEnter","titleDivEnter","iconOnlyOnLabel","legendIconClass","legendPlaceSelector","legendColorCss","ensureLegendTableCreated","dataPointsMatrix","splitArrayToOddEven","legendItemsContainer","legendItemsEnter","rowEnter","cellEnter","cellSpanEnter","legendItemNameClass","legendItemMeasureClass","legendCells","TextUtil","removeBreakingSpaces","legendTable","setPanGestureOnLegend","viewportWidth","xscale","linear","domain","zoom","behavior","scaleExtent","tx_1","ty","translateXWithPixels","oddData","evenData","legendObject","fillColor","DefaultLegendLabelFillColor","axisScale","resources","axisStyle","showBoth","showTitleOnly","showUnitOnly","axisType","scalar","both","basicShapeType","rectangle","oval","line","arrow","triangle","imageScalingType","normal","fit","labelPosition","insideEnd","insideCenter","outsideEnd","insideBase","labelStyle","topCenter","bottomCenter","leftCenter","rightCenter","kpiDirection","lineStyle","dashed","dotted","outline","outline_1","showTop","topOnly","topBottom","frame","showRight","rightOnly","leftRight","showBottom","bottomOnly","showLeft","leftOnly","referenceLinePosition","back","front","referenceLineDataLabelHorizontalPosition","referenceLineDataLabelVerticalPosition","above","under","slicerOrientation","yAxisPosition","AnimatorCommon","GetAnimationDuration","animator","suppressAnimations","getDuration","MinervaAnimationDuration","MaxDataPointsToAnimate","BaseAnimator","animationDuration","animate","getEasing","WebColumnChartAnimator","failed","shapes","viewModel","previousViewModel","dataPointCount","hasHighlights","animateNormalToHighlighted","animateHighlightedToHighlighted","animateHighlightedToNormal","itemCS","shapeSelection","shapeLayoutWithoutHighlights","ColumnUtil","getFillOpacity","transition","shapeLayout","animateDefaultShapes","zeroShapeLayout","WebDonutChartAnimator","highlightShapes","graphicsContext","highlightRatio","insert","_current","DonutChart","isSingleColor","colors","getNewColorScale","getColor","drawStrokeForDonutChart","radius","innerArcRadiusRatio","sliceWidthRatio","strokeWidth","highlightShapeLayout","NewDataLabelUtils","drawDefaultLabels","labelGraphicsContext","labels","drawLabelLeaderLines","animateDefaultHighlightShapes","WebFunnelAnimator","dataLabels","animateDefaultAxis","axisGraphicsContext","axisOptions","isHidingPercentBars","shapeGraphicsContext","FunnelChart","Selectors","funnel","bars","slices","FunnelBarHighlightClass","animatePercentBars","animateDefaultDataLabels","exitShapes","xScaleForAxis","ordinal","categoryLabels","rangeBands","rangeStart","rangeEnd","barToSpaceRatio","PercentBarToBarRatio","xAxis","orient","tickPadding","TickPadding","innerTickSize","InnerTickSize","margin","dataLabelsSettings","canShowDataLabels","dataLabelUtils","drawDefaultLabelsForFunnelChart","labelLayout","cleanDataLabels","animatePercentBarComponents","baseline","getFunnelSliceValue","percentData","percent","animateToFunnelPercent","targetData","percentGraphicsContext","zeroData","mainLine","percentBar","percentBarLayout","leftTick","rightTick","fp","flushAllD3TransitionsIfNeeded","visualInitOptions","WebTreemapAnimator","majorLabels","minorLabels","Treemap","HighlightNodeClassName","highlightNodes","highlightShapeClass","getFill","animateDefaultMajorLabels","majorLabeledNodes","labelSettings","animateDefaultMinorLabels","minorLabeledNodes","TreemapNodeClassName","shapeClass","isHighlightShape","MajorLabelClassName","majorLabelClass","majorLabelText","majorLabelLayout","MinorLabelClassName","minorLabelClass","minorLabelText","minorLabelLayout","StandardObjectProperties","axisEnd","description","placeHolderText","suppressFormatPainterCopy","axisStart","backColor","dataColor","dataLabelColor","dataLabelDecimalPoints","dataLabelDisplayUnits","dataLabelHorizontalPosition","dataLabelShow","dataLabelVerticalPosition","fontColor","labelPrecision","lineColor","outlineColor","outlineWeight","showAllDataPoints","showLegendTitle","referenceLineStyle","transparency","animatedTextObjectDescs","general","animatedNumberCapabilities","supportsSelection","basicShapeCapabilities","weight","roundEdge","rotation","angle","shapeType","suppressDefaultTitle","suppressDefaultPadding","canRotate","basicShapeProps","getColumnChartCapabilities","transposeAxes","categoryAxis","showAxisTitle","valueAxis","intersection","y1AxisReferenceLine","useHighlightValues","showSeries","plotArea","Category","Series","Gradient","Y","for","in","supportsHighlight","sorting","default","drilldown","columnChartProps","comboChartCapabilities","visualType1","visualType2","axisLabel","secShow","secAxisLabel","secPosition","secAxisScale","secStart","secEnd","secShowAxisTitle","secAxisStyle","secLabelDisplayUnits","secLabelPrecision","Y2","comboChartProps","donutChartCapabilities","donutChartProps","dataDotChartCapabilities","filledMapCapabilities","preferredTypes","X","Size","filledMapProps","funnelChartCapabilities","percentBarLabel","funnelChartProps","gaugeRoleNames","minValue","gaugeCapabilities","calloutValue","MinValue","MaxValue","TargetValue","gaugeProps","imageVisualCapabilities","imageScaling","scriptVisualCapabilities","dataInput","samples","consoleWriterCapabilities","ConsoleWriter","converter","anchor","lineChartCapabilities","lineChartProps","mapCapabilities","mapProps","multiRowCardCapabilities","cardTitle","card","barShow","barColor","barWeight","cardPadding","cardBackground","disableVisualDetails","multiRowCardProps","textboxCapabilities","cheerMeterCapabilities","scatterChartCapabilities","xAxisReferenceLine","colorBorder","fillPoint","colorByCategory","currentFrameIndex","Play","implicit","clauses","scatterChartProps","slicerCapabilities","selection","selectAllCheckboxEnabled","singleSelect","header","background","Values","includeEmptyGroups","slicerProps","selectedPropertyIdentifier","filterPropertyIdentifier","tableCapabilities","columnWidth","totals","autoSizeColumnWidth","grid","gridVertical","gridVerticalColor","gridVerticalWeight","gridHorizontal","gridHorizontalColor","gridHorizontalWeight","rowPadding","imageHeight","columnHeaders","fontColorPrimary","backColorPrimary","fontColorSecondary","backColorSecondary","urlIcon","total","matrixRoleNames","matrixCapabilities","rowSubtotals","columnSubtotals","rowHeaders","subTotals","Rows","filterMappings","measureFilter","targetRoles","treemapCapabilities","Group","Details","treemapProps","cardCapabilities","wordWrap","cardProps","waterfallChartCapabilities","sentimentColors","increaseFill","decreaseFill","totalFill","waterfallChartProps","KPIStatusWithHistoryCapabilities","Indicator","TrendLine","Goal","indicator","indicatorDisplayUnits","indicatorPrecision","kpiFormat","trendline","goals","showGoal","showDistance","animatedNumber","areaChart","barChart","multiRowCard","clusteredBarChart","clusteredColumnChart","columnChart","comboChart","dataDotChart","dataDotClusteredColumnComboChart","dataDotStackedColumnComboChart","donutChart","gauge","hundredPercentStackedBarChart","hundredPercentStackedColumnChart","lineChart","lineStackedColumnComboChart","lineClusteredColumnComboChart","filledMap","treemap","pieChart","scatterChart","slicer","textbox","waterfallChart","cheerMeter","scriptVisual","ColumnChartWebBehavior","bindEvents","selectionHandler","eventGroup","getDatumForLastInputEvent","handleSelection","ctrlKey","preventDefault","InteractivityUtils","getPositionOfLastInputEvent","handleContextMenu","renderSelection","datum","DataDotChartWebBehavior","dots","dotLabels","registerStandardInteractivityHandlers","DonutChartWebBehavior","highlightSlices","clickHandler","contextMenuHandler","handleClearSelection","FunnelWebBehavior","interactors","LineChartWebBehavior","lines","interactivityLines","areas","tooltipOverlay","LineChart","DimmedAreaFillOpacity","AreaFillOpacity","MapBehavior","mapPointerEventsDisabled","mapPointerTimeoutSet","viewChangedSinceLastClearMouseDown","receivedZoomOrPanEvent","bubbles","bubbleEventGroup","registerGroupContextMenuHandler","sliceEventGroup","shapeEventGroup","fill-opacity","stroke-opacity","viewChanged","resetZoomPan","hasReceivedZoomOrPanEvent","ScatterChartWebBehavior","dataPointsSelection","playOptions","traceLineRenderer","shouldEnableFill","sizeRange","registerGroupInteractivityHandlers","ScatterChart","getMarkerFillOpacity","getMarkerStrokeOpacity","selectedPoints","render","ScatterChartMobileBehavior","setOptions","interactivity","isInteractiveLegend","makeDataPointsSelectable","makeRootSelectable","makeDragable","disableDefaultTouchInteractions","selectRoot","HasSelection","setSelectionHandler","sel","drag","mainGraphicsContext","plotContext","xAxisProperties","yAxisProperties","selectDotByIndex","marker","onClick","onDrag","xy","getMouseCoordinates","moveCrosshairToXY","selectedIndex","findClosestDotIndex","selectDot","updateLegend","mainGfxContext","mouse","moveCrosshairToIndexDot","ScatterChartCircleTagName","DotClassSelector","notSelected","currentPoint","crosshair","drawCrosshair","crosshairHorizontal","Horizontal","crosshairVertical","Vertical","y1","y2","addTo","CrosshairClassName","minDistance","xAxisPropertiesScale","yAxisPropertiesScale","circleX","circleY","horizontalDistance","verticalDistance","distanceSqrd","lastDotIndex","createLegendDataPoints","point","blank","legendDataPoints","formattedCategory","sizeMeasure","xCol","icon","Box","axesLabels","yCol","DotClassName","HorizontalSlicerWebBehavior","itemLabels","slicerSettings","settings","SlicerWebBehavior","bindSlicerEvents","slicerContainer","setSelectionOnSlicerItems","VerticalSlicerWebBehavior","slicers","itemContainers","itemInputs","createWebBehavior","slicerClear","bindSlicerItemSelectionEvent","bindSlicerClearEvent","styleSlicerContainer","selectableItems","itemLabel","isSelectionModeInverted","styleSlicerItems","slicerText","slicerItems","isSelectionInverted","slicerItem","shouldCheck","isSelectAllDataPoint","classList","checked","isTouch","pointerType","toggleSelectionModeInversion","isMultiSelect","persistSelectionFilter","isDefaultValueEnabled","registerStandardSelectionHandler","TreemapWebBehavior","WaterfallChartWebBehavior","isTotal","DefaultOpacity","LabelsBehavior","labelItems","opacity","DefaultLabelOpacity","DimmedLabelOpacity","CartesianChartBehavior","behaviors","layerOptions","emptyDomain","AxisHelper","getRecommendedNumberOfTicksForXAxis","getRecommendedNumberOfTicksForYAxis","getBestNumberOfTicks","valuesMetadata","maxTickCount","isDateTime","DefaultBestTickCount","hasNonIntegerData","currentMetadata","getRecommendedTickValues","maxTicks","isScalar","minTickInterval","isOrdinalScale","getRecommendedTickValuesForAnOrdinalRange","getRecommendedTickValuesForADateTimeRange","getRecommendedTickValuesForAQuantitativeRange","tickLabels","minInterval","quantitiveScale","ticks","MinTickCount","createTrueZeroTickLabel","tickInterval","epsilon","closeZero","tick","dataDomain","dateTimeTickLabels","ensureValuesInRange","normalizeLinearDomain","getMargin","availableHeight","xMargin","yMargin","getTickLabelMargins","yMarginLimit","textHeightMeasurer","axes","bottomMarginLimit","scrollbarVisible","showOnRight","renderXAxis","renderY1Axis","renderY2Axis","y1AxisProperties","y2AxisProperties","xLabels","y1Labels","leftOverflow","rightOverflow","maxWidthY1","maxWidthY2","ordinalLabelOffset","categoryThickness","scaleIsOrdinal","xLabelOuterPadding","outerPadding","xLabelMaxWidth","LabelLayoutStrategy","DefaultRotationWithScrollbar","DefaultRotation","y2Labels","textHeight","xScale","xDomain","willLabelsWordBreak","wordBreaks","willLabelsFit","sine","cosine","TextHeightConstant","xPos","XLabelMaxAllowedOverflow","rightMargin","leftMargin","bottomMargin","yLeft","yRight","columnDataTypeHasValue","createOrdinalType","isOrdinal","invert","invertScale","invertOrdinalScale","extent","rangeExtent","leftEdges","rangeBand","halfInnerPadding","findClosestXAxisIndex","categoryAxisValues","closestValueIndex","distance","lookupOrdinalIndex","pixelValue","halfWidth","leftEdgeInPixels","midPoint","diffScaled","value1","createDomain","forcedScalarDomain","ensureDomain","userMin","userMax","createScalarDomain","createOrdinalDomain","filteredValues","getCategoryValueType","createAxis","pixelSpan","metaDataColumn","isCategoryAxis","isVertical","useTickIntervalForDisplayUnits","getValueFn","axisDisplayUnits","axisPrecision","is100Pct","scaleResult","createScale","bestTickCount","scaleDomain","isLogScaleAllowed","isLogScalePossible","oldSpan","newSpan","tickValues","getMinTickValueInterval","scaleType","powerOfTen","formatter","createFormatter","tickSize","formattedTickValues","formatAxisTickValues","CartesianChart","TickLabelPadding","getScalarLabelMaxWidth","ScalarTickLabelPadding","usingDefaultDomain","forcedTickCount","shouldClamp","scalarDomain","createOrdinalScale","createNumericalScale","normalizedRange","createLinearScale","MinOrdinalRectThickness","reverse","normalizeInfinityInScale","tickFormat","defaultMinX","kv","defaultMaxX","combineDomain","createValueDomain","minY","maxY","firstSeries","outerPaddingRatio","InnerPaddingRatio","axisScaleType","niceCount","createLogScale","clamp","nice","getRangeForColumn","sizeColumn","applyCustomizedDomain","customizedDomain","forcedDomain","combinedDomain","domainBeforeForced","createAxisLabel","unitType","modifiedLabel","scaleShouldClamp","normalizeNonFiniteNumber","LN10","LeftPadding","axisProperties","textMeasurer","labelMaxWidth","textTruncator","maxRotatedLength","mustRotate","moreWordBreakChars","allowedLengthProjectedOnXAxis","allowedLength","rotatedLength","wordBreakChars","rotateChars","removeEllipses","labelSelection","maxBottomMargin","needRotate","needEllipsis","defaultRotation","textContentIndex","dx","newLabelText","clip","sin","PI","cos","tangent","tan","ShapeFactory","createRectangle","viewportHeight","selectedElement","degrees","ShapeFactoryConsts","PaddingConstRatio","lineWeight","ShapeConstRatio","attrs","rx","ry","createShape","createOval","widthForCircle","OvalRadiusConst","heightForCircle","radiusXForCircle","OvalRadiusConstPadding","radiusYForCircle","createLine","ratio","SmallPaddingConstValue","vector-effect","stroke-width","lineTransparency","stroke","createUpArrow","viewportHeightWeight","viewportWidthWeight","arrowPoints","ArrowLeftHeadPoint","ArrowMiddleHeadPoint","ArrowRightHeadPoint","ArrowRightMiddleHeadPoint","ArrowBottomRightPoint","ArrowBottomLeftPoint","ArrowLeftMiddleHeadPoint","createPathFromArray","createTriangle","firstPointX","TrianglePaddingConstRatio","firstPointY","secondPointY","thirdPointX","TriangleEndPaddingConstRatio","thirdPointY","secondPointX","trianglePoints","lineFunction","interpolate","shapeAttrs","transform-origin","-webkit-transform","-webkit-transform-origin","showFill","shapeTransparency","originalWidth","originalHeight","offsetAngle","atan2","originalFactor","sqrt","radians","CartesianHelper","getCategoryAxisProperties","axisTitleOnByDefault","toReturn","categoryAxisObject","getValueAxisProperties","valueAxisObject","secLabelColor","xAxisCardProperties","lookupXValue","dataAtIndex","findMaxCategoryIndex","maxCategoryIndex","series_1","singleSeries","ColorHelper","fillProp","defaultDataPointColor","defaultColorScale","getColorForSeriesValue","fieldIds","getColorScaleForSeries","getColorScaleByKey","getColorForMeasure","measureKey","scaleColor","normalizeSelector","isSingleSeries","rectName","applyUserMinMax","transformDomain","categoryObjects","newcategoryValues","newObjects","resultDataView","resultDataViewValues","resultDataViewCategories","resultDataViewCategories0","measureArray","getCategoryAxis","forcedXMin","forcedXMax","ensureXDomain","applyInteractivity","onDragStart","hasPartialHighlights","DimmedOpacity","getClosestColumnIndex","coordinate","columnsCenters","currentIndex","currentDistance","setChosenColumnOpacity","columnGroupSelector","selectedColumnIndex","lastColumnIndex","ColumnChart","SeriesClasses","lastColumnUndefined","drawSeries","colGroupSelection","drawDefaultShapes","filterZeros","filteredData","datapoint","viewPort","isAnimator","drawDefaultLabelsForDataPointChart","scaledDomain","calculatePosition","yScale","scaledY0","scaledX0","chartType","ColumnChartType","stackedBar","hundredPercentStackedBar","valueAbsolute","defaultColumnLabelMargin","clusteredBar","stackedColumn","hundredPercentStackedColumn","clusteredColumn","ClusteredUtil","clearColumns","StackedUtil","zeroVal","calcValueDomain","is100pct","defaultNumberRange","PctRoundingError","getStackedMultiplier","categoryCount","converterStrategy","neg","getValueBySeriesAndCategory","absTotal","converterHelper","categoryIsAlsoSeriesRole","seriesRoleName","getPivotedCategories","categoryFormatter","defaultCategories","getFormattedLegendLabel","sourceForFormat","nameForFormat","createAxesLabels","categoryAxisProperties","valueAxisProperties","xAxisLabel","yAxisLabel","valuesNames","self","isImageUrlColumn","getMiscellaneousTypeDescriptor","isWebUrlColumn","hasImageUrlColumn","formatFromMetadataColumn","LabelStyle","updateLabelSettingsFromLabelsObject","labelsObj","displayUnits","defaultLabelPrecision","showLabelPerSeries","updateLineChartLabelSettingsFromLabelsObject","getDefaultLabelSettings","defaultLabelColor","formatterOptions","getDefaultCardLabelSettings","categoryLabelColor","showCategory","getDefaultTreemapLabelSettings","defaultInsideLabelColor","getDefaultSunburstLabelSettings","getDefaultColumnLabelSettings","isLabelPositionInside","getDefaultPointLabelSettings","getDefaultLineChartLabelSettings","isComboChart","LabelDensityMax","LabelDensityMin","getDefaultMapLabelSettings","getDefaultDonutLabelSettings","getDefaultGaugeLabelSettings","minLabelFontSize","getDefaultFunnelLabelSettings","getDefaultKpiLabelSettings","getLabelPrecision","positiveFormat","formatMetadata","defaultCountLabelPrecision","dataLabelManager","DataLabelManager","hideCollidedLabels","hasAnimation","selectLabels","labeltext","labelX","labelY","isDonut","forAnimation","labelGraphicsContextClass","hasKey","hasDataPointIdentity","getIdentifier","labelsClass","newLabels","removeLines","lineClass","linesGraphicsContextClass","setHighlightedLabelsOpacity","labelOpacity","getLabelFormattedText","LabelTextProperties","maxLabelWidth","getLabelLayoutXYForWaterfall","categoryWidth","getWaterfallLabelYPosition","yValue","yPos","scaleMinDomain","endPosition","outsideBelowPosition","outsideAbovePosition","labelMargin","isLabelInside","getWaterfallInsideLabelYPosition","startPosition","doesDataLabelFitInShape","outsidePosition","WaterfallChart","getRectTop","shapeWidth","shapeHeight","getMapLabelLayout","labelFill","getColumnChartLabelLayout","labelLayoutXY","isHundredPercent","axisFormatter","visualWidth","formatOverride","hundredPercentFormat","formattersCache","createColumnFormatterCacheManager","labelFormatString","getDisplayUnitValueFromAxisFormatter","getOrCreate","getColumnChartLabelFilter","text-anchor","validateLabelsSize","inside","lastSeries","shapesOpacity","getScatterChartLabelLayout","getBubbleRadius","getLineChartLabelLayout","getFunnelChartLabelLayout","textMinimumPadding","currentViewport","categoryScale","valueScale","marginLeft","innerTextHeightRate","barWidth","insideAvailableSpace","outsideAvailableSpace","maximumTextSize","labelHeight","categoryOrMeasureIndex","textLength","labelPositionValue","enumerateDataLabels","positionObject","validValues","lineChartSettings","pushInstance","enumerateCategoryLabels","withFill","isShowCategory","defaultFormatter","labelSetting","cacheKeyObject","cacheKey","getOptionsForLabelFormatter","isTextWidthOverflows","maxTextWidth","isTextHeightOverflows","innerChordLength","defaultColumnHalfLabelHeight","DefaultDy","StandardFontFamily","DonutLabelUtils","getLabelLeaderLineForDonutChart","donutArcDescriptor","donutProperties","parentPoint","sliceArc","textPoint","chartPoint","innerLinePointMultiplier","arc","outerRadius","outerArcRadiusRatio","innerRadius","outerArc","centroid","textPointX","lineMargin","maxLabelOffset","getLabelLeaderLinesSizeForDonutChart","leaderLinePoints","diagonalLineSize","horizontalLineSize","LineStrokeWidth","getXPositionForDonutLabel","getSpaceAvailableForDonutLabels","labelXPos","DiagonalLineIndex","HorizontalLineIndex","twoRows","hasTooltip","filteredDataLabels","labelKeyFunction","labelAttr","boundingBox","hasBackground","verticalLabelBackgroundPadding","DefaultLabelFontSizeInPt","textAnchor","filteredCategoryLabels","secondRowText","secondLineLabels","secondLineLabelClass","boundingBoxHeight","animateDefaultLabels","easeType","ease","drawLabelBackground","fillOpacity","labelRects","horizontalLabelBackgroundPadding","labelBackgroundRounding","leaderLineColor","removeDuplicates","labelDataPoints","uniqueLabelDataPoints","labelDataPointMap","sameParentIsInArray","newValue","parentIsRect","arrayValue","parentShape","labelDataPoints_1","parentType","resultsFromMap","getDataLabelLayoutOptions","maximumOffset","dataLabelLayoutMaximumOffset","startingOffset","dataLabelLayoutStartingOffset","offsetIterationDelta","dataLabelLayoutOffsetIterationDelta","allowLeaderLines","attemptToMoveLabelsIntoViewport","startingLabelOffset","getTextSize","labelTextProperties","MapPolylineOpacity","LabelDensityBufferFactor","LabelDensityPadding","labelBackgroundGraphicsContextClass","KpiUtil","getKpiIcon","numValue","statusGraphicFormat","statusGraphicFormatStrings","graphic","statusValues","normalizedFiveStateKpiRange","num","kpiIconClass","getKpiIconClassName","kpiIcon","kpiImageSize","KPIImageClassName","BigImageClassName","getClassForKpi","getKpiImageMetadata","caption","statusGraphic","RYGStatusIconClassNames","threeLights","roadSigns","trafficLight","THREE CIRCLES COLORED","TRAFFIC LIGHT - SINGLE","THREE FLAGS COLORED","ROAD SIGNS","THREE SYMBOLS CIRCLED COLORED","TRAFFIC LIGHT","THREE TRAFFIC LIGHTS RIMMED COLORED","THREE SYMBOLS UNCIRCLED COLORED","SHAPES","SMILEY FACE","THERMOMETER","CYLINDER","THREE SIGNS COLORED","THREE STARS COLORED","FIVE BARS COLORED","FIVE BOXES COLORED","FIVE QUARTERS COLORED","GAUGE - ASCENDING","GAUGE - DESCENDING","STANDARD ARROW","VARIANCE ARROW","STATUS ARROW - ASCENDING","STATUS ARROW - DESCENDING","ReferenceLineHelper","referenceLines","referenceLines_1","referenceLine","referenceLineProperties","referenceLineProps","graphicContext","classAndSelector","refValue","refLine","currentPosition","isRefLineExists","isPositionChanged","refLineX1","refLineY1","refLineX2","refLineY2","stroke-dasharray","stroke-linecap","createLabelDataPoint","offsetRefLine","decimalPoints","horizontalPosition","verticalPosition","formatterForReferenceLineDataLabel","dataLabelX","dataLabelY","rectWidth","rectHeight","validPositions","isPreferred","outsideFill","insideFill","extractReferenceLineValue","referenceLineValue","clientX","clientY","registerStandardContextMenuHandler","registerGroupSelectionHandler","getInvalidValueWarnings","supportsNaN","supportsNegativeInfinity","supportsPositiveInfinity","checker","InvalidDataValuesChecker","getWarningMessages","loadWarningStatus","warnings","hasNaN","NaNNotSupportedWarning","hasNegativeInfinity","hasPositiveInfinity","InfinityValuesNotSupportedWarning","hasOutOfRange","ValuesOutOfRangeWarning","valueLength","valueValueLength","ListViewFactory","createListView","ListView","scrollbarInner","baseContainer","renderImpl","rowHeight","scrollContainer","stopTouchPropagation","visibleGroupContainer","SetDefaultOptions","defaultRowHeight","getDatumIndex","dataReset","_data","setTotalRows","scrollTop","renderTimeoutId","clearTimeout","getRowHeight","totalHeight","scrollEnabled","_totalRows","scrollToFrame","isReadMode","event_1","touches","stopPropagation","loadMoreData","totalRows","visibleRows","getVisibleRows","scrollPosition","transformAttr","translateWithPixels","position0","position1","topRowHiddenHeight","halfRowHeight","rowSelection","order","rowUpdateSelection","loadMoreDataThreshold","minimumVisibleRows","listView","cancelMeasurePass","requestAnimationFrameId","firstRow","outerHeight","cancelAnimationFrame","MapUtil","defaultLevelOfDetail","getMapSize","levelOfDetail","latLongToPixelXYArray","latLongArray","buildString","helperArray","Float64Array","arrayString","MinAllowedLatitude","MaxAllowedLatitude","MinAllowedLongitude","MaxAllowedLongitude","sinLatitude","mapSize","pointArrayChunkLength","getLocationBoundaries","northWest","southEast","Microsoft","Maps","LocationRect","fromCorners","Location","parseEncodedSpatialValueArray","xsum","ysum","safeCharacters","tmp","ht","lt","hn","ln","nl","diagonal","ny","nx","lat","lon","calcGeoData","locations","location_1","geographic","nativeBing","polygon","absolute","DefaultLevelOfDetail","absoluteString","geographicBounds","absoluteBounds","locationRectToRectXY","locationToPixelXY","latLongToPixelXY","locationRect","topleft","getNorthwest","bottomRight","getSoutheast","pixelXYToLocation","pixelX","pixelY","atan","Settings","MaxBingRequest","MaxCacheSize","MaxCacheSizeOverflow","BingKey","BingUrl","BingUrlGeodata","UseDoubleArrayGeodataResult","UseDoubleArrayDequeueTimeout","TileSize","MaxLevelOfDetail","MinLevelOfDetail","MaxAutoZoomLevel","WorkerErrorName","CurrentLocation","createPushpin","template","draggable","htmlContent","Pushpin","MapPolygonInfo","_locationRect","reCalc","baseLocations","_baseRect","l0","l1","tryLocationToPixel","_currentRect","base","Transform","setViewBox","getBoundingClientRect","transformToString","m00","m10","m01","m11","m02","m12","Polygon","absolutePoints","polygonPoints","convertArrayPathToPoints","absoluteCentroid","_absoluteCentroid","calculatePolygonCentroid","absoluteBoundingRect","_absoluteBoundingRect","calculateBoundingRect","topLeft","topRight","bottomLeft","conflicts","isConflictWithBoundingBox","middleLeft","middleRight","lineIntersectionPoint","p0","p1","p2","p3","getLineIntersection","calculateAbsolutePolygonArea","area","isIntersecting","tempPoint","minX","maxX","insideVar","xi","yi","xj","yj","line0p1","line0p2","line1p1","line1p2","p0_x","p0_y","p1_x","p1_y","p2_x","p2_y","p3_x","p3_y","s1_x","s1_y","s2_x","s2_y","pointsRes","newPoint","offsetX","offsetY","newPointX","newPointY","getDistance","diffX","diffY","point1","point2","parsePoint","inflate","padding","deflate","combine","toRect","size1","size2","parseSize","getOffset","setSize","newLeft","newTop","inflateBy","deflateBy","getClosestPoint","rect1","rect2","containsPoint","parseRect","Thickness","thickness","getHeight","flipHorizontal","flipVertical","toCssString","thickness1","thickness2","parseThickness","resetValue","Vector","vector","getLength","getLengthSqr","normalize","rotate90DegCW","rotate90DegCCW","newX","newY","vector1","vector2","vect1","vect2","subtract","dotProduct","getDeltaVector","SlicerUtil","tryRemoveValueFromRetainedList","selectedScopeIds","caseInsensitive","retainedValueScopeId","HeaderContainer","Header","HeaderText","Body","Label","LabelText","LabelImage","CountText","Clear","MultiSelectEnabled","DisplayNameKeys","SelectAll","SettingsHelper","areSettingsDefined","DefaultValueHandler","getIdentityFields","DOMHelper","createSlicerHeader","slicerHeaderDiv","slicerHeader","getHeaderTextProperties","headerTextProperties","getSlicerBodyViewport","headerHeight","getHeaderHeight","slicerBodyHeight","borderBottomWidth","updateSlicerBodyDimensions","slicerBody","slicerViewport","getRowsOutlineWidth","styleSlicerHeader","headerText","headerTextElement","setSlicerHeaderTextStyle","setSlicerTextStyle","background-color","border-style","border-color","border-width","VisualBorderUtil","getBorderWidth","outlineElement","tooltipUtils","tooltipUpdate","tooltips","titles","titlesUpdate","translateAndRotate","py","translateAndScale","transformOrigin","xOffset","yOffset","flushAllD3Transitions","timer","flush","animationOptions","asVisualInitOptions","animation","transitionImmediate","ensureDAttribute","pathElement","getAttribute","ensureValidSVGPoint","parseTranslateTransform","xValue","translateCoordinates","xCoord","yCoord","getTransformScaleRatios","scaledRect","domRect","AlmostZero","SVGScaleDetector","scaleDetectorElement","replaceSpaceWithNBSP","txt","GradientUtils","getFillRuleRole","objectDescs","FillRulePropertyIdentifier","shouldShowGradient","visualConfig","isShowGradienCard","query","getUpdatedGradientSettings","gradientObject","gradientSettings","isEmptyObject","getDefaultGradientSettings","hasProperty","getGradientMeasureIndex","getGradientValueColumn","gradientMeasureIndex","gradientValueColumn","hasGradientRole","getDefaultColors","diverging","minColor","midColor","DefaultMidColor","maxColor","getDefaultFillRuleDefinition","getLinearGradien2FillRuleDefinition","updateFillRule","numericValueExpr","colorValueExpr","dataPointObjectDefinition","DataPointPropertyIdentifier","getFillRule","getColorExpressionValue","updateMinColor","updateMidColor","updateMaxColor","updateMinValue","updateMidValue","updateMaxValue","getLinearGradien3FillRuleDefinition","getGradientSettings","baseFillRule","getGradientSettingsFromRule","fillRuleDefinition","dataColors","DataColorPalette","maxColorInfo","getColorByIndex","maxColorExpr","minColorExpr","maxValueExpr","minValueExpr","midColorExpr","midValueExpr","getGradientBarColors","getDefaultColorExpression","defaultFillRule","colorExpressionValue","visualBackgroundHelper","getDefaultColor","getDefaultTransparency","getDefaultShow","enumeratePlot","backgroundObject","renderBackgroundImage","visualElement","imageFit","imageTransparency","backgroundImage","background-image","background-repeat","background-size","background-position","ObjectEnumerationBuilder","instances","containerIdx","instances_1","existingInstance","canMerge","pushContainer","container","containers","updatedLen","popContainer","sourceValues","targetValues","valuePropertyName","xNormalized","yNormalized","xCategoryCount","yInstance","yContainers","getContainerForInstance","outlineType","createTranslateMatrix","createScaleMatrix","createRotationMatrix","angleInRads","sinA","cosA","createInverseMatrix","determinant","invdet","multiplyMatrices","applyToPoint","applyToRect","x0","y0","isScaled","isRotated","p0x","p0y","p1x","p1y","p2x","p2y","p3x","p3y","_inverse","angleInRadians","getInverse","TrendLineHelper","trendLines","defaults","trendObjectName","trendLine","isDataViewForRegression","readDataView","trendProperties","trendLinePropertyNames","legacyColor","colorHelper","seriesLineColor","sourceGroups","darkenTrendLineColor","matchingMeasure","y2Axis","layer","TrendLineLayerClassSelector","TrendLineClassSelector","pathGen","visibilityHelper","partiallyVisible","is","VisualObjectRepetition","DataConversion","localizedSelectAllText","analyzer","analyzeFilter","defaultValuePropertyId","analyzedSemanticFilter","changes","persistProperties","slicerData","getSlicerData","isInvertedSelectionMode","selectedIdentities","hasSelectionOverride","isNotFilter","setSelectionModeInverted","setDefaultValueMode","categoryValuesLen","slicerDataPoints","numOfSelected","valueCounts","isImageData","displayNameIdentityPairs","isRetained","isImage","slicerData_1","displayNameIdentityPair","setIdentityDisplayNames","displayNamesIdentityPairs","getIdentityDisplayNames","displayNamesIdentityPairs_1","pair","slicerData_2","defaultSettings","createDefaultSettings","slicerDataPoints_1","categorySourceName","Slicer","DefaultStyleProperties","forceSingleSelect","headerBackground","textBackground","RectOrientation","OutsidePlacement","movingStep","hideOverlapped","defaultDataLabelSettings","anchorMargin","DefaultAnchorMargin","anchorRectOrientation","contentPosition","outsidePlacement","Disallowed","maximumMovingDistance","DefaultMaximumMovingDistance","minimumMovingDistance","DefaultMinimumMovingDistance","validContentPositions","addTransform","arrangeGrid","DataLabelArrangeGrid","getLabelInfo","anchorPoint","calculateContentPosition","hasCollisions","calculateContentPositionFromPoint","contentSize","calculateContentPositionFromRect","anchorRect","handleInsideCenterPosition","handleInsideEndPosition","handleInsideBasePosition","handleOutsideEndPosition","handleOutsideBasePosition","VerticalBottomTop","VerticalTopBottom","LocationConverter","middleVertical","HorizontalLeftRight","HorizontalRightLeft","middleHorizontal","topInside","bottomInside","leftInside","rightInside","topOutside","bottomOutside","leftOutside","rightOutside","anchoredElementInfo","hasConflict","InflateAmount","Partial","elements","cellSize","baseProperties","labelFontSize","getGridRowColCount","ARRANGEGRID_MIN_COUNT","ARRANGEGRID_MAX_COUNT","indexRect","getGridIndexRect","z","minCount","restrict","LabelArrangeGrid","labelDataPointsGroups","maxLabelHeight","labelDataPointsGroups_1","labelDataPointsGroup","labelDataPoint","dataLabelSize","labelSize","cellSizeMultiplier","columnCount","getCellCount","containingIndexRect","getContainingGridSubsection","yMin","yMax","isWithinGridViewport","hasCollision","tryPositionInViewport","isCloseToGridViewport","tryMoveInsideViewport","currentGridRect","bound","LabelLayout","defaultOffsetIterationDelta","horizontalPadding","defaultHorizontalPadding","verticalPadding","defaultVerticalPadding","labelDataPointsGroups_2","labelPoint","hasBeenRendered","resultingDataLabels","labelDataPointsGroups_3","maxLabelsToRender","maxNumberOfLabels","preferredLabels","localMax","positionedLabels","positionDataLabels","drawLeaderLinesOnIteration","offsetDelta","currentOffset","currentCenteredOffset","labelDataPoints_2","dataLabel","tryPositionForRectPositions","tryPositionForPointPositions","currentLabelOffset","currentCenteredLabelOffset","tryPosition","adjustForViewport","isPositionInside","DataLabelRectPositioner","canFitWithinParent","resultingBoundingBox","tryPositionRect","isLabelWithinParent","offsetForPosition","labelRect","getLabelRect","drawLeaderLines","tryPositionPoint","isInsideParent","DataLabelPointPositioner","getLabelLeaderLineEndingPoint","validPositions_1","parentRect","labelRectWithPadding","below","belowLeft","belowRight","aboveLeft","aboveRight","center","sin45","cos45","DonutLabelLayout","donutChartProperties","additionalCharsWidth","labelDataPoints_3","donutLabel","resultingLabels","positionLabels","labelDataPoints_4","tryPositionForDonut","defaultPosition","bestCandidate","tryAllPositions","score","buildLabel","splitLabelDataPoint","splitDonutDataPoint","bestSplitCandidate","generateCandidate","candidatePosition","generateCandidateAngleForPosition","getPointPositionForAngle","leaderLinesSize","newLabelDataPoint","linesSize","boundingBoxs","originalPoint","originalCandidate","textRect","positions","getLabelPointPositions","positions_1","candidate","horizontalLineRect","diagonalLineRect","formattedDataLabel","formattedCategoryLabel","labelSettingsStyle","spaceAvailableForLabels","hasOneLabelRow","categoryLabel","diagonalLineParentPoint","horizontalLineParentPoint","centerForLinesWidth","isTruncated","categoryLabelSize","newLabelPoint","midAngle","startAngle","endAngle","pointPosition","DefaultCentroidOffset","OffsetDelta","MaximumOffset","stemExtension","FilledMapLabelLayout","polygonInfoTransform","redrawDataLabels","labelDataPoints_5","allPolygons","labelDataPoints_6","pixelBoundingRect","shapesgrid","LabelPolygonArrangeGrid","labelDataPoints_7","getLabelByPolygonPositions","updateLabelOffsets","getLabelPolygon","mapDataPoint","dataPointSize","getLabelBoundingBox","shapesGrid","inverseTransorm","resultingAbsoluteBoundingBox","tryPositionForPolygonPosition","originalPixelOffset","isPlacedInsidePolygon","absoluteBoundingBoxCenter","pixelCentroid","resultingAbsolutBoundingBox","tryPlaceLabelOutsidePolygon","originalPosition","originalAbsoluteCentroid","pixelStemSource","calculateStemSource","setLeaderLinePoints","calculateStemDestination","absoluteStemSource","stemSource","stemDestination","labelBoundingBox","absoluteLabelRect","getAbsoluteRectangle","inverseTransform","otherLabelsConflict","newOffset","xDelta","yDelta","stemSourcePoint","polygons","maxPolygonWidth","maxPolygonHeight","polygons_1","polygonSize","polygons_2","absolutLabelRect","pixelLabelRect","currentPolygon","createColorAllocatorFactory","ColorAllocatorFactory","LinearGradient2Allocator","LinearGradient3AllocatorWithSplittedScales","LinearGradient3Allocator","scale1","scale2","Restatement_Comma","Restatement_CompoundAnd","RichTextbox_Link_DefaultText","Waterfall_IncreaseLabel","Waterfall_DecreaseLabel","Waterfall_TotalLabel","Slicer_SelectAll","DefaultVisualHostServices","createLocaleOptions","TooltipManager","setLocalizedStrings","createTooltipLocaleOptions","highlightedValueDisplayName","canSelect","onCustomSort","getViewMode","setWarnings","setToolbar","$toolbar","geocoder","services","createGeocoder","geolocation","createGeolocation","dentities","defaultVisualHostServices","createInteractivityService","InteractivityService","isCategoryColumnSelected","renderSelectionInVisual","renderSelectionInLegend","renderSelectionInLabels","hostService","overrideSelectionFromData","takeSelectionStateFromDataPoints","selectableLegendDataPoints","legendHasSelection","isLabels","selectableLabelsDataPoints","labelsHasSelection","selectableDataPoints","slicerDefaultValueHandler","syncSelectionState","clearSelection","useDefaultValue","applyToAllSelectableDataPoints","renderAll","dataPoints_2","checkDatapointAgainstSelectedIds","inverted","syncSelectionStateInverted","createChangeForFilterProperty","selectInverted","removeSelectionIdsWithOnlyMeasures","removeSelectionIdsExceptOnlyMeasures","removeId","wasSelected","toRemove","currentId","dataPoints_3","foundMatchingId","updateSelectableDataPointsBySelectedIds","labelsDataPoint_1","selectableDataPoints_1","dataPoint_1","selectableDataPoints_2","selectableDataPoints_3","selectableLegendDataPoints_1","selectableLabelsDataPoints_1","selectableDataPoints_4","geocode","geocodeBoundary","geocodePoint","tryGeocodeImmediate","tryGeocodeBoundaryImmediate","isCategoryType","CategoryTypeArray","mapLocalesForBing","geocodingCache","getCoordinates","GeocodeQuery","maxGeoData","GeocodeBoundaryQuery","geocodeCore","geocodeQuery","geocodeQueue","dequeue","GeocodePointQuery","decrement","activeRequests","makeRequest","config","jsonp","getUrl","completeRequest","BingAjaxCall","result_1","primitives","Primitives","coordinates","Shape","ringStr","ringArray","resourceSets","getBestResultIndex","pointData","addressData","addressLine","locality","neighborhood","adminDistrict","adminDistrict2","formattedAddress","countryRegionIso2","countryRegion","landmark","dequeueTimeoutId","registerCoordinates","queryString","iso2","getBingEntity","resultEntity","entityType","categoryToBingEntity","ajax","BingEntities","Sovereign","AdminDivision1","AdminDivision2","PopulatedPlace","Postcode","Postcode1","Neighborhood","categoryToBingEntityGeodata","createGeocodingCache","queryAdded","decodeURIComponent","cultures","maxCacheSize","maxCacheSizeOverflow","GeocodingCache","geocodeCache","geocodeCacheCount","hitCount","registerInMemory","registerInStorage","maxCacheCount","cacheSize","cachedA","cachedB","ca","cb","newGeocodeCache","GeolocationService","webGeolocation","watchPosition","successCallback","errorCallback","clearWatch","watchId","getCurrentPosition","visualPluginFactory","unsupportedVisuals","createPlugin","visualPlugins","modifyPluginFn","createDashboardPlugins","plugins","featureSwitches","tooltipsOnDashboard","tooltipsEnabled","lineChartLabelDensityEnabled","Gauge","stackedAreaChart","Map","disableZooming","disablePanning","Matrix","Table","isConditionalFormattingEnabled","createMinervaPlugins","scriptVisualEnabled","scriptVisualAuthoringEnabled","isLabelInteractivityEnabled","conditionalFormattingEnabled","fillMapDataLabelsEnabled","filledMapDataLabelsEnabled","Card","isLegendScrollable","ScriptVisual","canRefresh","VisualPluginService","createVisualPluginService","featureSwitch","createDashboard","DashboardPluginService","createInsights","InsightsPluginService","createMobile","smallViewPortProperties","MobileVisualPluginService","getVisuals","registry","getPlugin","requireSandbox","removeAnyCustomVisuals","include","isScriptVisual","visualCapabilities","shouldDisableVisual","mapDisabled","isScriptVisualQueryable","getInteractivityOptions","interactivityOptions","overflow","PlaygroundVisualPluginService","CartesianSmallViewPortProperties","hideAxesOnSmallViewPort","hideLegendOnSmallViewPort","MinHeightLegendVisible","MinHeightAxesVisible","GaugeSmallViewPortProperties","hideGaugeSideNumbersOnSmallViewPort","smallGaugeMarginsOnSmallViewPort","MinHeightGaugeSideNumbersVisible","GaugeMarginsOnSmallViewPort","FunnelSmallViewPortProperties","hideFunnelCategoryLabelsOnSmallViewPort","minHeightFunnelCategoryLabelsVisible","MinHeightFunnelCategoryLabelsVisible","DonutSmallViewPortProperties","maxHeightToScaleDonutLegend","MaxHeightToScaleDonutLegend","ShowTooltips","trimOrdinalDataOnOverflow","mapThrottleInterval","getMapThrottleInterval","cartesianSmallViewPortProperties","gaugeSmallViewPortProperties","funnelSmallViewPortProperties","disableGeometricCulling","isTouchEnabled","viewChangeThrottleInterval","enableCurrentLocation","mapCurrentLocationEnabled","windowsPhoneThrottleInterval","userAgentLowerCase","mobileOptions","getMobileOverflowString","isChartSupportInteractivity","controls","fire","eventHandlers","eventArgs","UNSELECTABLE_CLASS_NAME","ScrollbarButton","owner","_owner","_direction","_timerHandle","createView","that","_element","addEventListener","onMouseDown","_svg","_polygon","svgns","createElementNS","setAttributeNS","ARROW_COLOR","svgStyle","Scrollbar","arrowClassName","_mouseUpWrapper","cancelBubble","that_1","onMouseUp","addDocumentMouseUpEvent","_scrollSmallIncrement","refresh","removeDocumentMouseUpEvent","arrange","HTMLElementUtils","setElementWidth","setElementHeight","MIN_WIDTH","parentElement","layoutKind","MIN_BAR_SIZE","viewMin","viewSize","smallIncrement","_onscroll","_screenToOffsetScale","onBackgroundMouseDown","_middleBar","onMiddleBarMouseDown","_visible","_touchPanel","scrollBy","scrollTo","scrollUp","scrollDown","scrollPageUp","scrollPageDown","_width","invalidateArrange","_height","_maxButton","_getMouseOffset","layerX","layerY","screenX","screenY","_getOffsetXDelta","_screenPrevMousePos","_getOffsetYDelta","_getOffsetXTouchDelta","_offsetTouchPrevPos","_getOffsetYTouchDelta","initTouch","panel","allowMouseDrag","_allowMouseDrag","onTouchStart","onTouchMove","onTouchEnd","onTouchMouseDown","onTouchMouseMove","onTouchMouseUp","MSPointerEvent","MSPOINTER_TYPE_MOUSE","setCapture","_offsetTouchStartPos","_touchStarted","_getOffsetTouchDelta","_getRunningSize","bubble","releaseCapture","registerElementForMouseWheelScrolling","onMouseWheel","onFireFoxMouseWheel","_minButton","barClassName","_scrollByPage","net","_getOffsetDelta","scroll","_getScreenMousePos","_screenMaxMousePos","_screenMinMousePos","_actualWidth","_actualHeight","_actualButtonWidth","_actualButtonHeight","offsetWidth","offsetHeight","_calculateButtonWidth","_calculateButtonHeight","_getMinButtonAngle","_getMaxButtonAngle","_setMaxButtonPosition","onHoldBackgroundMouseDown","holdDelay","ScrollbarBackgroundMousedownHoldDelay","ScrollbarBackgroundFirstTimeMousedownHoldDelay","_backgroundMouseUpWrapper","onBackgroundMouseUp","getPinchZoomY","documentElement","clientHeight","innerHeight","_getScreenContextualLeft","_getScreenContextualRight","getAccumulatedScale","_middleBarMouseMoveWrapper","onMiddleBarMouseMove","addDocumentMouseMoveEvent","_middleBarMouseUpWrapper","onMiddleBarMouseUp","removeDocumentMouseMoveEvent","wheelDelta","mouseWheel","visible","MouseWheelRange","removeEventListener","DefaultScrollbarWidth","HorizontalScrollbar","actualHeight","setElementLeft","maxButton","actualButtonWidth","runningSize","barSize","barPos","middleBar","offsetLeft","barMinPos","VerticalScrollbar","setElementTop","actualButtonHeight","offsetTop","internal","TablixResizer","handler","_handler","_elementMouseDownWrapper","_elementMouseMoveWrapper","_elementMouseOutWrapper","_documentMouseMoveWrapper","_documentMouseUpWrapper","_startMousePosition","_originalCursor","pageX","pageY","getMouseCoordinateDelta","previous","onElementMouseDown","onElementMouseMove","onElementMouseOut","_elementMouseDoubleClickOutWrapper","onElementMouseDoubleClick","uninitialize","_hotSpot","onDocumentMouseMove","onDocumentMouseUp","cursor","resizeCursor","onStartResize","cell","onReset","onResize","onEndResize","resizeHandleSize","TablixDomResizer","_cell","TablixCellPresenter","fitProportionally","_tableCell","_contentElement","TablixUtils","createDiv","_contentHost","_resizer","registerTableCell","tableCell","registerClickHandler","onclick","unregisterClickHandler","onContainerWidthChanged","onContinerHeightChanged","onColumnSpanChanged","colSpan","onRowSpanChanged","rowSpan","onTextAlignChanged","textAlign","onClear","onHorizontalScroll","onVerticalScroll","onInitializeScrolling","enableHorizontalResize","enable","disableDragResize","_dragResizeDisabledAttributeName","TablixRowPresenter","_tableRow","_fitProportionally","_row","createCellPresenter","registerRow","tableRow","onAppendCell","presenter","_presenter","insertCell","onInsertCellBefore","refCell","cellIndex","onRemoveCell","getCellHeight","getTablixCell","getCellContentHeight","DashboardRowPresenter","gridPresenter","_gridPresenter","containerHeight","contentHeight","CanvasRowPresenter","TablixColumnPresenter","_column","getCellWidth","getCellContentWidth","DashboardColumnPresenter","sizeComputationManager","cellWidth","contentWidth","CanvasColumnPresenter","_columnIndex","persistedWidth","getPersistedCellWidth","getElementWidth","requiredWidth","contentElement","TablixGridPresenter","columnWidthManager","_table","createTable","_footerTable","_columnWidthManager","gridHost","footerHost","control","getScreenToCssRatioX","getScreenToCssRatioY","createRowPresenter","createColumnPresenter","onAppendRow","insertRow","tBodies","onInsertRowBefore","refRow","rowIndex","onRemoveRow","onAddFooterRow","clearChildren","onFillColumnsProportionallyChanged","invokeColumnResizeEndCallback","onColumnWidthChanged","getPersistedColumnWidth","DashboardTablixGridPresenter","_sizeComputationManager","fillColumnsProportionally","gridWidth","gridHeight","CanvasTablixGridPresenter","getElementHeight","TablixDimensionRealizationManager","binder","_binder","_adjustmentFactor","_getOwner","_itemsToRealizeCount","_itemsEstimatedContextualWidth","contextualWidth","onStartRenderingIteration","measureEnabled","_getEstimatedItemsToRealizeCount","_realizedLeavesCount","onEndRenderingIteration","gridContextualWidth","filled","allItemsRealized","_getSizeAdjustment","onEndRenderingSession","onCornerCellRealized","onHeaderRealized","leaf","RowRealizationManager","estimateRowsToRealizeCount","dimension","model","alignToEnd","itemsToRealizeCount","getItemsCount","getIntegerScrollOffset","contextualWidthToFill","getEstimatedRowHeight","adjustmentFactor","getFractionScrollOffset","otherLayoutManager","getDepth","getEstimatedRowHierarchyWidth","RowWidths","updateRowHiearchyEstimatedWidth","_hierarchyNavigator","getIndex","getFirstVisibleItem","levelsArray","levelCount","maxNonLeafWidth","maxLeafWidth","firstVisibleIndex","hierarchyNavigator","getCount","leafCount","getAt","getHeaderLabel","itemWidth","getEstimatedHeaderWidth","isLeaf","getLevel","RowWidth","getChildren","getFirstVisibleChildIndex","getRealizedItemsCount","ColumnRealizationManager","estimateColumnsToRealizeCount","realizationManager","getOtherHierarchyContextualHeight","rowRealizationManager","rowHierarchyWidth","widthToFill","DimensionLayoutManager","_pixelPrecision","startColumnIndex","endColumnIndex","startRowIndex","endRowIndex","itemsEstimatedContextualWidth","visibleSizeRatio","getVisibleSizeRatio","columnMember","getLeafAt","getIntersection","getCellContent","getEstimatedBodyCellWidth","TablixCell","_scrollable","_horizontalOffset","_verticalOffset","_colSpan","_rowSpan","_containerWidth","_containerHeight","CellPosition","unfixRowHeight","unfixSize","getCellSpanningHeight","_textAlign","initializeScrolling","setContainerWidth","setContainerHeight","prepare","scrollable","scrollVertically","offsetInPixels","scrollHorizontally","applyStyle","getExtraBottom","getExtraTop","getExtraLeft","getExtraRight","TablixColumn","_sizeFixed","_aligningWidth","_fixedToAligningWidth","_items","_itemType","_footerCell","_realizedRowHeaders","_realizedColumnHeaders","_realizedCornerCells","_realizedBodyCells","getColumnHeadersOrCorners","columnHeadersOrCornersEqual","newType","headers","columnHeaderOrCornerEquals","getLeafItem","type1","item1","type2","item2","cornerCellItemEquals","headerItemEquals","OnLeafRealized","columnHeadersOrCorners","clearSpanningCellsWidth","clearSize","cells","addCornerCell","addRowHeader","addColumnHeader","addBodyCell","footerCell","getContentContextualWidth","onResizeEnd","fixSize","shouldAlign","switched","getCellIContentContextualWidth","getCellSpanningWidthWithScrolling","tablixGrid","getContextualWidth","getScrollingOffset","realizedColumns","horizontalOffset","calculateSize","_e","_f","_g","setAligningContextualWidth","getAligningContextualWidth","realizedCells","getHeaders","getOtherDimensionHeaders","getCellContextualSpan","getOtherDimensionOwner","TablixRow","_allocatedCells","_heightFixed","_realizedCellsCount","releaseUnusedCells","releaseCells","releaseAllCells","_unbindCell","moveScrollableCellsToEnd","frontIndex","moveScrollableCellsToStart","getOrCreateCornerCell","getOrCreateCell","getOrCreateRowHeader","getOrCreateColumnHeader","getOrCreateBodyCell","getOrCreateFooterRowHeader","footer","getOrCreateFooterBodyCell","getRowHeaderLeafIndex","getAllocatedCellAt","moveCellsBy","createCell","getRealizedCellCount","getRealizedHeadersCount","getRealizedHeaderAt","getOrCreateEmptySpaceCell","layoutManager","getLayoutKind","setContentHeight","sizeFixed","realizedRows","TablixGrid","_footerRow","_realizedRows","_realizedColumns","_emptySpaceHeaderCell","_emptyFooterSpaceCell","_fillColumnsProportionally","ShowEmptySpaceCells","HideEmptySpaceCells","onStartRenderingSession","clearRows","initializeRows","initializeColumns","_rows","getOrCreateRow","currentRow","getOrCreateFootersRow","moveRowsToEnd","moveFromIndex","moveRowsToStart","moveToIndex","moveColumnsToEnd","firstCol","leafStartDepth","_columns","moveColumnsToStart","getOrCreateColumn","currentColumn","hasFooter","rowDimension","SizeComputationManager","_viewport","visibleWidth","visibleHeight","_cellHeight","_cellWidth","updateColumnCount","_columnCount","updateRowHeight","updateScalingFactor","scalingFactor","_scalingFactor","computeColumnWidth","updateViewport","computeColumnHeight","totalColumnCount","minimumColumnWidth","TablixMinimumColumnWidth","maxAllowedColumns","fitToColumnCount","hasImageContent","maxAllowedColumnCount","columnsToFit","_grid","_lastScrollOffset","_isScrolling","_fixedSizeEnabled","_done","_realizationManager","needsToRealize","_alignToEnd","_requiresMeasure","startScrollingSession","endScrollingSession","isScrolling","isResizing","otherDimension","contextualHeight","_getRealizedItems","_isAutoSized","_measureEnabled","_gridOffset","_sendDimensionsToControl","getFooterContextualWidth","_contextualWidthToFill","otherScrollbarContextualWidth","getGridScale","swapElements","scrollOffset","newScrollOffset","getGridContextualWidth","allRealized","scrollForwardToAlignEnd","scrollBackwardToFill","originalScrollbarVisible","scrollbar","updateScrollbar","_scrollOffsetPrecision","getScrollDeltaWithinPage","otherHierarchyDepth","_moveElementsToBottom","_moveElementsToTop","realizedItems","isScrollingWithinPage","getViewSize","canScroll","sizeInItems","sizeInPixels","scrollableArea","getMeaurementError","visibleRatio","itemContextualWidth","getItemContextualWidthWithScrolling","isScrollableHeader","currentItem","currentItems","isLastItem","reachedEnd","averageColumnwidth","getValidScrollOffset","getItemContextualWidth","getSizeWithScrolling","getGridContextualWidthFromItems","withinThreshold","widthToScroll","getActualContextualWidth","calculateSizes","fixedSizeEnabled","calculateContextualWidths","calculateSpans","_calculateSize","updateNonScrollableItemsSpans","updateScrollableItemsSpans","otherDimensionItems","otherDimensionItemsCount","otherDimensionItem","updateSpans","otherRealizedItems","otherRealizedItemsCount","otherRealizedItem","fixSizes","cellCount","totalSizeInSpan","updateLastChildSize","spanningCell","totalSpanSize","ResizeState","itemType","startColumnWidth","resizingDelta","animationFrame","getNewSize","ColumnLayoutManager","fillProportionally","_resizeState","columnDimension","getFirstVisibleColumn","autoSizeWidth","applyScrolling","columnOffset","firstVisibleColumnWidth","firstVisibleColumn","scrollCells","scrollBodyCells","currentX","currentY","deltaX","deltaY","minColumnWidth","performResizing","endResizing","updateItemToResizeState","newSize","otherContextualHeight","updateColumnDimensions","headerIndex","DashboardColumnLayoutManager","ignoreColumn","computedSize","getContentWidth","hasRowGroups","CanvasColumnLayoutManager","getEstimatedTextWidth","columnWidths","items_1","columnWidthsToPersist","RowLayoutManager","getFirstVisibleRow","autoSizeHeight","rowOffset","firstVisibleRowHeight","firstVisibleRow","footerRow","updateRowDimensions","DashboardRowLayoutManager","getHeaderWidth","CanvasRowLayoutManager","TablixLayoutManager","columnLayoutManager","rowLayoutManager","_allowHeaderResize","_columnLayoutManager","_rowLayoutManager","_columnWidthsToPersist","_container","_gridHost","contentHost","_footersHost","getTablixClassName","hierarchyNav","indexInSiblings","isFirst","isLast","areAllParentsFirst","areAllParentsLast","enableCellHorizontalResize","alignRowHeaderCells","rowLevel","columnLevel","columnDepth","cellItem","rowItem","rowItems","getVisibleWidth","getVisibleHeight","adjustContentSize","hasImage","getFirstVisibleChildLeaf","showEmptySpaceHeader","scrollingDimension","emptySpaceHeaderCell","unbindEmptySpaceHeaderCell","emptySpaceFooterCell","unbindEmptySpaceFooterCell","_scrollingDimension","measureSampleText","emptySpace","bindEmptySpaceHeaderCell","bindEmptySpaceFooterCell","columnLeaf","isColumnHierarchyLeaf","rowLeaf","isRowHierarchyLeaf","onRowHeaderRealized","tablixCell","onRowHeaderFooterRealized","onColumnHeaderRealized","onBodyCellRealized","onBodyCellFooterRealized","setAllowHeaderResize","DashboardTablixLayoutManager","columnRealizationManager","dashboardColumnLayoutManager","dashboardRowLayoutManager","createLayoutManager","_characterHeight","actualTextSize","TablixDefaultTextSize","rowDimensionDepth","columnInstances","CanvasTablixLayoutManager","canvasColumnLayoutManager","canvasRowLayoutManager","textDiv","cssFloat","lineHeight","textNode","createTextNode","characterWidth","characterHeight","hasChildNodes","firstChild","isAutoSize","TablixObjects","DataViewRoleWildCard","getMetadadataObjects","tablixType","TablixType","getTableColumnMetadata","repetition","ObjectValues","formattingProperties","PropValuesBackColor","totalsShown","shouldShowTableTotalsOption","shouldShowTableTotals","shouldShowColumnSubtotalsOption","shouldShowColumnSubtotals","shouldShowRowSubtotalsOption","shouldShowRowSubtotals","ObjectGeneral","enumerateGeneralOptions","ObjectGrid","enumerateGridOptions","ObjectColumnHeaders","enumerateColumnHeadersOptions","ObjectRowHeaders","enumerateRowHeadersOptions","enumerateValuesOptions","ObjectTotal","enumerateTotalOptions","ObjectSubTotals","enumerateSubTotalsOptions","visualObjectinstance","PropGeneralAutoSizeColumns","PropGeneralTextSize","PropGeneralTableTotals","PropGeneralMatrixRowSubtotals","PropGeneralMatrixColumnSubtotals","verticalGridEnabled","PropGridVertical","PropGridVerticalColor","PropGridVerticalWeight","horizontalGridEnabled","PropGridHorizontalTable","PropGridHorizontalMatrix","PropGridHorizontalColor","PropGridHorizontalWeight","PropGridRowPadding","PropGridOutlineColor","PropGridOutlineWeight","PropGridImageHeight","PropColumnsFontColor","PropColumnsBackColor","PropColumnsOutline","PropRowsFontColor","PropRowsBackColor","PropRowsOutline","PropValuesFontColorPrimary","PropValuesBackColorPrimary","PropValuesFontColorSecondary","PropValuesBackColorSecondary","PropValuesOutline","PropValuesUrlIconProp","PropTotalFontColor","PropTotalBackColor","PropTotalOutline","PropSubTotalsFontColor","PropSubTotalsBackColor","getTableObjects","getMatrixObjects","subtotals","PropSubTotalsOutline","generateTablixDefaultObjects","getTextSizeInPx","isDiscourageAggregationAcrossGroups","lastLevel","TablixProperty","getterFuntion","getPropertyID","PropColumnFormatString","resetCellCssClass","CssClassTablixDiv","CssClassContentElement","CssClassContentHost","addCellCssClass","clearCellStyle","cssText","clearCellTextAndTooltip","setCellTextAndTooltip","isValidSortClick","colHeader","appendATagToBodyCell","atag","childElementCount","CssClassValueURLIcon","CssClassValueURLIconContainer","innerText","appendImgTagToBodyCell","imgContainer","imgTag","createKpiDom","display","vertical-align","isValidStatusGraphic","getCustomSortEventArgs","sortDirection","sortDescriptors","reverseSort","createColumnHeaderWithSortIcon","colHeaderContainer","itemSort","createSortIcon","colHeaderTitle","isSorted","imgSort","SortIconContainerClassName","checkSortIconExists","removeSortIcons","CssClassTablixHeader","CssClassTablixColumnHeaderLeaf","CssClassTablixValueNumeric","CssClassTablixValueTotal","CssClassMatrixRowHeaderLeaf","CssClassMatrixRowHeaderSubTotal","CssClassTableFooter","CssClassTableBodyCell","CssClassTableBodyCellBottom","StringNonBreakingSpace","UnitOfMeasurement","CellPaddingLeft","CellPaddingRight","CellPaddingLeftMatrixTotal","FontFamilyCell","FontFamilyHeader","FontFamilyTotal","FontColorCells","FontColorHeaders","EdgeSettings","applyParams","shown","getCSS","CellStyle","borders","paddings","backgroundColor","borderShadow","border","boxShadow","paddingTop","paddingRight","paddingBottom","paddingLeft","extra","DimensionPosition","isMatch","TablixVisualCell","TablixControl","parentDomElement","scrollBarElementWidth","isInteractive","enableTouchSupport","mainDiv","TablixTableAreaClassName","footerDiv","TablixFooterClassName","InitializeTouchSupport","gridDimensions","containerElement","TablixContainerClassName","touchInterpreter","footerTouchInterpreter","controlLayoutManager","hierarchyTablixNavigator","columnDim","TablixColumnDimension","rowDim","TablixRowDimension","_otherDimension","InitializeScrollbars","scrollbarWidth","updateHorizontalPosition","updateVerticalPosition","updateFooterVisibility","lastRenderingArgs","touchManager","TouchUtils","TouchManager","TouchEventInterpreter","columnTouchDelegate","ColumnTouchDelegate","Rectangle","rowTouchDelegate","RowTouchDelegate","bodyTouchDelegate","BodyTouchDelegate","footerTouchDelegate","setHandler","onTouchEvent","addTouchRegion","_initializeScrollbar","rowDimensionScrollbarStyle","columnDimensionScrollbarStyle","getBinder","_autoSizeWidth","minWidth","_autoSizeHeight","minHeight","maximumWidth","maximumHeight","minimumWidth","minimumHeight","textFontSize","DefaultFontSize","textFontFamily","textFontColor","updateModels","resetScrollOffsets","rowModel","columnModel","modelDepth","getRowHierarchyDepth","getColumnHierarchyDepth","columnHierarchyWidth","columnHierarchyHeight","rowHierarchyHeight","rowHierarchyContentHeight","footerHeight","updateTouchDimensions","resize","setScrollDensity","determineDimensionToScroll","_onScrollAsync","performPendingScroll","hasVerticalScrollbar","isDashboardTile","showFooter","mainBottom","footerBottom","verticalScrollbarBottom","hasHorizontalScrollbar","removeProperty","alreadyRendered","rowScrollOffset","columnScrollOffset","makeScrollOffsetValid","renderIterationCount","priorFooterHeight","priorRowHierarchyHeight","priorRowHierarchyContentHeight","MaxRenderIterationCount","hScrollbarVisibility","vScrollbarVisibility","_onStartRenderingIteration","renderCorner","_render","_onEndRenderingIteration","updateContainerDimensions","vScrollBarWidth","hScrollBarHeight","cornerCellMatch","previousItem","rowDepth","getCorner","bindCornerCell","unbindBodyCell","unbindColumnHeader","unbindRowHeader","unbindCornerCell","colShift","rowShift","TablixDimension","tablixControl","_scrollStep","_tablixLayoutManager","updateScrollPosition","_scrollbar","_scrollItems","getFirstVisibleChild","startItem","getParent","touchDiv","_createScrollbar","onScroll","setProperty","getLeafCount","_layoutManager","firstVisibleScrollIndex","firstVisible","_firstVisibleScrollIndex","_footer","setFooter","footerHeader","firstVisibleRowItem","addFooterRowHeader","addFooterBodyCells","addNodes","addNode","bindRowHeader","previousCount","rowHeaderCell","rowHeaderMatch","addBodyCells","firstVisibleColumnIndex","otherModel","bindBodyCell","bodyCelMatch","columnItem","bodyCellItemEquals","firstVisibleColumnItem","columnHeaderMatch","childrenLevelDifference","getChildrenLevelDifference","bindColumnHeader","dim","averageSize","handlers","xRatio","getPixelToItem","down","TouchEvent","touchEvent","tablixObj","handlerCall","yRatio","averageSizeX","DefaultAverageSizeX","averageSizeY","DefaultAverageSizeY","MouseButton","isMouseDown","_x","_y","isMouseButtonDown","_dx","_dy","touchList","swipeDirection","matchingDirectionCount","lockThreshold","scrollThreshold","lastTouchEvent","lastPoint","upAllTouches","eventPoint","_getActive","_findRegions","MinDistanceForSwipe","MaxTimeForSwipe","manager","touchPanel","documentMouseMoveWrapper","documentMouseUpWrapper","sliding","touchReferencePoint","getXYByClient","mouchEvent","touchStartTime","touchStartPageY","touchLastPageY","touchLastPageX","clearTouchEvents","swipeInfo","getSwipeInfo","didUserSwipe","startSlideAffect","getSelection","removeAllRanges","validMouseDragEvent","which","NoClick","touchEndTime","touchTime","touchDist","touchDirection","endTime","slide","didUserChangeDirection","clearSlide","updatedDist","updatedDirection","slideDist","PropAutoSizeWidth","getMetadataObjects","TablixColumnWidthManager","hostPersistCallBack","matrixLeafNodes","columnWidthObjects","updateDataView","previousDataView","currentDataView","previousAutoColumnSizePropertyValue","currentAutoColumnSizePropertyValue","updateColumnWidthObjects","updateTablixColumnWidths","updateMatrixColumnWidthObjects","updateTableColumnWidthObjects","columnMetaData","rowGroup","shouldClearAllColumnWidths","autoSizeAllColumns","deserializeColumnWidths","columnMetaData_1","columnWidthPropValue","columnWidthProp","shouldPersistAllColumnWidths","getColumnWidthObjects","getFixedColumnWidthObjects","colIndex","callHostToPersist","generateInstances","generateVisualObjectInstancesToPersist","visualObjectInstancesToPersist","getAutoSizeColumnWidthObject","columnWidthObject","onColumnAutosized","persistAllColumnWidths","widthsToPersist","widths","added","AnimatedText","mainText","visualConfiguration","maxFontSize","getMetaDataColumn","getAdjustedFontHeight","textToMeasure","seedFontHeight","fontHeight","getAdjustedFontHeightCore","iteration","candidateLength","doValueTransition","startValue","endValue","forceUpdate","endValueArr","getSeedFontHeight","translateX","getTranslateX","getTranslateY","startText","endText","textElementUpdate","getTextAnchor","interpolatedValue_1","tween","setTextColor","boundingWidth","boundingHeight","estimatedSize","align","AnimatedNumber","updateViewportDependantProperties","updateInternal","setFormatter","BasicShapeVisual","DefaultShape","DefaultStrokeColor","DefaultLineTransValue","trans","DefaultWeightValue","DefaultRoundEdgeValue","DefaultFillShowValue","DefaultFillColor","DefaultFillTransValue","DefaultAngle","scaleTo360Deg","dataViewObject","getDataFromDataView","getValueFromColor","objectInstances","getLayerDataViews","hasMultipleYAxes","layers","shouldShowYAxisLabel","yAxisWillMerge","tryMergeYDomains","visualOptions","noMerge","merged","minOfMax","maxOfMin","y1props","calculateAxesProperties","y2props","firstYDomain","secondYDomain","forceMerge","COMBOCHART_DOMAIN_OVERLAP_TRESHOLD_PERCENTAGE","DEFAULT_AXIS_SCALE_TYPE","INTERACTIVITY_RIGHT_MARGIN","DEFAULT_AXIS_COLOR","xRefLine","y1RefLine","CartesianAxes","ScrollableAxes","ScrollbarWidth","svgAxes","SvgCartesianAxes","svgBrush","SvgBrush","scrollableAxes","getAxisVisibility","chartAreaSvg","ClassName","maxMarginFactor","setMaxMarginFactor","axisLinesVisibility","setAxisLinesVisibility","sharedColorPalette","SharedColorPalette","colorPalette","isMobileChart","isPlayAxis","categoryRoleIsPlay","getIsScalar","axisTypeValue","getAdditionalTelemetry","detectScalarMapping","dataViewCategories","categoryItems","populateObjectProperties","legendObjectProperties","xAxisReferenceLines","y1AxisReferenceLines","dataChanged","extractMetadataObjects","createAndInitLayers","clearPreferredScale","layerDataViews","trendLineDataViews","layerCount","layerDataView","supportsTrendLines","trendLineDataView","rotateScale","hasSetData","addWarnings","layersLength","shouldShowLegendCard","layerLegendData","hasCategoryAxis","getCategoryAxisValues","getValueAxisValues","refLinedefaultColor","ComboChart","enumerateDataPoints","layerIndex","supportsTrendLine","layersWithValuesCtr","hasLegend","getAxisScaleOptions","scaleOptions","supportedType","getSupportedCategoryAxisType","categoryAxisHasUnitType","isYAxisCategorical","secScaleOption","valueAxisHasUnitType","hasY2Axis","secInstance","secondaryValueAxisHasUnitType","CartesianLayerFactory","createLayers","cartesianOptions","getScrollableRegion","labelsContext","getLabelsRegion","cartesianHost","getSharedColors","triggerRender","renderLegend","this_1","calculateLegend","legendProperties","hideLegends","playAxisControlLayout","hideAxisLabels","plotAreaViewport","AxisPadding","PlayAxisBottomMargin","interactivityRightMargin","calculateInteractivityRightMargin","getMinimumDomainExtents","ensureYDomain","axesLayout","negotiateAxes","AxisTextProperties","plotAreaHasChanged","renderedPlotArea","renderPlotArea","isXScrollBarVisible","isYScrollBarVisible","ToolTipInstance","wheelEvent","scrollDelta","xs","ys","xAxisReferenceLineProperties","y1AxisReferenceLineProperties","getPlotAreaRect","legendPosition_1","plotAreaRect","easing","renderAxes","renderReferenceLines","renderLayers","renderTrendLines","scrollableRegion","refLineDefaultColor","showY1ReferenceLines","y1RefLineOptions","showXReferenceLines","xRefLineOptions","getReferenceLineLabels","referenceLineLabels","y1RefLineLabelOptions","xRefLineLabelOptions","renderDataLabels","labelDataPointGroups","labelsAreNumeric","isCombo","labelBackgroundRegion","getLabelBackground","labelRegion","labelLayoutOptions","svgLabels","PlayChart","FrameAnimationDuration","filteredLabels","labelsBehaviorOptions","layerBehaviorOptions","resultLabelDataPointsGroups","resultLabelDataPointsGroups_1","resultLabelDataPointsGroup","resultsLabelDataPoints","getPreferredPlotArea","noOuterPadding","preferredCategorySpan","getPreferredCategorySpan","OuterPaddingRatio","getLayout","getCategoryThickness","totalOuterPadding","calculatedBarCount","visibleCategoryCount","willScroll","oneOuterPadding","seriesList","numCategories","plotLength","getMinInterval","domainSpan","MinScalarRectThickness","maxRectThickness","series0data","FontSizeString","brushWidth","brush","Brush","brushGraphicsContext","getExtent","setExtent","setScale","setOrientation","renderBrush","extentLength","brushX","brushY","scrollCallback","brushStartExtent","resizeExtent","updateExtentPosition","brushContext","drag-resize-disabled","scrollBarLength","newStartPos","halfScrollBarLen","halfDragLength","filterDataToViewport","mainAxisScale","scrollScale","setFilteredData","axisPropsToUpdate","tickFormat_1","renderDelegate","scrollbarLength","numVisibleCategories","newAxisLength","brushMinExtent","renderOnScroll","onBrushed","currentStartIndex","newStartIndex","halfCategoryThickness","clampBrushExtent","minExtent","axisGraphicsContextScrollable","getXAxis","xAxisGraphicsContext","getY1Axis","y1AxisGraphicsContext","getY2Axis","y2AxisGraphicsContext","AxisGraphicsContext","svgScrollable","showLinesOnX","showLinesOnY","scrollX","scrollY","updateAnimatedTickTooltips","axisSelection","updateTickTooltips","xLabelColor","yLabelColor","y2LabelColor","marginLimits","tickLabelMargins","leftRightMarginLimit","shouldRenderAxis","TickPaddingRotatedX","xAxisGraphicsElement","darkenZeroLine","setAxisLabelColor","xAxisTextNodes","showY1OnRight","shouldShowY1OnRight","y1TickPadding","getYAxisOrientation","y1AxisGraphicsElement","y2TickPadding","Y2TickSize","y2AxisGraphicsElement","axisLabels","chartHasAxisLabels","hideXAxisTitle","shouldRenderAxisTitle","hideYAxisTitle","hideY2AxisTitle","renderAxisOptions","AxisLabelFontSize","renderAxesLabels","translateAxes","heightOffset","y2AxisLabel","zeroTick","MaxMarginFactor","yAxisOrientation","factor","axisPosition","hasDisallowedZeroInDomain","ZeroValueWarning","calculateAxes","existingAxisProperties","hideAxisTitles","mergeResult","forcedXDomain","showCategoryAxisLabel","showValueAxisLabel","categoryAxisScaleType","valueAxisScaleType","categoryAxisDisplayUnits","valueAxisDisplayUnits","categoryAxisPrecision","valueAxisPrecision","skipMerge","forcedYDomain","currentlayer","axes_1","overrideXScale","addUnitTypeToAxisLabels","MinimumMargin","getVisualCategoryAxisIsScalar","updateAxisMargins","previousTickCountY1","previousTickCountY2","previousWillFitX","previousWillBreakX","preferredPlotArea","rotateXTickLabels90","willAllCategoriesFitInPlotArea","allDone","maxY1Padding","maxY2Padding","maxXAxisBottom","XAxisLabelPadding","YAxisLabelPadding","axesHaveTicks","secondary","getAxisProperty","getUnitType","unitType_1","createLineChartLayer","createScatterChartLayer","createWaterfallChartLayer","createDataDotChartLayer","createColumnChartLayer","getComboColumnType","inComboChart","defaultOptions","isTrendLayer","DataDotChart","comboChartTypes","palette","scaleKey","setPreferredScale","preferredScale","getSentimentColors","getBasePickerColors","clearAndRotateScale","flagBar","flagColumn","flagClustered","flagStacked","flagStacked100","RoleNames","categoryAxisType","customizeQuery","getSortableRoles","updateVisualMetadata","ColumnChartClassName","unclippedGraphicsContext","cartesianVisualHost","getCategoryLayout","numCategoryValues","isBar","categoryDataType","scalarCategoryAxis","is100PercentStacked","dataViewCat","ColumnChartConverterHelper","categoryInfo","isStacked","defaultLegendLabelColor","legendAndSeriesInfo","getLegend","seriesSources","createDataPoints","seriesObjects","columnSeries","columnSeries_1","isMultiMeasure","canSupportOverflow","seriesObjectsList","defaultLabelSettings","isCategoryAlsoSeries","categoryObjectsList","dvCategories","baseValuesPos","baseValuesNeg","rawValues","rawHighlightValues","highlightsOverflow","seriesHighlightValues","highlightValue","getHighlightBySeriesAndCategory","dataPointObjects","seriesDataPoints","seriesLabelSettings","labelsSeriesGroup","labelObjects","valueColumnMetadata","valueMeasureIndex","pctFormatString","originalValue","multipliers","unadjustedValue","seriesGroup","getMeasureNameByIndex","rawCategoryValue","getDataPointColor","gradientColumnForTooltip","tooltipInfo","valueString","formattedOriginalValue","originalPct","dataPointLabelSettings","lastValue","getStackedLabelColor","valueOriginal","originalValueAbsolute","valueHighlight","unadjustedValueHighlight","highlightedTooltip","absoluteValueHighlight","highlightPosition","highlightIdentity","highlightedValueAndPct","highlightedValueFormat","highlightedPct","ToolTipComponent","localizationOptions","highlightDataPoint","drawThinner","colorOverride","nextValues","sliceSeries","newSeries","iNewSeries","getInteractiveColumnChartDomElement","is100PctStacked","isStacked100","setChartStrategy","ClusteredBarChartStrategy","ClusteredColumnChartStrategy","StackedBarChartStrategy","StackedColumnChartStrategy","createInteractiveLegendDataPoints","getLabelSettingsOptions","labelSettings_1","singleSeriesData","singleSeriesDataPoints","origCatgSize","chartLayout","catgSize","chartContext","ApplyInteractivity","setupVisualProps","isBarChart","setXScale","setYScale","dragDataPoint","dragMove","mousePoint","selectColumn","ColumnChartSvg","indexOfColumnSelected","force","lastInteractiveSelectedColumnIndex","allSeries","valueMetadata","formattedLabel","dataPointColor","xProperties","columnChartDrawInfo","drawColumns","addTooltip","tooltipEvent","allDataPoints","datapoints","shapesSelection","showLabel","getLabelFill","isInside","isClustered","clusteredValidLabelPositions","stackedValidLabelPositions","reader","allValues","valueGroupsIndex","valueGroupsLen","valueGroupObjects","valuesLen","dvValues","categoryLayout","props","xProps","seriesLength","seriesOffsetScale","valueDomain","yProps","useAnimation","clusteredColumnLayout","dataLabelSettings","createLabelDataPoints","classes","lastSelectedColumnIndex","moveHandle","getColumnsCenters","xScaleOffset_1","columnCenters","hoverLine","columnSelectionLineHandle","parentNode","handle","halfColumnWidth","quarterColumnWidth","xScaleOffset","series_2","currentSeries","barChartProps","forcedYMin","forcedYMax","barsCenters","clusteredBarLayout","getBarsCenters","yScaleOffset_1","barCenters","yScaleOffset","series_3","xReferenceLineValue","y1ReferenceLineValue","valueDomainArr","stackedColumnLayout","xScaleOffset_2","series_4","highlightItem","stackedBarLayout","yScaleOffset_2","series_5","HelloIVisual","DefaultText","toolTipInfo","svgText","selectiionManager","selectionManager","columnChartLayerIndex","columnMapping","columnValuesMapping","seriesSelect","lineMapping","sentimentcolors","basePickerColors","ThemeManager","getDefaultTheme","defaultSentimentColors","scales","getAllColors","D3ColorScale","createFromColors","rotatedColors","getDomain","defaultTheme","baseColors","defaultBaseColors","colorSectorCount","mainGraphicsG","clippedData","seriesArray","xMetaDataColumn","yMetaDataColumn","hasDataPoint","createClippedDataIfOverflowed","yDomain","requiredLength","clipped","dotWidth","dotRadius","dotColor","DotColorKey","DotLabelClassSelector","DotLabelClassName","DotLabelTextAnchor","DotLabelVerticalOffset","overflowed","hasClass","width_1","firstDataPoint","lineDataPoint","Line","blankCategoryValue","labelPositionObjects","isValidValueColumn","getFirstValidValueColumn","valueMetaData","firstValue","firstHighlight","previousValue","previousHighlight","hasNegativeValues","allValuesAreNegative","percentBarLabelSettings","percentLabelsObj","firstValueColumn","measureName","formattedCategoryValue","gradientColumnMetadata","addFunnelPercentsToTooltip","originalHighlightValue","slices_1","isValueNegative","isHighlightValueNegative","labelSettingsOptions","percentLabelSettingOptions","isDataLabels","VisualClassName","funnelGraphicsContext","updateViewportProperties","AllNegativeValuesWarning","NegativeValuesNotSupportedWarning","getMaxLabelLength","LabelFunnelPadding","slicesWithoutHighlights","setUpAxis","funnelContext","InnerTextMinimumPadding","drawDefaultAxis","drawPercentBars","drawInteractorShapes","getUsableVerticalSpace","verticalSpace","MinBarThickness","percentBarTextHeight","getPercentBarTextHeight","isSparklines","verticalRange","showCategoryLabels","longestLabelLength","maxLabelLength","labelLength","YAxisPadding","horizontalRange","BarToSpaceRatio","maxScore","maxHighlight","minScore","MaxBarHeight","percentBarTextProperties","columnHeight","percentBarTickHeight","overFlowHighlightColumnWidth","OverflowingHighlightWidthRatio","overFlowHighlightOffset","lastCategoryIndex","emptyHorizontalSpace","getMinimumShapeSize","MinimumInteractorSize","percentBarFontSize","baselineDelta","percentBarYOffset","interactorLayout","indices","asOriginal","interactorsData","drawPercentBarComponents","percentLabelSettings","localizedString","percentOfFirst","percentOfPrevious","DefaultBarOpacity","DimmedBarOpacity","InnerTextClassName","lastAngle","enumerateAxis","getDataLabelSettingsOptions","calloutValueLabelsSettings","enumerateDataPoint","getGaugeObjectsProperties","dataPointSettings","DefaultDataPointSettings","targetColor","hasAxisObject","targetSettings","DefaultTargetSettings","setMargins","MainGaugeGroupClassName","initKpiBands","backgroundArc","foregroundArc","backgroundArcPath","foregroundArcPath","animatedNumberGrapicsContext","gaugeDrawingOptions","gaugeVisualProperties","getGaugeVisualProperties","animatedNumberProperties","getAnimatedNumberProperties","innerRadiusFactor","showTargetLabel","MinWidthForTargetLabel","showMinMaxLabelsOnBottom","showSideNumbersLabelText","drawViewPort","updateCalloutValue","getFormatter","getValidSettings","maxVal","minVal","DEFAULT_MIN","targetVal","getGaugeData","tooltipItems","gaugeObjectsSettings","overrideGaugeSettings","gaugeData","adjustedTotal","convertDataLabelSettings","convertDataPointSettings","kpiBands","kpiArcs","kpiArcPaths","arcPath","updateKpiBands","tString","kpiAngleAttr","KpiBandDistanceFromMainArc","removeTargetElements","targetLine","targetText","targetConnector","getTargetRatio","updateTargetLine","outY","outX","inY","inX","boxAngle","innerRadiusOfArc","innerRadiusForTextBoundingBox","innerRCos","innerRSin","innerY","innerX","animatedNumberWidth","InnerRadiusFactor","drawOptions","separation","separationRadians","backgroudArc","appendTargetTextAlongArc","createTicks","numberOfLabels","arr","arcTween","appendTextAlongArc","updateVisualConfigurations","updateVisualStyles","configOptions","arcColors","divisor","onRight","onBottom","truncateTextIfNeeded","positionX","availableSpace","realValue2","valueFormatterOptions","tRatio","maxRatio","asin","MinDistanceFromBottom","finalRatio","targetX","targetY","TargetText","TargetConnector","attrTween","visualWhitespace","tickValue","margins","DefaultTopBottomMargin","DefaultLeftRightMargin","ReducedLeftRightMargin","foreground","ImageVisual","scalingType","enumerateImageScaling","imageBackgroundElement","appendTo","GetStatus","actual","directionType","KPIStatusWithHistory","NOGOAL","maxGoal","minGoal","IN_BETWEEN","DROP","INCREASE","getDistanceFromGoalInPercentageString","GetTextColorClassByStatus","kpiTextGreyClass","kpiGreenClass","kpiYellowClass","kpiRedClass","GetGraphColorClassByStatus","kpiGraphGreyClass","rootElement","mainGroupElement","areaFill","textContainer","indicatorTextContainer","absoluteGoalDistanceText","kpiActualText","initIcons","kpiViewModel","getProp_KPIDirection","successMarkIcon","betweenIcon","exclamationMarkIcon","setShowDataMissingWarning","indicatorExists","trendExists","targetExists","actualText","calculatedHeight","indicatorTextSizeInPx","allColorClasses","shownGoalString","formattedGoalString","shownDistanceFromGoalString","showDistanceFromGoal","showTrendLine","historyExists","VisualKPIDataMissingWarning","getDefaultFormatSettings","DefaultStyle","getProp_Show_KPIGoal","showKPIGoal","getProp_Show_KPITrendLine","showKPITrendLine","getProp_Show_KPIDistance","showKPIDistance","directionTypeStringProp","getProp_Indicator_DisplayUnits","initDefaultLabelSettings","indicatorDisplayUnitsProp","getProp_Indicator_Precision","indicatorPrecisionProp","defaultCardFormatSetting","getFormattedValue","theValue","isDefaultDisplayUnit","getFormattedGoalString","goalsString","catDv","indicatorMetadataColumn","goalMetadataColumn","actualValue","historyActualData","historyGoalData","indicatorColumns","getColumnsByRole","goalColumns","goals_1","goalCnt","maxActualData","minActualData","areaMaxHight","trendAreaFilePercentage","selectorId","roleString","retval","statusBandingType","Below","Above","actualTextConsts","VERTICAL_OFFSET_FROM_HALF_HEIGHT","FONT_WIDTH_FACTOR","RIGHT_MARGIN","estimatedIconHeightInPx","deferDragMoveOperation","lastDragMoveXPosition","lineType","lineClassAndSelector","LineClassSelector","shouldCalculateStacked","defaultSeriesColor","categoryData","seriesLen","stackedValues","times","groupedIdentity","categorical_1","categoryKey","stackedValue","lineIndex","valuesMetadataArray","getInteractiveLineChartDomElement","createStackedValueDomain","cartesainSVG","isInteractiveChart","scaleDetector","graphicsContextParent","mainGraphicsSVG","overlayRect","RectOverlayName","MainGraphicsContextClassName","hoverLineContext","LineElementName","selectionCircles","rootSvg_1","shouldAdjustMouseCoordsOnPathsForStroke","convertedData","hasZeroValueInYDomain","hasZeroValueInXDomain","ScalarOuterPadding","getAvailableWidth","labelSettings_2","previousCategoryCount","renderOld","renderNew","y0Position","yPosition","isStackedArea","getXOfFirstCategory","renderAreas","xPosition","getXValue","defined","CategoryAreaSelector","PathElementName","interactivityStrokeWidth","dotGroups","CategorySelector","CategoryValuePoint","shouldDrawCircle","CircleElementName","lineSeries","CircleRadius","explicitDots","CategoryPointSelector","pointColor","PointRadius","seriesTooltipApplier","pointX","elementCoordinates","getTooltipInfoForCombo","getCategoryIndexFromTooltipEvent","selectColumnForTooltip","getSeriesTooltipInfo","clearHoverLine","HoverLineCircleDot","dataPointsToBind","firstCategoryOffset","getAvailableHeight","catAreaSelect","catAreaEnter","catAreaUpdate","catSelect","catEnter","dragHandle","handleTop","linesCount","addedCircle","CircleClassName","catUpdate","lineSelection","updateSelection","transitions","circleIndex","selectionSize_1","endedTransitionCount_1","tooltipinfo","maxNumberOfItems","pointData_1","adjustPathXCoordinate","firstPathPoint","nextDataPoint","newLength","dataLength","isLastPoint","isFirstPoint","getChartX","createTooltipDataPoints","setHoverLineForTooltip","setDotsForTooltip","chartX","dotYPosition","tooltipDots","setHoverLine","circleToChange","getPosition","pathLength","getTotalLength","beginning","getPointAtLength","categoryDataPoint","lineData","seriesYCol","targetCategoryValue","seriesLabelDataPoints","seriesDataPointsCandidates","lineshift","isParentRect","bottomPos","areaWidth","validStackedLabelPositions","validLabelPositions","lastDataPoint","lastLabelDataPoint","pathXAdjustment","DefaultFillOpacity","DefaultBackgroundColor","LeaderLineColor","MapBubbleDataPointRenderer","mapDiv","addClearCatcher","clearSvg","getRootElement","bubbleGraphicsContext","sliceGraphicsContext","labelBackgroundGraphicsContext","sliceLayout","pie","clearMaxDataPointRadius","mapData","clearDataPoints","geocodingCategory","hasSize","getDataPointCount","getDataPointPadding","maxDataPointRadius","setMaxDataPointRadius","dataPointRadius","getDefaultMap","widthOverTwo","heightOverTwo","radiusScale","dataValuesSource","bubbleData","sliceData","sizeIndex","location_2","subDataPoints","subDataPoint","removeTransform3d","mapRendererData","sliceContainers","updateInternalDataLabels","allData","dataPoints_4","MapShapeDataPointRenderer","getFilledMapParams","dataCount","maxPolygons","buildPaths","paths","location_3","polygonInfo","clearMaxShapeDimension","shapeData","idKey","mainShapeIndex","getIndexOfLargestShape","pathIndex","pathCount","setMaxShapeDimension","absolutePointArray","pIdx","displayLabel","catagoryLabeltext","largestShapeIndex","largestShapeArea","currentShapeArea","drawLabelStems","maxShapeDimension","dataShapes","dataShapes_1","dataShape","secondRowTextWidth","hasSecondRow","secondRowProperties","firstRowProperties","validLabelPolygonPositions","showText","DefaultLocationZoomLevel","dataPointRenderer","isFilledMap","mapControlFactory","getDefaultMapControlFactory","boundsHaveBeenUpdated","pendingGeocodingRender","legendHeight","geoTaggingAnalyzerService","resetBounds","removeHillShading","loadModule","createCurrentLocation","pushpin","myLocBtn","isCurrentLocation","coords","updateMapView","addDataPoint","updateBounds","scheduleRedraw","enqueueGeoCode","geocodingQuery","completeGeoCode","geocodingContext_1","geocodingContext","enqueueGeoCodeAndGeoShape","params","completeGeoCodeAndGeoShape","geocodingContext_2","enqueueGeoShape","completeGeoShape","geocodingContext_3","getOptimumLevelOfDetail","threshold","minXmaxY","minLatitude","minLongitude","maxXminY","maxLatitude","maxLongitude","getViewCenter","isLegendHidden","getLegendFontSize","isShowLegendTitle","hideLegend","clonedLegendData","targetOrientation","calculateGroupSizes","groupSizeTotals","sizeMeasureIndex","currentValueScale","groupTotal","calculateRadius","rangeDiff","getGeocodingCategory","categoryString","categoryName","geotaggedResult","typeFromRoleName","hasSizeField","defaultIndexIfNoRole","shouldEnumerateDataPoints","usesSizeForGradient","hasSeries","gradientRole","shouldEnumerateCategoryLabels","getMapViewPort","dataPointsToEnumerate","enumerateLegend","labelSettingOptions","bubbleDataPoint","datalabelsObj","categoryLabelsObj","createLegendData","FilledMapWithoutValidGeotagCategoryWarning","seriesColumnIdentifier","sizeQueryName","categoryTotals","categoryTotalRange","categoryMin","categoryMax","categoryTotal","currentValue","hasLatLongGroup","hasCategoryGroup","location_4","categoryTooltipItem","latitudeTooltipItem","longitudeTooltipItem","seriesTooltipItem","sizeTooltipItem","gradientTooltipItem","colorRgb","StrokeDarkenColorValue","identityBuilder","subsliceValue","Circle","swapLogoContainerChildElement","logoContainer","aNode","divNode","mapOptions","credentials","showMapTypeSelector","enableClickableLogo","enableSearchLogo","mapTypeId","MapTypeId","road","customizeOverlays","showDashboard","showScalebar","disableKeyboardInput","divQuery","MapContainer","cssClass","createMapControl","Events","addThrottledHandler","onViewChanged","addHandler","onViewChangeEnded","updateOffsets","mapViewport","mapRoot","imageTiles","isLegendVisible","setView","Globals","roadUriFormat","appendImage","setImageStyle","imageStyle","getPixelString","max-height","max-width","TitleFontFamily","DefaultCaptionFontSizeInPt","DefaultTitleFontSizeInPt","DefaultDetailFontSizeInPt","DefaultTitleColor","DefaultTextColor","DefaultCategoryColor","DefaultOutline","DefaultOutlineColor","DefaultOutlineWeight","DefaultBarShow","DefaultBarColor","DefaultBarOutline","DefaultBarWeight","MultiRowCard","isInteractivityOverflowHidden","multiRowCardDiv","MultiRowCardRoot","initializeCardRowSelection","tableRows","resetScrollbarPosition","operationKind","Append","setCardDimensions","dataModel","dataColumnCount","cardTitleSettings","categoryLabelsSettings","cardSettings","getCardSettings","waitingForData","outlineSettings","barSettings","marginBottom","heightNotChanged","previousMaxColPerRow","maxColPerRow","getMaxColPerRow","widthNotChanged","maxCards","isDashboardVisual","tableDataRows","cardTitleLabelObjects","dataLabelObject","categoryLabelObject","isValuePromoted","showTitleAsURL","showTitleAsImage","showTitleAsKPI","cardData","statusGraphicInfo","columnCaption","showKPI","columnDetail","showURL","showImage","cardItemsData","ValuesRole","cardRow","cardHasTitle","Title","KPITitle","verticalAlign","cardItem","CardItemContainer","Caption","rowUpdate","getStyle","dataLabelHeight","categoryLabelHeight","titleLabelHeight","rowBorderStyle","getBorderStyles","margin-bottom","isSingleRowCard","line-height","TitleUrlSelector","TitleImageSelector","imageTitle","cardSelection","cardBorderStyle","CaptionImageSelector","imageCaption","padding-right","isLastRowItem","cardItemContainer","getColumnWidth","hideColumn","CaptionUrlSelector","rowExit","listViewOptions","onLoadMoreData","border-top","border-right","border-bottom","border-left","rowWidth","maxColumnPerRow","getRowIndex","fieldIndex","defaultStyles","customStyles","getCustomStyles","overrideStyle","tileMediaQueries","currentQuery","getSurroundSettings","edge","outlineProp","categoryLabelSettings","titleLabelSettings","customStyle","fontSizeInPt","maxRows","lastRowCount","enumerateCard","propNames","Textbox","readOnly","refreshView","updateSize","focus","editor","setSelection","saveContents","RichTextConversion","convertParagraphsToHtml","RichText","defaultFont","defaultFontSize","QuillWrapper","textChanged","editorElement","getElement","setContents","convertParagraphsToOps","contents","getContents","convertDeltaToParagraphs","paragraph","ops","insertOp","attributes","horizontalTextAlignment","newParagraph","textRun","textStyle","convertFormatAttributesToTextStyle","$paragraphs","paragraphIndex","paragraphDef","isParagraphEmpty","$paragraph","textRunIndex","textRunDef","$textRun","styleDef","getCssFontFamily","removeQuotes","textDecoration","$link","italic","bold","underline","op","getFontFamilyForBuiltInFont","family","fontMap","findKey","Segoe (Bold)","Segoe UI","Segoe UI Light","Heading","fonts","fontSizes","textAlignments","QuillPackage","quillJsFiles","quillCssFiles","$container","localizationProvider","dependenciesLoaded","loadQuillResources","initialized","rebuildQuillEditor","addModule","setHTML","setReadOnly","readOnlyChanged","activeElement","closest","$toolbarDiv","$editorDiv","getSelectionAtCursor","getTextWithoutTrailingBreak","getWord","insertLinkAtCursor","insertText","formatText","onTextChanged","getEditorContainer","getText","removeAllListeners","keydown","preventDefaultKeys","configs","styles","Quill","Toolbar","buildToolbar","textChangeThrottler","textChangeThrottle","relatedTarget","tagName","quillWrapper","linkTooltipTemplate","buildToolbarLinkInputTemplate","toolbarLinkInput","buildToolbarLinkInput","getTooltip","fontPicker","picker","$option","option","formatGroup","formatButton","toggleGroup","setSelectValue","$select","evt","createEvent","initUIEvent","dispatchEvent","linkTooltipTemplateGenerator","removeText","doneText","$group","$buttons","$button","change","optionModifier","$selector","clearLinkInput","linkTooltip","removeClass","DefaultLinkInputValue","buttonTooltip","defaultLinkText","toolbarUrlInput","endCursor","blur","blurTarget","inputElem","selectionStart","selectionEnd","mousedown","linkButton","cheerMeterProps","CheerMeter","isFirstTime","cat","catValues","object1","object2","color1","DefaultFontColor","color2","idn1","idn2","teamA","teamB","textOne","textTwo","draw","getRecomendedFontProperties","text1","text2","avaliableViewport","PaddingBetweenText","recomendedFontProperties","width1","width2","ensureStartState","startY","clearSelectionUI","updateSelectionUI","easeName","teams","dataPointInstance","renderer","SvgRenderer","hasPlayAxis","getObjectProperties","objectProperties","hasGradient","playFrameInfo","categoryQueryName","dataValues","dvSource","scatterMetadata","getSizeRangeForGroups","objProps","dataPointSeries","createDataPointSeries","reduce","createSeriesLegend","dataViewValueGroups","sizeColumnIndex","getMeasureValue","currentRange","hasX","hasY","indicies","dataValueSource","grouping","measureX","measureY","measureSize","seriesColor","measureSource","identityKey","xVal","yVal","createLazyFormattedCategory","radiusData","actualSizeDataRange","bubblePixelAreaSizeRange","BubbleRadius","minSize","maxSize","minRange","maxRange","getBubblePixelAreaSizeRange","MinSizeRange","MaxSizeRange","sizeValue","projectSizeToPixels","sizeCol","xIndex","yIndex","getDefaultData","renderAtFrame","converterOptions_1","isDataViewPlayable","playAxis","PlayAxis","playData","mergeSizeRanges","currentViewModel","setRenderFunction","mergedSizeRange","allViewModels","categoricalDataView","hasSizeMeasure","legendDataPointLength","getExtents","dps","extents","getCartesianExtents","setPlayControlPosition","combinedXDomain","isCurrentlyPlaying","fillMarkers","drawBubbles","suppressDataPointRendering","NoRenderResizeThreshold","isPlay","sortedData","sortBubbles","ScatterChartDataLabels","playRenderResult","playBehaviorOptions","createTraceLineRenderer","renderTraceLines","getStrokeFill","minSizeRange","maxSizeRange","AreaOf300By300Chart","rangeContains","projectedSize","isSelected","DimmedBubbleOpacity","DefaultBubbleOpacity","getMarkerStrokeFill","getMarkerStyle","getSeriesStyle","getBubbleOpacity","localeCompare","NoAnimationThreshold","MainGraphicsContext","mainGraphicsBackgroundRect","scatterMarkers","removeScatterMarkers","drawScatterMarkers","drawScatterMarkersNoAnimation","ScatterTraceLineRenderer","ScatterMarkerSeriesGroup","DotClass","fakeDataPointSeries","fakeSeriesGroups","markers","isBubble","seriesGroups","seriesStyle","styleException","elementStyle","elementValue","styleValue","preferredLabelsKeys","getPreferredLabelsKeys","dataPoints_5","isLabelPreferred","visualCenter","quadrantsCenters","getQuadrantsCenters","getCandidateLabels","visualHeight","quarterWidth","quarterHeight","minDistances","quadrantNumber","getPointQuadrantNumber","getDistanceBetweenPoints","ids_1","centerPoint","preferredLabelsKeys_1","preferredLabel","TraceLine","TraceBubble","shouldAnimate","scatterViewModel","seriesPoints","currentFrameIndex_1","hasBubbleAtCurrentFrame","selectedLen","frameIndex","frameLen","xScale_1","yScale_1","line_1","traceLines","sp","previousLengths_1","newLengths_1","reverse_1","existingPath","previousLength","hasAttribute","tempSvgPath","tempPath","stroke-dashoffset","circlePoints","selectedIndex_1","newPoints","circles","d1","d2","playControl","PlayControl","moveToFrameAndRender","onPlay","play","visualConverter","ridiculousFlagForPersistProperties","getDefaultPlayData","lastViewport","resized","playViewModel","data_5","updateCallout","rebuild","vm","flatAllDataPoints","flatten","frameData","plotAreaHeight","plotAreaWidth","calloutDimension","calloutData","calloutOffsetMultiplier","calloutText","callout","PlayCallout","isPlaying","indexToShow","getCurrentIndex","playNextFrame","startFrame","endFrame","nextFrame","setFrame","FrameStepDuration","pause","existingExtents","getMinMaxForAllFrames","playControlLayout","getContainer","data_6","createSliderDOM","playAxisContainer","playButton","noUiSlider","playButtonCircle","off","slider","labelData","sliderSize","calucalateSliderSize","SliderMarginLeft","skipStep","updateSliderControl","adjustWidthRegardingLastItem","nextLabelIndex","elem","labelInfo","labelWidth","sliderWidth","sliderElement","numFrames","pipOptions","skipMode","filterPipLabels","createPipsFilterFn","mode","density","escapedText","pips","pipSize","maxAllowedLabelWidth","widthRatio","anyWordBreaks","labelLenth","lastVisibleItemIndex","distanceToEnd","SliderMarginRight","lastItemWidth","SliderMaxMargin","PlayControlHeight","sliderLeftMargin","convertMatrixToCategorical","CategoryRowLevelsStartingIndex","i_2","hasRowChildren","hasColChildren","hasPlayAndCategory","columnLength_1","i_3","len_1","columnNode","dataViewColumn","playFrameNode","matrixIntersectionValues","categoryGroupLeafNode","categoryHierarchicalGroupNodes","addMatrixHierarchicalGroupToCategories","nodeQueue","seriesIndex_1","columnLength","leafNode","measureLength_1","sourceCategoryHierarchicalGroupNodes","destinationCategories","identityExpr","identityExprToAdd","keySourceColumn","frameKeys","matrixRows","rowChildrenLength","keyFormatter","valueRange","frameLabelText","frameLabelHtml","frameInfo","getLabelData","defaultData","data_7","keyColumn","labelFieldName","playRole","firstRowSourceRoles","selectedDataPoints","VerticalSlicerRenderer","domHelper","slicerInitOptions","bodyViewport","containerDiv","Container","onEnterSelection","onUpdateSelection","updateSelectionStyle","listItemElement","ItemContainer","labelElement","Input","Checkbox","labelImage","countText","slicerItemContainers","slicerItemLabels","slicerItemInputs","orientationBehaviorOptions","CheckboxSprite","MinimumSize","SizeRange","ItemWidthSampleSize","MinTextWidth","LoadMoreDataThreshold","marginRight","HorizontalSlicerRenderer","dataStartIndex","FlexDisplay","leftNavigationArrow","LeftNavigationArrow","itemsContainer","ItemsContainer","rightNavigationArrow","RightNavigationArrow","bindNavigationEvents","isMaxWidthCalculated","calculateAndSetMaxItemWidth","calculateAndSetTotalItemWidth","updateStyle","availableWidthForItemsContainer","itemsToDisplay","getNumberOfItemsToDisplay","renderCore","CanScrollRight","CanScrollLeft","renderItems","bindInteractivityService","materializedDataPoints","padding-left","margin-right","itemHeight","data_8","registerMouseWheelScrollEvents","registerMouseClickEvents","scrollRight","scrollLeft","scrollableElement","lastItemIndex","firstItemIndex","columnsToDisplay","getScaledTextWidth","getDataPointsCount","sampleSize","itemText","itemPadding","borderWidth","totalItemWidth","widthAvailable","initOptions","initializeSlicerRenderer","existingDataView","ObjectEnumerator","stopWaitingForData","slicerOrientation_1","orientationHasChanged","slicerRenderer","initializeHorizontalSlicer","initializeVerticalSlicer","verticalSlicerRenderer","createInitOptions","horizontalSlicerRenderer","enumerateItems","enumerateHeader","enumerateGeneral","shouldShowSelectionOption","enumerateSelection","areSelectionSettingsDefined","areHeaderSettingsDefined","areTextSettingsDefined","areGeneralSettingsDefined","TableHierarchyNavigator","tableDataView","isRow","getColumnIndex","cornerItem","isFirstItem","totalRow","totalCells","rowObjects","cellObject","arrayItem","TableBinder","onDataViewChanged","updateTextHeights","textProps","textHeightHeader","textHeightValue","textHeightTotal","onBindRowHeader","cellStyle","sortIconsEnabled","onColumnHeaderClick","setColumnHeaderStyle","propsGrid","propsTotal","propsValues","imgHeight","isUrl","domContent","setFooterStyle","setBodyStyle","propsColumns","dataViewTableRows","subtotalType","persistingObjects","lastAllowHeaderResize","waitingForSort","visualTable","visualRows","visualRow","getColumnWidthManager","refreshControl","createOrUpdateHierarchyNavigator","createColumnWidthManager","createTablixControl","persistColumnWidths","newViewport","verifyHeaderResize","dataNavigator","createControl","tableBinderOptions","tableBinder","tablixContainer","tablixOptions","createTotalsRow","shouldClearControl","totalValue","needsMoreData","loadMoreThreshold","preferredLoadMoreThreshold","shouldAllowHeaderResize","currentAllowHeaderResize","createMatrixHierarchyNavigator","MatrixHierarchyNavigator","MatrixVisualBodyItem","rowHierarchy","wrapMatrixHierarchy","columnHierarchy","getDataViewMatrix","getMatrixHierarchy","leafNodes","getLeafIndex","leafIndex","parent","siblings","bodyCell","isSubtotalItem","levelSource","isColumnHeaderLeaf","isRowHeaderLeaf","getMatrixColumnHierarchy","getMatrixRowHierarchy","updateColumns","updateHierarchy","updateStaticColumnHeaders","updateRecursive","columnLeafSources","rowHierarchyRootNodes","columnHierarchyRootNodes","MatrixBinder","bindHeader","getRowHeaderMetadata","setRowHeaderStyle","propsCols","overwriteTotalLabel","sortableHeaderColumnMetadata","getSortableHeaderColumnMetadata","showSortIcons","registerColumnHeaderClickHandler","getColumnHeaderMetadata","unregisterColumnHeaderClickHandler","overwriteSubtotalLabel","totalLabel","getNodeLabel","setBodyCellStyle","propsRows","rowBandingIndex","cornerHeaderMetadata","getSortableCornerColumnMetadata","setCornerCellsStyle","propsCol","propsRow","getHierarchyMetadata","levelInfo","columnGroupCount","rootChanged","matrixNavigator","matrixBinderOptions","TotalLabel","matrixBinder","labelsSettings","alternativeScale","majorLabelsEnabled","minorLabelsEnabled","getNodeClass","createTreemapShapeLayout","createTreemapZeroShapeLayout","TextMargin","MajorLabelTextSize","createMajorLabelText","createMinorLabelText","areMajorLabelsEnabled","areMinorLabelsEnabled","ShapesClassName","LabelsGroupClassName","sticky","highlightMultiplier","allNodes","dataWasCulled","getValuesFromCategoricalDataView","cullableValue","getCullableValue","isMultiSeries","shouldCullValue","valueColumnCount","ValuesRoleName","omitSecondLevel","categoryFormat","categoryLen","currentValues","gradientValueColumnMetadata","nodeKey","highlightedTooltipInfo","highlightTotal","value_1","checkValueForShape","childName","categoricalValues","childIdentity","childKey","highlightedValue","tooltipInfo_1","nodeName","seriesMetadataColumn","categoryValueCount","totalArea","culledPercent","CullableArea","treeMapData","rootChildren","treemapNode","calculateTreemapSize","initViewportDependantProperties","hasChildrenWithIdentity","canDisplayMajorLabel","MinTextWidthForMajorLabel","textHeightWithMargin","canDisplayMinorLabel","MinTextWidthForMinorLabel","MinorLabelTextSize","roomTop","parent_1","spaceAvaliableForLabels","baseTextProperties","MajorLabelTextProperties","measureFormatter","isHighlightRect","DimmedShapeOpacity","treemapLayout","drawDefaultHighlightShapes","drawDefaultMajorLabels","drawDefaultMinorLabels","nodeClass","ParentGroupClassName","NodeGroupClassName","RootNodeClassName","cleanMinorLabels","cardClassName","kpiImage","KPIImage","labelContext","cardFormatSetting","setTextProperties","cardTextProperties","getCardFormatTextSize","adjustedFontHeight","valueOnly","Value","formatSettings","valueTextHeightInPx","valueStyles","labelTextHeightInPx","labelHeightWithPadding","translatedLabelY","labelElementNode","displayStatusGraphic","valueElement","labelTextSizeInPx","kpiImageDiv","imageWidth","OwlHappiness","OwlGauge","rootElem","svgTailElem","owlTailSvg","svgBgElem","visualBgSvg","svgBodyElem","owlBodySvg","OwlDemoMode","setInterval","randomPercentage","updateGauge","updateViewportSize","percentage","rotationDeg","happinessLevel","Happy","Meh","Sad","smoothingFn","setImmediate","owlBodyHeightMultiplier","visualBgHeightMultiplier","owlTailHeightMultiplier","NoMapLocationWarning","getMessages","messageKey","titleKey","detailKey","visualMessage","GeometryCulledWarning","ScriptVisualRefreshWarning","WaterfallClassName","increaseColor","decreaseColor","totalColor","increaseLabel","IncreaseLabel","decreaseLabel","DecreaseLabel","posMin","posMax","catLen","tooltipInfo_2","totalIdentity","positionMin","positionMax","getSentimentColorsFromObjects","enumerateSentimentColors","renderableDataCount","cartesianLayout","xAxisCreationOptions","getXAxisCreationOptions","yAxisCreationOptions","getYAxisCreationOptions","createRects","colsSelection","CategoryValueClasses","createConnectors","connectorSelection","WaterfallConnectorClasses","connectors","defaultTotalColor","series_6","validZeroLabelPosition","ContainerClassName","ContentContainerClassName","ArrowClassName","TooltipHeaderClassName","TooltipRowClassName","TooltipColorCellClassName","TooltipTitleCellClassName","TooltipValueCellClassName","tooltipOptions","isTooltipVisible","DefaultTooltipOptions","isTooltipComponentVisible","setTestScreenSize","customScreenWidth","customScreenHeight","tooltipData","clickedArea","tooltipContainer","createTooltipContainer","setTooltipContent","setPosition","move","parentContainerSelector","currentTooltipData","rowsSelector","contentContainer","tooltipRow","newColorCell","newTitleCell","newValueCell","getTooltipPosition","clickedScreenArea","tooltipContainerBounds","centerPointOffset","arrowOffset","getClickedScreenArea","tooltipPosition","setArrowPosition","getArrowElement","screenWidth","innerWidth","screenHeight","halfHeight","highlightedValueDisplayNameResorceKey","getTooltipInfoDelegate","reloadTooltipDataOnMouseMove","onMouseOutDelegate","handleTouchTimeoutId","canDisplayTooltip","mouseCoordinates","isTouchEvent","clearTooltipTimeout","tooltipMouseOverDelay","tooltipTimeoutId","showDelayedTooltip","hideDelayedTooltip","tooltipMouseOutDelay","moveTooltipEventHandler","touchStartEventName","getTouchStartEventName","touchEndEventName","getTouchEndEventName","isPointerEvent","GlobalTooltipEventsAttached","attachGlobalEvents","hideTooltipEventHandler","tooltipTouchDelay","handleTouchDelay","showTooltipEventHandler","getClickedArea","d3Event","cadDisplay","mouseEvent","buttons","hasMouseButtonPressed","sourceEvent","clientLeft","clientTop","touchCoordinates","pointY","TooltipBuilder","createTooltipInfo","categorySource","seriesSource","valuesSource","categoriesData","compositeCategoriesData","isAutoGeneratedColumn","gradientToolTipData","createGradientToolTipData","createTooltipData","categoryFormattedValue","dynamicValue","dynamicValueMetadata","formattedHighlightedValue","getFormatStringFromColumn","visualStyles","subTitleText","isHighContrast","defaultSliceWidthRatio","DonutChartConversion","DonutChartConverter","d3PieLayout","culledDataPoints","cullDataByViewport","dataPointsToDeprecate","unCulledDataPoints","visibleGeometryCulled","drilled","allowDrilldown","donutChartSettings","chartRotationAnimationDuration","legendContainer","InteractiveLegendClassName","interactivityState","interactiveLegend","DonutChartInteractiveLegend","valueToAngleFactor","sliceAngles","currentRotate","interactiveChosenSliceFinishedSetting","lastChosenInteractiveSliceIndex","totalDragAngleDifference","currentIndexDrag","previousIndexDrag","previousDragAngle","donutCenter","initDonutProperties","setInteractiveChosenSlice","sliceIndex","moduledIndex","hw","denom","getScaleForLegendArrow","InteractiveLegendContainerHeight","previousRadius","halfViewportWidth","halfViewportHeight","OuterArcRadiusRatio","InnerArcRadiusRatio","mergeDatasets","second","secondSet","onlyFirst","has","derived","shapes_1","createLabels","assignInteractions","updateInternalToMove","measureFormatterCache","addInteractiveLegendArrow","arrowHeightOffset","arrowWidthOffset","interactiveLegendArrow","InteractiveLegendArrowClassName","scaleRatio","distanceBetweenLegendAndArrow","middleOfChart","calculateSliceAngles","angles","currentAngle","relativeAngle","assignInteractiveChartInteractions","setDrilldown","drilledDataPoints","internalDataPoints","DrillDownAnimationDuration","svgRect","clickedIndex","defaultPrevented","interactiveDragStart","interactiveDragMove","interactiveDragEnd","getAngleFromDragEvent","touch","adjustedCoordinates","angleToThePlane","currentDragAngle","angleDragDiff","currentHigherLimit","OpaqueOpacity","SemiTransparentOpacity","existingData","sliceClass","sliceHighlightClass","getHighlightRadius","donutData","isLastInDonut","sectionWithoutStroke","sectionWithStroke","sliceRadius","innerSliceArc","arcWithRadius","highlightArc","zeroWithZeroRadius","EffectiveZeroValue","prevPointColor","estimatedRadius","cullRatio","invisibleArcLengthInPixels","twoPi","dataPoints_6","PolylineOpacity","legendItemsPositions","legendTransitionAnimationDuration","currentNumberOfLegendItems","leftMostIndex","rightMostIndex","LegendContainerClassName","LegendItemSelector","legendContainerWidth","initialXOffset","ItemMargin","currX","currentXOffset","createLegendItem","itemDiv","itemCategory","itemValue","measureFormat","itemPercentage","itemColor","itemValueSpan","createBasicLegendItemSpan","LegendItemValueClassName","itemCategorySpan","LegendItemCategoryClassName","itemPercentageSpan","LegendItemPercentageClassName","valueSpanWidth","spanWidth","categorySpanWidth","precentageSpanWidth","currentLegendBoxWidth","legendBoxSize","getLeftValue","marginLeftValue","marginLeftCategory","marginLeftPrecentage","createLegendItemSpan","startX","boxWidth","LegendItemClassName","updateLabelBlocks","nextXOffset","styleTween","currentDX","hasChanged","dragStart","MinimumSwipeDX","dragDirectionLeft","dragLegend","touch-action","MinimumItemsInLegendForCycled","getCyclingCurrentIndex","shouldChangeIndexInNonCycling","dataLen","newIndex","updateLegendItemsBlocks","rightSidedShift","numberOfLegendItemsBlocksToShift","legendContainer$","smallestItem","insertAfter","highestItem","spanClass","existingSpan","text-overflow","boxSize","MaxLegendItemBoxSize","FakeElementSpan","allCategoryObjects","categoryColumnRef","categoryFormatString","isSingleMeasure","isDynamicSeries","normalizedMeasureAndValue","measureAndValue","normalized","convertCategoricalWithSlicing","convertSeries","convertMeasures","highlightMeasureValue","measureValue","normalizedHighlight","normalizedNonHighlight","highlightPercentage","pct","valueAndPct","highlightValueAndPct","convertLegendData","getLegendTitle","dvValuesSourceName","dvCategorySourceName","thisCategoryObjects","legendIdentity","nonHighlight","measureLabel","seriesFormat","seriesName","getImageUrl","ensureHtmlElement","watermarkKey","visualSortableOptions","basicShape","consoleWriter","helloIVisual","owlGauge","CanvasBackgroundHelper"],"mappings":"AA0BA,GAAOA,UAAP,SAAOA,IACH,SAAYC,GAERA,EAAAA,EAAA,SAAA,GAAA,WAEAA,EAAAA,EAAA,QAAA,GAAA,UAEAA,EAAAA,EAAA,kBAAA,GAAA,qBANQD,EAAAC,qBAAAD,EAAAC,uBAAAD,GAAAC,oBASZ,SAAYC,GACRA,EAAAA,EAAA,OAAA,GAAA,SACAA,EAAAA,EAAA,OAAA,GAAA,UAFQF,EAAAE,gCAAAF,EAAAE,kCAAAF,GAAAE,+BAKZ,SAAYC,GACRA,EAAAA,EAAA,KAAA,GAAA,OACAA,EAAAA,EAAA,OAAA,GAAA,SACAA,EAAAA,EAAA,SAAA,GAAA,WACAA,EAAAA,EAAA,MAAA,IAAA,QACAA,EAAAA,EAAA,UAAA,IAAA,aALQH,EAAAG,mBAAAH,EAAAG,qBAAAH,GAAAG,kBAQZ,SAAYC,KAAAJ,EAAAI,oBAAAJ,EAAAI,sBAAZ,IAmBcC,EAnBFL,GAAAI,mBAmBZ,SAAcC,GAAQ,GAAAC,IAAA,SAAAA,IAQlB,SAAYC,GACRA,EAAAA,EAAA,QAAA,GAAA,UACAA,EAAAA,EAAA,SAAA,GAAA,WACAA,EAAAA,EAAA,KAAA,GAAA,QAHQD,EAAAC,cAAAD,EAAAC,gBAAAD,GAAAC,aARMD,EAAAD,EAAAC,YAAAD,EAAAC,gBAARD,EAAAL,EAAAK,UAAAL,EAAAK,cA1CXL,UAAAA;;CCAP,GAAOA,UAAP,SAAOA,GAAQ,GAAAK,IAAA,SAAAA,GAAQ,GAAAC,IAAA,SAAAA,GAKnB,QAAAE,KACI,GAAIC,GAAO,GACPC,EAAM,CAEV,KAAKA,EAAM,EAAS,GAANA,EAAUA,GAAO,EAAG,CAC9B,GAAIC,GAAiC,GAAhBC,KAAKC,SAAgB,CAC1C,QAAQH,GACJ,IAAK,GACL,IAAK,IACL,IAAK,IACL,IAAK,IACDD,GAAQ,IAGhBA,GAAQE,EAAeG,SAAS,IAGpC,MAAOL,GAjBKH,EAAAE,aAAYA,GALTF,EAAAD,EAAAC,YAAAD,EAAAC,gBAARD,EAAAL,EAAAK,UAAAL,EAAAK,cAARL,UAAAA,YCAP,IAAOA,UAAP,SAAOA,GAAQ,GAAAK,IAAA,SAAAA,GAAQ,GAAAC,IAAA,SAAAA,GAiBRA,EAAAS,4BAA8B,SAASC,EAAcC,EAAoBC,EAAiBC,EAAkBC,EAA0BC,EAAsCC,GAAhE,SAAAF,IAAAA,GAAA,GAA0B,SAAAC,IAAAA,EAAAE,QAAsC,SAAAD,IAAAA,EAAAC,OACnL,IAAIC,IACAR,KAAMA,EACNC,WAAYA,EACZC,OAAQA,EACRC,SAAUA,EACVC,QAASA,EACTC,YAAaA,EACbC,UAAWA,GAGXG,GACAT,KAAM,mCACNU,SAAU,EACVC,KAAMC,KAAKC,MACXC,GAAIxB,EAAAE,eACJuB,uBAAwB,WACpB,GAAIC,IACAhB,KAAMQ,EAAKR,KACXC,WAAYO,EAAKP,WACjBC,OAAQM,EAAKN,OACbC,SAAUK,EAAKL,SACfC,QAASI,EAAKJ,QAQlB,OANgC,mBAArBI,GAAKH,cACZW,EAA6B,YAAI1B,EAAAC,YAAYiB,EAAKH,cAExB,mBAAnBG,GAAKF,YACZU,EAA2B,UAAIR,EAAKF,WAEjCU,GAEXR,KAAMA,EACNS,iBACAC,iBAOJ,OAJkD,mBAAvC5B,GAAA6B,qCACPV,EAAMW,QAAU9B,EAAA6B,oCAGbV,GAmBAnB,EAAA+B,gBAAkB,SAASC,EAAoBC,EAAmBtB,EAAoBuB,EAAgBC,EAAoBC,EAAsBC,EAAeC,GACtK,GAAIpB,IACAc,WAAYA,EACZC,SAAUA,EACVtB,WAAYA,EACZuB,OAAQA,EACRC,WAAYA,EACZC,aAAcA,EACdC,MAAOA,EACPC,QAASA,GAGTnB,GACAT,KAAM,sBACNU,SAAU,EACVC,KAAMC,KAAKC,MACXC,GAAIxB,EAAAE,eACJuB,uBAAwB,WACpB,GAAIC,IACAM,WAAYd,EAAKc,WACjBC,SAAUf,EAAKe,SACftB,WAAYO,EAAKP,WACjBuB,OAAQhB,EAAKgB,OACbC,WAAYjB,EAAKiB,WACjBC,aAAclB,EAAKkB,aACnBC,MAAOnB,EAAKmB,MACZC,QAASpB,EAAKoB,QAElB,OAAOZ,IAEXR,KAAMA,EACNS,iBACAC,iBAOJ,OAJsC,mBAA3B5B,GAAAuC,yBACPpB,EAAMW,QAAU9B,EAAAuC,wBAGbpB,IApHQnB,EAAAD,EAAAC,YAAAD,EAAAC,gBAARD,EAAAL,EAAAK,UAAAL,EAAAK,cAARL,UAAAA,YCAP,IAAOA,UAAP,SAAOA,GAAQ,GAAA8C,IAAA,SAAAA,GACX,QAAAC,GAA6BC,GACzB,MAAO,UAAUC,GACbA,EAAYC,iBAAmBF,EAAQG,cAF/BL,EAAAC,aAAYA,GADjBD,EAAA9C,EAAA8C,gBAAA9C,EAAA8C,oBAAR9C,UAAAA,YCAP,IAAOA,UAAP,SAAOA,GAAQ,GAAA8C,IAAA,SAAAA,GAOX,GAAAM,GAAA,WAKI,QAAAA,GAAmBJ,GACfK,KAAKC,aAAeN,EAAQM,aAC5BD,KAAKE,eACLF,KAAKG,eAAiBH,KAAKC,aAAaE,iBAgGhD,MA7FWJ,GAAAK,UAAAC,OAAP,SAAcC,EAA2BC,GAAA,SAAAA,IAAAA,GAAA,EACrC,IAAIC,GAAuCR,KAAKG,eAAeM,OAW/D,OATIT,MAAKC,aAAaS,wBAClBV,KAAKW,qBAAqBL,KAG1BN,KAAKY,eAAeN,EAAaC,GACjCP,KAAKW,oBAAoBX,KAAKE,cAGlCM,EAASK,QAAQb,KAAKE,aACfM,EAASM,SAGbf,EAAAK,UAAAW,gBAAP,SAAuBT,EAA2BU,GAC9C,GAAIR,GAA0BR,KAAKG,eAAeM,OAKlD,OAHAT,MAAKiB,sBAAsBX,EAAaU,GAExCR,EAASK,QAAQ,MACVL,EAASM,SAGbf,EAAAK,UAAAc,aAAP,WACI,MAAOlB,MAAKE,YAAYiB,OAAS,GAG9BpB,EAAAK,UAAAgB,MAAP,WACI,GAAIZ,GAAWR,KAAKG,eAAeM,OAInC,OAHAT,MAAKE,eACLF,KAAKW,wBACLH,EAASK,QAAQ,MACVL,EAASM,SAGbf,EAAAK,UAAAiB,gBAAP,WACI,MAAOrB,MAAKE,aAGRH,EAAAK,UAAAO,oBAAR,SAA4BW,GACxB,GAAIC,IACAC,KAAMF,EACDG,OAAO,SAACC,GAAwB,MAAsBA,GAAOC,gBAC7DC,IAAI,SAACF,GAAwB,MAAsBA,GAAOG,iBAG/DC,EAAQ9B,KAAK+B,qBAAqBT,EAEjCU,GAAEC,QAAQH,KACXP,EAAWO,MAAQA,GAEvB9B,KAAKC,aAAaiC,SAASX,IAGvBxB,EAAAK,UAAAa,sBAAR,SAA8BX,EAA2BU,GACrD,GAAImB,GAAYnC,KAAK+B,sBAAsBzB,GAC3C,KAAI0B,EAAEC,QAAQE,GAAd,CAGA,GAAIC,IACAZ,KAAMW,EACNnB,SAAUA,EAGdhB,MAAKC,aAAaoC,cAAcD,KAG5BrC,EAAAK,UAAA2B,qBAAR,SAA6BO,GACzB,MAAON,GAAEM,GACJb,OAAO,SAAAC,GAAS,MAAsBA,GAAOC,cAC7CC,IAAI,SAAAF,GAAS,MAAsBA,GAAOK,yBAC1CQ,UACAb,SAGD3B,EAAAK,UAAAQ,eAAR,SAAuBN,EAA2BC,GAC1CR,EAAiByC,kBAAkBxC,KAAKE,YAAaI,GACrDN,KAAKE,YAAcK,EACbP,KAAKE,YAAYuB,OAAO,SAAAgB,GAAK,OAAuBnC,EAAaoC,OAA4BD,KAC7FzC,KAAKE,YAAYiB,OAAS,GACrBb,MAEPC,EACAP,KAAKE,YAAYyC,KAAKrC,GAEtBN,KAAKE,aAAeI,IAIlBP,EAAAyC,kBAAd,SAAgCI,EAAsBnE,GAClD,MAAOmE,GAAKC,KAAK,SAAAJ,GAAK,MAAsBhE,GAAIiE,OAA4BD,MAEpF1C,IAxGaN,GAAAM,iBAAgBA,GAPlBN,EAAA9C,EAAA8C,gBAAA9C,EAAA8C,oBAAR9C,UAAAA,YCAP,IAAOA,UAAP,SAAOA,GAAQ,GAAA8C,IAAA,SAAAA,GAKX,GAAAqD,GAAA,WAAA,QAAAA,MAkCA,MA9BWA,GAAA1C,UAAA2C,aAAP,SAAoBC,EAAwCC,GAIxD,MAHID,IAAkBA,EAAe7D,QAAU6D,EAAe7D,OAAO+D,WAAaF,EAAeG,WAC7FnD,KAAKoD,gBAAgBJ,EAAe7D,OAAO+D,WAAaF,EAAeG,SAASF,IAE7EjD,MAGJ8C,EAAA1C,UAAAiD,WAAP,SAAkBC,EAAoCC,GAIlD,MAHID,IAAgBA,EAAanE,QAAUmE,EAAanE,OAAO+D,WAAaK,IACxEvD,KAAKoD,gBAAgBE,EAAanE,OAAO+D,WAAaK,EAAYJ,UAE/DnD,MAGJ8C,EAAA1C,UAAAoD,YAAP,SAAmBC,GAGf,MAFAzD,MAAK0D,QAAUD,EAERzD,MAGJ8C,EAAA1C,UAAAuD,kBAAP,WACI,MAAOhH,GAAAK,QAAQ4G,YAAYC,sCAAsC7D,KAAKoD,gBAAiBpD,KAAK0D,UAGxFZ,EAAA1C,UAAAgD,cAAR,WAII,MAHKpD,MAAK8D,UACN9D,KAAK8D,YAEF9D,KAAK8D,SAEpBhB,IAlCarD,GAAAqD,mBAAkBA,GALpBrD,EAAA9C,EAAA8C,gBAAA9C,EAAA8C,oBAAR9C,UAAAA,YCAP,IAAOA,UAAP,SAAOA,GAAQ,GAAA8C,IAAA,SAAAA,GASX,QAAAsE,GAAoCC,EAA6BC,GAC7D,GAAIC,IACAvG,KAAMqG,EAAarG,KACnBC,WAAYoG,EAAapG,WACzBC,SAAUmG,EAAanG,OAE3B,OAAO,IAAI4B,GAAA0E,2BAA2B,GAAIC,GAAcJ,EAAiCC,GAAmBC,EAAwCD,GAZxJ,GAAOvG,GAA8Bf,EAAAK,QAAQC,UAAUS,2BAI5C+B,GAAA4E,qBAEK5E,EAAAsE,oBAAmBA,CASnC,IAAAK,GAAA,WAOI,QAAAA,GAAYJ,EAA6BC,GACrCjE,KAAKiE,iBAAmBA,EACxBjE,KAAKsE,OAASN,CAEd,IAAIO,GAAUP,EAAapG,WACvB4G,EAAexE,KAAKyE,gBAAgBF,GACpCxG,GAAU,CAETwG,GAGIC,EAAe,IACpBxE,KAAK0E,gBAAkBF,EACvBxE,KAAK2E,QAAS,GAId5G,GAAU,EARViC,KAAK2E,QAAS,EAWd3E,KAAKiE,kBACLjE,KAAKiE,iBAAiBW,SAClBlH,EACAsC,KAAKsE,OAAO3G,KACZqC,KAAKsE,OAAO1G,aACVoC,KAAKsE,OAAOzG,OACdK,OACAH,EACApB,EAAAK,QAAQC,UAAUC,YAAY2H,MA4I9C,MAvIWT,GAAAhE,UAAA0E,KAAP,SAAYnF,GAMR,GAFAA,EAAQoF,QAAQC,QAEZhF,KAAK2E,OACL3E,KAAKiF,OAASjF,KAAKsE,OAAOY,SAC1BlF,KAAKmF,aAAaL,KAAKnF,OAEtB,CACD,GAAIyF,GAAO3F,EAAA4E,kBAAkBrE,KAAK0E,iBAAiBW,YAAY1F,EAAQyF,KACvEpF,MAAKiF,OAASjF,KAAKsE,OAAOY,QACtBH,QAASpF,EAAQoF,QAAQO,IAAI,GAC7BF,KAAMA,IAEVpF,KAAKuF,oBAINnB,EAAAhE,UAAAoF,OAAP,SAAc7F,GACNA,EAAQ8F,KAAO9I,EAAAG,iBAAiB4I,QAAU1F,KAAK2F,gBAAgB,cAC/D3F,KAAK4F,WAAWjG,EAAQkG,SAAUlG,EAAQmG,YACnC9F,KAAK2F,gBAAgB,UAC5B3F,KAAKmF,aAAaK,OAAO7F,MAEpBA,EAAQ8F,MAAQ9F,EAAQ8F,KAAO9I,EAAAG,iBAAiBiJ,OACjD/F,KAAKgG,cAAwChE,EAAEiE,KAAKtG,GAAU,YAAa,mBAE3EA,EAAQ8F,KAAO9I,EAAAG,iBAAiBoJ,UAChClG,KAAKmG,kBAAkBxG,EAAQyG,YAKpChC,EAAAhE,UAAAiG,QAAP,WACQrG,KAAK2F,gBAAgB,YACrB3F,KAAKmF,aAAakB,WAInBjC,EAAAhE,UAAAkG,yBAAP,SAAgC3G,GAC5B,MAAKK,MAAK2F,gBAAgB,4BAGnB3F,KAAKmF,aAAamB,yBAAyB3G,GAHlD,QAMGyE,EAAAhE,UAAAmG,0BAAP,WACI,MAAKvG,MAAK2F,gBAAgB,6BAGnB3F,KAAKmF,aAAaoB,4BAHzB,QAMGnC,EAAAhE,UAAAwF,WAAP,SAAkBY,EAA0BV,GACpC9F,KAAK2F,gBAAgB,eACrB3F,KAAKmF,aAAaS,WAAWY,EAAeV,IAI7C1B,EAAAhE,UAAA4F,cAAP,SAAqBrG,GACbK,KAAK2F,gBAAgB,kBACrB3F,KAAKmF,aAAaa,cAAcrG,IAIjCyE,EAAAhE,UAAA+F,kBAAP,SAAyBC,GACjBpG,KAAK2F,gBAAgB,sBACrB3F,KAAKmF,aAAagB,kBAAkBC,IAIrChC,EAAAhE,UAAAqG,iBAAP,WACQzG,KAAK2F,gBAAgB,qBACrB3F,KAAKmF,aAAasB,oBAInBrC,EAAAhE,UAAAsG,YAAP,SAAmBb,GACf,MAAI7F,MAAK2F,gBAAgB,eACd3F,KAAKmF,aAAauB,YAAYb,GADzC,QAKGzB,EAAAhE,UAAAuG,OAAP,WACI,MAAwB3G,MAAKiF,QAGjC2B,OAAAC,eAAYzC,EAAAhE,UAAA,aCiYJkF,IDjYR,WACI,MAAItF,MAAK2E,OAAT,OACsC3E,KAAKiF,QCoYvC6B,YAAY,EACZC,cAAc,IDlYtBH,OAAAC,eAAYzC,EAAAhE,UAAA,gBCqYJkF,IDrYR,WACI,MAAKtF,MAAK2E,OACc3E,KAAKiF,OAD7B,QCyYI6B,YAAY,EACZC,cAAc,IDtYd3C,EAAAhE,UAAAuF,gBAAR,SAAwBqB,GACpB,GAAI/B,GAASjF,KAAK2E,OAAS3E,KAAKmF,aAAenF,KAAKiH,SACpD,OAAOhC,IAAUjD,EAAEkF,WAAWjC,EAAO+B,KAGjC5C,EAAAhE,UAAAqE,gBAAR,SAAwBF,GACpB,GAAIA,EAEA,IAAK,GADD4C,GAAe1H,EAAc4E,kBAAkBlD,OAC1CiG,EAAI,EAAOD,EAAJC,EAAkBA,IAC9B,GAAI3H,EAAc4E,kBAAkB+C,GAAG7C,UAAYA,EAC/C,MAAO6C,EAInB,OAAO,IAGHhD,EAAAhE,UAAAmF,gBAAR,WACI,GAAI8B,GAAYrH,KAAKsH,sBACrB,KAAK,GAAIC,KAAOF,GACZrH,KAAKuH,GAAOF,EAAUE,IAItBnD,EAAAhE,UAAAkH,qBAAR,WAII,IAAK,GAHDD,MACA7C,EAAexE,KAAK0E,gBACpBuC,EAAYjH,KAAKiH,UACZG,EAAI,EAAQ5C,GAAL4C,EAAmBA,IAAK,CACpC,GAAII,GAAkB/H,EAAc4E,kBAAkB+C,GAAGC,SACrDrF,GAAEkF,WAAWM,IACbxF,EAAEyF,OAAOJ,EAAWG,EAAgBP,IAG5C,MAAOI,IAEfjD,IA/Ka3E,GAAA2E,cAAaA,GAlBf3E,EAAA9C,EAAA8C,gBAAA9C,EAAA8C,oBAAR9C,UAAAA,YEAP,IAAOA,UAAP,SAAOA,GAAQ,GAAA8C,IAAA,SAAAA,GAIX,GAAOT,GAAkBrC,EAAQK,QAAQC,UAAU+B,gBAEnDmF,EAAA,WACI,QAAAA,GACYuD,EACAC,EACA1D,EACA2D,GAHA5H,KAAA0H,cAAAA,EACA1H,KAAA2H,WAAAA,EACA3H,KAAAiE,iBAAAA,EACAjE,KAAA4H,OAAAA,EAoFhB,MAlFWzD,GAAA/D,UAAA0E,KAAP,SAAYnF,GAAZ,GAAAkI,GAAA7H,IACQA,MAAK0H,cAAc5C,MACnB9E,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAc5C,KAAKnF,MAIlDwE,EAAA/D,UAAAiG,QAAP,WAAA,GAAAwB,GAAA7H,IACQA,MAAK0H,cAAcrB,SACnBrG,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAcrB,aAG7ClC,EAAA/D,UAAAoF,OAAP,SAAc7F,GAAd,GAAAkI,GAAA7H,IACQA,MAAK0H,cAAclC,QACnBxF,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAclC,OAAO7F,MAGpDwE,EAAA/D,UAAAwF,WAAP,SAAkBY,EAA0BV,GAA5C,GAAA+B,GAAA7H,IACQA,MAAK0H,cAAc9B,YACnB5F,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAc9B,WAAWY,EAAeV,MAGvE3B,EAAA/D,UAAA4F,cAAP,SAAqBrG,GAArB,GAAAkI,GAAA7H,IACQA,MAAK0H,cAAc1B,eACnBhG,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAc1B,cAAcrG,MAG3DwE,EAAA/D,UAAA+F,kBAAP,SAAyBC,GAAzB,GAAAyB,GAAA7H,IACQA,MAAK0H,cAAcvB,mBACnBnG,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAcvB,kBAAkBC,MAG/DjC,EAAA/D,UAAAqG,iBAAP,WAAA,GAAAoB,GAAA7H,IACQA,MAAK0H,cAAcjB,kBACnBzG,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAcjB,sBAG7CtC,EAAA/D,UAAAsG,YAAP,SAAmBb,GAAnB,GAAAgC,GAAA7H,IACI,OAAIA,MAAK0H,cAAchB,YACZ1G,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAchB,YAAYb,KADnE,QAIG1B,EAAA/D,UAAAkG,yBAAP,SAAgC3G,GAAhC,GAAAkI,GAAA7H,IACI,OAAIA,MAAK0H,cAAcpB,yBACZtG,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAcpB,yBAAyB3G,KADhF,QAIGwE,EAAA/D,UAAAmG,0BAAP,WAAA,GAAAsB,GAAA7H,IACI,OAAIA,MAAK0H,cAAcnB,0BACZvG,KAAK8H,cAAc,WAAM,MAAAD,GAAKH,cAAcnB,8BADvD,QAIGpC,EAAA/D,UAAAuG,OAAP,WACI,GAAI1B,GAA0CjF,KAAK0H,aACnD,OAAOzC,GAAO0B,OAAS1B,EAAO0B,SAAW1B,GAGtCd,EAAA/D,UAAA2H,eAAP,WACI,MAAO/H,MAAK2H,WAAW9J,QAGnBsG,EAAA/D,UAAA0H,cAAR,SAAsBE,GAClB,IACI,MAAOA,KACT,MAAOC,IACAjI,KAAK4H,OAIN5H,KAAKiE,kBACLjE,KAAKiE,iBAAiBW,SAClB5F,EACAgB,KAAK2H,WAAWhK,KAChBqC,KAAK2H,WAAW9J,OAChBmC,KAAK2H,WAAW/J,WAChBqK,EAAUC,SACVD,EAAU7I,WACV6I,EAAU5I,aACV4I,EAAU3I,MACV2I,EAAU1I,WAI9B4E,IAzFa1E,GAAA0E,2BAA0BA,GAN5B1E,EAAA9C,EAAA8C,gBAAA9C,EAAA8C,oBAAR9C,UAAAA,YCAP,IAAOA,UAAP,SAAOA,GAAQ,GAAA8C,IAAA,SAAAA,GAAc,GAAA0I,IAAA,SAAAA,GACzB,GAAIX,GAAgD,SAACvC,GACjD,OACIO,OAAQ,SAAC7F,GACL,GAAIsF,EAAOO,OAAQ,CACf,GAAIC,GAAO9F,EAAQ8F,MAAQ9I,EAAAG,iBAAiBiJ,IACzCN,GAAO9I,EAAAG,iBAAiB4I,QAAiC,IAAvB/F,EAAQmG,aACzCL,GAAQ9I,EAAAG,iBAAiBsL,WAE7BnD,EAAOO,QACHK,SAAUlG,EAAQkG,SAClBwC,UAAW1I,EAAQ0I,UACnB5C,KAAMA,MAIlBY,QAAS,WACDpB,EAAOoB,SACPpB,EAAOoB,WAGfC,yBAA0B,SAAC3G,GACvB,MAAIsF,GAAOqB,yBACArB,EAAOqB,yBAAyB3G,GAD3C,UAOR0F,EAAiC,SAACD,GAClC,SAGJ3F,GAAA4E,kBAAkB1B,MACd4B,QAAS,QACT8C,UAAWG,EACXnC,YAAaA,KApCQ8C,EAAA1I,EAAA0I,OAAA1I,EAAA0I,WAAd1I,EAAA9C,EAAA8C,gBAAA9C,EAAA8C,oBAAR9C,UAAAA,YCAP,IAAOA,UAAP,SAAOA,GAAQ,GAAA8C,IAAA,SAAAA,GAAc,GAAA6I,IAAA,SAAAA,GACzB,GAAIjD,GAAiC,SAACD,GAClC,OACImD,yBAA0B,WAAM,MAAA,IAAI5L,GAAAK,QAAQ8F,oBAC5C0F,uBAAwB,WAAM,MAAA,IAAI/I,GAAAM,kBAAmBE,aAAcmF,MAI3E3F,GAAA4E,kBAAkB1B,MACd4B,QAAS,QACTc,YAAaA,KAVQiD,EAAA7I,EAAA6I,OAAA7I,EAAA6I,WAAd7I,EAAA9C,EAAA8C,gBAAA9C,EAAA8C,oBAAR9C,UAAAA;;CCAP,GAAO8L,WAAP,SAAOA,GAIH,GAAcC,IAAd,SAAcA,GAKGA,EAAAC,WAAa,GACbD,EAAAE,aAAe,GACfF,EAAAG,WAAa,EACbH,EAAAI,eAAiB,GACjBJ,EAAAK,iBAAmB,GACnBL,EAAAM,iBAAmB,GACnBN,EAAAO,kBAAoB,GACpBP,EAAAQ,YAAc,GACdR,EAAAS,WAAa,GACbT,EAAAU,iBAAmB,EACnBV,EAAAW,cAAgB,GAChBX,EAAAY,aAAe,GACfZ,EAAAa,aAAe,GACfb,EAAAc,YAAc,GACdd,EAAAe,WAAa,GAEbf,EAAAgB,SAAW,GACXhB,EAAAiB,SAAW,GACXjB,EAAAkB,SAAW,GACXlB,EAAAmB,SAAW,GACXnB,EAAAoB,SAAW,GACXpB,EAAAqB,SAAW,GACXrB,EAAAsB,SAAW,GACXtB,EAAAuB,SAAW,GAKXvB,EAAAwB,aAAe,OACfxB,EAAAyB,OAAS,IACTzB,EAAA0B,qBAAuB,kBACvB1B,EAAA2B,wBAA0B,kBAK1B3B,EAAA4B,yBAA2B,WAC3B5B,EAAA6B,yBAA2B,WAC3B7B,EAAA8B,YAAc,KACd9B,EAAA+B,eAAiB,QACjB/B,EAAAgC,cAAgB,OAChBhC,EAAAiC,gBAAkB,SAClBjC,EAAAkC,WAAa,SACblC,EAAAmC,UAAY,QACZnC,EAAAoC,eAAiB,QACjBpC,EAAAqC,eAAiB,QACjBrC,EAAAsC,aAAe,MAKftC,EAAAuC,qBAAuB,cACvBvC,EAAAwC,cAAgB,OAChBxC,EAAAyC,eAAiB,QACjBzC,EAAA0C,eAAiB,QACjB1C,EAAA2C,gBAAkB,SAClB3C,EAAA4C,aAAe,MACf5C,EAAA6C,iBAAmB,UACnB7C,EAAA8C,mBAAqB,YACrB9C,EAAA+C,mBAAqB,YACrB/C,EAAAgD,oBAAsB,aACtBhD,EAAAiD,oBAAsB,aACtBjD,EAAAkD,mBAAqB,YACrBlD,EAAAmD,kBAAoB,WACpBnD,EAAAoD,oBAAsB,QACtBpD,EAAAqD,eAAiB,QACjBrD,EAAAsD,gBAAkB,SAClBtD,EAAAuD,cAAgB,OAChBvD,EAAAwD,eAAiB,QACjBxD,EAAAyD,iBAAmB,UACnBzD,EAAA0D,kBAAoB,WACpB1D,EAAA2D,gBAAkB,SAClB3D,EAAA4D,iBAAmB,UACnB5D,EAAA6D,cAAgB,OAChB7D,EAAA8D,aAAe,eAKf9D,EAAA+D,yBAA2B,iBApF9B/D,EAAAD,EAAAC,eAAAD,EAAAC,mBAJXD,WAAAA,aCAP,IAAO9L,UAAP,SAAOA,IAmCH,SAAY+P,GACRA,EAAAA,EAAA,sBAAA,GAAA,wBACAA,EAAAA,EAAA,eAAA,GAAA,kBAFQ/P,EAAA+P,2BAAA/P,EAAA+P,6BAAZ,IAAYA,GAAA/P,EAAA+P,yBAeZC,EAAA,WAqBI,QAAAA,GAAYC,GACR5M,KAAK6M,eAAiBD,EAiB9B,MAlCIhG,QAAAC,eAAW8F,EAAAvM,UAAA,QCgGPkF,IDhGJ,WACI,MAAOqH,GAA0BG,UCkGjChG,YAAY,EACZC,cAAc,IDhGlBH,OAAAC,eAAW8F,EAAAvM,UAAA,aCmGPkF,IDnGJ,WACI,OAAO,GCqGPwB,YAAY,EACZC,cAAc,IDnGlBH,OAAAC,eAAW8F,EAAAvM,UAAA,aCsGPkF,IDtGJ,WACI,MAAOtF,MAAK+M,eCwGZC,IDrGJ,SAAqBtL,GACjB1B,KAAK+M,cAAgBrL,GCuGrBoF,YAAY,EACZC,cAAc,IDjGX4F,EAAAvM,UAAA6M,WAAP,SAAkBC,GACd,GAAIC,EAWJ,OATIA,GADmC,IAAnCnN,KAAK6M,eAAeO,WACLC,EAAyBC,6BAA6BJ,EAAkBlN,KAAK6M,gBAG7EQ,EAAyBE,oCAAoCL,EAAkBlN,KAAK6M,eAAeO,YAGtHC,EAAyBG,kBAAkBL,EAAcnN,KAAK6M,eAAeM,aAAcD,GAC3FG,EAAyBI,wBAAwBN,EAAcnN,KAAK6M,eAAetN,SAAW,KAAMS,KAAK6M,eAAea,YAAc,KAAMR,GAErIC,GAlCIR,EAAAG,SAAW,4BAoC9BH,IAvCahQ,GAAAgQ,0BAAyBA,CAyCtC,IAAAU,GAAA,WAAA,QAAAA,MAsGA,MApGkBA,GAAAG,kBAAd,SAAgCL,EAA4BQ,EAAuCC,GAC/F,GAAID,EACA,IAAK,GAAIvG,GAAI,EAAGA,EAAIuG,EAAgBxM,OAAQiG,IAAK,CAC7C,GAAIrC,GAAU4I,EAAgBvG,GAC1ByG,EAAgBD,EAASE,YAAYT,EAAyBU,kBAAoBhJ,EAAQiJ,MAC1FC,GACAC,aAAcL,EAAgBA,EAAgB9I,EAAQiJ,KACtDG,eAAgBpJ,EAAQqJ,OAAO3I,OAASiH,EAAyB2B,sBAAwBT,EAAStI,IAAI+H,EAAyBU,kBAAoBhJ,EAAQqJ,OAAO1M,OAASqD,EAAQqJ,OAAO1M,MAG9LyL,GAAamB,oBAAoB3L,KAAKsL,GAG9C,MAAOd,IAGGE,EAAAI,wBAAd,SAAsCN,EAA4B5N,EAAiBmO,EAAoBE,GACnG,GAAIrO,EAAS,CACT,GAAI0O,IACAC,aAAcN,EAAStI,IAAI,wCAC3B6I,eAAgB5O,EAEpB4N,GAAamB,oBAAoB3L,KAAKsL,GAE1C,GAAIP,EAAY,CACZ,GAAIO,IACAC,aAAcN,EAAStI,IAAI,sCAC3B6I,eAAgBT,EAEpBP,GAAamB,oBAAoB3L,KAAKsL,GAE1C,MAAOd,IAGGE,EAAAC,6BAAd,SAA2CM,EAAmChB,GAC1E,GAAIrN,GAAUqO,EAAStI,IAAI,iCACvBiC,EAAMqG,EAAStI,IAAI,iCACnBiJ,EAAM3B,EAAarN,QAEnBiP,IACJA,GAAe7L,MAAOuL,aAAc3G,EAAK4G,eAAgBI,GAEzD,IAAIpB,IACA5N,QAASA,EACT+O,oBAAqBE,EAGzB,OAAOrB,IAGGE,EAAAE,oCAAd,SAAkDK,EAAmCR,GAEjF,GAAI7N,GAAkB,GAClBgI,EAAc,GACdgH,EAAc,EAElB,QAAQnB,GACJ,IAAK,GACD7N,EAAUqO,EAAStI,IAAI,gCACvBiC,EAAMqG,EAAStI,IAAI,uCACnBiJ,EAAMX,EAAStI,IAAI,wCACnB,MACJ,KAAK,GACD/F,EAAUqO,EAAStI,IAAI,gCACvBiC,EAAMqG,EAAStI,IAAI,wCACnBiJ,EAAMX,EAAStI,IAAI,yCACnB,MACJ,KAAK,GACD/F,EAAUqO,EAAStI,IAAI,gCACvBiC,EAAMqG,EAAStI,IAAI,wCACnBiJ,EAAMX,EAAStI,IAAI,yCACnB,MACJ,KAAK,GACD/F,EAAUqO,EAAStI,IAAI,iCACvBiC,EAAMqG,EAAStI,IAAI,6CACnBiJ,EAAMX,EAAStI,IAAI,8CACnB,MACJ,KAAK,GACD/F,EAAUqO,EAAStI,IAAI,iCACvBiC,EAAMqG,EAAStI,IAAI,2DACnBiJ,EAAMX,EAAStI,IAAI,4DACnB,MACJ,KAAK,GACL,QACI/F,EAAUqO,EAAStI,IAAI,6BACvBiC,EAAMqG,EAAStI,IAAI,gCACnBiJ,EAAMX,EAAStI,IAAI,kCAI3B,GAAIkJ,KACJA,GAAe7L,MAAOuL,aAAc3G,EAAK4G,eAAgBI,GAEzD,IAAIpB,IACA5N,QAASA,EACT+O,oBAAqBE,EAGzB,OAAOrB,IAnGIE,EAAAU,kBAAoB,eAqGvCV,IAtGa1Q,GAAA0Q,yBAAwBA,GA3FlC1Q,UAAAA,YEAP,IAAOA,UAAP,SAAOA,KAAAA,UAAAA,YCAP,IAAOA,QCEP,IDFA,SAAOA,GAsBH,QAAA8R,GAAgDC,GAC5C,MAAO,IAAIC,GAA0BD,GAtB5B/R,EAAAiS,eACTC,QAAS,UACTC,KAAM,OACNC,UAAW,YACXC,cAAe,UACfC,OAAQ,SACRC,UAAW,YACXC,SAAU,WACVC,MAAO,QACPC,WAAY,aACZC,gBAAiB,mBAWL3S,EAAA8R,gCAA+BA,CAI/C,IAAMc,IACFC,2BAA4B,YAC5BC,4BAA6B,aAC7BC,yBAA0B,UAC1BC,2BAA4B,YAC5BC,uBAAwB,QACxBC,wBAAyB,SACzBC,sBAAuB,OACvBC,wBAAyB,SACzBC,sBAAuB,OACvBC,uBAAwB,QACxBC,0BAA2B,WAC3BC,2BAA4B,YAC5BC,wBAAyB,SACzBC,0BAA2B,WAC3BC,yBAA0B,UAC1BC,0BAA2B,WAC3BC,sBAAuB,OACvBC,qBAAsB,MACtBC,sBAAuB,OACvBC,uBAAwB,QACxBC,wBAAyB,SACzBC,yBAA0B,UAC1BC,2BAA4B,YAC5BC,wBAAyB,SACzBC,yBAA0B,UAC1BC,2BAA4B,YAC5BC,iCAAkC,MAClCC,0BAA2B,WAC3BC,gCAAiC,MACjCC,4BAA6B,cAC7BC,6BAA8B,eAC9BC,yBAA0B,WAC1BC,0BAA2B,YAC3BC,2BAA4B,YAC5BC,6BAA8B,cAC9BC,6CAA8C,gBAC9CC,+CAAgD,mBAGpDjD,EAAA,WAuCI,QAAAA,GAAYD,GAHJ1O,KAAA2R,6CAA+C,gBAC/C3R,KAAA4R,+CAAiD,kBAGrD5R,KAAKwP,2BAA6Bd,EAAa,8BAA8BmD,cAC7E7R,KAAKyP,4BAA8Bf,EAAa,+BAA+BmD,cAC/E7R,KAAK0P,yBAA2BhB,EAAa,4BAA4BmD,cACzE7R,KAAK2P,2BAA6BjB,EAAa,8BAA8BmD,cAC7E7R,KAAK4P,uBAAyBlB,EAAa,0BAA0BmD,cACrE7R,KAAK6P,wBAA0BnB,EAAa,2BAA2BmD,cACvE7R,KAAK8P,sBAAwBpB,EAAa,yBAAyBmD,cACnE7R,KAAK+P,wBAA0BrB,EAAa,2BAA2BmD,cACvE7R,KAAKgQ,sBAAwBtB,EAAa,yBAAyBmD,cACnE7R,KAAKiQ,uBAAyBvB,EAAa,0BAA0BmD,cACrE7R,KAAKkQ,0BAA4BxB,EAAa,6BAA6BmD,cAC3E7R,KAAKmQ,2BAA6BzB,EAAa,8BAA8BmD,cAC7E7R,KAAKoQ,wBAA0B1B,EAAa,2BAA2BmD,cACvE7R,KAAKqQ,0BAA4B3B,EAAa,6BAA6BmD,cAC3E7R,KAAKsQ,yBAA2B5B,EAAa,4BAA4BmD,cACzE7R,KAAKuQ,0BAA4B7B,EAAa,6BAA6BmD,cAC3E7R,KAAKwQ,sBAAwB9B,EAAa,yBAAyBmD,cACnE7R,KAAKyQ,qBAAuB/B,EAAa,wBAAwBmD,cACjE7R,KAAK0Q,sBAAwBhC,EAAa,yBAAyBmD,cACnE7R,KAAK2Q,uBAAyBjC,EAAa,0BAA0BmD,cACrE7R,KAAK4Q,wBAA0BlC,EAAa,2BAA2BmD,cACvE7R,KAAK6Q,yBAA2BnC,EAAa,4BAA4BmD,cACzE7R,KAAK8Q,2BAA6BpC,EAAa,8BAA8BmD,cAC7E7R,KAAK+Q,wBAA0BrC,EAAa,2BAA2BmD,cACvE7R,KAAKgR,yBAA2BtC,EAAa,4BAA4BmD,cACzE7R,KAAKiR,2BAA6BvC,EAAa,8BAA8BmD,cAC7E7R,KAAKkR,iCAAmCxC,EAAa,oCAAoCmD,cACzF7R,KAAKmR,0BAA4BzC,EAAa,6BAA6BmD,cAC3E7R,KAAKoR,gCAAkC1C,EAAa,mCAAmCmD,cACvF7R,KAAKqR,4BAA8B3C,EAAa,+BAA+BmD,cAC/E7R,KAAKsR,6BAA+B5C,EAAa,gCAAgCmD,cACjF7R,KAAKuR,yBAA2B7C,EAAa,4BAA4BmD,cACzE7R,KAAKwR,0BAA4B9C,EAAa,6BAA6BmD,cAC3E7R,KAAKyR,2BAA6B/C,EAAa,8BAA8BmD,cAC7E7R,KAAK0R,6BAA+BhD,EAAa,gCAAgCmD,cAwUzF,MArUWlD,GAAAvO,UAAA0R,sBAAP,SAA6BC,GACzB,MAAO/R,MAAKgS,YAAYD,IACpB/R,KAAKiS,WAAWF,IAGjBpD,EAAAvO,UAAA8R,aAAP,SAAoBH,GAChB,MAAO/R,MAAK8R,sBAAsBC,IAC9B/R,KAAKmS,aAAaJ,IAGnBpD,EAAAvO,UAAA+R,aAAP,SAAoBJ,GAChB,MAAO/R,MAAKoS,UAAUL,IAClB/R,KAAKqS,OAAON,IACZ/R,KAAKsS,YAAYP,IACjB/R,KAAKuS,UAAUR,IACf/R,KAAKwS,SAAST,IACd/R,KAAKyS,kBAAkBV,IACvB/R,KAAK0S,QAAQX,IACb/R,KAAK2S,aAAaZ,IAClB/R,KAAK4S,YAAYb,IAGlBpD,EAAAvO,UAAAyS,cAAP,SAAqBd,GACjB,MAAO/R,MAAKqS,OAAON,IACf/R,KAAKuS,UAAUR,IACf/R,KAAKwS,SAAST,IACd/R,KAAKyS,kBAAkBV,IACvB/R,KAAK2S,aAAaZ,IAClB/R,KAAK4S,YAAYb,IACjB/R,KAAK8S,qBAAqBf,IAG1BpD,EAAAvO,UAAA0S,qBAAR,SAA6Bf,GACzB,MAAO/R,MAAK+S,cAAchB,IACtB/R,KAAKgT,iBAAiBjB,IACtB/R,KAAKiT,gBAAgBlB,IACrB/R,KAAKkT,yBAAyBnB,IAC9B/R,KAAKmT,oBAAoBpB,IACzB/R,KAAKoT,mBAAmBrB,IAGxBpD,EAAAvO,UAAAgS,UAAR,SAAkBL,GACd,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAK6Q,yBACL7Q,KAAK8Q,2BACL9Q,KAAK+Q,wBACL/Q,KAAKgR,4BAILrC,EAAAvO,UAAAsS,QAAR,SAAgBX,GACZ,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAK2Q,uBACL3Q,KAAK4Q,2BAILjC,EAAAvO,UAAAiS,OAAR,SAAeN,GACX,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAK8P,sBACL9P,KAAK+P,wBACL/P,KAAKgQ,sBACLhQ,KAAKiQ,uBACLjQ,KAAKsQ,yBACLtQ,KAAKuQ,6BAIL5B,EAAAvO,UAAAqS,kBAAR,SAA0BV,GACtB,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAK4P,uBACL5P,KAAK6P,wBACL7P,KAAKkQ,0BACLlQ,KAAKmQ,2BACLnQ,KAAK4R,kDAILjD,EAAAvO,UAAAmS,UAAR,SAAkBR,GACd,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAK0P,yBACL1P,KAAK2P,2BACL3P,KAAK2R,gDAILhD,EAAAvO,UAAAoS,SAAR,SAAiBT,GACb,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAKoQ,wBACLpQ,KAAKqQ,6BAIL1B,EAAAvO,UAAAkS,YAAR,SAAoBP,GAChB,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAKwP,2BACLxP,KAAKyP,+BAILd,EAAAvO,UAAAuS,aAAR,SAAqBZ,GACjB,GAAIuB,GACC3E,EAA0B0E,WAAWtB,GAClC/R,KAAKwQ,sBACLxQ,KAAKyQ,wBACF9B,EAA0B0E,WAAWtB,GAAe/R,KAAK0Q,yBAChE/B,EAA0B0E,WAAWtB,GACjC/R,KAAKqR,4BACLrR,KAAKsR,6BACLtR,KAAKuR,yBACLvR,KAAKwR,2BAIb,KAAK8B,EAAQ,CACT,GAAIC,GAAkB,MAClBC,EAA6BzB,EAAa0B,QAAQF,EAAiB,GACvED,GAAS3E,EAA0B0E,WAAWG,GAC1CxT,KAAKqR,4BAA4BoC,QAAQF,EAAiB,IAC1DvT,KAAKsR,6BAA6BmC,QAAQF,EAAiB,IAC3DvT,KAAKuR,yBAAyBkC,QAAQF,EAAiB,IACvDvT,KAAKwR,0BAA0BiC,QAAQF,EAAiB,MAIhE,MAAOD,IAGH3E,EAAAvO,UAAA4R,YAAR,SAAoBD,GAChB,MAAOpD,GAA0B0E,WAAWtB,GAAe/R,KAAKiR,8BACzDtC,EAA0B0E,WAAWtB,GAAe/R,KAAKkR,mCAAmC,IAG/FvC,EAAAvO,UAAA6R,WAAR,SAAmBF,GACf,MAAOpD,GAA0B0E,WAAWtB,GAAe/R,KAAKmR,6BACzDxC,EAA0B0E,WAAWtB,GAAe/R,KAAKoR,kCAAkC,IAG9FzC,EAAAvO,UAAAwS,YAAR,SAAoBb,GAChB,MAAOpD,GAA0B0E,WAAWtB,GACxC/R,KAAKyR,2BACLzR,KAAK0R,gCAIE/C,EAAA0E,WAAf,SAA0BK,EAAmBC,EAA2BC,GAGpE,IAAK,GAFDC,GAAe,KACfnS,EAAQgS,EAAU7B,cACbzK,EAAI,EAAG0M,EAAMH,EAAgBxS,OAAY2S,EAAJ1M,EAASA,IAAK,CACxD,GAAI2M,GAAgBJ,EAAgBvM,GAAGyK,aACvC,IAAK+B,EAIA,CACD,GAAII,GAAuBtS,EAAMuS,QAAQF,EACzC,IAAIC,EAAuB,GAAI,CAC3B,GAAIE,GAAW,OAAEC,EAAa,MAM9B,IALAD,EAAcC,GAAgB,EAC1BH,EAAuB,EAAI,IAC3BG,EAAgBN,EAAaO,KAAK1S,EAAMsS,EAAuB,KAC/DA,EAAuBD,EAAc5S,OAASO,EAAMP,SACpD+S,EAAcL,EAAaO,KAAK1S,EAAMsS,EAAuBD,EAAc5S,UAC3EgT,GAAiBD,EACjB,OAAO,OAbf,IAAIxS,EAAMuS,QAAQF,GAAiB,GAC/B,OAAO,EAgBnB,OAAO,GAGJpF,EAAAvO,UAAAiU,aAAP,SAAoBX,GAChB,MAAiB,OAAbA,EAEA1T,KAAKiS,WAAWyB,GACT/W,EAAAiS,cAAcO,SACrBnP,KAAKgS,YAAY0B,GACV/W,EAAAiS,cAAcM,UACrBlP,KAAK2S,aAAae,GACX/W,EAAAiS,cAAcS,WACrBrP,KAAKoS,UAAUsB,GACR/W,EAAAiS,cAAcC,QACrB7O,KAAK0S,QAAQgB,GACN/W,EAAAiS,cAAcQ,MACrBpP,KAAKqS,OAAOqB,GACL/W,EAAAiS,cAAcE,KACrB9O,KAAKuS,UAAUmB,GACR/W,EAAAiS,cAAcI,cACrBhP,KAAKwS,SAASkB,GACP/W,EAAAiS,cAAcK,OACrBjP,KAAKyS,kBAAkBiB,GAChB/W,EAAAiS,cAAcU,gBACrBtP,KAAKsS,YAAYoB,GACV/W,EAAAiS,cAAcG,UAClB/O,KAAKsU,oBAAoBZ,GAtBhC,QAyBI/E,EAAAvO,UAAAmU,iBAAR,SAAyBxC,GACrB,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAcsB,yBACdtB,EAAcuB,2BACdvB,EAAcwB,wBACdxB,EAAcyB,4BAIdrC,EAAAvO,UAAAoU,eAAR,SAAuBzC,GACnB,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAcoB,uBACdpB,EAAcqB,2BAIdjC,EAAAvO,UAAA2S,cAAR,SAAsBhB,GAClB,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAcO,sBACdP,EAAcQ,wBACdR,EAAcS,sBACdT,EAAcU,uBACdV,EAAce,yBACdf,EAAcgB,6BAId5B,EAAAvO,UAAA8S,yBAAR,SAAiCnB,GAC7B,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAcK,uBACdL,EAAcM,wBACdN,EAAcW,0BACdX,EAAcY,2BACdZ,EAAcqC,kDAIdjD,EAAAvO,UAAA4S,iBAAR,SAAyBjB,GACrB,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAcG,yBACdH,EAAcI,2BACdJ,EAAcoC,gDAIdhD,EAAAvO,UAAA6S,gBAAR,SAAwBlB,GACpB,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAca,wBACdb,EAAcc,6BAId1B,EAAAvO,UAAAqU,mBAAR,SAA2B1C,GACvB,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAcC,2BACdD,EAAcE,+BAIdd,EAAAvO,UAAA+S,oBAAR,SAA4BpB,GACxB,GAAIuB,GACC3E,EAA0B0E,WAAWtB,GAClCxC,EAAciB,sBACdjB,EAAckB,wBACf9B,EAA0B0E,WAAWtB,GAAe/R,KAAK0Q,yBAC5D/B,EAA0B0E,WAAWtB,GACjCxC,EAAc8B,4BACd9B,EAAc+B,6BACd/B,EAAcgC,yBACdhC,EAAciC,2BAItB,KAAK8B,EAAQ,CACT,GAAIoB,GAAyB,GAAIC,QAAO,IACxCrB,GAAS3E,EAA0B0E,WAAWtB,GAC1CxC,EAAc8B,4BAA4BoC,QAAQiB,EAAwB,IAC1EnF,EAAc+B,6BAA6BmC,QAAQiB,EAAwB,IAC3EnF,EAAcgC,yBAAyBkC,QAAQiB,EAAwB,IACvEnF,EAAciC,0BAA0BiC,QAAQiB,EAAwB,MAIhF,MAAOpB,IAGH3E,EAAAvO,UAAAwU,mBAAR,SAA2B7C,GACvB,MAAOpD,GAA0B0E,WAAWtB,GAAexC,EAAc0B,8BAClEtC,EAA0B0E,WAAWtB,GAAexC,EAAc2B,mCAAmC,IAGxGvC,EAAAvO,UAAAyU,kBAAR,SAA0B9C,GACtB,MAAOpD,GAA0B0E,WAAWtB,GAAexC,EAAc4B,6BAClExC,EAA0B0E,WAAWtB,GAAexC,EAAc6B,kCAAkC,IAGrGzC,EAAAvO,UAAAgT,mBAAV,SAA6BrB,GACzB,MAAOpD,GAA0B0E,WAAWtB,GACxCxC,EAAckC,2BACdlC,EAAcmC,gCAId/C,EAAAvO,UAAAkU,oBAAR,SAA4BZ,GACxB,MAAiB,OAAbA,EAEA1T,KAAK6U,kBAAkBnB,GAChB/W,EAAAiS,cAAcO,SACrBnP,KAAK4U,mBAAmBlB,GACjB/W,EAAAiS,cAAcM,UACrBlP,KAAKmT,oBAAoBO,GAClB/W,EAAAiS,cAAcS,WACrBrP,KAAKuU,iBAAiBb,GACf/W,EAAAiS,cAAcC,QACrB7O,KAAKwU,eAAed,GACb/W,EAAAiS,cAAcQ,MACrBpP,KAAK+S,cAAcW,GACZ/W,EAAAiS,cAAcE,KACrB9O,KAAKgT,iBAAiBU,GACf/W,EAAAiS,cAAcI,cACrBhP,KAAKiT,gBAAgBS,GACd/W,EAAAiS,cAAcK,OACrBjP,KAAKkT,yBAAyBQ,GACvB/W,EAAAiS,cAAcU,gBACrBtP,KAAKyU,mBAAmBf,GACjB/W,EAAAiS,cAAcG,UADzB,OApBA,QAwBRJ,IAlZahS,GAAAgS,0BAAyBA,GAlEnChS,UAAAA,aCEc,mBAAVmY,OAAuB,GAAIA,QAAQ,CCF9C,IAAOnY,UAAP,SAAOA,GAsBH,GAAAoY,GAAA,WAUI,QAAAA,GAAY/G,GAGRhO,KAAK/B,UAAY+P,EAWzB,MArBIpH,QAAAC,eAAWkO,EAAA3U,UAAA,QJiwBPkF,IIjwBJ,WACI,MAAOtF,MAAK/B,WJmwBZ6I,YAAY,EACZC,cAAc,IIlwBlBH,OAAAC,eAAWkO,EAAA3U,UAAA,aJqwBPkF,IIrwBJ,WACI,OAAO,GJuwBPwB,YAAY,EACZC,cAAc,II/vBXgO,EAAA3U,UAAA6M,WAAP,SAAkBC,GACd,GAAI8H,IACAzV,QAAS2N,EAAiB5H,IAAI,uCAC9BgJ,sBAAwBJ,aAAchB,EAAiB5H,IAAI,qCAAsC6I,eAAgBjB,EAAiB5H,IAAI,yCAG1I,OAAO0P,IAEfD,IAxBsBpY,GAAAoY,mBAAkBA,CA0BxC,IAAAE,GAAA,WAII,QAAAA,GAAYC,EAAwBC,GAGhCnV,KAAKkV,eAAiBA,EACtBlV,KAAK+M,cAAgBoI,EA0B7B,MAvBIvO,QAAAC,eAAWoO,EAAA7U,UAAA,QJ8vBPkF,II9vBJ,WACI,MAAO,mBJgwBPwB,YAAY,EACZC,cAAc,II9vBlBH,OAAAC,eAAWoO,EAAA7U,UAAA,aJiwBPkF,IIjwBJ,WACI,OAAO,GJmwBPwB,YAAY,EACZC,cAAc,IIjwBlBH,OAAAC,eAAWoO,EAAA7U,UAAA,aJowBPkF,IIpwBJ,WACI,MAAOtF,MAAK+M,eJswBZjG,YAAY,EACZC,cAAc,IIpwBXkO,EAAA7U,UAAA6M,WAAP,SAAkBC,GAEd,GAAI8H,IACAzV,QAAS,KACT+O,sBACMJ,aAAchB,EAAiB5H,IAAI,gBAAiB6I,eAAgBjB,EAAiB5H,IAAI,gCACzF4I,aAAchB,EAAiB5H,IAAI,yCAA0C6I,eAAgBnO,KAAKkV,eAAezX,aAG3H,OAAOuX,IAEfC,IAlCatY,GAAAsY,gBAAeA,CAoC5B,IAAAG,GAAA,WAAA,QAAAA,MAgBA,MAfIxO,QAAAC,eAAWuO,EAAAhV,UAAA,QJywBPkF,IIzwBJ,WACI,MAAO,wBJ2wBPwB,YAAY,EACZC,cAAc,II1wBlBH,OAAAC,eAAWuO,EAAAhV,UAAA,aJ6wBPkF,II7wBJ,WACI,OAAO,GJ+wBPwB,YAAY,EACZC,cAAc,II7wBXqO,EAAAhV,UAAA6M,WAAP,SAAkBC,GACd,GAAI8H,IACAzV,QAAS,GACT+O,uBAGJ,OAAO0G,IAEfI,IAhBazY,GAAAyY,qBAAoBA,GApF9BzY,UAAAA,YCAP,IAAO8L,WAAP,SAAOA,GASH,GAAc4M,IAAd,SAAcA,GAIV,QAAAC,GAA6BC,EAAaC,GAEtC,IAAK,GADDlC,MACKlM,EAAImO,EAAOpU,OAAS,EAAGiG,GAAK,IAAKA,EACL,KAA7BoO,EAAMvB,QAAQsB,EAAOnO,KACrBkM,EAAO3Q,KAAK4S,EAAOnO,GAG3B,OAAOkM,GAMX,QAAAmC,GAAwBF,EAAaC,GAEjC,IAAK,GADDlC,MACKlM,EAAImO,EAAOpU,OAAS,EAAGiG,GAAK,IAAKA,EAAG,CACzC,GAAI1F,GAAW6T,EAAOnO,EACO,MAAzBoO,EAAMvB,QAAQvS,IACd4R,EAAO3Q,KAAKjB,GAGpB,MAAO4R,GAMX,QAAAoC,GAA4BvW,GAExB,IAAK,GADDmU,MACKlM,EAAI,EAAG0M,EAAM3U,EAAOgC,OAAY2S,EAAJ1M,EAASA,IAAK,CAC/C,GAAI1F,GAAWvC,EAAOiI,EACQ,MAA1BkM,EAAOW,QAAQvS,IACf4R,EAAO3Q,KAAKjB,GAGpB,MAAO4R,GAOX,QAAAqC,GAAyBJ,EAAapW,GAClC,IAAK,GAAIiI,GAAI,EAAG0M,EAAM3U,EAAOgC,OAAY2S,EAAJ1M,IAAWA,EAC5CwO,EAAYL,EAAQpW,EAAOiI,IAOnC,QAAAwO,GAA+BL,EAAa7T,GACpC6T,EAAOtB,QAAQvS,GAAS,GACxB6T,EAAO5S,KAAKjB,GAQpB,QAAAmU,GAAyB1W,EAAa2W,EAAoBC,GAKtD,IAAK,GADDzC,MACKlM,EAAI0O,EAAiBC,GAAL3O,IAAiBA,EACtCkM,EAAO3Q,KAAKxD,EAAOiI,GAEvB,OAAOkM,GAMX,QAAA0C,GAAwB7W,EAAa8W,GAKjC,IAAK,GADD3C,MACKlM,EAAI,EAAO6O,EAAJ7O,IAAaA,EACzBkM,EAAO3Q,KAAKxD,EAAOiI,GAEvB,OAAOkM,GAGX,QAAA4C,GAAwB/W,GAGpB,MAAO6W,GAAK7W,EAAQA,EAAOgC,QAM/B,QAAAgV,GAAiCC,EAAWC,EAAYC,GAGpD,GAAIF,IAASC,EACT,OAAO,CAGX,MAAMD,KAAWC,EACb,OAAO,CAGX,IAAIvC,GAAMsC,EAAKjV,MACf,IAAI2S,IAAQuC,EAAMlV,OACd,OAAO,CAIX,KADA,GAAIiG,GAAI,EACG0M,EAAJ1M,GAAWkP,EAAWF,EAAKhP,GAAIiP,EAAMjP,OACtCA,CAGN,OAAOA,KAAM0M,EAOjB,QAAAyC,GAA+BC,GAC3B,MAAIA,IAA0B,IAAjBA,EAAMrV,OACR,KAEJqV,EAGX,QAAAvC,GAA2BuC,EAAYC,GAInC,IAAK,GAAIrP,GAAI,EAAG0M,EAAM0C,EAAMrV,OAAY2S,EAAJ1M,IAAWA,EAC3C,GAAIqP,EAAUD,EAAMpP,IAChB,MAAOA,EAGf,OAAO,GAMX,QAAAsP,GAA0BF,EAAYG,GAClC,GAAe,IAAXA,EACA,MAAOH,GAAMI,OAEjB,IAAIC,GAAUL,EAAMI,MAAMD,EAG1B,OAFAG,OAAM1W,UAAUuC,KAAKoU,MAAMF,EAASL,EAAMI,MAAM,EAAGD,IAE5CE,EAGX,QAAAG,KACI,MAAOC,OAGX,QAAAA,GAAgCT,GAG5B,GAAIU,GAAiCV,CAGrC,OAFAU,GAASC,OAASA,EAEXD,EAMX,QAAAE,GAA8BZ,EAAY/X,GACtC,IAAK,GAAI2I,GAAI,EAAG0M,EAAM0C,EAAMrV,OAAY2S,EAAJ1M,EAASA,IAAK,CAC9C,GAAIiQ,GAAOb,EAAMpP,EACjB,IAAUiQ,EAAM5Y,KAAOA,EACnB,MAAO4Y,IAInB,QAAAF,GAAmB1Y,GACf,MAAO4W,GAAgB+B,WAAcpX,KAAMvB,GAG/C,QAAA6Y,KACI,MAAOC,OAGX,QAAAA,GAAkCf,GAG9B,GAAIU,GAAoCV,CAGxC,OAFAU,GAASM,SAAWA,EAEbN,EAGX,QAAAO,GAAoCjB,EAAY7Y,GAC5C,GAAIsF,GAAQyU,EAAclB,EAAO7Y,EACjC,OAAIsF,IAAS,EACFuT,EAAMvT,GADjB,OAIJ,QAAAyU,GAAiClB,EAAY7Y,GACzC,IAAK,GAAIyJ,GAAI,EAAG0M,EAAM0C,EAAMrV,OAAY2S,EAAJ1M,EAASA,IAAK,CAC9C,GAAIiQ,GAAOb,EAAMpP,EACjB,IAAUiQ,EAAM1Z,OAASA,EACrB,MAAOyJ,GAGf,MAAO,GAOX,QAAAuQ,GAA6B/U,EAAgBlB,GAOzC,IAAK,GAHDoS,GAAMlR,EAAKzB,OAGNiG,EAAI0M,EAAM,EAAG1M,GAAK,EAAGA,IAAK,CAC/B,GAAIwQ,GAAOhV,EAAKwE,GAAK1F,CAErB,IAAa,IAATkW,EACA,OAAO,CAEX,MAAIA,EAAO,GAKX,MADAhV,GAAKiV,OAAOzQ,EAAI,EAAG,EAAG1F,IACf,EAIX,MADAkB,GAAKkV,QAAQpW,IACN,EAOX,QAAAqW,GAA+BnV,EAAWlB,GACtC,GAAIuB,GAAQL,EAAKqR,QAAQvS,EACzB,OAAY,GAARuB,GACO,GAEXL,EAAKiV,OAAO5U,EAAO,IAEZ,GAMX,QAAAuU,GAAqB7Z,GACjB,GAAI6Y,GAAaxW,IACjB,OAAOyX,GAAiBjB,EAAO7Y,GAMnC,QAAAyD,GAAsBoV,GAClB,GAAKA,EAGL,KAAOA,EAAMrV,OAAS,GAClBqV,EAAMwB,MAGd,QAAAC,GAAmCzB,GAC/B,OAAKA,GAA0B,IAAjBA,EAAMrV,OAMxB,QAAA+W,GAAwB1B,EAAY2B,EAAoBC,GACpD,GAAIC,GAAO7B,EAAM2B,EACjB3B,GAAM2B,GAAc3B,EAAM4B,GAC1B5B,EAAM4B,GAAeC,EAGzB,QAAAC,GAA6B9B,EAAY+B,EAAeC,GACpD,MAAOxW,GAAEyW,IAAIjC,EAAO,SAAAa,GAAQ,MAAAmB,GAAgBnB,EAAMkB,KAItD,QAAAG,GAAwCC,GAIpC,IADA,GAAIC,GAAgBD,EACI,MAAjBC,GAAuB,CAC1B,GAAI5W,EAAE6W,QAAQD,GACV,OAAO,CAEXA,GAAgBhS,OAAOkS,eAAeF,GAG1C,OAAO,EA/SKvD,EAAAC,UAASA,EAaTD,EAAAI,KAAIA,EAcJJ,EAAAK,SAAQA,EAeRL,EAAAM,MAAKA,EASLN,EAAAO,YAAWA,EAUXP,EAAAQ,MAAKA,EAcLR,EAAAW,KAAIA,EAWJX,EAAAa,KAAIA,EASJb,EAAAc,cAAaA,EA4Bbd,EAAAkB,YAAWA,EAOXlB,EAAApB,QAAOA,EAePoB,EAAAqB,OAAMA,EAUNrB,EAAA2B,aAAYA,EAIZ3B,EAAA4B,aAAYA,EAYZ5B,EAAA+B,WAAUA,EAYV/B,EAAAiC,eAAcA,EAIdjC,EAAAkC,eAAcA,EASdlC,EAAAoC,iBAAgBA,EAMhBpC,EAAAqC,cAAaA,EAcbrC,EAAAsC,aAAYA,EA6BZtC,EAAA0C,YAAWA,EAqBX1C,EAAAjU,MAAKA,EAQLiU,EAAA4C,mBAAkBA,EAOlB5C,EAAA6C,KAAIA,EAMJ7C,EAAAiD,UAASA,EAKTjD,EAAAqD,wBAAuBA,GAxS7BrD,EAAA5M,EAAA4M,kBAAA5M,EAAA4M,sBATX5M,WAAAA,aCAP,IAAOsQ,OAAP,SAAOA,GACH,GAAcC,IAAd,SAAcA,GAEV,QAAAC,KACI,MAAOC,GAAE,UAGb,QAAAC,KACI,MAAOD,GAAE,WAGb,QAAAE,KACI,MAAOF,GAAE,4BAGb,QAAAG,KACI,MAAOH,GAAE,SAGb,QAAAI,KACI,MAAOJ,GAAE,SAGb,QAAAK,KACI,MAAOL,GAAE,0BAGb,QAAA7Y,KACI,MAAO6Y,GAAE,aAGb,QAAAM,KACI,MAAON,GAAE,wBAGb,QAAAO,KACI,MAAOP,GAAE,UAGb,QAAAQ,KACI,MAAOR,GAAE,aArCGF,EAAAC,IAAGA,EAIHD,EAAAG,KAAIA,EAIJH,EAAAI,SAAQA,EAIRJ,EAAAK,GAAEA,EAIFL,EAAAM,GAAEA,EAIFN,EAAAO,OAAMA,EAINP,EAAA3Y,OAAMA,EAIN2Y,EAAAQ,QAAOA,EAIPR,EAAAS,IAAGA,EAIHT,EAAAU,OAAMA,GAtCZV,EAAAD,EAAAC,aAAAD,EAAAC,iBADXD,OAAAA,SCAP,IAAOpc,UAAP,SAAOA,GAwcH,QAAAgd,GAAsBjY,EAAekY,GACjC,MAAiB1b,UAAVwD,EAAsBA,EAAQkY,EAnczC,GAAcC,IAAd,SAAcA,GA2BV,QAAAC,GAAsBC,GAIlB,MAAIA,IAAO,EACHA,EAAMF,EAAOG,gBAAgB7Y,OACtB0Y,EAAOG,gBAAgBD,GAEvBE,EAAAA,GAIfF,GAAOA,EACHA,EAAM,GAAKA,EAAMF,EAAOK,gBAAgB/Y,OACjC0Y,EAAOK,gBAAgBH,GAEvB,GASf,QAAAI,GAAsB5L,GAIlB,GAAIA,EAAM,GAAW,KAANA,EACX,MAAU,KAANA,EACU,IAANA,EACU,IAANA,EACU,GAANA,EACO,EAEA,EAGD,IAANA,EACO,EAEA,EAIL,IAANA,EACU,IAANA,EACO,EAEA,EAGD,IAANA,EACO,EAEA,EAKT,KAANA,EACU,KAANA,EACU,IAANA,EACO,EAEA,EAGD,KAANA,EACO,GAEA,GAIL,KAANA,EACU,KAANA,EACO,GAEA,GAGD,KAANA,EACO,GAEA,EAO3B,IAAIA,EAAM,OAAe,EAANA,EACf,MAAU,MAANA,EACU,MAANA,EACU,MAANA,EACU,MAANA,EACO,IAEA,IAGD,MAANA,EACO,IAEA,IAIL,MAANA,EACU,MAANA,EACO,IAEA,IAGD,KAANA,EACO,IAEA,GAKT,KAANA,EACU,KAANA,EACU,KAANA,EACO,GAEA,GAGD,KAANA,EACO,GAEA,GAIL,IAANA,EACU,KAANA,EACO,GAEA,GAGD,GAANA,EACO,GAEA,EAQ3B,IAAI4L,GAAQ5c,KAAK6c,IAAI7L,GAAOsL,EAAOQ,QACnC,OAAOR,GAAOS,mBAAmBH,GASrC,QAAAI,GAA6BC,EAAWC,GAMpC,GALsBvc,SAAlBuc,IACAA,EAAgBZ,EAAOa,qCAItBF,EAAL,CAIA,GAAIT,GAAMF,EAAOM,MAAM5c,KAAKod,IAAIH,GAEhC,IAAIT,EAAMF,EAAOe,QACb,MAAO,EAEX,IAAIC,GAAetd,KAAKud,IAAIf,EAAMU,GAAgBZ,EAAOK,gBAAgB/Y,OAAS,EAClF,OAAO0Y,GAAOC,MAAMe,IASxB,QAAAE,GAAmCP,EAAWQ,EAAWC,GAIrD,MAHAA,GAAYtB,EAAasB,EAAWpB,EAAOqB,mBAGpCV,IAAMQ,GAAKzd,KAAKod,IAAIH,EAAIQ,GAAKC,EAUxC,QAAAE,GAAkCX,EAAWQ,EAAWC,GAIpD,MAHAA,GAAYtB,EAAasB,EAAWpB,EAAOqB,mBAGhCF,EAAJR,GAASjd,KAAKod,IAAIH,EAAIQ,GAAKC,EAUtC,QAAAG,GAAyCZ,EAAWQ,EAAWC,GAI3D,MAHAA,GAAYtB,EAAasB,EAAWpB,EAAOqB,mBAGhCF,EAAJR,GAASjd,KAAKod,IAAIH,EAAIQ,GAAKC,EAUtC,QAAAI,GAAqCb,EAAWQ,EAAWC,GAIvD,MAHAA,GAAYtB,EAAasB,EAAWpB,EAAOqB,mBAGpCV,EAAIQ,GAAKzd,KAAKod,IAAIH,EAAIQ,GAAKC,EAUtC,QAAAK,GAA4Cd,EAAWQ,EAAWC,GAI9D,MAHAA,GAAYtB,EAAasB,EAAWpB,EAAOqB,mBAGpCV,EAAIQ,GAAKzd,KAAKod,IAAIH,EAAIQ,GAAKC,EAQtC,QAAAX,GAAmCE,EAAWS,GAC1CA,EAAYtB,EAAasB,EAAWpB,EAAOqB,kBAG3C,IAAIK,GAAShe,KAAKie,MAAMhB,EACxB,OAAIjd,MAAKod,IAAIH,EAAIe,GAAUN,EAChBM,EAEAhe,KAAKke,MAAMjB,GAS1B,QAAAkB,GAAkClB,EAAWS,GACzCA,EAAYtB,EAAasB,EAAWpB,EAAOqB,kBAG3C,IAAIK,GAAShe,KAAKie,MAAMhB,EACxB,OAAIjd,MAAKod,IAAIH,EAAIe,GAAUN,EAChBM,EAEAhe,KAAKoe,KAAKnB,GAUzB,QAAAoB,GAAiCpB,EAAWS,GAGxC,MAFAA,GAAYtB,EAAasB,EAAWpB,EAAOqB,mBAEzB,IAAdD,GAAyB,IAANT,EACZA,EAGJjd,KAAKke,MAAMjB,EAAIS,GAAaA,EASvC,QAAAY,GAAgCrB,EAAWS,GAGvC,MAFAA,GAAYtB,EAAasB,EAAWpB,EAAOqB,mBAEzB,IAAdD,GAAyB,IAANT,EACZA,EAGJjd,KAAKoe,KAAKnB,EAAIS,GAAaA,EAStC,QAAAa,GAAiCtB,EAAWS,GAGxC,GAFAA,EAAYtB,EAAasB,EAAWpB,EAAOqB,mBAEzB,IAAdD,GAAyB,IAANT,EACnB,MAAOA,EAGX,IAAIlH,GAAS/V,KAAKie,MAAMhB,EAAIS,GAAaA,EACrCR,EAAgBld,KAAKie,MAAM3B,EAAOM,MAAM5c,KAAKod,IAAIH,IAAMX,EAAOM,MAAMc,IAAc,CAKtF,OAJIR,GAAgB,GAAqB,GAAhBA,IACrBnH,EAASyI,WAAWzI,EAAO0I,YAAYvB,KAGpCnH,EASX,QAAA2I,GAA8BzB,EAAW0B,EAAapB,GAElD,MAAU5c,UAANsc,GAAyB,OAANA,EACZA,EAEH0B,EAAJ1B,EACO0B,EAEP1B,EAAIM,EACGA,EAEJN,EAOX,QAAAgB,GAAsBhB,GAGlB,MAAQ,GAAMA,GAAM,EAUxB,QAAA2B,GAAwBza,EAAe0a,EAAiBC,EAAkBC,EAAeC,GACrF,GAAiB,IAAbF,GAA6B,IAAXE,EAClB,MAAe7a,IAAX0a,GAA6BA,EAAUC,GAAnB3a,EACb4a,EAEAE,GAGf,IAAIC,IAAa/a,EAAQ0a,GAAWC,EAChCK,EAAaJ,EAAQG,EAAYF,CACrC,OAAOG,GAOX,QAAAC,GAAmCjb,GAC/B,MAAOoa,GAAiBpa,EAAO6Y,EAAa7Y,IAOhD,QAAAkb,GAA0Blb,GACtB,MAAiB,QAAVA,GAAkBA,EAAQ,IAAM,EAW3C,QAAAmb,GAA4Bnb,EAAeob,GACvC,MAAOvf,MAAKie,MAAM9Z,EAAQob,GAAaA,EA3b9BjD,EAAAkD,WAAaC,OAAOC,UACpBpD,EAAAoD,UAAYD,OAAOC,UACnBpD,EAAAe,QAAU,KACVf,EAAAqD,QAAU,IACVrD,EAAAsD,QAAU,OACVtD,EAAAqB,kBAAoB,KACpBrB,EAAAa,oCAAsC,GACtCb,EAAAQ,SAAW9c,KAAK6c,IAAI,IACpBP,EAAAG,iBACT,EAAK,GAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KACxkB,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACrrB,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACrrB,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,OAC/CH,EAAAK,iBACT,EAAK,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAC1qB,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OACxxB,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OACxxB,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ,OAAQ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","file":"powerbi-visuals.min.js","sourcesContent":["/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export enum VisualDataRoleKind {\r\n /** Indicates that the role should be bound to something that evaluates to a grouping of values. */\r\n Grouping,\r\n /** Indicates that the role should be bound to something that evaluates to a single value in a scope. */\r\n Measure,\r\n /** Indicates that the role can be bound to either Grouping or Measure. */\r\n GroupingOrMeasure,\r\n }\r\n\r\n export enum VisualDataChangeOperationKind {\r\n Create = 0,\r\n Append = 1,\r\n }\r\n\r\n export enum VisualUpdateType {\r\n Data = 1 << 1,\r\n Resize = 1 << 2,\r\n ViewMode = 1 << 3,\r\n Style = 1 << 4,\r\n ResizeEnd = 1 << 5,\r\n }\r\n\r\n export enum VisualPermissions {\r\n\r\n }\r\n\r\n export const enum CartesianRoleKind {\r\n X,\r\n Y,\r\n }\r\n\r\n export const enum ViewMode {\r\n View = 0,\r\n Edit = 1,\r\n }\r\n\r\n export const enum ResizeMode {\r\n Resizing = 1,\r\n Resized = 2,\r\n }\r\n\r\n export module visuals.telemetry {\r\n export const enum TelemetryCategory {\r\n Verbose,\r\n CustomerAction,\r\n CriticalError,\r\n Trace,\r\n }\r\n\r\n export enum ErrorSource {\r\n PowerBI = 0,\r\n External = 1,\r\n User = 2,\r\n }\r\n }\r\n\r\n export const enum JoinPredicateBehavior {\r\n /** Prevent items in this role from acting as join predicates. */\r\n None,\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.telemetry {\r\n /**\r\n * Creates a client-side Guid string.\r\n * @returns A string representation of a Guid.\r\n */\r\n export function generateGuid(): string {\r\n let guid = \"\",\r\n idx = 0;\r\n\r\n for (idx = 0; idx < 32; idx += 1) {\r\n let guidDigitsItem = Math.random() * 16 | 0;\r\n switch (idx) {\r\n case 8:\r\n case 12:\r\n case 16:\r\n case 20:\r\n guid += \"-\";\r\n break;\r\n }\r\n guid += guidDigitsItem.toString(16);\r\n }\r\n\r\n return guid;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.telemetry {\r\n\r\n /**\r\n * Event fired when a visual is loaded through the visual adapter\r\n * @param name Name (guid) of the visual. \r\n * @param apiVersion Api version used by the visual. \r\n * @param custom Is the visual custom? \r\n * @param parentId Id of the parent event \r\n * @param isError True - action failed. \r\n * @param errorSource Source of the error. PowerBI = PowerBI has a problem, External = External Service (e.g. on-prem AS server is down), User = User error (e.g. uploading too much and hitting resource limitations. \r\n * @param errorCode PowerBI Error Code \r\n *\r\n * Generated by: Extensibility/events.bond\r\n */\r\n\r\n export declare var ExtensibilityVisualApiUsageLoggers: number;\r\n\r\n export var ExtensibilityVisualApiUsage = function(name: string, apiVersion: string, custom: boolean, parentId: string, isError: boolean = false, errorSource: ErrorSource = undefined, errorCode: string = undefined): ITelemetryEventI<IPBIExtensibilityVisualApiUsage> {\r\n var info = {\r\n name: name,\r\n apiVersion: apiVersion,\r\n custom: custom,\r\n parentId: parentId,\r\n isError: isError,\r\n errorSource: errorSource,\r\n errorCode: errorCode,\r\n };\r\n\r\n var event: ITelemetryEventI<IPBIExtensibilityVisualApiUsage> = {\r\n name: 'PBI.Extensibility.VisualApiUsage',\r\n category: TelemetryCategory.CustomerAction,\r\n time: Date.now(),\r\n id: generateGuid(),\r\n getFormattedInfoObject: function() {\r\n var formattedObject = {\r\n name: info.name,\r\n apiVersion: info.apiVersion,\r\n custom: info.custom,\r\n parentId: info.parentId,\r\n isError: info.isError,\r\n };\r\n if (typeof info.errorSource !== 'undefined') {\r\n formattedObject['errorSource'] = ErrorSource[info.errorSource];\r\n }\r\n if (typeof info.errorCode !== 'undefined') {\r\n formattedObject['errorCode'] = info.errorCode;\r\n }\r\n return formattedObject;\r\n },\r\n info: info,\r\n privateFields: [],\r\n orgInfoFields: []\r\n };\r\n\r\n if (typeof ExtensibilityVisualApiUsageLoggers !== 'undefined') {\r\n event.loggers = ExtensibilityVisualApiUsageLoggers;\r\n }\r\n\r\n return event;\r\n };\r\n\r\n /**\r\n * Event fired for uncaught exception in IVisual.\r\n * @param visualType Type of the visual. \r\n * @param isCustom Is the visual custom? \r\n * @param apiVersion Api version used by the visual \r\n * @param source Source URL \r\n * @param lineNumber Line number \r\n * @param columnNumber Column number \r\n * @param stack Stack trace \r\n * @param message Error exception message. \r\n *\r\n * Generated by JsCommon/commonTelemetryEvents.bond\r\n */\r\n\r\n export declare var VisualExceptionLoggers: number;\r\n\r\n export var VisualException = function(visualType: string, isCustom: boolean, apiVersion: string, source: string, lineNumber: number, columnNumber: number, stack: string, message: string): ITelemetryEventI<IPBIVisualException> {\r\n var info = {\r\n visualType: visualType,\r\n isCustom: isCustom,\r\n apiVersion: apiVersion,\r\n source: source,\r\n lineNumber: lineNumber,\r\n columnNumber: columnNumber,\r\n stack: stack,\r\n message: message,\r\n };\r\n\r\n var event: ITelemetryEventI<IPBIVisualException> = {\r\n name: 'PBI.VisualException',\r\n category: TelemetryCategory.CriticalError,\r\n time: Date.now(),\r\n id: generateGuid(),\r\n getFormattedInfoObject: function() {\r\n var formattedObject = {\r\n visualType: info.visualType,\r\n isCustom: info.isCustom,\r\n apiVersion: info.apiVersion,\r\n source: info.source,\r\n lineNumber: info.lineNumber,\r\n columnNumber: info.columnNumber,\r\n stack: info.stack,\r\n message: info.message,\r\n };\r\n return formattedObject;\r\n },\r\n info: info,\r\n privateFields: [],\r\n orgInfoFields: []\r\n };\r\n\r\n if (typeof VisualExceptionLoggers !== 'undefined') {\r\n event.loggers = VisualExceptionLoggers;\r\n }\r\n\r\n return event;\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.extensibility {\r\n export function VisualPlugin(options: IVisualPluginOptions): ClassDecorator {\r\n return function (constructor: IVisualConstructor): void {\r\n constructor.__capabilities__ = options.capabilities;\r\n };\r\n }\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.extensibility {\r\n import IPoint = visuals.IPoint;\r\n\r\n export interface SelectionManagerOptions{\r\n hostServices: IVisualHostServices;\r\n };\r\n\r\n export class SelectionManager implements ISelectionManager {\r\n private selectedIds: ISelectionId[];\r\n private hostServices: IVisualHostServices;\r\n private promiseFactory: IPromiseFactory;\r\n\r\n public constructor(options: SelectionManagerOptions) {\r\n this.hostServices = options.hostServices;\r\n this.selectedIds = [];\r\n this.promiseFactory = this.hostServices.promiseFactory();\r\n }\r\n \r\n public select(selectionId: ISelectionId, multiSelect: boolean = false): IPromise<ISelectionId[]> {\r\n let deferred: IDeferred<data.Selector[]> = this.promiseFactory.defer();\r\n \r\n if (this.hostServices.shouldRetainSelection()) {\r\n this.sendSelectionToHost([selectionId]);\r\n }\r\n else {\r\n this.selectInternal(selectionId, multiSelect);\r\n this.sendSelectionToHost(this.selectedIds);\r\n }\r\n\r\n deferred.resolve(this.selectedIds);\r\n return deferred.promise;\r\n }\r\n\r\n public showContextMenu(selectionId: ISelectionId, position: IPoint): IPromise<{}> {\r\n let deferred: IDeferred<{}> = this.promiseFactory.defer();\r\n\r\n this.sendContextMenuToHost(selectionId, position);\r\n\r\n deferred.resolve(null);\r\n return deferred.promise;\r\n }\r\n\r\n public hasSelection(): boolean {\r\n return this.selectedIds.length > 0;\r\n }\r\n\r\n public clear(): IPromise<{}> {\r\n let deferred = this.promiseFactory.defer();\r\n this.selectedIds = [];\r\n this.sendSelectionToHost([]);\r\n deferred.resolve(null);\r\n return deferred.promise;\r\n }\r\n\r\n public getSelectionIds(): ISelectionId[] {\r\n return this.selectedIds;\r\n }\r\n\r\n private sendSelectionToHost(ids: ISelectionId[]) {\r\n let selectArgs: SelectEventArgs = {\r\n data: ids\r\n .filter((value: ISelectionId) => (<visuals.SelectionId>value).hasIdentity())\r\n .map((value: ISelectionId) => (<visuals.SelectionId>value).getSelector())\r\n };\r\n\r\n let data2 = this.getSelectorsByColumn(ids);\r\n\r\n if (!_.isEmpty(data2))\r\n selectArgs.data2 = data2;\r\n\r\n this.hostServices.onSelect(selectArgs);\r\n }\r\n\r\n private sendContextMenuToHost(selectionId: ISelectionId, position: IPoint): void {\r\n let selectors = this.getSelectorsByColumn([selectionId]);\r\n if (_.isEmpty(selectors))\r\n return;\r\n\r\n let args: ContextMenuArgs = {\r\n data: selectors,\r\n position: position\r\n };\r\n\r\n this.hostServices.onContextMenu(args);\r\n }\r\n\r\n private getSelectorsByColumn(selectionIds: ISelectionId[]): SelectorsByColumn[] {\r\n return _(selectionIds)\r\n .filter(value => (<visuals.SelectionId>value).hasIdentity)\r\n .map(value => (<visuals.SelectionId>value).getSelectorsByColumn())\r\n .compact()\r\n .value();\r\n }\r\n\r\n private selectInternal(selectionId: ISelectionId, multiSelect: boolean) {\r\n if (SelectionManager.containsSelection(this.selectedIds, selectionId)) {\r\n this.selectedIds = multiSelect\r\n ? this.selectedIds.filter(d => !(<visuals.SelectionId>selectionId).equals(<visuals.SelectionId>d))\r\n : this.selectedIds.length > 1\r\n ? [selectionId] : [];\r\n } else {\r\n if (multiSelect)\r\n this.selectedIds.push(selectionId);\r\n else\r\n this.selectedIds = [selectionId];\r\n }\r\n }\r\n\r\n public static containsSelection(list: ISelectionId[], id: ISelectionId) {\r\n return list.some(d => (<visuals.SelectionId>id).equals(<visuals.SelectionId>d));\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.extensibility {\r\n /**\r\n * This class is designed to simplify the creation of SelectionId objects\r\n * It allows chaining to build up an object before calling 'create' to build a SelectionId\r\n */\r\n export class SelectionIdBuilder implements ISelectionIdBuilder {\r\n private dataMap: SelectorForColumn;\r\n private measure: string;\r\n\r\n public withCategory(categoryColumn: DataViewCategoryColumn, index: number): this{\r\n if (categoryColumn && categoryColumn.source && categoryColumn.source.queryName && categoryColumn.identity)\r\n this.ensureDataMap()[categoryColumn.source.queryName] = categoryColumn.identity[index];\r\n \r\n return this;\r\n }\r\n\r\n public withSeries(seriesColumn: DataViewValueColumns, valueColumn: DataViewValueColumn | DataViewValueColumnGroup): this {\r\n if (seriesColumn && seriesColumn.source && seriesColumn.source.queryName && valueColumn)\r\n this.ensureDataMap()[seriesColumn.source.queryName] = valueColumn.identity;\r\n\r\n return this;\r\n }\r\n\r\n public withMeasure(measureId: string): this {\r\n this.measure = measureId;\r\n\r\n return this;\r\n }\r\n\r\n public createSelectionId(): ISelectionId {\r\n return visuals.SelectionId.createWithSelectorForColumnAndMeasure(this.ensureDataMap(), this.measure);\r\n }\r\n\r\n private ensureDataMap(): SelectorForColumn {\r\n if (!this.dataMap)\r\n this.dataMap = {};\r\n\r\n return this.dataMap;\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.extensibility {\r\n\r\n import ITelemetryService = visuals.telemetry.ITelemetryService;\r\n import ExtensibilityVisualApiUsage = visuals.telemetry.ExtensibilityVisualApiUsage;\r\n import VisualTelemetryInfo = visuals.telemetry.VisualTelemetryInfo;\r\n\r\n //TODO: refactor this into a service\r\n export let visualApiVersions: VisualVersion[] = [];\r\n\r\n export function createVisualAdapter(visualPlugin: IVisualPlugin, telemetryService?: powerbi.ITelemetryService | ITelemetryService): powerbi.IVisual {\r\n let visualTelemetryInfo: VisualTelemetryInfo = {\r\n name: visualPlugin.name,\r\n apiVersion: visualPlugin.apiVersion,\r\n custom: !!visualPlugin.custom\r\n };\r\n return new VisualSafeExecutionWrapper(new VisualAdapter(visualPlugin, <ITelemetryService>telemetryService), visualTelemetryInfo, <ITelemetryService>telemetryService);\r\n }\r\n\r\n export class VisualAdapter implements powerbi.IVisual, WrappedVisual {\r\n private visual: powerbi.IVisual | powerbi.extensibility.IVisual;\r\n private apiVersionIndex: number;\r\n private plugin: powerbi.IVisualPlugin;\r\n private telemetryService: ITelemetryService;\r\n private legacy: boolean;\r\n\r\n constructor(visualPlugin: IVisualPlugin, telemetryService?: ITelemetryService) {\r\n this.telemetryService = telemetryService;\r\n this.plugin = visualPlugin;\r\n\r\n let version = visualPlugin.apiVersion;\r\n let versionIndex = this.getVersionIndex(version);\r\n let isError = false;\r\n\r\n if (!version) {\r\n this.legacy = true;\r\n }\r\n else if (versionIndex > -1) {\r\n this.apiVersionIndex = versionIndex;\r\n this.legacy = false;\r\n }\r\n else {\r\n debug.assertFail(\"The API version '\" + version + \"' is invalid.\");\r\n isError = true;\r\n }\r\n\r\n if (this.telemetryService) {\r\n this.telemetryService.logEvent(\r\n ExtensibilityVisualApiUsage,\r\n this.plugin.name,\r\n this.plugin.apiVersion,\r\n !!this.plugin.custom,\r\n undefined,\r\n isError,\r\n visuals.telemetry.ErrorSource.User\r\n );\r\n }\r\n }\r\n\r\n public init(options: powerbi.VisualInitOptions) {\r\n debug.assertValue(options.element, \"options.element\");\r\n debug.assertValue(options.host, \"options.host\");\r\n\r\n options.element.empty();\r\n\r\n if (this.legacy) {\r\n this.visual = this.plugin.create();\r\n this.visualLegacy.init(options);\r\n }\r\n else {\r\n let host = visualApiVersions[this.apiVersionIndex].hostAdapter(options.host);\r\n this.visual = this.plugin.create({\r\n element: options.element.get(0),\r\n host: host\r\n });\r\n this.overloadMethods();\r\n }\r\n }\r\n\r\n public update(options: powerbi.VisualUpdateOptions): void {\r\n if (options.type & VisualUpdateType.Resize && this.visualHasMethod('onResizing')) {\r\n this.onResizing(options.viewport, options.resizeMode);\r\n } else if (this.visualHasMethod('update')) {\r\n this.visualLegacy.update(options);\r\n } else {\r\n if (!options.type || options.type & VisualUpdateType.Data) {\r\n this.onDataChanged(<VisualDataChangedOptions>_.pick(options, ['dataViews', 'operationKind']));\r\n }\r\n if (options.type & VisualUpdateType.ViewMode) {\r\n this.onViewModeChanged(options.viewMode);\r\n }\r\n }\r\n }\r\n\r\n public destroy(): void {\r\n if (this.visualHasMethod('destroy')) {\r\n this.visualLegacy.destroy();\r\n }\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n if (!this.visualHasMethod('enumerateObjectInstances')) {\r\n return;\r\n }\r\n return this.visualLegacy.enumerateObjectInstances(options);\r\n }\r\n\r\n public enumerateObjectRepetition(): VisualObjectRepetition[] {\r\n if (!this.visualHasMethod('enumerateObjectRepetition')) {\r\n return;\r\n }\r\n return this.visualLegacy.enumerateObjectRepetition();\r\n }\r\n\r\n public onResizing(finalViewport: IViewport, resizeMode: ResizeMode): void {\r\n if (this.visualHasMethod('onResizing')) {\r\n this.visualLegacy.onResizing(finalViewport, resizeMode);\r\n }\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n if (this.visualHasMethod('onDataChanged')) {\r\n this.visualLegacy.onDataChanged(options);\r\n }\r\n }\r\n\r\n public onViewModeChanged(viewMode: ViewMode): void {\r\n if (this.visualHasMethod('onViewModeChanged')) {\r\n this.visualLegacy.onViewModeChanged(viewMode);\r\n }\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.visualHasMethod('onClearSelection')) {\r\n this.visualLegacy.onClearSelection();\r\n }\r\n }\r\n\r\n public canResizeTo(viewport: IViewport): boolean {\r\n if (this.visualHasMethod('canResizeTo')) {\r\n return this.visualLegacy.canResizeTo(viewport);\r\n }\r\n }\r\n\r\n public unwrap(): powerbi.IVisual {\r\n return <powerbi.IVisual>this.visual;\r\n }\r\n\r\n private get visualNew(): powerbi.extensibility.IVisual {\r\n if (this.legacy) return;\r\n return <powerbi.extensibility.IVisual>this.visual;\r\n }\r\n\r\n private get visualLegacy(): powerbi.IVisual {\r\n if (!this.legacy) return;\r\n return <powerbi.IVisual>this.visual;\r\n }\r\n\r\n private visualHasMethod(methodName: string): boolean {\r\n let visual = this.legacy ? this.visualLegacy : this.visualNew;\r\n return visual && _.isFunction(visual[methodName]);\r\n }\r\n\r\n private getVersionIndex(version: string): number {\r\n if (version) {\r\n let versionCount = extensibility.visualApiVersions.length;\r\n for (let i = 0; i < versionCount; i++) {\r\n if (extensibility.visualApiVersions[i].version === version) {\r\n return i;\r\n }\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n private overloadMethods(): void {\r\n let overloads = this.getCompiledOverloads();\r\n for (let key in overloads) {\r\n this[key] = overloads[key];\r\n }\r\n }\r\n\r\n private getCompiledOverloads(): VisualVersionOverloads {\r\n let overloads: VisualVersionOverloads = {};\r\n let versionIndex = this.apiVersionIndex;\r\n let visualNew = this.visualNew;\r\n for (let i = 0; i <= versionIndex; i++) {\r\n let overloadFactory = extensibility.visualApiVersions[i].overloads;\r\n if (_.isFunction(overloadFactory)) {\r\n _.assign(overloads, overloadFactory(visualNew));\r\n }\r\n }\r\n return overloads;\r\n }\r\n }\r\n}","/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n///<reference path=\"../../Typedefs/jquery/jquery.d.ts\"/>\n///<reference path=\"../../Typedefs/globalize/globalize.d.ts\"/>\n///<reference path=\"../../Typedefs/lodash/lodash.d.ts\"/>\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var telemetry;\n (function (telemetry) {\n /**\n * Creates a client-side Guid string.\n * @returns A string representation of a Guid.\n */\n function generateGuid() {\n var guid = \"\", idx = 0;\n for (idx = 0; idx < 32; idx += 1) {\n var guidDigitsItem = Math.random() * 16 | 0;\n switch (idx) {\n case 8:\n case 12:\n case 16:\n case 20:\n guid += \"-\";\n break;\n }\n guid += guidDigitsItem.toString(16);\n }\n return guid;\n }\n telemetry.generateGuid = generateGuid;\n })(telemetry = visuals.telemetry || (visuals.telemetry = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var telemetry;\n (function (telemetry) {\n telemetry.ExtensibilityVisualApiUsage = function (name, apiVersion, custom, parentId, isError, errorSource, errorCode) {\n if (isError === void 0) { isError = false; }\n if (errorSource === void 0) { errorSource = undefined; }\n if (errorCode === void 0) { errorCode = undefined; }\n var info = {\n name: name,\n apiVersion: apiVersion,\n custom: custom,\n parentId: parentId,\n isError: isError,\n errorSource: errorSource,\n errorCode: errorCode,\n };\n var event = {\n name: 'PBI.Extensibility.VisualApiUsage',\n category: 1 /* CustomerAction */,\n time: Date.now(),\n id: telemetry.generateGuid(),\n getFormattedInfoObject: function () {\n var formattedObject = {\n name: info.name,\n apiVersion: info.apiVersion,\n custom: info.custom,\n parentId: info.parentId,\n isError: info.isError,\n };\n if (typeof info.errorSource !== 'undefined') {\n formattedObject['errorSource'] = telemetry.ErrorSource[info.errorSource];\n }\n if (typeof info.errorCode !== 'undefined') {\n formattedObject['errorCode'] = info.errorCode;\n }\n return formattedObject;\n },\n info: info,\n privateFields: [],\n orgInfoFields: []\n };\n if (typeof telemetry.ExtensibilityVisualApiUsageLoggers !== 'undefined') {\n event.loggers = telemetry.ExtensibilityVisualApiUsageLoggers;\n }\n return event;\n };\n telemetry.VisualException = function (visualType, isCustom, apiVersion, source, lineNumber, columnNumber, stack, message) {\n var info = {\n visualType: visualType,\n isCustom: isCustom,\n apiVersion: apiVersion,\n source: source,\n lineNumber: lineNumber,\n columnNumber: columnNumber,\n stack: stack,\n message: message,\n };\n var event = {\n name: 'PBI.VisualException',\n category: 2 /* CriticalError */,\n time: Date.now(),\n id: telemetry.generateGuid(),\n getFormattedInfoObject: function () {\n var formattedObject = {\n visualType: info.visualType,\n isCustom: info.isCustom,\n apiVersion: info.apiVersion,\n source: info.source,\n lineNumber: info.lineNumber,\n columnNumber: info.columnNumber,\n stack: info.stack,\n message: info.message,\n };\n return formattedObject;\n },\n info: info,\n privateFields: [],\n orgInfoFields: []\n };\n if (typeof telemetry.VisualExceptionLoggers !== 'undefined') {\n event.loggers = telemetry.VisualExceptionLoggers;\n }\n return event;\n };\n })(telemetry = visuals.telemetry || (visuals.telemetry = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var extensibility;\n (function (extensibility) {\n function VisualPlugin(options) {\n return function (constructor) {\n constructor.__capabilities__ = options.capabilities;\n };\n }\n extensibility.VisualPlugin = VisualPlugin;\n })(extensibility = powerbi.extensibility || (powerbi.extensibility = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var extensibility;\n (function (extensibility) {\n ;\n var SelectionManager = (function () {\n function SelectionManager(options) {\n this.hostServices = options.hostServices;\n this.selectedIds = [];\n this.promiseFactory = this.hostServices.promiseFactory();\n }\n SelectionManager.prototype.select = function (selectionId, multiSelect) {\n if (multiSelect === void 0) { multiSelect = false; }\n var deferred = this.promiseFactory.defer();\n if (this.hostServices.shouldRetainSelection()) {\n this.sendSelectionToHost([selectionId]);\n }\n else {\n this.selectInternal(selectionId, multiSelect);\n this.sendSelectionToHost(this.selectedIds);\n }\n deferred.resolve(this.selectedIds);\n return deferred.promise;\n };\n SelectionManager.prototype.showContextMenu = function (selectionId, position) {\n var deferred = this.promiseFactory.defer();\n this.sendContextMenuToHost(selectionId, position);\n deferred.resolve(null);\n return deferred.promise;\n };\n SelectionManager.prototype.hasSelection = function () {\n return this.selectedIds.length > 0;\n };\n SelectionManager.prototype.clear = function () {\n var deferred = this.promiseFactory.defer();\n this.selectedIds = [];\n this.sendSelectionToHost([]);\n deferred.resolve(null);\n return deferred.promise;\n };\n SelectionManager.prototype.getSelectionIds = function () {\n return this.selectedIds;\n };\n SelectionManager.prototype.sendSelectionToHost = function (ids) {\n var selectArgs = {\n data: ids\n .filter(function (value) { return value.hasIdentity(); })\n .map(function (value) { return value.getSelector(); })\n };\n var data2 = this.getSelectorsByColumn(ids);\n if (!_.isEmpty(data2))\n selectArgs.data2 = data2;\n this.hostServices.onSelect(selectArgs);\n };\n SelectionManager.prototype.sendContextMenuToHost = function (selectionId, position) {\n var selectors = this.getSelectorsByColumn([selectionId]);\n if (_.isEmpty(selectors))\n return;\n var args = {\n data: selectors,\n position: position\n };\n this.hostServices.onContextMenu(args);\n };\n SelectionManager.prototype.getSelectorsByColumn = function (selectionIds) {\n return _(selectionIds)\n .filter(function (value) { return value.hasIdentity; })\n .map(function (value) { return value.getSelectorsByColumn(); })\n .compact()\n .value();\n };\n SelectionManager.prototype.selectInternal = function (selectionId, multiSelect) {\n if (SelectionManager.containsSelection(this.selectedIds, selectionId)) {\n this.selectedIds = multiSelect\n ? this.selectedIds.filter(function (d) { return !selectionId.equals(d); })\n : this.selectedIds.length > 1\n ? [selectionId] : [];\n }\n else {\n if (multiSelect)\n this.selectedIds.push(selectionId);\n else\n this.selectedIds = [selectionId];\n }\n };\n SelectionManager.containsSelection = function (list, id) {\n return list.some(function (d) { return id.equals(d); });\n };\n return SelectionManager;\n }());\n extensibility.SelectionManager = SelectionManager;\n })(extensibility = powerbi.extensibility || (powerbi.extensibility = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var extensibility;\n (function (extensibility) {\n /**\n * This class is designed to simplify the creation of SelectionId objects\n * It allows chaining to build up an object before calling 'create' to build a SelectionId\n */\n var SelectionIdBuilder = (function () {\n function SelectionIdBuilder() {\n }\n SelectionIdBuilder.prototype.withCategory = function (categoryColumn, index) {\n if (categoryColumn && categoryColumn.source && categoryColumn.source.queryName && categoryColumn.identity)\n this.ensureDataMap()[categoryColumn.source.queryName] = categoryColumn.identity[index];\n return this;\n };\n SelectionIdBuilder.prototype.withSeries = function (seriesColumn, valueColumn) {\n if (seriesColumn && seriesColumn.source && seriesColumn.source.queryName && valueColumn)\n this.ensureDataMap()[seriesColumn.source.queryName] = valueColumn.identity;\n return this;\n };\n SelectionIdBuilder.prototype.withMeasure = function (measureId) {\n this.measure = measureId;\n return this;\n };\n SelectionIdBuilder.prototype.createSelectionId = function () {\n return powerbi.visuals.SelectionId.createWithSelectorForColumnAndMeasure(this.ensureDataMap(), this.measure);\n };\n SelectionIdBuilder.prototype.ensureDataMap = function () {\n if (!this.dataMap)\n this.dataMap = {};\n return this.dataMap;\n };\n return SelectionIdBuilder;\n }());\n extensibility.SelectionIdBuilder = SelectionIdBuilder;\n })(extensibility = powerbi.extensibility || (powerbi.extensibility = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var extensibility;\n (function (extensibility) {\n var ExtensibilityVisualApiUsage = powerbi.visuals.telemetry.ExtensibilityVisualApiUsage;\n //TODO: refactor this into a service\n extensibility.visualApiVersions = [];\n function createVisualAdapter(visualPlugin, telemetryService) {\n var visualTelemetryInfo = {\n name: visualPlugin.name,\n apiVersion: visualPlugin.apiVersion,\n custom: !!visualPlugin.custom\n };\n return new extensibility.VisualSafeExecutionWrapper(new VisualAdapter(visualPlugin, telemetryService), visualTelemetryInfo, telemetryService);\n }\n extensibility.createVisualAdapter = createVisualAdapter;\n var VisualAdapter = (function () {\n function VisualAdapter(visualPlugin, telemetryService) {\n this.telemetryService = telemetryService;\n this.plugin = visualPlugin;\n var version = visualPlugin.apiVersion;\n var versionIndex = this.getVersionIndex(version);\n var isError = false;\n if (!version) {\n this.legacy = true;\n }\n else if (versionIndex > -1) {\n this.apiVersionIndex = versionIndex;\n this.legacy = false;\n }\n else {\n debug.assertFail(\"The API version '\" + version + \"' is invalid.\");\n isError = true;\n }\n if (this.telemetryService) {\n this.telemetryService.logEvent(ExtensibilityVisualApiUsage, this.plugin.name, this.plugin.apiVersion, !!this.plugin.custom, undefined, isError, powerbi.visuals.telemetry.ErrorSource.User);\n }\n }\n VisualAdapter.prototype.init = function (options) {\n debug.assertValue(options.element, \"options.element\");\n debug.assertValue(options.host, \"options.host\");\n options.element.empty();\n if (this.legacy) {\n this.visual = this.plugin.create();\n this.visualLegacy.init(options);\n }\n else {\n var host = extensibility.visualApiVersions[this.apiVersionIndex].hostAdapter(options.host);\n this.visual = this.plugin.create({\n element: options.element.get(0),\n host: host\n });\n this.overloadMethods();\n }\n };\n VisualAdapter.prototype.update = function (options) {\n if (options.type & powerbi.VisualUpdateType.Resize && this.visualHasMethod('onResizing')) {\n this.onResizing(options.viewport, options.resizeMode);\n }\n else if (this.visualHasMethod('update')) {\n this.visualLegacy.update(options);\n }\n else {\n if (!options.type || options.type & powerbi.VisualUpdateType.Data) {\n this.onDataChanged(_.pick(options, ['dataViews', 'operationKind']));\n }\n if (options.type & powerbi.VisualUpdateType.ViewMode) {\n this.onViewModeChanged(options.viewMode);\n }\n }\n };\n VisualAdapter.prototype.destroy = function () {\n if (this.visualHasMethod('destroy')) {\n this.visualLegacy.destroy();\n }\n };\n VisualAdapter.prototype.enumerateObjectInstances = function (options) {\n if (!this.visualHasMethod('enumerateObjectInstances')) {\n return;\n }\n return this.visualLegacy.enumerateObjectInstances(options);\n };\n VisualAdapter.prototype.enumerateObjectRepetition = function () {\n if (!this.visualHasMethod('enumerateObjectRepetition')) {\n return;\n }\n return this.visualLegacy.enumerateObjectRepetition();\n };\n VisualAdapter.prototype.onResizing = function (finalViewport, resizeMode) {\n if (this.visualHasMethod('onResizing')) {\n this.visualLegacy.onResizing(finalViewport, resizeMode);\n }\n };\n VisualAdapter.prototype.onDataChanged = function (options) {\n if (this.visualHasMethod('onDataChanged')) {\n this.visualLegacy.onDataChanged(options);\n }\n };\n VisualAdapter.prototype.onViewModeChanged = function (viewMode) {\n if (this.visualHasMethod('onViewModeChanged')) {\n this.visualLegacy.onViewModeChanged(viewMode);\n }\n };\n VisualAdapter.prototype.onClearSelection = function () {\n if (this.visualHasMethod('onClearSelection')) {\n this.visualLegacy.onClearSelection();\n }\n };\n VisualAdapter.prototype.canResizeTo = function (viewport) {\n if (this.visualHasMethod('canResizeTo')) {\n return this.visualLegacy.canResizeTo(viewport);\n }\n };\n VisualAdapter.prototype.unwrap = function () {\n return this.visual;\n };\n Object.defineProperty(VisualAdapter.prototype, \"visualNew\", {\n get: function () {\n if (this.legacy)\n return;\n return this.visual;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(VisualAdapter.prototype, \"visualLegacy\", {\n get: function () {\n if (!this.legacy)\n return;\n return this.visual;\n },\n enumerable: true,\n configurable: true\n });\n VisualAdapter.prototype.visualHasMethod = function (methodName) {\n var visual = this.legacy ? this.visualLegacy : this.visualNew;\n return visual && _.isFunction(visual[methodName]);\n };\n VisualAdapter.prototype.getVersionIndex = function (version) {\n if (version) {\n var versionCount = extensibility.visualApiVersions.length;\n for (var i = 0; i < versionCount; i++) {\n if (extensibility.visualApiVersions[i].version === version) {\n return i;\n }\n }\n }\n return -1;\n };\n VisualAdapter.prototype.overloadMethods = function () {\n var overloads = this.getCompiledOverloads();\n for (var key in overloads) {\n this[key] = overloads[key];\n }\n };\n VisualAdapter.prototype.getCompiledOverloads = function () {\n var overloads = {};\n var versionIndex = this.apiVersionIndex;\n var visualNew = this.visualNew;\n for (var i = 0; i <= versionIndex; i++) {\n var overloadFactory = extensibility.visualApiVersions[i].overloads;\n if (_.isFunction(overloadFactory)) {\n _.assign(overloads, overloadFactory(visualNew));\n }\n }\n return overloads;\n };\n return VisualAdapter;\n }());\n extensibility.VisualAdapter = VisualAdapter;\n })(extensibility = powerbi.extensibility || (powerbi.extensibility = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var extensibility;\n (function (extensibility) {\n var VisualException = powerbi.visuals.telemetry.VisualException;\n var VisualSafeExecutionWrapper = (function () {\n function VisualSafeExecutionWrapper(wrappedVisual, visualInfo, telemetryService, silent) {\n this.wrappedVisual = wrappedVisual;\n this.visualInfo = visualInfo;\n this.telemetryService = telemetryService;\n this.silent = silent;\n }\n VisualSafeExecutionWrapper.prototype.init = function (options) {\n var _this = this;\n if (this.wrappedVisual.init) {\n this.executeSafely(function () { return _this.wrappedVisual.init(options); });\n }\n };\n VisualSafeExecutionWrapper.prototype.destroy = function () {\n var _this = this;\n if (this.wrappedVisual.destroy)\n this.executeSafely(function () { return _this.wrappedVisual.destroy(); });\n };\n VisualSafeExecutionWrapper.prototype.update = function (options) {\n var _this = this;\n if (this.wrappedVisual.update)\n this.executeSafely(function () { return _this.wrappedVisual.update(options); });\n };\n VisualSafeExecutionWrapper.prototype.onResizing = function (finalViewport, resizeMode) {\n var _this = this;\n if (this.wrappedVisual.onResizing)\n this.executeSafely(function () { return _this.wrappedVisual.onResizing(finalViewport, resizeMode); });\n };\n VisualSafeExecutionWrapper.prototype.onDataChanged = function (options) {\n var _this = this;\n if (this.wrappedVisual.onDataChanged)\n this.executeSafely(function () { return _this.wrappedVisual.onDataChanged(options); });\n };\n VisualSafeExecutionWrapper.prototype.onViewModeChanged = function (viewMode) {\n var _this = this;\n if (this.wrappedVisual.onViewModeChanged)\n this.executeSafely(function () { return _this.wrappedVisual.onViewModeChanged(viewMode); });\n };\n VisualSafeExecutionWrapper.prototype.onClearSelection = function () {\n var _this = this;\n if (this.wrappedVisual.onClearSelection)\n this.executeSafely(function () { return _this.wrappedVisual.onClearSelection(); });\n };\n VisualSafeExecutionWrapper.prototype.canResizeTo = function (viewport) {\n var _this = this;\n if (this.wrappedVisual.canResizeTo)\n return this.executeSafely(function () { return _this.wrappedVisual.canResizeTo(viewport); });\n };\n VisualSafeExecutionWrapper.prototype.enumerateObjectInstances = function (options) {\n var _this = this;\n if (this.wrappedVisual.enumerateObjectInstances)\n return this.executeSafely(function () { return _this.wrappedVisual.enumerateObjectInstances(options); });\n };\n VisualSafeExecutionWrapper.prototype.enumerateObjectRepetition = function () {\n var _this = this;\n if (this.wrappedVisual.enumerateObjectRepetition)\n return this.executeSafely(function () { return _this.wrappedVisual.enumerateObjectRepetition(); });\n };\n VisualSafeExecutionWrapper.prototype.unwrap = function () {\n var visual = this.wrappedVisual;\n return visual.unwrap ? visual.unwrap() : visual;\n };\n VisualSafeExecutionWrapper.prototype.isCustomVisual = function () {\n return this.visualInfo.custom;\n };\n VisualSafeExecutionWrapper.prototype.executeSafely = function (callback) {\n try {\n return callback();\n }\n catch (exception) {\n if (!this.silent) {\n console.error(\"Visual exception\", exception.stack || exception);\n }\n if (this.telemetryService) {\n this.telemetryService.logEvent(VisualException, this.visualInfo.name, this.visualInfo.custom, this.visualInfo.apiVersion, exception.fileName, exception.lineNumber, exception.columnNumber, exception.stack, exception.message);\n }\n }\n };\n return VisualSafeExecutionWrapper;\n }());\n extensibility.VisualSafeExecutionWrapper = VisualSafeExecutionWrapper;\n })(extensibility = powerbi.extensibility || (powerbi.extensibility = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var extensibility;\n (function (extensibility) {\n var v100;\n (function (v100) {\n var overloadFactory = function (visual) {\n return {\n update: function (options) {\n if (visual.update) {\n var type = options.type || powerbi.VisualUpdateType.Data;\n if (type & powerbi.VisualUpdateType.Resize && options.resizeMode === 2 /* Resized */) {\n type |= powerbi.VisualUpdateType.ResizeEnd;\n }\n visual.update({\n viewport: options.viewport,\n dataViews: options.dataViews,\n type: type\n });\n }\n },\n destroy: function () {\n if (visual.destroy) {\n visual.destroy();\n }\n },\n enumerateObjectInstances: function (options) {\n if (visual.enumerateObjectInstances) {\n return visual.enumerateObjectInstances(options);\n }\n }\n };\n };\n var hostAdapter = function (host) {\n return {};\n };\n extensibility.visualApiVersions.push({\n version: '1.0.0',\n overloads: overloadFactory,\n hostAdapter: hostAdapter\n });\n })(v100 = extensibility.v100 || (extensibility.v100 = {}));\n })(extensibility = powerbi.extensibility || (powerbi.extensibility = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var extensibility;\n (function (extensibility) {\n var v110;\n (function (v110) {\n var hostAdapter = function (host) {\n return {\n createSelectionIdBuilder: function () { return new powerbi.visuals.SelectionIdBuilder(); },\n createSelectionManager: function () { return new extensibility.SelectionManager({ hostServices: host }); }\n };\n };\n extensibility.visualApiVersions.push({\n version: '1.1.0',\n hostAdapter: hostAdapter\n });\n })(v110 = extensibility.v110 || (extensibility.v110 = {}));\n })(extensibility = powerbi.extensibility || (powerbi.extensibility = {}));\n})(powerbi || (powerbi = {}));\n\n\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.extensibility {\r\n\r\n import ITelemetryService = visuals.telemetry.ITelemetryService;\r\n import VisualTelemetryInfo = visuals.telemetry.VisualTelemetryInfo;\r\n import VisualException = powerbi.visuals.telemetry.VisualException;\r\n\r\n export class VisualSafeExecutionWrapper implements powerbi.IVisual, WrappedVisual {\r\n constructor(\r\n private wrappedVisual: powerbi.IVisual,\r\n private visualInfo: VisualTelemetryInfo,\r\n private telemetryService: ITelemetryService,\r\n private silent?: boolean) { }\r\n\r\n public init(options: VisualInitOptions): void {\r\n if (this.wrappedVisual.init) {\r\n this.executeSafely(() => this.wrappedVisual.init(options));\r\n }\r\n }\r\n\r\n public destroy(): void {\r\n if (this.wrappedVisual.destroy)\r\n this.executeSafely(() => this.wrappedVisual.destroy());\r\n }\r\n\r\n public update(options: powerbi.VisualUpdateOptions): void {\r\n if (this.wrappedVisual.update)\r\n this.executeSafely(() => this.wrappedVisual.update(options));\r\n }\r\n\r\n public onResizing(finalViewport: IViewport, resizeMode: ResizeMode): void {\r\n if (this.wrappedVisual.onResizing)\r\n this.executeSafely(() => this.wrappedVisual.onResizing(finalViewport, resizeMode));\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n if (this.wrappedVisual.onDataChanged)\r\n this.executeSafely(() => this.wrappedVisual.onDataChanged(options));\r\n }\r\n\r\n public onViewModeChanged(viewMode: ViewMode): void {\r\n if (this.wrappedVisual.onViewModeChanged)\r\n this.executeSafely(() => this.wrappedVisual.onViewModeChanged(viewMode));\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.wrappedVisual.onClearSelection)\r\n this.executeSafely(() => this.wrappedVisual.onClearSelection());\r\n }\r\n\r\n public canResizeTo(viewport: IViewport): boolean {\r\n if (this.wrappedVisual.canResizeTo)\r\n return this.executeSafely(() => this.wrappedVisual.canResizeTo(viewport));\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n if (this.wrappedVisual.enumerateObjectInstances)\r\n return this.executeSafely(() => this.wrappedVisual.enumerateObjectInstances(options));\r\n }\r\n\r\n public enumerateObjectRepetition(): VisualObjectRepetition[] {\r\n if (this.wrappedVisual.enumerateObjectRepetition)\r\n return this.executeSafely(() => this.wrappedVisual.enumerateObjectRepetition());\r\n }\r\n\r\n public unwrap(): powerbi.IVisual {\r\n let visual = <powerbi.IVisual & WrappedVisual>this.wrappedVisual;\r\n return visual.unwrap ? visual.unwrap() : visual;\r\n }\r\n\r\n public isCustomVisual(): boolean {\r\n return this.visualInfo.custom;\r\n }\r\n\r\n private executeSafely(callback: () => any): any {\r\n try {\r\n return callback();\r\n } catch (exception) {\r\n if (!this.silent) {\r\n console.error(\"Visual exception\", exception.stack || exception);\r\n }\r\n\r\n if (this.telemetryService) {\r\n this.telemetryService.logEvent(\r\n VisualException,\r\n this.visualInfo.name,\r\n this.visualInfo.custom,\r\n this.visualInfo.apiVersion,\r\n exception.fileName,\r\n exception.lineNumber,\r\n exception.columnNumber,\r\n exception.stack,\r\n exception.message);\r\n }\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.extensibility.v100 {\r\n let overloadFactory: VisualVersionOverloadFactory = (visual: IVisual) => {\r\n return {\r\n update: (options: powerbi.VisualUpdateOptions) => {\r\n if (visual.update) {\r\n let type = options.type || VisualUpdateType.Data;\r\n if(type & VisualUpdateType.Resize && options.resizeMode === ResizeMode.Resized) {\r\n type |= VisualUpdateType.ResizeEnd;\r\n } \r\n visual.update({\r\n viewport: options.viewport,\r\n dataViews: options.dataViews,\r\n type: type\r\n });\r\n }\r\n },\r\n destroy: () => {\r\n if (visual.destroy) {\r\n visual.destroy();\r\n }\r\n },\r\n enumerateObjectInstances: (options: EnumerateVisualObjectInstancesOptions) => {\r\n if (visual.enumerateObjectInstances) {\r\n return visual.enumerateObjectInstances(options);\r\n }\r\n }\r\n };\r\n };\r\n\r\n let hostAdapter: VisualHostAdapter = (host: IVisualHostServices): IVisualHost => {\r\n return {};\r\n };\r\n\r\n visualApiVersions.push({\r\n version: '1.0.0',\r\n overloads: overloadFactory,\r\n hostAdapter: hostAdapter\r\n });\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.extensibility.v110 {\r\n let hostAdapter: VisualHostAdapter = (host: powerbi.IVisualHostServices): IVisualHost => {\r\n return {\r\n createSelectionIdBuilder: () => new visuals.SelectionIdBuilder(),\r\n createSelectionManager: () => new SelectionManager({ hostServices: host })\r\n };\r\n };\r\n\r\n visualApiVersions.push({\r\n version: '1.1.0',\r\n hostAdapter: hostAdapter\r\n });\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n /**\r\n * DOM constants.\r\n */\r\n export module DOMConstants {\r\n\r\n /** \r\n * Integer codes corresponding to individual keys on the keyboard.\r\n */\r\n export const escKeyCode = 27;\r\n export const enterKeyCode = 13;\r\n export const tabKeyCode = 9;\r\n export const upArrowKeyCode = 38;\r\n export const downArrowKeyCode = 40;\r\n export const leftArrowKeyCode = 37;\r\n export const rightArrowKeyCode = 39;\r\n export const homeKeyCode = 36;\r\n export const endKeyCode = 35;\r\n export const backSpaceKeyCode = 8;\r\n export const deleteKeyCode = 46;\r\n export const spaceKeyCode = 32;\r\n export const shiftKeyCode = 16;\r\n export const ctrlKeyCode = 17;\r\n export const altKeyCode = 18;\r\n\r\n export const aKeyCode = 65;\r\n export const cKeyCode = 67;\r\n export const sKeyCode = 83;\r\n export const vKeyCode = 86;\r\n export const wKeyCode = 87;\r\n export const xKeyCode = 88;\r\n export const yKeyCode = 89;\r\n export const zKeyCode = 90;\r\n\r\n /** \r\n * DOM Elements.\r\n */\r\n export const DocumentBody = 'body';\r\n export const Anchor = 'a';\r\n export const EditableTextElements = ':text, textarea';\r\n export const EditableNumericElements = '[type=\"number\"]';\r\n\r\n /** \r\n * DOM Attributes and values.\r\n */\r\n export const disabledAttributeOrValue = 'disabled';\r\n export const readonlyAttributeOrValue = 'readonly';\r\n export const idAttribute = 'id';\r\n export const styleAttribute = 'style';\r\n export const hrefAttribute = 'href';\r\n export const targetAttribute = 'target';\r\n export const blankValue = '_blank';\r\n export const selfValue = '_self';\r\n export const classAttribute = 'class';\r\n export const titleAttribute = 'title';\r\n export const srcAttribute = 'src';\r\n\r\n /**\r\n * DOM event names.\r\n */\r\n export const contextmenuEventName = 'contextmenu';\r\n export const blurEventName = 'blur';\r\n export const keyUpEventName = 'keyup';\r\n export const inputEventName = 'input';\r\n export const changeEventName = 'change';\r\n export const cutEventName = 'cut';\r\n export const keyDownEventName = 'keydown';\r\n export const mouseMoveEventName = 'mousemove';\r\n export const mouseDownEventName = 'mousedown';\r\n export const mouseEnterEventName = 'mouseenter';\r\n export const mouseLeaveEventName = 'mouseleave';\r\n export const mouseOverEventName = 'mouseover';\r\n export const mouseOutEventName = 'mouseout';\r\n export const mouseClickEventName = 'click';\r\n export const pasteEventName = 'paste';\r\n export const scrollEventName = 'scroll';\r\n export const dropEventName = 'drop';\r\n export const focusEventName = 'focus';\r\n export const focusInEventName = 'focusin';\r\n export const focusOutEventName = 'focusout';\r\n export const selectEventName = 'select';\r\n export const messageEventName = 'message';\r\n export const loadEventName = 'load';\r\n export const beforeUnload = 'beforeunload';\r\n \r\n /**\r\n * Common DOM event combination names.\r\n */\r\n export const inputAndSelectEventNames = 'input, select';\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import IStringResourceProvider = jsCommon.IStringResourceProvider;\r\n\r\n export interface ServiceError {\r\n statusCode: number;\r\n\r\n /**\r\n * This error code corresponds with a PowerBIServiceException that happened on the server.\r\n */\r\n errorCode?: string;\r\n \r\n /**\r\n * Message and stack trace should only be sent in non-production environments.\r\n */\r\n message?: string;\r\n stackTrace?: string;\r\n errorDetails?: PowerBIErrorDetail[];\r\n parameters?: ErrorParameter[];\r\n }\r\n\r\n export interface PowerBIErrorDetail {\r\n code: string;\r\n detail: PowerBIErrorDetailValue;\r\n }\r\n\r\n export interface ErrorParameter {\r\n Key: string;\r\n Value: string;\r\n }\r\n\r\n export interface PowerBIErrorDetailValue {\r\n type: PowerBIErrorResourceType;\r\n value: string;\r\n }\r\n\r\n export enum PowerBIErrorResourceType {\r\n ResourceCodeReference = 0,\r\n EmbeddedString = 1,\r\n }\r\n\r\n export const enum ServiceErrorStatusCode {\r\n GeneralError = 0,\r\n CsdlFetching = 1,\r\n CsdlConvertXmlToConceptualSchema = 2,\r\n CsdlCreateClientSchema = 3,\r\n ExecuteSemanticQueryError = 4,\r\n ExecuteSemanticQueryInvalidStreamFormat = 5,\r\n ExecuteSemanticQueryTransformError = 6,\r\n }\r\n\r\n export class ServiceErrorToClientError implements IClientError {\r\n private m_serviceError: ServiceError;\r\n private httpRequestId: string;\r\n private static codeName = 'ServiceErrorToClientError';\r\n\r\n public get code(): string {\r\n return ServiceErrorToClientError.codeName;\r\n }\r\n\r\n public get ignorable(): boolean {\r\n return false;\r\n }\r\n\r\n public get requestId(): string {\r\n return this.httpRequestId;\r\n }\r\n\r\n public set requestId(value: string) {\r\n this.httpRequestId = value;\r\n }\r\n\r\n constructor(serviceError: ServiceError) {\r\n this.m_serviceError = serviceError;\r\n }\r\n\r\n public getDetails(resourceProvider: IStringResourceProvider): ErrorDetails {\r\n let errorDetails: ErrorDetails;\r\n if (this.m_serviceError.statusCode === ServiceErrorStatusCode.ExecuteSemanticQueryTransformError) {\r\n errorDetails = PowerBIErrorDetailHelper.GetDetailsFromTransformError(resourceProvider, this.m_serviceError);\r\n }\r\n else {\r\n errorDetails = PowerBIErrorDetailHelper.GetDetailsFromServerErrorStatusCode(resourceProvider, this.m_serviceError.statusCode);\r\n }\r\n\r\n PowerBIErrorDetailHelper.addAdditionalInfo(errorDetails, this.m_serviceError.errorDetails, resourceProvider);\r\n PowerBIErrorDetailHelper.addMessageAndStackTrace(errorDetails, this.m_serviceError.message || null, this.m_serviceError.stackTrace || null, resourceProvider);\r\n\r\n return errorDetails;\r\n }\r\n }\r\n\r\n export class PowerBIErrorDetailHelper {\r\n private static serverErrorPrefix = \"ServerError_\";\r\n public static addAdditionalInfo(errorDetails: ErrorDetails, pbiErrorDetails: PowerBIErrorDetail[], localize: IStringResourceProvider): ErrorDetails {\r\n if (pbiErrorDetails) {\r\n for (let i = 0; i < pbiErrorDetails.length; i++) {\r\n let element = pbiErrorDetails[i];\r\n let localizedCode = localize.getOptional(PowerBIErrorDetailHelper.serverErrorPrefix + element.code);\r\n let additionErrorInfoKeyValuePair = {\r\n errorInfoKey: localizedCode ? localizedCode : element.code,\r\n errorInfoValue: element.detail.type === PowerBIErrorResourceType.ResourceCodeReference ? localize.get(PowerBIErrorDetailHelper.serverErrorPrefix + element.detail.value) : element.detail.value\r\n };\r\n\r\n errorDetails.additionalErrorInfo.push(additionErrorInfoKeyValuePair);\r\n }\r\n }\r\n return errorDetails;\r\n }\r\n\r\n public static addMessageAndStackTrace(errorDetails: ErrorDetails, message: string, stackTrace: string, localize: IStringResourceProvider): ErrorDetails {\r\n if (message) {\r\n let additionErrorInfoKeyValuePair = {\r\n errorInfoKey: localize.get(\"AdditionalErrorInfo_ErrorDetailsText\"),\r\n errorInfoValue: message\r\n };\r\n errorDetails.additionalErrorInfo.push(additionErrorInfoKeyValuePair);\r\n }\r\n if (stackTrace) {\r\n let additionErrorInfoKeyValuePair = {\r\n errorInfoKey: localize.get(\"AdditionalErrorInfo_StackTraceText\"),\r\n errorInfoValue: stackTrace\r\n };\r\n errorDetails.additionalErrorInfo.push(additionErrorInfoKeyValuePair);\r\n }\r\n return errorDetails;\r\n }\r\n\r\n public static GetDetailsFromTransformError(localize: IStringResourceProvider, serviceError: ServiceError): ErrorDetails {\r\n let message = localize.get('ServiceError_CannotLoadVisual');\r\n let key = localize.get('ServiceError_CannotLoadVisual');\r\n let val = serviceError.message;\r\n\r\n let additionalInfo: ErrorInfoKeyValuePair[] = [];\r\n additionalInfo.push({ errorInfoKey: key, errorInfoValue: val, });\r\n\r\n let errorDetails: ErrorDetails = {\r\n message: message,\r\n additionalErrorInfo: additionalInfo,\r\n };\r\n\r\n return errorDetails;\r\n }\r\n\r\n public static GetDetailsFromServerErrorStatusCode(localize: IStringResourceProvider, statusCode: number): ErrorDetails {\r\n // TODO: Localize\r\n let message: string = \"\";\r\n let key: string = \"\";\r\n let val: string = \"\";\r\n\r\n switch (statusCode) {\r\n case ServiceErrorStatusCode.CsdlConvertXmlToConceptualSchema:\r\n message = localize.get('ServiceError_ModelCannotLoad');\r\n key = localize.get('ServiceError_ModelConvertFailureKey');\r\n val = localize.get('ServiceError_ModelConvertFailureValue');\r\n break;\r\n case ServiceErrorStatusCode.CsdlCreateClientSchema:\r\n message = localize.get('ServiceError_ModelCannotLoad');\r\n key = localize.get('ServiceError_ModelCreationFailureKey');\r\n val = localize.get('ServiceError_ModelCreationFailureValue');\r\n break;\r\n case ServiceErrorStatusCode.CsdlFetching:\r\n message = localize.get('ServiceError_ModelCannotLoad');\r\n key = localize.get('ServiceError_ModelFetchingFailureKey');\r\n val = localize.get('ServiceError_ModelFetchingFailureValue');\r\n break;\r\n case ServiceErrorStatusCode.ExecuteSemanticQueryError:\r\n message = localize.get('ServiceError_CannotLoadVisual');\r\n key = localize.get('ServiceError_ExecuteSemanticQueryErrorKey');\r\n val = localize.get('ServiceError_ExecuteSemanticQueryErrorValue');\r\n break;\r\n case ServiceErrorStatusCode.ExecuteSemanticQueryInvalidStreamFormat:\r\n message = localize.get('ServiceError_CannotLoadVisual');\r\n key = localize.get('ServiceError_ExecuteSemanticQueryInvalidStreamFormatKey');\r\n val = localize.get('ServiceError_ExecuteSemanticQueryInvalidStreamFormatValue');\r\n break;\r\n case ServiceErrorStatusCode.GeneralError:\r\n default:\r\n message = localize.get('ServiceError_GeneralError');\r\n key = localize.get('ServiceError_GeneralErrorKey');\r\n val = localize.get('ServiceError_GeneralErrorValue');\r\n break;\r\n }\r\n\r\n let additionalInfo: ErrorInfoKeyValuePair[] = [];\r\n additionalInfo.push({ errorInfoKey: key, errorInfoValue: val, });\r\n\r\n let errorDetails: ErrorDetails = {\r\n message: message,\r\n additionalErrorInfo: additionalInfo,\r\n };\r\n\r\n return errorDetails;\r\n }\r\n }\r\n} ","/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n///<reference path=\"../../Typedefs/jquery/jquery.d.ts\"/>\n///<reference path=\"../../Typedefs/d3/d3.d.ts\"/>\n///<reference path=\"../../Typedefs/lodash/lodash.d.ts\"/> \n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * DOM constants.\n */\n var DOMConstants;\n (function (DOMConstants) {\n /**\n * Integer codes corresponding to individual keys on the keyboard.\n */\n DOMConstants.escKeyCode = 27;\n DOMConstants.enterKeyCode = 13;\n DOMConstants.tabKeyCode = 9;\n DOMConstants.upArrowKeyCode = 38;\n DOMConstants.downArrowKeyCode = 40;\n DOMConstants.leftArrowKeyCode = 37;\n DOMConstants.rightArrowKeyCode = 39;\n DOMConstants.homeKeyCode = 36;\n DOMConstants.endKeyCode = 35;\n DOMConstants.backSpaceKeyCode = 8;\n DOMConstants.deleteKeyCode = 46;\n DOMConstants.spaceKeyCode = 32;\n DOMConstants.shiftKeyCode = 16;\n DOMConstants.ctrlKeyCode = 17;\n DOMConstants.altKeyCode = 18;\n DOMConstants.aKeyCode = 65;\n DOMConstants.cKeyCode = 67;\n DOMConstants.sKeyCode = 83;\n DOMConstants.vKeyCode = 86;\n DOMConstants.wKeyCode = 87;\n DOMConstants.xKeyCode = 88;\n DOMConstants.yKeyCode = 89;\n DOMConstants.zKeyCode = 90;\n /**\n * DOM Elements.\n */\n DOMConstants.DocumentBody = 'body';\n DOMConstants.Anchor = 'a';\n DOMConstants.EditableTextElements = ':text, textarea';\n DOMConstants.EditableNumericElements = '[type=\"number\"]';\n /**\n * DOM Attributes and values.\n */\n DOMConstants.disabledAttributeOrValue = 'disabled';\n DOMConstants.readonlyAttributeOrValue = 'readonly';\n DOMConstants.idAttribute = 'id';\n DOMConstants.styleAttribute = 'style';\n DOMConstants.hrefAttribute = 'href';\n DOMConstants.targetAttribute = 'target';\n DOMConstants.blankValue = '_blank';\n DOMConstants.selfValue = '_self';\n DOMConstants.classAttribute = 'class';\n DOMConstants.titleAttribute = 'title';\n DOMConstants.srcAttribute = 'src';\n /**\n * DOM event names.\n */\n DOMConstants.contextmenuEventName = 'contextmenu';\n DOMConstants.blurEventName = 'blur';\n DOMConstants.keyUpEventName = 'keyup';\n DOMConstants.inputEventName = 'input';\n DOMConstants.changeEventName = 'change';\n DOMConstants.cutEventName = 'cut';\n DOMConstants.keyDownEventName = 'keydown';\n DOMConstants.mouseMoveEventName = 'mousemove';\n DOMConstants.mouseDownEventName = 'mousedown';\n DOMConstants.mouseEnterEventName = 'mouseenter';\n DOMConstants.mouseLeaveEventName = 'mouseleave';\n DOMConstants.mouseOverEventName = 'mouseover';\n DOMConstants.mouseOutEventName = 'mouseout';\n DOMConstants.mouseClickEventName = 'click';\n DOMConstants.pasteEventName = 'paste';\n DOMConstants.scrollEventName = 'scroll';\n DOMConstants.dropEventName = 'drop';\n DOMConstants.focusEventName = 'focus';\n DOMConstants.focusInEventName = 'focusin';\n DOMConstants.focusOutEventName = 'focusout';\n DOMConstants.selectEventName = 'select';\n DOMConstants.messageEventName = 'message';\n DOMConstants.loadEventName = 'load';\n DOMConstants.beforeUnload = 'beforeunload';\n /**\n * Common DOM event combination names.\n */\n DOMConstants.inputAndSelectEventNames = 'input, select';\n })(DOMConstants = jsCommon.DOMConstants || (jsCommon.DOMConstants = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n (function (PowerBIErrorResourceType) {\n PowerBIErrorResourceType[PowerBIErrorResourceType[\"ResourceCodeReference\"] = 0] = \"ResourceCodeReference\";\n PowerBIErrorResourceType[PowerBIErrorResourceType[\"EmbeddedString\"] = 1] = \"EmbeddedString\";\n })(powerbi.PowerBIErrorResourceType || (powerbi.PowerBIErrorResourceType = {}));\n var PowerBIErrorResourceType = powerbi.PowerBIErrorResourceType;\n var ServiceErrorToClientError = (function () {\n function ServiceErrorToClientError(serviceError) {\n this.m_serviceError = serviceError;\n }\n Object.defineProperty(ServiceErrorToClientError.prototype, \"code\", {\n get: function () {\n return ServiceErrorToClientError.codeName;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ServiceErrorToClientError.prototype, \"ignorable\", {\n get: function () {\n return false;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ServiceErrorToClientError.prototype, \"requestId\", {\n get: function () {\n return this.httpRequestId;\n },\n set: function (value) {\n this.httpRequestId = value;\n },\n enumerable: true,\n configurable: true\n });\n ServiceErrorToClientError.prototype.getDetails = function (resourceProvider) {\n var errorDetails;\n if (this.m_serviceError.statusCode === 6 /* ExecuteSemanticQueryTransformError */) {\n errorDetails = PowerBIErrorDetailHelper.GetDetailsFromTransformError(resourceProvider, this.m_serviceError);\n }\n else {\n errorDetails = PowerBIErrorDetailHelper.GetDetailsFromServerErrorStatusCode(resourceProvider, this.m_serviceError.statusCode);\n }\n PowerBIErrorDetailHelper.addAdditionalInfo(errorDetails, this.m_serviceError.errorDetails, resourceProvider);\n PowerBIErrorDetailHelper.addMessageAndStackTrace(errorDetails, this.m_serviceError.message || null, this.m_serviceError.stackTrace || null, resourceProvider);\n return errorDetails;\n };\n ServiceErrorToClientError.codeName = 'ServiceErrorToClientError';\n return ServiceErrorToClientError;\n }());\n powerbi.ServiceErrorToClientError = ServiceErrorToClientError;\n var PowerBIErrorDetailHelper = (function () {\n function PowerBIErrorDetailHelper() {\n }\n PowerBIErrorDetailHelper.addAdditionalInfo = function (errorDetails, pbiErrorDetails, localize) {\n if (pbiErrorDetails) {\n for (var i = 0; i < pbiErrorDetails.length; i++) {\n var element = pbiErrorDetails[i];\n var localizedCode = localize.getOptional(PowerBIErrorDetailHelper.serverErrorPrefix + element.code);\n var additionErrorInfoKeyValuePair = {\n errorInfoKey: localizedCode ? localizedCode : element.code,\n errorInfoValue: element.detail.type === PowerBIErrorResourceType.ResourceCodeReference ? localize.get(PowerBIErrorDetailHelper.serverErrorPrefix + element.detail.value) : element.detail.value\n };\n errorDetails.additionalErrorInfo.push(additionErrorInfoKeyValuePair);\n }\n }\n return errorDetails;\n };\n PowerBIErrorDetailHelper.addMessageAndStackTrace = function (errorDetails, message, stackTrace, localize) {\n if (message) {\n var additionErrorInfoKeyValuePair = {\n errorInfoKey: localize.get(\"AdditionalErrorInfo_ErrorDetailsText\"),\n errorInfoValue: message\n };\n errorDetails.additionalErrorInfo.push(additionErrorInfoKeyValuePair);\n }\n if (stackTrace) {\n var additionErrorInfoKeyValuePair = {\n errorInfoKey: localize.get(\"AdditionalErrorInfo_StackTraceText\"),\n errorInfoValue: stackTrace\n };\n errorDetails.additionalErrorInfo.push(additionErrorInfoKeyValuePair);\n }\n return errorDetails;\n };\n PowerBIErrorDetailHelper.GetDetailsFromTransformError = function (localize, serviceError) {\n var message = localize.get('ServiceError_CannotLoadVisual');\n var key = localize.get('ServiceError_CannotLoadVisual');\n var val = serviceError.message;\n var additionalInfo = [];\n additionalInfo.push({ errorInfoKey: key, errorInfoValue: val, });\n var errorDetails = {\n message: message,\n additionalErrorInfo: additionalInfo,\n };\n return errorDetails;\n };\n PowerBIErrorDetailHelper.GetDetailsFromServerErrorStatusCode = function (localize, statusCode) {\n // TODO: Localize\n var message = \"\";\n var key = \"\";\n var val = \"\";\n switch (statusCode) {\n case 2 /* CsdlConvertXmlToConceptualSchema */:\n message = localize.get('ServiceError_ModelCannotLoad');\n key = localize.get('ServiceError_ModelConvertFailureKey');\n val = localize.get('ServiceError_ModelConvertFailureValue');\n break;\n case 3 /* CsdlCreateClientSchema */:\n message = localize.get('ServiceError_ModelCannotLoad');\n key = localize.get('ServiceError_ModelCreationFailureKey');\n val = localize.get('ServiceError_ModelCreationFailureValue');\n break;\n case 1 /* CsdlFetching */:\n message = localize.get('ServiceError_ModelCannotLoad');\n key = localize.get('ServiceError_ModelFetchingFailureKey');\n val = localize.get('ServiceError_ModelFetchingFailureValue');\n break;\n case 4 /* ExecuteSemanticQueryError */:\n message = localize.get('ServiceError_CannotLoadVisual');\n key = localize.get('ServiceError_ExecuteSemanticQueryErrorKey');\n val = localize.get('ServiceError_ExecuteSemanticQueryErrorValue');\n break;\n case 5 /* ExecuteSemanticQueryInvalidStreamFormat */:\n message = localize.get('ServiceError_CannotLoadVisual');\n key = localize.get('ServiceError_ExecuteSemanticQueryInvalidStreamFormatKey');\n val = localize.get('ServiceError_ExecuteSemanticQueryInvalidStreamFormatValue');\n break;\n case 0 /* GeneralError */:\n default:\n message = localize.get('ServiceError_GeneralError');\n key = localize.get('ServiceError_GeneralErrorKey');\n val = localize.get('ServiceError_GeneralErrorValue');\n break;\n }\n var additionalInfo = [];\n additionalInfo.push({ errorInfoKey: key, errorInfoValue: val, });\n var errorDetails = {\n message: message,\n additionalErrorInfo: additionalInfo,\n };\n return errorDetails;\n };\n PowerBIErrorDetailHelper.serverErrorPrefix = \"ServerError_\";\n return PowerBIErrorDetailHelper;\n }());\n powerbi.PowerBIErrorDetailHelper = PowerBIErrorDetailHelper;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n powerbi.CategoryTypes = {\n Address: \"Address\",\n City: \"City\",\n Continent: \"Continent\",\n CountryRegion: \"Country\",\n County: \"County\",\n Longitude: \"Longitude\",\n Latitude: \"Latitude\",\n Place: \"Place\",\n PostalCode: \"PostalCode\",\n StateOrProvince: \"StateOrProvince\"\n };\n function createGeoTaggingAnalyzerService(getLocalized) {\n return new GeoTaggingAnalyzerService(getLocalized);\n }\n powerbi.createGeoTaggingAnalyzerService = createGeoTaggingAnalyzerService;\n var EnglishBackup = {\n GeotaggingString_Continent: \"continent\",\n GeotaggingString_Continents: \"continents\",\n GeotaggingString_Country: \"country\",\n GeotaggingString_Countries: \"countries\",\n GeotaggingString_State: \"state\",\n GeotaggingString_States: \"states\",\n GeotaggingString_City: \"city\",\n GeotaggingString_Cities: \"cities\",\n GeotaggingString_Town: \"town\",\n GeotaggingString_Towns: \"towns\",\n GeotaggingString_Province: \"province\",\n GeotaggingString_Provinces: \"provinces\",\n GeotaggingString_County: \"county\",\n GeotaggingString_Counties: \"counties\",\n GeotaggingString_Village: \"village\",\n GeotaggingString_Villages: \"villages\",\n GeotaggingString_Post: \"post\",\n GeotaggingString_Zip: \"zip\",\n GeotaggingString_Code: \"code\",\n GeotaggingString_Place: \"place\",\n GeotaggingString_Places: \"places\",\n GeotaggingString_Address: \"address\",\n GeotaggingString_Addresses: \"addresses\",\n GeotaggingString_Street: \"street\",\n GeotaggingString_Streets: \"streets\",\n GeotaggingString_Longitude: \"longitude\",\n GeotaggingString_Longitude_Short: \"lon\",\n GeotaggingString_Latitude: \"latitude\",\n GeotaggingString_Latitude_Short: \"lat\",\n GeotaggingString_PostalCode: \"postal code\",\n GeotaggingString_PostalCodes: \"postal codes\",\n GeotaggingString_ZipCode: \"zip code\",\n GeotaggingString_ZipCodes: \"zip codes\",\n GeotaggingString_Territory: \"territory\",\n GeotaggingString_Territories: \"territories\",\n GeotaggingString_VRMBackCompat_CountryRegion: \"CountryRegion\",\n GeotaggingString_VRMBackCompat_StateOrProvince: \"StateOrProvince\",\n };\n var GeoTaggingAnalyzerService = (function () {\n function GeoTaggingAnalyzerService(getLocalized) {\n this.GeotaggingString_VRMBackCompat_CountryRegion = \"CountryRegion\";\n this.GeotaggingString_VRMBackCompat_StateOrProvince = \"StateOrProvince\";\n this.GeotaggingString_Continent = getLocalized(\"GeotaggingString_Continent\").toLowerCase();\n this.GeotaggingString_Continents = getLocalized(\"GeotaggingString_Continents\").toLowerCase();\n this.GeotaggingString_Country = getLocalized(\"GeotaggingString_Country\").toLowerCase();\n this.GeotaggingString_Countries = getLocalized(\"GeotaggingString_Countries\").toLowerCase();\n this.GeotaggingString_State = getLocalized(\"GeotaggingString_State\").toLowerCase();\n this.GeotaggingString_States = getLocalized(\"GeotaggingString_States\").toLowerCase();\n this.GeotaggingString_City = getLocalized(\"GeotaggingString_City\").toLowerCase();\n this.GeotaggingString_Cities = getLocalized(\"GeotaggingString_Cities\").toLowerCase();\n this.GeotaggingString_Town = getLocalized(\"GeotaggingString_Town\").toLowerCase();\n this.GeotaggingString_Towns = getLocalized(\"GeotaggingString_Towns\").toLowerCase();\n this.GeotaggingString_Province = getLocalized(\"GeotaggingString_Province\").toLowerCase();\n this.GeotaggingString_Provinces = getLocalized(\"GeotaggingString_Provinces\").toLowerCase();\n this.GeotaggingString_County = getLocalized(\"GeotaggingString_County\").toLowerCase();\n this.GeotaggingString_Counties = getLocalized(\"GeotaggingString_Counties\").toLowerCase();\n this.GeotaggingString_Village = getLocalized(\"GeotaggingString_Village\").toLowerCase();\n this.GeotaggingString_Villages = getLocalized(\"GeotaggingString_Villages\").toLowerCase();\n this.GeotaggingString_Post = getLocalized(\"GeotaggingString_Post\").toLowerCase();\n this.GeotaggingString_Zip = getLocalized(\"GeotaggingString_Zip\").toLowerCase();\n this.GeotaggingString_Code = getLocalized(\"GeotaggingString_Code\").toLowerCase();\n this.GeotaggingString_Place = getLocalized(\"GeotaggingString_Place\").toLowerCase();\n this.GeotaggingString_Places = getLocalized(\"GeotaggingString_Places\").toLowerCase();\n this.GeotaggingString_Address = getLocalized(\"GeotaggingString_Address\").toLowerCase();\n this.GeotaggingString_Addresses = getLocalized(\"GeotaggingString_Addresses\").toLowerCase();\n this.GeotaggingString_Street = getLocalized(\"GeotaggingString_Street\").toLowerCase();\n this.GeotaggingString_Streets = getLocalized(\"GeotaggingString_Streets\").toLowerCase();\n this.GeotaggingString_Longitude = getLocalized(\"GeotaggingString_Longitude\").toLowerCase();\n this.GeotaggingString_Longitude_Short = getLocalized(\"GeotaggingString_Longitude_Short\").toLowerCase();\n this.GeotaggingString_Latitude = getLocalized(\"GeotaggingString_Latitude\").toLowerCase();\n this.GeotaggingString_Latitude_Short = getLocalized(\"GeotaggingString_Latitude_Short\").toLowerCase();\n this.GeotaggingString_PostalCode = getLocalized(\"GeotaggingString_PostalCode\").toLowerCase();\n this.GeotaggingString_PostalCodes = getLocalized(\"GeotaggingString_PostalCodes\").toLowerCase();\n this.GeotaggingString_ZipCode = getLocalized(\"GeotaggingString_ZipCode\").toLowerCase();\n this.GeotaggingString_ZipCodes = getLocalized(\"GeotaggingString_ZipCodes\").toLowerCase();\n this.GeotaggingString_Territory = getLocalized(\"GeotaggingString_Territory\").toLowerCase();\n this.GeotaggingString_Territories = getLocalized(\"GeotaggingString_Territories\").toLowerCase();\n }\n GeoTaggingAnalyzerService.prototype.isLongitudeOrLatitude = function (fieldRefName) {\n return this.isLongitude(fieldRefName) ||\n this.isLatitude(fieldRefName);\n };\n GeoTaggingAnalyzerService.prototype.isGeographic = function (fieldRefName) {\n return this.isLongitudeOrLatitude(fieldRefName) ||\n this.isGeocodable(fieldRefName);\n };\n GeoTaggingAnalyzerService.prototype.isGeocodable = function (fieldRefName) {\n return this.isAddress(fieldRefName) ||\n this.isCity(fieldRefName) ||\n this.isContinent(fieldRefName) ||\n this.isCountry(fieldRefName) ||\n this.isCounty(fieldRefName) ||\n this.isStateOrProvince(fieldRefName) ||\n this.isPlace(fieldRefName) ||\n this.isPostalCode(fieldRefName) ||\n this.isTerritory(fieldRefName);\n };\n GeoTaggingAnalyzerService.prototype.isGeoshapable = function (fieldRefName) {\n return this.isCity(fieldRefName) ||\n this.isCountry(fieldRefName) ||\n this.isCounty(fieldRefName) ||\n this.isStateOrProvince(fieldRefName) ||\n this.isPostalCode(fieldRefName) ||\n this.isTerritory(fieldRefName) ||\n this.isGeoshapableEnglish(fieldRefName);\n };\n GeoTaggingAnalyzerService.prototype.isGeoshapableEnglish = function (fieldRefName) {\n return this.isEnglishCity(fieldRefName) ||\n this.isEnglishCountry(fieldRefName) ||\n this.isEnglishCounty(fieldRefName) ||\n this.isEnglishStateOrProvince(fieldRefName) ||\n this.isEnglishPostalCode(fieldRefName) ||\n this.isEnglishTerritory(fieldRefName);\n };\n GeoTaggingAnalyzerService.prototype.isAddress = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_Address,\n this.GeotaggingString_Addresses,\n this.GeotaggingString_Street,\n this.GeotaggingString_Streets\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isPlace = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_Place,\n this.GeotaggingString_Places\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isCity = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_City,\n this.GeotaggingString_Cities,\n this.GeotaggingString_Town,\n this.GeotaggingString_Towns,\n this.GeotaggingString_Village,\n this.GeotaggingString_Villages\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isStateOrProvince = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_State,\n this.GeotaggingString_States,\n this.GeotaggingString_Province,\n this.GeotaggingString_Provinces,\n this.GeotaggingString_VRMBackCompat_StateOrProvince,\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isCountry = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_Country,\n this.GeotaggingString_Countries,\n this.GeotaggingString_VRMBackCompat_CountryRegion\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isCounty = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_County,\n this.GeotaggingString_Counties\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isContinent = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_Continent,\n this.GeotaggingString_Continents\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isPostalCode = function (fieldRefName) {\n var result = (GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_Post,\n this.GeotaggingString_Zip])\n && GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Code])) ||\n GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_PostalCode,\n this.GeotaggingString_PostalCodes,\n this.GeotaggingString_ZipCode,\n this.GeotaggingString_ZipCodes\n ]);\n //Check again for strings without whitespace\n if (!result) {\n var whiteSpaceRegex = /\\s+/;\n var fieldNameWithoutWhitespace = fieldRefName.replace(whiteSpaceRegex, \"\");\n result = GeoTaggingAnalyzerService.hasMatches(fieldNameWithoutWhitespace, [\n this.GeotaggingString_PostalCode.replace(whiteSpaceRegex, ''),\n this.GeotaggingString_PostalCodes.replace(whiteSpaceRegex, ''),\n this.GeotaggingString_ZipCode.replace(whiteSpaceRegex, ''),\n this.GeotaggingString_ZipCodes.replace(whiteSpaceRegex, '')\n ]);\n }\n return result;\n };\n GeoTaggingAnalyzerService.prototype.isLongitude = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Longitude])\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Longitude_Short], true /* useStrict */);\n };\n GeoTaggingAnalyzerService.prototype.isLatitude = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Latitude])\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Latitude_Short], true /* useStrict */);\n };\n GeoTaggingAnalyzerService.prototype.isTerritory = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n this.GeotaggingString_Territory,\n this.GeotaggingString_Territories\n ]);\n };\n GeoTaggingAnalyzerService.hasMatches = function (fieldName, possibleMatches, useStrict) {\n var nonWordRegex = /\\W/;\n var value = fieldName.toLowerCase();\n for (var i = 0, len = possibleMatches.length; i < len; i++) {\n var possibleMatch = possibleMatches[i].toLowerCase();\n if (!useStrict) {\n if (value.indexOf(possibleMatch) > -1)\n return true;\n }\n else {\n var indexofpossibleMatch = value.indexOf(possibleMatch);\n if (indexofpossibleMatch > -1) {\n var wordEndFlag = void 0, wordBeginFlag = void 0;\n wordEndFlag = wordBeginFlag = true;\n if (indexofpossibleMatch - 1 > 0)\n wordBeginFlag = nonWordRegex.test(value[indexofpossibleMatch - 1]);\n if (indexofpossibleMatch + possibleMatch.length < value.length)\n wordEndFlag = nonWordRegex.test(value[indexofpossibleMatch + possibleMatch.length]);\n if (wordBeginFlag && wordEndFlag)\n return true;\n }\n }\n }\n return false;\n };\n GeoTaggingAnalyzerService.prototype.getFieldType = function (fieldName) {\n if (fieldName == null)\n return undefined;\n if (this.isLatitude(fieldName))\n return powerbi.CategoryTypes.Latitude;\n if (this.isLongitude(fieldName))\n return powerbi.CategoryTypes.Longitude;\n if (this.isPostalCode(fieldName))\n return powerbi.CategoryTypes.PostalCode;\n if (this.isAddress(fieldName))\n return powerbi.CategoryTypes.Address;\n if (this.isPlace(fieldName))\n return powerbi.CategoryTypes.Place;\n if (this.isCity(fieldName))\n return powerbi.CategoryTypes.City;\n if (this.isCountry(fieldName))\n return powerbi.CategoryTypes.CountryRegion;\n if (this.isCounty(fieldName))\n return powerbi.CategoryTypes.County;\n if (this.isStateOrProvince(fieldName))\n return powerbi.CategoryTypes.StateOrProvince;\n if (this.isContinent(fieldName))\n return powerbi.CategoryTypes.Continent;\n return this.getEnglishFieldType(fieldName);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishAddress = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_Address,\n EnglishBackup.GeotaggingString_Addresses,\n EnglishBackup.GeotaggingString_Street,\n EnglishBackup.GeotaggingString_Streets\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishPlace = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_Place,\n EnglishBackup.GeotaggingString_Places\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishCity = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_City,\n EnglishBackup.GeotaggingString_Cities,\n EnglishBackup.GeotaggingString_Town,\n EnglishBackup.GeotaggingString_Towns,\n EnglishBackup.GeotaggingString_Village,\n EnglishBackup.GeotaggingString_Villages\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishStateOrProvince = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_State,\n EnglishBackup.GeotaggingString_States,\n EnglishBackup.GeotaggingString_Province,\n EnglishBackup.GeotaggingString_Provinces,\n EnglishBackup.GeotaggingString_VRMBackCompat_StateOrProvince,\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishCountry = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_Country,\n EnglishBackup.GeotaggingString_Countries,\n EnglishBackup.GeotaggingString_VRMBackCompat_CountryRegion\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishCounty = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_County,\n EnglishBackup.GeotaggingString_Counties\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishContinent = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_Continent,\n EnglishBackup.GeotaggingString_Continents\n ]);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishPostalCode = function (fieldRefName) {\n var result = (GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_Post,\n EnglishBackup.GeotaggingString_Zip])\n && GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Code])) ||\n GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_PostalCode,\n EnglishBackup.GeotaggingString_PostalCodes,\n EnglishBackup.GeotaggingString_ZipCode,\n EnglishBackup.GeotaggingString_ZipCodes\n ]);\n //Check again for strings without whitespace\n if (!result) {\n var whiteSpaceRegexPattern = new RegExp('\\s');\n result = GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_PostalCode.replace(whiteSpaceRegexPattern, ''),\n EnglishBackup.GeotaggingString_PostalCodes.replace(whiteSpaceRegexPattern, ''),\n EnglishBackup.GeotaggingString_ZipCode.replace(whiteSpaceRegexPattern, ''),\n EnglishBackup.GeotaggingString_ZipCodes.replace(whiteSpaceRegexPattern, '')\n ]);\n }\n return result;\n };\n GeoTaggingAnalyzerService.prototype.isEnglishLongitude = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Longitude])\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Longitude_Short], true /* useStrict */);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishLatitude = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Latitude])\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Latitude_Short], true /* useStrict */);\n };\n GeoTaggingAnalyzerService.prototype.isEnglishTerritory = function (fieldRefName) {\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\n EnglishBackup.GeotaggingString_Territory,\n EnglishBackup.GeotaggingString_Territories\n ]);\n };\n GeoTaggingAnalyzerService.prototype.getEnglishFieldType = function (fieldName) {\n if (fieldName == null)\n return undefined;\n if (this.isEnglishLatitude(fieldName))\n return powerbi.CategoryTypes.Latitude;\n if (this.isEnglishLongitude(fieldName))\n return powerbi.CategoryTypes.Longitude;\n if (this.isEnglishPostalCode(fieldName))\n return powerbi.CategoryTypes.PostalCode;\n if (this.isEnglishAddress(fieldName))\n return powerbi.CategoryTypes.Address;\n if (this.isEnglishPlace(fieldName))\n return powerbi.CategoryTypes.Place;\n if (this.isEnglishCity(fieldName))\n return powerbi.CategoryTypes.City;\n if (this.isEnglishCountry(fieldName))\n return powerbi.CategoryTypes.CountryRegion;\n if (this.isEnglishCounty(fieldName))\n return powerbi.CategoryTypes.County;\n if (this.isEnglishStateOrProvince(fieldName))\n return powerbi.CategoryTypes.StateOrProvince;\n if (this.isEnglishContinent(fieldName))\n return powerbi.CategoryTypes.Continent;\n return undefined;\n };\n return GeoTaggingAnalyzerService;\n }());\n powerbi.GeoTaggingAnalyzerService = GeoTaggingAnalyzerService;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nif (typeof DEBUG === 'undefined')\n var DEBUG = true;\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n /**\n this base class should be derived to give a generic error message but with a unique error code.\n */\n var UnknownClientError = (function () {\n function UnknownClientError(code) {\n debug.assertValue(code, 'code');\n this.errorCode = code;\n }\n Object.defineProperty(UnknownClientError.prototype, \"code\", {\n get: function () {\n return this.errorCode;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(UnknownClientError.prototype, \"ignorable\", {\n get: function () {\n return false;\n },\n enumerable: true,\n configurable: true\n });\n UnknownClientError.prototype.getDetails = function (resourceProvider) {\n var details = {\n message: resourceProvider.get('ClientError_UnknownClientErrorValue'),\n additionalErrorInfo: [{ errorInfoKey: resourceProvider.get('ClientError_UnknownClientErrorKey'), errorInfoValue: resourceProvider.get('ClientError_UnknownClientErrorValue'), }],\n };\n return details;\n };\n return UnknownClientError;\n }());\n powerbi.UnknownClientError = UnknownClientError;\n var HttpClientError = (function () {\n function HttpClientError(httpStatusCode, requestId) {\n debug.assertValue(httpStatusCode, 'httpStatusCode');\n debug.assertValue(requestId, 'requestId');\n this.httpStatusCode = httpStatusCode;\n this.httpRequestId = requestId;\n }\n Object.defineProperty(HttpClientError.prototype, \"code\", {\n get: function () {\n return 'HttpClientError';\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(HttpClientError.prototype, \"ignorable\", {\n get: function () {\n return false;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(HttpClientError.prototype, \"requestId\", {\n get: function () {\n return this.httpRequestId;\n },\n enumerable: true,\n configurable: true\n });\n HttpClientError.prototype.getDetails = function (resourceProvider) {\n // Use a general error message for a HTTP request failure, since we currently do not know of any specifc error cases at this point in time.\n var details = {\n message: null,\n additionalErrorInfo: [\n { errorInfoKey: resourceProvider.get('DsrError_Key'), errorInfoValue: resourceProvider.get('DsrError_UnknownErrorValue') },\n { errorInfoKey: resourceProvider.get('ClientError_HttpResponseStatusCodeKey'), errorInfoValue: this.httpStatusCode.toString() }],\n };\n return details;\n };\n return HttpClientError;\n }());\n powerbi.HttpClientError = HttpClientError;\n var IgnorableClientError = (function () {\n function IgnorableClientError() {\n }\n Object.defineProperty(IgnorableClientError.prototype, \"code\", {\n get: function () {\n return 'IgnorableClientError';\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(IgnorableClientError.prototype, \"ignorable\", {\n get: function () {\n return true;\n },\n enumerable: true,\n configurable: true\n });\n IgnorableClientError.prototype.getDetails = function (resourceProvider) {\n var details = {\n message: '',\n additionalErrorInfo: [],\n };\n return details;\n };\n return IgnorableClientError;\n }());\n powerbi.IgnorableClientError = IgnorableClientError;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var ArrayExtensions;\n (function (ArrayExtensions) {\n /**\n * Returns items that exist in target and other.\n */\n function intersect(target, other) {\n var result = [];\n for (var i = target.length - 1; i >= 0; --i) {\n if (other.indexOf(target[i]) !== -1) {\n result.push(target[i]);\n }\n }\n return result;\n }\n ArrayExtensions.intersect = intersect;\n /**\n * Return elements exists in target but not exists in other.\n */\n function diff(target, other) {\n var result = [];\n for (var i = target.length - 1; i >= 0; --i) {\n var value = target[i];\n if (other.indexOf(value) === -1) {\n result.push(value);\n }\n }\n return result;\n }\n ArrayExtensions.diff = diff;\n /**\n * Return an array with only the distinct items in the source.\n */\n function distinct(source) {\n var result = [];\n for (var i = 0, len = source.length; i < len; i++) {\n var value = source[i];\n if (result.indexOf(value) === -1) {\n result.push(value);\n }\n }\n return result;\n }\n ArrayExtensions.distinct = distinct;\n /**\n * Pushes content of source onto target,\n * for parts of course that do not already exist in target.\n */\n function union(target, source) {\n for (var i = 0, len = source.length; i < len; ++i) {\n unionSingle(target, source[i]);\n }\n }\n ArrayExtensions.union = union;\n /**\n * Pushes value onto target, if value does not already exist in target.\n */\n function unionSingle(target, value) {\n if (target.indexOf(value) < 0) {\n target.push(value);\n }\n }\n ArrayExtensions.unionSingle = unionSingle;\n /**\n * Returns an array with a range of items from source,\n * including the startIndex & endIndex.\n */\n function range(source, startIndex, endIndex) {\n debug.assert(startIndex >= 0 && startIndex < source.length, 'startIndex is out of range.');\n debug.assert(endIndex >= 0 && endIndex < source.length, 'endIndex is out of range.');\n var result = [];\n for (var i = startIndex; i <= endIndex; ++i) {\n result.push(source[i]);\n }\n return result;\n }\n ArrayExtensions.range = range;\n /**\n * Returns an array that includes items from source, up to the specified count.\n */\n function take(source, count) {\n debug.assert(count >= 0, 'Count is negative.');\n debug.assert(count <= source.length, 'Count is too large.');\n var result = [];\n for (var i = 0; i < count; ++i) {\n result.push(source[i]);\n }\n return result;\n }\n ArrayExtensions.take = take;\n function copy(source) {\n debug.assertValue(source, 'source');\n return take(source, source.length);\n }\n ArrayExtensions.copy = copy;\n /**\n * Returns a value indicating whether the arrays have the same values in the same sequence.\n */\n function sequenceEqual(left, right, comparison) {\n debug.assertValue(comparison, 'comparison');\n if (left === right) {\n return true;\n }\n if (!!left !== !!right) {\n return false;\n }\n var len = left.length;\n if (len !== right.length) {\n return false;\n }\n var i = 0;\n while (i < len && comparison(left[i], right[i])) {\n ++i;\n }\n return i === len;\n }\n ArrayExtensions.sequenceEqual = sequenceEqual;\n /**\n * Returns null if the specified array is empty.\n * Otherwise returns the specified array.\n */\n function emptyToNull(array) {\n if (array && array.length === 0) {\n return null;\n }\n return array;\n }\n ArrayExtensions.emptyToNull = emptyToNull;\n function indexOf(array, predicate) {\n debug.assertValue(array, 'array');\n debug.assertValue(predicate, 'predicate');\n for (var i = 0, len = array.length; i < len; ++i) {\n if (predicate(array[i])) {\n return i;\n }\n }\n return -1;\n }\n ArrayExtensions.indexOf = indexOf;\n /**\n * Returns a copy of the array rotated by the specified offset.\n */\n function rotate(array, offset) {\n if (offset === 0)\n return array.slice();\n var rotated = array.slice(offset);\n Array.prototype.push.apply(rotated, array.slice(0, offset));\n return rotated;\n }\n ArrayExtensions.rotate = rotate;\n function createWithId() {\n return extendWithId([]);\n }\n ArrayExtensions.createWithId = createWithId;\n function extendWithId(array) {\n debug.assertValue(array, 'array');\n var extended = array;\n extended.withId = withId;\n return extended;\n }\n ArrayExtensions.extendWithId = extendWithId;\n /**\n * Finds and returns the first item with a matching ID.\n */\n function findWithId(array, id) {\n for (var i = 0, len = array.length; i < len; i++) {\n var item = array[i];\n if (item.id === id)\n return item;\n }\n }\n ArrayExtensions.findWithId = findWithId;\n function withId(id) {\n return ArrayExtensions.findWithId(this, id);\n }\n function createWithName() {\n return extendWithName([]);\n }\n ArrayExtensions.createWithName = createWithName;\n function extendWithName(array) {\n debug.assertValue(array, 'array');\n var extended = array;\n extended.withName = withName;\n return extended;\n }\n ArrayExtensions.extendWithName = extendWithName;\n function findItemWithName(array, name) {\n var index = indexWithName(array, name);\n if (index >= 0)\n return array[index];\n }\n ArrayExtensions.findItemWithName = findItemWithName;\n function indexWithName(array, name) {\n for (var i = 0, len = array.length; i < len; i++) {\n var item = array[i];\n if (item.name === name)\n return i;\n }\n return -1;\n }\n ArrayExtensions.indexWithName = indexWithName;\n /**\n * Inserts a number in sorted order into a list of numbers already in sorted order.\n * @returns True if the item was added, false if it already existed.\n */\n function insertSorted(list, value) {\n debug.assertValue(list, 'list');\n debug.assertValue(value, 'value');\n var len = list.length;\n // NOTE: iterate backwards because incoming values tend to be sorted already.\n for (var i = len - 1; i >= 0; i--) {\n var diff_1 = list[i] - value;\n if (diff_1 === 0)\n return false;\n if (diff_1 > 0)\n continue;\n // diff < 0\n list.splice(i + 1, 0, value);\n return true;\n }\n list.unshift(value);\n return true;\n }\n ArrayExtensions.insertSorted = insertSorted;\n /**\n * Removes the first occurrence of a value from a list if it exists.\n * @returns True if the value was removed, false if it did not exist in the list.\n */\n function removeFirst(list, value) {\n var index = list.indexOf(value);\n if (index < 0)\n return false;\n list.splice(index, 1);\n return true;\n }\n ArrayExtensions.removeFirst = removeFirst;\n /**\n * Finds and returns the first item with a matching name.\n */\n function withName(name) {\n var array = this;\n return findItemWithName(array, name);\n }\n /**\n * Deletes all items from the array.\n */\n function clear(array) {\n if (!array)\n return;\n while (array.length > 0)\n array.pop();\n }\n ArrayExtensions.clear = clear;\n function isUndefinedOrEmpty(array) {\n if (!array || array.length === 0) {\n return true;\n }\n return false;\n }\n ArrayExtensions.isUndefinedOrEmpty = isUndefinedOrEmpty;\n function swap(array, firstIndex, secondIndex) {\n var temp = array[firstIndex];\n array[firstIndex] = array[secondIndex];\n array[secondIndex] = temp;\n }\n ArrayExtensions.swap = swap;\n function isInArray(array, lookupItem, compareCallback) {\n return _.any(array, function (item) { return compareCallback(item, lookupItem); });\n }\n ArrayExtensions.isInArray = isInArray;\n /** Checks if the given object is an Array, and looking all the way up the prototype chain. */\n function isArrayOrInheritedArray(obj) {\n debug.assertValue(obj, 'obj');\n var nextPrototype = obj;\n while (nextPrototype != null) {\n if (_.isArray(nextPrototype))\n return true;\n nextPrototype = Object.getPrototypeOf(nextPrototype);\n }\n return false;\n }\n ArrayExtensions.isArrayOrInheritedArray = isArrayOrInheritedArray;\n })(ArrayExtensions = jsCommon.ArrayExtensions || (jsCommon.ArrayExtensions = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar InJs;\n(function (InJs) {\n var DomFactory;\n (function (DomFactory) {\n function div() {\n return $('<div/>');\n }\n DomFactory.div = div;\n function span() {\n return $('<span/>');\n }\n DomFactory.span = span;\n function checkbox() {\n return $('<input type=\"checkbox\"/>');\n }\n DomFactory.checkbox = checkbox;\n function ul() {\n return $('<ul/>');\n }\n DomFactory.ul = ul;\n function li() {\n return $('<li/>');\n }\n DomFactory.li = li;\n function button() {\n return $('<input type=\"button\"/>');\n }\n DomFactory.button = button;\n function select() {\n return $('<select/>');\n }\n DomFactory.select = select;\n function textBox() {\n return $('<input type=\"text\"/>');\n }\n DomFactory.textBox = textBox;\n function img() {\n return $('<img/>');\n }\n DomFactory.img = img;\n function iframe() {\n return $('<iframe/>');\n }\n DomFactory.iframe = iframe;\n })(DomFactory = InJs.DomFactory || (InJs.DomFactory = {}));\n})(InJs || (InJs = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n /**\n * Module Double contains a set of constants and precision based utility methods\n * for dealing with doubles and their decimal garbage in the javascript.\n */\n var Double;\n (function (Double) {\n // Constants.\n Double.MIN_VALUE = -Number.MAX_VALUE;\n Double.MAX_VALUE = Number.MAX_VALUE;\n Double.MIN_EXP = -308;\n Double.MAX_EXP = 308;\n Double.EPSILON = 1E-323;\n Double.DEFAULT_PRECISION = 0.0001;\n Double.DEFAULT_PRECISION_IN_DECIMAL_DIGITS = 12;\n Double.LOG_E_10 = Math.log(10);\n Double.POSITIVE_POWERS = [\n 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15, 1E16, 1E17, 1E18, 1E19, 1E20, 1E21, 1E22, 1E23, 1E24, 1E25, 1E26, 1E27, 1E28, 1E29, 1E30, 1E31, 1E32, 1E33, 1E34, 1E35, 1E36, 1E37, 1E38, 1E39, 1E40, 1E41, 1E42, 1E43, 1E44, 1E45, 1E46, 1E47, 1E48, 1E49, 1E50, 1E51, 1E52, 1E53, 1E54, 1E55, 1E56, 1E57, 1E58, 1E59, 1E60, 1E61, 1E62, 1E63, 1E64, 1E65, 1E66, 1E67, 1E68, 1E69, 1E70, 1E71, 1E72, 1E73, 1E74, 1E75, 1E76, 1E77, 1E78, 1E79, 1E80, 1E81, 1E82, 1E83, 1E84, 1E85, 1E86, 1E87, 1E88, 1E89, 1E90, 1E91, 1E92, 1E93, 1E94, 1E95, 1E96, 1E97, 1E98, 1E99,\n 1E100, 1E101, 1E102, 1E103, 1E104, 1E105, 1E106, 1E107, 1E108, 1E109, 1E110, 1E111, 1E112, 1E113, 1E114, 1E115, 1E116, 1E117, 1E118, 1E119, 1E120, 1E121, 1E122, 1E123, 1E124, 1E125, 1E126, 1E127, 1E128, 1E129, 1E130, 1E131, 1E132, 1E133, 1E134, 1E135, 1E136, 1E137, 1E138, 1E139, 1E140, 1E141, 1E142, 1E143, 1E144, 1E145, 1E146, 1E147, 1E148, 1E149, 1E150, 1E151, 1E152, 1E153, 1E154, 1E155, 1E156, 1E157, 1E158, 1E159, 1E160, 1E161, 1E162, 1E163, 1E164, 1E165, 1E166, 1E167, 1E168, 1E169, 1E170, 1E171, 1E172, 1E173, 1E174, 1E175, 1E176, 1E177, 1E178, 1E179, 1E180, 1E181, 1E182, 1E183, 1E184, 1E185, 1E186, 1E187, 1E188, 1E189, 1E190, 1E191, 1E192, 1E193, 1E194, 1E195, 1E196, 1E197, 1E198, 1E199,\n 1E200, 1E201, 1E202, 1E203, 1E204, 1E205, 1E206, 1E207, 1E208, 1E209, 1E210, 1E211, 1E212, 1E213, 1E214, 1E215, 1E216, 1E217, 1E218, 1E219, 1E220, 1E221, 1E222, 1E223, 1E224, 1E225, 1E226, 1E227, 1E228, 1E229, 1E230, 1E231, 1E232, 1E233, 1E234, 1E235, 1E236, 1E237, 1E238, 1E239, 1E240, 1E241, 1E242, 1E243, 1E244, 1E245, 1E246, 1E247, 1E248, 1E249, 1E250, 1E251, 1E252, 1E253, 1E254, 1E255, 1E256, 1E257, 1E258, 1E259, 1E260, 1E261, 1E262, 1E263, 1E264, 1E265, 1E266, 1E267, 1E268, 1E269, 1E270, 1E271, 1E272, 1E273, 1E274, 1E275, 1E276, 1E277, 1E278, 1E279, 1E280, 1E281, 1E282, 1E283, 1E284, 1E285, 1E286, 1E287, 1E288, 1E289, 1E290, 1E291, 1E292, 1E293, 1E294, 1E295, 1E296, 1E297, 1E298, 1E299,\n 1E300, 1E301, 1E302, 1E303, 1E304, 1E305, 1E306, 1E307, 1E308];\n Double.NEGATIVE_POWERS = [\n 1E0, 1E-1, 1E-2, 1E-3, 1E-4, 1E-5, 1E-6, 1E-7, 1E-8, 1E-9, 1E-10, 1E-11, 1E-12, 1E-13, 1E-14, 1E-15, 1E-16, 1E-17, 1E-18, 1E-19, 1E-20, 1E-21, 1E-22, 1E-23, 1E-24, 1E-25, 1E-26, 1E-27, 1E-28, 1E-29, 1E-30, 1E-31, 1E-32, 1E-33, 1E-34, 1E-35, 1E-36, 1E-37, 1E-38, 1E-39, 1E-40, 1E-41, 1E-42, 1E-43, 1E-44, 1E-45, 1E-46, 1E-47, 1E-48, 1E-49, 1E-50, 1E-51, 1E-52, 1E-53, 1E-54, 1E-55, 1E-56, 1E-57, 1E-58, 1E-59, 1E-60, 1E-61, 1E-62, 1E-63, 1E-64, 1E-65, 1E-66, 1E-67, 1E-68, 1E-69, 1E-70, 1E-71, 1E-72, 1E-73, 1E-74, 1E-75, 1E-76, 1E-77, 1E-78, 1E-79, 1E-80, 1E-81, 1E-82, 1E-83, 1E-84, 1E-85, 1E-86, 1E-87, 1E-88, 1E-89, 1E-90, 1E-91, 1E-92, 1E-93, 1E-94, 1E-95, 1E-96, 1E-97, 1E-98, 1E-99,\n 1E-100, 1E-101, 1E-102, 1E-103, 1E-104, 1E-105, 1E-106, 1E-107, 1E-108, 1E-109, 1E-110, 1E-111, 1E-112, 1E-113, 1E-114, 1E-115, 1E-116, 1E-117, 1E-118, 1E-119, 1E-120, 1E-121, 1E-122, 1E-123, 1E-124, 1E-125, 1E-126, 1E-127, 1E-128, 1E-129, 1E-130, 1E-131, 1E-132, 1E-133, 1E-134, 1E-135, 1E-136, 1E-137, 1E-138, 1E-139, 1E-140, 1E-141, 1E-142, 1E-143, 1E-144, 1E-145, 1E-146, 1E-147, 1E-148, 1E-149, 1E-150, 1E-151, 1E-152, 1E-153, 1E-154, 1E-155, 1E-156, 1E-157, 1E-158, 1E-159, 1E-160, 1E-161, 1E-162, 1E-163, 1E-164, 1E-165, 1E-166, 1E-167, 1E-168, 1E-169, 1E-170, 1E-171, 1E-172, 1E-173, 1E-174, 1E-175, 1E-176, 1E-177, 1E-178, 1E-179, 1E-180, 1E-181, 1E-182, 1E-183, 1E-184, 1E-185, 1E-186, 1E-187, 1E-188, 1E-189, 1E-190, 1E-191, 1E-192, 1E-193, 1E-194, 1E-195, 1E-196, 1E-197, 1E-198, 1E-199,\n 1E-200, 1E-201, 1E-202, 1E-203, 1E-204, 1E-205, 1E-206, 1E-207, 1E-208, 1E-209, 1E-210, 1E-211, 1E-212, 1E-213, 1E-214, 1E-215, 1E-216, 1E-217, 1E-218, 1E-219, 1E-220, 1E-221, 1E-222, 1E-223, 1E-224, 1E-225, 1E-226, 1E-227, 1E-228, 1E-229, 1E-230, 1E-231, 1E-232, 1E-233, 1E-234, 1E-235, 1E-236, 1E-237, 1E-238, 1E-239, 1E-240, 1E-241, 1E-242, 1E-243, 1E-244, 1E-245, 1E-246, 1E-247, 1E-248, 1E-249, 1E-250, 1E-251, 1E-252, 1E-253, 1E-254, 1E-255, 1E-256, 1E-257, 1E-258, 1E-259, 1E-260, 1E-261, 1E-262, 1E-263, 1E-264, 1E-265, 1E-266, 1E-267, 1E-268, 1E-269, 1E-270, 1E-271, 1E-272, 1E-273, 1E-274, 1E-275, 1E-276, 1E-277, 1E-278, 1E-279, 1E-280, 1E-281, 1E-282, 1E-283, 1E-284, 1E-285, 1E-286, 1E-287, 1E-288, 1E-289, 1E-290, 1E-291, 1E-292, 1E-293, 1E-294, 1E-295, 1E-296, 1E-297, 1E-298, 1E-299,\n 1E-300, 1E-301, 1E-302, 1E-303, 1E-304, 1E-305, 1E-306, 1E-307, 1E-308, 1E-309, 1E-310, 1E-311, 1E-312, 1E-313, 1E-314, 1E-315, 1E-316, 1E-317, 1E-318, 1E-319, 1E-320, 1E-321, 1E-322, 1E-323, 1E-324];\n /**\n * Returns powers of 10.\n * Unlike the Math.pow this function produces no decimal garbage.\n * @param exp Exponent.\n */\n function pow10(exp) {\n debug.assertValue(exp, \"exp\");\n // Positive & zero\n if (exp >= 0) {\n if (exp < Double.POSITIVE_POWERS.length) {\n return Double.POSITIVE_POWERS[exp];\n }\n else {\n return Infinity;\n }\n }\n // Negative\n exp = -exp;\n if (exp > 0 && exp < Double.NEGATIVE_POWERS.length) {\n return Double.NEGATIVE_POWERS[exp];\n }\n else {\n return 0;\n }\n }\n Double.pow10 = pow10;\n /**\n * Returns the 10 base logarithm of the number.\n * Unlike Math.log function this produces integer results with no decimal garbage.\n * @param val Positive value or zero.\n */\n function log10(val) {\n debug.assert(val >= 0, \"val\");\n // Fast Log10() algorithm \n if (val > 1 && val < 1E16) {\n if (val < 1E8) {\n if (val < 1E4) {\n if (val < 1E2) {\n if (val < 1E1) {\n return 0;\n }\n else {\n return 1;\n }\n }\n else {\n if (val < 1E3) {\n return 2;\n }\n else {\n return 3;\n }\n }\n }\n else {\n if (val < 1E6) {\n if (val < 1E5) {\n return 4;\n }\n else {\n return 5;\n }\n }\n else {\n if (val < 1E7) {\n return 6;\n }\n else {\n return 7;\n }\n }\n }\n }\n else {\n if (val < 1E12) {\n if (val < 1E10) {\n if (val < 1E9) {\n return 8;\n }\n else {\n return 9;\n }\n }\n else {\n if (val < 1E11) {\n return 10;\n }\n else {\n return 11;\n }\n }\n }\n else {\n if (val < 1E14) {\n if (val < 1E13) {\n return 12;\n }\n else {\n return 13;\n }\n }\n else {\n if (val < 1E15) {\n return 14;\n }\n else {\n return 15;\n }\n }\n }\n }\n }\n if (val > 1E-16 && val < 1) {\n if (val < 1E-8) {\n if (val < 1E-12) {\n if (val < 1E-14) {\n if (val < 1E-15) {\n return -16;\n }\n else {\n return -15;\n }\n }\n else {\n if (val < 1E-13) {\n return -14;\n }\n else {\n return -13;\n }\n }\n }\n else {\n if (val < 1E-10) {\n if (val < 1E-11) {\n return -12;\n }\n else {\n return -11;\n }\n }\n else {\n if (val < 1E-9) {\n return -10;\n }\n else {\n return -9;\n }\n }\n }\n }\n else {\n if (val < 1E-4) {\n if (val < 1E-6) {\n if (val < 1E-7) {\n return -8;\n }\n else {\n return -7;\n }\n }\n else {\n if (val < 1E-5) {\n return -6;\n }\n else {\n return -5;\n }\n }\n }\n else {\n if (val < 1E-2) {\n if (val < 1E-3) {\n return -4;\n }\n else {\n return -3;\n }\n }\n else {\n if (val < 1E-1) {\n return -2;\n }\n else {\n return -1;\n }\n }\n }\n }\n }\n // JS Math provides only natural log function so we need to calc the 10 base logarithm:\n // logb(x) = logk(x)/logk(b); \n var log10 = Math.log(val) / Double.LOG_E_10;\n return Double.floorWithPrecision(log10);\n }\n Double.log10 = log10;\n /**\n * Returns a power of 10 representing precision of the number based on the number of meaningful decimal digits.\n * For example the precision of 56,263.3767 with the 6 meaningful decimal digit is 0.1.\n * @param x Value.\n * @param decimalDigits How many decimal digits are meaningfull.\n */\n function getPrecision(x, decimalDigits) {\n if (decimalDigits === undefined) {\n decimalDigits = Double.DEFAULT_PRECISION_IN_DECIMAL_DIGITS;\n }\n else {\n debug.assert(decimalDigits >= 0, \"decimalDigits\");\n }\n if (!x) {\n return undefined;\n }\n var exp = Double.log10(Math.abs(x));\n if (exp < Double.MIN_EXP) {\n return 0;\n }\n var precisionExp = Math.max(exp - decimalDigits, -Double.NEGATIVE_POWERS.length + 1);\n return Double.pow10(precisionExp);\n }\n Double.getPrecision = getPrecision;\n /**\n * Checks if a delta between 2 numbers is less than provided precision.\n * @param x One value.\n * @param y Another value.\n * @param precision Precision value.\n */\n function equalWithPrecision(x, y, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n return x === y || Math.abs(x - y) < precision;\n }\n Double.equalWithPrecision = equalWithPrecision;\n /**\n * Checks if a first value is less than another taking\n * into account the loose precision based equality.\n * @param x One value.\n * @param y Another value.\n * @param precision Precision value.\n */\n function lessWithPrecision(x, y, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n return x < y && Math.abs(x - y) > precision;\n }\n Double.lessWithPrecision = lessWithPrecision;\n /**\n * Checks if a first value is less or equal than another taking\n * into account the loose precision based equality.\n * @param x One value.\n * @param y Another value.\n * @param precision Precision value.\n */\n function lessOrEqualWithPrecision(x, y, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n return x < y || Math.abs(x - y) < precision;\n }\n Double.lessOrEqualWithPrecision = lessOrEqualWithPrecision;\n /**\n * Checks if a first value is greater than another taking\n * into account the loose precision based equality.\n * @param x One value.\n * @param y Another value.\n * @param precision Precision value.\n */\n function greaterWithPrecision(x, y, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n return x > y && Math.abs(x - y) > precision;\n }\n Double.greaterWithPrecision = greaterWithPrecision;\n /**\n * Checks if a first value is greater or equal to another taking\n * into account the loose precision based equality.\n * @param x One value.\n * @param y Another value.\n * @param precision Precision value.\n */\n function greaterOrEqualWithPrecision(x, y, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n return x > y || Math.abs(x - y) < precision;\n }\n Double.greaterOrEqualWithPrecision = greaterOrEqualWithPrecision;\n /**\n * Floors the number unless it's withing the precision distance from the higher int.\n * @param x One value.\n * @param precision Precision value.\n */\n function floorWithPrecision(x, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n var roundX = Math.round(x);\n if (Math.abs(x - roundX) < precision) {\n return roundX;\n }\n else {\n return Math.floor(x);\n }\n }\n Double.floorWithPrecision = floorWithPrecision;\n /**\n * Ceils the number unless it's withing the precision distance from the lower int.\n * @param x One value.\n * @param precision Precision value.\n */\n function ceilWithPrecision(x, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n var roundX = Math.round(x);\n if (Math.abs(x - roundX) < precision) {\n return roundX;\n }\n else {\n return Math.ceil(x);\n }\n }\n Double.ceilWithPrecision = ceilWithPrecision;\n /**\n * Floors the number to the provided precision.\n * For example 234,578 floored to 1,000 precision is 234,000.\n * @param x One value.\n * @param precision Precision value.\n */\n function floorToPrecision(x, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n if (precision === 0 || x === 0) {\n return x;\n }\n //Precision must be a Power of 10\n return Math.floor(x / precision) * precision;\n }\n Double.floorToPrecision = floorToPrecision;\n /**\n * Ceils the number to the provided precision.\n * For example 234,578 floored to 1,000 precision is 235,000.\n * @param x One value.\n * @param precision Precision value.\n */\n function ceilToPrecision(x, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n if (precision === 0 || x === 0) {\n return x;\n }\n //Precision must be a Power of 10\n return Math.ceil(x / precision) * precision;\n }\n Double.ceilToPrecision = ceilToPrecision;\n /**\n * Rounds the number to the provided precision.\n * For example 234,578 floored to 1,000 precision is 235,000.\n * @param x One value.\n * @param precision Precision value.\n */\n function roundToPrecision(x, precision) {\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\n debug.assert(precision >= 0, \"precision\");\n if (precision === 0 || x === 0) {\n return x;\n }\n //Precision must be a Power of 10\n var result = Math.round(x / precision) * precision;\n var decimalDigits = Math.round(Double.log10(Math.abs(x)) - Double.log10(precision)) + 1;\n if (decimalDigits > 0 && decimalDigits < 16) {\n result = parseFloat(result.toPrecision(decimalDigits));\n }\n return result;\n }\n Double.roundToPrecision = roundToPrecision;\n /**\n * Returns the value making sure that it's restricted to the provided range.\n * @param x One value.\n * @param min Range min boundary.\n * @param max Range max boundary.\n */\n function ensureInRange(x, min, max) {\n debug.assert(min <= max, \"min must be less or equal to max\");\n if (x === undefined || x === null) {\n return x;\n }\n if (x < min) {\n return min;\n }\n if (x > max) {\n return max;\n }\n return x;\n }\n Double.ensureInRange = ensureInRange;\n /**\n * Rounds the value - this method is actually faster than Math.round - used in the graphics utils.\n * @param x Value to round.\n */\n function round(x) {\n debug.assert(x >= 0, \"x must be greater or equal to 0\");\n return (0.5 + x) << 0;\n }\n Double.round = round;\n /**\n * Projects the value from the source range into the target range.\n * @param value Value to project.\n * @param fromMin Minimum of the source range.\n * @param toMin Minimum of the target range.\n * @param toMax Maximum of the target range.\n */\n function project(value, fromMin, fromSize, toMin, toSize) {\n if (fromSize === 0 || toSize === 0) {\n if (fromMin <= value && value <= fromMin + fromSize) {\n return toMin;\n }\n else {\n return NaN;\n }\n }\n var relativeX = (value - fromMin) / fromSize;\n var projectedX = toMin + relativeX * toSize;\n return projectedX;\n }\n Double.project = project;\n /**\n * Removes decimal noise.\n * @param value Value to be processed.\n */\n function removeDecimalNoise(value) {\n return roundToPrecision(value, getPrecision(value));\n }\n Double.removeDecimalNoise = removeDecimalNoise;\n /**\n * Checks whether the number is integer.\n * @param value Value to be checked.\n */\n function isInteger(value) {\n return value !== null && value % 1 === 0;\n }\n Double.isInteger = isInteger;\n /**\n * Dividing by increment will give us count of increments\n * Round out the rough edges into even integer\n * Multiply back by increment to get rounded value\n * e.g. Rounder.toIncrement(0.647291, 0.05) => 0.65\n * @param value - value to round to nearest increment\n * @param increment - smallest increment to round toward\n */\n function toIncrement(value, increment) {\n return Math.round(value / increment) * increment;\n }\n Double.toIncrement = toIncrement;\n })(Double = powerbi.Double || (powerbi.Double = {}));\n function applyDefault(value, defaultValue) {\n return value !== undefined ? value : defaultValue;\n }\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var Double = powerbi.Double;\n var Color;\n (function (Color) {\n function rotate(rgbString, rotateFactor) {\n if (rotateFactor === 0)\n return rgbString;\n var originalRgb = parseColorString(rgbString);\n var originalHsv = rgbToHsv(originalRgb);\n var rotatedHsv = rotateHsv(originalHsv, rotateFactor);\n var rotatedRgb = hsvToRgb(rotatedHsv);\n return hexString(rotatedRgb);\n }\n Color.rotate = rotate;\n function normalizeToHexString(color) {\n var rgb = parseColorString(color);\n return hexString(rgb);\n }\n Color.normalizeToHexString = normalizeToHexString;\n function parseColorString(color) {\n debug.assertValue(color, 'color');\n if (color.indexOf('#') >= 0) {\n if (color.length === 7) {\n // #RRGGBB\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(color);\n if (result == null || result.length < 4)\n return;\n return {\n R: parseInt(result[1], 16),\n G: parseInt(result[2], 16),\n B: parseInt(result[3], 16),\n };\n }\n else if (color.length === 4) {\n // #RGB\n var result = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i.exec(color);\n if (result == null || result.length < 4)\n return;\n return {\n R: parseInt(result[1] + result[1], 16),\n G: parseInt(result[2] + result[2], 16),\n B: parseInt(result[3] + result[3], 16),\n };\n }\n }\n else if (color.indexOf('rgb(') >= 0) {\n // rgb(R, G, B)\n var result = /^rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)$/.exec(color);\n if (result == null || result.length < 4)\n return;\n return {\n R: parseInt(result[1], 10),\n G: parseInt(result[2], 10),\n B: parseInt(result[3], 10),\n };\n }\n else if (color.indexOf('rgba(') >= 0) {\n // rgba(R, G, B, A)\n var result = /^rgba\\((\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d*(?:\\.\\d+)?)\\)$/.exec(color);\n if (result == null || result.length < 5)\n return;\n return {\n R: parseInt(result[1], 10),\n G: parseInt(result[2], 10),\n B: parseInt(result[3], 10),\n A: parseFloat(result[4]),\n };\n }\n }\n Color.parseColorString = parseColorString;\n function rgbToHsv(rgbColor) {\n var s, h;\n var r = rgbColor.R / 255, g = rgbColor.G / 255, b = rgbColor.B / 255;\n var min = Math.min(r, Math.min(g, b));\n var max = Math.max(r, Math.max(g, b));\n var v = max;\n var delta = max - min;\n if (max === 0 || delta === 0) {\n // R, G, and B must be 0.0, or all the same.\n // In this case, S is 0.0, and H is undefined.\n // Using H = 0.0 is as good as any...\n s = 0;\n h = 0;\n }\n else {\n s = delta / max;\n if (r === max) {\n // Between Yellow and Magenta\n h = (g - b) / delta;\n }\n else if (g === max) {\n // Between Cyan and Yellow\n h = 2 + (b - r) / delta;\n }\n else {\n // Between Magenta and Cyan\n h = 4 + (r - g) / delta;\n }\n }\n // Scale h to be between 0.0 and 1.\n // This may require adding 1, if the value\n // is negative.\n h /= 6;\n if (h < 0) {\n h += 1;\n }\n return {\n H: h,\n S: s,\n V: v,\n };\n }\n function hsvToRgb(hsvColor) {\n var r, g, b;\n var h = hsvColor.H, s = hsvColor.S, v = hsvColor.V;\n if (s === 0) {\n // If s is 0, all colors are the same.\n // This is some flavor of gray.\n r = v;\n g = v;\n b = v;\n }\n else {\n var p = void 0, q = void 0, t = void 0, fractionalSector = void 0, sectorNumber = void 0, sectorPos = void 0;\n // The color wheel consists of 6 sectors.\n // Figure out which sector you//re in.\n sectorPos = h * 6;\n sectorNumber = Math.floor(sectorPos);\n // get the fractional part of the sector.\n // That is, how many degrees into the sector\n // are you?\n fractionalSector = sectorPos - sectorNumber;\n // Calculate values for the three axes\n // of the color.\n p = v * (1.0 - s);\n q = v * (1.0 - (s * fractionalSector));\n t = v * (1.0 - (s * (1 - fractionalSector)));\n // Assign the fractional colors to r, g, and b\n // based on the sector the angle is in.\n switch (sectorNumber) {\n case 0:\n r = v;\n g = t;\n b = p;\n break;\n case 1:\n r = q;\n g = v;\n b = p;\n break;\n case 2:\n r = p;\n g = v;\n b = t;\n break;\n case 3:\n r = p;\n g = q;\n b = v;\n break;\n case 4:\n r = t;\n g = p;\n b = v;\n break;\n case 5:\n r = v;\n g = p;\n b = q;\n break;\n }\n }\n return {\n R: Math.floor(r * 255),\n G: Math.floor(g * 255),\n B: Math.floor(b * 255),\n };\n }\n function rotateHsv(hsvColor, rotateFactor) {\n var newH = hsvColor.H + rotateFactor;\n return {\n H: newH > 1 ? newH - 1 : newH,\n S: hsvColor.S,\n V: hsvColor.V,\n };\n }\n function darken(color, diff) {\n var flooredNumber = Math.floor(diff);\n return {\n R: Math.max(0, color.R - flooredNumber),\n G: Math.max(0, color.G - flooredNumber),\n B: Math.max(0, color.B - flooredNumber),\n };\n }\n Color.darken = darken;\n function rgbString(color) {\n if (color.A == null)\n return \"rgb(\" + color.R + \",\" + color.G + \",\" + color.B + \")\";\n return \"rgba(\" + color.R + \",\" + color.G + \",\" + color.B + \",\" + color.A + \")\";\n }\n Color.rgbString = rgbString;\n function hexString(color) {\n return \"#\" + componentToHex(color.R) + componentToHex(color.G) + componentToHex(color.B);\n }\n Color.hexString = hexString;\n function componentToHex(hexComponent) {\n var clamped = Double.ensureInRange(hexComponent, 0, 255);\n var hex = clamped.toString(16).toUpperCase();\n return hex.length === 1 ? \"0\" + hex : hex;\n }\n })(Color = jsCommon.Color || (jsCommon.Color = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * CSS constants.\n */\n var CssConstants;\n (function (CssConstants) {\n function createClassAndSelector(className) {\n return {\n class: className,\n selector: '.' + className,\n };\n }\n CssConstants.createClassAndSelector = createClassAndSelector;\n CssConstants.styleAttribute = 'style';\n CssConstants.pixelUnits = 'px';\n CssConstants.heightProperty = 'height';\n CssConstants.widthProperty = 'width';\n CssConstants.topProperty = 'top';\n CssConstants.bottomProperty = 'bottom';\n CssConstants.leftProperty = 'left';\n CssConstants.rightProperty = 'right';\n CssConstants.marginTopProperty = 'margin-top';\n CssConstants.marginLeftProperty = 'margin-left';\n CssConstants.displayProperty = 'display';\n CssConstants.backgroundProperty = 'background';\n CssConstants.backgroundColorProperty = 'background-color';\n CssConstants.backgroundRepeatProperty = 'background-repeat';\n CssConstants.backgroundSizeProperty = 'background-size';\n CssConstants.backgroundImageProperty = 'background-image';\n CssConstants.textShadowProperty = 'text-shadow';\n CssConstants.textAlignProperty = 'text-align';\n CssConstants.borderTopWidthProperty = 'border-top-width';\n CssConstants.borderBottomWidthProperty = 'border-bottom-width';\n CssConstants.borderLeftWidthProperty = 'border-left-width';\n CssConstants.borderRightWidthProperty = 'border-right-width';\n CssConstants.fontSizeProperty = 'font-size';\n CssConstants.fontWeightProperty = 'font-weight';\n CssConstants.colorProperty = 'color';\n CssConstants.opacityProperty = 'opacity';\n CssConstants.paddingLeftProperty = 'padding-left';\n CssConstants.paddingRightProperty = 'padding-right';\n CssConstants.positionProperty = 'position';\n CssConstants.maxWidthProperty = 'max-width';\n CssConstants.minWidthProperty = 'min-width';\n CssConstants.overflowProperty = 'overflow';\n CssConstants.overflowXProperty = 'overflow-x';\n CssConstants.overflowYProperty = 'overflow-y';\n CssConstants.transformProperty = 'transform';\n CssConstants.webkitTransformProperty = '-webkit-transform';\n CssConstants.cursorProperty = 'cursor';\n CssConstants.visibilityProperty = 'visibility';\n CssConstants.absoluteValue = 'absolute';\n CssConstants.zeroPixelValue = '0px';\n CssConstants.autoValue = 'auto';\n CssConstants.hiddenValue = 'hidden';\n CssConstants.noneValue = 'none';\n CssConstants.blockValue = 'block';\n CssConstants.inlineBlockValue = 'inline-block';\n CssConstants.transparentValue = 'transparent';\n CssConstants.boldValue = 'bold';\n CssConstants.visibleValue = 'visible';\n CssConstants.tableRowValue = 'table-row';\n CssConstants.coverValue = 'cover';\n CssConstants.pointerValue = 'pointer';\n CssConstants.scrollValue = 'scroll';\n })(CssConstants = jsCommon.CssConstants || (jsCommon.CssConstants = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/**\n * Defines a Debug object. Calls to any functions in this object removed by the minifier.\n * The functions within this class are not minified away, so we use the preprocessor-style\n * comments to have the minifier remove those as well.\n */\n///#DEBUG\nvar debug;\n(function (debug) {\n /**\n * Asserts that the condition is true, fails otherwise.\n */\n function assert(condition, message) {\n if (condition !== true) {\n assertFail(message || ('condition: ' + condition));\n }\n }\n debug.assert = assert;\n /**\n * Asserts that the value is neither null nor undefined, fails otherwise.\n */\n function assertValue(value, message) {\n if (value === null || value === undefined) {\n assertFail(message || ('condition: ' + value));\n }\n }\n debug.assertValue = assertValue;\n /**\n * Asserts that the value is neither null nor undefined, and has a length property that returns greater than zero, fails otherwise.\n */\n function assertNonEmpty(value, message) {\n if (!(value != null && value.length > 0)) {\n assertFail(message || ('condition: ' + value));\n }\n }\n debug.assertNonEmpty = assertNonEmpty;\n /**\n * Makes no assertion on the given value.\n * This is documentation/placeholder that a value is possibly null or undefined (unlike assertValue).\n */\n function assertAnyValue(value, message) {\n }\n debug.assertAnyValue = assertAnyValue;\n function assertFail(message) {\n (debug.assertFailFunction || alert)('Debug Assert failed: ' + message);\n }\n debug.assertFail = assertFail;\n})(debug || (debug = {}));\n///#ENDDEBUG \n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var Errors;\n (function (Errors) {\n function infoNavAppAlreadyPresent() {\n return {\n name: 'infoNavAppAlreadyPresent',\n message: 'Cannot initialize embedded scenario when the InfoNav App is already present in this context',\n stack: getExceptionStackTrace()\n };\n }\n Errors.infoNavAppAlreadyPresent = infoNavAppAlreadyPresent;\n function invalidOperation(message) {\n return {\n name: 'invalidOperation',\n message: message,\n stack: getExceptionStackTrace()\n };\n }\n Errors.invalidOperation = invalidOperation;\n function argument(argumentName, message) {\n return {\n name: 'invalidArgumentError',\n argument: argumentName,\n message: message,\n stack: getExceptionStackTrace()\n };\n }\n Errors.argument = argument;\n function argumentNull(argumentName) {\n return {\n name: 'argumentNull',\n argument: argumentName,\n message: 'Argument was null',\n stack: getExceptionStackTrace()\n };\n }\n Errors.argumentNull = argumentNull;\n function argumentUndefined(argumentName) {\n return {\n name: 'argumentUndefined',\n argument: argumentName,\n message: 'Argument was undefined',\n stack: getExceptionStackTrace()\n };\n }\n Errors.argumentUndefined = argumentUndefined;\n function argumentOutOfRange(argumentName) {\n return {\n name: 'argumentOutOfRange',\n argument: argumentName,\n message: 'Argument was out of range',\n stack: getExceptionStackTrace()\n };\n }\n Errors.argumentOutOfRange = argumentOutOfRange;\n function pureVirtualMethodException(className, methodName) {\n return {\n name: 'pureVirtualMethodException',\n message: 'This method must be overriden by the derived class:' + className + '.' + methodName,\n stack: getExceptionStackTrace()\n };\n }\n Errors.pureVirtualMethodException = pureVirtualMethodException;\n function notImplementedException(message) {\n return {\n name: 'notImplementedException',\n message: message,\n stack: getExceptionStackTrace()\n };\n }\n Errors.notImplementedException = notImplementedException;\n function getExceptionStackTrace() {\n return getStackTrace(/*leadingFramesToRemove*/ 2);\n }\n })(Errors = jsCommon.Errors || (jsCommon.Errors = {}));\n /**\n * Captures the stack trace, if available.\n * It optionally takes the number of frames to remove from the stack trace.\n * By default, it removes the last frame to consider the calling type's\n * constructor and the temporary error used to capture the stack trace (below).\n * More levels can be requested as needed e..g. when an error is created\n * from a helper method. <Min requirement: IE10, Chrome, Firefox, Opera>.\n */\n function getStackTrace(leadingFramesToRemove) {\n if (leadingFramesToRemove === void 0) { leadingFramesToRemove = 1; }\n var stackTrace, stackSegments;\n try {\n // needs to throw for stack trace to work in IE\n throw new Error();\n }\n catch (error) {\n stackTrace = error.stack;\n if (stackTrace != null) {\n stackSegments = stackTrace.split('\\n');\n stackSegments.splice(1, leadingFramesToRemove);\n // Finally\n stackTrace = stackSegments.join('\\n');\n }\n }\n return stackTrace;\n }\n jsCommon.getStackTrace = getStackTrace;\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n$.fn.multiline = function (text) {\n this.text(text);\n this.html(this.html().replace(/\\n/g, '<br/>'));\n return this;\n};\n$.fn.togglePanelControl = function () {\n return this.each(function () {\n $(this).addClass(\"ui-accordion ui-accordion-icons ui-widget ui-helper-reset\")\n .find(\".accordionHeader\")\n .addClass(\"ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom\")\n .hover(function () {\n $(this).toggleClass(\"ui-state-hover\");\n })\n .prepend('<span class=\"ui-icon ui-icon-triangle-1-e\"></span>')\n .click(function () {\n $(this)\n .toggleClass(\"ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom\")\n .find(\"> .ui-icon\").toggleClass(\"ui-icon-triangle-1-e ui-icon-triangle-1-s\").end()\n .next().slideToggle();\n return false;\n })\n .next()\n .addClass(\"ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom\")\n .hide();\n });\n};\nvar jsCommon;\n(function (jsCommon) {\n var JQueryConstants;\n (function (JQueryConstants) {\n JQueryConstants.VisibleSelector = ':visible';\n })(JQueryConstants = jsCommon.JQueryConstants || (jsCommon.JQueryConstants = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * Represents a lazily instantiated value.\n */\n var Lazy = (function () {\n function Lazy(factoryMethod) {\n jsCommon.Utility.throwIfNullOrUndefined(factoryMethod, this, 'constructor', 'factoryMethod');\n this.factoryMethod = factoryMethod;\n }\n Lazy.prototype.getValue = function () {\n if (this.factoryMethod !== null) {\n this.value = this.factoryMethod();\n // Optimization: Release the factoryMethod, as it could be holding a large object graph.\n this.factoryMethod = null;\n }\n return this.value;\n };\n return Lazy;\n }());\n jsCommon.Lazy = Lazy;\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var Prototype;\n (function (Prototype) {\n /**\n * Returns a new object with the provided obj as its prototype.\n */\n function inherit(obj, extension) {\n debug.assertValue(obj, 'obj');\n function wrapCtor() { }\n ;\n wrapCtor.prototype = obj;\n var inherited = new wrapCtor();\n if (extension)\n extension(inherited);\n return inherited;\n }\n Prototype.inherit = inherit;\n /**\n * Returns a new object with the provided obj as its prototype\n * if, and only if, the prototype has not been previously set\n */\n function inheritSingle(obj) {\n debug.assertValue(obj, 'obj');\n var proto = Object.getPrototypeOf(obj);\n if (proto === Object.prototype || proto === Array.prototype)\n obj = inherit(obj);\n return obj;\n }\n Prototype.inheritSingle = inheritSingle;\n /**\n * Uses the provided callback function to selectively replace contents in the provided array.\n * @return A new array with those values overriden\n * or undefined if no overrides are necessary.\n */\n function overrideArray(prototype, override) {\n if (!prototype)\n return;\n var overwritten;\n for (var i = 0, len = prototype.length; i < len; i++) {\n var value = override(prototype[i]);\n if (value) {\n if (!overwritten)\n overwritten = inherit(prototype);\n overwritten[i] = value;\n }\n }\n return overwritten;\n }\n Prototype.overrideArray = overrideArray;\n })(Prototype = powerbi.Prototype || (powerbi.Prototype = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var Formatting;\n (function (Formatting) {\n var regexCache;\n /**\n * Translate .NET format into something supported by jQuery.Globalize.\n */\n function findDateFormat(value, format, cultureName) {\n switch (format) {\n case \"m\":\n // Month + day\n format = \"M\";\n break;\n case \"O\":\n case \"o\":\n // Roundtrip\n format = \"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'0000'\";\n break;\n case \"R\":\n case \"r\":\n // RFC1123 pattern - - time must be converted to UTC before formatting \n value = new Date(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());\n format = \"ddd, dd MMM yyyy HH':'mm':'ss 'GMT'\";\n break;\n case \"s\":\n // Sortable - should use invariant culture\n format = \"S\";\n break;\n case \"u\":\n // Universal sortable - should convert to UTC before applying the \"yyyy'-'MM'-'dd HH':'mm':'ss'Z' format.\n value = new Date(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());\n format = \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\";\n break;\n case \"U\":\n // Universal full - the pattern is same as F but the time must be converted to UTC before formatting\n value = new Date(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());\n format = \"F\";\n break;\n case \"y\":\n case \"Y\":\n // Year and month\n switch (cultureName) {\n case \"default\":\n case \"en\":\n case \"en-US\":\n format = \"MMMM, yyyy\"; // Fix the default year-month pattern for english\n break;\n default:\n format = \"Y\"; // For other cultures - use the localized pattern\n }\n break;\n }\n return { value: value, format: format };\n }\n Formatting.findDateFormat = findDateFormat;\n /**\n * Translates unsupported .NET custom format expressions to the custom expressions supported by JQuery.Globalize.\n */\n function fixDateTimeFormat(format) {\n // Fix for the \"K\" format (timezone): \n //The js dates don't have a kind property so we'll support only local kind which is equavalent to zzz format.\n format = format.replace(/%K/g, \"zzz\");\n format = format.replace(/K/g, \"zzz\");\n format = format.replace(/fffffff/g, \"fff0000\");\n format = format.replace(/ffffff/g, \"fff000\");\n format = format.replace(/fffff/g, \"fff00\");\n format = format.replace(/ffff/g, \"fff0\");\n // Fix for the 5 digit year: \"yyyyy\" format. \n //The Globalize doesn't support dates greater than 9999 so we replace the \"yyyyy\" with \"0yyyy\".\n format = format.replace(/yyyyy/g, \"0yyyy\");\n // Fix for the 3 digit year: \"yyy\" format. \n //The Globalize doesn't support this formatting so we need to replace it with the 4 digit year \"yyyy\" format.\n format = format.replace(/(^y|^)yyy(^y|$)/g, \"yyyy\");\n if (!regexCache) {\n // Creating Regexes for cases \"Using single format specifier\" \n //- http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx#UsingSingleSpecifiers\n // This is not supported from The Globalize.\n // The case covers all single \"%\" lead specifier (like \"%d\" but not %dd) \n // The cases as single \"%d\" are filtered in if the bellow.\n // (?!S) where S is the specifier make sure that we only one symbol for specifier.\n regexCache = [\"d\", \"f\", \"F\", \"g\", \"h\", \"H\", \"K\", \"m\", \"M\", \"s\", \"t\", \"y\", \"z\", \":\", \"/\"].map(function (s) {\n return { r: new RegExp(\"\\%\" + s + \"(?!\" + s + \")\", \"g\"), s: s };\n });\n }\n if (format.indexOf(\"%\") !== -1 && format.length > 2) {\n for (var i = 0; i < regexCache.length; i++) {\n format = format.replace(regexCache[i].r, regexCache[i].s);\n }\n }\n return format;\n }\n Formatting.fixDateTimeFormat = fixDateTimeFormat;\n })(Formatting = jsCommon.Formatting || (jsCommon.Formatting = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var doc = document, headElement = doc.head, firstScriptInHeadElement = headElement.getElementsByTagName('script')[0], linkElement = doc.createElement('link'), scriptElement = doc.createElement('script'), styleSheetLoaded = [], javaScriptFilesLoaded = [], javaScriptFilesLoading = [];\n linkElement.setAttribute('rel', 'stylesheet');\n function requires(dependency, to) {\n if (to === void 0) { to = $.noop; }\n loadStyleSheets(dependency.cssFiles || []);\n var scriptsToRun = dependency.javaScriptFilesWithCallback || [];\n if (dependency.javaScriptFiles) {\n for (var i = 0, len = dependency.javaScriptFiles.length; i < len; ++i) {\n scriptsToRun.push({ javascriptFile: dependency.javaScriptFiles[i] });\n }\n }\n loadJavaScriptFiles(scriptsToRun, to);\n }\n jsCommon.requires = requires;\n /**\n * Private Helpers.\n */\n function loadStyleSheets(hrefList) {\n hrefList.forEach(function (href) {\n if (styleSheetLoaded.indexOf(href) === -1) {\n styleSheetLoaded.push(href);\n loadStyleSheet(href);\n }\n });\n }\n function loadJavaScriptFiles(scripts, callback) {\n var loadingCount = scripts.length, parsingCount = loadingCount, sourceCodeList = [];\n function parseIfLoadingComplete() {\n if (!--loadingCount) {\n parseJavaScriptSourceCodes(scripts, sourceCodeList);\n }\n }\n function makeCallbackIfParsingComplete() {\n if (!--parsingCount) {\n callback();\n }\n }\n scripts.forEach(function (script, index) {\n var file = script.javascriptFile;\n if (javaScriptFilesLoaded.indexOf(file) === -1) {\n if (file in javaScriptFilesLoading) {\n javaScriptFilesLoading[file].push(function () {\n parseIfLoadingComplete();\n makeCallbackIfParsingComplete();\n });\n }\n else {\n javaScriptFilesLoading[file] = [function () {\n makeCallbackIfParsingComplete();\n }];\n if (isExternalUrl(file)) {\n sourceCodeList[index] = script;\n parseIfLoadingComplete();\n }\n else {\n loadJavaScriptSourceCode(file, function (sourceCode) {\n sourceCodeList[index] = { javascriptFile: sourceCode };\n parseIfLoadingComplete();\n });\n }\n }\n }\n else {\n parseIfLoadingComplete();\n makeCallbackIfParsingComplete();\n }\n });\n }\n function loadStyleSheet(href) {\n var link = linkElement.cloneNode();\n link.href = href;\n if (firstScriptInHeadElement) {\n headElement.insertBefore(link, firstScriptInHeadElement);\n }\n else {\n headElement.appendChild(link);\n }\n }\n function loadJavaScriptSourceCode(src, onload) {\n webGet(src, function () {\n onload(this.responseText);\n });\n }\n function parseJavaScript(script, onComplete) {\n if (onComplete === void 0) { onComplete = $.noop; }\n if (!script) {\n onComplete();\n return;\n }\n var sourceCodeOrFileName = script.javascriptFile;\n var targetCallback = onComplete;\n if (script.onLoadCallback) {\n var promiseAsCallback = function () {\n script.onLoadCallback().then(onComplete);\n };\n targetCallback = promiseAsCallback;\n }\n isExternalUrl(sourceCodeOrFileName)\n ? loadExternalJavaScriptFile(sourceCodeOrFileName, targetCallback)\n : parseInternalJavaScriptCode(sourceCodeOrFileName, targetCallback);\n }\n function parseInternalJavaScriptCode(sourceCode, onComplete) {\n if (onComplete === void 0) { onComplete = $.noop; }\n var script;\n if (sourceCode) {\n script = scriptElement.cloneNode();\n script.setAttribute('type', 'text/javascript');\n script.innerHTML = sourceCode;\n headElement.appendChild(script);\n }\n setTimeout(onComplete, 0);\n }\n function loadExternalJavaScriptFile(src, onload) {\n var script;\n if (src) {\n script = scriptElement.cloneNode();\n script.setAttribute('src', src);\n script.setAttribute('charset', 'utf-8');\n script.onload = onload;\n headElement.appendChild(script);\n }\n }\n function parseJavaScriptSourceCodes(scripts, sourceCodeList) {\n asyncLoop(sourceCodeList, parseJavaScript, /*on all files parsed*/ function () {\n scripts.forEach(function (script) {\n var file = script.javascriptFile;\n var listeners = javaScriptFilesLoading[file];\n if (listeners) {\n listeners.forEach(function (listener) {\n listener();\n });\n }\n delete javaScriptFilesLoading[file];\n if (javaScriptFilesLoaded.indexOf(file) === -1) {\n javaScriptFilesLoaded.push(file);\n }\n });\n });\n }\n function webGet(src, onload, onerror) {\n var xhr = new XMLHttpRequest();\n try {\n xhr.open('GET', src, true);\n xhr.onload = onload;\n xhr.onerror = onerror;\n xhr.send(null);\n }\n catch (e) {\n }\n }\n function isExternalUrl(url) {\n var origin = location.protocol + '//' + location.host + '/';\n return /^http[s]?:\\/\\/.+/i.test(url) && url.indexOf(origin) !== 0;\n }\n function _() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i - 0] = arguments[_i];\n }\n }\n function asyncSteps() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i - 0] = arguments[_i];\n }\n if (args.length === 0) {\n return;\n }\n var steps = [], i = args.length;\n while (i--) {\n (function (j) {\n steps[j] = function () {\n args[j](steps[j + 1] || _);\n };\n })(i);\n }\n steps[0]();\n }\n function asyncLoop(enumerable, func, callback) {\n var steps = [], i = 0, len = enumerable.length;\n for (; i < len - 1; i++) {\n (function (i) {\n steps[i] = function (next) {\n func(enumerable[i], next);\n };\n }(i));\n }\n steps[len - 1] = function (next) {\n func(enumerable[len - 1], callback);\n };\n asyncSteps.apply(null, steps);\n }\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n function createJQueryPromiseFactory() {\n return new JQueryPromiseFactory();\n }\n powerbi.createJQueryPromiseFactory = createJQueryPromiseFactory;\n /**\n * jQuery-based implementation of IPromiseFactory.\n * This is useful for cases when Angular is not present, or when immediate promise resolving (not tied to Angular digest cycle) is desired.\n */\n var JQueryPromiseFactory = (function () {\n function JQueryPromiseFactory() {\n }\n JQueryPromiseFactory.prototype.defer = function () {\n return new JQueryDeferredWrapper($.Deferred());\n };\n JQueryPromiseFactory.prototype.reject = function (reason) {\n var deferred = this.defer();\n deferred.reject(reason);\n return deferred.promise;\n };\n JQueryPromiseFactory.prototype.resolve = function (value) {\n var deferred = this.defer();\n deferred.resolve(value);\n return deferred.promise;\n };\n JQueryPromiseFactory.prototype.all = function (promises) {\n var unwrappedPromises = jQuery.map(promises, function (value) {\n return value && value.promise ? value.promise : value;\n });\n return new JQueryPromiseWrapper($.when.apply($, unwrappedPromises));\n };\n JQueryPromiseFactory.prototype.when = function (value) {\n var unwrappedPromise = value && value.promise ? value.promise : value;\n return new JQueryPromiseWrapper($.when(unwrappedPromise));\n };\n return JQueryPromiseFactory;\n }());\n /**\n * Implements IDeferred via a wrapped a jQuery Deferred.\n */\n var JQueryDeferredWrapper = (function () {\n function JQueryDeferredWrapper(deferred) {\n debug.assertValue(deferred, 'deferred');\n this.deferred = deferred;\n this.promise = new JQueryPromiseWrapper(deferred.promise());\n }\n JQueryDeferredWrapper.prototype.resolve = function (value) {\n this.deferred.resolve(value);\n };\n JQueryDeferredWrapper.prototype.reject = function (reason) {\n this.deferred.reject(reason);\n };\n return JQueryDeferredWrapper;\n }());\n /**\n * Implements IDeferred via a wrapped a jQuery Promise.\n */\n var JQueryPromiseWrapper = (function () {\n function JQueryPromiseWrapper(promise) {\n debug.assertValue(promise, 'promise');\n this.promise = promise;\n }\n JQueryPromiseWrapper.prototype.then = function (a, b) {\n return new JQueryPromiseWrapper(this.promise.then(JQueryPromiseWrapper.wrapCallback(a), JQueryPromiseWrapper.wrapCallback(b)));\n };\n JQueryPromiseWrapper.prototype.catch = function (callback) {\n return this.then(null, callback);\n };\n JQueryPromiseWrapper.prototype.finally = function (callback) {\n this.promise.always(JQueryPromiseWrapper.wrapCallback(callback));\n return this;\n };\n /**\n * Wraps a callback, which may return a IPromise.\n */\n JQueryPromiseWrapper.wrapCallback = function (callback) {\n if (callback)\n return function (arg) {\n var value = callback(arg);\n // If the callback returns a Promise, unwrap that to allow jQuery to chain.\n if (value instanceof JQueryPromiseWrapper)\n return value.promise;\n return value;\n };\n return callback;\n };\n return JQueryPromiseWrapper;\n }());\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var LocalStorageService = (function () {\n function LocalStorageService() {\n }\n LocalStorageService.prototype.getData = function (key) {\n try {\n if (localStorage) {\n var value = localStorage[key];\n if (value) {\n return JSON.parse(value);\n }\n }\n }\n catch (exception) { }\n return null;\n };\n LocalStorageService.prototype.setData = function (key, data) {\n try {\n if (localStorage) {\n localStorage[key] = JSON.stringify(data);\n }\n }\n catch (e) { }\n };\n return LocalStorageService;\n }());\n var EphemeralStorageService = (function () {\n function EphemeralStorageService(clearCacheInterval) {\n this.cache = {};\n this.clearCacheInterval = (clearCacheInterval != null)\n ? clearCacheInterval\n : EphemeralStorageService.defaultClearCacheInterval;\n this.clearCache();\n }\n EphemeralStorageService.prototype.getData = function (key) {\n return this.cache[key];\n };\n EphemeralStorageService.prototype.setData = function (key, data) {\n var _this = this;\n this.cache[key] = data;\n if (this.clearCacheTimerId == null) {\n this.clearCacheTimerId = setTimeout(function () { return _this.clearCache(); }, this.clearCacheInterval);\n }\n };\n EphemeralStorageService.prototype.clearCache = function () {\n this.cache = {};\n this.clearCacheTimerId = undefined;\n };\n EphemeralStorageService.defaultClearCacheInterval = (1000 * 60 * 60 * 24); // 1 day\n return EphemeralStorageService;\n }());\n powerbi.EphemeralStorageService = EphemeralStorageService;\n powerbi.localStorageService = new LocalStorageService();\n powerbi.ephemeralStorageService = new EphemeralStorageService();\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var WordBreaker;\n (function (WordBreaker) {\n var SPACE = ' ';\n var BREAKERS_REGEX = /[\\s\\n]+/g;\n function search(index, content, backward) {\n if (backward) {\n for (var i = index - 1; i > -1; i--) {\n if (hasBreakers(content[i]))\n return i + 1;\n }\n }\n else {\n for (var i = index, ilen = content.length; i < ilen; i++) {\n if (hasBreakers(content[i]))\n return i;\n }\n }\n return backward ? 0 : content.length;\n }\n /**\n * Find the word nearest the cursor specified within content\n * @param index - point within content to search forward/backward from\n * @param content - string to search\n */\n function find(index, content) {\n debug.assert(index >= 0 && index <= content.length, 'index within content string bounds');\n var result = { start: 0, end: 0 };\n if (content.length === 0)\n return result;\n result.start = search(index, content, true);\n result.end = search(index, content, false);\n return result;\n }\n WordBreaker.find = find;\n /**\n * Test for presence of breakers within content\n * @param content - string to test\n */\n function hasBreakers(content) {\n BREAKERS_REGEX.lastIndex = 0;\n return BREAKERS_REGEX.test(content);\n }\n WordBreaker.hasBreakers = hasBreakers;\n /**\n * Count the number of pieces when broken by BREAKERS_REGEX\n * ~2.7x faster than WordBreaker.split(content).length\n * @param content - string to break and count\n */\n function wordCount(content) {\n var count = 1;\n BREAKERS_REGEX.lastIndex = 0;\n BREAKERS_REGEX.exec(content);\n while (BREAKERS_REGEX.lastIndex !== 0) {\n count++;\n BREAKERS_REGEX.exec(content);\n }\n return count;\n }\n WordBreaker.wordCount = wordCount;\n function getMaxWordWidth(content, textWidthMeasurer, properties) {\n var words = split(content);\n var maxWidth = 0;\n for (var _i = 0, words_1 = words; _i < words_1.length; _i++) {\n var w = words_1[_i];\n properties.text = w;\n maxWidth = Math.max(maxWidth, textWidthMeasurer(properties));\n }\n return maxWidth;\n }\n WordBreaker.getMaxWordWidth = getMaxWordWidth;\n function split(content) {\n return content.split(BREAKERS_REGEX);\n }\n function getWidth(content, properties, textWidthMeasurer) {\n properties.text = content;\n return textWidthMeasurer(properties);\n }\n function truncate(content, properties, truncator, maxWidth) {\n properties.text = content;\n return truncator(properties, maxWidth);\n }\n /**\n * Split content by breakers (words) and greedy fit as many words\n * into each index in the result based on max width and number of lines\n * e.g. Each index in result corresponds to a line of content\n * when used by AxisHelper.LabelLayoutStrategy.wordBreak\n * @param content - string to split\n * @param properties - text properties to be used by @param:textWidthMeasurer\n * @param textWidthMeasurer - function to calculate width of given text content\n * @param maxWidth - maximum allowed width of text content in each result\n * @param maxNumLines - maximum number of results we will allow, valid values must be greater than 0\n * @param truncator - (optional) if specified, used as a function to truncate content to a given width\n */\n function splitByWidth(content, properties, textWidthMeasurer, maxWidth, maxNumLines, truncator) {\n // Default truncator returns string as-is\n truncator = truncator ? truncator : function (properties, maxWidth) { return properties.text; };\n var result = [];\n var words = split(content);\n var usedWidth = 0;\n var wordsInLine = [];\n for (var _i = 0, words_2 = words; _i < words_2.length; _i++) {\n var word = words_2[_i];\n // Last line? Just add whatever is left\n if ((maxNumLines > 0) && (result.length >= maxNumLines - 1)) {\n wordsInLine.push(word);\n continue;\n }\n // Determine width if we add this word\n // Account for SPACE we will add when joining...\n var wordWidth = wordsInLine.length === 0\n ? getWidth(word, properties, textWidthMeasurer)\n : getWidth(SPACE + word, properties, textWidthMeasurer);\n // If width would exceed max width,\n // then push used words and start new split result\n if (usedWidth + wordWidth > maxWidth) {\n // Word alone exceeds max width, just add it.\n if (wordsInLine.length === 0) {\n result.push(truncate(word, properties, truncator, maxWidth));\n usedWidth = 0;\n wordsInLine = [];\n continue;\n }\n result.push(truncate(wordsInLine.join(SPACE), properties, truncator, maxWidth));\n usedWidth = 0;\n wordsInLine = [];\n }\n // ...otherwise, add word and continue\n wordsInLine.push(word);\n usedWidth += wordWidth;\n }\n // Push remaining words onto result\n result.push(truncate(wordsInLine.join(SPACE), properties, truncator, maxWidth));\n return result;\n }\n WordBreaker.splitByWidth = splitByWidth;\n })(WordBreaker = jsCommon.WordBreaker || (jsCommon.WordBreaker = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var TextMeasurementService;\n (function (TextMeasurementService) {\n var ellipsis = '…';\n var OverflowingText = jsCommon.CssConstants.createClassAndSelector('overflowingText');\n var spanElement;\n var svgTextElement;\n var canvasCtx;\n var fallbackFontFamily;\n /**\n * Idempotent function for adding the elements to the DOM.\n */\n function ensureDOM() {\n if (spanElement)\n return;\n spanElement = $('<span/>');\n $('body').append(spanElement);\n //The style hides the svg element from the canvas, preventing canvas from scrolling down to show svg black square.\n svgTextElement = d3.select($('body').get(0))\n .append('svg')\n .style({\n 'height': '0px',\n 'width': '0px',\n 'position': 'absolute'\n })\n .append('text');\n canvasCtx = $('<canvas/>').get(0).getContext(\"2d\");\n fallbackFontFamily = window.getComputedStyle(svgTextElement.node()).fontFamily;\n }\n /**\n * Removes spanElement from DOM.\n */\n function removeSpanElement() {\n if (spanElement && spanElement.remove) {\n spanElement.remove();\n }\n spanElement = null;\n }\n TextMeasurementService.removeSpanElement = removeSpanElement;\n /**\n * This method measures the width of the text with the given SVG text properties.\n * @param textProperties The text properties to use for text measurement.\n */\n function measureSvgTextWidth(textProperties) {\n debug.assertValue(textProperties, 'textProperties');\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\n ensureDOM();\n canvasCtx.font =\n (textProperties.fontStyle || \"\") + \" \" +\n (textProperties.fontVariant || \"\") + \" \" +\n (textProperties.fontWeight || \"\") + \" \" +\n textProperties.fontSize + \" \" +\n (textProperties.fontFamily || fallbackFontFamily);\n return canvasCtx.measureText(textProperties.text).width;\n }\n TextMeasurementService.measureSvgTextWidth = measureSvgTextWidth;\n /**\n * This method return the rect with the given SVG text properties.\n * @param textProperties The text properties to use for text measurement.\n */\n function measureSvgTextRect(textProperties) {\n debug.assertValue(textProperties, 'textProperties');\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\n ensureDOM();\n svgTextElement.style(null);\n svgTextElement\n .text(textProperties.text)\n .attr({\n 'visibility': 'hidden',\n 'font-family': textProperties.fontFamily || fallbackFontFamily,\n 'font-variant': textProperties.fontVariant,\n 'font-size': textProperties.fontSize,\n 'font-weight': textProperties.fontWeight,\n 'font-style': textProperties.fontStyle,\n 'white-space': textProperties.whiteSpace || 'nowrap'\n });\n // We're expecting the browser to give a synchronous measurement here\n // We're using SVGTextElement because it works across all browsers \n return svgTextElement.node().getBBox();\n }\n TextMeasurementService.measureSvgTextRect = measureSvgTextRect;\n /**\n * This method measures the height of the text with the given SVG text properties.\n * @param textProperties The text properties to use for text measurement.\n */\n function measureSvgTextHeight(textProperties) {\n return measureSvgTextRect(textProperties).height;\n }\n TextMeasurementService.measureSvgTextHeight = measureSvgTextHeight;\n /**\n * This method returns the text Rect with the given SVG text properties.\n * Does NOT return text width; obliterates text value\n * @param {TextProperties} textProperties - The text properties to use for text measurement\n */\n function estimateSvgTextRect(textProperties) {\n debug.assertValue(textProperties, 'textProperties');\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\n var propertiesKey = textProperties.fontFamily + textProperties.fontSize;\n var rect = powerbi.ephemeralStorageService.getData(propertiesKey);\n if (rect == null) {\n // To estimate we check the height of a particular character, once it is cached, subsequent\n // calls should always get the height from the cache (regardless of the text).\n var estimatedTextProperties = {\n fontFamily: textProperties.fontFamily,\n fontSize: textProperties.fontSize,\n text: \"M\",\n };\n rect = TextMeasurementService.measureSvgTextRect(estimatedTextProperties);\n // NOTE: In some cases (disconnected/hidden DOM) we may provide incorrect measurement results (zero sized bounding-box), so\n // we only store values in the cache if we are confident they are correct.\n if (rect.height > 0)\n powerbi.ephemeralStorageService.setData(propertiesKey, rect);\n }\n return rect;\n }\n /**\n * This method returns the text Rect with the given SVG text properties.\n * @param {TextProperties} textProperties - The text properties to use for text measurement\n */\n function estimateSvgTextBaselineDelta(textProperties) {\n var rect = estimateSvgTextRect(textProperties);\n return rect.y + rect.height;\n }\n TextMeasurementService.estimateSvgTextBaselineDelta = estimateSvgTextBaselineDelta;\n /**\n * This method estimates the height of the text with the given SVG text properties.\n * @param {TextProperties} textProperties - The text properties to use for text measurement\n */\n function estimateSvgTextHeight(textProperties, tightFightForNumeric) {\n if (tightFightForNumeric === void 0) { tightFightForNumeric = false; }\n var height = estimateSvgTextRect(textProperties).height;\n //TODO: replace it with new baseline calculation\n if (tightFightForNumeric)\n height *= 0.7;\n return height;\n }\n TextMeasurementService.estimateSvgTextHeight = estimateSvgTextHeight;\n /**\n * This method measures the width of the svgElement.\n * @param svgElement The SVGTextElement to be measured.\n */\n function measureSvgTextElementWidth(svgElement) {\n debug.assertValue(svgElement, 'svgElement');\n return measureSvgTextWidth(getSvgMeasurementProperties(svgElement));\n }\n TextMeasurementService.measureSvgTextElementWidth = measureSvgTextElementWidth;\n /**\n * This method fetches the text measurement properties of the given DOM element.\n * @param element The selector for the DOM Element.\n */\n function getMeasurementProperties(element) {\n debug.assertValue(element, 'element');\n return {\n text: element.val() || element.text(),\n fontFamily: element.css('font-family'),\n fontSize: element.css('font-size'),\n fontWeight: element.css('font-weight'),\n fontStyle: element.css('font-style'),\n fontVariant: element.css('font-variant'),\n whiteSpace: element.css('white-space')\n };\n }\n TextMeasurementService.getMeasurementProperties = getMeasurementProperties;\n /**\n * This method fetches the text measurement properties of the given SVG text element.\n * @param svgElement The SVGTextElement to be measured.\n */\n function getSvgMeasurementProperties(svgElement) {\n debug.assertValue(svgElement, 'svgElement');\n var style = window.getComputedStyle(svgElement, null);\n return {\n text: svgElement.textContent,\n fontFamily: style.fontFamily,\n fontSize: style.fontSize,\n fontWeight: style.fontWeight,\n fontStyle: style.fontStyle,\n fontVariant: style.fontVariant,\n whiteSpace: style.whiteSpace\n };\n }\n TextMeasurementService.getSvgMeasurementProperties = getSvgMeasurementProperties;\n /**\n * This method returns the width of a div element.\n * @param element The div element.\n */\n function getDivElementWidth(element) {\n debug.assert(element.is('div'), 'Given element is not a div type. Cannot get width');\n return getComputedStyle(element[0]).width;\n }\n TextMeasurementService.getDivElementWidth = getDivElementWidth;\n /**\n * Compares labels text size to the available size and renders ellipses when the available size is smaller.\n * @param textProperties The text properties (including text content) to use for text measurement.\n * @param maxWidth The maximum width available for rendering the text.\n */\n function getTailoredTextOrDefault(textProperties, maxWidth) {\n debug.assertValue(textProperties, 'properties');\n debug.assertValue(textProperties.text, 'properties.text');\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\n ensureDOM();\n var strLength = textProperties.text.length;\n if (strLength === 0)\n return textProperties.text;\n var width = measureSvgTextWidth(textProperties);\n if (width < maxWidth)\n return textProperties.text;\n // Create a copy of the textProperties so we don't modify the one that's passed in.\n var copiedTextProperties = powerbi.Prototype.inherit(textProperties);\n // Take the properties and apply them to svgTextElement\n // Then, do the binary search to figure out the substring we want\n // Set the substring on textElement argument\n var text = copiedTextProperties.text = ellipsis + copiedTextProperties.text;\n var min = 1;\n var max = text.length;\n var i = ellipsis.length;\n while (min <= max) {\n // num | 0 prefered to Math.floor(num) for performance benefits\n i = (min + max) / 2 | 0;\n copiedTextProperties.text = text.substr(0, i);\n width = measureSvgTextWidth(copiedTextProperties);\n if (maxWidth > width)\n min = i + 1;\n else if (maxWidth < width)\n max = i - 1;\n else\n break;\n }\n // Since the search algorithm almost never finds an exact match,\n // it will pick one of the closest two, which could result in a\n // value bigger with than 'maxWidth' thus we need to go back by \n // one to guarantee a smaller width than 'maxWidth'.\n copiedTextProperties.text = text.substr(0, i);\n width = measureSvgTextWidth(copiedTextProperties);\n if (width > maxWidth)\n i--;\n return text.substr(ellipsis.length, i - ellipsis.length) + ellipsis;\n }\n TextMeasurementService.getTailoredTextOrDefault = getTailoredTextOrDefault;\n /**\n * Compares labels text size to the available size and renders ellipses when the available size is smaller.\n * @param textElement The SVGTextElement containing the text to render.\n * @param maxWidth The maximum width available for rendering the text.\n */\n function svgEllipsis(textElement, maxWidth) {\n debug.assertValue(textElement, 'textElement');\n var properties = getSvgMeasurementProperties(textElement);\n var originalText = properties.text;\n var tailoredText = getTailoredTextOrDefault(properties, maxWidth);\n if (originalText !== tailoredText) {\n textElement.textContent = tailoredText;\n }\n }\n TextMeasurementService.svgEllipsis = svgEllipsis;\n /**\n * Word break textContent of <text> SVG element into <tspan>s\n * Each tspan will be the height of a single line of text\n * @param textElement - the SVGTextElement containing the text to wrap\n * @param maxWidth - the maximum width available\n * @param maxHeight - the maximum height available (defaults to single line)\n * @param linePadding - (optional) padding to add to line height\n */\n function wordBreak(textElement, maxWidth, maxHeight, linePadding) {\n if (linePadding === void 0) { linePadding = 0; }\n debug.assertValue(textElement, 'textElement');\n var properties = getSvgMeasurementProperties(textElement);\n var height = estimateSvgTextHeight(properties) + linePadding;\n var maxNumLines = Math.max(1, Math.floor(maxHeight / height));\n var node = d3.select(textElement);\n // Save y of parent textElement to apply as first tspan dy\n var firstDY = node.attr('y');\n // Store and clear text content\n var labelText = textElement.textContent;\n textElement.textContent = null;\n // Append a tspan for each word broken section\n var words = jsCommon.WordBreaker.splitByWidth(labelText, properties, measureSvgTextWidth, maxWidth, maxNumLines);\n for (var i = 0, ilen = words.length; i < ilen; i++) {\n properties.text = words[i];\n node\n .append('tspan')\n .attr({\n 'x': 0,\n 'dy': i === 0 ? firstDY : height,\n })\n .text(getTailoredTextOrDefault(properties, maxWidth));\n }\n }\n TextMeasurementService.wordBreak = wordBreak;\n /**\n * Word break textContent of span element into <span>s\n * Each span will be the height of a single line of text\n * @param textElement - the element containing the text to wrap\n * @param maxWidth - the maximum width available\n * @param maxHeight - the maximum height available (defaults to single line)\n * @param linePadding - (optional) padding to add to line height\n */\n function wordBreakOverflowingText(textElement, maxWidth, maxHeight, linePadding) {\n if (linePadding === void 0) { linePadding = 0; }\n debug.assertValue(textElement, 'textElement');\n var properties = getSvgMeasurementProperties(textElement);\n var height = estimateSvgTextHeight(properties) + linePadding;\n var maxNumLines = Math.max(1, Math.floor(maxHeight / height));\n // Store and clear text content\n var labelText = textElement.textContent;\n textElement.textContent = null;\n // Append a span for each word broken section\n var words = jsCommon.WordBreaker.splitByWidth(labelText, properties, measureSvgTextWidth, maxWidth, maxNumLines);\n // splitByWidth() occasionally returns unnecessary empty strings, so get rid of them.\n // TODO: Fix splitByWidth.\n words = _.compact(words);\n var spanItem = d3.select(textElement)\n .selectAll(OverflowingText.selector)\n .data(words, function (d) { return $.inArray(d, words); });\n spanItem\n .enter()\n .append(\"span\")\n .classed(OverflowingText.class, true)\n .text(function (d) { return d; })\n .style(\"width\", jsCommon.PixelConverter.toString(maxWidth));\n }\n TextMeasurementService.wordBreakOverflowingText = wordBreakOverflowingText;\n })(TextMeasurementService = powerbi.TextMeasurementService || (powerbi.TextMeasurementService = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var DOMConstants = jsCommon.DOMConstants;\n var KeyUtils;\n (function (KeyUtils) {\n function isArrowKey(keyCode) {\n return keyCode === DOMConstants.downArrowKeyCode\n || keyCode === DOMConstants.upArrowKeyCode\n || keyCode === DOMConstants.leftArrowKeyCode\n || keyCode === DOMConstants.rightArrowKeyCode;\n }\n KeyUtils.isArrowKey = isArrowKey;\n })(KeyUtils = jsCommon.KeyUtils || (jsCommon.KeyUtils = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * Responsible for throttling input function.\n */\n var ThrottleUtility = (function () {\n function ThrottleUtility(delay) {\n this.timerFactory = jsCommon.TimerPromiseFactory.instance;\n this.delay = 0;\n if (delay) {\n this.delay = delay;\n }\n }\n ThrottleUtility.prototype.run = function (fn) {\n var _this = this;\n if (!this.fn) {\n this.fn = fn;\n this.timerFactory.create(this.delay).done(function () { return _this.timerComplete(_this.fn); });\n }\n else {\n this.fn = fn;\n }\n };\n /**\n * Note: Public for testing purpose.\n */\n ThrottleUtility.prototype.timerComplete = function (fn) {\n // run fn\n fn();\n // clear fn\n this.fn = null;\n };\n return ThrottleUtility;\n }());\n jsCommon.ThrottleUtility = ThrottleUtility;\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * Responsible for creating timer promises.\n */\n var TimerPromiseFactory = (function () {\n function TimerPromiseFactory() {\n }\n /**\n * {@inheritDoc}\n */\n TimerPromiseFactory.prototype.create = function (delayInMs) {\n debug.assertValue(delayInMs, 'delayInMs');\n debug.assert(delayInMs >= 0, 'delayInMs must be a positive value.');\n var deferred = $.Deferred();\n window.setTimeout(function () { return deferred.resolve(); }, delayInMs);\n return deferred;\n };\n TimerPromiseFactory.instance = new TimerPromiseFactory();\n return TimerPromiseFactory;\n }());\n jsCommon.TimerPromiseFactory = TimerPromiseFactory;\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * Http Status code we are interested.\n */\n (function (HttpStatusCode) {\n HttpStatusCode[HttpStatusCode[\"OK\"] = 200] = \"OK\";\n HttpStatusCode[HttpStatusCode[\"BadRequest\"] = 400] = \"BadRequest\";\n HttpStatusCode[HttpStatusCode[\"Unauthorized\"] = 401] = \"Unauthorized\";\n HttpStatusCode[HttpStatusCode[\"Forbidden\"] = 403] = \"Forbidden\";\n HttpStatusCode[HttpStatusCode[\"RequestEntityTooLarge\"] = 413] = \"RequestEntityTooLarge\";\n })(jsCommon.HttpStatusCode || (jsCommon.HttpStatusCode = {}));\n var HttpStatusCode = jsCommon.HttpStatusCode;\n /**\n * Other HTTP Constants.\n */\n var HttpConstants;\n (function (HttpConstants) {\n HttpConstants.ApplicationOctetStream = 'application/octet-stream';\n HttpConstants.MultiPartFormData = 'multipart/form-data';\n })(HttpConstants = jsCommon.HttpConstants || (jsCommon.HttpConstants = {}));\n /**\n * Extensions to String class.\n */\n var StringExtensions;\n (function (StringExtensions) {\n var HtmlTagRegex = new RegExp('[<>]', 'g');\n function format() {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i - 0] = arguments[_i];\n }\n var s = args[0];\n if (isNullOrUndefinedOrWhiteSpaceString(s))\n return s;\n for (var i = 0; i < args.length - 1; i++) {\n var reg = new RegExp(\"\\\\{\" + i + \"\\\\}\", \"gm\");\n s = s.replace(reg, args[i + 1]);\n }\n return s;\n }\n StringExtensions.format = format;\n /**\n * Compares two strings for equality, ignoring case.\n */\n function equalIgnoreCase(a, b) {\n return StringExtensions.normalizeCase(a) === StringExtensions.normalizeCase(b);\n }\n StringExtensions.equalIgnoreCase = equalIgnoreCase;\n function startsWithIgnoreCase(a, b) {\n var normalizedSearchString = StringExtensions.normalizeCase(b);\n return StringExtensions.normalizeCase(a).indexOf(normalizedSearchString) === 0;\n }\n StringExtensions.startsWithIgnoreCase = startsWithIgnoreCase;\n function startsWith(a, b) {\n return a.indexOf(b) === 0;\n }\n StringExtensions.startsWith = startsWith;\n /** Determines whether a string contains a specified substring (while ignoring case). */\n function containsIgnoreCase(source, substring) {\n if (source == null)\n return false;\n return source.toLowerCase().indexOf(substring.toLowerCase().toString()) !== -1;\n }\n StringExtensions.containsIgnoreCase = containsIgnoreCase;\n /**\n * Normalizes case for a string.\n * Used by equalIgnoreCase method.\n */\n function normalizeCase(value) {\n Utility.throwIfNullOrUndefined(value, StringExtensions, 'normalizeCase', 'value');\n return value.toUpperCase();\n }\n StringExtensions.normalizeCase = normalizeCase;\n /**\n * Is string null or empty or undefined?\n * @return True if the value is null or undefined or empty string,\n * otherwise false.\n */\n function isNullOrEmpty(value) {\n return (value == null) || (value.length === 0);\n }\n StringExtensions.isNullOrEmpty = isNullOrEmpty;\n /**\n * Returns true if the string is null, undefined, empty, or only includes white spaces.\n * @return True if the str is null, undefined, empty, or only includes white spaces,\n * otherwise false.\n */\n function isNullOrUndefinedOrWhiteSpaceString(str) {\n return StringExtensions.isNullOrEmpty(str) || StringExtensions.isNullOrEmpty(str.trim());\n }\n StringExtensions.isNullOrUndefinedOrWhiteSpaceString = isNullOrUndefinedOrWhiteSpaceString;\n /**\n * Returns a value indicating whether the str contains any whitespace.\n */\n function containsWhitespace(str) {\n Utility.throwIfNullOrUndefined(str, this, 'containsWhitespace', 'str');\n var expr = /\\s/;\n return expr.test(str);\n }\n StringExtensions.containsWhitespace = containsWhitespace;\n /**\n * Returns a value indicating whether the str is a whitespace string.\n */\n function isWhitespace(str) {\n Utility.throwIfNullOrUndefined(str, this, 'isWhitespace', 'str');\n return str.trim() === '';\n }\n StringExtensions.isWhitespace = isWhitespace;\n /**\n * Returns the string with any trailing whitespace from str removed.\n */\n function trimTrailingWhitespace(str) {\n Utility.throwIfNullOrUndefined(str, this, 'trimTrailingWhitespace', 'str');\n return str.replace(/\\s+$/, '');\n }\n StringExtensions.trimTrailingWhitespace = trimTrailingWhitespace;\n /**\n * Returns the string with any leading and trailing whitespace from str removed.\n */\n function trimWhitespace(str) {\n Utility.throwIfNullOrUndefined(str, this, 'trimWhitespace', 'str');\n return str.replace(/^\\s+/, '').replace(/\\s+$/, '');\n }\n StringExtensions.trimWhitespace = trimWhitespace;\n /**\n * Returns length difference between the two provided strings.\n */\n function getLengthDifference(left, right) {\n Utility.throwIfNullOrUndefined(left, this, 'getLengthDifference', 'left');\n Utility.throwIfNullOrUndefined(right, this, 'getLengthDifference', 'right');\n return Math.abs(left.length - right.length);\n }\n StringExtensions.getLengthDifference = getLengthDifference;\n /**\n * Repeat char or string several times.\n * @param char The string to repeat.\n * @param count How many times to repeat the string.\n */\n function repeat(char, count) {\n var result = \"\";\n for (var i = 0; i < count; i++) {\n result += char;\n }\n return result;\n }\n StringExtensions.repeat = repeat;\n /**\n * Replace all the occurrences of the textToFind in the text with the textToReplace.\n * @param text The original string.\n * @param textToFind Text to find in the original string.\n * @param textToReplace New text replacing the textToFind.\n */\n function replaceAll(text, textToFind, textToReplace) {\n if (!textToFind)\n return text;\n var pattern = escapeStringForRegex(textToFind);\n return text.replace(new RegExp(pattern, 'gi'), textToReplace);\n }\n StringExtensions.replaceAll = replaceAll;\n function ensureUniqueNames(names) {\n debug.assertValue(names, 'names');\n var usedNames = {};\n // Make sure we are giving fair chance for all columns to stay with their original name\n // First we fill the used names map to contain all the original unique names from the list.\n for (var _i = 0, names_1 = names; _i < names_1.length; _i++) {\n var name_1 = names_1[_i];\n usedNames[name_1] = false;\n }\n var uniqueNames = [];\n // Now we go over all names and find a unique name for each\n for (var _a = 0, names_2 = names; _a < names_2.length; _a++) {\n var name_2 = names_2[_a];\n var uniqueName = name_2;\n // If the (original) column name is already taken lets try to find another name\n if (usedNames[uniqueName]) {\n var counter = 0;\n // Find a name that is not already in the map\n while (usedNames[uniqueName] !== undefined) {\n uniqueName = name_2 + \".\" + (++counter);\n }\n }\n uniqueNames.push(uniqueName);\n usedNames[uniqueName] = true;\n }\n return uniqueNames;\n }\n StringExtensions.ensureUniqueNames = ensureUniqueNames;\n /**\n * Returns a name that is not specified in the values.\n */\n function findUniqueName(usedNames, baseName) {\n debug.assertValue(usedNames, 'usedNames');\n debug.assertValue(baseName, 'baseName');\n // Find a unique name\n var i = 0, uniqueName = baseName;\n while (usedNames[uniqueName]) {\n uniqueName = baseName + (++i);\n }\n return uniqueName;\n }\n StringExtensions.findUniqueName = findUniqueName;\n function constructCommaSeparatedList(list, resourceProvider, maxValue) {\n if (!list || list.length === 0)\n return '';\n if (maxValue === null || maxValue === undefined)\n maxValue = Number.MAX_VALUE;\n var length = Math.min(maxValue, list.length);\n var replacedList = [];\n // Only need to replace user entries of {0} and {1} since we build the list in pairs.\n for (var j = 0; j < 2; j++) {\n var targetValue = '{' + j + '}';\n var replaceValue = '_|_<' + j + '>_|_';\n for (var i = 0; i < length; i++) {\n if (list[i].indexOf(targetValue) > -1) {\n list[i] = list[i].replace(targetValue, replaceValue);\n replacedList.push({ targetValue: targetValue, replaceValue: replaceValue });\n }\n }\n }\n var commaSeparatedList = '';\n for (var i = 0; i < length; i++) {\n if (i === 0)\n commaSeparatedList = list[i];\n else\n commaSeparatedList = StringExtensions.format(resourceProvider.get('FilterRestatement_Comma'), commaSeparatedList, list[i]);\n }\n for (var i = 0; i < replacedList.length; i++) {\n commaSeparatedList = commaSeparatedList.replace(replacedList[i].replaceValue, replacedList[i].targetValue);\n }\n return commaSeparatedList;\n }\n StringExtensions.constructCommaSeparatedList = constructCommaSeparatedList;\n function escapeStringForRegex(s) {\n return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1');\n }\n StringExtensions.escapeStringForRegex = escapeStringForRegex;\n /**\n * Remove file name reserved characters <>:\"/\\|?* from input string.\n */\n function normalizeFileName(fileName) {\n debug.assertValue(fileName, 'fileName');\n return fileName.replace(/[\\<\\>\\:\"\\/\\\\\\|\\?*]/g, '');\n }\n StringExtensions.normalizeFileName = normalizeFileName;\n /**\n * Similar to JSON.stringify, but strips away escape sequences so that the resulting\n * string is human-readable (and parsable by JSON formatting/validating tools).\n */\n function stringifyAsPrettyJSON(object) {\n //let specialCharacterRemover = (key: string, value: string) => value.replace(/[^\\w\\s]/gi, '');\n return JSON.stringify(object /*, specialCharacterRemover*/);\n }\n StringExtensions.stringifyAsPrettyJSON = stringifyAsPrettyJSON;\n /**\n * Derive a CLS-compliant name from a specified string. If no allowed characters are present, return a fallback string instead.\n * TODO (6708134): this should have a fully Unicode-aware implementation\n */\n function deriveClsCompliantName(input, fallback) {\n debug.assertValue(input, 'input');\n var result = input.replace(/^[^A-Za-z]*/g, '').replace(/[ :\\.\\/\\\\\\-\\u00a0\\u1680\\u180e\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]/g, '_').replace(/[\\W]/g, '');\n return result.length > 0 ? result : fallback;\n }\n StringExtensions.deriveClsCompliantName = deriveClsCompliantName;\n /** Performs cheap sanitization by stripping away HTML tag (<>) characters. */\n function stripTagDelimiters(s) {\n return s.replace(HtmlTagRegex, '');\n }\n StringExtensions.stripTagDelimiters = stripTagDelimiters;\n })(StringExtensions = jsCommon.StringExtensions || (jsCommon.StringExtensions = {}));\n /**\n * The general utility class.\n */\n var Utility = (function () {\n function Utility() {\n }\n /**\n * Ensures the specified value is not null or undefined. Throws a relevent exception if it is.\n * @param value The value to check.\n * @param context The context from which the check originated.\n * @param methodName The name of the method that initiated the check.\n * @param parameterName The parameter name of the value to check.\n */\n Utility.throwIfNullOrUndefined = function (value, context, methodName, parameterName) {\n if (value === null) {\n Utility.throwException(jsCommon.Errors.argumentNull(Utility.getComponentName(context) + methodName + '.' + parameterName));\n }\n else if (typeof (value) === Utility.Undefined) {\n Utility.throwException(jsCommon.Errors.argumentUndefined(Utility.getComponentName(context) + methodName + '.' + parameterName));\n }\n };\n /**\n * Ensures the specified value is not null, undefined or empty. Throws a relevent exception if it is.\n * @param value The value to check.\n * @param context The context from which the check originated.\n * @param methodName The name of the method that initiated the check.\n * @param parameterName The parameter name of the value to check.\n */\n Utility.throwIfNullOrEmpty = function (value, context, methodName, parameterName) {\n Utility.throwIfNullOrUndefined(value, context, methodName, parameterName);\n if (!value.length) {\n Utility.throwException(jsCommon.Errors.argumentOutOfRange(Utility.getComponentName(context) + methodName + '.' + parameterName));\n }\n };\n /**\n * Ensures the specified string is not null, undefined or empty. Throws a relevent exception if it is.\n * @param value The value to check.\n * @param context The context from which the check originated.\n * @param methodName The name of the method that initiated the check.\n * @param parameterName The parameter name of the value to check.\n */\n Utility.throwIfNullOrEmptyString = function (value, context, methodName, parameterName) {\n Utility.throwIfNullOrUndefined(value, context, methodName, parameterName);\n if (value.length < 1) {\n Utility.throwException(jsCommon.Errors.argumentOutOfRange(Utility.getComponentName(context) + methodName + '.' + parameterName));\n }\n };\n /**\n * Ensures the specified value is not null, undefined, whitespace or empty. Throws a relevent exception if it is.\n * @param value The value to check.\n * @param context The context from which the check originated.\n * @param methodName The name of the method that initiated the check.\n * @param parameterName The parameter name of the value to check.\n */\n Utility.throwIfNullEmptyOrWhitespaceString = function (value, context, methodName, parameterName) {\n Utility.throwIfNullOrUndefined(value, context, methodName, parameterName);\n if (StringExtensions.isNullOrUndefinedOrWhiteSpaceString(value)) {\n Utility.throwException(jsCommon.Errors.argumentOutOfRange(Utility.getComponentName(context) + methodName + '.' + parameterName));\n }\n };\n /**\n * Ensures the specified condition is true. Throws relevant exception if it isn't.\n * @param condition The condition to check.\n * @param context The context from which the check originated.\n * @param methodName The name of the method that initiated the check.\n * @param parameterName The parameter name against which the condition is checked.\n */\n Utility.throwIfNotTrue = function (condition, context, methodName, parameterName) {\n if (!condition) {\n Utility.throwException(jsCommon.Errors.argument(parameterName, Utility.getComponentName(context) + methodName + '.' + parameterName));\n }\n };\n /**\n * Checks whether the provided value is a 'string'.\n * @param value The value to test.\n */\n Utility.isString = function (value) {\n return ((typeof value) === 'string');\n };\n /**\n * Checks whether the provided value is a 'boolean'.\n * @param value The value to test.\n */\n Utility.isBoolean = function (value) {\n return ((typeof value) === 'boolean');\n };\n /**\n * Checks whether the provided value is a 'number'.\n * @param value The value to test.\n */\n Utility.isNumber = function (value) {\n return ((typeof value) === 'number');\n };\n /**\n * Checks whether the provided value is a Date instance.\n * @param value The value to test.\n */\n Utility.isDate = function (value) {\n return Utility.isObject(value) && (value instanceof Date);\n };\n /**\n * Checks whether the provided value is an 'object'.\n * @param value The value to test.\n */\n Utility.isObject = function (value) {\n return (value != null) && ((typeof value) === 'object');\n };\n /**\n * Checks whether the provided value is null or undefined.\n * @param value The value to test.\n */\n Utility.isNullOrUndefined = function (value) {\n return (value === null) || (typeof (value) === Utility.Undefined);\n };\n /**\n * Combine a base url and a path.\n * @param baseUrl The base url.\n * @param path The path to add on to the base url.\n * @returns The combined url.\n */\n Utility.urlCombine = function (baseUrl, path) {\n Utility.throwIfNullOrUndefined(baseUrl, null, \"urlCombine\", \"baseUrl\");\n Utility.throwIfNullOrUndefined(path, null, \"urlCombine\", \"path\");\n // should any of the components be empty, fail gracefuly - this is important when using the test page\n if (StringExtensions.isNullOrUndefinedOrWhiteSpaceString(path)) {\n return baseUrl;\n }\n if (StringExtensions.isNullOrUndefinedOrWhiteSpaceString(baseUrl)) {\n return path;\n }\n var finalUrl = baseUrl;\n if (finalUrl.charAt(finalUrl.length - 1) === '/') {\n if (path.charAt(0) === '/')\n path = path.slice(1);\n }\n else {\n if (path.charAt(0) !== '/')\n path = '/' + path;\n }\n return finalUrl + path;\n };\n Utility.getAbsoluteUri = function (path) {\n Utility.throwIfNullOrUndefined(path, null, \"getAbsoluteUri\", \"path\");\n var url = path;\n // Make absolute\n if (url && url.indexOf('http') === -1) {\n url = Utility.urlCombine(clusterUri, url);\n }\n return url;\n };\n Utility.getStaticResourceUri = function (path) {\n Utility.throwIfNullOrUndefined(path, null, \"getStaticResourceUri\", \"path\");\n var url = path;\n // Make absolute\n if (url && url.indexOf('http') === -1) {\n url = jsCommon.Utility.urlCombine(Utility.staticContentLocation, url);\n }\n return url;\n };\n Utility.getComponentName = function (context) {\n return !context ? '' : (typeof context).toString() + '.';\n };\n Utility.throwException = function (e) {\n jsCommon.Trace.error(StringExtensions.format(\"Throwing exception: {0}\", JSON.stringify(e)), \n /*includeStackTrace*/ e.stack != null ? false : true);\n throw e;\n };\n Utility.createClassSelector = function (className) {\n Utility.throwIfNullOrEmptyString(className, null, 'CreateClassSelector', 'className');\n return '.' + className;\n };\n Utility.createIdSelector = function (id) {\n Utility.throwIfNullOrEmptyString(id, null, 'CreateIdSelector', 'id');\n return '#' + id;\n };\n /**\n * Creates a client-side Guid string.\n * @returns A string representation of a Guid.\n */\n Utility.generateGuid = function () {\n var guid = \"\", idx = 0;\n for (idx = 0; idx < 32; idx += 1) {\n var guidDigitsItem = Math.random() * 16 | 0;\n switch (idx) {\n case 8:\n case 12:\n case 16:\n case 20:\n guid += \"-\";\n break;\n }\n guid += guidDigitsItem.toString(16);\n }\n return guid;\n };\n /**\n * Try extract a cookie from {@link document.cookie} identified by key.\n */\n Utility.getCookieValue = function (key) {\n // the cookie is of the format <key1=value1>; <key2=value2>. Split by ';', then by '=' \n // to search for the key\n var keyValuePairs = document.cookie.split(';');\n for (var i = 0; i < keyValuePairs.length; i++) {\n var keyValue = keyValuePairs[i];\n var split = keyValue.split('=');\n if (split.length > 0 && split[0].trim() === key) {\n return keyValue.substr(keyValue.indexOf('=') + 1);\n }\n }\n return null;\n };\n /**\n * Extracts the protocol://hostname section of a url.\n * @param url The URL from which to extract the section.\n * @returns The protocol://hostname portion of the given URL.\n */\n Utility.getDomainForUrl = function (url) {\n var hrefObject = Utility.getHrefObjectFromUrl(url);\n return hrefObject.prop('protocol') + '//' + hrefObject.prop('hostname');\n };\n /**\n * Extracts the hostname and absolute path sections of a url.\n * @param url The URL from which to extract the section.\n * @returns The hostname and absolute path portion of the given URL.\n */\n Utility.getHostNameForUrl = function (url) {\n var hrefObject = Utility.getHrefObjectFromUrl(url);\n return Utility.urlCombine(hrefObject.prop('hostname'), hrefObject.prop('pathname'));\n };\n /**\n * Return the original url with query string stripped.\n * @param url The URL from which to extract the section.\n * @returns the original url with query string stripped.\n */\n Utility.getUrlWithoutQueryString = function (url) {\n var hrefObject = Utility.getHrefObjectFromUrl(url);\n return hrefObject.prop('protocol') + '//' + Utility.urlCombine(hrefObject.prop('host'), hrefObject.prop('pathname'));\n };\n /**\n * Extracts the protocol section of a url.\n * @param url The URL from which to extract the section.\n * @returns The protocol for the current URL.\n */\n Utility.getProtocolFromUrl = function (url) {\n return Utility.getHrefObjectFromUrl(url).prop('protocol').replace(':', '');\n };\n /**\n * Returns a formatted href object from a URL.\n * @param url The URL used to generate the object.\n * @returns A jQuery object with the url.\n */\n Utility.getHrefObjectFromUrl = function (url) {\n var aObject = $('<a>');\n aObject = aObject.prop('href', url);\n return aObject;\n };\n /**\n * Converts a WCF representation of a dictionary to a JavaScript dictionary.\n * @param wcfDictionary The WCF dictionary to convert.\n * @returns The native JavaScript representation of this dictionary.\n */\n Utility.convertWcfToJsDictionary = function (wcfDictionary) {\n // convert the WCF JSON representation of a dictionary\n // to JS dictionary.\n // WCF representation: [{\"Key\": Key, \"Value\": Value}..]\n // JS representation: [Key: Value ..]\n var result = {};\n for (var i = 0; i < wcfDictionary.length; i++) {\n var keyValuePair = wcfDictionary[i];\n result[keyValuePair['Key']] = keyValuePair['Value'];\n }\n return result;\n };\n Utility.getDateFromWcfJsonString = function (jsonDate, fromUtcMilliseconds) {\n if (StringExtensions.isNullOrEmpty(jsonDate)) {\n return null;\n }\n var begIndex = jsonDate.indexOf('(');\n var endIndex = jsonDate.indexOf(')');\n if (begIndex !== -1 && endIndex !== -1) {\n var milliseconds = parseInt(jsonDate.substring(begIndex + 1, endIndex), 10);\n if (fromUtcMilliseconds) {\n return new Date(milliseconds);\n }\n else {\n var retValue = new Date(0);\n retValue.setUTCMilliseconds(milliseconds);\n return retValue;\n }\n }\n return null;\n };\n /**\n * Get the outer html of the given jquery object.\n * @param content The jquery object.\n * @returns The entire html representation of the object.\n */\n Utility.getOuterHtml = function (content) {\n return $('<div>').append(content).html();\n };\n /**\n * Comparison Method: Compares two integer numbers.\n * @param a An integer value.\n * @param b An integer value.\n * @returns The comparison result.\n */\n Utility.compareInt = function (a, b) {\n return a - b;\n };\n /**\n * Return the index of the smallest value in a numerical array.\n * @param a A numeric array.\n * @returns The index of the smallest value in the array.\n */\n Utility.getIndexOfMinValue = function (a) {\n var retValue = 0;\n var currentMinValue = a[0];\n for (var i = 0; i < a.length; i++) {\n if (a[i] < currentMinValue) {\n currentMinValue = a[i];\n retValue = i;\n }\n }\n return retValue;\n };\n /**\n * Extracts a url from a background image attribute in the format of: url('www.foobar.com/image.png').\n * @param input The value of the background-image attribute.\n * @returns The extracted url.\n */\n Utility.extractUrlFromCssBackgroundImage = function (input) {\n return input.replace(/\"/g, \"\").replace(/url\\(|\\)$/ig, \"\");\n };\n /**\n * Verifies image data url of images.\n */\n Utility.isValidImageDataUrl = function (url) {\n var regex = new RegExp('data:(image\\/(png|jpg|jpeg|gif|svg))');\n return regex.test(url);\n };\n Utility.isLocalUrl = function (url) {\n return _.startsWith(url, \"data:\") || _.startsWith(url, \"blob:\");\n };\n /**\n * Downloads a content string as a file.\n * @param content Content stream.\n * @param fileName File name to use.\n */\n Utility.saveAsFile = function (content, fileName) {\n var contentBlob = new Blob([content], { type: HttpConstants.ApplicationOctetStream });\n var url = window['webkitURL'] || URL;\n var urlLink = url.createObjectURL(contentBlob);\n var fileNameLink = fileName || urlLink;\n // IE support, use msSaveOrOpenBlob API\n if (window.navigator.msSaveOrOpenBlob) {\n window.navigator.msSaveOrOpenBlob(contentBlob, fileNameLink);\n return;\n }\n // WebKit-based browser support requires generating an anchor tag with\n // download attribute set to blob store and triggering a click event to invoke \n // a download to file action\n var hyperlink = document.createElement('a');\n hyperlink.href = urlLink;\n hyperlink.target = '_blank';\n hyperlink['download'] = fileNameLink;\n document.body.appendChild(hyperlink);\n hyperlink.click();\n document.body.removeChild(hyperlink);\n };\n /**\n * Helper method to get the simple type name from a typed object.\n * @param obj The typed object.\n * @returns The simple type name for the object.\n */\n Utility.getType = function (obj) {\n Utility.throwIfNullEmptyOrWhitespaceString(obj.__type, this, 'getType', 'obj');\n var parts = obj.__type.split(\":\");\n if (parts.length !== 2) {\n jsCommon.Errors.argument(\"obj.__type\", \"Type String not in expected format [Type]#[Namespace]: \" + obj.__type);\n }\n if (parts[1] !== Utility.TypeNamespace) {\n jsCommon.Errors.argument(\"obj.__type\", \"Type Namespace not expected: \" + parts[1]);\n }\n return parts[0];\n };\n /**\n * Check if an element supports a specific event type.\n * @param eventName The name of the event.\n * @param element The element to test for event support.\n * @returns Whether the even is supported on the provided element.\n */\n Utility.isEventSupported = function (eventName, element) {\n eventName = 'on' + eventName;\n var isSupported = (eventName in element);\n if (!isSupported) {\n // if we can't use setAttribute try a generic element\n if (!element.setAttribute) {\n element = document.createElement('div');\n }\n if (element.setAttribute && element.removeAttribute) {\n element.setAttribute(eventName, '');\n isSupported = typeof element[eventName] === 'function';\n // if the property was created - remove it\n if (typeof element[eventName] !== 'undefined') {\n element[eventName] = null;\n }\n element.removeAttribute(eventName);\n }\n }\n element = null;\n return isSupported;\n };\n Utility.toPixel = function (pixelAmount) {\n Utility.throwIfNullOrUndefined(pixelAmount, this, \"toPixel\", \"pixelAmount\");\n return pixelAmount.toString() + jsCommon.CssConstants.pixelUnits;\n };\n Utility.getPropertyCount = function (object) {\n Utility.throwIfNullOrUndefined(object, this, \"getPropertyCount\", \"object\");\n return Object.getOwnPropertyNames(object).length;\n };\n /**\n * Check if an element supports a specific event type.\n * @param filePath File path.\n * @returns File extension.\n */\n Utility.getFileExtension = function (filePath) {\n if (filePath) {\n var index = filePath.lastIndexOf('.');\n if (index >= 0)\n return filePath.substr(index + 1);\n }\n return '';\n };\n /**\n * Extract the filename out of a full path delimited by '\\' or '/'.\n * @param filePath File path.\n * @returns filename File name.\n */\n Utility.extractFileNameFromPath = function (filePath) {\n return filePath.replace(/^.*[\\\\\\/]/, '');\n };\n /**\n * This method indicates whether window.clipboardData is supported.\n * For example, clipboard support for Windows Store apps is currently disabled\n * since window.clipboardData is unsupported (it raises access denied error)\n * since clipboard in Windows Store is being\n * achieved through Windows.ApplicationModel.DataTransfer.Clipboard class.\n */\n Utility.canUseClipboard = function () {\n return (typeof MSApp === \"undefined\");\n };\n Utility.is64BitOperatingSystem = function () {\n return navigator.userAgent.indexOf(\"WOW64\") !== -1 ||\n navigator.userAgent.indexOf(\"Win64\") !== -1;\n };\n Utility.parseNumber = function (value, defaultValue) {\n if (value === null)\n return null;\n if (value === undefined)\n return defaultValue;\n var result = Number(value);\n if (isFinite(result))\n return result;\n if (isNaN(result) && !(typeof value === \"number\" || value === \"NaN\"))\n return defaultValue;\n return result;\n };\n Utility.getURLParamValue = function (name) {\n var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);\n if (results == null) {\n return null;\n }\n else {\n return results[1] || 0;\n }\n };\n /**\n * Return local timezone.\n * This function uses summer and winter offset to determine local time zone.\n * The result localTimeZoneString must be a subset of the strings used by server,\n * as documented here: https://msdn.microsoft.com/en-us/library/gg154758.aspx (Dynamic Daylight Savings Time (Compact 2013)).\n * @return Local timezone string or UTC if timezone cannot be found.\n */\n Utility.getLocalTimeZoneString = function () {\n var timeSummer = new Date(Date.UTC(2005, 6, 30, 0, 0, 0, 0));\n var summerOffset = -1 * timeSummer.getTimezoneOffset();\n var timeWinter = new Date(Date.UTC(2005, 12, 30, 0, 0, 0, 0));\n var winterOffset = -1 * timeWinter.getTimezoneOffset();\n var localTimeZoneString;\n if (-720 === summerOffset && -720 === winterOffset) {\n localTimeZoneString = 'Dateline Standard Time';\n }\n else if (-660 === summerOffset && -660 === winterOffset) {\n localTimeZoneString = 'UTC-11';\n }\n else if (-660 === summerOffset && -660 === winterOffset) {\n localTimeZoneString = 'Samoa Standard Time';\n }\n else if (-600 === summerOffset && -600 === winterOffset) {\n localTimeZoneString = 'Hawaiian Standard Time';\n }\n else if (-480 === summerOffset && -540 === winterOffset) {\n localTimeZoneString = 'Alaskan Standard Time';\n }\n else if (-420 === summerOffset && -480 === winterOffset) {\n localTimeZoneString = 'Pacific Standard Time';\n }\n else if (-420 === summerOffset && -420 === winterOffset) {\n localTimeZoneString = 'US Mountain Standard Time';\n }\n else if (-360 === summerOffset && -420 === winterOffset) {\n localTimeZoneString = 'Mountain Standard Time';\n }\n else if (-360 === summerOffset && -360 === winterOffset) {\n localTimeZoneString = 'Central America Standard Time';\n }\n else if (-300 === summerOffset && -360 === winterOffset) {\n localTimeZoneString = 'Central Standard Time';\n }\n else if (-300 === summerOffset && -300 === winterOffset) {\n localTimeZoneString = 'SA Pacific Standard Time';\n }\n else if (-240 === summerOffset && -300 === winterOffset) {\n localTimeZoneString = 'Eastern Standard Time';\n }\n else if (-270 === summerOffset && -270 === winterOffset) {\n localTimeZoneString = 'Venezuela Standard Time';\n }\n else if (-240 === summerOffset && -240 === winterOffset) {\n localTimeZoneString = 'SA Western Standard Time';\n }\n else if (-240 === summerOffset && -180 === winterOffset) {\n localTimeZoneString = 'Central Brazilian Standard Time';\n }\n else if (-180 === summerOffset && -240 === winterOffset) {\n localTimeZoneString = 'Atlantic Standard Time';\n }\n else if (-180 === summerOffset && -180 === winterOffset) {\n localTimeZoneString = 'Montevideo Standard Time';\n }\n else if (-180 === summerOffset && -120 === winterOffset) {\n localTimeZoneString = 'E. South America Standard Time';\n }\n else if (-150 === summerOffset && -210 === winterOffset) {\n localTimeZoneString = 'Mid-Atlantic Standard Time';\n }\n else if (-120 === summerOffset && -120 === winterOffset) {\n localTimeZoneString = 'SA Eastern Standard Time';\n }\n else if (0 === summerOffset && 0 === winterOffset) {\n localTimeZoneString = 'UTC';\n }\n else if (60 === summerOffset && 0 === winterOffset) {\n localTimeZoneString = 'GMT Standard Time';\n }\n else if (60 === summerOffset && 120 === winterOffset) {\n localTimeZoneString = 'Namibia Standard Time';\n }\n else if (120 === summerOffset && 60 === winterOffset) {\n localTimeZoneString = 'Romance Standard Time';\n }\n else if (120 === summerOffset && 120 === winterOffset) {\n localTimeZoneString = 'South Africa Standard Time';\n }\n else if (180 === summerOffset && 120 === winterOffset) {\n localTimeZoneString = 'GTB Standard Time';\n }\n else if (180 === summerOffset && 180 === winterOffset) {\n localTimeZoneString = 'E. Africa Standard Time';\n }\n else if (240 === summerOffset && 180 === winterOffset) {\n localTimeZoneString = 'Russian Standard Time';\n }\n else if (240 === summerOffset && 240 === winterOffset) {\n localTimeZoneString = 'Arabian Standard Time';\n }\n else if (270 === summerOffset && 210 === winterOffset) {\n localTimeZoneString = 'Iran Standard Time';\n }\n else if (270 === summerOffset && 270 === winterOffset) {\n localTimeZoneString = 'Afghanistan Standard Time';\n }\n else if (300 === summerOffset && 240 === winterOffset) {\n localTimeZoneString = 'Pakistan Standard Time';\n }\n else if (300 === summerOffset && 300 === winterOffset) {\n localTimeZoneString = 'West Asia Standard Time';\n }\n else if (330 === summerOffset && 330 === winterOffset) {\n localTimeZoneString = 'India Standard Time';\n }\n else if (345 === summerOffset && 345 === winterOffset) {\n localTimeZoneString = 'Nepal Standard Time';\n }\n else if (360 === summerOffset && 300 === winterOffset) {\n localTimeZoneString = 'N. Central Asia Standard Time';\n }\n else if (360 === summerOffset && 360 === winterOffset) {\n localTimeZoneString = 'Central Asia Standard Time';\n }\n else if (390 === summerOffset && 390 === winterOffset) {\n localTimeZoneString = 'Myanmar Standard Time';\n }\n else if (420 === summerOffset && 360 === winterOffset) {\n localTimeZoneString = 'North Asia Standard Time';\n }\n else if (420 === summerOffset && 420 === winterOffset) {\n localTimeZoneString = 'SE Asia Standard Time';\n }\n else if (480 === summerOffset && 420 === winterOffset) {\n localTimeZoneString = 'North Asia East Standard Time';\n }\n else if (480 === summerOffset && 480 === winterOffset) {\n localTimeZoneString = 'China Standard Time';\n }\n else if (540 === summerOffset && 480 === winterOffset) {\n localTimeZoneString = 'Yakutsk Standard Time';\n }\n else if (540 === summerOffset && 540 === winterOffset) {\n localTimeZoneString = 'Tokyo Standard Time';\n }\n else if (570 === summerOffset && 570 === winterOffset) {\n localTimeZoneString = 'Cen. Australia Standard Time';\n }\n else if (600 === summerOffset && 600 === winterOffset) {\n localTimeZoneString = 'E. Australia Standard Time';\n }\n else if (600 === summerOffset && 660 === winterOffset) {\n localTimeZoneString = 'AUS Eastern Standard Time';\n }\n else if (660 === summerOffset && 600 === winterOffset) {\n localTimeZoneString = 'Tasmania Standard Time';\n }\n else if (660 === summerOffset && 660 === winterOffset) {\n localTimeZoneString = 'West Pacific Standard Time';\n }\n else if (690 === summerOffset && 690 === winterOffset) {\n localTimeZoneString = 'Central Pacific Standard Time';\n }\n else if (720 === summerOffset && 660 === winterOffset) {\n localTimeZoneString = 'Magadan Standard Time';\n }\n else if (720 === summerOffset && 720 === winterOffset) {\n localTimeZoneString = 'Fiji Standard Time';\n }\n else if (720 === summerOffset && 780 === winterOffset) {\n localTimeZoneString = 'New Zealand Standard Time';\n }\n else if (780 === summerOffset && 780 === winterOffset) {\n localTimeZoneString = 'Tonga Standard Time';\n }\n else {\n localTimeZoneString = 'UTC';\n }\n return localTimeZoneString;\n };\n Utility.TypeNamespace = 'http://schemas.microsoft.com/sqlbi/2013/01/NLRuntimeService';\n Utility.JsonContentType = 'application/json';\n Utility.JpegContentType = 'image/jpeg';\n Utility.XJavascriptContentType = 'application/x-javascript';\n Utility.JsonDataType = 'json';\n Utility.BlobDataType = 'blob';\n Utility.HttpGetMethod = 'GET';\n Utility.HttpPostMethod = 'POST';\n Utility.HttpPutMethod = 'PUT';\n Utility.HttpDeleteMethod = 'DELETE';\n Utility.HttpContentTypeHeader = 'Content-Type';\n Utility.HttpAcceptHeader = 'Accept';\n Utility.Undefined = 'undefined';\n Utility.staticContentLocation = window.location.protocol + '//' + window.location.host;\n return Utility;\n }());\n jsCommon.Utility = Utility;\n var VersionUtility = (function () {\n function VersionUtility() {\n }\n /**\n * Compares 2 version strings.\n * @param versionA The first version string.\n * @param versionB The second version string.\n * @returns A result for the comparison.\n */\n VersionUtility.compareVersions = function (versionA, versionB) {\n var a = versionA.split('.').map(parseFloat);\n var b = versionB.split('.').map(parseFloat);\n var versionParts = Math.max(a.length, b.length);\n for (var i = 0; i < versionParts; i++) {\n var partA = a[i] || 0;\n var partB = b[i] || 0;\n if (partA > partB)\n return 1;\n if (partA < partB)\n return -1;\n }\n return 0;\n };\n return VersionUtility;\n }());\n jsCommon.VersionUtility = VersionUtility;\n var PerformanceUtil;\n (function (PerformanceUtil) {\n var PerfMarker = (function () {\n function PerfMarker(name) {\n this._name = name;\n this._start = PerfMarker.begin(name);\n }\n PerfMarker.begin = function (name) {\n if (window.performance === undefined || performance.mark === undefined)\n return;\n if (console.time) {\n console.time(name);\n }\n name = 'Begin ' + name;\n performance.mark(name);\n return name;\n };\n PerfMarker.prototype.end = function () {\n if (window.performance === undefined || performance.mark === undefined || performance.measure === undefined)\n return;\n var name = this._name;\n var end = 'End ' + name;\n performance.mark(end);\n performance.measure(name, this._start, end);\n if (console.timeEnd) {\n console.timeEnd(name);\n }\n };\n return PerfMarker;\n }());\n PerformanceUtil.PerfMarker = PerfMarker;\n function create(name) {\n return new PerfMarker(name);\n }\n PerformanceUtil.create = create;\n })(PerformanceUtil = jsCommon.PerformanceUtil || (jsCommon.PerformanceUtil = {}));\n var DeferUtility;\n (function (DeferUtility) {\n /**\n * Wraps a callback and returns a new function.\n * The function can be called many times but the callback\n * will only be executed once on the next frame.\n * Use this to throttle big UI updates and access to DOM.\n */\n function deferUntilNextFrame(callback) {\n var isWaiting, args, context;\n if (!window.requestAnimationFrame) {\n window.requestAnimationFrame = function (func) { return setTimeout(func, 1000 / 50); };\n }\n return function () {\n if (!isWaiting) {\n isWaiting = true;\n args = arguments;\n context = this;\n window.requestAnimationFrame(function () {\n isWaiting = false;\n callback.apply(context, args);\n });\n }\n };\n }\n DeferUtility.deferUntilNextFrame = deferUntilNextFrame;\n })(DeferUtility = jsCommon.DeferUtility || (jsCommon.DeferUtility = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var TraceItem = (function () {\n function TraceItem(text, type, sessionId, requestId) {\n this.text = text;\n this.type = type;\n this.sessionId = sessionId;\n this.requestId = requestId;\n this.timeStamp = new Date();\n }\n TraceItem.prototype.toString = function () {\n var resultString = '';\n resultString += (jsCommon.StringExtensions.format('{0} ({1}): {2}', TraceItem.traceTypeStrings[this.type], this.timeStamp.toUTCString(), this.text));\n if (this.requestId)\n resultString += ('\\n(Request id: ' + this.requestId + ')');\n return resultString;\n };\n TraceItem.traceTypeStrings = [\n 'INFORMATION',\n 'VERBOSE',\n 'WARNING',\n 'ERROR',\n 'EXPECTEDERROR',\n 'UNEXPECTEDERROR',\n 'FATAL',\n ];\n return TraceItem;\n }());\n jsCommon.TraceItem = TraceItem;\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var UrlUtils;\n (function (UrlUtils) {\n var urlRegex = /http[s]?:\\/\\/(\\S)+/gi;\n function isValidUrl(value) {\n if (jsCommon.StringExtensions.isNullOrEmpty(value))\n return false;\n var match = jsCommon.RegExpExtensions.run(urlRegex, value);\n if (!!match && match.index === 0)\n return true;\n return false;\n }\n UrlUtils.isValidUrl = isValidUrl;\n /* Tests whether a URL is valid.\n * @param url The url to be tested.\n * @returns Whether the provided url is valid.\n **/\n function isValidImageUrl(url) {\n // VSTS: 7252099 / 7112236\n // For now, passes for any valid Url\n return isValidUrl(url);\n }\n UrlUtils.isValidImageUrl = isValidImageUrl;\n function findAllValidUrls(text) {\n if (jsCommon.StringExtensions.isNullOrEmpty(text))\n return [];\n // Find all urls in the text.\n // TODO: This could potentially be expensive, maybe include a cap here for text with many urls?\n var urlRanges = [];\n var matches;\n var start = 0;\n while ((matches = jsCommon.RegExpExtensions.run(urlRegex, text, start)) !== null) {\n var url = matches[0];\n var end = matches.index + url.length;\n urlRanges.push({\n start: matches.index,\n end: end,\n text: url,\n });\n start = end;\n }\n return urlRanges;\n }\n UrlUtils.findAllValidUrls = findAllValidUrls;\n function getBase64ContentFromDataUri(uri) {\n if (uri.indexOf('data:') !== 0)\n throw new Error(\"Expected data uri\");\n // Locate the base 64 content from the URL (e.g. \"data:image/png;base64,xxxxx=\")\n var base64Token = \";base64,\";\n var indexBase64TokenStart = uri.indexOf(base64Token);\n if (indexBase64TokenStart < 0)\n throw new Error(\"Expected base 64 content in data url\");\n var indexBase64Start = indexBase64TokenStart + base64Token.length;\n return uri.substr(indexBase64Start, uri.length - indexBase64Start);\n }\n UrlUtils.getBase64ContentFromDataUri = getBase64ContentFromDataUri;\n })(UrlUtils = jsCommon.UrlUtils || (jsCommon.UrlUtils = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var BrowserUtils;\n (function (BrowserUtils) {\n function isChrome() {\n var vendorName = window.navigator.vendor || \"\";\n var userAgent = window.navigator.userAgent.toLowerCase();\n return vendorName.toLowerCase().indexOf('google') > -1 &&\n userAgent.indexOf('chrome') > -1 &&\n userAgent.indexOf('edge') === -1 &&\n userAgent.indexOf('opr') === -1;\n }\n BrowserUtils.isChrome = isChrome;\n function isInternetExplorerOrEdge() {\n var userAgent = window.navigator.userAgent.toLowerCase();\n return userAgent.indexOf('msie') > -1\n || userAgent.indexOf('trident') > -1\n || userAgent.indexOf('edge') > -1;\n }\n BrowserUtils.isInternetExplorerOrEdge = isInternetExplorerOrEdge;\n /**\n * Get the current version of IE\n * @returns The version of Internet Explorer or a 0 (indicating the use of another browser).\n */\n function getInternetExplorerVersion() {\n var retValue = 0;\n if (navigator.appName === 'Microsoft Internet Explorer' || window.navigator.userAgent.indexOf('MSIE') >= 0) {\n var re = new RegExp('MSIE ([0-9]{1,}[\\\\.0-9]{0,})');\n var result = re.exec(window.navigator.userAgent);\n if (result) {\n retValue = parseFloat(result[1]);\n }\n }\n return retValue;\n }\n BrowserUtils.getInternetExplorerVersion = getInternetExplorerVersion;\n })(BrowserUtils = jsCommon.BrowserUtils || (jsCommon.BrowserUtils = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * Extensions for Enumerations.\n */\n var EnumExtensions;\n (function (EnumExtensions) {\n /**\n * Gets a value indicating whether the value has the bit flags set.\n */\n function hasFlag(value, flag) {\n debug.assert(!!flag, 'flag must be specified and nonzero.');\n return (value & flag) === flag;\n }\n EnumExtensions.hasFlag = hasFlag;\n /**\n * Sets a value of a flag without modifying any other flags.\n */\n function setFlag(value, flag) {\n debug.assert(!!flag, \"flag must be specified and nonzero.\");\n return value |= flag;\n }\n EnumExtensions.setFlag = setFlag;\n /**\n * Resets a value of a flag without modifying any other flags.\n */\n function resetFlag(value, flag) {\n debug.assert(!!flag, \"flag must be specified and nonzero.\");\n return value &= ~flag;\n }\n EnumExtensions.resetFlag = resetFlag;\n /**\n * According to the TypeScript Handbook, this is safe to do.\n */\n function toString(enumType, value) {\n return enumType[value];\n }\n EnumExtensions.toString = toString;\n })(EnumExtensions = jsCommon.EnumExtensions || (jsCommon.EnumExtensions = {}));\n /**\n * Extensions to String class.\n */\n var StringExtensions;\n (function (StringExtensions) {\n /**\n * Checks if a string ends with a sub-string.\n */\n function endsWith(str, suffix) {\n debug.assertValue(str, 'str');\n debug.assertValue(suffix, 'suffix');\n return str.indexOf(suffix, str.length - suffix.length) !== -1;\n }\n StringExtensions.endsWith = endsWith;\n })(StringExtensions = jsCommon.StringExtensions || (jsCommon.StringExtensions = {}));\n var LogicExtensions;\n (function (LogicExtensions) {\n function XOR(a, b) {\n return (a || b) && !(a && b);\n }\n LogicExtensions.XOR = XOR;\n })(LogicExtensions = jsCommon.LogicExtensions || (jsCommon.LogicExtensions = {}));\n var JsonComparer;\n (function (JsonComparer) {\n /**\n * Performs JSON-style comparison of two objects.\n */\n function equals(x, y) {\n if (x === y)\n return true;\n return JSON.stringify(x) === JSON.stringify(y);\n }\n JsonComparer.equals = equals;\n })(JsonComparer = jsCommon.JsonComparer || (jsCommon.JsonComparer = {}));\n /**\n * Values are in terms of 'pt'\n * Convert to pixels using PixelConverter.fromPoint\n */\n var TextSizeDefaults;\n (function (TextSizeDefaults) {\n /**\n * Stored in terms of 'pt'\n * Convert to pixels using PixelConverter.fromPoint\n */\n TextSizeDefaults.TextSizeMin = 8;\n /**\n * Stored in terms of 'pt'\n * Convert to pixels using PixelConverter.fromPoint\n */\n TextSizeDefaults.TextSizeMax = 40;\n var TextSizeRange = TextSizeDefaults.TextSizeMax - TextSizeDefaults.TextSizeMin;\n /**\n * Returns the percentage of this value relative to the TextSizeMax\n * @param textSize - should be given in terms of 'pt'\n */\n function getScale(textSize) {\n return (textSize - TextSizeDefaults.TextSizeMin) / TextSizeRange;\n }\n TextSizeDefaults.getScale = getScale;\n })(TextSizeDefaults = jsCommon.TextSizeDefaults || (jsCommon.TextSizeDefaults = {}));\n var PixelConverter;\n (function (PixelConverter) {\n var PxPtRatio = 4 / 3;\n var PixelString = 'px';\n /**\n * Appends 'px' to the end of number value for use as pixel string in styles\n */\n function toString(px) {\n return px + PixelString;\n }\n PixelConverter.toString = toString;\n /**\n * Converts point value (pt) to pixels\n * Returns a string for font-size property\n * e.g. fromPoint(8) => '24px'\n */\n function fromPoint(pt) {\n return toString(fromPointToPixel(pt));\n }\n PixelConverter.fromPoint = fromPoint;\n /**\n * Converts point value (pt) to pixels\n * Returns a number for font-size property\n * e.g. fromPoint(8) => 24px\n */\n function fromPointToPixel(pt) {\n return (PxPtRatio * pt);\n }\n PixelConverter.fromPointToPixel = fromPointToPixel;\n /**\n * Converts pixel value (px) to pt\n * e.g. toPoint(24) => 8\n */\n function toPoint(px) {\n return px / PxPtRatio;\n }\n PixelConverter.toPoint = toPoint;\n })(PixelConverter = jsCommon.PixelConverter || (jsCommon.PixelConverter = {}));\n var RegExpExtensions;\n (function (RegExpExtensions) {\n /**\n * Runs exec on regex starting from 0 index\n * This is the expected behavior but RegExp actually remember\n * the last index they stopped at (found match at) and will\n * return unexpected results when run in sequence.\n * @param regex - regular expression object\n * @param value - string to search wiht regex\n * @param start - index within value to start regex\n */\n function run(regex, value, start) {\n debug.assertValue(regex, 'regex');\n regex.lastIndex = start || 0;\n return regex.exec(value);\n }\n RegExpExtensions.run = run;\n })(RegExpExtensions = jsCommon.RegExpExtensions || (jsCommon.RegExpExtensions = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var utility;\n (function (utility) {\n var StyleUtils;\n (function (StyleUtils) {\n function getRotateAngleFromElement(element) {\n var rawElemStyle = element.get(0).style;\n var transformString = rawElemStyle.transform || rawElemStyle.webkitTransform;\n if (transformString) {\n var transform = transformString.match(/rotate\\((-?\\d+(?:\\.\\d*)?)deg\\)/);\n if (transform) {\n return parseFloat(transform[1]);\n }\n }\n return 0;\n }\n StyleUtils.getRotateAngleFromElement = getRotateAngleFromElement;\n function getTranslateTransformFromElement(element) {\n var rawElemStyle = element.get(0).style;\n // IE will recognize \"webkitTransform\" as \"WebkitTransform\" and set that as style property. \n // This means transform property is not read.\n // We put the \"transform\" before the \"webkitTransform\" to counteract the weirdness of IE. \n var transformString = rawElemStyle.transform || rawElemStyle.webkitTransform;\n var retValue = { x: 0, y: 0 };\n if (transformString && transformString.length > 0) {\n var transform = transformString.match(/translate\\((-?\\d+(?:\\.\\d*)?)px, (-?\\d+(?:\\.\\d*)?)px\\)/);\n if (transform) {\n retValue.x = parseFloat(transform[1]);\n retValue.y = parseFloat(transform[2]);\n }\n }\n return retValue;\n }\n StyleUtils.getTranslateTransformFromElement = getTranslateTransformFromElement;\n function getPadding(element) {\n if (!element)\n return;\n return {\n left: parseFloat(element.css('padding-left')) || 0,\n right: parseFloat(element.css('padding-right')) || 0,\n top: parseFloat(element.css('padding-top')) || 0,\n bottom: parseFloat(element.css('padding-bottom')) || 0,\n };\n }\n StyleUtils.getPadding = getPadding;\n })(StyleUtils = utility.StyleUtils || (utility.StyleUtils = {}));\n })(utility = visuals.utility || (visuals.utility = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n var ConsoleTracer = (function () {\n function ConsoleTracer() {\n }\n ConsoleTracer.prototype.logTrace = function (trace) {\n if (DEBUG) {\n switch (trace.type) {\n case jsCommon.TraceType.Information:\n console.info(trace.toString());\n break;\n case jsCommon.TraceType.UnexpectedError:\n case jsCommon.TraceType.Error:\n case jsCommon.TraceType.Fatal:\n console.error(trace.toString());\n break;\n case jsCommon.TraceType.ExpectedError:\n case jsCommon.TraceType.Warning:\n console.warn(trace.toString());\n break;\n case jsCommon.TraceType.Verbose:\n console.log(trace.toString());\n break;\n default:\n console.log(trace.toString());\n break;\n }\n }\n };\n return ConsoleTracer;\n }());\n jsCommon.ConsoleTracer = ConsoleTracer;\n var Trace;\n (function (Trace) {\n var traceMaxCount = 1000;\n var traces = new Array(traceMaxCount);\n var lastTraceIndex = -1;\n var defaultListener = new ConsoleTracer();\n var listeners = new Array(defaultListener);\n /**\n * Trace a warning. Please ensure that no PII is being logged.\n */\n function warning(text, requestId) {\n debug.assertValue(text, 'text');\n logTraceInternal(new jsCommon.TraceItem(text, jsCommon.TraceType.Warning, requestId));\n }\n Trace.warning = warning;\n /**\n * Trace an error. Please ensure that no PII is being logged.\n */\n function error(text, includeStackTrace, requestId) {\n debug.assertValue(text, 'text');\n if (includeStackTrace)\n text = jsCommon.StringExtensions.format(\"{0}.\\nStack:\\n{1}\", text, jsCommon.getStackTrace());\n logTraceInternal(new jsCommon.TraceItem(text, jsCommon.TraceType.Error, requestId));\n }\n Trace.error = error;\n /**\n * Trace an information. Please ensure that no PII is being logged.\n */\n function verbose(text, requestId) {\n debug.assertValue(text, 'text');\n logTraceInternal(new jsCommon.TraceItem(text, jsCommon.TraceType.Verbose, requestId));\n }\n Trace.verbose = verbose;\n function addListener(listener) {\n debug.assertValue(listener, 'listener');\n listeners.push(listener);\n }\n Trace.addListener = addListener;\n function removeListener(listener) {\n debug.assertValue(listener, 'listener');\n var index = listeners.indexOf(listener);\n if (index >= 0)\n listeners.splice(index, 1);\n }\n Trace.removeListener = removeListener;\n function resetListeners() {\n listeners = new Array(defaultListener);\n }\n Trace.resetListeners = resetListeners;\n function reset() {\n lastTraceIndex = -1;\n }\n Trace.reset = reset;\n function getTraces() {\n if (lastTraceIndex < 0)\n return;\n var result = new Array(lastTraceIndex + 1);\n for (var i = 0; i <= lastTraceIndex; i++)\n result[i] = traces[i];\n return result;\n }\n Trace.getTraces = getTraces;\n /**\n * Note: Used for unit-test only.\n */\n function disableDefaultListener() {\n removeListener(defaultListener);\n }\n Trace.disableDefaultListener = disableDefaultListener;\n function enableDefaultListener() {\n addListener(defaultListener);\n }\n Trace.enableDefaultListener = enableDefaultListener;\n function logTraceInternal(trace) {\n if ((lastTraceIndex + 1) >= traceMaxCount)\n reset();\n traces[++lastTraceIndex] = trace;\n for (var i = 0, len = listeners.length; i < len; i++)\n listeners[i].logTrace(trace);\n }\n })(Trace = jsCommon.Trace || (jsCommon.Trace = {}));\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * The types of possible traces within the system, this aligns to the traces available in Cloud Platform.\n */\n (function (TraceType) {\n TraceType[TraceType[\"Information\"] = 0] = \"Information\";\n TraceType[TraceType[\"Verbose\"] = 1] = \"Verbose\";\n TraceType[TraceType[\"Warning\"] = 2] = \"Warning\";\n TraceType[TraceType[\"Error\"] = 3] = \"Error\";\n TraceType[TraceType[\"ExpectedError\"] = 4] = \"ExpectedError\";\n TraceType[TraceType[\"UnexpectedError\"] = 5] = \"UnexpectedError\";\n TraceType[TraceType[\"Fatal\"] = 6] = \"Fatal\";\n })(jsCommon.TraceType || (jsCommon.TraceType = {}));\n var TraceType = jsCommon.TraceType;\n})(jsCommon || (jsCommon = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar jsCommon;\n(function (jsCommon) {\n /**\n * JavaScript files.\n */\n var MSMapcontrol = 'https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&s=1&onscriptload=globalMapControlLoaded';\n /**\n * Map loading logic.\n */\n var MSMapcontrolLoaded = false;\n var WaitForMSMapLoad = null;\n var PowerViewPackage = {\n javaScriptFiles: [\n powerbi.build + '/externals/pv/webclient.js'\n ],\n cssFiles: [\n powerbi.build + '/externals/pv/Styles/_all.css'\n ],\n javaScriptFilesWithCallback: [\n { javascriptFile: MSMapcontrol, onLoadCallback: waitForMapControlLoaded }\n ]\n };\n function ensurePowerView(action) {\n if (action === void 0) { action = _.noop; }\n jsCommon.requires(PowerViewPackage, action);\n }\n jsCommon.ensurePowerView = ensurePowerView;\n var MapPackage = {\n javaScriptFilesWithCallback: [\n { javascriptFile: MSMapcontrol, onLoadCallback: waitForMapControlLoaded }\n ]\n };\n function ensureMap(locale, action) {\n var mapPackageWithLocale = powerbi.Prototype.inherit(MapPackage);\n if (!_.isEmpty(locale)) {\n mapPackageWithLocale.javaScriptFilesWithCallback[0].javascriptFile = MSMapcontrol.concat('&mkt=' + locale);\n }\n jsCommon.requires(mapPackageWithLocale, action);\n }\n jsCommon.ensureMap = ensureMap;\n function mapControlLoaded() {\n MSMapcontrolLoaded = true;\n if (WaitForMSMapLoad) {\n WaitForMSMapLoad.resolve();\n WaitForMSMapLoad = undefined;\n }\n }\n jsCommon.mapControlLoaded = mapControlLoaded;\n function waitForMapControlLoaded() {\n var task;\n if (!MSMapcontrolLoaded) {\n task = WaitForMSMapLoad = $.Deferred();\n }\n else {\n task = $.Deferred();\n task.resolve();\n }\n return task.promise();\n }\n jsCommon.waitForMapControlLoaded = waitForMapControlLoaded;\n})(jsCommon || (jsCommon = {}));\n/* tslint:disable:no-unused-variable */\nvar globalMapControlLoaded = function () {\n // Map requires a function in the global namespace to callback once loaded\n jsCommon.mapControlLoaded();\n};\n/* tslint:enable:no-unused-variable */ \n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar InJs;\n(function (InJs) {\n /**\n * The types of possible traces within the system, this aligns to the traces available in Cloud Platform.\n */\n (function (TraceType) {\n TraceType[TraceType[\"information\"] = 0] = \"information\";\n TraceType[TraceType[\"verbose\"] = 1] = \"verbose\";\n TraceType[TraceType[\"warning\"] = 2] = \"warning\";\n TraceType[TraceType[\"error\"] = 3] = \"error\";\n TraceType[TraceType[\"expectedError\"] = 4] = \"expectedError\";\n TraceType[TraceType[\"unexpectedError\"] = 5] = \"unexpectedError\";\n TraceType[TraceType[\"fatal\"] = 6] = \"fatal\";\n })(InJs.TraceType || (InJs.TraceType = {}));\n var TraceType = InJs.TraceType;\n})(InJs || (InJs = {}));\n\n\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export declare let build;\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export const CategoryTypes = {\r\n Address: \"Address\",\r\n City: \"City\",\r\n Continent: \"Continent\",\r\n CountryRegion: \"Country\", // The text has to stay \"Country\" because it is used as a key in the geocoding caching dictionary\r\n County: \"County\",\r\n Longitude: \"Longitude\",\r\n Latitude: \"Latitude\",\r\n Place: \"Place\",\r\n PostalCode: \"PostalCode\",\r\n StateOrProvince: \"StateOrProvince\"\r\n };\r\n\r\n export interface IGeoTaggingAnalyzerService {\r\n isLongitudeOrLatitude(fieldRefName: string): boolean;\r\n isGeographic(fieldRefName: string): boolean;\r\n isGeocodable(fieldRefName: string): boolean;\r\n getFieldType(fieldName: string): string;\r\n isGeoshapable(fieldRefName: string): boolean;\r\n }\r\n\r\n export function createGeoTaggingAnalyzerService(getLocalized: (string) => string): IGeoTaggingAnalyzerService {\r\n return new GeoTaggingAnalyzerService(getLocalized);\r\n }\r\n\r\n const EnglishBackup = {\r\n GeotaggingString_Continent: \"continent\",\r\n GeotaggingString_Continents: \"continents\",\r\n GeotaggingString_Country: \"country\",\r\n GeotaggingString_Countries: \"countries\",\r\n GeotaggingString_State: \"state\",\r\n GeotaggingString_States: \"states\",\r\n GeotaggingString_City: \"city\",\r\n GeotaggingString_Cities: \"cities\",\r\n GeotaggingString_Town: \"town\",\r\n GeotaggingString_Towns: \"towns\",\r\n GeotaggingString_Province: \"province\",\r\n GeotaggingString_Provinces: \"provinces\",\r\n GeotaggingString_County: \"county\",\r\n GeotaggingString_Counties: \"counties\",\r\n GeotaggingString_Village: \"village\",\r\n GeotaggingString_Villages: \"villages\",\r\n GeotaggingString_Post: \"post\",\r\n GeotaggingString_Zip: \"zip\",\r\n GeotaggingString_Code: \"code\",\r\n GeotaggingString_Place: \"place\",\r\n GeotaggingString_Places: \"places\",\r\n GeotaggingString_Address: \"address\",\r\n GeotaggingString_Addresses: \"addresses\",\r\n GeotaggingString_Street: \"street\",\r\n GeotaggingString_Streets: \"streets\",\r\n GeotaggingString_Longitude: \"longitude\",\r\n GeotaggingString_Longitude_Short: \"lon\",\r\n GeotaggingString_Latitude: \"latitude\",\r\n GeotaggingString_Latitude_Short: \"lat\",\r\n GeotaggingString_PostalCode: \"postal code\",\r\n GeotaggingString_PostalCodes: \"postal codes\",\r\n GeotaggingString_ZipCode: \"zip code\",\r\n GeotaggingString_ZipCodes: \"zip codes\",\r\n GeotaggingString_Territory: \"territory\",\r\n GeotaggingString_Territories: \"territories\",\r\n GeotaggingString_VRMBackCompat_CountryRegion: \"CountryRegion\",\r\n GeotaggingString_VRMBackCompat_StateOrProvince: \"StateOrProvince\",\r\n };\r\n\r\n export class GeoTaggingAnalyzerService implements IGeoTaggingAnalyzerService {\r\n private GeotaggingString_Continent;\r\n private GeotaggingString_Continents;\r\n private GeotaggingString_Country;\r\n private GeotaggingString_Countries;\r\n private GeotaggingString_State;\r\n private GeotaggingString_States;\r\n private GeotaggingString_City;\r\n private GeotaggingString_Cities;\r\n private GeotaggingString_Town;\r\n private GeotaggingString_Towns;\r\n private GeotaggingString_Province;\r\n private GeotaggingString_Provinces;\r\n private GeotaggingString_County;\r\n private GeotaggingString_Counties;\r\n private GeotaggingString_Village;\r\n private GeotaggingString_Villages;\r\n private GeotaggingString_Post;\r\n private GeotaggingString_Zip;\r\n private GeotaggingString_Code;\r\n private GeotaggingString_Place;\r\n private GeotaggingString_Places;\r\n private GeotaggingString_Address;\r\n private GeotaggingString_Addresses;\r\n private GeotaggingString_Street;\r\n private GeotaggingString_Streets;\r\n private GeotaggingString_Longitude;\r\n private GeotaggingString_Longitude_Short;\r\n private GeotaggingString_Latitude;\r\n private GeotaggingString_Latitude_Short;\r\n private GeotaggingString_PostalCode;\r\n private GeotaggingString_PostalCodes;\r\n private GeotaggingString_ZipCode;\r\n private GeotaggingString_ZipCodes;\r\n private GeotaggingString_Territory;\r\n private GeotaggingString_Territories;\r\n private GeotaggingString_VRMBackCompat_CountryRegion = \"CountryRegion\";\r\n private GeotaggingString_VRMBackCompat_StateOrProvince = \"StateOrProvince\";\r\n\r\n constructor(getLocalized: (string) => string) {\r\n this.GeotaggingString_Continent = getLocalized(\"GeotaggingString_Continent\").toLowerCase();\r\n this.GeotaggingString_Continents = getLocalized(\"GeotaggingString_Continents\").toLowerCase();\r\n this.GeotaggingString_Country = getLocalized(\"GeotaggingString_Country\").toLowerCase();\r\n this.GeotaggingString_Countries = getLocalized(\"GeotaggingString_Countries\").toLowerCase();\r\n this.GeotaggingString_State = getLocalized(\"GeotaggingString_State\").toLowerCase();\r\n this.GeotaggingString_States = getLocalized(\"GeotaggingString_States\").toLowerCase();\r\n this.GeotaggingString_City = getLocalized(\"GeotaggingString_City\").toLowerCase();\r\n this.GeotaggingString_Cities = getLocalized(\"GeotaggingString_Cities\").toLowerCase();\r\n this.GeotaggingString_Town = getLocalized(\"GeotaggingString_Town\").toLowerCase();\r\n this.GeotaggingString_Towns = getLocalized(\"GeotaggingString_Towns\").toLowerCase();\r\n this.GeotaggingString_Province = getLocalized(\"GeotaggingString_Province\").toLowerCase();\r\n this.GeotaggingString_Provinces = getLocalized(\"GeotaggingString_Provinces\").toLowerCase();\r\n this.GeotaggingString_County = getLocalized(\"GeotaggingString_County\").toLowerCase();\r\n this.GeotaggingString_Counties = getLocalized(\"GeotaggingString_Counties\").toLowerCase();\r\n this.GeotaggingString_Village = getLocalized(\"GeotaggingString_Village\").toLowerCase();\r\n this.GeotaggingString_Villages = getLocalized(\"GeotaggingString_Villages\").toLowerCase();\r\n this.GeotaggingString_Post = getLocalized(\"GeotaggingString_Post\").toLowerCase();\r\n this.GeotaggingString_Zip = getLocalized(\"GeotaggingString_Zip\").toLowerCase();\r\n this.GeotaggingString_Code = getLocalized(\"GeotaggingString_Code\").toLowerCase();\r\n this.GeotaggingString_Place = getLocalized(\"GeotaggingString_Place\").toLowerCase();\r\n this.GeotaggingString_Places = getLocalized(\"GeotaggingString_Places\").toLowerCase();\r\n this.GeotaggingString_Address = getLocalized(\"GeotaggingString_Address\").toLowerCase();\r\n this.GeotaggingString_Addresses = getLocalized(\"GeotaggingString_Addresses\").toLowerCase();\r\n this.GeotaggingString_Street = getLocalized(\"GeotaggingString_Street\").toLowerCase();\r\n this.GeotaggingString_Streets = getLocalized(\"GeotaggingString_Streets\").toLowerCase();\r\n this.GeotaggingString_Longitude = getLocalized(\"GeotaggingString_Longitude\").toLowerCase();\r\n this.GeotaggingString_Longitude_Short = getLocalized(\"GeotaggingString_Longitude_Short\").toLowerCase();\r\n this.GeotaggingString_Latitude = getLocalized(\"GeotaggingString_Latitude\").toLowerCase();\r\n this.GeotaggingString_Latitude_Short = getLocalized(\"GeotaggingString_Latitude_Short\").toLowerCase();\r\n this.GeotaggingString_PostalCode = getLocalized(\"GeotaggingString_PostalCode\").toLowerCase();\r\n this.GeotaggingString_PostalCodes = getLocalized(\"GeotaggingString_PostalCodes\").toLowerCase();\r\n this.GeotaggingString_ZipCode = getLocalized(\"GeotaggingString_ZipCode\").toLowerCase();\r\n this.GeotaggingString_ZipCodes = getLocalized(\"GeotaggingString_ZipCodes\").toLowerCase();\r\n this.GeotaggingString_Territory = getLocalized(\"GeotaggingString_Territory\").toLowerCase();\r\n this.GeotaggingString_Territories = getLocalized(\"GeotaggingString_Territories\").toLowerCase();\r\n }\r\n\r\n public isLongitudeOrLatitude(fieldRefName: string): boolean {\r\n return this.isLongitude(fieldRefName) ||\r\n this.isLatitude(fieldRefName);\r\n }\r\n\r\n public isGeographic(fieldRefName: string): boolean {\r\n return this.isLongitudeOrLatitude(fieldRefName) ||\r\n this.isGeocodable(fieldRefName);\r\n }\r\n\r\n public isGeocodable(fieldRefName: string): boolean {\r\n return this.isAddress(fieldRefName) ||\r\n this.isCity(fieldRefName) ||\r\n this.isContinent(fieldRefName) ||\r\n this.isCountry(fieldRefName) ||\r\n this.isCounty(fieldRefName) ||\r\n this.isStateOrProvince(fieldRefName) ||\r\n this.isPlace(fieldRefName) ||\r\n this.isPostalCode(fieldRefName) ||\r\n this.isTerritory(fieldRefName);\r\n }\r\n\r\n public isGeoshapable(fieldRefName: string): boolean {\r\n return this.isCity(fieldRefName) ||\r\n this.isCountry(fieldRefName) ||\r\n this.isCounty(fieldRefName) ||\r\n this.isStateOrProvince(fieldRefName) ||\r\n this.isPostalCode(fieldRefName) ||\r\n this.isTerritory(fieldRefName) ||\r\n this.isGeoshapableEnglish(fieldRefName);\r\n }\r\n\r\n private isGeoshapableEnglish(fieldRefName: string): boolean {\r\n return this.isEnglishCity(fieldRefName) ||\r\n this.isEnglishCountry(fieldRefName) ||\r\n this.isEnglishCounty(fieldRefName) ||\r\n this.isEnglishStateOrProvince(fieldRefName) ||\r\n this.isEnglishPostalCode(fieldRefName) ||\r\n this.isEnglishTerritory(fieldRefName);\r\n }\r\n\r\n private isAddress(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_Address,\r\n this.GeotaggingString_Addresses,\r\n this.GeotaggingString_Street,\r\n this.GeotaggingString_Streets\r\n ]);\r\n }\r\n\r\n private isPlace(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_Place,\r\n this.GeotaggingString_Places\r\n ]);\r\n }\r\n\r\n private isCity(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_City,\r\n this.GeotaggingString_Cities,\r\n this.GeotaggingString_Town,\r\n this.GeotaggingString_Towns,\r\n this.GeotaggingString_Village,\r\n this.GeotaggingString_Villages\r\n ]);\r\n }\r\n\r\n private isStateOrProvince(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_State,\r\n this.GeotaggingString_States,\r\n this.GeotaggingString_Province,\r\n this.GeotaggingString_Provinces,\r\n this.GeotaggingString_VRMBackCompat_StateOrProvince,\r\n ]);\r\n }\r\n\r\n private isCountry(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_Country,\r\n this.GeotaggingString_Countries,\r\n this.GeotaggingString_VRMBackCompat_CountryRegion\r\n ]);\r\n }\r\n\r\n private isCounty(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_County,\r\n this.GeotaggingString_Counties\r\n ]);\r\n }\r\n\r\n private isContinent(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_Continent,\r\n this.GeotaggingString_Continents\r\n ]);\r\n }\r\n\r\n private isPostalCode(fieldRefName: string): boolean {\r\n let result =\r\n (GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_Post,\r\n this.GeotaggingString_Zip])\r\n && GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Code])) ||\r\n GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_PostalCode,\r\n this.GeotaggingString_PostalCodes,\r\n this.GeotaggingString_ZipCode,\r\n this.GeotaggingString_ZipCodes\r\n ]);\r\n\r\n //Check again for strings without whitespace\r\n if (!result) {\r\n let whiteSpaceRegex = /\\s+/;\r\n let fieldNameWithoutWhitespace = fieldRefName.replace(whiteSpaceRegex, \"\");\r\n result = GeoTaggingAnalyzerService.hasMatches(fieldNameWithoutWhitespace, [\r\n this.GeotaggingString_PostalCode.replace(whiteSpaceRegex, ''),\r\n this.GeotaggingString_PostalCodes.replace(whiteSpaceRegex, ''),\r\n this.GeotaggingString_ZipCode.replace(whiteSpaceRegex, ''),\r\n this.GeotaggingString_ZipCodes.replace(whiteSpaceRegex, '')\r\n ]);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private isLongitude(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Longitude])\r\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Longitude_Short], true /* useStrict */);\r\n }\r\n\r\n private isLatitude(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Latitude])\r\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Latitude_Short], true /* useStrict */);\r\n }\r\n\r\n private isTerritory(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n this.GeotaggingString_Territory,\r\n this.GeotaggingString_Territories\r\n ]);\r\n }\r\n\r\n private static hasMatches(fieldName: string, possibleMatches: string[], useStrict?: boolean): boolean {\r\n let nonWordRegex = /\\W/;\r\n let value = fieldName.toLowerCase();\r\n for (let i = 0, len = possibleMatches.length; i < len; i++) {\r\n let possibleMatch = possibleMatches[i].toLowerCase();\r\n if (!useStrict) {\r\n if (value.indexOf(possibleMatch) > -1)\r\n return true;\r\n }\r\n else {\r\n let indexofpossibleMatch = value.indexOf(possibleMatch);\r\n if (indexofpossibleMatch > -1) {\r\n let wordEndFlag, wordBeginFlag: boolean;\r\n wordEndFlag = wordBeginFlag = true;\r\n if (indexofpossibleMatch - 1 > 0)\r\n wordBeginFlag = nonWordRegex.test(value[indexofpossibleMatch - 1]);\r\n if (indexofpossibleMatch + possibleMatch.length < value.length)\r\n wordEndFlag = nonWordRegex.test(value[indexofpossibleMatch + possibleMatch.length]);\r\n if (wordBeginFlag && wordEndFlag)\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n public getFieldType(fieldName: string): string {\r\n if (fieldName == null)\r\n return undefined;\r\n if (this.isLatitude(fieldName))\r\n return CategoryTypes.Latitude;\r\n if (this.isLongitude(fieldName))\r\n return CategoryTypes.Longitude;\r\n if (this.isPostalCode(fieldName))\r\n return CategoryTypes.PostalCode;\r\n if (this.isAddress(fieldName))\r\n return CategoryTypes.Address;\r\n if (this.isPlace(fieldName))\r\n return CategoryTypes.Place;\r\n if (this.isCity(fieldName))\r\n return CategoryTypes.City;\r\n if (this.isCountry(fieldName))\r\n return CategoryTypes.CountryRegion;\r\n if (this.isCounty(fieldName))\r\n return CategoryTypes.County;\r\n if (this.isStateOrProvince(fieldName))\r\n return CategoryTypes.StateOrProvince;\r\n if (this.isContinent(fieldName))\r\n return CategoryTypes.Continent;\r\n return this.getEnglishFieldType(fieldName);\r\n }\r\n\r\n private isEnglishAddress(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_Address,\r\n EnglishBackup.GeotaggingString_Addresses,\r\n EnglishBackup.GeotaggingString_Street,\r\n EnglishBackup.GeotaggingString_Streets\r\n ]);\r\n }\r\n\r\n private isEnglishPlace(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_Place,\r\n EnglishBackup.GeotaggingString_Places\r\n ]);\r\n }\r\n\r\n private isEnglishCity(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_City,\r\n EnglishBackup.GeotaggingString_Cities,\r\n EnglishBackup.GeotaggingString_Town,\r\n EnglishBackup.GeotaggingString_Towns,\r\n EnglishBackup.GeotaggingString_Village,\r\n EnglishBackup.GeotaggingString_Villages\r\n ]);\r\n }\r\n\r\n private isEnglishStateOrProvince(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_State,\r\n EnglishBackup.GeotaggingString_States,\r\n EnglishBackup.GeotaggingString_Province,\r\n EnglishBackup.GeotaggingString_Provinces,\r\n EnglishBackup.GeotaggingString_VRMBackCompat_StateOrProvince,\r\n ]);\r\n }\r\n\r\n private isEnglishCountry(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_Country,\r\n EnglishBackup.GeotaggingString_Countries,\r\n EnglishBackup.GeotaggingString_VRMBackCompat_CountryRegion\r\n ]);\r\n }\r\n\r\n private isEnglishCounty(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_County,\r\n EnglishBackup.GeotaggingString_Counties\r\n ]);\r\n }\r\n\r\n private isEnglishContinent(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_Continent,\r\n EnglishBackup.GeotaggingString_Continents\r\n ]);\r\n }\r\n\r\n private isEnglishPostalCode(fieldRefName: string): boolean {\r\n let result =\r\n (GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_Post,\r\n EnglishBackup.GeotaggingString_Zip])\r\n && GeoTaggingAnalyzerService.hasMatches(fieldRefName, [this.GeotaggingString_Code])) ||\r\n GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_PostalCode,\r\n EnglishBackup.GeotaggingString_PostalCodes,\r\n EnglishBackup.GeotaggingString_ZipCode,\r\n EnglishBackup.GeotaggingString_ZipCodes\r\n ]);\r\n\r\n //Check again for strings without whitespace\r\n if (!result) {\r\n let whiteSpaceRegexPattern = new RegExp('\\s');\r\n result = GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_PostalCode.replace(whiteSpaceRegexPattern, ''),\r\n EnglishBackup.GeotaggingString_PostalCodes.replace(whiteSpaceRegexPattern, ''),\r\n EnglishBackup.GeotaggingString_ZipCode.replace(whiteSpaceRegexPattern, ''),\r\n EnglishBackup.GeotaggingString_ZipCodes.replace(whiteSpaceRegexPattern, '')\r\n ]);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private isEnglishLongitude(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Longitude])\r\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Longitude_Short], true /* useStrict */);\r\n }\r\n\r\n private isEnglishLatitude(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Latitude])\r\n || GeoTaggingAnalyzerService.hasMatches(fieldRefName, [EnglishBackup.GeotaggingString_Latitude_Short], true /* useStrict */);\r\n }\r\n\r\n protected isEnglishTerritory(fieldRefName: string): boolean {\r\n return GeoTaggingAnalyzerService.hasMatches(fieldRefName, [\r\n EnglishBackup.GeotaggingString_Territory,\r\n EnglishBackup.GeotaggingString_Territories\r\n ]);\r\n }\r\n\r\n private getEnglishFieldType(fieldName: string): string {\r\n if (fieldName == null)\r\n return undefined;\r\n if (this.isEnglishLatitude(fieldName))\r\n return CategoryTypes.Latitude;\r\n if (this.isEnglishLongitude(fieldName))\r\n return CategoryTypes.Longitude;\r\n if (this.isEnglishPostalCode(fieldName))\r\n return CategoryTypes.PostalCode;\r\n if (this.isEnglishAddress(fieldName))\r\n return CategoryTypes.Address;\r\n if (this.isEnglishPlace(fieldName))\r\n return CategoryTypes.Place;\r\n if (this.isEnglishCity(fieldName))\r\n return CategoryTypes.City;\r\n if (this.isEnglishCountry(fieldName))\r\n return CategoryTypes.CountryRegion;\r\n if (this.isEnglishCounty(fieldName))\r\n return CategoryTypes.County;\r\n if (this.isEnglishStateOrProvince(fieldName))\r\n return CategoryTypes.StateOrProvince;\r\n if (this.isEnglishContinent(fieldName))\r\n return CategoryTypes.Continent;\r\n return undefined;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\ndeclare var DEBUG: boolean;\r\n\r\nif (typeof DEBUG === 'undefined') var DEBUG = true;","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import IStringResourceProvider = jsCommon.IStringResourceProvider;\r\n\r\n export interface ILocalizableError {\r\n getDetails(resourceProvider: IStringResourceProvider): ErrorDetails;\r\n }\r\n\r\n export interface IClientError extends ILocalizableError {\r\n code: string;\r\n debugInfo?: string;\r\n ignorable?: boolean;\r\n requestId?: string;\r\n }\r\n\r\n export interface IClientWarning extends ILocalizableError {\r\n code: string;\r\n columnNameFromIndex: (index: number) => string;\r\n }\r\n\r\n /**\r\n this base class should be derived to give a generic error message but with a unique error code.\r\n */\r\n export abstract class UnknownClientError implements IClientError {\r\n private errorCode: string;\r\n\r\n public get code(): string {\r\n return this.errorCode;\r\n }\r\n public get ignorable(): boolean {\r\n return false;\r\n }\r\n\r\n constructor(code: string) {\r\n debug.assertValue(code, 'code');\r\n\r\n this.errorCode = code;\r\n }\r\n\r\n public getDetails(resourceProvider: IStringResourceProvider): ErrorDetails {\r\n let details: ErrorDetails = {\r\n message: resourceProvider.get('ClientError_UnknownClientErrorValue'),\r\n additionalErrorInfo: [{ errorInfoKey: resourceProvider.get('ClientError_UnknownClientErrorKey'), errorInfoValue: resourceProvider.get('ClientError_UnknownClientErrorValue'), }],\r\n };\r\n\r\n return details;\r\n }\r\n }\r\n\r\n export class HttpClientError implements IClientError {\r\n private httpRequestId: string;\r\n private httpStatusCode: number;\r\n \r\n constructor(httpStatusCode: number, requestId: string) {\r\n debug.assertValue(httpStatusCode, 'httpStatusCode');\r\n debug.assertValue(requestId, 'requestId');\r\n this.httpStatusCode = httpStatusCode;\r\n this.httpRequestId = requestId;\r\n }\r\n\r\n public get code(): string {\r\n return 'HttpClientError';\r\n }\r\n\r\n public get ignorable(): boolean {\r\n return false;\r\n }\r\n\r\n public get requestId(): string {\r\n return this.httpRequestId;\r\n }\r\n\r\n public getDetails(resourceProvider: IStringResourceProvider): ErrorDetails {\r\n // Use a general error message for a HTTP request failure, since we currently do not know of any specifc error cases at this point in time.\r\n let details: ErrorDetails = {\r\n message: null,\r\n additionalErrorInfo: [\r\n { errorInfoKey: resourceProvider.get('DsrError_Key'), errorInfoValue: resourceProvider.get('DsrError_UnknownErrorValue')},\r\n { errorInfoKey: resourceProvider.get('ClientError_HttpResponseStatusCodeKey'), errorInfoValue: this.httpStatusCode.toString() }],\r\n };\r\n\r\n return details;\r\n }\r\n }\r\n\r\n export class IgnorableClientError implements IClientError {\r\n public get code(): string {\r\n return 'IgnorableClientError';\r\n }\r\n public get ignorable(): boolean {\r\n return true;\r\n }\r\n\r\n public getDetails(resourceProvider: IStringResourceProvider): ErrorDetails {\r\n let details: ErrorDetails = {\r\n message: '',\r\n additionalErrorInfo: [],\r\n };\r\n\r\n return details;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n export interface ArrayIdItems<T> extends Array<T> {\r\n withId(id: number): T;\r\n }\r\n\r\n export interface ArrayNamedItems<T> extends Array<T> {\r\n withName(name: string): T;\r\n }\r\n\r\n export module ArrayExtensions {\r\n /**\r\n * Returns items that exist in target and other.\r\n */\r\n export function intersect<T>(target: T[], other: T[]): T[] {\r\n let result: T[] = [];\r\n for (let i = target.length - 1; i >= 0; --i) {\r\n if (other.indexOf(target[i]) !== -1) {\r\n result.push(target[i]);\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Return elements exists in target but not exists in other.\r\n */\r\n export function diff<T>(target: T[], other: T[]): T[] {\r\n let result: T[] = [];\r\n for (let i = target.length - 1; i >= 0; --i) {\r\n let value: T = target[i];\r\n if (other.indexOf(value) === -1) {\r\n result.push(value);\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n /** \r\n * Return an array with only the distinct items in the source. \r\n */\r\n export function distinct<T>(source: T[]): T[] {\r\n let result: T[] = [];\r\n for (let i = 0, len = source.length; i < len; i++) {\r\n let value: T = source[i];\r\n if (result.indexOf(value) === -1) {\r\n result.push(value);\r\n }\r\n }\r\n return result;\r\n }\r\n \r\n /**\r\n * Pushes content of source onto target,\r\n * for parts of course that do not already exist in target.\r\n */\r\n export function union<T>(target: T[], source: T[]): void {\r\n for (let i = 0, len = source.length; i < len; ++i) {\r\n unionSingle(target, source[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Pushes value onto target, if value does not already exist in target.\r\n */\r\n export function unionSingle<T>(target: T[], value: T): void {\r\n if (target.indexOf(value) < 0) {\r\n target.push(value);\r\n }\r\n }\r\n \r\n /**\r\n * Returns an array with a range of items from source,\r\n * including the startIndex & endIndex.\r\n */\r\n export function range<T>(source: T[], startIndex: number, endIndex: number): T[] {\r\n debug.assert(startIndex >= 0 && startIndex < source.length, 'startIndex is out of range.');\r\n debug.assert(endIndex >= 0 && endIndex < source.length, 'endIndex is out of range.');\r\n\r\n let result: T[] = [];\r\n for (let i = startIndex; i <= endIndex; ++i) {\r\n result.push(source[i]);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Returns an array that includes items from source, up to the specified count.\r\n */\r\n export function take<T>(source: T[], count: number): T[] {\r\n debug.assert(count >= 0, 'Count is negative.');\r\n debug.assert(count <= source.length, 'Count is too large.');\r\n\r\n let result: T[] = [];\r\n for (let i = 0; i < count; ++i) {\r\n result.push(source[i]);\r\n }\r\n return result;\r\n }\r\n\r\n export function copy<T>(source: T[]): T[] {\r\n debug.assertValue(source, 'source');\r\n\r\n return take(source, source.length);\r\n }\r\n\r\n /**\r\n * Returns a value indicating whether the arrays have the same values in the same sequence.\r\n */\r\n export function sequenceEqual<T>(left: T[], right: T[], comparison: (x: T, y: T) => boolean): boolean {\r\n debug.assertValue(comparison, 'comparison');\r\n\r\n if (left === right) {\r\n return true;\r\n }\r\n\r\n if (!!left !== !!right) {\r\n return false;\r\n }\r\n\r\n let len = left.length;\r\n if (len !== right.length) {\r\n return false;\r\n }\r\n\r\n let i = 0;\r\n while (i < len && comparison(left[i], right[i])) {\r\n ++i;\r\n }\r\n\r\n return i === len;\r\n }\r\n\r\n /**\r\n * Returns null if the specified array is empty. \r\n * Otherwise returns the specified array.\r\n */\r\n export function emptyToNull<T>(array: T[]): T[] {\r\n if (array && array.length === 0) {\r\n return null;\r\n }\r\n return array;\r\n }\r\n\r\n export function indexOf<T>(array: T[], predicate: (T) => boolean): number {\r\n debug.assertValue(array, 'array');\r\n debug.assertValue(predicate, 'predicate');\r\n\r\n for (let i = 0, len = array.length; i < len; ++i) {\r\n if (predicate(array[i])) {\r\n return i;\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n /**\r\n * Returns a copy of the array rotated by the specified offset.\r\n */\r\n export function rotate<T>(array: T[], offset: number): T[] {\r\n if (offset === 0)\r\n return array.slice();\r\n\r\n let rotated = array.slice(offset);\r\n Array.prototype.push.apply(rotated, array.slice(0, offset));\r\n\r\n return rotated;\r\n }\r\n\r\n export function createWithId<T>(): ArrayIdItems<T> {\r\n return extendWithId<T>([]);\r\n }\r\n\r\n export function extendWithId<T>(array: { id: number }[]): ArrayIdItems<T> {\r\n debug.assertValue(array, 'array');\r\n\r\n let extended: ArrayIdItems<T> = <any>array;\r\n extended.withId = withId;\r\n\r\n return extended;\r\n }\r\n\r\n /**\r\n * Finds and returns the first item with a matching ID.\r\n */\r\n export function findWithId<T>(array: T[], id: number): T {\r\n for (let i = 0, len = array.length; i < len; i++) {\r\n let item = array[i];\r\n if ((<any>item).id === id)\r\n return item;\r\n }\r\n }\r\n\r\n function withId<T>(id: number): T {\r\n return ArrayExtensions.findWithId<T>(this, id);\r\n }\r\n\r\n export function createWithName<T>(): ArrayNamedItems<T> {\r\n return extendWithName<T>([]);\r\n }\r\n\r\n export function extendWithName<T>(array: { name: string }[]): ArrayNamedItems<T> {\r\n debug.assertValue(array, 'array');\r\n\r\n let extended: ArrayNamedItems<T> = <any>array;\r\n extended.withName = withName;\r\n\r\n return extended;\r\n }\r\n\r\n export function findItemWithName<T>(array: T[], name: string): T {\r\n let index = indexWithName(array, name);\r\n if (index >= 0)\r\n return array[index];\r\n }\r\n\r\n export function indexWithName<T>(array: T[], name: string): number {\r\n for (let i = 0, len = array.length; i < len; i++) {\r\n let item = array[i];\r\n if ((<any>item).name === name)\r\n return i;\r\n }\r\n\r\n return -1;\r\n }\r\n\r\n /**\r\n * Inserts a number in sorted order into a list of numbers already in sorted order.\r\n * @returns True if the item was added, false if it already existed.\r\n */\r\n export function insertSorted(list: number[], value: number): boolean {\r\n debug.assertValue(list, 'list');\r\n debug.assertValue(value, 'value');\r\n\r\n let len = list.length;\r\n\r\n // NOTE: iterate backwards because incoming values tend to be sorted already.\r\n for (let i = len - 1; i >= 0; i--) {\r\n let diff = list[i] - value;\r\n\r\n if (diff === 0)\r\n return false;\r\n\r\n if (diff > 0)\r\n continue;\r\n\r\n // diff < 0\r\n list.splice(i + 1, 0, value);\r\n return true;\r\n }\r\n\r\n list.unshift(value);\r\n return true;\r\n }\r\n\r\n /**\r\n * Removes the first occurrence of a value from a list if it exists.\r\n * @returns True if the value was removed, false if it did not exist in the list.\r\n */\r\n export function removeFirst<T>(list: T[], value: T): boolean {\r\n let index = list.indexOf(value);\r\n if (index < 0)\r\n return false;\r\n\r\n list.splice(index, 1);\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Finds and returns the first item with a matching name.\r\n */\r\n function withName<T>(name: string): T {\r\n let array: T[] = this;\r\n return findItemWithName(array, name);\r\n }\r\n\r\n /**\r\n * Deletes all items from the array.\r\n */\r\n export function clear(array: any[]): void {\r\n if (!array)\r\n return;\r\n\r\n while (array.length > 0)\r\n array.pop();\r\n }\r\n\r\n export function isUndefinedOrEmpty(array: any[]): boolean {\r\n if (!array || array.length === 0) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n export function swap<T>(array: T[], firstIndex: number, secondIndex: number): void {\r\n let temp = array[firstIndex];\r\n array[firstIndex] = array[secondIndex];\r\n array[secondIndex] = temp;\r\n }\r\n\r\n export function isInArray<T>(array: T[], lookupItem: T, compareCallback: (item1: T, item2: T) => boolean): boolean {\r\n return _.any(array, item => compareCallback(item, lookupItem));\r\n }\r\n\r\n /** Checks if the given object is an Array, and looking all the way up the prototype chain. */\r\n export function isArrayOrInheritedArray(obj: {}): obj is Array<any> {\r\n debug.assertValue(obj, 'obj');\r\n\r\n let nextPrototype = obj;\r\n while (nextPrototype != null) {\r\n if (_.isArray(nextPrototype))\r\n return true;\r\n\r\n nextPrototype = Object.getPrototypeOf(nextPrototype);\r\n }\r\n\r\n return false;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule InJs {\r\n export module DomFactory {\r\n\r\n export function div(): JQuery {\r\n return $('<div/>');\r\n }\r\n\r\n export function span(): JQuery {\r\n return $('<span/>');\r\n }\r\n\r\n export function checkbox(): JQuery {\r\n return $('<input type=\"checkbox\"/>');\r\n }\r\n\r\n export function ul(): JQuery {\r\n return $('<ul/>');\r\n }\r\n\r\n export function li(): JQuery {\r\n return $('<li/>');\r\n }\r\n\r\n export function button(): JQuery {\r\n return $('<input type=\"button\"/>');\r\n }\r\n\r\n export function select(): JQuery {\r\n return $('<select/>');\r\n }\r\n\r\n export function textBox(): JQuery {\r\n return $('<input type=\"text\"/>');\r\n }\r\n\r\n export function img(): JQuery {\r\n return $('<img/>');\r\n }\r\n\r\n export function iframe(): JQuery {\r\n return $('<iframe/>');\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n /**\r\n * Module Double contains a set of constants and precision based utility methods \r\n * for dealing with doubles and their decimal garbage in the javascript.\r\n */\r\n export module Double {\r\n\r\n // Constants.\r\n export const MIN_VALUE = -Number.MAX_VALUE;\r\n export const MAX_VALUE = Number.MAX_VALUE;\r\n export const MIN_EXP = -308;\r\n export const MAX_EXP = 308;\r\n export const EPSILON = 1E-323;\r\n export const DEFAULT_PRECISION = 0.0001;\r\n export const DEFAULT_PRECISION_IN_DECIMAL_DIGITS = 12;\r\n export const LOG_E_10 = Math.log(10);\r\n export const POSITIVE_POWERS = [\r\n 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15, 1E16, 1E17, 1E18, 1E19, 1E20, 1E21, 1E22, 1E23, 1E24, 1E25, 1E26, 1E27, 1E28, 1E29, 1E30, 1E31, 1E32, 1E33, 1E34, 1E35, 1E36, 1E37, 1E38, 1E39, 1E40, 1E41, 1E42, 1E43, 1E44, 1E45, 1E46, 1E47, 1E48, 1E49, 1E50, 1E51, 1E52, 1E53, 1E54, 1E55, 1E56, 1E57, 1E58, 1E59, 1E60, 1E61, 1E62, 1E63, 1E64, 1E65, 1E66, 1E67, 1E68, 1E69, 1E70, 1E71, 1E72, 1E73, 1E74, 1E75, 1E76, 1E77, 1E78, 1E79, 1E80, 1E81, 1E82, 1E83, 1E84, 1E85, 1E86, 1E87, 1E88, 1E89, 1E90, 1E91, 1E92, 1E93, 1E94, 1E95, 1E96, 1E97, 1E98, 1E99,\r\n 1E100, 1E101, 1E102, 1E103, 1E104, 1E105, 1E106, 1E107, 1E108, 1E109, 1E110, 1E111, 1E112, 1E113, 1E114, 1E115, 1E116, 1E117, 1E118, 1E119, 1E120, 1E121, 1E122, 1E123, 1E124, 1E125, 1E126, 1E127, 1E128, 1E129, 1E130, 1E131, 1E132, 1E133, 1E134, 1E135, 1E136, 1E137, 1E138, 1E139, 1E140, 1E141, 1E142, 1E143, 1E144, 1E145, 1E146, 1E147, 1E148, 1E149, 1E150, 1E151, 1E152, 1E153, 1E154, 1E155, 1E156, 1E157, 1E158, 1E159, 1E160, 1E161, 1E162, 1E163, 1E164, 1E165, 1E166, 1E167, 1E168, 1E169, 1E170, 1E171, 1E172, 1E173, 1E174, 1E175, 1E176, 1E177, 1E178, 1E179, 1E180, 1E181, 1E182, 1E183, 1E184, 1E185, 1E186, 1E187, 1E188, 1E189, 1E190, 1E191, 1E192, 1E193, 1E194, 1E195, 1E196, 1E197, 1E198, 1E199,\r\n 1E200, 1E201, 1E202, 1E203, 1E204, 1E205, 1E206, 1E207, 1E208, 1E209, 1E210, 1E211, 1E212, 1E213, 1E214, 1E215, 1E216, 1E217, 1E218, 1E219, 1E220, 1E221, 1E222, 1E223, 1E224, 1E225, 1E226, 1E227, 1E228, 1E229, 1E230, 1E231, 1E232, 1E233, 1E234, 1E235, 1E236, 1E237, 1E238, 1E239, 1E240, 1E241, 1E242, 1E243, 1E244, 1E245, 1E246, 1E247, 1E248, 1E249, 1E250, 1E251, 1E252, 1E253, 1E254, 1E255, 1E256, 1E257, 1E258, 1E259, 1E260, 1E261, 1E262, 1E263, 1E264, 1E265, 1E266, 1E267, 1E268, 1E269, 1E270, 1E271, 1E272, 1E273, 1E274, 1E275, 1E276, 1E277, 1E278, 1E279, 1E280, 1E281, 1E282, 1E283, 1E284, 1E285, 1E286, 1E287, 1E288, 1E289, 1E290, 1E291, 1E292, 1E293, 1E294, 1E295, 1E296, 1E297, 1E298, 1E299,\r\n 1E300, 1E301, 1E302, 1E303, 1E304, 1E305, 1E306, 1E307, 1E308];\r\n export const NEGATIVE_POWERS = [\r\n 1E0, 1E-1, 1E-2, 1E-3, 1E-4, 1E-5, 1E-6, 1E-7, 1E-8, 1E-9, 1E-10, 1E-11, 1E-12, 1E-13, 1E-14, 1E-15, 1E-16, 1E-17, 1E-18, 1E-19, 1E-20, 1E-21, 1E-22, 1E-23, 1E-24, 1E-25, 1E-26, 1E-27, 1E-28, 1E-29, 1E-30, 1E-31, 1E-32, 1E-33, 1E-34, 1E-35, 1E-36, 1E-37, 1E-38, 1E-39, 1E-40, 1E-41, 1E-42, 1E-43, 1E-44, 1E-45, 1E-46, 1E-47, 1E-48, 1E-49, 1E-50, 1E-51, 1E-52, 1E-53, 1E-54, 1E-55, 1E-56, 1E-57, 1E-58, 1E-59, 1E-60, 1E-61, 1E-62, 1E-63, 1E-64, 1E-65, 1E-66, 1E-67, 1E-68, 1E-69, 1E-70, 1E-71, 1E-72, 1E-73, 1E-74, 1E-75, 1E-76, 1E-77, 1E-78, 1E-79, 1E-80, 1E-81, 1E-82, 1E-83, 1E-84, 1E-85, 1E-86, 1E-87, 1E-88, 1E-89, 1E-90, 1E-91, 1E-92, 1E-93, 1E-94, 1E-95, 1E-96, 1E-97, 1E-98, 1E-99,\r\n 1E-100, 1E-101, 1E-102, 1E-103, 1E-104, 1E-105, 1E-106, 1E-107, 1E-108, 1E-109, 1E-110, 1E-111, 1E-112, 1E-113, 1E-114, 1E-115, 1E-116, 1E-117, 1E-118, 1E-119, 1E-120, 1E-121, 1E-122, 1E-123, 1E-124, 1E-125, 1E-126, 1E-127, 1E-128, 1E-129, 1E-130, 1E-131, 1E-132, 1E-133, 1E-134, 1E-135, 1E-136, 1E-137, 1E-138, 1E-139, 1E-140, 1E-141, 1E-142, 1E-143, 1E-144, 1E-145, 1E-146, 1E-147, 1E-148, 1E-149, 1E-150, 1E-151, 1E-152, 1E-153, 1E-154, 1E-155, 1E-156, 1E-157, 1E-158, 1E-159, 1E-160, 1E-161, 1E-162, 1E-163, 1E-164, 1E-165, 1E-166, 1E-167, 1E-168, 1E-169, 1E-170, 1E-171, 1E-172, 1E-173, 1E-174, 1E-175, 1E-176, 1E-177, 1E-178, 1E-179, 1E-180, 1E-181, 1E-182, 1E-183, 1E-184, 1E-185, 1E-186, 1E-187, 1E-188, 1E-189, 1E-190, 1E-191, 1E-192, 1E-193, 1E-194, 1E-195, 1E-196, 1E-197, 1E-198, 1E-199,\r\n 1E-200, 1E-201, 1E-202, 1E-203, 1E-204, 1E-205, 1E-206, 1E-207, 1E-208, 1E-209, 1E-210, 1E-211, 1E-212, 1E-213, 1E-214, 1E-215, 1E-216, 1E-217, 1E-218, 1E-219, 1E-220, 1E-221, 1E-222, 1E-223, 1E-224, 1E-225, 1E-226, 1E-227, 1E-228, 1E-229, 1E-230, 1E-231, 1E-232, 1E-233, 1E-234, 1E-235, 1E-236, 1E-237, 1E-238, 1E-239, 1E-240, 1E-241, 1E-242, 1E-243, 1E-244, 1E-245, 1E-246, 1E-247, 1E-248, 1E-249, 1E-250, 1E-251, 1E-252, 1E-253, 1E-254, 1E-255, 1E-256, 1E-257, 1E-258, 1E-259, 1E-260, 1E-261, 1E-262, 1E-263, 1E-264, 1E-265, 1E-266, 1E-267, 1E-268, 1E-269, 1E-270, 1E-271, 1E-272, 1E-273, 1E-274, 1E-275, 1E-276, 1E-277, 1E-278, 1E-279, 1E-280, 1E-281, 1E-282, 1E-283, 1E-284, 1E-285, 1E-286, 1E-287, 1E-288, 1E-289, 1E-290, 1E-291, 1E-292, 1E-293, 1E-294, 1E-295, 1E-296, 1E-297, 1E-298, 1E-299,\r\n 1E-300, 1E-301, 1E-302, 1E-303, 1E-304, 1E-305, 1E-306, 1E-307, 1E-308, 1E-309, 1E-310, 1E-311, 1E-312, 1E-313, 1E-314, 1E-315, 1E-316, 1E-317, 1E-318, 1E-319, 1E-320, 1E-321, 1E-322, 1E-323, 1E-324];\r\n\r\n /**\r\n * Returns powers of 10. \r\n * Unlike the Math.pow this function produces no decimal garbage.\r\n * @param exp Exponent.\r\n */\r\n export function pow10(exp: number): number {\r\n debug.assertValue(exp, \"exp\");\r\n\r\n // Positive & zero\r\n if (exp >= 0) {\r\n if (exp < Double.POSITIVE_POWERS.length) {\r\n return Double.POSITIVE_POWERS[exp];\r\n } else {\r\n return Infinity;\r\n }\r\n }\r\n // Negative\r\n exp = -exp;\r\n if (exp > 0 && exp < Double.NEGATIVE_POWERS.length) { // if exp==int.MIN_VALUE then changing the sign will overflow and keep the number negative - we need to check for exp > 0 to filter out this corner case\r\n return Double.NEGATIVE_POWERS[exp];\r\n } else {\r\n return 0;\r\n }\r\n }\r\n\r\n /** \r\n * Returns the 10 base logarithm of the number.\r\n * Unlike Math.log function this produces integer results with no decimal garbage.\r\n * @param val Positive value or zero.\r\n */\r\n export function log10(val: number): number {\r\n debug.assert(val >= 0, \"val\");\r\n\r\n // Fast Log10() algorithm \r\n if (val > 1 && val < 1E16) {\r\n if (val < 1E8) {\r\n if (val < 1E4) {\r\n if (val < 1E2) {\r\n if (val < 1E1) {\r\n return 0;\r\n } else {\r\n return 1;\r\n }\r\n } else {\r\n if (val < 1E3) {\r\n return 2;\r\n } else {\r\n return 3;\r\n }\r\n }\r\n } else {\r\n if (val < 1E6) {\r\n if (val < 1E5) {\r\n return 4;\r\n } else {\r\n return 5;\r\n }\r\n } else {\r\n if (val < 1E7) {\r\n return 6;\r\n } else {\r\n return 7;\r\n }\r\n }\r\n }\r\n } else {\r\n if (val < 1E12) {\r\n if (val < 1E10) {\r\n if (val < 1E9) {\r\n return 8;\r\n } else {\r\n return 9;\r\n }\r\n } else {\r\n if (val < 1E11) {\r\n return 10;\r\n } else {\r\n return 11;\r\n }\r\n }\r\n } else {\r\n if (val < 1E14) {\r\n if (val < 1E13) {\r\n return 12;\r\n } else {\r\n return 13;\r\n }\r\n } else {\r\n if (val < 1E15) {\r\n return 14;\r\n } else {\r\n return 15;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (val > 1E-16 && val < 1) {\r\n if (val < 1E-8) {\r\n if (val < 1E-12) {\r\n if (val < 1E-14) {\r\n if (val < 1E-15) {\r\n return -16;\r\n } else {\r\n return -15;\r\n }\r\n } else {\r\n if (val < 1E-13) {\r\n return -14;\r\n } else {\r\n return -13;\r\n }\r\n }\r\n } else {\r\n if (val < 1E-10) {\r\n if (val < 1E-11) {\r\n return -12;\r\n } else {\r\n return -11;\r\n }\r\n } else {\r\n if (val < 1E-9) {\r\n return -10;\r\n } else {\r\n return -9;\r\n }\r\n }\r\n }\r\n } else {\r\n if (val < 1E-4) {\r\n if (val < 1E-6) {\r\n if (val < 1E-7) {\r\n return -8;\r\n } else {\r\n return -7;\r\n }\r\n } else {\r\n if (val < 1E-5) {\r\n return -6;\r\n } else {\r\n return -5;\r\n }\r\n }\r\n } else {\r\n if (val < 1E-2) {\r\n if (val < 1E-3) {\r\n return -4;\r\n } else {\r\n return -3;\r\n }\r\n } else {\r\n if (val < 1E-1) {\r\n return -2;\r\n } else {\r\n return -1;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n // JS Math provides only natural log function so we need to calc the 10 base logarithm:\r\n // logb(x) = logk(x)/logk(b); \r\n let log10 = Math.log(val) / Double.LOG_E_10;\r\n return Double.floorWithPrecision(log10);\r\n }\r\n\r\n /**\r\n * Returns a power of 10 representing precision of the number based on the number of meaningful decimal digits. \r\n * For example the precision of 56,263.3767 with the 6 meaningful decimal digit is 0.1.\r\n * @param x Value.\r\n * @param decimalDigits How many decimal digits are meaningfull.\r\n */\r\n export function getPrecision(x: number, decimalDigits?: number): number {\r\n if (decimalDigits === undefined) {\r\n decimalDigits = Double.DEFAULT_PRECISION_IN_DECIMAL_DIGITS;\r\n } else {\r\n debug.assert(decimalDigits >= 0, \"decimalDigits\");\r\n }\r\n if (!x) {\r\n return undefined;\r\n }\r\n\r\n let exp = Double.log10(Math.abs(x));\r\n\r\n if (exp < Double.MIN_EXP) {\r\n return 0;\r\n }\r\n let precisionExp = Math.max(exp - decimalDigits, -Double.NEGATIVE_POWERS.length + 1);\r\n return Double.pow10(precisionExp);\r\n }\r\n\r\n /** \r\n * Checks if a delta between 2 numbers is less than provided precision.\r\n * @param x One value.\r\n * @param y Another value.\r\n * @param precision Precision value.\r\n */\r\n export function equalWithPrecision(x: number, y: number, precision?: number): boolean {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n\r\n return x === y || Math.abs(x - y) < precision;\r\n }\r\n\r\n /** \r\n * Checks if a first value is less than another taking \r\n * into account the loose precision based equality.\r\n * @param x One value.\r\n * @param y Another value.\r\n * @param precision Precision value.\r\n */\r\n export function lessWithPrecision(x: number, y: number, precision?: number): boolean {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n\r\n return x < y && Math.abs(x - y) > precision;\r\n }\r\n\r\n /** \r\n * Checks if a first value is less or equal than another taking \r\n * into account the loose precision based equality.\r\n * @param x One value.\r\n * @param y Another value.\r\n * @param precision Precision value.\r\n */\r\n export function lessOrEqualWithPrecision(x: number, y: number, precision?: number): boolean {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n\r\n return x < y || Math.abs(x - y) < precision;\r\n }\r\n\r\n /** \r\n * Checks if a first value is greater than another taking \r\n * into account the loose precision based equality.\r\n * @param x One value.\r\n * @param y Another value.\r\n * @param precision Precision value.\r\n */\r\n export function greaterWithPrecision(x: number, y: number, precision?: number): boolean {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n\r\n return x > y && Math.abs(x - y) > precision;\r\n }\r\n\r\n /** \r\n * Checks if a first value is greater or equal to another taking \r\n * into account the loose precision based equality.\r\n * @param x One value.\r\n * @param y Another value.\r\n * @param precision Precision value.\r\n */\r\n export function greaterOrEqualWithPrecision(x: number, y: number, precision?: number): boolean {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n\r\n return x > y || Math.abs(x - y) < precision;\r\n }\r\n\r\n /** \r\n * Floors the number unless it's withing the precision distance from the higher int.\r\n * @param x One value.\r\n * @param precision Precision value.\r\n */\r\n export function floorWithPrecision(x: number, precision?: number): number {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n\r\n let roundX = Math.round(x);\r\n if (Math.abs(x - roundX) < precision) {\r\n return roundX;\r\n } else {\r\n return Math.floor(x);\r\n }\r\n }\r\n\r\n /** \r\n * Ceils the number unless it's withing the precision distance from the lower int.\r\n * @param x One value.\r\n * @param precision Precision value.\r\n */\r\n export function ceilWithPrecision(x: number, precision?: number): number {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n\r\n let roundX = Math.round(x);\r\n if (Math.abs(x - roundX) < precision) {\r\n return roundX;\r\n } else {\r\n return Math.ceil(x);\r\n }\r\n }\r\n\r\n /** \r\n * Floors the number to the provided precision.\r\n * For example 234,578 floored to 1,000 precision is 234,000.\r\n * @param x One value.\r\n * @param precision Precision value.\r\n */\r\n export function floorToPrecision(x: number, precision?: number): number {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n if (precision === 0 || x === 0) {\r\n return x;\r\n }\r\n //Precision must be a Power of 10\r\n return Math.floor(x / precision) * precision;\r\n }\r\n\r\n /** \r\n * Ceils the number to the provided precision.\r\n * For example 234,578 floored to 1,000 precision is 235,000.\r\n * @param x One value.\r\n * @param precision Precision value.\r\n */\r\n export function ceilToPrecision(x: number, precision?: number): number {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n if (precision === 0 || x === 0) {\r\n return x;\r\n }\r\n //Precision must be a Power of 10\r\n return Math.ceil(x / precision) * precision;\r\n }\r\n\r\n /** \r\n * Rounds the number to the provided precision. \r\n * For example 234,578 floored to 1,000 precision is 235,000.\r\n * @param x One value.\r\n * @param precision Precision value.\r\n */\r\n export function roundToPrecision(x: number, precision?: number): number {\r\n precision = applyDefault(precision, Double.DEFAULT_PRECISION);\r\n debug.assert(precision >= 0, \"precision\");\r\n if (precision === 0 || x === 0) {\r\n return x;\r\n } \r\n //Precision must be a Power of 10\r\n let result = Math.round(x / precision) * precision;\r\n let decimalDigits = Math.round(Double.log10(Math.abs(x)) - Double.log10(precision)) + 1;\r\n if (decimalDigits > 0 && decimalDigits < 16) {\r\n result = parseFloat(result.toPrecision(decimalDigits));\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /** \r\n * Returns the value making sure that it's restricted to the provided range.\r\n * @param x One value.\r\n * @param min Range min boundary.\r\n * @param max Range max boundary.\r\n */\r\n export function ensureInRange(x: number, min: number, max: number): number {\r\n debug.assert(min <= max, \"min must be less or equal to max\");\r\n if (x === undefined || x === null) {\r\n return x;\r\n }\r\n if (x < min) {\r\n return min;\r\n }\r\n if (x > max) {\r\n return max;\r\n }\r\n return x;\r\n }\r\n\r\n /** \r\n * Rounds the value - this method is actually faster than Math.round - used in the graphics utils.\r\n * @param x Value to round.\r\n */\r\n export function round(x: number): number {\r\n debug.assert(x >= 0, \"x must be greater or equal to 0\");\r\n\r\n return (0.5 + x) << 0;\r\n }\r\n\r\n /** \r\n * Projects the value from the source range into the target range.\r\n * @param value Value to project.\r\n * @param fromMin Minimum of the source range.\r\n * @param toMin Minimum of the target range.\r\n * @param toMax Maximum of the target range.\r\n */\r\n export function project(value: number, fromMin: number, fromSize: number, toMin: number, toSize: number): number {\r\n if (fromSize === 0 || toSize === 0) {\r\n if (fromMin <= value && value <= fromMin + fromSize) {\r\n return toMin;\r\n } else {\r\n return NaN;\r\n }\r\n }\r\n let relativeX = (value - fromMin) / fromSize;\r\n let projectedX = toMin + relativeX * toSize;\r\n return projectedX;\r\n }\r\n\r\n /** \r\n * Removes decimal noise.\r\n * @param value Value to be processed.\r\n */\r\n export function removeDecimalNoise(value: number): number {\r\n return roundToPrecision(value, getPrecision(value));\r\n }\r\n\r\n /** \r\n * Checks whether the number is integer.\r\n * @param value Value to be checked.\r\n */\r\n export function isInteger(value: number): boolean {\r\n return value !== null && value % 1 === 0;\r\n }\r\n\r\n /**\r\n * Dividing by increment will give us count of increments\r\n * Round out the rough edges into even integer\r\n * Multiply back by increment to get rounded value\r\n * e.g. Rounder.toIncrement(0.647291, 0.05) => 0.65\r\n * @param value - value to round to nearest increment\r\n * @param increment - smallest increment to round toward\r\n */\r\n export function toIncrement(value: number, increment: number): number {\r\n return Math.round(value / increment) * increment;\r\n }\r\n }\r\n\r\n function applyDefault(value: number, defaultValue: number): number {\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n import Double = powerbi.Double;\r\n\r\n export module Color {\r\n export function rotate(rgbString: string, rotateFactor: number): string {\r\n if (rotateFactor === 0)\r\n return rgbString;\r\n\r\n let originalRgb = parseColorString(rgbString);\r\n let originalHsv = rgbToHsv(originalRgb);\r\n let rotatedHsv = rotateHsv(originalHsv, rotateFactor);\r\n let rotatedRgb = hsvToRgb(rotatedHsv);\r\n return hexString(rotatedRgb);\r\n }\r\n\r\n export function normalizeToHexString(color: string): string {\r\n let rgb = parseColorString(color);\r\n return hexString(rgb);\r\n }\r\n\r\n export function parseColorString(color: string): RgbColor {\r\n debug.assertValue(color, 'color');\r\n\r\n if (color.indexOf('#') >= 0) {\r\n if (color.length === 7) {\r\n // #RRGGBB\r\n let result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(color);\r\n if (result == null || result.length < 4)\r\n return;\r\n\r\n return {\r\n R: parseInt(result[1], 16),\r\n G: parseInt(result[2], 16),\r\n B: parseInt(result[3], 16),\r\n };\r\n } else if (color.length === 4) {\r\n // #RGB\r\n let result = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i.exec(color);\r\n if (result == null || result.length < 4)\r\n return;\r\n\r\n return {\r\n R: parseInt(result[1] + result[1], 16),\r\n G: parseInt(result[2] + result[2], 16),\r\n B: parseInt(result[3] + result[3], 16),\r\n };\r\n }\r\n }\r\n else if (color.indexOf('rgb(') >= 0) {\r\n // rgb(R, G, B)\r\n let result = /^rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)$/.exec(color);\r\n if (result == null || result.length < 4)\r\n return;\r\n\r\n return {\r\n R: parseInt(result[1], 10),\r\n G: parseInt(result[2], 10),\r\n B: parseInt(result[3], 10),\r\n };\r\n }\r\n else if (color.indexOf('rgba(') >= 0) {\r\n // rgba(R, G, B, A)\r\n let result = /^rgba\\((\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d*(?:\\.\\d+)?)\\)$/.exec(color);\r\n if (result == null || result.length < 5)\r\n return;\r\n\r\n return {\r\n R: parseInt(result[1], 10),\r\n G: parseInt(result[2], 10),\r\n B: parseInt(result[3], 10),\r\n A: parseFloat(result[4]),\r\n };\r\n }\r\n }\r\n\r\n function rgbToHsv(rgbColor: RgbColor): HsvColor {\r\n let s, h;\r\n let r = rgbColor.R / 255,\r\n g = rgbColor.G / 255,\r\n b = rgbColor.B / 255;\r\n\r\n let min = Math.min(r, Math.min(g, b));\r\n let max = Math.max(r, Math.max(g, b));\r\n\r\n let v = max;\r\n let delta = max - min;\r\n if (max === 0 || delta === 0) {\r\n // R, G, and B must be 0.0, or all the same.\r\n // In this case, S is 0.0, and H is undefined.\r\n // Using H = 0.0 is as good as any...\r\n s = 0;\r\n h = 0;\r\n }\r\n else {\r\n s = delta / max;\r\n if (r === max) {\r\n // Between Yellow and Magenta\r\n h = (g - b) / delta;\r\n }\r\n else if (g === max) {\r\n // Between Cyan and Yellow\r\n h = 2 + (b - r) / delta;\r\n }\r\n else {\r\n // Between Magenta and Cyan\r\n h = 4 + (r - g) / delta;\r\n }\r\n }\r\n\r\n // Scale h to be between 0.0 and 1.\r\n // This may require adding 1, if the value\r\n // is negative.\r\n h /= 6;\r\n if (h < 0) {\r\n h += 1;\r\n }\r\n\r\n return {\r\n H: h,\r\n S: s,\r\n V: v,\r\n };\r\n }\r\n\r\n function hsvToRgb(hsvColor: HsvColor): RgbColor {\r\n let r, g, b;\r\n let h = hsvColor.H,\r\n s = hsvColor.S,\r\n v = hsvColor.V;\r\n\r\n if (s === 0) {\r\n // If s is 0, all colors are the same.\r\n // This is some flavor of gray.\r\n r = v;\r\n g = v;\r\n b = v;\r\n }\r\n else {\r\n let p, q, t, fractionalSector, sectorNumber, sectorPos;\r\n\r\n // The color wheel consists of 6 sectors.\r\n // Figure out which sector you//re in.\r\n sectorPos = h * 6;\r\n sectorNumber = Math.floor(sectorPos);\r\n\r\n // get the fractional part of the sector.\r\n // That is, how many degrees into the sector\r\n // are you?\r\n fractionalSector = sectorPos - sectorNumber;\r\n\r\n // Calculate values for the three axes\r\n // of the color.\r\n p = v * (1.0 - s);\r\n q = v * (1.0 - (s * fractionalSector));\r\n t = v * (1.0 - (s * (1 - fractionalSector)));\r\n\r\n // Assign the fractional colors to r, g, and b\r\n // based on the sector the angle is in.\r\n switch (sectorNumber) {\r\n case 0:\r\n r = v;\r\n g = t;\r\n b = p;\r\n break;\r\n\r\n case 1:\r\n r = q;\r\n g = v;\r\n b = p;\r\n break;\r\n\r\n case 2:\r\n r = p;\r\n g = v;\r\n b = t;\r\n break;\r\n\r\n case 3:\r\n r = p;\r\n g = q;\r\n b = v;\r\n break;\r\n\r\n case 4:\r\n r = t;\r\n g = p;\r\n b = v;\r\n break;\r\n\r\n case 5:\r\n r = v;\r\n g = p;\r\n b = q;\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n R: Math.floor(r * 255),\r\n G: Math.floor(g * 255),\r\n B: Math.floor(b * 255),\r\n };\r\n }\r\n\r\n function rotateHsv(hsvColor: HsvColor, rotateFactor: number): HsvColor {\r\n let newH = hsvColor.H + rotateFactor;\r\n\r\n return {\r\n H: newH > 1 ? newH - 1 : newH,\r\n S: hsvColor.S,\r\n V: hsvColor.V,\r\n };\r\n }\r\n\r\n export function darken(color: RgbColor, diff: number): RgbColor {\r\n let flooredNumber = Math.floor(diff);\r\n return {\r\n R: Math.max(0, color.R - flooredNumber),\r\n G: Math.max(0, color.G - flooredNumber),\r\n B: Math.max(0, color.B - flooredNumber),\r\n };\r\n }\r\n\r\n export function rgbString(color: RgbColor): string {\r\n if (color.A == null)\r\n return \"rgb(\" + color.R + \",\" + color.G + \",\" + color.B + \")\";\r\n return \"rgba(\" + color.R + \",\" + color.G + \",\" + color.B + \",\" + color.A + \")\";\r\n }\r\n\r\n export function hexString(color: RgbColor): string {\r\n return \"#\" + componentToHex(color.R) + componentToHex(color.G) + componentToHex(color.B);\r\n }\r\n\r\n function componentToHex(hexComponent: number): string {\r\n let clamped = Double.ensureInRange(hexComponent, 0, 255);\r\n let hex = clamped.toString(16).toUpperCase();\r\n return hex.length === 1 ? \"0\" + hex : hex;\r\n }\r\n\r\n export interface RgbColor {\r\n R: number;\r\n G: number;\r\n B: number;\r\n A?: number;\r\n }\r\n\r\n interface HsvColor {\r\n H: number;\r\n S: number;\r\n V: number;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n /**\r\n * CSS constants.\r\n */\r\n export module CssConstants {\r\n export interface ClassAndSelector {\r\n class: string;\r\n selector: string;\r\n }\r\n\r\n export function createClassAndSelector(className: string): ClassAndSelector {\r\n return {\r\n class: className,\r\n selector: '.' + className,\r\n };\r\n }\r\n\r\n export const styleAttribute = 'style';\r\n export const pixelUnits = 'px';\r\n\r\n export const heightProperty = 'height';\r\n export const widthProperty = 'width';\r\n export const topProperty = 'top';\r\n export const bottomProperty = 'bottom';\r\n export const leftProperty = 'left';\r\n export const rightProperty = 'right';\r\n export const marginTopProperty = 'margin-top';\r\n export const marginLeftProperty = 'margin-left';\r\n export const displayProperty = 'display';\r\n export const backgroundProperty = 'background';\r\n export const backgroundColorProperty = 'background-color';\r\n export const backgroundRepeatProperty = 'background-repeat';\r\n export const backgroundSizeProperty = 'background-size';\r\n export const backgroundImageProperty = 'background-image';\r\n export const textShadowProperty = 'text-shadow';\r\n export const textAlignProperty = 'text-align';\r\n export const borderTopWidthProperty = 'border-top-width';\r\n export const borderBottomWidthProperty = 'border-bottom-width';\r\n export const borderLeftWidthProperty = 'border-left-width';\r\n export const borderRightWidthProperty = 'border-right-width';\r\n export const fontSizeProperty = 'font-size';\r\n export const fontWeightProperty = 'font-weight';\r\n export const colorProperty = 'color';\r\n export const opacityProperty = 'opacity';\r\n export const paddingLeftProperty = 'padding-left';\r\n export const paddingRightProperty = 'padding-right';\r\n export const positionProperty = 'position';\r\n export const maxWidthProperty = 'max-width';\r\n export const minWidthProperty = 'min-width';\r\n export const overflowProperty = 'overflow';\r\n export const overflowXProperty = 'overflow-x';\r\n export const overflowYProperty = 'overflow-y';\r\n export const transformProperty = 'transform';\r\n export const webkitTransformProperty = '-webkit-transform';\r\n export const cursorProperty = 'cursor';\r\n export const visibilityProperty = 'visibility';\r\n\r\n export const absoluteValue = 'absolute';\r\n export const zeroPixelValue = '0px';\r\n export const autoValue = 'auto';\r\n export const hiddenValue = 'hidden';\r\n export const noneValue = 'none';\r\n export const blockValue = 'block';\r\n export const inlineBlockValue = 'inline-block';\r\n export const transparentValue = 'transparent';\r\n export const boldValue = 'bold';\r\n export const visibleValue = 'visible';\r\n export const tableRowValue = 'table-row';\r\n export const coverValue = 'cover';\r\n export const pointerValue = 'pointer';\r\n export const scrollValue = 'scroll';\r\n }\r\n\r\n export interface ExtendedCSSProperties extends CSSStyleDeclaration {\r\n scrollbarShadowColor: string;\r\n scrollbarHighlightColor: string;\r\n layoutGridChar: string;\r\n layoutGridType: string;\r\n textAutospace: string;\r\n textKashidaSpace: string;\r\n writingMode: string;\r\n scrollbarFaceColor: string;\r\n backgroundPositionY: string;\r\n lineBreak: string;\r\n imeMode: string;\r\n msBlockProgression: string;\r\n layoutGridLine: string;\r\n scrollbarBaseColor: string;\r\n layoutGrid: string;\r\n layoutFlow: string;\r\n textKashida: string;\r\n filter: string;\r\n zoom: string;\r\n scrollbarArrowColor: string;\r\n behavior: string;\r\n backgroundPositionX: string;\r\n accelerator: string;\r\n layoutGridMode: string;\r\n textJustifyTrim: string;\r\n scrollbar3dLightColor: string;\r\n msInterpolationMode: string;\r\n scrollbarTrackColor: string;\r\n scrollbarDarkShadowColor: string;\r\n styleFloat: string;\r\n getAttribute(attributeName: string, flags?: number): any;\r\n setAttribute(attributeName: string, AttributeValue: any, flags?: number): void;\r\n removeAttribute(attributeName: string, flags?: number): boolean;\r\n\r\n pixelWidth: number;\r\n posHeight: number;\r\n posLeft: number;\r\n pixelTop: number;\r\n pixelBottom: number;\r\n textDecorationNone: boolean;\r\n pixelLeft: number;\r\n posTop: number;\r\n posBottom: number;\r\n textDecorationOverline: boolean;\r\n posWidth: number;\r\n textDecorationLineThrough: boolean;\r\n pixelHeight: number;\r\n textDecorationBlink: boolean;\r\n posRight: number;\r\n pixelRight: number;\r\n textDecorationUnderline: boolean;\r\n\r\n webkitTransform: string;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\n/**\r\n * Defines a Debug object. Calls to any functions in this object removed by the minifier.\r\n * The functions within this class are not minified away, so we use the preprocessor-style\r\n * comments to have the minifier remove those as well.\r\n */\r\n \r\n///#DEBUG\r\n\r\nmodule debug {\r\n\r\n export let assertFailFunction: {\r\n (message: string): void;\r\n };\r\n\r\n /** \r\n * Asserts that the condition is true, fails otherwise.\r\n */\r\n export function assert(condition: boolean, message: string): void {\r\n if (condition !== true) {\r\n assertFail(message || ('condition: ' + condition));\r\n }\r\n }\r\n\r\n /**\r\n * Asserts that the value is neither null nor undefined, fails otherwise. \r\n */\r\n export function assertValue<T>(value: T, message: string): void {\r\n if (value === null || value === undefined) {\r\n assertFail(message || ('condition: ' + value));\r\n }\r\n }\r\n\r\n /**\r\n * Asserts that the value is neither null nor undefined, and has a length property that returns greater than zero, fails otherwise. \r\n */\r\n export function assertNonEmpty<T>(value: T[], message: string): void {\r\n if (!(value != null && value.length > 0)) {\r\n assertFail(message || ('condition: ' + value));\r\n }\r\n }\r\n\r\n /**\r\n * Makes no assertion on the given value.\r\n * This is documentation/placeholder that a value is possibly null or undefined (unlike assertValue).\r\n */\r\n export function assertAnyValue<T>(value: T, message: string): void {\r\n }\r\n\r\n export function assertFail(message: string): void {\r\n (assertFailFunction || alert)('Debug Assert failed: ' + message);\r\n }\r\n}\r\n\r\n///#ENDDEBUG","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n export interface IError extends Error {\r\n stack?: string;\r\n argument?: string;\r\n }\r\n\r\n export module Errors {\r\n export function infoNavAppAlreadyPresent(): IError {\r\n return {\r\n name: 'infoNavAppAlreadyPresent',\r\n message: 'Cannot initialize embedded scenario when the InfoNav App is already present in this context',\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n export function invalidOperation(message: string): IError {\r\n return {\r\n name: 'invalidOperation',\r\n message: message,\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n export function argument(argumentName: string, message: string): IError {\r\n return {\r\n name: 'invalidArgumentError',\r\n argument: argumentName,\r\n message: message,\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n export function argumentNull(argumentName: string): IError {\r\n return {\r\n name: 'argumentNull',\r\n argument: argumentName,\r\n message: 'Argument was null',\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n export function argumentUndefined(argumentName: string): IError {\r\n return {\r\n name: 'argumentUndefined',\r\n argument: argumentName,\r\n message: 'Argument was undefined',\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n export function argumentOutOfRange(argumentName: string): IError {\r\n return {\r\n name: 'argumentOutOfRange',\r\n argument: argumentName,\r\n message: 'Argument was out of range',\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n export function pureVirtualMethodException(className: string, methodName: string): IError {\r\n return {\r\n name: 'pureVirtualMethodException',\r\n message: 'This method must be overriden by the derived class:' + className + '.' + methodName,\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n export function notImplementedException(message: string): IError {\r\n return {\r\n name: 'notImplementedException',\r\n message: message,\r\n stack: getExceptionStackTrace()\r\n };\r\n }\r\n\r\n function getExceptionStackTrace(): string {\r\n return getStackTrace(/*leadingFramesToRemove*/2);\r\n }\r\n }\r\n\r\n /**\r\n * Captures the stack trace, if available.\r\n * It optionally takes the number of frames to remove from the stack trace.\r\n * By default, it removes the last frame to consider the calling type's\r\n * constructor and the temporary error used to capture the stack trace (below).\r\n * More levels can be requested as needed e..g. when an error is created\r\n * from a helper method. <Min requirement: IE10, Chrome, Firefox, Opera>.\r\n */\r\n export function getStackTrace(leadingFramesToRemove = 1): string {\r\n let stackTrace: string,\r\n stackSegments: string[];\r\n\r\n try {\r\n // needs to throw for stack trace to work in IE\r\n throw new Error();\r\n } catch (error) {\r\n stackTrace = error.stack;\r\n if (stackTrace != null) {\r\n stackSegments = stackTrace.split('\\n');\r\n stackSegments.splice(1, leadingFramesToRemove);\r\n // Finally\r\n stackTrace = stackSegments.join('\\n');\r\n }\r\n }\r\n\r\n return stackTrace;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\n$.fn.multiline = function (text) {\r\n this.text(text);\r\n this.html(this.html().replace(/\\n/g, '<br/>'));\r\n return this;\r\n};\r\n\r\n$.fn.togglePanelControl = function () {\r\n return this.each(function () {\r\n $(this).addClass(\"ui-accordion ui-accordion-icons ui-widget ui-helper-reset\")\r\n .find(\".accordionHeader\")\r\n .addClass(\"ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom\")\r\n .hover(function() {\r\n $(this).toggleClass(\"ui-state-hover\");\r\n })\r\n .prepend('<span class=\"ui-icon ui-icon-triangle-1-e\"></span>')\r\n .click(function() {\r\n $(this)\r\n .toggleClass(\"ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom\")\r\n .find(\"> .ui-icon\").toggleClass(\"ui-icon-triangle-1-e ui-icon-triangle-1-s\").end()\r\n .next().slideToggle();\r\n return false;\r\n })\r\n .next()\r\n .addClass(\"ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom\")\r\n .hide();\r\n });\r\n};\r\n\r\nmodule jsCommon {\r\n /** \r\n * Represents a promise that may be rejected by its consumer.\r\n */ \r\n export interface IRejectablePromise extends JQueryPromise<void> {\r\n reject(...args: any[]): void;\r\n }\r\n\r\n export module JQueryConstants {\r\n export const VisibleSelector: string = ':visible';\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n\r\n /** \r\n * Represents a lazily instantiated value.\r\n */\r\n export class Lazy<T> {\r\n private value: T;\r\n private factoryMethod: () => T;\r\n\r\n constructor(factoryMethod: () => T) {\r\n Utility.throwIfNullOrUndefined(factoryMethod, this, 'constructor', 'factoryMethod');\r\n\r\n this.factoryMethod = factoryMethod;\r\n }\r\n\r\n public getValue(): T {\r\n if (this.factoryMethod !== null) {\r\n this.value = this.factoryMethod();\r\n\r\n // Optimization: Release the factoryMethod, as it could be holding a large object graph.\r\n this.factoryMethod = null;\r\n }\r\n\r\n return this.value;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export module Prototype {\r\n /**\r\n * Returns a new object with the provided obj as its prototype.\r\n */\r\n export function inherit<T>(obj: T, extension?: (inherited: T) => void): T {\r\n debug.assertValue(obj, 'obj');\r\n\r\n function wrapCtor(): void { };\r\n wrapCtor.prototype = obj;\r\n\r\n let inherited = new wrapCtor();\r\n\r\n if (extension)\r\n extension(inherited);\r\n\r\n return inherited;\r\n }\r\n\r\n /**\r\n * Returns a new object with the provided obj as its prototype\r\n * if, and only if, the prototype has not been previously set\r\n */\r\n export function inheritSingle<T>(obj: T): T {\r\n debug.assertValue(obj, 'obj');\r\n\r\n let proto = Object.getPrototypeOf(obj);\r\n if (proto === Object.prototype || proto === Array.prototype)\r\n obj = inherit(obj);\r\n\r\n return obj;\r\n }\r\n\r\n /**\r\n * Uses the provided callback function to selectively replace contents in the provided array.\r\n * @return A new array with those values overriden\r\n * or undefined if no overrides are necessary.\r\n */\r\n export function overrideArray<T, TArray>(prototype: TArray, override: (T) => T): TArray {\r\n if (!prototype)\r\n return;\r\n\r\n let overwritten: TArray;\r\n\r\n for (let i = 0, len = (<T[]><any>prototype).length; i < len; i++) {\r\n let value = override(prototype[i]);\r\n if (value) {\r\n if (!overwritten)\r\n overwritten = inherit(prototype);\r\n\r\n overwritten[i] = value;\r\n }\r\n }\r\n\r\n return overwritten;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n\r\n export module Formatting {\r\n\r\n interface IRegexInt {\r\n // Regex for replace.\r\n r: RegExp;\r\n // The string to replace.\r\n s: string;\r\n }\r\n\r\n let regexCache: IRegexInt[];\r\n\r\n /** \r\n * Translate .NET format into something supported by jQuery.Globalize.\r\n */\r\n export function findDateFormat(value: Date, format: string, cultureName: string)\r\n {\r\n switch (format) {\r\n case \"m\":\r\n // Month + day\r\n format = \"M\";\r\n break;\r\n case \"O\":\r\n case \"o\":\r\n // Roundtrip\r\n format = \"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'0000'\";\r\n break;\r\n case \"R\":\r\n case \"r\":\r\n // RFC1123 pattern - - time must be converted to UTC before formatting \r\n value = new Date(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());\r\n format = \"ddd, dd MMM yyyy HH':'mm':'ss 'GMT'\";\r\n break;\r\n case \"s\":\r\n // Sortable - should use invariant culture\r\n format = \"S\";\r\n break;\r\n case \"u\":\r\n // Universal sortable - should convert to UTC before applying the \"yyyy'-'MM'-'dd HH':'mm':'ss'Z' format.\r\n value = new Date(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());\r\n format = \"yyyy'-'MM'-'dd HH':'mm':'ss'Z'\";\r\n break;\r\n case \"U\":\r\n // Universal full - the pattern is same as F but the time must be converted to UTC before formatting\r\n value = new Date(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());\r\n format = \"F\";\r\n break;\r\n case \"y\":\r\n case \"Y\":\r\n // Year and month\r\n switch (cultureName) {\r\n case \"default\":\r\n case \"en\":\r\n case \"en-US\":\r\n format = \"MMMM, yyyy\"; // Fix the default year-month pattern for english\r\n break;\r\n default:\r\n format = \"Y\"; // For other cultures - use the localized pattern\r\n }\r\n break;\r\n }\r\n return { value: value, format: format };\r\n }\r\n \r\n /** \r\n * Translates unsupported .NET custom format expressions to the custom expressions supported by JQuery.Globalize.\r\n */\r\n export function fixDateTimeFormat(format: string): string {\r\n // Fix for the \"K\" format (timezone): \r\n //The js dates don't have a kind property so we'll support only local kind which is equavalent to zzz format.\r\n format = format.replace(/%K/g, \"zzz\"); \r\n format = format.replace(/K/g, \"zzz\");\r\n format = format.replace(/fffffff/g, \"fff0000\");\r\n format = format.replace(/ffffff/g, \"fff000\");\r\n format = format.replace(/fffff/g, \"fff00\");\r\n format = format.replace(/ffff/g, \"fff0\");\r\n // Fix for the 5 digit year: \"yyyyy\" format. \r\n //The Globalize doesn't support dates greater than 9999 so we replace the \"yyyyy\" with \"0yyyy\".\r\n format = format.replace(/yyyyy/g, \"0yyyy\"); \r\n // Fix for the 3 digit year: \"yyy\" format. \r\n //The Globalize doesn't support this formatting so we need to replace it with the 4 digit year \"yyyy\" format.\r\n format = format.replace(/(^y|^)yyy(^y|$)/g, \"yyyy\"); \r\n\r\n if (!regexCache) {\r\n // Creating Regexes for cases \"Using single format specifier\" \r\n //- http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx#UsingSingleSpecifiers\r\n // This is not supported from The Globalize.\r\n // The case covers all single \"%\" lead specifier (like \"%d\" but not %dd) \r\n // The cases as single \"%d\" are filtered in if the bellow.\r\n // (?!S) where S is the specifier make sure that we only one symbol for specifier.\r\n regexCache = [\"d\", \"f\", \"F\", \"g\", \"h\", \"H\", \"K\", \"m\", \"M\", \"s\", \"t\", \"y\", \"z\", \":\", \"/\"].map((s) => {\r\n return { r: new RegExp(\"\\%\" + s + \"(?!\" + s + \")\", \"g\"), s: s };\r\n });\r\n }\r\n\r\n if (format.indexOf(\"%\") !== -1 && format.length > 2) {\r\n for (let i = 0; i < regexCache.length; i++) {\r\n format = format.replace(regexCache[i].r, regexCache[i].s);\r\n }\r\n }\r\n return format;\r\n }\r\n\r\n }\r\n\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n\r\n let doc: HTMLDocument = document,\r\n headElement: HTMLElement = doc.head,\r\n firstScriptInHeadElement: HTMLElement = headElement.getElementsByTagName('script')[0],\r\n linkElement: HTMLElement = doc.createElement('link'),\r\n scriptElement: HTMLElement = doc.createElement('script'),\r\n styleSheetLoaded: string[] = [],\r\n javaScriptFilesLoaded: string[] = [],\r\n javaScriptFilesLoading: any[] = [];\r\n\r\n linkElement.setAttribute('rel', 'stylesheet');\r\n\r\n /**\r\n * Public API.\r\n */\r\n\texport interface IJavaScriptDependency {\r\n\t\tjavascriptFile: string;\r\n\r\n // Callback that indicates when the script is loaded, after writing a <script> tag\r\n\t\tonLoadCallback?: () => JQueryPromise<void>;\r\n\t}\r\n\r\n export interface IDependency {\r\n javaScriptFiles?: string[];\r\n cssFiles?: string[];\r\n\t\tjavaScriptFilesWithCallback?: IJavaScriptDependency[];\r\n }\r\n\r\n export function requires(dependency: IDependency, to: () => void = $.noop): void {\r\n loadStyleSheets(dependency.cssFiles || []);\r\n\r\n\t\tlet scriptsToRun = dependency.javaScriptFilesWithCallback || [];\r\n\r\n\t\tif (dependency.javaScriptFiles) {\r\n\t\t\tfor(let i=0, len=dependency.javaScriptFiles.length; i<len; ++i) {\r\n\t\t\t\tscriptsToRun.push({javascriptFile:dependency.javaScriptFiles[i]});\r\n\t\t\t}\r\n\t\t}\r\n loadJavaScriptFiles(scriptsToRun, to);\r\n }\r\n\r\n /**\r\n * Private Helpers.\r\n */\r\n function loadStyleSheets(hrefList: string[]): void {\r\n hrefList.forEach(href => {\r\n if (styleSheetLoaded.indexOf(href) === -1) {\r\n styleSheetLoaded.push(href);\r\n loadStyleSheet(href);\r\n }\r\n });\r\n }\r\n\r\n function loadJavaScriptFiles(scripts: IJavaScriptDependency[], callback: () => void): void {\r\n let loadingCount = scripts.length,\r\n parsingCount = loadingCount,\r\n sourceCodeList: IJavaScriptDependency[] = [];\r\n\r\n function parseIfLoadingComplete(): void {\r\n if (!--loadingCount) {\r\n parseJavaScriptSourceCodes(scripts, sourceCodeList);\r\n }\r\n }\r\n\r\n function makeCallbackIfParsingComplete(): void {\r\n if (!--parsingCount) {\r\n callback();\r\n }\r\n }\r\n\r\n scripts.forEach((script: IJavaScriptDependency, index: number) => {\r\n let file = script.javascriptFile;\r\n if (javaScriptFilesLoaded.indexOf(file) === -1) { // not loaded\r\n\r\n if (file in javaScriptFilesLoading) { // loading\r\n javaScriptFilesLoading[file].push(() => {\r\n parseIfLoadingComplete();\r\n makeCallbackIfParsingComplete();\r\n });\r\n\r\n } else { // not loading\r\n javaScriptFilesLoading[file] = [() => {\r\n makeCallbackIfParsingComplete();\r\n }];\r\n\r\n if (isExternalUrl(file)) { // external JS file\r\n sourceCodeList[index] = script;\r\n parseIfLoadingComplete();\r\n\r\n } else { // internal JS file\r\n loadJavaScriptSourceCode(file, (sourceCode: string) => {\r\n sourceCodeList[index] = {javascriptFile: sourceCode};\r\n parseIfLoadingComplete();\r\n });\r\n }\r\n }\r\n\r\n } else { // loaded\r\n parseIfLoadingComplete();\r\n makeCallbackIfParsingComplete();\r\n }\r\n });\r\n }\r\n\r\n function loadStyleSheet(href: string): void {\r\n let link = <any>linkElement.cloneNode();\r\n link.href = href;\r\n if (firstScriptInHeadElement) {\r\n headElement.insertBefore(link, firstScriptInHeadElement);\r\n } else {\r\n headElement.appendChild(link);\r\n }\r\n }\r\n\r\n function loadJavaScriptSourceCode(src: string, onload: (code: string) => void): void {\r\n webGet(src, function (): void {\r\n onload(this.responseText);\r\n });\r\n }\r\n\r\n function parseJavaScript(script: IJavaScriptDependency, onComplete: () => void = $.noop): void {\r\n if (!script) {\r\n onComplete();\r\n return;\r\n }\r\n\r\n\t\tlet sourceCodeOrFileName = script.javascriptFile;\r\n\r\n\t\tlet targetCallback = onComplete;\r\n\t\tif (script.onLoadCallback) {\r\n\t\t\tlet promiseAsCallback = () => {\r\n\t\t\t\tscript.onLoadCallback().then(onComplete);\r\n\t\t\t};\r\n\t\t\ttargetCallback = promiseAsCallback;\r\n\t\t}\r\n\r\n isExternalUrl(sourceCodeOrFileName)\r\n ? loadExternalJavaScriptFile(sourceCodeOrFileName, targetCallback)\r\n : parseInternalJavaScriptCode(sourceCodeOrFileName, targetCallback);\r\n }\r\n\r\n function parseInternalJavaScriptCode(sourceCode: string, onComplete: () => void = $.noop): void {\r\n let script: HTMLElement;\r\n if (sourceCode) {\r\n script = <any>scriptElement.cloneNode();\r\n script.setAttribute('type', 'text/javascript');\r\n script.innerHTML = sourceCode;\r\n headElement.appendChild(script);\r\n }\r\n setTimeout(onComplete, 0);\r\n }\r\n\r\n function loadExternalJavaScriptFile(src, onload: () => void): void {\r\n let script: HTMLElement;\r\n if (src) {\r\n script = <any>scriptElement.cloneNode();\r\n script.setAttribute('src', src);\r\n script.setAttribute('charset', 'utf-8');\r\n script.onload = onload;\r\n headElement.appendChild(script);\r\n }\r\n }\r\n\r\n function parseJavaScriptSourceCodes(scripts: IJavaScriptDependency[], sourceCodeList: IJavaScriptDependency[]): void {\r\n asyncLoop(sourceCodeList, parseJavaScript, /*on all files parsed*/() => {\r\n scripts.forEach((script: IJavaScriptDependency) => {\r\n let file = script.javascriptFile;\r\n let listeners = javaScriptFilesLoading[file];\r\n if (listeners) {\r\n listeners.forEach((listener) => {\r\n listener();\r\n });\r\n }\r\n\r\n delete javaScriptFilesLoading[file];\r\n if (javaScriptFilesLoaded.indexOf(file) === -1) {\r\n javaScriptFilesLoaded.push(file);\r\n }\r\n });\r\n });\r\n }\r\n\r\n function webGet(src: string, onload: () => void, onerror?: (error: any) => void): void {\r\n let xhr = new XMLHttpRequest();\r\n\r\n try {\r\n xhr.open('GET', src, true);\r\n xhr.onload = onload;\r\n xhr.onerror = onerror;\r\n xhr.send(null);\r\n }\r\n catch (e) {\r\n // handle it\r\n }\r\n }\r\n\r\n function isExternalUrl(url: string): boolean {\r\n let origin = location.protocol + '//' + location.host + '/';\r\n return /^http[s]?:\\/\\/.+/i.test(url) && url.indexOf(origin) !== 0;\r\n }\r\n\r\n function _(...args: any[]): any { }\r\n\r\n function asyncSteps(...args: Function[]): void {\r\n if (args.length === 0) {\r\n return;\r\n }\r\n\r\n let steps = [],\r\n i = args.length;\r\n\r\n while (i--) {\r\n (function (j) {\r\n steps[j] = function () {\r\n args[j](steps[j + 1] || _);\r\n };\r\n })(i);\r\n }\r\n steps[0]();\r\n }\r\n\r\n function asyncLoop(enumerable: any[], func: (item, next) => void, callback: () => void): void {\r\n let steps = [],\r\n i = 0,\r\n len = enumerable.length;\r\n\r\n for (; i < len - 1; i++) {\r\n (function (i) {\r\n steps[i] = (next) => {\r\n func(enumerable[i], next);\r\n };\r\n } (i));\r\n }\r\n\r\n steps[len - 1] = (next) => {\r\n func(enumerable[len - 1], callback);\r\n };\r\n\r\n asyncSteps.apply(null, steps);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export function createJQueryPromiseFactory(): IPromiseFactory {\r\n return new JQueryPromiseFactory();\r\n }\r\n\r\n /**\r\n * jQuery-based implementation of IPromiseFactory.\r\n * This is useful for cases when Angular is not present, or when immediate promise resolving (not tied to Angular digest cycle) is desired.\r\n */\r\n class JQueryPromiseFactory implements IPromiseFactory {\r\n public defer<TSuccess, TError>(): IDeferred2<TSuccess, TError> {\r\n return new JQueryDeferredWrapper($.Deferred());\r\n }\r\n\r\n public reject<TError>(reason?: TError): IPromise2<any, TError> {\r\n let deferred = this.defer();\r\n deferred.reject(reason);\r\n return deferred.promise;\r\n }\r\n\r\n public resolve<TSuccess>(value: TSuccess): IPromise2<TSuccess, any> {\r\n let deferred = this.defer();\r\n deferred.resolve(value);\r\n return deferred.promise;\r\n }\r\n\r\n public all(promises: IPromise2<any, any>[]): IPromise<any[]>;\r\n\r\n public all(promises: any): IPromise<any[]> {\r\n let unwrappedPromises = jQuery.map(promises, (value) => {\r\n return value && value.promise ? value.promise : value;\r\n });\r\n\r\n return new JQueryPromiseWrapper($.when.apply($, unwrappedPromises));\r\n }\r\n\r\n public when<T>(value: T | IPromise<T>): IPromise<T>;\r\n\r\n public when<T>(value: any): IPromise<T> {\r\n let unwrappedPromise = value && value.promise ? value.promise : value;\r\n return new JQueryPromiseWrapper($.when(unwrappedPromise));\r\n }\r\n }\r\n\r\n /** \r\n * Implements IDeferred via a wrapped a jQuery Deferred.\r\n */\r\n class JQueryDeferredWrapper<TSuccess, TError> implements IDeferred2<TSuccess, TError> {\r\n public promise: IPromise2<TSuccess, TError>;\r\n private deferred: JQueryDeferred<any>;\r\n\r\n constructor(deferred: JQueryDeferred<any>) {\r\n debug.assertValue(deferred, 'deferred');\r\n\r\n this.deferred = deferred;\r\n this.promise = new JQueryPromiseWrapper(deferred.promise());\r\n }\r\n\r\n public resolve(value: TSuccess | IPromise<any>): void {\r\n this.deferred.resolve(value);\r\n }\r\n\r\n public reject(reason?: TError): void {\r\n this.deferred.reject(reason);\r\n }\r\n }\r\n\r\n /** \r\n * Implements IDeferred via a wrapped a jQuery Promise.\r\n */\r\n class JQueryPromiseWrapper<TSuccess, TError> implements IPromise2<TSuccess, TError> {\r\n private promise: JQueryPromise<any>;\r\n\r\n constructor(promise: JQueryPromise<any>) {\r\n debug.assertValue(promise, 'promise');\r\n\r\n this.promise = promise;\r\n }\r\n\r\n public then(a: (arg: any) => any, b: (arg: any) => any): IPromise2<any, any> {\r\n return new JQueryPromiseWrapper(\r\n this.promise.then(\r\n JQueryPromiseWrapper.wrapCallback(a),\r\n JQueryPromiseWrapper.wrapCallback(b)));\r\n }\r\n\r\n public catch(callback): IPromise2<any, any> {\r\n return this.then(null, callback);\r\n }\r\n\r\n public finally(callback): IPromise2<any, any> {\r\n this.promise.always(\r\n JQueryPromiseWrapper.wrapCallback(callback));\r\n return this;\r\n }\r\n\r\n /** \r\n * Wraps a callback, which may return a IPromise. \r\n */\r\n private static wrapCallback(callback: (arg: any) => any): (arg: any) => any {\r\n if (callback)\r\n return arg => {\r\n let value = callback(arg);\r\n\r\n // If the callback returns a Promise, unwrap that to allow jQuery to chain.\r\n if (value instanceof JQueryPromiseWrapper)\r\n return (<JQueryPromiseWrapper<any, any>>value).promise;\r\n\r\n return value;\r\n };\r\n\r\n return callback;\r\n }\r\n }\r\n}\r\n ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n export interface IStorageService {\r\n getData(key: string): any;\r\n setData(key: string, data: any): void;\r\n }\r\n\r\n class LocalStorageService implements IStorageService {\r\n public getData(key: string): any {\r\n try {\r\n if (localStorage) {\r\n let value = localStorage[key];\r\n if (value) {\r\n return JSON.parse(value);\r\n }\r\n }\r\n }\r\n catch (exception) {}\r\n\r\n return null;\r\n }\r\n\r\n public setData(key: string, data: any) {\r\n try {\r\n if (localStorage) {\r\n localStorage[key] = JSON.stringify(data);\r\n }\r\n }\r\n catch (e) {}\r\n }\r\n }\r\n\r\n export class EphemeralStorageService implements IStorageService {\r\n private cache: { [key: string]: any } = {};\r\n private clearCacheTimerId: number;\r\n private clearCacheInterval: number;\r\n public static defaultClearCacheInterval: number = (1000 * 60 * 60 * 24); // 1 day\r\n\r\n constructor(clearCacheInterval?: number) {\r\n this.clearCacheInterval = (clearCacheInterval != null)\r\n ? clearCacheInterval\r\n : EphemeralStorageService.defaultClearCacheInterval;\r\n\r\n this.clearCache();\r\n }\r\n\r\n public getData(key: string): any {\r\n return this.cache[key];\r\n }\r\n\r\n public setData(key: string, data: any) {\r\n this.cache[key] = data;\r\n\r\n if (this.clearCacheTimerId == null) {\r\n this.clearCacheTimerId = setTimeout(() => this.clearCache(), this.clearCacheInterval);\r\n }\r\n }\r\n\r\n private clearCache(): void {\r\n this.cache = {};\r\n this.clearCacheTimerId = undefined;\r\n }\r\n }\r\n\r\n export var localStorageService: IStorageService = new LocalStorageService();\r\n export const ephemeralStorageService: IStorageService = new EphemeralStorageService();\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n export module WordBreaker {\r\n import TextProperties = powerbi.TextProperties;\r\n import ITextAsSVGMeasurer = powerbi.ITextAsSVGMeasurer;\r\n import ITextTruncator = powerbi.ITextTruncator;\r\n \r\n export interface WordBreakerResult {\r\n start: number;\r\n end: number;\r\n }\r\n\r\n const SPACE = ' ';\r\n const BREAKERS_REGEX = /[\\s\\n]+/g;\r\n\r\n function search(index: number, content: string, backward: boolean): number {\r\n if (backward) {\r\n for (let i = index - 1; i > -1; i--) {\r\n if (hasBreakers(content[i]))\r\n return i + 1;\r\n }\r\n } else {\r\n for (let i = index, ilen = content.length; i < ilen; i++) {\r\n if (hasBreakers(content[i]))\r\n return i;\r\n }\r\n }\r\n\r\n return backward ? 0 : content.length;\r\n }\r\n\r\n /**\r\n * Find the word nearest the cursor specified within content\r\n * @param index - point within content to search forward/backward from\r\n * @param content - string to search\r\n */\r\n export function find(index: number, content: string): WordBreakerResult {\r\n debug.assert(index >= 0 && index <= content.length, 'index within content string bounds');\r\n\r\n let result = { start: 0, end: 0 };\r\n if (content.length === 0)\r\n return result;\r\n\r\n result.start = search(index, content, true);\r\n result.end = search(index, content, false);\r\n return result;\r\n }\r\n\r\n /**\r\n * Test for presence of breakers within content\r\n * @param content - string to test\r\n */\r\n export function hasBreakers(content: string): boolean {\r\n BREAKERS_REGEX.lastIndex = 0;\r\n return BREAKERS_REGEX.test(content);\r\n }\r\n\r\n /**\r\n * Count the number of pieces when broken by BREAKERS_REGEX\r\n * ~2.7x faster than WordBreaker.split(content).length\r\n * @param content - string to break and count\r\n */\r\n export function wordCount(content: string): number {\r\n let count = 1;\r\n BREAKERS_REGEX.lastIndex = 0;\r\n BREAKERS_REGEX.exec(content);\r\n while (BREAKERS_REGEX.lastIndex !== 0) {\r\n count++;\r\n BREAKERS_REGEX.exec(content);\r\n }\r\n\r\n return count;\r\n }\r\n\r\n export function getMaxWordWidth(content: string, textWidthMeasurer: ITextAsSVGMeasurer, properties: TextProperties): number {\r\n let words = split(content);\r\n let maxWidth = 0;\r\n for (let w of words) {\r\n properties.text = w;\r\n maxWidth = Math.max(maxWidth, textWidthMeasurer(properties));\r\n }\r\n return maxWidth;\r\n }\r\n\r\n function split(content: string): string[] {\r\n return content.split(BREAKERS_REGEX);\r\n }\r\n\r\n function getWidth(content: string, properties: TextProperties, textWidthMeasurer: ITextAsSVGMeasurer): number {\r\n properties.text = content;\r\n return textWidthMeasurer(properties);\r\n }\r\n\r\n function truncate(content: string, properties: TextProperties, truncator: ITextTruncator, maxWidth: number): string {\r\n properties.text = content;\r\n return truncator(properties, maxWidth);\r\n }\r\n\r\n /**\r\n * Split content by breakers (words) and greedy fit as many words\r\n * into each index in the result based on max width and number of lines\r\n * e.g. Each index in result corresponds to a line of content\r\n * when used by AxisHelper.LabelLayoutStrategy.wordBreak\r\n * @param content - string to split\r\n * @param properties - text properties to be used by @param:textWidthMeasurer\r\n * @param textWidthMeasurer - function to calculate width of given text content\r\n * @param maxWidth - maximum allowed width of text content in each result\r\n * @param maxNumLines - maximum number of results we will allow, valid values must be greater than 0\r\n * @param truncator - (optional) if specified, used as a function to truncate content to a given width\r\n */\r\n export function splitByWidth(\r\n content: string,\r\n properties: TextProperties,\r\n textWidthMeasurer: ITextAsSVGMeasurer,\r\n maxWidth: number,\r\n maxNumLines: number,\r\n truncator?: ITextTruncator): string[] {\r\n // Default truncator returns string as-is\r\n truncator = truncator ? truncator : (properties: TextProperties, maxWidth: number) => properties.text;\r\n\r\n let result: string[] = [];\r\n let words = split(content);\r\n\r\n let usedWidth = 0;\r\n let wordsInLine: string[] = [];\r\n\r\n for (let word of words) {\r\n // Last line? Just add whatever is left\r\n if ((maxNumLines > 0) && (result.length >= maxNumLines - 1)) {\r\n wordsInLine.push(word);\r\n continue;\r\n }\r\n\r\n // Determine width if we add this word\r\n // Account for SPACE we will add when joining...\r\n let wordWidth = wordsInLine.length === 0\r\n ? getWidth(word, properties, textWidthMeasurer)\r\n : getWidth(SPACE + word, properties, textWidthMeasurer);\r\n\r\n // If width would exceed max width,\r\n // then push used words and start new split result\r\n if (usedWidth + wordWidth > maxWidth) {\r\n // Word alone exceeds max width, just add it.\r\n if (wordsInLine.length === 0) {\r\n result.push(truncate(word, properties, truncator, maxWidth));\r\n\r\n usedWidth = 0;\r\n wordsInLine = [];\r\n continue;\r\n }\r\n \r\n result.push(truncate(wordsInLine.join(SPACE), properties, truncator, maxWidth));\r\n\r\n usedWidth = 0;\r\n wordsInLine = [];\r\n }\r\n\r\n // ...otherwise, add word and continue\r\n wordsInLine.push(word);\r\n usedWidth += wordWidth;\r\n }\r\n\r\n // Push remaining words onto result\r\n result.push(truncate(wordsInLine.join(SPACE), properties, truncator, maxWidth));\r\n\r\n return result;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export interface ITextMeasurer {\r\n (textElement: SVGTextElement): number;\r\n }\r\n\r\n export interface ITextAsSVGMeasurer {\r\n (textProperties: TextProperties): number;\r\n }\r\n\r\n export interface ITextTruncator {\r\n (properties: TextProperties, maxWidth: number): string;\r\n }\r\n\r\n export interface TextProperties {\r\n text?: string;\r\n fontFamily: string;\r\n fontSize: string;\r\n fontWeight?: string;\r\n fontStyle?: string;\r\n fontVariant?: string;\r\n whiteSpace?: string;\r\n }\r\n\r\n interface CanvasContext {\r\n font: string;\r\n measureText(text: string): { width: number };\r\n }\r\n\r\n interface CanvasElement extends HTMLElement {\r\n getContext(name: string);\r\n }\r\n\r\n export module TextMeasurementService {\r\n const ellipsis = '…';\r\n const OverflowingText = jsCommon.CssConstants.createClassAndSelector('overflowingText');\r\n\r\n let spanElement: JQuery;\r\n let svgTextElement: D3.Selection;\r\n let canvasCtx: CanvasContext;\r\n let fallbackFontFamily: string;\r\n\r\n /**\r\n * Idempotent function for adding the elements to the DOM. \r\n */\r\n function ensureDOM(): void {\r\n if (spanElement)\r\n return;\r\n\r\n spanElement = $('<span/>');\r\n $('body').append(spanElement);\r\n //The style hides the svg element from the canvas, preventing canvas from scrolling down to show svg black square.\r\n svgTextElement = d3.select($('body').get(0))\r\n .append('svg')\r\n .style({\r\n 'height': '0px',\r\n 'width': '0px',\r\n 'position': 'absolute'\r\n })\r\n .append('text');\r\n canvasCtx = (<CanvasElement>$('<canvas/>').get(0)).getContext(\"2d\");\r\n fallbackFontFamily = window.getComputedStyle(svgTextElement.node()).fontFamily;\r\n }\r\n\r\n /**\r\n * Removes spanElement from DOM.\r\n */\r\n export function removeSpanElement() {\r\n if (spanElement && spanElement.remove) {\r\n spanElement.remove();\r\n }\r\n\r\n spanElement = null;\r\n }\r\n\r\n /**\r\n * This method measures the width of the text with the given SVG text properties.\r\n * @param textProperties The text properties to use for text measurement.\r\n */\r\n export function measureSvgTextWidth(textProperties: TextProperties): number {\r\n debug.assertValue(textProperties, 'textProperties');\r\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\r\n\r\n ensureDOM();\r\n\r\n canvasCtx.font =\r\n (textProperties.fontStyle || \"\") + \" \" +\r\n (textProperties.fontVariant || \"\") + \" \" +\r\n (textProperties.fontWeight || \"\") + \" \" +\r\n textProperties.fontSize + \" \" +\r\n (textProperties.fontFamily || fallbackFontFamily);\r\n\r\n return canvasCtx.measureText(textProperties.text).width;\r\n }\r\n\r\n /**\r\n * This method return the rect with the given SVG text properties.\r\n * @param textProperties The text properties to use for text measurement.\r\n */\r\n export function measureSvgTextRect(textProperties: TextProperties): SVGRect {\r\n debug.assertValue(textProperties, 'textProperties');\r\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\r\n\r\n ensureDOM();\r\n\r\n svgTextElement.style(null);\r\n svgTextElement\r\n .text(textProperties.text)\r\n .attr({\r\n 'visibility': 'hidden',\r\n 'font-family': textProperties.fontFamily || fallbackFontFamily,\r\n 'font-variant': textProperties.fontVariant,\r\n 'font-size': textProperties.fontSize,\r\n 'font-weight': textProperties.fontWeight,\r\n 'font-style': textProperties.fontStyle,\r\n 'white-space': textProperties.whiteSpace || 'nowrap'\r\n });\r\n\r\n // We're expecting the browser to give a synchronous measurement here\r\n // We're using SVGTextElement because it works across all browsers \r\n return svgTextElement.node<SVGTextElement>().getBBox();\r\n }\r\n\r\n /**\r\n * This method measures the height of the text with the given SVG text properties.\r\n * @param textProperties The text properties to use for text measurement.\r\n */\r\n export function measureSvgTextHeight(textProperties: TextProperties): number {\r\n return measureSvgTextRect(textProperties).height;\r\n }\r\n\r\n /**\r\n * This method returns the text Rect with the given SVG text properties.\r\n * Does NOT return text width; obliterates text value\r\n * @param {TextProperties} textProperties - The text properties to use for text measurement\r\n */\r\n function estimateSvgTextRect(textProperties: TextProperties): SVGRect {\r\n debug.assertValue(textProperties, 'textProperties');\r\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\r\n\r\n let propertiesKey = textProperties.fontFamily + textProperties.fontSize;\r\n let rect: SVGRect = ephemeralStorageService.getData(propertiesKey);\r\n\r\n if (rect == null) {\r\n // To estimate we check the height of a particular character, once it is cached, subsequent\r\n // calls should always get the height from the cache (regardless of the text).\r\n let estimatedTextProperties: TextProperties = {\r\n fontFamily: textProperties.fontFamily,\r\n fontSize: textProperties.fontSize,\r\n text: \"M\",\r\n };\r\n\r\n rect = TextMeasurementService.measureSvgTextRect(estimatedTextProperties);\r\n\r\n // NOTE: In some cases (disconnected/hidden DOM) we may provide incorrect measurement results (zero sized bounding-box), so\r\n // we only store values in the cache if we are confident they are correct.\r\n if (rect.height > 0)\r\n ephemeralStorageService.setData(propertiesKey, rect);\r\n }\r\n\r\n return rect;\r\n }\r\n\r\n /**\r\n * This method returns the text Rect with the given SVG text properties.\r\n * @param {TextProperties} textProperties - The text properties to use for text measurement\r\n */\r\n export function estimateSvgTextBaselineDelta(textProperties: TextProperties): number {\r\n let rect = estimateSvgTextRect(textProperties);\r\n return rect.y + rect.height;\r\n }\r\n\r\n /**\r\n * This method estimates the height of the text with the given SVG text properties.\r\n * @param {TextProperties} textProperties - The text properties to use for text measurement\r\n */\r\n export function estimateSvgTextHeight(textProperties: TextProperties, tightFightForNumeric: boolean = false): number {\r\n let height = estimateSvgTextRect(textProperties).height;\r\n\r\n //TODO: replace it with new baseline calculation\r\n if (tightFightForNumeric)\r\n height *= 0.7;\r\n\r\n return height;\r\n }\r\n\r\n /**\r\n * This method measures the width of the svgElement.\r\n * @param svgElement The SVGTextElement to be measured.\r\n */\r\n export function measureSvgTextElementWidth(svgElement: SVGTextElement): number {\r\n debug.assertValue(svgElement, 'svgElement');\r\n return measureSvgTextWidth(getSvgMeasurementProperties(svgElement));\r\n }\r\n\r\n /**\r\n * This method fetches the text measurement properties of the given DOM element.\r\n * @param element The selector for the DOM Element.\r\n */\r\n export function getMeasurementProperties(element: JQuery): TextProperties {\r\n debug.assertValue(element, 'element');\r\n\r\n return {\r\n text: element.val() || element.text(),\r\n fontFamily: element.css('font-family'),\r\n fontSize: element.css('font-size'),\r\n fontWeight: element.css('font-weight'),\r\n fontStyle: element.css('font-style'),\r\n fontVariant: element.css('font-variant'),\r\n whiteSpace: element.css('white-space')\r\n };\r\n }\r\n\r\n /**\r\n * This method fetches the text measurement properties of the given SVG text element.\r\n * @param svgElement The SVGTextElement to be measured.\r\n */\r\n export function getSvgMeasurementProperties(svgElement: SVGTextElement): TextProperties {\r\n debug.assertValue(svgElement, 'svgElement');\r\n\r\n let style = window.getComputedStyle(svgElement, null);\r\n return {\r\n text: svgElement.textContent,\r\n fontFamily: style.fontFamily,\r\n fontSize: style.fontSize,\r\n fontWeight: style.fontWeight,\r\n fontStyle: style.fontStyle,\r\n fontVariant: style.fontVariant,\r\n whiteSpace: style.whiteSpace\r\n };\r\n }\r\n\r\n /**\r\n * This method returns the width of a div element.\r\n * @param element The div element.\r\n */\r\n export function getDivElementWidth(element: JQuery): string {\r\n debug.assert(element.is('div'), 'Given element is not a div type. Cannot get width');\r\n return getComputedStyle(element[0]).width;\r\n }\r\n\r\n /**\r\n * Compares labels text size to the available size and renders ellipses when the available size is smaller.\r\n * @param textProperties The text properties (including text content) to use for text measurement.\r\n * @param maxWidth The maximum width available for rendering the text.\r\n */\r\n export function getTailoredTextOrDefault(textProperties: TextProperties, maxWidth: number): string {\r\n debug.assertValue(textProperties, 'properties');\r\n debug.assertValue(textProperties.text, 'properties.text');\r\n debug.assert(_.isEmpty(textProperties.fontSize) || textProperties.fontSize.indexOf(\"px\") !== -1, \"TextProperties' text size should be in px.\");\r\n\r\n ensureDOM();\r\n\r\n let strLength = textProperties.text.length;\r\n\r\n if (strLength === 0)\r\n return textProperties.text;\r\n\r\n let width = measureSvgTextWidth(textProperties);\r\n\r\n if (width < maxWidth)\r\n return textProperties.text;\r\n\r\n // Create a copy of the textProperties so we don't modify the one that's passed in.\r\n let copiedTextProperties = Prototype.inherit(textProperties);\r\n\r\n // Take the properties and apply them to svgTextElement\r\n // Then, do the binary search to figure out the substring we want\r\n // Set the substring on textElement argument\r\n let text = copiedTextProperties.text = ellipsis + copiedTextProperties.text;\r\n\r\n let min = 1;\r\n let max = text.length;\r\n let i = ellipsis.length;\r\n\r\n while (min <= max) {\r\n // num | 0 prefered to Math.floor(num) for performance benefits\r\n i = (min + max) / 2 | 0;\r\n\r\n copiedTextProperties.text = text.substr(0, i);\r\n width = measureSvgTextWidth(copiedTextProperties);\r\n\r\n if (maxWidth > width)\r\n min = i + 1;\r\n else if (maxWidth < width)\r\n max = i - 1;\r\n else\r\n break;\r\n }\r\n\r\n // Since the search algorithm almost never finds an exact match,\r\n // it will pick one of the closest two, which could result in a\r\n // value bigger with than 'maxWidth' thus we need to go back by \r\n // one to guarantee a smaller width than 'maxWidth'.\r\n copiedTextProperties.text = text.substr(0, i);\r\n width = measureSvgTextWidth(copiedTextProperties);\r\n if (width > maxWidth)\r\n i--;\r\n\r\n return text.substr(ellipsis.length, i - ellipsis.length) + ellipsis;\r\n }\r\n\r\n /**\r\n * Compares labels text size to the available size and renders ellipses when the available size is smaller.\r\n * @param textElement The SVGTextElement containing the text to render.\r\n * @param maxWidth The maximum width available for rendering the text.\r\n */\r\n export function svgEllipsis(textElement: SVGTextElement, maxWidth: number): void {\r\n debug.assertValue(textElement, 'textElement');\r\n\r\n let properties = getSvgMeasurementProperties(textElement);\r\n let originalText = properties.text;\r\n let tailoredText = getTailoredTextOrDefault(properties, maxWidth);\r\n\r\n if (originalText !== tailoredText) {\r\n textElement.textContent = tailoredText;\r\n }\r\n }\r\n\r\n /**\r\n * Word break textContent of <text> SVG element into <tspan>s\r\n * Each tspan will be the height of a single line of text\r\n * @param textElement - the SVGTextElement containing the text to wrap\r\n * @param maxWidth - the maximum width available\r\n * @param maxHeight - the maximum height available (defaults to single line)\r\n * @param linePadding - (optional) padding to add to line height\r\n */\r\n export function wordBreak(textElement: SVGTextElement, maxWidth: number, maxHeight: number, linePadding: number = 0): void {\r\n debug.assertValue(textElement, 'textElement');\r\n\r\n let properties = getSvgMeasurementProperties(textElement);\r\n let height = estimateSvgTextHeight(properties) + linePadding;\r\n let maxNumLines = Math.max(1, Math.floor(maxHeight / height));\r\n let node = d3.select(textElement);\r\n\r\n // Save y of parent textElement to apply as first tspan dy\r\n let firstDY = node.attr('y');\r\n\r\n // Store and clear text content\r\n let labelText = textElement.textContent;\r\n textElement.textContent = null;\r\n\r\n // Append a tspan for each word broken section\r\n let words = jsCommon.WordBreaker.splitByWidth(labelText, properties, measureSvgTextWidth, maxWidth, maxNumLines);\r\n for (let i = 0, ilen = words.length; i < ilen; i++) {\r\n properties.text = words[i];\r\n node\r\n .append('tspan')\r\n .attr({\r\n 'x': 0,\r\n 'dy': i === 0 ? firstDY : height,\r\n })\r\n // Truncate\r\n .text(getTailoredTextOrDefault(properties, maxWidth));\r\n }\r\n }\r\n\r\n /**\r\n * Word break textContent of span element into <span>s\r\n * Each span will be the height of a single line of text\r\n * @param textElement - the element containing the text to wrap\r\n * @param maxWidth - the maximum width available\r\n * @param maxHeight - the maximum height available (defaults to single line)\r\n * @param linePadding - (optional) padding to add to line height\r\n */\r\n export function wordBreakOverflowingText(textElement: any, maxWidth: number, maxHeight: number, linePadding: number = 0): void {\r\n debug.assertValue(textElement, 'textElement');\r\n\r\n let properties = getSvgMeasurementProperties(<SVGTextElement>textElement);\r\n let height = estimateSvgTextHeight(properties) + linePadding;\r\n let maxNumLines = Math.max(1, Math.floor(maxHeight / height));\r\n\r\n // Store and clear text content\r\n let labelText = textElement.textContent;\r\n textElement.textContent = null;\r\n\r\n // Append a span for each word broken section\r\n let words = jsCommon.WordBreaker.splitByWidth(labelText, properties, measureSvgTextWidth, maxWidth, maxNumLines);\r\n\r\n // splitByWidth() occasionally returns unnecessary empty strings, so get rid of them.\r\n // TODO: Fix splitByWidth.\r\n words = _.compact(words);\r\n\r\n let spanItem = d3.select(textElement)\r\n .selectAll(OverflowingText.selector)\r\n .data(words, (d: String) => $.inArray(d, words));\r\n\r\n spanItem\r\n .enter()\r\n .append(\"span\")\r\n .classed(OverflowingText.class, true)\r\n .text((d: string) => d)\r\n .style(\"width\", jsCommon.PixelConverter.toString(maxWidth));\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n import DOMConstants = jsCommon.DOMConstants;\r\n\r\n export module KeyUtils {\r\n export function isArrowKey(keyCode: number): boolean {\r\n return keyCode === DOMConstants.downArrowKeyCode\r\n || keyCode === DOMConstants.upArrowKeyCode\r\n || keyCode === DOMConstants.leftArrowKeyCode\r\n || keyCode === DOMConstants.rightArrowKeyCode;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n /**\r\n * Responsible for throttling input function.\r\n */\r\n export class ThrottleUtility {\r\n private fn: () => void;\r\n private timerFactory: ITimerPromiseFactory;\r\n private delay: number;\r\n\r\n constructor(delay?: number) {\r\n this.timerFactory = TimerPromiseFactory.instance;\r\n this.delay = 0;\r\n if (delay) {\r\n this.delay = delay;\r\n }\r\n }\r\n\r\n public run(fn: () => void): void {\r\n if (!this.fn) {\r\n this.fn = fn;\r\n this.timerFactory.create(this.delay).done(() => this.timerComplete(this.fn));\r\n } else {\r\n this.fn = fn;\r\n }\r\n }\r\n\r\n /**\r\n * Note: Public for testing purpose.\r\n */\r\n public timerComplete(fn: () => void) {\r\n // run fn\r\n fn();\r\n \r\n // clear fn\r\n this.fn = null;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n\r\n export interface ITimerPromiseFactory {\r\n /** \r\n * Creates a promise that will be resolved after the specified delayInMs.\r\n * @return Promise.\r\n */\r\n create(delayInMs: number): IRejectablePromise;\r\n }\r\n\r\n /** \r\n * Responsible for creating timer promises.\r\n */\r\n export class TimerPromiseFactory implements ITimerPromiseFactory {\r\n public static instance = new TimerPromiseFactory();\r\n\r\n /**\r\n * {@inheritDoc}\r\n */\r\n public create(delayInMs: number): IRejectablePromise {\r\n debug.assertValue(delayInMs, 'delayInMs');\r\n debug.assert(delayInMs >= 0, 'delayInMs must be a positive value.');\r\n\r\n let deferred = $.Deferred<void>();\r\n\r\n window.setTimeout(\r\n () => deferred.resolve(),\r\n delayInMs);\r\n\r\n return deferred;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\n/**\r\n * Defined in host.\r\n */\r\ndeclare var clusterUri: string;\r\n\r\nmodule jsCommon {\r\n\r\n /**\r\n * Http Status code we are interested.\r\n */\r\n export enum HttpStatusCode {\r\n OK = 200,\r\n BadRequest = 400,\r\n Unauthorized = 401,\r\n Forbidden = 403,\r\n RequestEntityTooLarge = 413,\r\n }\r\n\r\n /**\r\n * Other HTTP Constants.\r\n */\r\n export module HttpConstants {\r\n export const ApplicationOctetStream = 'application/octet-stream';\r\n export const MultiPartFormData = 'multipart/form-data';\r\n }\r\n\r\n /**\r\n * Extensions to String class.\r\n */\r\n export module StringExtensions {\r\n const HtmlTagRegex = new RegExp('[<>]', 'g');\r\n\r\n export function format(...args: string[]) {\r\n let s = args[0];\r\n\r\n if (isNullOrUndefinedOrWhiteSpaceString(s))\r\n return s;\r\n\r\n for (let i = 0; i < args.length - 1; i++) {\r\n let reg = new RegExp(\"\\\\{\" + i + \"\\\\}\", \"gm\");\r\n s = s.replace(reg, args[i + 1]);\r\n }\r\n return s;\r\n }\r\n\r\n /**\r\n * Compares two strings for equality, ignoring case.\r\n */\r\n export function equalIgnoreCase(a: string, b: string): boolean {\r\n return StringExtensions.normalizeCase(a) === StringExtensions.normalizeCase(b);\r\n }\r\n\r\n export function startsWithIgnoreCase(a: string, b: string): boolean {\r\n let normalizedSearchString = StringExtensions.normalizeCase(b);\r\n return StringExtensions.normalizeCase(a).indexOf(normalizedSearchString) === 0;\r\n }\r\n\r\n export function startsWith(a: string, b: string): boolean {\r\n return a.indexOf(b) === 0;\r\n }\r\n\r\n /** Determines whether a string contains a specified substring (while ignoring case). */\r\n export function containsIgnoreCase(source: string, substring: string): boolean {\r\n if (source == null)\r\n return false;\r\n\r\n return source.toLowerCase().indexOf(substring.toLowerCase().toString()) !== -1;\r\n }\r\n\r\n /** \r\n * Normalizes case for a string.\r\n * Used by equalIgnoreCase method. \r\n */\r\n export function normalizeCase(value: string): string {\r\n Utility.throwIfNullOrUndefined(value, StringExtensions, 'normalizeCase', 'value');\r\n\r\n return value.toUpperCase();\r\n }\r\n\r\n /** \r\n * Is string null or empty or undefined?\r\n * @return True if the value is null or undefined or empty string,\r\n * otherwise false.\r\n */\r\n export function isNullOrEmpty(value: string): boolean {\r\n return (value == null) || (value.length === 0);\r\n }\r\n\r\n /** \r\n * Returns true if the string is null, undefined, empty, or only includes white spaces.\r\n * @return True if the str is null, undefined, empty, or only includes white spaces,\r\n * otherwise false.\r\n */\r\n export function isNullOrUndefinedOrWhiteSpaceString(str: string): boolean {\r\n return StringExtensions.isNullOrEmpty(str) || StringExtensions.isNullOrEmpty(str.trim());\r\n }\r\n\r\n /**\r\n * Returns a value indicating whether the str contains any whitespace.\r\n */\r\n export function containsWhitespace(str: string): boolean {\r\n Utility.throwIfNullOrUndefined(str, this, 'containsWhitespace', 'str');\r\n\r\n let expr: RegExp = /\\s/;\r\n return expr.test(str);\r\n }\r\n\r\n /**\r\n * Returns a value indicating whether the str is a whitespace string.\r\n */\r\n export function isWhitespace(str: string): boolean {\r\n Utility.throwIfNullOrUndefined(str, this, 'isWhitespace', 'str');\r\n\r\n return str.trim() === '';\r\n }\r\n\r\n /** \r\n * Returns the string with any trailing whitespace from str removed.\r\n */\r\n export function trimTrailingWhitespace(str: string): string {\r\n Utility.throwIfNullOrUndefined(str, this, 'trimTrailingWhitespace', 'str');\r\n return str.replace(/\\s+$/, '');\r\n }\r\n\r\n /**\r\n * Returns the string with any leading and trailing whitespace from str removed.\r\n */\r\n export function trimWhitespace(str: string): string {\r\n Utility.throwIfNullOrUndefined(str, this, 'trimWhitespace', 'str');\r\n return str.replace(/^\\s+/, '').replace(/\\s+$/, '');\r\n }\r\n\r\n /** \r\n * Returns length difference between the two provided strings.\r\n */\r\n export function getLengthDifference(left: string, right: string) {\r\n Utility.throwIfNullOrUndefined(left, this, 'getLengthDifference', 'left');\r\n Utility.throwIfNullOrUndefined(right, this, 'getLengthDifference', 'right');\r\n\r\n return Math.abs(left.length - right.length);\r\n }\r\n\r\n /**\r\n * Repeat char or string several times.\r\n * @param char The string to repeat.\r\n * @param count How many times to repeat the string.\r\n */\r\n export function repeat(char: string, count: number): string {\r\n let result = \"\";\r\n for (let i = 0; i < count; i++) {\r\n result += char;\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Replace all the occurrences of the textToFind in the text with the textToReplace.\r\n * @param text The original string.\r\n * @param textToFind Text to find in the original string.\r\n * @param textToReplace New text replacing the textToFind.\r\n */\r\n export function replaceAll(text: string, textToFind: string, textToReplace: string): string {\r\n if (!textToFind)\r\n return text;\r\n\r\n let pattern = escapeStringForRegex(textToFind);\r\n return text.replace(new RegExp(pattern, 'gi'), textToReplace);\r\n }\r\n\r\n export function ensureUniqueNames(names: string[]): string[] {\r\n debug.assertValue(names, 'names');\r\n\r\n let usedNames: { [name: string]: boolean } = {};\r\n\r\n // Make sure we are giving fair chance for all columns to stay with their original name\r\n // First we fill the used names map to contain all the original unique names from the list.\r\n for (let name of names) {\r\n usedNames[name] = false;\r\n }\r\n\r\n let uniqueNames: string[] = [];\r\n\r\n // Now we go over all names and find a unique name for each\r\n for (let name of names) {\r\n let uniqueName = name;\r\n\r\n // If the (original) column name is already taken lets try to find another name\r\n if (usedNames[uniqueName]) {\r\n let counter = 0;\r\n // Find a name that is not already in the map\r\n while (usedNames[uniqueName] !== undefined) {\r\n uniqueName = name + \".\" + (++counter);\r\n }\r\n }\r\n\r\n uniqueNames.push(uniqueName);\r\n usedNames[uniqueName] = true;\r\n }\r\n\r\n return uniqueNames;\r\n }\r\n\r\n /**\r\n * Returns a name that is not specified in the values.\r\n */\r\n export function findUniqueName(\r\n usedNames: { [name: string]: boolean },\r\n baseName: string): string {\r\n debug.assertValue(usedNames, 'usedNames');\r\n debug.assertValue(baseName, 'baseName');\r\n\r\n // Find a unique name\r\n let i = 0,\r\n uniqueName: string = baseName;\r\n while (usedNames[uniqueName]) {\r\n uniqueName = baseName + (++i);\r\n }\r\n\r\n return uniqueName;\r\n }\r\n\r\n export function constructCommaSeparatedList(list: string[], resourceProvider: IStringResourceProvider, maxValue?: number): string {\r\n if (!list || list.length === 0)\r\n return '';\r\n\r\n if (maxValue === null || maxValue === undefined)\r\n maxValue = Number.MAX_VALUE;\r\n\r\n let length = Math.min(maxValue, list.length);\r\n\r\n let replacedList = [];\r\n // Only need to replace user entries of {0} and {1} since we build the list in pairs.\r\n for (let j = 0; j < 2; j++) {\r\n let targetValue = '{' + j + '}';\r\n let replaceValue = '_|_<' + j + '>_|_';\r\n for (let i = 0; i < length; i++) {\r\n if (list[i].indexOf(targetValue) > -1) {\r\n list[i] = list[i].replace(targetValue, replaceValue);\r\n replacedList.push({ targetValue: targetValue, replaceValue: replaceValue });\r\n }\r\n }\r\n }\r\n\r\n let commaSeparatedList: string = '';\r\n for (let i = 0; i < length; i++) {\r\n if (i === 0)\r\n commaSeparatedList = list[i];\r\n else\r\n commaSeparatedList = StringExtensions.format(resourceProvider.get('FilterRestatement_Comma'), commaSeparatedList, list[i]);\r\n }\r\n\r\n for (let i = 0; i < replacedList.length; i++) {\r\n commaSeparatedList = commaSeparatedList.replace(replacedList[i].replaceValue, replacedList[i].targetValue);\r\n }\r\n\r\n return commaSeparatedList;\r\n }\r\n\r\n export function escapeStringForRegex(s: string): string {\r\n return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1');\r\n }\r\n\r\n /**\r\n * Remove file name reserved characters <>:\"/\\|?* from input string.\r\n */\r\n export function normalizeFileName(fileName: string): string { \r\n debug.assertValue(fileName, 'fileName'); \r\n return fileName.replace(/[\\<\\>\\:\"\\/\\\\\\|\\?*]/g, '');\r\n }\r\n\r\n /**\r\n * Similar to JSON.stringify, but strips away escape sequences so that the resulting\r\n * string is human-readable (and parsable by JSON formatting/validating tools).\r\n */\r\n export function stringifyAsPrettyJSON(object: any): string {\r\n //let specialCharacterRemover = (key: string, value: string) => value.replace(/[^\\w\\s]/gi, '');\r\n return JSON.stringify(object /*, specialCharacterRemover*/);\r\n }\r\n\r\n /**\r\n * Derive a CLS-compliant name from a specified string. If no allowed characters are present, return a fallback string instead.\r\n * TODO (6708134): this should have a fully Unicode-aware implementation\r\n */\r\n export function deriveClsCompliantName(input: string, fallback: string): string {\r\n debug.assertValue(input, 'input');\r\n\r\n let result = input.replace(/^[^A-Za-z]*/g, '').replace(/[ :\\.\\/\\\\\\-\\u00a0\\u1680\\u180e\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]/g, '_').replace(/[\\W]/g, '');\r\n\r\n return result.length > 0 ? result : fallback;\r\n }\r\n\r\n /** Performs cheap sanitization by stripping away HTML tag (<>) characters. */\r\n export function stripTagDelimiters(s: string): string {\r\n return s.replace(HtmlTagRegex, '');\r\n }\r\n }\r\n\r\n /**\r\n * Interface used for interacting with WCF typed objects.\r\n */\r\n export interface TypedObject {\r\n __type: string;\r\n }\r\n\r\n export interface TextMatch {\r\n start: number;\r\n end: number;\r\n text: string;\r\n }\r\n\r\n /** \r\n * The general utility class.\r\n */\r\n export class Utility {\r\n private static TypeNamespace = 'http://schemas.microsoft.com/sqlbi/2013/01/NLRuntimeService';\r\n\r\n public static JsonContentType = 'application/json';\r\n public static JpegContentType = 'image/jpeg';\r\n public static XJavascriptContentType = 'application/x-javascript';\r\n public static JsonDataType = 'json';\r\n public static BlobDataType = 'blob';\r\n public static HttpGetMethod = 'GET';\r\n public static HttpPostMethod = 'POST';\r\n public static HttpPutMethod = 'PUT';\r\n public static HttpDeleteMethod = 'DELETE';\r\n public static HttpContentTypeHeader = 'Content-Type';\r\n public static HttpAcceptHeader = 'Accept';\r\n public static Undefined = 'undefined';\r\n\r\n private static staticContentLocation: string = window.location.protocol + '//' + window.location.host;\r\n \r\n /**\r\n * Ensures the specified value is not null or undefined. Throws a relevent exception if it is.\r\n * @param value The value to check.\r\n * @param context The context from which the check originated.\r\n * @param methodName The name of the method that initiated the check.\r\n * @param parameterName The parameter name of the value to check.\r\n */\r\n public static throwIfNullOrUndefined(value, context, methodName, parameterName) {\r\n if (value === null) {\r\n Utility.throwException(Errors.argumentNull(Utility.getComponentName(context) + methodName + '.' + parameterName));\r\n }\r\n else if (typeof (value) === Utility.Undefined) {\r\n Utility.throwException(Errors.argumentUndefined(Utility.getComponentName(context) + methodName + '.' + parameterName));\r\n }\r\n }\r\n\r\n /**\r\n * Ensures the specified value is not null, undefined or empty. Throws a relevent exception if it is.\r\n * @param value The value to check.\r\n * @param context The context from which the check originated.\r\n * @param methodName The name of the method that initiated the check.\r\n * @param parameterName The parameter name of the value to check.\r\n */\r\n public static throwIfNullOrEmpty(value: any, context: any, methodName: string, parameterName: string) {\r\n Utility.throwIfNullOrUndefined(value, context, methodName, parameterName);\r\n if (!value.length) {\r\n Utility.throwException(Errors.argumentOutOfRange(Utility.getComponentName(context) + methodName + '.' + parameterName));\r\n }\r\n }\r\n\r\n /**\r\n * Ensures the specified string is not null, undefined or empty. Throws a relevent exception if it is.\r\n * @param value The value to check.\r\n * @param context The context from which the check originated.\r\n * @param methodName The name of the method that initiated the check.\r\n * @param parameterName The parameter name of the value to check.\r\n */\r\n public static throwIfNullOrEmptyString(value: string, context: any, methodName: string, parameterName: string) {\r\n Utility.throwIfNullOrUndefined(value, context, methodName, parameterName);\r\n if (value.length < 1) {\r\n Utility.throwException(Errors.argumentOutOfRange(Utility.getComponentName(context) + methodName + '.' + parameterName));\r\n }\r\n }\r\n\r\n /**\r\n * Ensures the specified value is not null, undefined, whitespace or empty. Throws a relevent exception if it is.\r\n * @param value The value to check.\r\n * @param context The context from which the check originated.\r\n * @param methodName The name of the method that initiated the check.\r\n * @param parameterName The parameter name of the value to check.\r\n */\r\n public static throwIfNullEmptyOrWhitespaceString(value: string, context: any, methodName: string, parameterName: string) {\r\n Utility.throwIfNullOrUndefined(value, context, methodName, parameterName);\r\n if (StringExtensions.isNullOrUndefinedOrWhiteSpaceString(value)) {\r\n Utility.throwException(Errors.argumentOutOfRange(Utility.getComponentName(context) + methodName + '.' + parameterName));\r\n }\r\n }\r\n\r\n /**\r\n * Ensures the specified condition is true. Throws relevant exception if it isn't.\r\n * @param condition The condition to check.\r\n * @param context The context from which the check originated.\r\n * @param methodName The name of the method that initiated the check.\r\n * @param parameterName The parameter name against which the condition is checked.\r\n */\r\n public static throwIfNotTrue(condition: boolean, context: any, methodName: string, parameterName: string) {\r\n if (!condition) {\r\n Utility.throwException(Errors.argument(parameterName, Utility.getComponentName(context) + methodName + '.' + parameterName));\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether the provided value is a 'string'.\r\n * @param value The value to test.\r\n */\r\n public static isString(value: any): boolean {\r\n return ((typeof value) === 'string');\r\n }\r\n\r\n /**\r\n * Checks whether the provided value is a 'boolean'.\r\n * @param value The value to test.\r\n */\r\n public static isBoolean(value: any): boolean {\r\n return ((typeof value) === 'boolean');\r\n }\r\n\r\n /**\r\n * Checks whether the provided value is a 'number'.\r\n * @param value The value to test.\r\n */\r\n public static isNumber(value: any): boolean {\r\n return ((typeof value) === 'number');\r\n }\r\n\r\n /**\r\n * Checks whether the provided value is a Date instance.\r\n * @param value The value to test.\r\n */\r\n public static isDate(value: any): boolean {\r\n return Utility.isObject(value) && (value instanceof Date);\r\n }\r\n\r\n /**\r\n * Checks whether the provided value is an 'object'.\r\n * @param value The value to test.\r\n */\r\n public static isObject(value: any): boolean {\r\n return (value != null) && ((typeof value) === 'object');\r\n }\r\n\r\n /**\r\n * Checks whether the provided value is null or undefined.\r\n * @param value The value to test.\r\n */\r\n public static isNullOrUndefined(value: any): boolean {\r\n return (value === null) || (typeof (value) === Utility.Undefined);\r\n }\r\n\r\n /**\r\n * Combine a base url and a path.\r\n * @param baseUrl The base url.\r\n * @param path The path to add on to the base url.\r\n * @returns The combined url.\r\n */\r\n public static urlCombine(baseUrl: string, path: string) {\r\n Utility.throwIfNullOrUndefined(baseUrl, null, \"urlCombine\", \"baseUrl\");\r\n Utility.throwIfNullOrUndefined(path, null, \"urlCombine\", \"path\");\r\n\r\n // should any of the components be empty, fail gracefuly - this is important when using the test page\r\n if (StringExtensions.isNullOrUndefinedOrWhiteSpaceString(path)) {\r\n return baseUrl;\r\n }\r\n\r\n if (StringExtensions.isNullOrUndefinedOrWhiteSpaceString(baseUrl)) {\r\n return path;\r\n }\r\n\r\n let finalUrl = baseUrl;\r\n\r\n if (finalUrl.charAt(finalUrl.length - 1) === '/') {\r\n if (path.charAt(0) === '/')\r\n path = path.slice(1);\r\n } else {\r\n if (path.charAt(0) !== '/')\r\n path = '/' + path;\r\n }\r\n\r\n return finalUrl + path;\r\n }\r\n\r\n public static getAbsoluteUri(path: string): string {\r\n Utility.throwIfNullOrUndefined(path, null, \"getAbsoluteUri\", \"path\");\r\n\r\n let url = path;\r\n // Make absolute\r\n if (url && url.indexOf('http') === - 1) {\r\n url = Utility.urlCombine(clusterUri, url);\r\n }\r\n return url;\r\n }\r\n\r\n public static getStaticResourceUri(path: string) {\r\n Utility.throwIfNullOrUndefined(path, null, \"getStaticResourceUri\", \"path\");\r\n\r\n let url = path;\r\n // Make absolute\r\n if (url && url.indexOf('http') === - 1) {\r\n url = jsCommon.Utility.urlCombine(Utility.staticContentLocation, url);\r\n }\r\n return url;\r\n }\r\n\r\n public static getComponentName(context) {\r\n return !context ? '' : (typeof context).toString() + '.';\r\n }\r\n\r\n public static throwException(e) {\r\n Trace.error(\r\n StringExtensions.format(\"Throwing exception: {0}\", JSON.stringify(e)), \r\n /*includeStackTrace*/ e.stack != null ? false : true);\r\n throw e;\r\n }\r\n\r\n public static createClassSelector(className: string): string {\r\n Utility.throwIfNullOrEmptyString(className, null, 'CreateClassSelector', 'className');\r\n return '.' + className;\r\n }\r\n\r\n public static createIdSelector(id: string): string {\r\n Utility.throwIfNullOrEmptyString(id, null, 'CreateIdSelector', 'id');\r\n return '#' + id;\r\n }\r\n\r\n /**\r\n * Creates a client-side Guid string.\r\n * @returns A string representation of a Guid.\r\n */\r\n public static generateGuid(): string {\r\n let guid = \"\",\r\n idx = 0;\r\n\r\n for (idx = 0; idx < 32; idx += 1) {\r\n let guidDigitsItem = Math.random() * 16 | 0;\r\n switch (idx) {\r\n case 8:\r\n case 12:\r\n case 16:\r\n case 20:\r\n guid += \"-\";\r\n break;\r\n }\r\n guid += guidDigitsItem.toString(16);\r\n }\r\n\r\n return guid;\r\n }\r\n\r\n /**\r\n * Try extract a cookie from {@link document.cookie} identified by key.\r\n */\r\n public static getCookieValue(key: string): string {\r\n // the cookie is of the format <key1=value1>; <key2=value2>. Split by ';', then by '=' \r\n // to search for the key\r\n let keyValuePairs = document.cookie.split(';');\r\n for (let i = 0; i < keyValuePairs.length; i++) {\r\n let keyValue = keyValuePairs[i];\r\n let split = keyValue.split('=');\r\n if (split.length > 0 && split[0].trim() === key) {\r\n return keyValue.substr(keyValue.indexOf('=') + 1);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Extracts the protocol://hostname section of a url.\r\n * @param url The URL from which to extract the section.\r\n * @returns The protocol://hostname portion of the given URL.\r\n */\r\n public static getDomainForUrl(url: string): string {\r\n let hrefObject = Utility.getHrefObjectFromUrl(url);\r\n return hrefObject.prop('protocol') + '//' + hrefObject.prop('hostname');\r\n }\r\n\r\n /**\r\n * Extracts the hostname and absolute path sections of a url.\r\n * @param url The URL from which to extract the section.\r\n * @returns The hostname and absolute path portion of the given URL.\r\n */\r\n public static getHostNameForUrl(url: string): string {\r\n let hrefObject = Utility.getHrefObjectFromUrl(url);\r\n return Utility.urlCombine(hrefObject.prop('hostname'), hrefObject.prop('pathname'));\r\n }\r\n\r\n /**\r\n * Return the original url with query string stripped.\r\n * @param url The URL from which to extract the section.\r\n * @returns the original url with query string stripped.\r\n */\r\n public static getUrlWithoutQueryString(url: string): string {\r\n let hrefObject = Utility.getHrefObjectFromUrl(url);\r\n return hrefObject.prop('protocol') + '//' + Utility.urlCombine(hrefObject.prop('host'), hrefObject.prop('pathname'));\r\n }\r\n\r\n /**\r\n * Extracts the protocol section of a url.\r\n * @param url The URL from which to extract the section.\r\n * @returns The protocol for the current URL.\r\n */\r\n public static getProtocolFromUrl(url: string): string {\r\n return Utility.getHrefObjectFromUrl(url).prop('protocol').replace(':', '');\r\n }\r\n\r\n /**\r\n * Returns a formatted href object from a URL.\r\n * @param url The URL used to generate the object.\r\n * @returns A jQuery object with the url.\r\n */\r\n public static getHrefObjectFromUrl(url: string): JQuery {\r\n let aObject = $('<a>');\r\n aObject = aObject.prop('href', url);\r\n return aObject;\r\n }\r\n\r\n /**\r\n * Converts a WCF representation of a dictionary to a JavaScript dictionary.\r\n * @param wcfDictionary The WCF dictionary to convert.\r\n * @returns The native JavaScript representation of this dictionary.\r\n */\r\n public static convertWcfToJsDictionary(wcfDictionary: any[]): { [index: string]: any; } {\r\n // convert the WCF JSON representation of a dictionary\r\n // to JS dictionary.\r\n // WCF representation: [{\"Key\": Key, \"Value\": Value}..]\r\n // JS representation: [Key: Value ..]\r\n\r\n let result: { [index: string]: any; } = {};\r\n\r\n for (let i = 0; i < wcfDictionary.length; i++) {\r\n let keyValuePair = wcfDictionary[i];\r\n result[keyValuePair['Key']] = keyValuePair['Value'];\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public static getDateFromWcfJsonString(jsonDate: string, fromUtcMilliseconds: boolean): Date {\r\n if (StringExtensions.isNullOrEmpty(jsonDate)) {\r\n return null;\r\n }\r\n let begIndex = jsonDate.indexOf('(');\r\n let endIndex = jsonDate.indexOf(')');\r\n if (begIndex !== -1 && endIndex !== -1) {\r\n let milliseconds = parseInt(jsonDate.substring(begIndex + 1, endIndex), 10);\r\n\r\n if (fromUtcMilliseconds) {\r\n return new Date(milliseconds);\r\n }\r\n else {\r\n let retValue = new Date(0);\r\n retValue.setUTCMilliseconds(milliseconds);\r\n return retValue;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Get the outer html of the given jquery object.\r\n * @param content The jquery object.\r\n * @returns The entire html representation of the object.\r\n */\r\n public static getOuterHtml(content: JQuery): string {\r\n return $('<div>').append(content).html();\r\n }\r\n\r\n /**\r\n * Comparison Method: Compares two integer numbers.\r\n * @param a An integer value.\r\n * @param b An integer value.\r\n * @returns The comparison result.\r\n */\r\n public static compareInt(a: number, b: number): number {\r\n return a - b;\r\n }\r\n \r\n /**\r\n * Return the index of the smallest value in a numerical array.\r\n * @param a A numeric array.\r\n * @returns The index of the smallest value in the array.\r\n */\r\n public static getIndexOfMinValue(a: number[]) {\r\n let retValue = 0;\r\n let currentMinValue = a[0];\r\n\r\n for (let i = 0; i < a.length; i++) {\r\n if (a[i] < currentMinValue) {\r\n currentMinValue = a[i];\r\n retValue = i;\r\n }\r\n }\r\n\r\n return retValue;\r\n }\r\n \r\n /**\r\n * Extracts a url from a background image attribute in the format of: url('www.foobar.com/image.png').\r\n * @param input The value of the background-image attribute.\r\n * @returns The extracted url.\r\n */\r\n public static extractUrlFromCssBackgroundImage(input: string) {\r\n return input.replace(/\"/g, \"\").replace(/url\\(|\\)$/ig, \"\");\r\n }\r\n \r\n /**\r\n * Verifies image data url of images.\r\n */\r\n public static isValidImageDataUrl(url: string): boolean {\r\n let regex: RegExp = new RegExp('data:(image\\/(png|jpg|jpeg|gif|svg))');\r\n return regex.test(url);\r\n }\r\n \r\n public static isLocalUrl(url: string): boolean {\r\n return _.startsWith(url, \"data:\") || _.startsWith(url, \"blob:\");\r\n }\r\n\r\n /**\r\n * Downloads a content string as a file.\r\n * @param content Content stream.\r\n * @param fileName File name to use.\r\n */\r\n public static saveAsFile(content: any, fileName: string): void {\r\n let contentBlob = new Blob([content], { type: HttpConstants.ApplicationOctetStream });\r\n let url = window['webkitURL'] || URL;\r\n let urlLink = url.createObjectURL(contentBlob);\r\n let fileNameLink = fileName || urlLink;\r\n\r\n // IE support, use msSaveOrOpenBlob API\r\n if (window.navigator.msSaveOrOpenBlob) {\r\n window.navigator.msSaveOrOpenBlob(contentBlob, fileNameLink);\r\n return;\r\n }\r\n\r\n // WebKit-based browser support requires generating an anchor tag with\r\n // download attribute set to blob store and triggering a click event to invoke \r\n // a download to file action\r\n let hyperlink = document.createElement('a');\r\n hyperlink.href = urlLink;\r\n hyperlink.target = '_blank';\r\n hyperlink['download'] = fileNameLink;\r\n document.body.appendChild(hyperlink);\r\n hyperlink.click();\r\n\r\n document.body.removeChild(hyperlink);\r\n }\r\n\r\n /**\r\n * Helper method to get the simple type name from a typed object.\r\n * @param obj The typed object.\r\n * @returns The simple type name for the object.\r\n */\r\n public static getType(obj: TypedObject) {\r\n Utility.throwIfNullEmptyOrWhitespaceString(obj.__type, this, 'getType', 'obj');\r\n\r\n let parts = obj.__type.split(\":\");\r\n\r\n if (parts.length !== 2) {\r\n Errors.argument(\"obj.__type\", \"Type String not in expected format [Type]#[Namespace]: \" + obj.__type);\r\n }\r\n\r\n if (parts[1] !== Utility.TypeNamespace) {\r\n Errors.argument(\"obj.__type\", \"Type Namespace not expected: \" + parts[1]);\r\n }\r\n\r\n return parts[0];\r\n }\r\n\r\n /** \r\n * Check if an element supports a specific event type.\r\n * @param eventName The name of the event.\r\n * @param element The element to test for event support.\r\n * @returns Whether the even is supported on the provided element.\r\n */\r\n public static isEventSupported(eventName: string, element: Element): boolean {\r\n eventName = 'on' + eventName;\r\n let isSupported = (eventName in element);\r\n\r\n if (!isSupported) {\r\n // if we can't use setAttribute try a generic element\r\n if (!element.setAttribute) {\r\n element = document.createElement('div');\r\n }\r\n if (element.setAttribute && element.removeAttribute) {\r\n element.setAttribute(eventName, '');\r\n isSupported = typeof element[eventName] === 'function';\r\n\r\n // if the property was created - remove it\r\n if (typeof element[eventName] !== 'undefined') {\r\n element[eventName] = null;\r\n }\r\n\r\n element.removeAttribute(eventName);\r\n }\r\n }\r\n\r\n element = null;\r\n return isSupported;\r\n }\r\n\r\n public static toPixel(pixelAmount: number): string {\r\n Utility.throwIfNullOrUndefined(pixelAmount, this, \"toPixel\", \"pixelAmount\");\r\n\r\n return pixelAmount.toString() + CssConstants.pixelUnits;\r\n }\r\n\r\n public static getPropertyCount(object: any) {\r\n Utility.throwIfNullOrUndefined(object, this, \"getPropertyCount\", \"object\");\r\n return Object.getOwnPropertyNames(object).length;\r\n }\r\n\r\n /** \r\n * Check if an element supports a specific event type.\r\n * @param filePath File path.\r\n * @returns File extension.\r\n */\r\n public static getFileExtension(filePath: string): string {\r\n if (filePath) {\r\n let index = filePath.lastIndexOf('.');\r\n if (index >= 0)\r\n return filePath.substr(index + 1);\r\n }\r\n return '';\r\n }\r\n\r\n /** \r\n * Extract the filename out of a full path delimited by '\\' or '/'.\r\n * @param filePath File path.\r\n * @returns filename File name.\r\n */\r\n public static extractFileNameFromPath(filePath: string): string {\r\n return filePath.replace(/^.*[\\\\\\/]/, '');\r\n }\r\n\r\n /**\r\n * This method indicates whether window.clipboardData is supported.\r\n * For example, clipboard support for Windows Store apps is currently disabled \r\n * since window.clipboardData is unsupported (it raises access denied error)\r\n * since clipboard in Windows Store is being \r\n * achieved through Windows.ApplicationModel.DataTransfer.Clipboard class.\r\n */\r\n public static canUseClipboard(): boolean {\r\n return (typeof MSApp === \"undefined\");\r\n }\r\n\r\n public static is64BitOperatingSystem(): boolean {\r\n return navigator.userAgent.indexOf(\"WOW64\") !== -1 ||\r\n navigator.userAgent.indexOf(\"Win64\") !== -1;\r\n }\r\n\r\n public static parseNumber(value: any, defaultValue?: number): number {\r\n if (value === null)\r\n return null;\r\n if (value === undefined)\r\n return defaultValue;\r\n \r\n let result = Number(value);\r\n if (isFinite(result))\r\n return result;\r\n if (isNaN(result) && !(typeof value === \"number\" || value === \"NaN\"))\r\n return defaultValue;\r\n return result;\r\n }\r\n\r\n public static getURLParamValue(name:string) {\r\n let results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);\r\n if (results == null) {\r\n return null;\r\n }\r\n else {\r\n return results[1] || 0;\r\n }\r\n }\r\n\r\n /**\r\n * Return local timezone.\r\n * This function uses summer and winter offset to determine local time zone.\r\n * The result localTimeZoneString must be a subset of the strings used by server, \r\n * as documented here: https://msdn.microsoft.com/en-us/library/gg154758.aspx (Dynamic Daylight Savings Time (Compact 2013)).\r\n * @return Local timezone string or UTC if timezone cannot be found.\r\n */\r\n public static getLocalTimeZoneString(): string {\r\n let timeSummer = new Date(Date.UTC(2005, 6, 30, 0, 0, 0, 0));\r\n let summerOffset = -1 * timeSummer.getTimezoneOffset();\r\n let timeWinter = new Date(Date.UTC(2005, 12, 30, 0, 0, 0, 0));\r\n let winterOffset = -1 * timeWinter.getTimezoneOffset();\r\n let localTimeZoneString;\r\n\r\n if (-720 === summerOffset && -720 === winterOffset) { localTimeZoneString = 'Dateline Standard Time'; }\r\n else if (-660 === summerOffset && -660 === winterOffset) { localTimeZoneString = 'UTC-11'; }\r\n else if (-660 === summerOffset && -660 === winterOffset) { localTimeZoneString = 'Samoa Standard Time'; }\r\n else if (-600 === summerOffset && -600 === winterOffset) { localTimeZoneString = 'Hawaiian Standard Time'; }\r\n else if (-480 === summerOffset && -540 === winterOffset) { localTimeZoneString = 'Alaskan Standard Time'; }\r\n else if (-420 === summerOffset && -480 === winterOffset) { localTimeZoneString = 'Pacific Standard Time'; }\r\n else if (-420 === summerOffset && -420 === winterOffset) { localTimeZoneString = 'US Mountain Standard Time'; }\r\n else if (-360 === summerOffset && -420 === winterOffset) { localTimeZoneString = 'Mountain Standard Time'; }\r\n else if (-360 === summerOffset && -360 === winterOffset) { localTimeZoneString = 'Central America Standard Time'; }\r\n else if (-300 === summerOffset && -360 === winterOffset) { localTimeZoneString = 'Central Standard Time'; }\r\n else if (-300 === summerOffset && -300 === winterOffset) { localTimeZoneString = 'SA Pacific Standard Time'; }\r\n else if (-240 === summerOffset && -300 === winterOffset) { localTimeZoneString = 'Eastern Standard Time'; }\r\n else if (-270 === summerOffset && -270 === winterOffset) { localTimeZoneString = 'Venezuela Standard Time'; }\r\n else if (-240 === summerOffset && -240 === winterOffset) { localTimeZoneString = 'SA Western Standard Time'; }\r\n else if (-240 === summerOffset && -180 === winterOffset) { localTimeZoneString = 'Central Brazilian Standard Time'; }\r\n else if (-180 === summerOffset && -240 === winterOffset) { localTimeZoneString = 'Atlantic Standard Time'; }\r\n else if (-180 === summerOffset && -180 === winterOffset) { localTimeZoneString = 'Montevideo Standard Time'; }\r\n else if (-180 === summerOffset && -120 === winterOffset) { localTimeZoneString = 'E. South America Standard Time'; }\r\n else if (-150 === summerOffset && -210 === winterOffset) { localTimeZoneString = 'Mid-Atlantic Standard Time'; }\r\n else if (-120 === summerOffset && -120 === winterOffset) { localTimeZoneString = 'SA Eastern Standard Time'; }\r\n else if (0 === summerOffset && 0 === winterOffset) { localTimeZoneString = 'UTC'; }\r\n else if (60 === summerOffset && 0 === winterOffset) { localTimeZoneString = 'GMT Standard Time'; }\r\n else if (60 === summerOffset && 120 === winterOffset) { localTimeZoneString = 'Namibia Standard Time'; }\r\n else if (120 === summerOffset && 60 === winterOffset) { localTimeZoneString = 'Romance Standard Time'; }\r\n else if (120 === summerOffset && 120 === winterOffset) { localTimeZoneString = 'South Africa Standard Time'; }\r\n else if (180 === summerOffset && 120 === winterOffset) { localTimeZoneString = 'GTB Standard Time'; }\r\n else if (180 === summerOffset && 180 === winterOffset) { localTimeZoneString = 'E. Africa Standard Time'; }\r\n else if (240 === summerOffset && 180 === winterOffset) { localTimeZoneString = 'Russian Standard Time'; }\r\n else if (240 === summerOffset && 240 === winterOffset) { localTimeZoneString = 'Arabian Standard Time'; }\r\n else if (270 === summerOffset && 210 === winterOffset) { localTimeZoneString = 'Iran Standard Time'; }\r\n else if (270 === summerOffset && 270 === winterOffset) { localTimeZoneString = 'Afghanistan Standard Time'; }\r\n else if (300 === summerOffset && 240 === winterOffset) { localTimeZoneString = 'Pakistan Standard Time'; }\r\n else if (300 === summerOffset && 300 === winterOffset) { localTimeZoneString = 'West Asia Standard Time'; }\r\n else if (330 === summerOffset && 330 === winterOffset) { localTimeZoneString = 'India Standard Time'; }\r\n else if (345 === summerOffset && 345 === winterOffset) { localTimeZoneString = 'Nepal Standard Time'; }\r\n else if (360 === summerOffset && 300 === winterOffset) { localTimeZoneString = 'N. Central Asia Standard Time'; }\r\n else if (360 === summerOffset && 360 === winterOffset) { localTimeZoneString = 'Central Asia Standard Time'; }\r\n else if (390 === summerOffset && 390 === winterOffset) { localTimeZoneString = 'Myanmar Standard Time'; }\r\n else if (420 === summerOffset && 360 === winterOffset) { localTimeZoneString = 'North Asia Standard Time'; }\r\n else if (420 === summerOffset && 420 === winterOffset) { localTimeZoneString = 'SE Asia Standard Time'; }\r\n else if (480 === summerOffset && 420 === winterOffset) { localTimeZoneString = 'North Asia East Standard Time'; }\r\n else if (480 === summerOffset && 480 === winterOffset) { localTimeZoneString = 'China Standard Time'; }\r\n else if (540 === summerOffset && 480 === winterOffset) { localTimeZoneString = 'Yakutsk Standard Time'; }\r\n else if (540 === summerOffset && 540 === winterOffset) { localTimeZoneString = 'Tokyo Standard Time'; }\r\n else if (570 === summerOffset && 570 === winterOffset) { localTimeZoneString = 'Cen. Australia Standard Time'; }\r\n else if (600 === summerOffset && 600 === winterOffset) { localTimeZoneString = 'E. Australia Standard Time'; }\r\n else if (600 === summerOffset && 660 === winterOffset) { localTimeZoneString = 'AUS Eastern Standard Time'; }\r\n else if (660 === summerOffset && 600 === winterOffset) { localTimeZoneString = 'Tasmania Standard Time'; }\r\n else if (660 === summerOffset && 660 === winterOffset) { localTimeZoneString = 'West Pacific Standard Time'; }\r\n else if (690 === summerOffset && 690 === winterOffset) { localTimeZoneString = 'Central Pacific Standard Time'; }\r\n else if (720 === summerOffset && 660 === winterOffset) { localTimeZoneString = 'Magadan Standard Time'; }\r\n else if (720 === summerOffset && 720 === winterOffset) { localTimeZoneString = 'Fiji Standard Time'; }\r\n else if (720 === summerOffset && 780 === winterOffset) { localTimeZoneString = 'New Zealand Standard Time'; }\r\n else if (780 === summerOffset && 780 === winterOffset) { localTimeZoneString = 'Tonga Standard Time'; }\r\n else { localTimeZoneString = 'UTC'; }\r\n return localTimeZoneString;\r\n }\r\n }\r\n\r\n export class VersionUtility {\r\n /**\r\n * Compares 2 version strings.\r\n * @param versionA The first version string.\r\n * @param versionB The second version string.\r\n * @returns A result for the comparison.\r\n */\r\n static compareVersions(versionA: string, versionB: string): number {\r\n let a = versionA.split('.').map(parseFloat);\r\n let b = versionB.split('.').map(parseFloat);\r\n\r\n let versionParts = Math.max(a.length, b.length);\r\n\r\n for (let i = 0; i < versionParts; i++) {\r\n let partA = a[i] || 0;\r\n let partB = b[i] || 0;\r\n\r\n if (partA > partB)\r\n return 1;\r\n\r\n if (partA < partB)\r\n return -1;\r\n }\r\n\r\n return 0;\r\n }\r\n }\r\n\r\n export module PerformanceUtil {\r\n export class PerfMarker {\r\n private _name: string;\r\n private _start: string;\r\n\r\n constructor(name: string) {\r\n this._name = name;\r\n this._start = PerfMarker.begin(name);\r\n }\r\n\r\n private static begin(name: string) {\r\n if (window.performance === undefined || performance.mark === undefined) return;\r\n if (console.time) {\r\n console.time(name);\r\n }\r\n name = 'Begin ' + name;\r\n performance.mark(name);\r\n return name;\r\n }\r\n\r\n public end() {\r\n if (window.performance === undefined || performance.mark === undefined || performance.measure === undefined) return;\r\n let name = this._name;\r\n let end = 'End ' + name;\r\n performance.mark(end);\r\n performance.measure(name, this._start, end);\r\n if (console.timeEnd) {\r\n console.timeEnd(name);\r\n }\r\n }\r\n }\r\n\r\n export function create(name: string): PerfMarker {\r\n return new PerfMarker(name);\r\n }\r\n }\r\n\r\n export module DeferUtility {\r\n /**\r\n * Wraps a callback and returns a new function.\r\n * The function can be called many times but the callback\r\n * will only be executed once on the next frame.\r\n * Use this to throttle big UI updates and access to DOM.\r\n */\r\n export function deferUntilNextFrame(callback: Function): Function {\r\n let isWaiting, args, context;\r\n\r\n if (!window.requestAnimationFrame) {\r\n window.requestAnimationFrame = (func) => setTimeout(func, 1000 / 50);\r\n }\r\n\r\n return function() {\r\n if (!isWaiting) {\r\n isWaiting = true;\r\n args = arguments;\r\n context = this;\r\n window.requestAnimationFrame(() => {\r\n isWaiting = false;\r\n callback.apply(context, args);\r\n });\r\n }\r\n };\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n export class TraceItem {\r\n public type: TraceType;\r\n public sessionId: string;\r\n public requestId: string;\r\n public text: string;\r\n public timeStamp: Date;\r\n\r\n /** \r\n * Note: DO NOT USE for backward compability only.\r\n */\r\n public _activityId: string;\r\n\r\n private static traceTypeStrings: string[] = [\r\n 'INFORMATION',\r\n 'VERBOSE',\r\n 'WARNING',\r\n 'ERROR',\r\n 'EXPECTEDERROR',\r\n 'UNEXPECTEDERROR',\r\n 'FATAL',\r\n ];\r\n\r\n constructor(text: string, type: TraceType, sessionId: string, requestId?: string) {\r\n this.text = text;\r\n this.type = type;\r\n this.sessionId = sessionId;\r\n this.requestId = requestId;\r\n this.timeStamp = new Date();\r\n }\r\n\r\n public toString(): string {\r\n let resultString: string = '';\r\n\r\n resultString += (StringExtensions.format(\r\n '{0} ({1}): {2}',\r\n TraceItem.traceTypeStrings[this.type],\r\n this.timeStamp.toUTCString(),\r\n this.text));\r\n\r\n if (this.requestId)\r\n resultString += ('\\n(Request id: ' + this.requestId + ')');\r\n\r\n return resultString;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n\r\n export module UrlUtils {\r\n const urlRegex = /http[s]?:\\/\\/(\\S)+/gi;\r\n\r\n export function isValidUrl(value: string): boolean {\r\n if (StringExtensions.isNullOrEmpty(value))\r\n return false;\r\n\r\n let match = RegExpExtensions.run(urlRegex, value);\r\n if (!!match && match.index === 0)\r\n return true;\r\n\r\n return false;\r\n }\r\n\r\n /* Tests whether a URL is valid.\r\n * @param url The url to be tested.\r\n * @returns Whether the provided url is valid.\r\n **/\r\n export function isValidImageUrl(url: string): boolean {\r\n // VSTS: 7252099 / 7112236\r\n // For now, passes for any valid Url\r\n\r\n return isValidUrl(url);\r\n }\r\n\r\n export function findAllValidUrls(text: string): TextMatch[] {\r\n if (StringExtensions.isNullOrEmpty(text))\r\n return [];\r\n\r\n // Find all urls in the text.\r\n // TODO: This could potentially be expensive, maybe include a cap here for text with many urls?\r\n let urlRanges: TextMatch[] = [];\r\n let matches: RegExpExecArray;\r\n let start = 0;\r\n while ((matches = RegExpExtensions.run(urlRegex, text, start)) !== null) {\r\n let url = matches[0];\r\n let end = matches.index + url.length;\r\n urlRanges.push({\r\n start: matches.index,\r\n end: end,\r\n text: url,\r\n });\r\n start = end;\r\n }\r\n\r\n return urlRanges;\r\n }\r\n\r\n export function getBase64ContentFromDataUri(uri: string): string {\r\n if (uri.indexOf('data:') !== 0)\r\n throw new Error(\"Expected data uri\");\r\n\r\n // Locate the base 64 content from the URL (e.g. \"data:image/png;base64,xxxxx=\")\r\n const base64Token = \";base64,\";\r\n let indexBase64TokenStart = uri.indexOf(base64Token);\r\n if (indexBase64TokenStart < 0)\r\n throw new Error(\"Expected base 64 content in data url\");\r\n\r\n let indexBase64Start = indexBase64TokenStart + base64Token.length;\r\n return uri.substr(indexBase64Start, uri.length - indexBase64Start);\r\n }\r\n\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n export module BrowserUtils {\r\n export function isChrome(): boolean {\r\n let vendorName = window.navigator.vendor || \"\";\r\n let userAgent = window.navigator.userAgent.toLowerCase();\r\n\r\n return vendorName.toLowerCase().indexOf('google') > -1 &&\r\n userAgent.indexOf('chrome') > -1 &&\r\n userAgent.indexOf('edge') === -1 &&\r\n userAgent.indexOf('opr') === -1;\r\n }\r\n\r\n export function isInternetExplorerOrEdge(): boolean {\r\n let userAgent = window.navigator.userAgent.toLowerCase();\r\n return userAgent.indexOf('msie') > -1\r\n || userAgent.indexOf('trident') > -1\r\n || userAgent.indexOf('edge') > -1;\r\n }\r\n \r\n /**\r\n * Get the current version of IE\r\n * @returns The version of Internet Explorer or a 0 (indicating the use of another browser).\r\n */\r\n export function getInternetExplorerVersion(): number {\r\n var retValue = 0;\r\n if (navigator.appName === 'Microsoft Internet Explorer' || window.navigator.userAgent.indexOf('MSIE') >= 0) {\r\n var re = new RegExp('MSIE ([0-9]{1,}[\\\\.0-9]{0,})');\r\n var result = re.exec(window.navigator.userAgent);\r\n if (result) {\r\n retValue = parseFloat(result[1]);\r\n }\r\n }\r\n\r\n return retValue;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n // NOTE: this file includes standalone utilities that should have no dependencies on external libraries, including jQuery.\r\n\r\n /**\r\n * Interface to help define objects indexed by number to a particular type.\r\n */\r\n export interface INumberDictionary<T> {\r\n [key: number]: T;\r\n }\r\n\r\n /**\r\n * Interface to help define objects indexed by name to a particular type.\r\n */\r\n export interface IStringDictionary<T> {\r\n [key: string]: T;\r\n }\r\n\r\n /**\r\n * Extensions for Enumerations.\r\n */\r\n export module EnumExtensions {\r\n /**\r\n * Gets a value indicating whether the value has the bit flags set.\r\n */\r\n export function hasFlag(value: number, flag: number): boolean {\r\n debug.assert(!!flag, 'flag must be specified and nonzero.');\r\n\r\n return (value & flag) === flag;\r\n }\r\n\r\n /**\r\n * Sets a value of a flag without modifying any other flags.\r\n */ \r\n export function setFlag(value: number, flag: number): number {\r\n debug.assert(!!flag, \"flag must be specified and nonzero.\");\r\n return value |= flag;\r\n }\r\n\r\n /**\r\n * Resets a value of a flag without modifying any other flags.\r\n */ \r\n export function resetFlag(value: number, flag: number): number {\r\n debug.assert(!!flag, \"flag must be specified and nonzero.\");\r\n return value &= ~flag;\r\n }\r\n\r\n /**\r\n * According to the TypeScript Handbook, this is safe to do.\r\n */\r\n export function toString(enumType: any, value: number): string {\r\n return enumType[value];\r\n }\r\n }\r\n\r\n /**\r\n * Extensions to String class.\r\n */\r\n export module StringExtensions {\r\n /**\r\n * Checks if a string ends with a sub-string.\r\n */\r\n export function endsWith(str: string, suffix: string): boolean {\r\n debug.assertValue(str, 'str');\r\n debug.assertValue(suffix, 'suffix');\r\n\r\n return str.indexOf(suffix, str.length - suffix.length) !== -1;\r\n }\r\n }\r\n\r\n export module LogicExtensions {\r\n export function XOR(a: boolean, b: boolean): boolean {\r\n return (a || b) && !(a && b);\r\n }\r\n }\r\n\r\n export module JsonComparer {\r\n /**\r\n * Performs JSON-style comparison of two objects.\r\n */\r\n export function equals<T>(x: T, y: T): boolean {\r\n if (x === y)\r\n return true;\r\n\r\n return JSON.stringify(x) === JSON.stringify(y);\r\n }\r\n }\r\n\r\n /**\r\n * Values are in terms of 'pt'\r\n * Convert to pixels using PixelConverter.fromPoint\r\n */\r\n export module TextSizeDefaults {\r\n /**\r\n * Stored in terms of 'pt'\r\n * Convert to pixels using PixelConverter.fromPoint\r\n */\r\n export const TextSizeMin: number = 8;\r\n\r\n /**\r\n * Stored in terms of 'pt'\r\n * Convert to pixels using PixelConverter.fromPoint\r\n */\r\n export const TextSizeMax: number = 40;\r\n\r\n const TextSizeRange: number = TextSizeMax - TextSizeMin;\r\n\r\n /**\r\n * Returns the percentage of this value relative to the TextSizeMax\r\n * @param textSize - should be given in terms of 'pt'\r\n */\r\n export function getScale(textSize: number) {\r\n return (textSize - TextSizeMin) / TextSizeRange;\r\n }\r\n\r\n }\r\n\r\n export module PixelConverter {\r\n const PxPtRatio: number = 4 / 3;\r\n const PixelString: string = 'px';\r\n\r\n /**\r\n * Appends 'px' to the end of number value for use as pixel string in styles\r\n */\r\n export function toString(px: number): string {\r\n return px + PixelString;\r\n }\r\n\r\n /**\r\n * Converts point value (pt) to pixels\r\n * Returns a string for font-size property\r\n * e.g. fromPoint(8) => '24px'\r\n */\r\n export function fromPoint(pt: number): string {\r\n return toString(fromPointToPixel(pt));\r\n }\r\n\r\n /**\r\n * Converts point value (pt) to pixels\r\n * Returns a number for font-size property\r\n * e.g. fromPoint(8) => 24px\r\n */\r\n export function fromPointToPixel(pt: number): number {\r\n return (PxPtRatio * pt);\r\n }\r\n\r\n /**\r\n * Converts pixel value (px) to pt\r\n * e.g. toPoint(24) => 8\r\n */\r\n export function toPoint(px: number): number {\r\n return px / PxPtRatio;\r\n }\r\n }\r\n\r\n export module RegExpExtensions {\r\n /**\r\n * Runs exec on regex starting from 0 index\r\n * This is the expected behavior but RegExp actually remember\r\n * the last index they stopped at (found match at) and will\r\n * return unexpected results when run in sequence.\r\n * @param regex - regular expression object\r\n * @param value - string to search wiht regex\r\n * @param start - index within value to start regex\r\n */\r\n export function run(regex: RegExp, value: string, start?: number): RegExpExecArray {\r\n debug.assertValue(regex, 'regex');\r\n\r\n regex.lastIndex = start || 0;\r\n return regex.exec(value);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.utility {\r\n import ExtendedCSSProperties = jsCommon.ExtendedCSSProperties;\r\n import IThickness = powerbi.visuals.shapes.IThickness;\r\n\r\n export module StyleUtils {\r\n export function getRotateAngleFromElement(element: JQuery): number {\r\n let rawElemStyle = <ExtendedCSSProperties>element.get(0).style;\r\n\r\n let transformString = rawElemStyle.transform || rawElemStyle.webkitTransform;\r\n if (transformString) {\r\n let transform = transformString.match(/rotate\\((-?\\d+(?:\\.\\d*)?)deg\\)/);\r\n if (transform) {\r\n return parseFloat(transform[1]);\r\n }\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n export function getTranslateTransformFromElement(element: JQuery): IPoint {\r\n let rawElemStyle = <ExtendedCSSProperties>element.get(0).style;\r\n \r\n // IE will recognize \"webkitTransform\" as \"WebkitTransform\" and set that as style property. \r\n // This means transform property is not read.\r\n // We put the \"transform\" before the \"webkitTransform\" to counteract the weirdness of IE. \r\n let transformString = rawElemStyle.transform || rawElemStyle.webkitTransform;\r\n\r\n let retValue: IPoint = { x: 0, y: 0 };\r\n\r\n if (transformString && transformString.length > 0) {\r\n let transform = transformString.match(/translate\\((-?\\d+(?:\\.\\d*)?)px, (-?\\d+(?:\\.\\d*)?)px\\)/);\r\n if (transform) {\r\n retValue.x = parseFloat(transform[1]);\r\n retValue.y = parseFloat(transform[2]);\r\n }\r\n }\r\n\r\n return retValue;\r\n }\r\n\r\n export function getPadding(element: JQuery): IThickness {\r\n if (!element)\r\n return;\r\n\r\n return {\r\n left: parseFloat(element.css('padding-left')) || 0,\r\n right: parseFloat(element.css('padding-right')) || 0,\r\n top: parseFloat(element.css('padding-top')) || 0,\r\n bottom: parseFloat(element.css('padding-bottom')) || 0,\r\n };\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n export interface ITraceListener {\r\n logTrace(trace: TraceItem): void;\r\n }\r\n\r\n export class ConsoleTracer implements ITraceListener {\r\n public logTrace(trace: TraceItem): void {\r\n if (DEBUG) {\r\n switch (trace.type) {\r\n case TraceType.Information:\r\n console.info(trace.toString());\r\n break;\r\n case TraceType.UnexpectedError:\r\n case TraceType.Error:\r\n case TraceType.Fatal:\r\n console.error(trace.toString());\r\n break;\r\n case TraceType.ExpectedError:\r\n case TraceType.Warning:\r\n console.warn(trace.toString());\r\n break;\r\n case TraceType.Verbose:\r\n console.log(trace.toString());\r\n break;\r\n default:\r\n console.log(trace.toString());\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n export module Trace {\r\n const traceMaxCount = 1000;\r\n let traces = new Array<TraceItem>(traceMaxCount);\r\n let lastTraceIndex: number = -1;\r\n let defaultListener = new ConsoleTracer();\r\n let listeners = new Array<ITraceListener>(defaultListener);\r\n\r\n /**\r\n * Trace a warning. Please ensure that no PII is being logged.\r\n */\r\n export function warning(text: string, requestId?: string): void {\r\n debug.assertValue(text, 'text');\r\n logTraceInternal(new TraceItem(text, TraceType.Warning, requestId));\r\n }\r\n\r\n /** \r\n * Trace an error. Please ensure that no PII is being logged.\r\n */\r\n export function error(text: string, includeStackTrace?: boolean, requestId?: string): void {\r\n debug.assertValue(text, 'text');\r\n if (includeStackTrace)\r\n text = StringExtensions.format(\"{0}.\\nStack:\\n{1}\", text, getStackTrace());\r\n logTraceInternal(new TraceItem(text, TraceType.Error, requestId));\r\n }\r\n\r\n /** \r\n * Trace an information. Please ensure that no PII is being logged.\r\n */\r\n export function verbose(text: string, requestId?: string): void {\r\n debug.assertValue(text, 'text');\r\n logTraceInternal(new TraceItem(text, TraceType.Verbose, requestId));\r\n }\r\n\r\n export function addListener(listener: ITraceListener): void {\r\n debug.assertValue(listener, 'listener');\r\n listeners.push(listener);\r\n }\r\n\r\n export function removeListener(listener: ITraceListener): void {\r\n debug.assertValue(listener, 'listener');\r\n\r\n let index = listeners.indexOf(listener);\r\n if (index >= 0)\r\n listeners.splice(index, 1);\r\n }\r\n\r\n export function resetListeners(): void {\r\n listeners = new Array<ITraceListener>(defaultListener);\r\n }\r\n\r\n export function reset(): void {\r\n lastTraceIndex = -1;\r\n }\r\n\r\n export function getTraces(): Array<TraceItem> {\r\n if (lastTraceIndex < 0)\r\n return;\r\n\r\n let result = new Array<TraceItem>(lastTraceIndex+1);\r\n for (let i = 0; i <= lastTraceIndex; i++)\r\n result[i] = traces[i];\r\n\r\n return result;\r\n }\r\n\r\n /** \r\n * Note: Used for unit-test only. \r\n */\r\n export function disableDefaultListener(): void {\r\n removeListener(defaultListener);\r\n }\r\n\r\n export function enableDefaultListener(): void {\r\n addListener(defaultListener);\r\n }\r\n\r\n function logTraceInternal(trace: TraceItem): void {\r\n if ((lastTraceIndex + 1) >= traceMaxCount)\r\n reset();\r\n\r\n traces[++lastTraceIndex] = trace;\r\n\r\n for (let i = 0, len = listeners.length; i < len; i++)\r\n listeners[i].logTrace(trace);\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n /** \r\n * The types of possible traces within the system, this aligns to the traces available in Cloud Platform.\r\n */\r\n export enum TraceType {\r\n Information = 0,\r\n Verbose = 1,\r\n Warning = 2,\r\n Error = 3,\r\n ExpectedError = 4,\r\n UnexpectedError = 5,\r\n Fatal = 6,\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule jsCommon {\r\n /**\r\n * JavaScript files.\r\n */ \r\n const MSMapcontrol = 'https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&s=1&onscriptload=globalMapControlLoaded';\r\n\r\n /**\r\n * Map loading logic.\r\n */\r\n let MSMapcontrolLoaded = false;\r\n let WaitForMSMapLoad: JQueryDeferred<void> = null;\r\n\r\n const PowerViewPackage: IDependency = {\r\n javaScriptFiles: [\r\n powerbi.build + '/externals/pv/webclient.js'\r\n ],\r\n cssFiles: [\r\n powerbi.build +'/externals/pv/Styles/_all.css'\r\n ],\r\n\t\tjavaScriptFilesWithCallback: [\r\n { javascriptFile: MSMapcontrol, onLoadCallback: waitForMapControlLoaded }\r\n ]\r\n };\r\n\r\n export function ensurePowerView(action: () => void = _.noop): void {\r\n requires(PowerViewPackage, action);\r\n }\r\n\r\n const MapPackage: IDependency = {\r\n\t\tjavaScriptFilesWithCallback: [\r\n { javascriptFile: MSMapcontrol, onLoadCallback: waitForMapControlLoaded }\r\n ]\r\n };\r\n\r\n export function ensureMap(locale: string, action: () => void): void {\r\n let mapPackageWithLocale = powerbi.Prototype.inherit(MapPackage);\r\n if (!_.isEmpty(locale)) {\r\n mapPackageWithLocale.javaScriptFilesWithCallback[0].javascriptFile = MSMapcontrol.concat('&mkt=' + locale);\r\n }\r\n requires(mapPackageWithLocale, action);\r\n }\r\n\r\n\texport function mapControlLoaded(): void {\r\n\t\tMSMapcontrolLoaded = true;\r\n\t\tif (WaitForMSMapLoad) {\r\n\t\t\tWaitForMSMapLoad.resolve();\r\n WaitForMSMapLoad = undefined;\r\n\t\t}\r\n\t}\r\n\r\n\texport function waitForMapControlLoaded(): JQueryPromise<void> {\r\n\t\tlet task: JQueryDeferred<void>;\r\n\t\tif (!MSMapcontrolLoaded) {\r\n\t\t\ttask = WaitForMSMapLoad = $.Deferred<void>();\r\n\t\t} else {\r\n\t\t\ttask = $.Deferred<void>();\r\n\t\t\ttask.resolve();\r\n\t\t}\r\n\r\n\t\treturn task.promise();\r\n\t}\r\n}\r\n\r\n/* tslint:disable:no-unused-variable */\r\nlet globalMapControlLoaded = function() {\r\n\t// Map requires a function in the global namespace to callback once loaded\r\n\tjsCommon.mapControlLoaded();\r\n};\r\n/* tslint:enable:no-unused-variable */","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule InJs\r\n{\r\n /** \r\n * The types of possible traces within the system, this aligns to the traces available in Cloud Platform.\r\n */\r\n export enum TraceType {\r\n information = 0,\r\n verbose = 1,\r\n warning = 2,\r\n error = 3,\r\n expectedError = 4,\r\n unexpectedError = 5,\r\n fatal = 6,\r\n }\r\n}","var __extends = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n};\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n///<reference path=\"../../Typedefs/jquery/jquery.d.ts\"/>\n///<reference path=\"../../Typedefs/globalize/globalize.d.ts\"/>\n///<reference path=\"../../Typedefs/lodash/lodash.d.ts\"/>\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n /** Default IQueryExprVisitorWithArg implementation that others may derive from. */\n var DefaultSQExprVisitorWithArg = (function () {\n function DefaultSQExprVisitorWithArg() {\n }\n DefaultSQExprVisitorWithArg.prototype.visitEntity = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitColumnRef = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitMeasureRef = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitAggr = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitPercentile = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitHierarchy = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitHierarchyLevel = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitPropertyVariationSource = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitSelectRef = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitBetween = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitIn = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitAnd = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitOr = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitCompare = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitContains = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitExists = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitNot = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitStartsWith = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitConstant = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitDateSpan = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitDateAdd = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitNow = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitDefaultValue = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitAnyValue = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitArithmetic = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitFillRule = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitResourcePackageItem = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitScopedEval = function (expr, arg) {\n return this.visitDefault(expr, arg);\n };\n DefaultSQExprVisitorWithArg.prototype.visitDefault = function (expr, arg) {\n return;\n };\n return DefaultSQExprVisitorWithArg;\n }());\n data.DefaultSQExprVisitorWithArg = DefaultSQExprVisitorWithArg;\n /** Default ISQExprVisitor implementation that others may derive from. */\n var DefaultSQExprVisitor = (function (_super) {\n __extends(DefaultSQExprVisitor, _super);\n function DefaultSQExprVisitor() {\n _super.apply(this, arguments);\n }\n return DefaultSQExprVisitor;\n }(DefaultSQExprVisitorWithArg));\n data.DefaultSQExprVisitor = DefaultSQExprVisitor;\n /** Default ISQExprVisitor implementation that implements default traversal and that others may derive from. */\n var DefaultSQExprVisitorWithTraversal = (function () {\n function DefaultSQExprVisitorWithTraversal() {\n }\n DefaultSQExprVisitorWithTraversal.prototype.visitEntity = function (expr) {\n this.visitDefault(expr);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitColumnRef = function (expr) {\n expr.source.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitMeasureRef = function (expr) {\n expr.source.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitAggr = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitPercentile = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitHierarchy = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitHierarchyLevel = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitPropertyVariationSource = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitSelectRef = function (expr) {\n this.visitDefault(expr);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitBetween = function (expr) {\n expr.arg.accept(this);\n expr.lower.accept(this);\n expr.upper.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitIn = function (expr) {\n var args = expr.args;\n for (var i = 0, len = args.length; i < len; i++)\n args[i].accept(this);\n var values = expr.values;\n for (var i = 0, len = values.length; i < len; i++) {\n var valueTuple = values[i];\n for (var j = 0, jlen = valueTuple.length; j < jlen; j++)\n valueTuple[j].accept(this);\n }\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitAnd = function (expr) {\n expr.left.accept(this);\n expr.right.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitOr = function (expr) {\n expr.left.accept(this);\n expr.right.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitCompare = function (expr) {\n expr.left.accept(this);\n expr.right.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitContains = function (expr) {\n expr.left.accept(this);\n expr.right.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitExists = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitNot = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitStartsWith = function (expr) {\n expr.left.accept(this);\n expr.right.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitConstant = function (expr) {\n this.visitDefault(expr);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitDateSpan = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitDateAdd = function (expr) {\n expr.arg.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitNow = function (expr) {\n this.visitDefault(expr);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitDefaultValue = function (expr) {\n this.visitDefault(expr);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitAnyValue = function (expr) {\n this.visitDefault(expr);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitArithmetic = function (expr) {\n expr.left.accept(this);\n expr.right.accept(this);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitFillRule = function (expr) {\n expr.input.accept(this);\n var rule = expr.rule, gradient2 = rule.linearGradient2, gradient3 = rule.linearGradient3;\n if (gradient2) {\n this.visitLinearGradient2(gradient2);\n }\n if (gradient3) {\n this.visitLinearGradient3(gradient3);\n }\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitLinearGradient2 = function (gradient2) {\n debug.assertValue(gradient2, 'gradient2');\n this.visitFillRuleStop(gradient2.min);\n this.visitFillRuleStop(gradient2.max);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitLinearGradient3 = function (gradient3) {\n debug.assertValue(gradient3, 'gradient3');\n this.visitFillRuleStop(gradient3.min);\n this.visitFillRuleStop(gradient3.mid);\n this.visitFillRuleStop(gradient3.max);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitResourcePackageItem = function (expr) {\n this.visitDefault(expr);\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitScopedEval = function (expr) {\n expr.expression.accept(this);\n for (var _i = 0, _a = expr.scope; _i < _a.length; _i++) {\n var scopeExpr = _a[_i];\n scopeExpr.accept(this);\n }\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitDefault = function (expr) {\n return;\n };\n DefaultSQExprVisitorWithTraversal.prototype.visitFillRuleStop = function (stop) {\n debug.assertValue(stop, 'stop');\n stop.color.accept(this);\n var value = stop.value;\n if (value)\n value.accept(this);\n };\n return DefaultSQExprVisitorWithTraversal;\n }());\n data.DefaultSQExprVisitorWithTraversal = DefaultSQExprVisitorWithTraversal;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n function createEnumType(members) {\n return new EnumType(members);\n }\n powerbi.createEnumType = createEnumType;\n var EnumType = (function () {\n function EnumType(allMembers) {\n debug.assertValue(allMembers, 'allMembers');\n this.allMembers = allMembers;\n }\n EnumType.prototype.members = function (validMembers) {\n var allMembers = this.allMembers;\n if (!validMembers)\n return allMembers;\n var membersToReturn = [];\n for (var _i = 0, allMembers_1 = allMembers; _i < allMembers_1.length; _i++) {\n var member = allMembers_1[_i];\n if (_.contains(validMembers, member.value))\n membersToReturn.push(member);\n }\n return membersToReturn;\n };\n return EnumType;\n }());\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var FillSolidColorTypeDescriptor;\n (function (FillSolidColorTypeDescriptor) {\n /** Gets a value indicating whether the descriptor is nullable or not. */\n function nullable(descriptor) {\n debug.assertValue(descriptor, 'descriptor');\n if (descriptor === true)\n return false;\n var advancedDescriptor = descriptor;\n return !!advancedDescriptor.nullable;\n }\n FillSolidColorTypeDescriptor.nullable = nullable;\n })(FillSolidColorTypeDescriptor = powerbi.FillSolidColorTypeDescriptor || (powerbi.FillSolidColorTypeDescriptor = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var ImageDefinition;\n (function (ImageDefinition) {\n ImageDefinition.urlType = { misc: { imageUrl: true } };\n })(ImageDefinition = powerbi.ImageDefinition || (powerbi.ImageDefinition = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var StructuralTypeDescriptor;\n (function (StructuralTypeDescriptor) {\n function isValid(type) {\n debug.assertValue(type, 'type');\n if (type.fill ||\n type.fillRule ||\n type.filter ||\n type.expression ||\n type.image ||\n type.paragraphs) {\n return true;\n }\n return false;\n }\n StructuralTypeDescriptor.isValid = isValid;\n })(StructuralTypeDescriptor = powerbi.StructuralTypeDescriptor || (powerbi.StructuralTypeDescriptor = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var EnumExtensions = jsCommon.EnumExtensions;\n /** Describes a data value type, including a primitive type and extended type if any (derived from data category). */\n var ValueType = (function () {\n /** Do not call the ValueType constructor directly. Use the ValueType.fromXXX methods. */\n function ValueType(type, category, enumType) {\n debug.assert((!!type && ExtendedType[type] != null) || type === ExtendedType.Null, 'type');\n debug.assert(!!category || category === null, 'category');\n debug.assert(type !== ExtendedType.Enumeration || !!enumType, 'enumType');\n this.underlyingType = type;\n this.category = category;\n if (EnumExtensions.hasFlag(type, ExtendedType.Temporal)) {\n this.temporalType = new TemporalType(type);\n }\n if (EnumExtensions.hasFlag(type, ExtendedType.Geography)) {\n this.geographyType = new GeographyType(type);\n }\n if (EnumExtensions.hasFlag(type, ExtendedType.Miscellaneous)) {\n this.miscType = new MiscellaneousType(type);\n }\n if (EnumExtensions.hasFlag(type, ExtendedType.Formatting)) {\n this.formattingType = new FormattingType(type);\n }\n if (EnumExtensions.hasFlag(type, ExtendedType.Enumeration)) {\n this.enumType = enumType;\n }\n if (EnumExtensions.hasFlag(type, ExtendedType.Scripting)) {\n this.scriptingType = new ScriptType(type);\n }\n }\n /** Creates or retrieves a ValueType object based on the specified ValueTypeDescriptor. */\n ValueType.fromDescriptor = function (descriptor) {\n descriptor = descriptor || {};\n // Simplified primitive types\n if (descriptor.text)\n return ValueType.fromExtendedType(ExtendedType.Text);\n if (descriptor.integer)\n return ValueType.fromExtendedType(ExtendedType.Integer);\n if (descriptor.numeric)\n return ValueType.fromExtendedType(ExtendedType.Double);\n if (descriptor.bool)\n return ValueType.fromExtendedType(ExtendedType.Boolean);\n if (descriptor.dateTime)\n return ValueType.fromExtendedType(ExtendedType.DateTime);\n if (descriptor.duration)\n return ValueType.fromExtendedType(ExtendedType.Duration);\n if (descriptor.binary)\n return ValueType.fromExtendedType(ExtendedType.Binary);\n if (descriptor.none)\n return ValueType.fromExtendedType(ExtendedType.None);\n // Extended types\n if (descriptor.scripting) {\n if (descriptor.scripting.source)\n return ValueType.fromExtendedType(ExtendedType.ScriptSource);\n }\n if (descriptor.enumeration)\n return ValueType.fromEnum(descriptor.enumeration);\n if (descriptor.temporal) {\n if (descriptor.temporal.year)\n return ValueType.fromExtendedType(ExtendedType.Year_Integer);\n if (descriptor.temporal.month)\n return ValueType.fromExtendedType(ExtendedType.Month_Integer);\n }\n if (descriptor.geography) {\n if (descriptor.geography.address)\n return ValueType.fromExtendedType(ExtendedType.Address);\n if (descriptor.geography.city)\n return ValueType.fromExtendedType(ExtendedType.City);\n if (descriptor.geography.continent)\n return ValueType.fromExtendedType(ExtendedType.Continent);\n if (descriptor.geography.country)\n return ValueType.fromExtendedType(ExtendedType.Country);\n if (descriptor.geography.county)\n return ValueType.fromExtendedType(ExtendedType.County);\n if (descriptor.geography.region)\n return ValueType.fromExtendedType(ExtendedType.Region);\n if (descriptor.geography.postalCode)\n return ValueType.fromExtendedType(ExtendedType.PostalCode_Text);\n if (descriptor.geography.stateOrProvince)\n return ValueType.fromExtendedType(ExtendedType.StateOrProvince);\n if (descriptor.geography.place)\n return ValueType.fromExtendedType(ExtendedType.Place);\n if (descriptor.geography.latitude)\n return ValueType.fromExtendedType(ExtendedType.Latitude_Double);\n if (descriptor.geography.longitude)\n return ValueType.fromExtendedType(ExtendedType.Longitude_Double);\n }\n if (descriptor.misc) {\n if (descriptor.misc.image)\n return ValueType.fromExtendedType(ExtendedType.Image);\n if (descriptor.misc.imageUrl)\n return ValueType.fromExtendedType(ExtendedType.ImageUrl);\n if (descriptor.misc.webUrl)\n return ValueType.fromExtendedType(ExtendedType.WebUrl);\n if (descriptor.misc.barcode)\n return ValueType.fromExtendedType(ExtendedType.Barcode_Text);\n }\n if (descriptor.formatting) {\n if (descriptor.formatting.color)\n return ValueType.fromExtendedType(ExtendedType.Color);\n if (descriptor.formatting.formatString)\n return ValueType.fromExtendedType(ExtendedType.FormatString);\n if (descriptor.formatting.alignment)\n return ValueType.fromExtendedType(ExtendedType.Alignment);\n if (descriptor.formatting.labelDisplayUnits)\n return ValueType.fromExtendedType(ExtendedType.LabelDisplayUnits);\n if (descriptor.formatting.fontSize)\n return ValueType.fromExtendedType(ExtendedType.FontSize);\n if (descriptor.formatting.labelDensity)\n return ValueType.fromExtendedType(ExtendedType.LabelDensity);\n }\n if (descriptor.extendedType) {\n return ValueType.fromExtendedType(descriptor.extendedType);\n }\n return ValueType.fromExtendedType(ExtendedType.Null);\n };\n /** Advanced: Generally use fromDescriptor instead. Creates or retrieves a ValueType object for the specified ExtendedType. */\n ValueType.fromExtendedType = function (extendedType) {\n extendedType = extendedType || ExtendedType.Null;\n var primitiveType = getPrimitiveType(extendedType), category = getCategoryFromExtendedType(extendedType);\n debug.assert(primitiveType !== PrimitiveType.Null || extendedType === ExtendedType.Null, 'Cannot create ValueType for abstract extended type. Consider using fromDescriptor instead.');\n return ValueType.fromPrimitiveTypeAndCategory(primitiveType, category);\n };\n /** Creates or retrieves a ValueType object for the specified PrimitiveType and data category. */\n ValueType.fromPrimitiveTypeAndCategory = function (primitiveType, category) {\n primitiveType = primitiveType || PrimitiveType.Null;\n category = category || null;\n var id = primitiveType.toString();\n if (category)\n id += '|' + category;\n return ValueType.typeCache[id] || (ValueType.typeCache[id] = new ValueType(toExtendedType(primitiveType, category), category));\n };\n /** Creates a ValueType to describe the given IEnumType. */\n ValueType.fromEnum = function (enumType) {\n debug.assertValue(enumType, 'enumType');\n return new ValueType(ExtendedType.Enumeration, null, enumType);\n };\n /** Determines if the specified type is compatible from at least one of the otherTypes. */\n ValueType.isCompatibleTo = function (type, otherTypes) {\n debug.assertValue(type, 'type');\n debug.assertValue(otherTypes, 'otherTypes');\n var valueType = ValueType.fromDescriptor(type);\n for (var _i = 0, otherTypes_1 = otherTypes; _i < otherTypes_1.length; _i++) {\n var otherType = otherTypes_1[_i];\n var otherValueType = ValueType.fromDescriptor(otherType);\n if (otherValueType.isCompatibleFrom(valueType))\n return true;\n }\n return false;\n };\n /** Determines if the instance ValueType is convertable from the 'other' ValueType. */\n ValueType.prototype.isCompatibleFrom = function (other) {\n debug.assertValue(other, 'other');\n var otherPrimitiveType = other.primitiveType;\n if (this === other ||\n this.primitiveType === otherPrimitiveType ||\n otherPrimitiveType === PrimitiveType.Null)\n return true;\n return false;\n };\n /**\n * Determines if the instance ValueType is equal to the 'other' ValueType\n * @param {ValueType} other the other ValueType to check equality against\n * @returns True if the instance ValueType is equal to the 'other' ValueType\n */\n ValueType.prototype.equals = function (other) {\n return _.isEqual(this, other);\n };\n Object.defineProperty(ValueType.prototype, \"primitiveType\", {\n /** Gets the exact primitive type of this ValueType. */\n get: function () {\n return getPrimitiveType(this.underlyingType);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"extendedType\", {\n /** Gets the exact extended type of this ValueType. */\n get: function () {\n return this.underlyingType;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"categoryString\", {\n /** Gets the data category string (if any) for this ValueType. */\n get: function () {\n return this.category;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"text\", {\n // Simplified primitive types\n /** Indicates whether the type represents text values. */\n get: function () {\n return this.primitiveType === PrimitiveType.Text;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"numeric\", {\n /** Indicates whether the type represents any numeric value. */\n get: function () {\n return EnumExtensions.hasFlag(this.underlyingType, ExtendedType.Numeric);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"integer\", {\n /** Indicates whether the type represents integer numeric values. */\n get: function () {\n return this.primitiveType === PrimitiveType.Integer;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"bool\", {\n /** Indicates whether the type represents Boolean values. */\n get: function () {\n return this.primitiveType === PrimitiveType.Boolean;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"dateTime\", {\n /** Indicates whether the type represents any date/time values. */\n get: function () {\n return this.primitiveType === PrimitiveType.DateTime ||\n this.primitiveType === PrimitiveType.Date ||\n this.primitiveType === PrimitiveType.Time;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"duration\", {\n /** Indicates whether the type represents duration values. */\n get: function () {\n return this.primitiveType === PrimitiveType.Duration;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"binary\", {\n /** Indicates whether the type represents binary values. */\n get: function () {\n return this.primitiveType === PrimitiveType.Binary;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"none\", {\n /** Indicates whether the type represents none values. */\n get: function () {\n return this.primitiveType === PrimitiveType.None;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"temporal\", {\n // Extended types\n /** Returns an object describing temporal values represented by the type, if it represents a temporal type. */\n get: function () {\n return this.temporalType;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"geography\", {\n /** Returns an object describing geographic values represented by the type, if it represents a geographic type. */\n get: function () {\n return this.geographyType;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"misc\", {\n /** Returns an object describing the specific values represented by the type, if it represents a miscellaneous extended type. */\n get: function () {\n return this.miscType;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"formatting\", {\n /** Returns an object describing the formatting values represented by the type, if it represents a formatting type. */\n get: function () {\n return this.formattingType;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"enum\", {\n /** Returns an object describing the enum values represented by the type, if it represents an enumeration type. */\n get: function () {\n return this.enumType;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ValueType.prototype, \"scripting\", {\n get: function () {\n return this.scriptingType;\n },\n enumerable: true,\n configurable: true\n });\n ValueType.typeCache = {};\n return ValueType;\n }());\n powerbi.ValueType = ValueType;\n var ScriptType = (function () {\n function ScriptType(type) {\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Scripting), 'type');\n this.underlyingType = type;\n }\n Object.defineProperty(ScriptType.prototype, \"source\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.ScriptSource);\n },\n enumerable: true,\n configurable: true\n });\n return ScriptType;\n }());\n powerbi.ScriptType = ScriptType;\n var TemporalType = (function () {\n function TemporalType(type) {\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Temporal), 'type');\n this.underlyingType = type;\n }\n Object.defineProperty(TemporalType.prototype, \"year\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Year);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TemporalType.prototype, \"month\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Month);\n },\n enumerable: true,\n configurable: true\n });\n return TemporalType;\n }());\n powerbi.TemporalType = TemporalType;\n var GeographyType = (function () {\n function GeographyType(type) {\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Geography), 'type');\n this.underlyingType = type;\n }\n Object.defineProperty(GeographyType.prototype, \"address\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Address);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"city\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.City);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"continent\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Continent);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"country\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Country);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"county\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.County);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"region\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Region);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"postalCode\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.PostalCode);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"stateOrProvince\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.StateOrProvince);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"place\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Place);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"latitude\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Latitude);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeographyType.prototype, \"longitude\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Longitude);\n },\n enumerable: true,\n configurable: true\n });\n return GeographyType;\n }());\n powerbi.GeographyType = GeographyType;\n var MiscellaneousType = (function () {\n function MiscellaneousType(type) {\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Miscellaneous), 'type');\n this.underlyingType = type;\n }\n Object.defineProperty(MiscellaneousType.prototype, \"image\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Image);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(MiscellaneousType.prototype, \"imageUrl\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.ImageUrl);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(MiscellaneousType.prototype, \"webUrl\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.WebUrl);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(MiscellaneousType.prototype, \"barcode\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Barcode);\n },\n enumerable: true,\n configurable: true\n });\n return MiscellaneousType;\n }());\n powerbi.MiscellaneousType = MiscellaneousType;\n var FormattingType = (function () {\n function FormattingType(type) {\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Formatting), 'type');\n this.underlyingType = type;\n }\n Object.defineProperty(FormattingType.prototype, \"color\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Color);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormattingType.prototype, \"formatString\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.FormatString);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormattingType.prototype, \"alignment\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Alignment);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormattingType.prototype, \"labelDisplayUnits\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.LabelDisplayUnits);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormattingType.prototype, \"fontSize\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.FontSize);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormattingType.prototype, \"labelDensity\", {\n get: function () {\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.LabelDensity);\n },\n enumerable: true,\n configurable: true\n });\n return FormattingType;\n }());\n powerbi.FormattingType = FormattingType;\n /** Defines primitive value types. Must be consistent with types defined by server conceptual schema. */\n (function (PrimitiveType) {\n PrimitiveType[PrimitiveType[\"Null\"] = 0] = \"Null\";\n PrimitiveType[PrimitiveType[\"Text\"] = 1] = \"Text\";\n PrimitiveType[PrimitiveType[\"Decimal\"] = 2] = \"Decimal\";\n PrimitiveType[PrimitiveType[\"Double\"] = 3] = \"Double\";\n PrimitiveType[PrimitiveType[\"Integer\"] = 4] = \"Integer\";\n PrimitiveType[PrimitiveType[\"Boolean\"] = 5] = \"Boolean\";\n PrimitiveType[PrimitiveType[\"Date\"] = 6] = \"Date\";\n PrimitiveType[PrimitiveType[\"DateTime\"] = 7] = \"DateTime\";\n PrimitiveType[PrimitiveType[\"DateTimeZone\"] = 8] = \"DateTimeZone\";\n PrimitiveType[PrimitiveType[\"Time\"] = 9] = \"Time\";\n PrimitiveType[PrimitiveType[\"Duration\"] = 10] = \"Duration\";\n PrimitiveType[PrimitiveType[\"Binary\"] = 11] = \"Binary\";\n PrimitiveType[PrimitiveType[\"None\"] = 12] = \"None\";\n })(powerbi.PrimitiveType || (powerbi.PrimitiveType = {}));\n var PrimitiveType = powerbi.PrimitiveType;\n /** Defines extended value types, which include primitive types and known data categories constrained to expected primitive types. */\n (function (ExtendedType) {\n // Flags (1 << 8-15 range [0xFF00])\n // Important: Enum members must be declared before they are used in TypeScript.\n ExtendedType[ExtendedType[\"Numeric\"] = 256] = \"Numeric\";\n ExtendedType[ExtendedType[\"Temporal\"] = 512] = \"Temporal\";\n ExtendedType[ExtendedType[\"Geography\"] = 1024] = \"Geography\";\n ExtendedType[ExtendedType[\"Miscellaneous\"] = 2048] = \"Miscellaneous\";\n ExtendedType[ExtendedType[\"Formatting\"] = 4096] = \"Formatting\";\n ExtendedType[ExtendedType[\"Scripting\"] = 8192] = \"Scripting\";\n // Primitive types (0-255 range [0xFF] | flags)\n // The member names and base values must match those in PrimitiveType.\n ExtendedType[ExtendedType[\"Null\"] = 0] = \"Null\";\n ExtendedType[ExtendedType[\"Text\"] = 1] = \"Text\";\n ExtendedType[ExtendedType[\"Decimal\"] = 258] = \"Decimal\";\n ExtendedType[ExtendedType[\"Double\"] = 259] = \"Double\";\n ExtendedType[ExtendedType[\"Integer\"] = 260] = \"Integer\";\n ExtendedType[ExtendedType[\"Boolean\"] = 5] = \"Boolean\";\n ExtendedType[ExtendedType[\"Date\"] = 518] = \"Date\";\n ExtendedType[ExtendedType[\"DateTime\"] = 519] = \"DateTime\";\n ExtendedType[ExtendedType[\"DateTimeZone\"] = 520] = \"DateTimeZone\";\n ExtendedType[ExtendedType[\"Time\"] = 521] = \"Time\";\n ExtendedType[ExtendedType[\"Duration\"] = 10] = \"Duration\";\n ExtendedType[ExtendedType[\"Binary\"] = 11] = \"Binary\";\n ExtendedType[ExtendedType[\"None\"] = 12] = \"None\";\n // Extended types (0-32767 << 16 range [0xFFFF0000] | corresponding primitive type | flags)\n // Temporal\n ExtendedType[ExtendedType[\"Year\"] = 66048] = \"Year\";\n ExtendedType[ExtendedType[\"Year_Text\"] = 66049] = \"Year_Text\";\n ExtendedType[ExtendedType[\"Year_Integer\"] = 66308] = \"Year_Integer\";\n ExtendedType[ExtendedType[\"Year_Date\"] = 66054] = \"Year_Date\";\n ExtendedType[ExtendedType[\"Year_DateTime\"] = 66055] = \"Year_DateTime\";\n ExtendedType[ExtendedType[\"Month\"] = 131584] = \"Month\";\n ExtendedType[ExtendedType[\"Month_Text\"] = 131585] = \"Month_Text\";\n ExtendedType[ExtendedType[\"Month_Integer\"] = 131844] = \"Month_Integer\";\n ExtendedType[ExtendedType[\"Month_Date\"] = 131590] = \"Month_Date\";\n ExtendedType[ExtendedType[\"Month_DateTime\"] = 131591] = \"Month_DateTime\";\n // Geography\n ExtendedType[ExtendedType[\"Address\"] = 6554625] = \"Address\";\n ExtendedType[ExtendedType[\"City\"] = 6620161] = \"City\";\n ExtendedType[ExtendedType[\"Continent\"] = 6685697] = \"Continent\";\n ExtendedType[ExtendedType[\"Country\"] = 6751233] = \"Country\";\n ExtendedType[ExtendedType[\"County\"] = 6816769] = \"County\";\n ExtendedType[ExtendedType[\"Region\"] = 6882305] = \"Region\";\n ExtendedType[ExtendedType[\"PostalCode\"] = 6947840] = \"PostalCode\";\n ExtendedType[ExtendedType[\"PostalCode_Text\"] = 6947841] = \"PostalCode_Text\";\n ExtendedType[ExtendedType[\"PostalCode_Integer\"] = 6948100] = \"PostalCode_Integer\";\n ExtendedType[ExtendedType[\"StateOrProvince\"] = 7013377] = \"StateOrProvince\";\n ExtendedType[ExtendedType[\"Place\"] = 7078913] = \"Place\";\n ExtendedType[ExtendedType[\"Latitude\"] = 7144448] = \"Latitude\";\n ExtendedType[ExtendedType[\"Latitude_Decimal\"] = 7144706] = \"Latitude_Decimal\";\n ExtendedType[ExtendedType[\"Latitude_Double\"] = 7144707] = \"Latitude_Double\";\n ExtendedType[ExtendedType[\"Longitude\"] = 7209984] = \"Longitude\";\n ExtendedType[ExtendedType[\"Longitude_Decimal\"] = 7210242] = \"Longitude_Decimal\";\n ExtendedType[ExtendedType[\"Longitude_Double\"] = 7210243] = \"Longitude_Double\";\n // Miscellaneous\n ExtendedType[ExtendedType[\"Image\"] = 13109259] = \"Image\";\n ExtendedType[ExtendedType[\"ImageUrl\"] = 13174785] = \"ImageUrl\";\n ExtendedType[ExtendedType[\"WebUrl\"] = 13240321] = \"WebUrl\";\n ExtendedType[ExtendedType[\"Barcode\"] = 13305856] = \"Barcode\";\n ExtendedType[ExtendedType[\"Barcode_Text\"] = 13305857] = \"Barcode_Text\";\n ExtendedType[ExtendedType[\"Barcode_Integer\"] = 13306116] = \"Barcode_Integer\";\n // Formatting\n ExtendedType[ExtendedType[\"Color\"] = 19664897] = \"Color\";\n ExtendedType[ExtendedType[\"FormatString\"] = 19730433] = \"FormatString\";\n ExtendedType[ExtendedType[\"Alignment\"] = 20058113] = \"Alignment\";\n ExtendedType[ExtendedType[\"LabelDisplayUnits\"] = 20123649] = \"LabelDisplayUnits\";\n ExtendedType[ExtendedType[\"FontSize\"] = 20189443] = \"FontSize\";\n ExtendedType[ExtendedType[\"LabelDensity\"] = 20254979] = \"LabelDensity\";\n // Enumeration\n ExtendedType[ExtendedType[\"Enumeration\"] = 26214401] = \"Enumeration\";\n // Scripting\n ExtendedType[ExtendedType[\"ScriptSource\"] = 32776193] = \"ScriptSource\";\n })(powerbi.ExtendedType || (powerbi.ExtendedType = {}));\n var ExtendedType = powerbi.ExtendedType;\n var PrimitiveTypeMask = 0xFF;\n var PrimitiveTypeWithFlagsMask = 0xFFFF;\n var PrimitiveTypeFlagsExcludedMask = 0xFFFF0000;\n function getPrimitiveType(extendedType) {\n return extendedType & PrimitiveTypeMask;\n }\n function isPrimitiveType(extendedType) {\n return (extendedType & PrimitiveTypeWithFlagsMask) === extendedType;\n }\n function getCategoryFromExtendedType(extendedType) {\n if (isPrimitiveType(extendedType))\n return null;\n var category = ExtendedType[extendedType];\n if (category) {\n // Check for ExtendedType declaration without a primitive type.\n // If exists, use it as category (e.g. Longitude rather than Longitude_Double)\n // Otherwise use the ExtendedType declaration with a primitive type (e.g. Address)\n var delimIdx = category.lastIndexOf('_');\n if (delimIdx > 0) {\n var baseCategory = category.slice(0, delimIdx);\n if (ExtendedType[baseCategory]) {\n debug.assert((ExtendedType[baseCategory] & PrimitiveTypeFlagsExcludedMask) === (extendedType & PrimitiveTypeFlagsExcludedMask), 'Unexpected value for ExtendedType base member of ' + extendedType);\n category = baseCategory;\n }\n }\n }\n return category || null;\n }\n function toExtendedType(primitiveType, category) {\n var primitiveString = PrimitiveType[primitiveType];\n var t = ExtendedType[primitiveString];\n if (t == null) {\n debug.assertFail('Unexpected primitiveType ' + primitiveType);\n t = ExtendedType.Null;\n }\n if (primitiveType && category) {\n var categoryType = ExtendedType[category];\n if (categoryType) {\n var categoryPrimitiveType = getPrimitiveType(categoryType);\n if (categoryPrimitiveType === PrimitiveType.Null) {\n // Category supports multiple primitive types, check if requested primitive type is supported\n // (note: important to use t here rather than primitiveType as it may include primitive type flags)\n categoryType = t | categoryType;\n if (ExtendedType[categoryType]) {\n debug.assert(ExtendedType[categoryType] === (category + '_' + primitiveString), 'Unexpected name for ExtendedType member ' + categoryType);\n t = categoryType;\n }\n }\n else if (categoryPrimitiveType === primitiveType) {\n // Primitive type matches the single supported type for the category\n t = categoryType;\n }\n }\n }\n return t;\n }\n function matchesExtendedTypeWithAnyPrimitive(a, b) {\n return (a & PrimitiveTypeFlagsExcludedMask) === (b & PrimitiveTypeFlagsExcludedMask);\n }\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n (function (DataShapeBindingLimitType) {\n DataShapeBindingLimitType[DataShapeBindingLimitType[\"Top\"] = 0] = \"Top\";\n DataShapeBindingLimitType[DataShapeBindingLimitType[\"First\"] = 1] = \"First\";\n DataShapeBindingLimitType[DataShapeBindingLimitType[\"Last\"] = 2] = \"Last\";\n DataShapeBindingLimitType[DataShapeBindingLimitType[\"Sample\"] = 3] = \"Sample\";\n DataShapeBindingLimitType[DataShapeBindingLimitType[\"Bottom\"] = 4] = \"Bottom\";\n })(data.DataShapeBindingLimitType || (data.DataShapeBindingLimitType = {}));\n var DataShapeBindingLimitType = data.DataShapeBindingLimitType;\n (function (SubtotalType) {\n SubtotalType[SubtotalType[\"None\"] = 0] = \"None\";\n SubtotalType[SubtotalType[\"Before\"] = 1] = \"Before\";\n SubtotalType[SubtotalType[\"After\"] = 2] = \"After\";\n })(data.SubtotalType || (data.SubtotalType = {}));\n var SubtotalType = data.SubtotalType;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataShapeBindingDataReduction;\n (function (DataShapeBindingDataReduction) {\n function createFrom(reduction) {\n if (!reduction)\n return;\n var result;\n if (reduction.top) {\n result = {\n Top: {}\n };\n if (reduction.top.count)\n result.Top.Count = reduction.top.count;\n }\n if (reduction.bottom) {\n result = {\n Bottom: {}\n };\n if (reduction.bottom.count)\n result.Bottom.Count = reduction.bottom.count;\n }\n if (reduction.sample) {\n result = {\n Sample: {}\n };\n if (reduction.sample.count)\n result.Sample.Count = reduction.sample.count;\n }\n if (reduction.window) {\n result = {\n Window: {}\n };\n if (reduction.window.count)\n result.Window.Count = reduction.window.count;\n }\n return result;\n }\n DataShapeBindingDataReduction.createFrom = createFrom;\n })(DataShapeBindingDataReduction = data.DataShapeBindingDataReduction || (data.DataShapeBindingDataReduction = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n /** Represents a federated conceptual schema. */\n var FederatedConceptualSchema = (function () {\n function FederatedConceptualSchema(options) {\n debug.assertValue(options, 'options');\n this.schemas = options.schemas;\n if (options.links)\n this.links = options.links;\n }\n FederatedConceptualSchema.prototype.schema = function (name) {\n return this.schemas[name];\n };\n return FederatedConceptualSchema;\n }());\n data.FederatedConceptualSchema = FederatedConceptualSchema;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data_1) {\n var Selector;\n (function (Selector) {\n function filterFromSelector(selectors, isNot) {\n if (_.isEmpty(selectors))\n return;\n var exprs = [];\n for (var i = 0, ilen = selectors.length; i < ilen; i++) {\n var identity = selectors[i];\n var data_2 = identity.data;\n var exprToAdd = undefined;\n if (data_2 && data_2.length) {\n for (var j = 0, jlen = data_2.length; j < jlen; j++) {\n exprToAdd = data_1.SQExprBuilder.and(exprToAdd, identity.data[j].expr);\n }\n }\n if (exprToAdd)\n exprs.push(exprToAdd);\n }\n if (!_.isEmpty(exprs))\n return powerbi.DataViewScopeIdentity.filterFromExprs(exprs, isNot);\n }\n Selector.filterFromSelector = filterFromSelector;\n function matchesData(selector, identities) {\n debug.assertValue(selector, 'selector');\n debug.assertValue(selector.data, 'selector.data');\n debug.assertValue(identities, 'identities');\n var selectorData = selector.data;\n if (selectorData.length !== identities.length)\n return false;\n for (var i = 0, len = selectorData.length; i < len; i++) {\n var dataItem = selector.data[i];\n var selectorDataItem = dataItem;\n if (selectorDataItem.expr) {\n if (!powerbi.DataViewScopeIdentity.equals(selectorDataItem, identities[i]))\n return false;\n }\n else {\n if (!data_1.DataViewScopeWildcard.matches(dataItem, identities[i]))\n return false;\n }\n }\n return true;\n }\n Selector.matchesData = matchesData;\n function matchesKeys(selector, keysList) {\n debug.assertValue(selector, 'selector');\n debug.assertValue(selector.data, 'selector.data');\n debug.assertValue(keysList, 'keysList');\n var selectorData = selector.data, selectorDataLength = selectorData.length;\n if (selectorDataLength !== keysList.length)\n return false;\n for (var i = 0; i < selectorDataLength; i++) {\n var selectorDataItem = selector.data[i], selectorDataExprs = void 0;\n if (selectorDataItem.expr) {\n selectorDataExprs = data_1.ScopeIdentityExtractor.getKeys(selectorDataItem.expr);\n }\n else if (selectorDataItem.exprs) {\n selectorDataExprs = selectorDataItem.exprs;\n }\n else {\n // In case DataViewRoleWildcard\n return false;\n }\n if (!selectorDataExprs)\n continue;\n if (!data_1.SQExprUtils.sequenceEqual(keysList[i], selectorDataExprs))\n return false;\n }\n return true;\n }\n Selector.matchesKeys = matchesKeys;\n /** Determines whether two selectors are equal. */\n function equals(x, y) {\n // Normalize falsy to null\n x = x || null;\n y = y || null;\n if (x === y)\n return true;\n if (!x !== !y)\n return false;\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n if (x.id !== y.id)\n return false;\n if (x.metadata !== y.metadata)\n return false;\n if (!equalsDataArray(x.data, y.data))\n return false;\n return true;\n }\n Selector.equals = equals;\n function equalsDataArray(x, y) {\n // Normalize falsy to null\n x = x || null;\n y = y || null;\n if (x === y)\n return true;\n if (!x !== !y)\n return false;\n if (x.length !== y.length)\n return false;\n for (var i = 0, len = x.length; i < len; i++) {\n if (!equalsData(x[i], y[i]))\n return false;\n }\n return true;\n }\n function equalsData(x, y) {\n var selector1 = x;\n var selector2 = y;\n if (selector1.expr && selector2.expr)\n return powerbi.DataViewScopeIdentity.equals(selector1, selector2);\n if (selector1.exprs && selector2.exprs)\n return data_1.DataViewScopeWildcard.equals(selector1, selector2);\n if (selector1.roles && selector2.roles)\n return data_1.DataViewRoleWildcard.equals(selector1, selector2);\n return false;\n }\n function getKey(selector) {\n var toStringify = {};\n if (selector.data) {\n var data_3 = [];\n for (var i = 0, ilen = selector.data.length; i < ilen; i++) {\n data_3.push(selector.data[i].key);\n }\n toStringify.data = data_3;\n }\n if (selector.metadata)\n toStringify.metadata = selector.metadata;\n if (selector.id)\n toStringify.id = selector.id;\n return JSON.stringify(toStringify);\n }\n Selector.getKey = getKey;\n function containsWildcard(selector) {\n debug.assertValue(selector, 'selector');\n var dataItems = selector.data;\n if (!dataItems)\n return false;\n for (var _i = 0, dataItems_1 = dataItems; _i < dataItems_1.length; _i++) {\n var dataItem = dataItems_1[_i];\n var wildCard = dataItem;\n if (wildCard.exprs || wildCard.roles)\n return true;\n }\n return false;\n }\n Selector.containsWildcard = containsWildcard;\n function hasRoleWildcard(selector) {\n debug.assertValue(selector, 'selector');\n var dataItems = selector.data;\n if (_.isEmpty(dataItems))\n return false;\n for (var _i = 0, dataItems_2 = dataItems; _i < dataItems_2.length; _i++) {\n var dataItem = dataItems_2[_i];\n if (isRoleWildcard(dataItem))\n return true;\n }\n return false;\n }\n Selector.hasRoleWildcard = hasRoleWildcard;\n function isRoleWildcard(dataItem) {\n return !_.isEmpty(dataItem.roles);\n }\n Selector.isRoleWildcard = isRoleWildcard;\n })(Selector = data_1.Selector || (data_1.Selector = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n (function (EntitySourceType) {\n EntitySourceType[EntitySourceType[\"Table\"] = 0] = \"Table\";\n EntitySourceType[EntitySourceType[\"Pod\"] = 1] = \"Pod\";\n })(data.EntitySourceType || (data.EntitySourceType = {}));\n var EntitySourceType = data.EntitySourceType;\n function getArithmeticOperatorName(arithmeticOperatorKind) {\n switch (arithmeticOperatorKind) {\n case 0 /* Add */:\n return \"Add\";\n case 1 /* Subtract */:\n return \"Subtract\";\n case 2 /* Multiply */:\n return \"Multiply\";\n case 3 /* Divide */:\n return \"Divide\";\n }\n throw new Error('Unexpected ArithmeticOperatorKind: ' + arithmeticOperatorKind);\n }\n data.getArithmeticOperatorName = getArithmeticOperatorName;\n (function (TimeUnit) {\n TimeUnit[TimeUnit[\"Day\"] = 0] = \"Day\";\n TimeUnit[TimeUnit[\"Week\"] = 1] = \"Week\";\n TimeUnit[TimeUnit[\"Month\"] = 2] = \"Month\";\n TimeUnit[TimeUnit[\"Year\"] = 3] = \"Year\";\n TimeUnit[TimeUnit[\"Decade\"] = 4] = \"Decade\";\n TimeUnit[TimeUnit[\"Second\"] = 5] = \"Second\";\n TimeUnit[TimeUnit[\"Minute\"] = 6] = \"Minute\";\n TimeUnit[TimeUnit[\"Hour\"] = 7] = \"Hour\";\n })(data.TimeUnit || (data.TimeUnit = {}));\n var TimeUnit = data.TimeUnit;\n (function (QueryAggregateFunction) {\n QueryAggregateFunction[QueryAggregateFunction[\"Sum\"] = 0] = \"Sum\";\n QueryAggregateFunction[QueryAggregateFunction[\"Avg\"] = 1] = \"Avg\";\n QueryAggregateFunction[QueryAggregateFunction[\"Count\"] = 2] = \"Count\";\n QueryAggregateFunction[QueryAggregateFunction[\"Min\"] = 3] = \"Min\";\n QueryAggregateFunction[QueryAggregateFunction[\"Max\"] = 4] = \"Max\";\n QueryAggregateFunction[QueryAggregateFunction[\"CountNonNull\"] = 5] = \"CountNonNull\";\n QueryAggregateFunction[QueryAggregateFunction[\"Median\"] = 6] = \"Median\";\n QueryAggregateFunction[QueryAggregateFunction[\"StandardDeviation\"] = 7] = \"StandardDeviation\";\n QueryAggregateFunction[QueryAggregateFunction[\"Variance\"] = 8] = \"Variance\";\n })(data.QueryAggregateFunction || (data.QueryAggregateFunction = {}));\n var QueryAggregateFunction = data.QueryAggregateFunction;\n (function (QueryComparisonKind) {\n QueryComparisonKind[QueryComparisonKind[\"Equal\"] = 0] = \"Equal\";\n QueryComparisonKind[QueryComparisonKind[\"GreaterThan\"] = 1] = \"GreaterThan\";\n QueryComparisonKind[QueryComparisonKind[\"GreaterThanOrEqual\"] = 2] = \"GreaterThanOrEqual\";\n QueryComparisonKind[QueryComparisonKind[\"LessThan\"] = 3] = \"LessThan\";\n QueryComparisonKind[QueryComparisonKind[\"LessThanOrEqual\"] = 4] = \"LessThanOrEqual\";\n })(data.QueryComparisonKind || (data.QueryComparisonKind = {}));\n var QueryComparisonKind = data.QueryComparisonKind;\n /** Defines semantic data types. */\n (function (SemanticType) {\n SemanticType[SemanticType[\"None\"] = 0] = \"None\";\n SemanticType[SemanticType[\"Number\"] = 1] = \"Number\";\n SemanticType[SemanticType[\"Integer\"] = 3] = \"Integer\";\n SemanticType[SemanticType[\"DateTime\"] = 4] = \"DateTime\";\n SemanticType[SemanticType[\"Time\"] = 8] = \"Time\";\n SemanticType[SemanticType[\"Date\"] = 20] = \"Date\";\n SemanticType[SemanticType[\"Month\"] = 35] = \"Month\";\n SemanticType[SemanticType[\"Year\"] = 67] = \"Year\";\n SemanticType[SemanticType[\"YearAndMonth\"] = 128] = \"YearAndMonth\";\n SemanticType[SemanticType[\"MonthAndDay\"] = 256] = \"MonthAndDay\";\n SemanticType[SemanticType[\"Decade\"] = 515] = \"Decade\";\n SemanticType[SemanticType[\"YearAndWeek\"] = 1024] = \"YearAndWeek\";\n SemanticType[SemanticType[\"String\"] = 2048] = \"String\";\n SemanticType[SemanticType[\"Boolean\"] = 4096] = \"Boolean\";\n SemanticType[SemanticType[\"Table\"] = 8192] = \"Table\";\n SemanticType[SemanticType[\"Range\"] = 16384] = \"Range\";\n })(data.SemanticType || (data.SemanticType = {}));\n var SemanticType = data.SemanticType;\n (function (FilterKind) {\n FilterKind[FilterKind[\"Default\"] = 0] = \"Default\";\n FilterKind[FilterKind[\"Period\"] = 1] = \"Period\";\n })(data.FilterKind || (data.FilterKind = {}));\n var FilterKind = data.FilterKind;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var QueryProjectionCollection = (function () {\n function QueryProjectionCollection(items, activeProjectionRefs, showAll) {\n debug.assertValue(items, 'items');\n this.items = items;\n this._activeProjectionRefs = activeProjectionRefs;\n this._showAll = showAll;\n }\n /** Returns all projections in a mutable array. */\n QueryProjectionCollection.prototype.all = function () {\n return this.items;\n };\n Object.defineProperty(QueryProjectionCollection.prototype, \"activeProjectionRefs\", {\n get: function () {\n return this._activeProjectionRefs;\n },\n set: function (queryReferences) {\n if (!_.isEmpty(queryReferences)) {\n var queryRefs = this.items.map(function (val) { return val.queryRef; });\n for (var _i = 0, queryReferences_1 = queryReferences; _i < queryReferences_1.length; _i++) {\n var queryReference = queryReferences_1[_i];\n if (!_.contains(queryRefs, queryReference))\n return;\n }\n this._activeProjectionRefs = queryReferences;\n }\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(QueryProjectionCollection.prototype, \"showAll\", {\n get: function () {\n return this._showAll;\n },\n set: function (value) {\n this._showAll = value;\n },\n enumerable: true,\n configurable: true\n });\n QueryProjectionCollection.prototype.addActiveQueryReference = function (queryRef) {\n if (!this._activeProjectionRefs)\n this._activeProjectionRefs = [queryRef];\n else\n this._activeProjectionRefs.push(queryRef);\n };\n QueryProjectionCollection.prototype.getLastActiveQueryReference = function () {\n if (!_.isEmpty(this._activeProjectionRefs)) {\n return this._activeProjectionRefs[this._activeProjectionRefs.length - 1];\n }\n };\n /** Replaces the given oldQueryRef with newQueryRef in this QueryProjectionCollection. */\n QueryProjectionCollection.prototype.replaceQueryRef = function (oldQueryRef, newQueryRef) {\n debug.assertValue(oldQueryRef, 'oldQueryRef');\n debug.assertValue(newQueryRef, 'newQueryRef');\n debug.assert(oldQueryRef !== newQueryRef, 'oldQueryRef !== newQueryRef');\n debug.assert(_.isEmpty(this._activeProjectionRefs), 'replaceQueryRef(...) is not supported on the QueryProjectionCollection of a drillable role');\n // Note: the same queryRef can get projected multiple times\n for (var _i = 0, _a = this.items; _i < _a.length; _i++) {\n var item = _a[_i];\n if (item.queryRef === oldQueryRef) {\n item.queryRef = newQueryRef;\n }\n }\n };\n QueryProjectionCollection.prototype.clone = function () {\n return new QueryProjectionCollection(_.cloneDeep(this.items), _.clone(this._activeProjectionRefs), this._showAll);\n };\n return QueryProjectionCollection;\n }());\n data.QueryProjectionCollection = QueryProjectionCollection;\n var QueryProjectionsByRole;\n (function (QueryProjectionsByRole) {\n /** Clones the QueryProjectionsByRole. */\n function clone(roles) {\n if (!roles)\n return roles;\n var clonedRoles = {};\n for (var roleName in roles)\n clonedRoles[roleName] = roles[roleName].clone();\n return clonedRoles;\n }\n QueryProjectionsByRole.clone = clone;\n /** Returns the QueryProjectionCollection for that role. Even returns empty collections so that 'drillable' and 'activeProjection' fields are preserved. */\n function getRole(roles, name) {\n debug.assertAnyValue(roles, 'roles');\n debug.assertValue(name, 'name');\n if (!roles)\n return;\n return roles[name];\n }\n QueryProjectionsByRole.getRole = getRole;\n })(QueryProjectionsByRole = data.QueryProjectionsByRole || (data.QueryProjectionsByRole = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n /** The system used to determine display units used during formatting */\n (function (DisplayUnitSystemType) {\n /** Default display unit system, which saves space by using units such as K, M, bn with PowerView rules for when to pick a unit. Suitable for chart axes. */\n DisplayUnitSystemType[DisplayUnitSystemType[\"Default\"] = 0] = \"Default\";\n /** A verbose display unit system that will only respect the formatting defined in the model. Suitable for explore mode single-value cards. */\n DisplayUnitSystemType[DisplayUnitSystemType[\"Verbose\"] = 1] = \"Verbose\";\n /**\n * A display unit system that uses units such as K, M, bn if we have at least one of those units (e.g. 0.9M is not valid as it's less than 1 million).\n * Suitable for dashboard tile cards\n */\n DisplayUnitSystemType[DisplayUnitSystemType[\"WholeUnits\"] = 2] = \"WholeUnits\";\n /**A display unit system that also contains Auto and None units for data labels*/\n DisplayUnitSystemType[DisplayUnitSystemType[\"DataLabels\"] = 3] = \"DataLabels\";\n })(powerbi.DisplayUnitSystemType || (powerbi.DisplayUnitSystemType = {}));\n var DisplayUnitSystemType = powerbi.DisplayUnitSystemType;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n /** Repreasents the sequence of the dates/times */\n var DateTimeSequence = (function () {\n // Constructors\n /** Creates new instance of the DateTimeSequence */\n function DateTimeSequence(unit) {\n this.unit = unit;\n this.sequence = [];\n this.min = new Date(\"9999-12-31T23:59:59.999\");\n this.max = new Date(\"0001-01-01T00:00:00.000\");\n }\n // Methods\n /**\n * Add a new Date to a sequence.\n * @param date - date to add\n */\n DateTimeSequence.prototype.add = function (date) {\n if (date < this.min) {\n this.min = date;\n }\n if (date > this.max) {\n this.max = date;\n }\n this.sequence.push(date);\n };\n // Methods\n /**\n * Extends the sequence to cover new date range\n * @param min - new min to be covered by sequence\n * @param max - new max to be covered by sequence\n */\n DateTimeSequence.prototype.extendToCover = function (min, max) {\n var x = this.min;\n while (min < x) {\n x = DateTimeSequence.addInterval(x, -this.interval, this.unit);\n this.sequence.splice(0, 0, x);\n }\n this.min = x;\n x = this.max;\n while (x < max) {\n x = DateTimeSequence.addInterval(x, this.interval, this.unit);\n this.sequence.push(x);\n }\n this.max = x;\n };\n /**\n * Move the sequence to cover new date range\n * @param min - new min to be covered by sequence\n * @param max - new max to be covered by sequence\n */\n DateTimeSequence.prototype.moveToCover = function (min, max) {\n var delta = DateTimeSequence.getDelta(min, max, this.unit);\n var count = Math.floor(delta / this.interval);\n this.min = DateTimeSequence.addInterval(this.min, count * this.interval, this.unit);\n this.sequence = [];\n this.sequence.push(this.min);\n this.max = this.min;\n while (this.max < max) {\n this.max = DateTimeSequence.addInterval(this.max, this.interval, this.unit);\n this.sequence.push(this.max);\n }\n };\n // Static\n /**\n * Calculate a new DateTimeSequence\n * @param dataMin - Date representing min of the data range\n * @param dataMax - Date representing max of the data range\n * @param expectedCount - expected number of intervals in the sequence\n * @param unit - of the intervals in the sequence\n */\n DateTimeSequence.calculate = function (dataMin, dataMax, expectedCount, unit) {\n if (!unit) {\n unit = DateTimeSequence.getIntervalUnit(dataMin, dataMax, expectedCount);\n }\n switch (unit) {\n case powerbi.DateTimeUnit.Year:\n return DateTimeSequence.calculateYears(dataMin, dataMax, expectedCount);\n case powerbi.DateTimeUnit.Month:\n return DateTimeSequence.calculateMonths(dataMin, dataMax, expectedCount);\n case powerbi.DateTimeUnit.Week:\n return DateTimeSequence.calculateWeeks(dataMin, dataMax, expectedCount);\n case powerbi.DateTimeUnit.Day:\n return DateTimeSequence.calculateDays(dataMin, dataMax, expectedCount);\n case powerbi.DateTimeUnit.Hour:\n return DateTimeSequence.calculateHours(dataMin, dataMax, expectedCount);\n case powerbi.DateTimeUnit.Minute:\n return DateTimeSequence.calculateMinutes(dataMin, dataMax, expectedCount);\n case powerbi.DateTimeUnit.Second:\n return DateTimeSequence.calculateSeconds(dataMin, dataMax, expectedCount);\n case powerbi.DateTimeUnit.Millisecond:\n return DateTimeSequence.calculateMilliseconds(dataMin, dataMax, expectedCount);\n default:\n debug.assertFail(\"Unsupported DateTimeUnit\");\n }\n };\n DateTimeSequence.calculateYears = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(!expectedCount || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"Expected count is out of range\");\n // Calculate range and sequence\n var yearsRange = powerbi.NumericSequenceRange.calculateDataRange(dataMin.getFullYear(), dataMax.getFullYear(), false);\n // Calculate year sequence\n var sequence = powerbi.NumericSequence.calculate(powerbi.NumericSequenceRange.calculate(0, yearsRange.max - yearsRange.min), expectedCount, 0, null, null, [1, 2, 5]);\n var newMinYear = Math.floor(yearsRange.min / sequence.interval) * sequence.interval;\n var date = new Date(newMinYear, 0, 1);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Year);\n return result;\n };\n DateTimeSequence.calculateMonths = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\n // Calculate range\n var minYear = dataMin.getFullYear();\n var maxYear = dataMax.getFullYear();\n var minMonth = dataMin.getMonth();\n var maxMonth = (maxYear - minYear) * 12 + dataMax.getMonth();\n var date = new Date(minYear, 0, 1);\n // Calculate month sequence\n var sequence = powerbi.NumericSequence.calculateUnits(minMonth, maxMonth, expectedCount, [1, 2, 3, 6, 12]);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Month);\n return result;\n };\n DateTimeSequence.calculateWeeks = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\n var firstDayOfWeek = 0;\n var minDayOfWeek = dataMin.getDay();\n var dayOffset = (minDayOfWeek - firstDayOfWeek + 7) % 7;\n var minDay = dataMin.getDate() - dayOffset;\n // Calculate range\n var date = new Date(dataMin.getFullYear(), dataMin.getMonth(), minDay);\n var min = 0;\n var max = powerbi.Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, powerbi.DateTimeUnit.Week));\n // Calculate week sequence\n var sequence = powerbi.NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 4, 8]);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Week);\n return result;\n };\n DateTimeSequence.calculateDays = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\n // Calculate range\n var date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate());\n var min = 0;\n var max = powerbi.Double.ceilWithPrecision(DateTimeSequence.getDelta(dataMin, dataMax, powerbi.DateTimeUnit.Day));\n // Calculate day sequence\n var sequence = powerbi.NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 7, 14]);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Day);\n return result;\n };\n DateTimeSequence.calculateHours = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\n // Calculate range\n var date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate());\n var min = powerbi.Double.floorWithPrecision(DateTimeSequence.getDelta(date, dataMin, powerbi.DateTimeUnit.Hour));\n var max = powerbi.Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, powerbi.DateTimeUnit.Hour));\n // Calculate hour sequence\n var sequence = powerbi.NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 3, 6, 12, 24]);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Hour);\n return result;\n };\n DateTimeSequence.calculateMinutes = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\n // Calculate range\n var date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate(), dataMin.getHours());\n var min = powerbi.Double.floorWithPrecision(DateTimeSequence.getDelta(date, dataMin, powerbi.DateTimeUnit.Minute));\n var max = powerbi.Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, powerbi.DateTimeUnit.Minute));\n // Calculate minutes numeric sequence\n var sequence = powerbi.NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 5, 10, 15, 30, 60, 60 * 2, 60 * 3, 60 * 6, 60 * 12, 60 * 24]);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Minute);\n return result;\n };\n DateTimeSequence.calculateSeconds = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\n // Calculate range\n var date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate(), dataMin.getHours(), dataMin.getMinutes());\n var min = powerbi.Double.floorWithPrecision(DateTimeSequence.getDelta(date, dataMin, powerbi.DateTimeUnit.Second));\n var max = powerbi.Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, powerbi.DateTimeUnit.Second));\n // Calculate minutes numeric sequence\n var sequence = powerbi.NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 5, 10, 15, 30, 60, 60 * 2, 60 * 5, 60 * 10, 60 * 15, 60 * 30, 60 * 60]);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Second);\n return result;\n };\n DateTimeSequence.calculateMilliseconds = function (dataMin, dataMax, expectedCount) {\n debug.assertValue(dataMin, \"dataMin\");\n debug.assertValue(dataMax, \"dataMax\");\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\n // Calculate range\n var date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate(), dataMin.getHours(), dataMin.getMinutes(), dataMin.getSeconds());\n var min = DateTimeSequence.getDelta(date, dataMin, powerbi.DateTimeUnit.Millisecond);\n var max = DateTimeSequence.getDelta(date, dataMax, powerbi.DateTimeUnit.Millisecond);\n // Calculate milliseconds numeric sequence\n var sequence = powerbi.NumericSequence.calculate(powerbi.NumericSequenceRange.calculate(min, max), expectedCount, 0);\n // Convert to date sequence\n var result = DateTimeSequence.fromNumericSequence(date, sequence, powerbi.DateTimeUnit.Millisecond);\n return result;\n };\n DateTimeSequence.addInterval = function (value, interval, unit) {\n interval = Math.round(interval);\n switch (unit) {\n case powerbi.DateTimeUnit.Year:\n return DateUtils.addYears(value, interval);\n case powerbi.DateTimeUnit.Month:\n return DateUtils.addMonths(value, interval);\n case powerbi.DateTimeUnit.Week:\n return DateUtils.addWeeks(value, interval);\n case powerbi.DateTimeUnit.Day:\n return DateUtils.addDays(value, interval);\n case powerbi.DateTimeUnit.Hour:\n return DateUtils.addHours(value, interval);\n case powerbi.DateTimeUnit.Minute:\n return DateUtils.addMinutes(value, interval);\n case powerbi.DateTimeUnit.Second:\n return DateUtils.addSeconds(value, interval);\n case powerbi.DateTimeUnit.Millisecond:\n return DateUtils.addMilliseconds(value, interval);\n }\n };\n DateTimeSequence.fromNumericSequence = function (date, sequence, unit) {\n var result = new DateTimeSequence(unit);\n for (var i = 0; i < sequence.sequence.length; i++) {\n var x = sequence.sequence[i];\n var d = DateTimeSequence.addInterval(date, x, unit);\n result.add(d);\n }\n result.interval = sequence.interval;\n result.intervalOffset = sequence.intervalOffset;\n return result;\n };\n DateTimeSequence.getDelta = function (min, max, unit) {\n var delta = 0;\n switch (unit) {\n case powerbi.DateTimeUnit.Year:\n delta = max.getFullYear() - min.getFullYear();\n break;\n case powerbi.DateTimeUnit.Month:\n delta = (max.getFullYear() - min.getFullYear()) * 12 + max.getMonth() - min.getMonth();\n break;\n case powerbi.DateTimeUnit.Week:\n delta = (max.getTime() - min.getTime()) / (7 * 24 * 3600000);\n break;\n case powerbi.DateTimeUnit.Day:\n delta = (max.getTime() - min.getTime()) / (24 * 3600000);\n break;\n case powerbi.DateTimeUnit.Hour:\n delta = (max.getTime() - min.getTime()) / 3600000;\n break;\n case powerbi.DateTimeUnit.Minute:\n delta = (max.getTime() - min.getTime()) / 60000;\n break;\n case powerbi.DateTimeUnit.Second:\n delta = (max.getTime() - min.getTime()) / 1000;\n break;\n case powerbi.DateTimeUnit.Millisecond:\n delta = max.getTime() - min.getTime();\n break;\n }\n return delta;\n };\n DateTimeSequence.getIntervalUnit = function (min, max, maxCount) {\n maxCount = Math.max(maxCount, 2);\n var totalDays = DateTimeSequence.getDelta(min, max, powerbi.DateTimeUnit.Day);\n if (totalDays > 356 && totalDays >= 30 * 6 * maxCount)\n return powerbi.DateTimeUnit.Year;\n if (totalDays > 60 && totalDays > 7 * maxCount)\n return powerbi.DateTimeUnit.Month;\n if (totalDays > 14 && totalDays > 2 * maxCount)\n return powerbi.DateTimeUnit.Week;\n var totalHours = DateTimeSequence.getDelta(min, max, powerbi.DateTimeUnit.Hour);\n if (totalDays > 2 && totalHours > 12 * maxCount)\n return powerbi.DateTimeUnit.Day;\n if (totalHours >= 24 && totalHours >= maxCount)\n return powerbi.DateTimeUnit.Hour;\n var totalMinutes = DateTimeSequence.getDelta(min, max, powerbi.DateTimeUnit.Minute);\n if (totalMinutes > 2 && totalMinutes >= maxCount)\n return powerbi.DateTimeUnit.Minute;\n var totalSeconds = DateTimeSequence.getDelta(min, max, powerbi.DateTimeUnit.Second);\n if (totalSeconds > 2 && totalSeconds >= 0.8 * maxCount)\n return powerbi.DateTimeUnit.Second;\n var totalMilliseconds = DateTimeSequence.getDelta(min, max, powerbi.DateTimeUnit.Millisecond);\n if (totalMilliseconds > 0)\n return powerbi.DateTimeUnit.Millisecond;\n // If the size of the range is 0 we need to guess the unit based on the date's non-zero values starting with milliseconds\n var date = min;\n if (date.getMilliseconds() !== 0)\n return powerbi.DateTimeUnit.Millisecond;\n if (date.getSeconds() !== 0)\n return powerbi.DateTimeUnit.Second;\n if (date.getMinutes() !== 0)\n return powerbi.DateTimeUnit.Minute;\n if (date.getHours() !== 0)\n return powerbi.DateTimeUnit.Hour;\n if (date.getDate() !== 1)\n return powerbi.DateTimeUnit.Day;\n if (date.getMonth() !== 0)\n return powerbi.DateTimeUnit.Month;\n return powerbi.DateTimeUnit.Year;\n };\n // Constants\n DateTimeSequence.MIN_COUNT = 1;\n DateTimeSequence.MAX_COUNT = 1000;\n return DateTimeSequence;\n }());\n powerbi.DateTimeSequence = DateTimeSequence;\n /** DateUtils module provides DateTimeSequence with set of additional date manipulation routines */\n var DateUtils;\n (function (DateUtils) {\n var MonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n var MonthDaysLeap = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n /**\n * Returns bool indicating weither the provided year is a leap year.\n * @param year - year value\n */\n function isLeap(year) {\n return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);\n }\n /**\n * Returns number of days in the provided year/month.\n * @param year - year value\n * @param month - month value\n */\n function getMonthDays(year, month) {\n return isLeap(year) ? MonthDaysLeap[month] : MonthDays[month];\n }\n /**\n * Adds a specified number of years to the provided date.\n * @param date - date value\n * @param yearDelta - number of years to add\n */\n function addYears(date, yearDelta) {\n var year = date.getFullYear();\n var month = date.getMonth();\n var day = date.getDate();\n var isLeapDay = month === 2 && day === 29;\n var result = new Date(date.getTime());\n year = year + yearDelta;\n if (isLeapDay && !isLeap(year)) {\n day = 28;\n }\n result.setFullYear(year, month, day);\n return result;\n }\n DateUtils.addYears = addYears;\n /**\n * Adds a specified number of months to the provided date.\n * @param date - date value\n * @param monthDelta - number of months to add\n */\n function addMonths(date, monthDelta) {\n var year = date.getFullYear();\n var month = date.getMonth();\n var day = date.getDate();\n var result = new Date(date.getTime());\n year += (monthDelta - (monthDelta % 12)) / 12;\n month += monthDelta % 12;\n // VSTS 1325771: Certain column charts don't display any data\n // Wrap arround the month if is after december (value 11)\n if (month > 11) {\n month = month % 12;\n year++;\n }\n day = Math.min(day, getMonthDays(year, month));\n result.setFullYear(year, month, day);\n return result;\n }\n DateUtils.addMonths = addMonths;\n /**\n * Adds a specified number of weeks to the provided date.\n * @param date - date value\n * @param weeks - number of weeks to add\n */\n function addWeeks(date, weeks) {\n return addDays(date, weeks * 7);\n }\n DateUtils.addWeeks = addWeeks;\n /**\n * Adds a specified number of days to the provided date.\n * @param date - date value\n * @param days - number of days to add\n */\n function addDays(date, days) {\n var year = date.getFullYear();\n var month = date.getMonth();\n var day = date.getDate();\n var result = new Date(date.getTime());\n result.setFullYear(year, month, day + days);\n return result;\n }\n DateUtils.addDays = addDays;\n /**\n * Adds a specified number of hours to the provided date.\n * @param date - date value\n * @param hours - number of hours to add\n */\n function addHours(date, hours) {\n return new Date(date.getTime() + hours * 3600000);\n }\n DateUtils.addHours = addHours;\n /**\n * Adds a specified number of minutes to the provided date.\n * @param date - date value\n * @param minutes - number of minutes to add\n */\n function addMinutes(date, minutes) {\n return new Date(date.getTime() + minutes * 60000);\n }\n DateUtils.addMinutes = addMinutes;\n /**\n * Adds a specified number of seconds to the provided date.\n * @param date - date value\n * @param seconds - number of seconds to add\n */\n function addSeconds(date, seconds) {\n return new Date(date.getTime() + seconds * 1000);\n }\n DateUtils.addSeconds = addSeconds;\n /**\n * Adds a specified number of milliseconds to the provided date.\n * @param date - date value\n * @param milliseconds - number of milliseconds to add\n */\n function addMilliseconds(date, milliseconds) {\n return new Date(date.getTime() + milliseconds);\n }\n DateUtils.addMilliseconds = addMilliseconds;\n })(DateUtils = powerbi.DateUtils || (powerbi.DateUtils = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n // Constants\n var maxExponent = 24;\n var defaultScientificBigNumbersBoundary = 1E15;\n var scientificSmallNumbersBoundary = 1E-4;\n var PERCENTAGE_FORMAT = '%';\n var SCIENTIFIC_FORMAT = 'E+0';\n var DEFAULT_SCIENTIFIC_FORMAT = '0.##' + SCIENTIFIC_FORMAT;\n // Regular expressions\n /**\n * This regex looks for strings that match one of the following conditions:\n * - Optionally contain \"0\", \"#\", followed by a period, followed by at least one \"0\" or \"#\" (Ex. ###,000.###)\n * - Contains at least one of \"0\", \"#\", or \",\" (Ex. ###,000)\n * - Contain a \"g\" (indicates to use the general .NET numeric format string)\n * The entire string (start to end) must match, and the match is not case-sensitive.\n */\n var SUPPORTED_SCIENTIFIC_FORMATS = /^([0\\#,]*\\.[0\\#]+|[0\\#,]+|g)$/i;\n var DisplayUnit = (function () {\n function DisplayUnit() {\n }\n // Methods\n DisplayUnit.prototype.project = function (value) {\n if (this.value) {\n return powerbi.Double.removeDecimalNoise(value / this.value);\n }\n else {\n return value;\n }\n };\n DisplayUnit.prototype.reverseProject = function (value) {\n if (this.value) {\n return value * this.value;\n }\n else {\n return value;\n }\n };\n DisplayUnit.prototype.isApplicableTo = function (value) {\n value = Math.abs(value);\n var precision = powerbi.Double.getPrecision(value, 3);\n return powerbi.Double.greaterOrEqualWithPrecision(value, this.applicableRangeMin, precision) && powerbi.Double.lessWithPrecision(value, this.applicableRangeMax, precision);\n };\n DisplayUnit.prototype.isScaling = function () {\n return this.value > 1;\n };\n return DisplayUnit;\n }());\n powerbi.DisplayUnit = DisplayUnit;\n var DisplayUnitSystem = (function () {\n // Constructor\n function DisplayUnitSystem(units) {\n this.units = units ? units : [];\n }\n Object.defineProperty(DisplayUnitSystem.prototype, \"title\", {\n // Properties\n get: function () {\n return this.displayUnit ? this.displayUnit.title : undefined;\n },\n enumerable: true,\n configurable: true\n });\n // Methods\n DisplayUnitSystem.prototype.update = function (value) {\n if (value === undefined)\n return;\n this.unitBaseValue = value;\n this.displayUnit = this.findApplicableDisplayUnit(value);\n };\n DisplayUnitSystem.prototype.findApplicableDisplayUnit = function (value) {\n for (var _i = 0, _a = this.units; _i < _a.length; _i++) {\n var unit = _a[_i];\n if (unit.isApplicableTo(value))\n return unit;\n }\n return undefined;\n };\n DisplayUnitSystem.prototype.format = function (value, format, decimals, trailingZeros) {\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\n if (this.isFormatSupported(format)) {\n decimals = this.getNumberOfDecimalsForFormatting(format, decimals);\n if (this.hasScientitifcFormat(format)) {\n return this.formatHelper(value, '', format, decimals, trailingZeros);\n }\n if (this.isScalingUnit() && this.shouldRespectScalingUnit(format)) {\n return this.formatHelper(this.displayUnit.project(value), this.displayUnit.labelFormat, format, decimals, trailingZeros);\n }\n if (decimals != null) {\n return this.formatHelper(value, '', format, decimals, trailingZeros);\n }\n }\n return powerbi.formattingService.formatValue(value, format);\n };\n DisplayUnitSystem.prototype.isFormatSupported = function (format) {\n return !DisplayUnitSystem.UNSUPPORTED_FORMATS.test(format);\n };\n DisplayUnitSystem.prototype.isPercentageFormat = function (format) {\n return format && format.indexOf(PERCENTAGE_FORMAT) >= 0;\n };\n DisplayUnitSystem.prototype.shouldRespectScalingUnit = function (format) {\n return !this.isPercentageFormat(format);\n };\n DisplayUnitSystem.prototype.getNumberOfDecimalsForFormatting = function (format, decimals) {\n return decimals;\n };\n DisplayUnitSystem.prototype.isScalingUnit = function () {\n return this.displayUnit && this.displayUnit.isScaling();\n };\n DisplayUnitSystem.prototype.formatHelper = function (value, nonScientificFormat, format, decimals, trailingZeros) {\n // If the format is \"general\" and we want to override the number of decimal places then use the default numeric format string.\n if ((format === 'g' || format === 'G') && decimals != null)\n format = powerbi.visuals.valueFormatter.DefaultNumericFormat;\n format = powerbi.NumberFormat.addDecimalsToFormat(format, decimals, trailingZeros);\n if (format && !powerbi.formattingService.isStandardNumberFormat(format))\n return powerbi.formattingService.formatNumberWithCustomOverride(value, format, nonScientificFormat);\n if (!format)\n format = 'G';\n if (!nonScientificFormat)\n nonScientificFormat = '{0}';\n var text = powerbi.formattingService.formatValue(value, format);\n return powerbi.formattingService.format(nonScientificFormat, [text]);\n };\n /** Formats a single value by choosing an appropriate base for the DisplayUnitSystem before formatting. */\n DisplayUnitSystem.prototype.formatSingleValue = function (value, format, decimals, trailingZeros) {\n // Change unit base to a value appropriate for this value\n this.update(this.shouldUseValuePrecision(value) ? powerbi.Double.getPrecision(value, 8) : value);\n return this.format(value, format, decimals, trailingZeros);\n };\n DisplayUnitSystem.prototype.shouldUseValuePrecision = function (value) {\n if (this.units.length === 0)\n return true;\n // Check if the value is big enough to have a valid unit by checking against the smallest unit (that it's value bigger than 1).\n var applicableRangeMin = 0;\n for (var i = 0; i < this.units.length; i++) {\n if (this.units[i].isScaling()) {\n applicableRangeMin = this.units[i].applicableRangeMin;\n break;\n }\n }\n return Math.abs(value) < applicableRangeMin;\n };\n DisplayUnitSystem.prototype.isScientific = function (value) {\n return value < -defaultScientificBigNumbersBoundary || value > defaultScientificBigNumbersBoundary ||\n (-scientificSmallNumbersBoundary < value && value < scientificSmallNumbersBoundary && value !== 0);\n };\n DisplayUnitSystem.prototype.hasScientitifcFormat = function (format) {\n return format && format.toUpperCase().indexOf(\"E\") !== -1;\n };\n DisplayUnitSystem.prototype.supportsScientificFormat = function (format) {\n if (format)\n return SUPPORTED_SCIENTIFIC_FORMATS.test(format);\n return true;\n };\n DisplayUnitSystem.prototype.shouldFallbackToScientific = function (value, format) {\n return !this.hasScientitifcFormat(format)\n && this.supportsScientificFormat(format)\n && this.isScientific(value);\n };\n DisplayUnitSystem.prototype.getScientificFormat = function (data, format, decimals, trailingZeros) {\n // Use scientific format outside of the range\n if (this.isFormatSupported(format) && this.shouldFallbackToScientific(data, format)) {\n var numericFormat = powerbi.NumberFormat.getNumericFormat(data, format);\n if (decimals)\n numericFormat = powerbi.NumberFormat.addDecimalsToFormat(numericFormat ? numericFormat : '0', Math.abs(decimals), trailingZeros);\n if (numericFormat)\n return numericFormat + SCIENTIFIC_FORMAT;\n else\n return DEFAULT_SCIENTIFIC_FORMAT;\n }\n return format;\n };\n DisplayUnitSystem.UNSUPPORTED_FORMATS = /^(p\\d*)|(.*\\%)|(e\\d*)$/i;\n return DisplayUnitSystem;\n }());\n powerbi.DisplayUnitSystem = DisplayUnitSystem;\n /** Provides a unit system that is defined by formatting in the model, and is suitable for visualizations shown in single number visuals in explore mode. */\n var NoDisplayUnitSystem = (function (_super) {\n __extends(NoDisplayUnitSystem, _super);\n // Constructor\n function NoDisplayUnitSystem() {\n _super.call(this, []);\n }\n return NoDisplayUnitSystem;\n }(DisplayUnitSystem));\n powerbi.NoDisplayUnitSystem = NoDisplayUnitSystem;\n /** Provides a unit system that creates a more concise format for displaying values. This is suitable for most of the cases where\n we are showing values (chart axes) and as such it is the default unit system. */\n var DefaultDisplayUnitSystem = (function (_super) {\n __extends(DefaultDisplayUnitSystem, _super);\n // Constructor\n function DefaultDisplayUnitSystem(unitLookup) {\n _super.call(this, DefaultDisplayUnitSystem.getUnits(unitLookup));\n }\n // Methods\n DefaultDisplayUnitSystem.prototype.format = function (data, format, decimals, trailingZeros) {\n format = this.getScientificFormat(data, format, decimals, trailingZeros);\n return _super.prototype.format.call(this, data, format, decimals, trailingZeros);\n };\n DefaultDisplayUnitSystem.reset = function () {\n DefaultDisplayUnitSystem.units = null;\n };\n DefaultDisplayUnitSystem.getUnits = function (unitLookup) {\n if (!DefaultDisplayUnitSystem.units) {\n DefaultDisplayUnitSystem.units = createDisplayUnits(unitLookup, function (value, previousUnitValue, min) {\n // When dealing with millions/billions/trillions we need to switch to millions earlier: for example instead of showing 100K 200K 300K we should show 0.1M 0.2M 0.3M etc\n if (value - previousUnitValue >= 1000) {\n return value / 10;\n }\n return min;\n });\n // Ensure last unit has max of infinity\n DefaultDisplayUnitSystem.units[DefaultDisplayUnitSystem.units.length - 1].applicableRangeMax = Infinity;\n }\n return DefaultDisplayUnitSystem.units;\n };\n return DefaultDisplayUnitSystem;\n }(DisplayUnitSystem));\n powerbi.DefaultDisplayUnitSystem = DefaultDisplayUnitSystem;\n /** Provides a unit system that creates a more concise format for displaying values, but only allows showing a unit if we have at least\n one of those units (e.g. 0.9M is not allowed since it's less than 1 million). This is suitable for cases such as dashboard tiles\n where we have restricted space but do not want to show partial units. */\n var WholeUnitsDisplayUnitSystem = (function (_super) {\n __extends(WholeUnitsDisplayUnitSystem, _super);\n // Constructor\n function WholeUnitsDisplayUnitSystem(unitLookup) {\n _super.call(this, WholeUnitsDisplayUnitSystem.getUnits(unitLookup));\n }\n WholeUnitsDisplayUnitSystem.reset = function () {\n WholeUnitsDisplayUnitSystem.units = null;\n };\n WholeUnitsDisplayUnitSystem.getUnits = function (unitLookup) {\n if (!WholeUnitsDisplayUnitSystem.units) {\n WholeUnitsDisplayUnitSystem.units = createDisplayUnits(unitLookup);\n // Ensure last unit has max of infinity\n WholeUnitsDisplayUnitSystem.units[WholeUnitsDisplayUnitSystem.units.length - 1].applicableRangeMax = Infinity;\n }\n return WholeUnitsDisplayUnitSystem.units;\n };\n WholeUnitsDisplayUnitSystem.prototype.format = function (data, format, decimals, trailingZeros) {\n format = this.getScientificFormat(data, format, decimals, trailingZeros);\n return _super.prototype.format.call(this, data, format, decimals, trailingZeros);\n };\n return WholeUnitsDisplayUnitSystem;\n }(DisplayUnitSystem));\n powerbi.WholeUnitsDisplayUnitSystem = WholeUnitsDisplayUnitSystem;\n var DataLabelsDisplayUnitSystem = (function (_super) {\n __extends(DataLabelsDisplayUnitSystem, _super);\n function DataLabelsDisplayUnitSystem(unitLookup) {\n _super.call(this, DataLabelsDisplayUnitSystem.getUnits(unitLookup));\n }\n DataLabelsDisplayUnitSystem.prototype.isFormatSupported = function (format) {\n return !DataLabelsDisplayUnitSystem.UNSUPPORTED_FORMATS.test(format);\n };\n DataLabelsDisplayUnitSystem.getUnits = function (unitLookup) {\n if (!DataLabelsDisplayUnitSystem.units) {\n var units = [];\n var adjustMinBasedOnPreviousUnit = function (value, previousUnitValue, min) {\n // Never returns true, we are always ignoring\n // We do not early switch (e.g. 100K instead of 0.1M)\n // Intended? If so, remove this function, otherwise, remove if statement\n if (value === -1)\n if (value - previousUnitValue >= 1000) {\n return value / 10;\n }\n return min;\n };\n // Add Auto & None\n var names = unitLookup(-1);\n addUnitIfNonEmpty(units, DataLabelsDisplayUnitSystem.AUTO_DISPLAYUNIT_VALUE, names.title, names.format, adjustMinBasedOnPreviousUnit);\n names = unitLookup(0);\n addUnitIfNonEmpty(units, DataLabelsDisplayUnitSystem.NONE_DISPLAYUNIT_VALUE, names.title, names.format, adjustMinBasedOnPreviousUnit);\n // Add normal units\n DataLabelsDisplayUnitSystem.units = units.concat(createDisplayUnits(unitLookup, adjustMinBasedOnPreviousUnit));\n // Ensure last unit has max of infinity\n DataLabelsDisplayUnitSystem.units[DataLabelsDisplayUnitSystem.units.length - 1].applicableRangeMax = Infinity;\n }\n return DataLabelsDisplayUnitSystem.units;\n };\n DataLabelsDisplayUnitSystem.prototype.format = function (data, format, decimals, trailingZeros) {\n format = this.getScientificFormat(data, format, decimals, trailingZeros);\n return _super.prototype.format.call(this, data, format, decimals, trailingZeros);\n };\n // Constants\n DataLabelsDisplayUnitSystem.AUTO_DISPLAYUNIT_VALUE = 0;\n DataLabelsDisplayUnitSystem.NONE_DISPLAYUNIT_VALUE = 1;\n DataLabelsDisplayUnitSystem.UNSUPPORTED_FORMATS = /^(e\\d*)$/i;\n return DataLabelsDisplayUnitSystem;\n }(DisplayUnitSystem));\n powerbi.DataLabelsDisplayUnitSystem = DataLabelsDisplayUnitSystem;\n function createDisplayUnits(unitLookup, adjustMinBasedOnPreviousUnit) {\n var units = [];\n for (var i = 3; i < maxExponent; i++) {\n var names = unitLookup(i);\n if (names)\n addUnitIfNonEmpty(units, powerbi.Double.pow10(i), names.title, names.format, adjustMinBasedOnPreviousUnit);\n }\n return units;\n }\n function addUnitIfNonEmpty(units, value, title, labelFormat, adjustMinBasedOnPreviousUnit) {\n if (title || labelFormat) {\n var min = value;\n if (units.length > 0) {\n var previousUnit = units[units.length - 1];\n if (adjustMinBasedOnPreviousUnit)\n min = adjustMinBasedOnPreviousUnit(value, previousUnit.value, min);\n previousUnit.applicableRangeMax = min;\n }\n var unit = new DisplayUnit();\n unit.value = value;\n unit.applicableRangeMin = min;\n unit.applicableRangeMax = min * 1000;\n unit.title = title;\n unit.labelFormat = labelFormat;\n units.push(unit);\n }\n }\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var NumericSequence = (function () {\n function NumericSequence() {\n }\n NumericSequence.calculate = function (range, expectedCount, maxAllowedMargin, minPower, useZeroRefPoint, steps) {\n debug.assertValue(range, \"range\");\n debug.assert(expectedCount === undefined || (expectedCount >= NumericSequence.MIN_COUNT && expectedCount <= NumericSequence.MAX_COUNT), \"expectedCount\");\n debug.assert(minPower === undefined || (minPower >= powerbi.Double.MIN_EXP && minPower <= powerbi.Double.MAX_EXP), \"minPower\");\n debug.assert(maxAllowedMargin === undefined || (maxAllowedMargin >= 0), \"maxAllowedMargin\");\n var result = new NumericSequence();\n if (expectedCount === undefined)\n expectedCount = 10;\n else\n expectedCount = powerbi.Double.ensureInRange(expectedCount, NumericSequence.MIN_COUNT, NumericSequence.MAX_COUNT);\n if (minPower === undefined)\n minPower = powerbi.Double.MIN_EXP;\n if (useZeroRefPoint === undefined)\n useZeroRefPoint = false;\n if (maxAllowedMargin === undefined)\n maxAllowedMargin = 1;\n if (steps === undefined)\n steps = [1, 2, 5];\n // Handle single stop case\n if (range.forcedSingleStop) {\n result.interval = range.getSize();\n result.intervalOffset = result.interval - (range.forcedSingleStop - range.min);\n result.min = range.min;\n result.max = range.max;\n result.sequence = [range.forcedSingleStop];\n return result;\n }\n var interval = 0;\n var min = 0;\n var max = 9;\n var canExtendMin = maxAllowedMargin > 0 && !range.hasFixedMin;\n var canExtendMax = maxAllowedMargin > 0 && !range.hasFixedMax;\n var size = range.getSize();\n var exp = powerbi.Double.log10(size);\n // Account for Exp of steps\n var stepExp = powerbi.Double.log10(steps[0]);\n exp = exp - stepExp;\n // Account for MaxCount\n var expectedCountExp = powerbi.Double.log10(expectedCount);\n exp = exp - expectedCountExp;\n // Account for MinPower\n exp = Math.max(exp, minPower - stepExp + 1);\n var count = undefined;\n // Create array of \"good looking\" numbers\n if (interval !== 0) {\n // If explicit interval is defined - use it instead of the steps array.\n var power = powerbi.Double.pow10(exp);\n var roundMin = powerbi.Double.floorToPrecision(range.min, power);\n var roundMax = powerbi.Double.ceilToPrecision(range.max, power);\n var roundRange = powerbi.NumericSequenceRange.calculateFixedRange(roundMin, roundMax);\n roundRange.shrinkByStep(range, interval);\n min = roundRange.min;\n max = roundRange.max;\n count = Math.floor(roundRange.getSize() / interval);\n }\n else {\n // No interval defined -> find optimal interval\n var dexp = void 0;\n for (dexp = 0; dexp < 3; dexp++) {\n var e = exp + dexp;\n var power = powerbi.Double.pow10(e);\n var roundMin = powerbi.Double.floorToPrecision(range.min, power);\n var roundMax = powerbi.Double.ceilToPrecision(range.max, power);\n // Go throught the steps array looking for the smallest step that produces the right interval count.\n var stepsCount = steps.length;\n var stepPower = powerbi.Double.pow10(e - 1);\n for (var i = 0; i < stepsCount; i++) {\n var step = steps[i] * stepPower;\n var roundRange = powerbi.NumericSequenceRange.calculateFixedRange(roundMin, roundMax, useZeroRefPoint);\n roundRange.shrinkByStep(range, step);\n // If the range is based on Data we might need to extend it to provide nice data margins.\n if (canExtendMin && range.min === roundRange.min && maxAllowedMargin >= 1)\n roundRange.min -= step;\n if (canExtendMax && range.max === roundRange.max && maxAllowedMargin >= 1)\n roundRange.max += step;\n // Count the intervals\n count = powerbi.Double.ceilWithPrecision(roundRange.getSize() / step);\n if (count <= expectedCount || (dexp === 2 && i === stepsCount - 1) || (expectedCount === 1 && count === 2 && (step > range.getSize() || (range.min < 0 && range.max > 0 && step * 2 >= range.getSize())))) {\n interval = step;\n min = roundRange.min;\n max = roundRange.max;\n break;\n }\n }\n // Increase the scale power until the interval is found\n if (interval !== 0)\n break;\n }\n }\n // Avoid extreme count cases (>1000 ticks)\n if (count > expectedCount * 32 || count > NumericSequence.MAX_COUNT) {\n count = Math.min(expectedCount * 32, NumericSequence.MAX_COUNT);\n interval = (max - min) / count;\n }\n result.min = min;\n result.max = max;\n result.interval = interval;\n result.intervalOffset = min - range.min;\n result.maxAllowedMargin = maxAllowedMargin;\n result.canExtendMin = canExtendMin;\n result.canExtendMax = canExtendMax;\n // Fill in the Sequence\n var precision = powerbi.Double.getPrecision(interval, 0);\n result.precision = precision;\n var sequence = [];\n var x = powerbi.Double.roundToPrecision(min, precision);\n sequence.push(x);\n for (var i = 0; i < count; i++) {\n x = powerbi.Double.roundToPrecision(x + interval, precision);\n sequence.push(x);\n }\n result.sequence = sequence;\n result.trimMinMax(range.min, range.max);\n return result;\n };\n /**\n * Calculates the sequence of int numbers which are mapped to the multiples of the units grid.\n * @min - The minimum of the range.\n * @max - The maximum of the range.\n * @maxCount - The max count of intervals.\n * @steps - array of intervals.\n */\n NumericSequence.calculateUnits = function (min, max, maxCount, steps) {\n // Initialization actions\n maxCount = powerbi.Double.ensureInRange(maxCount, NumericSequence.MIN_COUNT, NumericSequence.MAX_COUNT);\n if (min === max) {\n max = min + 1;\n }\n var stepCount = 0;\n var step = 0;\n // Calculate step\n for (var i = 0; i < steps.length; i++) {\n step = steps[i];\n var maxStepCount = powerbi.Double.ceilWithPrecision(max / step);\n var minStepCount = powerbi.Double.floorWithPrecision(min / step);\n stepCount = maxStepCount - minStepCount;\n if (stepCount <= maxCount) {\n break;\n }\n }\n // Calculate the offset\n var offset = -min;\n offset = offset % step;\n // Create sequence\n var result = new NumericSequence();\n result.sequence = [];\n for (var x = min + offset;; x += step) {\n result.sequence.push(x);\n if (x >= max)\n break;\n }\n result.interval = step;\n result.intervalOffset = offset;\n result.min = result.sequence[0];\n result.max = result.sequence[result.sequence.length - 1];\n return result;\n };\n NumericSequence.prototype.trimMinMax = function (min, max) {\n var minMargin = (min - this.min) / this.interval;\n var maxMargin = (this.max - max) / this.interval;\n var marginPrecision = 0.001;\n if (!this.canExtendMin || (minMargin > this.maxAllowedMargin && minMargin > marginPrecision)) {\n this.min = min;\n }\n if (!this.canExtendMax || (maxMargin > this.maxAllowedMargin && maxMargin > marginPrecision)) {\n this.max = max;\n }\n };\n NumericSequence.MIN_COUNT = 1;\n NumericSequence.MAX_COUNT = 1000;\n return NumericSequence;\n }());\n powerbi.NumericSequence = NumericSequence;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var NumericSequenceRange = (function () {\n function NumericSequenceRange() {\n }\n NumericSequenceRange.prototype._ensureIncludeZero = function () {\n if (this.includeZero) {\n // fixed min and max has higher priority than includeZero\n if (this.min > 0 && !this.hasFixedMin) {\n this.min = 0;\n }\n if (this.max < 0 && !this.hasFixedMax) {\n this.max = 0;\n }\n }\n };\n NumericSequenceRange.prototype._ensureNotEmpty = function () {\n if (this.min === this.max) {\n if (!this.min) {\n this.min = 0;\n this.max = NumericSequenceRange.DEFAULT_MAX;\n this.hasFixedMin = true;\n this.hasFixedMax = true;\n }\n else {\n // We are dealing with a single data value (includeZero is not set)\n // In order to fix the range we need to extend it in both directions by half of the interval.\n // Interval is calculated based on the number:\n // 1. Integers below 10,000 are extended by 0.5: so the [2006-2006] empty range is extended to [2005.5-2006.5] range and the ForsedSingleStop=2006\n // 2. Other numbers are extended by half of their power: [700,001-700,001] => [650,001-750,001] and the ForsedSingleStop=null as we want the intervals to be calculated to cover the range.\n var value = this.min;\n var exp = powerbi.Double.log10(Math.abs(value));\n var step = void 0;\n if (exp >= 0 && exp < 4) {\n step = 0.5;\n this.forcedSingleStop = value;\n }\n else {\n step = powerbi.Double.pow10(exp) / 2;\n this.forcedSingleStop = null;\n }\n this.min = value - step;\n this.max = value + step;\n }\n }\n };\n NumericSequenceRange.prototype._ensureDirection = function () {\n if (this.min > this.max) {\n var temp = this.min;\n this.min = this.max;\n this.max = temp;\n }\n };\n NumericSequenceRange.prototype.getSize = function () {\n return this.max - this.min;\n };\n NumericSequenceRange.prototype.shrinkByStep = function (range, step) {\n debug.assertValue(range, \"range\");\n debug.assert(step > 0, \"step\");\n var oldCount = this.min / step;\n var newCount = range.min / step;\n var deltaCount = Math.floor(newCount - oldCount);\n this.min += deltaCount * step;\n oldCount = this.max / step;\n newCount = range.max / step;\n deltaCount = Math.ceil(newCount - oldCount);\n this.max += deltaCount * step;\n };\n NumericSequenceRange.calculate = function (dataMin, dataMax, fixedMin, fixedMax, includeZero) {\n debug.assert(dataMin <= dataMax, \"dataMin should be less or equal to dataMax.\");\n debug.assert(!fixedMin || !fixedMax || fixedMin <= fixedMax, \"fixedMin should be less or equal to fixedMax.\");\n var result = new NumericSequenceRange();\n result.includeZero = includeZero ? true : false;\n result.hasDataRange = ValueUtil.hasValue(dataMin) && ValueUtil.hasValue(dataMax);\n result.hasFixedMin = ValueUtil.hasValue(fixedMin);\n result.hasFixedMax = ValueUtil.hasValue(fixedMax);\n dataMin = powerbi.Double.ensureInRange(dataMin, NumericSequenceRange.MIN_SUPPORTED_DOUBLE, NumericSequenceRange.MAX_SUPPORTED_DOUBLE);\n dataMax = powerbi.Double.ensureInRange(dataMax, NumericSequenceRange.MIN_SUPPORTED_DOUBLE, NumericSequenceRange.MAX_SUPPORTED_DOUBLE);\n // Calculate the range using the min, max, dataRange\n if (result.hasFixedMin && result.hasFixedMax) {\n result.min = fixedMin;\n result.max = fixedMax;\n }\n else if (result.hasFixedMin) {\n result.min = fixedMin;\n result.max = dataMax > fixedMin ? dataMax : fixedMin;\n }\n else if (result.hasFixedMax) {\n result.min = dataMin < fixedMax ? dataMin : fixedMax;\n result.max = fixedMax;\n }\n else if (result.hasDataRange) {\n result.min = dataMin;\n result.max = dataMax;\n }\n else {\n result.min = 0;\n result.max = 0;\n }\n result._ensureIncludeZero();\n result._ensureNotEmpty();\n result._ensureDirection();\n if (result.min === 0) {\n result.hasFixedMin = true; // If the range starts from zero we should prevent extending the intervals into the negative range\n }\n else if (result.max === 0) {\n result.hasFixedMax = true; // If the range ends at zero we should prevent extending the intervals into the positive range\n }\n return result;\n };\n NumericSequenceRange.calculateDataRange = function (dataMin, dataMax, includeZero) {\n if (!ValueUtil.hasValue(dataMin) || !ValueUtil.hasValue(dataMax)) {\n return NumericSequenceRange.calculateFixedRange(0, NumericSequenceRange.DEFAULT_MAX);\n }\n else {\n return NumericSequenceRange.calculate(dataMin, dataMax, null, null, includeZero);\n }\n };\n NumericSequenceRange.calculateFixedRange = function (fixedMin, fixedMax, includeZero) {\n debug.assertValue(fixedMin, \"fixedMin\");\n debug.assertValue(fixedMax, \"fixedMax\");\n var result = new NumericSequenceRange();\n result.hasDataRange = false;\n result.includeZero = includeZero;\n result.min = fixedMin;\n result.max = fixedMax;\n result._ensureIncludeZero();\n result._ensureNotEmpty();\n result._ensureDirection();\n result.hasFixedMin = true;\n result.hasFixedMax = true;\n return result;\n };\n NumericSequenceRange.DEFAULT_MAX = 10;\n NumericSequenceRange.MIN_SUPPORTED_DOUBLE = -1E307;\n NumericSequenceRange.MAX_SUPPORTED_DOUBLE = 1E307;\n return NumericSequenceRange;\n }());\n powerbi.NumericSequenceRange = NumericSequenceRange;\n /** Note: Exported for testability */\n var ValueUtil;\n (function (ValueUtil) {\n function hasValue(value) {\n return value !== undefined && value !== null;\n }\n ValueUtil.hasValue = hasValue;\n })(ValueUtil = powerbi.ValueUtil || (powerbi.ValueUtil = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var valueFormatter;\n (function (valueFormatter) {\n var StringExtensions = jsCommon.StringExtensions;\n var BeautifiedFormat = {\n '0.00 %;-0.00 %;0.00 %': 'Percentage',\n '0.0 %;-0.0 %;0.0 %': 'Percentage1',\n };\n valueFormatter.DefaultIntegerFormat = 'g';\n valueFormatter.DefaultNumericFormat = '#,0.00';\n valueFormatter.DefaultDateFormat = 'd';\n var defaultLocalizedStrings = {\n 'NullValue': '(Blank)',\n 'BooleanTrue': 'True',\n 'BooleanFalse': 'False',\n 'NaNValue': 'NaN',\n 'InfinityValue': '+Infinity',\n 'NegativeInfinityValue': '-Infinity',\n 'RestatementComma': '{0}, {1}',\n 'RestatementCompoundAnd': '{0} and {1}',\n 'RestatementCompoundOr': '{0} or {1}',\n 'DisplayUnitSystem_EAuto_Title': 'Auto',\n 'DisplayUnitSystem_E0_Title': 'None',\n 'DisplayUnitSystem_E3_LabelFormat': '{0}K',\n 'DisplayUnitSystem_E3_Title': 'Thousands',\n 'DisplayUnitSystem_E6_LabelFormat': '{0}M',\n 'DisplayUnitSystem_E6_Title': 'Millions',\n 'DisplayUnitSystem_E9_LabelFormat': '{0}bn',\n 'DisplayUnitSystem_E9_Title': 'Billions',\n 'DisplayUnitSystem_E12_LabelFormat': '{0}T',\n 'DisplayUnitSystem_E12_Title': 'Trillions',\n 'Percentage': '#,0.##%',\n 'Percentage1': '#,0.#%',\n 'TableTotalLabel': 'Total',\n 'Tooltip_HighlightedValueDisplayName': 'Highlighted',\n 'Funnel_PercentOfFirst': 'Percent of first',\n 'Funnel_PercentOfPrevious': 'Percent of previous',\n 'Funnel_PercentOfFirst_Highlight': 'Percent of first (highlighted)',\n 'Funnel_PercentOfPrevious_Highlight': 'Percent of previous (highlighted)',\n // Geotagging strings\n 'GeotaggingString_Continent': 'continent',\n 'GeotaggingString_Continents': 'continents',\n 'GeotaggingString_Country': 'country',\n 'GeotaggingString_Countries': 'countries',\n 'GeotaggingString_State': 'state',\n 'GeotaggingString_States': 'states',\n 'GeotaggingString_City': 'city',\n 'GeotaggingString_Cities': 'cities',\n 'GeotaggingString_Town': 'town',\n 'GeotaggingString_Towns': 'towns',\n 'GeotaggingString_Province': 'province',\n 'GeotaggingString_Provinces': 'provinces',\n 'GeotaggingString_County': 'county',\n 'GeotaggingString_Counties': 'counties',\n 'GeotaggingString_Village': 'village',\n 'GeotaggingString_Villages': 'villages',\n 'GeotaggingString_Post': 'post',\n 'GeotaggingString_Zip': 'zip',\n 'GeotaggingString_Code': 'code',\n 'GeotaggingString_Place': 'place',\n 'GeotaggingString_Places': 'places',\n 'GeotaggingString_Address': 'address',\n 'GeotaggingString_Addresses': 'addresses',\n 'GeotaggingString_Street': 'street',\n 'GeotaggingString_Streets': 'streets',\n 'GeotaggingString_Longitude': 'longitude',\n 'GeotaggingString_Longitude_Short': 'lon',\n 'GeotaggingString_Latitude': 'latitude',\n 'GeotaggingString_Latitude_Short': 'lat',\n 'GeotaggingString_PostalCode': 'postal code',\n 'GeotaggingString_PostalCodes': 'postal codes',\n 'GeotaggingString_ZipCode': 'zip code',\n 'GeotaggingString_ZipCodes': 'zip codes',\n 'GeotaggingString_Territory': 'territory',\n 'GeotaggingString_Territories': 'territories',\n };\n function beautify(format) {\n var key = BeautifiedFormat[format];\n if (key)\n return defaultLocalizedStrings[key] || format;\n return format;\n }\n function describeUnit(exponent) {\n var exponentLookup = (exponent === -1) ? 'Auto' : exponent.toString();\n var title = defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_Title\"];\n var format = (exponent <= 0) ? '{0}' : defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_LabelFormat\"];\n if (title || format)\n return { title: title, format: format };\n }\n function getLocalizedString(stringId) {\n return defaultLocalizedStrings[stringId];\n }\n valueFormatter.getLocalizedString = getLocalizedString;\n // NOTE: Define default locale options, but these can be overriden by setLocaleOptions.\n var locale = {\n null: defaultLocalizedStrings['NullValue'],\n true: defaultLocalizedStrings['BooleanTrue'],\n false: defaultLocalizedStrings['BooleanFalse'],\n NaN: defaultLocalizedStrings['NaNValue'],\n infinity: defaultLocalizedStrings['InfinityValue'],\n negativeInfinity: defaultLocalizedStrings['NegativeInfinityValue'],\n beautify: function (format) { return beautify(format); },\n describe: function (exponent) { return describeUnit(exponent); },\n restatementComma: defaultLocalizedStrings['RestatementComma'],\n restatementCompoundAnd: defaultLocalizedStrings['RestatementCompoundAnd'],\n restatementCompoundOr: defaultLocalizedStrings['RestatementCompoundOr'],\n };\n var MaxScaledDecimalPlaces = 2;\n var MaxValueForDisplayUnitRounding = 1000;\n var MinIntegerValueForDisplayUnits = 10000;\n var MinPrecisionForDisplayUnits = 2;\n var DateTimeMetadataColumn = {\n displayName: '',\n type: powerbi.ValueType.fromPrimitiveTypeAndCategory(powerbi.PrimitiveType.DateTime),\n };\n function getFormatMetadata(format) {\n return powerbi.NumberFormat.getCustomFormatMetadata(format);\n }\n valueFormatter.getFormatMetadata = getFormatMetadata;\n function setLocaleOptions(options) {\n debug.assertValue(options, 'options');\n locale = options;\n powerbi.DefaultDisplayUnitSystem.reset();\n powerbi.WholeUnitsDisplayUnitSystem.reset();\n }\n valueFormatter.setLocaleOptions = setLocaleOptions;\n function createDefaultFormatter(formatString, allowFormatBeautification) {\n if (allowFormatBeautification === void 0) { allowFormatBeautification = false; }\n var formatBeaut = allowFormatBeautification ? locale.beautify(formatString) : formatString;\n return {\n format: function (value) {\n if (value == null)\n return locale.null;\n return formatCore(value, formatBeaut);\n }\n };\n }\n valueFormatter.createDefaultFormatter = createDefaultFormatter;\n /** Creates an IValueFormatter to be used for a range of values. */\n function create(options) {\n debug.assertValue(options, 'options');\n var format = !!options.allowFormatBeautification ? locale.beautify(options.format) : options.format;\n if (shouldUseNumericDisplayUnits(options)) {\n var displayUnitSystem_1 = createDisplayUnitSystem(options.displayUnitSystemType);\n var singleValueFormattingMode_1 = !!options.formatSingleValues;\n displayUnitSystem_1.update(Math.max(Math.abs(options.value || 0), Math.abs(options.value2 || 0)));\n var forcePrecision_1 = options.precision != null;\n var decimals_1;\n if (forcePrecision_1)\n decimals_1 = -options.precision;\n else if (displayUnitSystem_1.displayUnit && displayUnitSystem_1.displayUnit.value > 1)\n decimals_1 = -MaxScaledDecimalPlaces;\n // Detect axis precision\n if (options.detectAxisPrecision) {\n // Trailing zeroes\n forcePrecision_1 = true;\n var axisValue = options.value;\n if (displayUnitSystem_1.displayUnit && displayUnitSystem_1.displayUnit.value > 0)\n axisValue = axisValue / displayUnitSystem_1.displayUnit.value;\n if (powerbi.Double.isInteger(axisValue))\n decimals_1 = 0;\n else\n decimals_1 = powerbi.Double.log10(axisValue);\n }\n return {\n format: function (value) {\n var formattedValue = getStringFormat(value, true /*nullsAreBlank*/);\n if (!StringExtensions.isNullOrUndefinedOrWhiteSpaceString(formattedValue))\n return formattedValue;\n // Round to Double.DEFAULT_PRECISION\n if (value && !displayUnitSystem_1.isScalingUnit() && Math.abs(value) < MaxValueForDisplayUnitRounding && !forcePrecision_1)\n value = powerbi.Double.roundToPrecision(value);\n return singleValueFormattingMode_1 ?\n displayUnitSystem_1.formatSingleValue(value, format, decimals_1, forcePrecision_1) :\n displayUnitSystem_1.format(value, format, decimals_1, forcePrecision_1);\n },\n displayUnit: displayUnitSystem_1.displayUnit,\n options: options\n };\n }\n if (shouldUseDateUnits(options.value, options.value2, options.tickCount)) {\n var unit_1 = powerbi.DateTimeSequence.getIntervalUnit(options.value /* minDate */, options.value2 /* maxDate */, options.tickCount);\n return {\n format: function (value) {\n if (value == null)\n return locale.null;\n var formatString = powerbi.formattingService.dateFormatString(unit_1);\n return formatCore(value, formatString);\n },\n options: options\n };\n }\n return createDefaultFormatter(format);\n }\n valueFormatter.create = create;\n function format(value, format, allowFormatBeautification) {\n if (value == null)\n return locale.null;\n return formatCore(value, !!allowFormatBeautification ? locale.beautify(format) : format);\n }\n valueFormatter.format = format;\n function getValueFormat(value, columnType) {\n // If column type not defined or is not datetime\n // ...and the value is of time datetime,\n // then use the default date format string\n if ((!columnType || !columnType.dateTime) && value instanceof Date)\n return getFormatString(DateTimeMetadataColumn, null, false);\n }\n function formatValueColumn(value, column, formatStringProp) {\n var valueFormat = getValueFormat(value, column.type);\n if (valueFormat)\n return formatCore(value, valueFormat);\n else\n return formatCore(value, getFormatString(column, formatStringProp));\n }\n valueFormatter.formatValueColumn = formatValueColumn;\n function createDisplayUnitSystem(displayUnitSystemType) {\n if (displayUnitSystemType == null)\n return new powerbi.DefaultDisplayUnitSystem(locale.describe);\n switch (displayUnitSystemType) {\n case powerbi.DisplayUnitSystemType.Default:\n return new powerbi.DefaultDisplayUnitSystem(locale.describe);\n case powerbi.DisplayUnitSystemType.WholeUnits:\n return new powerbi.WholeUnitsDisplayUnitSystem(locale.describe);\n case powerbi.DisplayUnitSystemType.Verbose:\n return new powerbi.NoDisplayUnitSystem();\n case powerbi.DisplayUnitSystemType.DataLabels:\n return new powerbi.DataLabelsDisplayUnitSystem(locale.describe);\n default:\n debug.assertFail('Unknown display unit system type');\n return new powerbi.DefaultDisplayUnitSystem(locale.describe);\n }\n }\n function shouldUseNumericDisplayUnits(options) {\n var value = options.value;\n var value2 = options.value2;\n var format = options.format;\n // For singleValue visuals like card, gauge we don't want to roundoff data to the nearest thousands so format the whole number / integers below 10K to not use display units\n if (options.formatSingleValues && format) {\n if (Math.abs(value) < MinIntegerValueForDisplayUnits) {\n var isCustomFormat = !powerbi.NumberFormat.isStandardFormat(format);\n if (isCustomFormat) {\n var precision = powerbi.NumberFormat.getCustomFormatMetadata(format, true /*calculatePrecision*/).precision;\n if (precision < MinPrecisionForDisplayUnits)\n return false;\n }\n else if (powerbi.Double.isInteger(value))\n return false;\n }\n }\n if ((typeof value === 'number') || (typeof value2 === 'number')) {\n return true;\n }\n }\n function shouldUseDateUnits(value, value2, tickCount) {\n // must check both value and value2 because we'll need to get an interval for date units\n return (value instanceof Date) && (value2 instanceof Date) && (tickCount !== undefined && tickCount !== null);\n }\n /*\n * Get the column format. Order of precendence is:\n * 1. Column format\n * 2. Default PowerView policy for column type\n */\n function getFormatString(column, formatStringProperty, suppressTypeFallback) {\n if (column) {\n if (formatStringProperty) {\n var propertyValue = powerbi.DataViewObjects.getValue(column.objects, formatStringProperty);\n if (propertyValue)\n return propertyValue;\n }\n if (!suppressTypeFallback) {\n var columnType = column.type;\n if (columnType) {\n if (columnType.dateTime)\n return valueFormatter.DefaultDateFormat;\n if (columnType.integer)\n return valueFormatter.DefaultIntegerFormat;\n if (columnType.numeric)\n return valueFormatter.DefaultNumericFormat;\n }\n }\n }\n }\n valueFormatter.getFormatString = getFormatString;\n function formatListCompound(strings, conjunction) {\n var result;\n if (!strings) {\n return null;\n }\n var length = strings.length;\n if (length > 0) {\n result = strings[0];\n var lastIndex = length - 1;\n for (var i = 1, len = lastIndex; i < len; i++) {\n var value = strings[i];\n result = StringExtensions.format(locale.restatementComma, result, value);\n }\n if (length > 1) {\n var value = strings[lastIndex];\n result = StringExtensions.format(conjunction, result, value);\n }\n }\n else {\n result = null;\n }\n return result;\n }\n /** The returned string will look like 'A, B, ..., and C' */\n function formatListAnd(strings) {\n return formatListCompound(strings, locale.restatementCompoundAnd);\n }\n valueFormatter.formatListAnd = formatListAnd;\n /** The returned string will look like 'A, B, ..., or C' */\n function formatListOr(strings) {\n return formatListCompound(strings, locale.restatementCompoundOr);\n }\n valueFormatter.formatListOr = formatListOr;\n function formatCore(value, format) {\n var formattedValue = getStringFormat(value, false /*nullsAreBlank*/);\n if (!StringExtensions.isNullOrUndefinedOrWhiteSpaceString(formattedValue))\n return formattedValue;\n return powerbi.formattingService.formatValue(value, format);\n }\n function getStringFormat(value, nullsAreBlank) {\n if (value == null && nullsAreBlank)\n return locale.null;\n if (value === true)\n return locale.true;\n if (value === false)\n return locale.false;\n if (typeof value === 'number' && isNaN(value))\n return locale.NaN;\n if (value === Number.NEGATIVE_INFINITY)\n return locale.negativeInfinity;\n if (value === Number.POSITIVE_INFINITY)\n return locale.infinity;\n return '';\n }\n function getDisplayUnits(displayUnitSystemType) {\n var displayUnitSystem = createDisplayUnitSystem(displayUnitSystemType);\n return displayUnitSystem.units;\n }\n valueFormatter.getDisplayUnits = getDisplayUnits;\n })(valueFormatter = visuals.valueFormatter || (visuals.valueFormatter = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataRoleHelper;\n (function (DataRoleHelper) {\n function getMeasureIndexOfRole(grouped, roleName) {\n if (!_.isEmpty(grouped)) {\n var firstGroup = grouped[0];\n if (firstGroup.values && firstGroup.values.length > 0) {\n for (var i = 0, len = firstGroup.values.length; i < len; ++i) {\n var value = firstGroup.values[i];\n if (value && value.source) {\n if (hasRole(value.source, roleName))\n return i;\n }\n }\n }\n }\n return -1;\n }\n DataRoleHelper.getMeasureIndexOfRole = getMeasureIndexOfRole;\n function getCategoryIndexOfRole(categories, roleName) {\n if (!_.isEmpty(categories)) {\n for (var i = 0, ilen = categories.length; i < ilen; i++) {\n if (hasRole(categories[i].source, roleName))\n return i;\n }\n }\n return -1;\n }\n DataRoleHelper.getCategoryIndexOfRole = getCategoryIndexOfRole;\n function hasRole(column, name) {\n var roles = column.roles;\n return roles && roles[name];\n }\n DataRoleHelper.hasRole = hasRole;\n function hasRoleInDataView(dataView, name) {\n return dataView != null\n && dataView.metadata != null\n && dataView.metadata.columns\n && _.any(dataView.metadata.columns, function (c) { return c.roles && c.roles[name] !== undefined; });\n }\n DataRoleHelper.hasRoleInDataView = hasRoleInDataView;\n function hasRoleInValueColumn(valueColumn, name) {\n return valueColumn && valueColumn.source && valueColumn.source.roles && (valueColumn.source.roles[name] === true);\n }\n DataRoleHelper.hasRoleInValueColumn = hasRoleInValueColumn;\n })(DataRoleHelper = data.DataRoleHelper || (data.DataRoleHelper = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n function createIDataViewCategoricalReader(dataView) {\n return new DataViewCategoricalReader(dataView);\n }\n data.createIDataViewCategoricalReader = createIDataViewCategoricalReader;\n var DataViewCategoricalReader = (function () {\n function DataViewCategoricalReader(dataView) {\n debug.assertValue(dataView, 'dataView');\n this.dataView = dataView;\n // Validate categories\n var categorical;\n if (dataView)\n categorical = dataView.categorical;\n var categories;\n if (categorical)\n categories = this.categories = categorical.categories;\n this.hasValidCategories = !_.isEmpty(categories);\n // Validate values\n var values;\n if (categorical)\n values = categorical.values;\n // We need to access grouped as long as values is non-null; if it's an empty array (meaning there is a category + series), we'll use grouped for non-value stuff\n // TODO: think a bit more about how to represent this internally; Maybe split this up between hasGroup and hasValidValues or something\n this.hasAnyValidValues = false;\n if (values != null) {\n var grouped = dataView.categorical.values.grouped();\n if (grouped.length > 0) {\n this.hasAnyValidValues = true;\n this.grouped = grouped;\n // Iterate through the first group's values to populate the valueRoleIndexMapping\n var valueRoleIndexMapping = {};\n var firstGroupValues = grouped[0].values;\n for (var valueIndex = 0, valueCount = firstGroupValues.length; valueIndex < valueCount; valueIndex++) {\n var valueRoles = firstGroupValues[valueIndex].source.roles;\n for (var role in valueRoles) {\n if (valueRoles[role]) {\n if (!valueRoleIndexMapping[role])\n valueRoleIndexMapping[role] = [];\n valueRoleIndexMapping[role].push(valueIndex);\n }\n }\n }\n this.valueRoleIndexMapping = valueRoleIndexMapping;\n }\n }\n if (this.hasAnyValidValues)\n this.dataHasDynamicSeries = !!this.dataView.categorical.values.source;\n }\n // Category methods\n DataViewCategoricalReader.prototype.hasCategories = function () {\n return this.hasValidCategories;\n };\n DataViewCategoricalReader.prototype.getCategoryCount = function () {\n if (this.hasValidCategories)\n return this.categories[0].values.length;\n else\n return 0;\n };\n DataViewCategoricalReader.prototype.getCategoryValues = function (roleName) {\n if (this.hasValidCategories) {\n var categories = this.getCategoryFromRole(roleName);\n return categories ? categories.values : undefined;\n }\n };\n DataViewCategoricalReader.prototype.getCategoryValue = function (roleName, categoryIndex) {\n if (this.hasValidCategories) {\n var categories = this.getCategoryFromRole(roleName);\n return categories ? categories.values[categoryIndex] : undefined;\n }\n };\n DataViewCategoricalReader.prototype.getCategoryColumn = function (roleName) {\n if (this.hasValidCategories)\n return this.getCategoryFromRole(roleName);\n };\n DataViewCategoricalReader.prototype.getCategoryMetadataColumn = function (roleName) {\n if (this.hasValidCategories) {\n var categories = this.getCategoryFromRole(roleName);\n return categories ? categories.source : undefined;\n }\n };\n DataViewCategoricalReader.prototype.getCategoryColumnIdentityFields = function (roleName) {\n if (this.hasValidCategories) {\n var categories = this.getCategoryFromRole(roleName);\n return categories ? categories.identityFields : undefined;\n }\n };\n DataViewCategoricalReader.prototype.getCategoryDisplayName = function (roleName) {\n if (this.hasValidCategories) {\n var targetColumn = this.getCategoryColumn(roleName);\n if (targetColumn && targetColumn.source) {\n return targetColumn.source.displayName;\n }\n }\n };\n DataViewCategoricalReader.prototype.hasCompositeCategories = function () {\n if (this.hasValidCategories)\n return this.categories.length > 1;\n };\n DataViewCategoricalReader.prototype.hasCategoryWithRole = function (roleName) {\n return DataRoleHelper.getCategoryIndexOfRole(this.categories, roleName) !== -1;\n };\n DataViewCategoricalReader.prototype.getCategoryObjects = function (roleName, categoryIndex) {\n if (this.hasValidCategories) {\n var category = this.getCategoryFromRole(roleName);\n if (category && category.objects) {\n return category.objects[categoryIndex];\n }\n }\n };\n DataViewCategoricalReader.prototype.getCategoryFromRole = function (roleName) {\n var categories = this.categories;\n return categories[DataRoleHelper.getCategoryIndexOfRole(categories, roleName)];\n };\n // Value and measure methods\n DataViewCategoricalReader.prototype.hasValues = function (roleName) {\n return this.valueRoleIndexMapping && !_.isEmpty(this.valueRoleIndexMapping[roleName]);\n };\n DataViewCategoricalReader.prototype.getValue = function (roleName, categoryIndex, seriesIndex) {\n if (seriesIndex === void 0) { seriesIndex = 0; }\n if (this.hasValues(roleName)) {\n if (this.dataHasDynamicSeries) {\n // For dynamic series, we only ever obtain the first value column from a role\n return this.getValueInternal(roleName, categoryIndex, seriesIndex, 0, false /* getHighlight */);\n }\n else {\n // For static series or single series, we obtain value columns from the first series\n // and use the seriesIndex to index into the value columns within the role\n return this.getValueInternal(roleName, categoryIndex, 0, seriesIndex, false /* getHighlight */);\n }\n }\n };\n DataViewCategoricalReader.prototype.getHighlight = function (roleName, categoryIndex, seriesIndex) {\n if (seriesIndex === void 0) { seriesIndex = 0; }\n if (this.hasValues(roleName)) {\n if (this.dataHasDynamicSeries) {\n // For dynamic series, we only ever obtain the first value column from a role\n return this.getValueInternal(roleName, categoryIndex, seriesIndex, 0, true /* getHighlight */);\n }\n else {\n // For static series or single series, we obtain value columns from the first series\n // and use the seriesIndex to index into the value columns within the role\n return this.getValueInternal(roleName, categoryIndex, 0, seriesIndex, true /* getHighlight */);\n }\n }\n };\n DataViewCategoricalReader.prototype.getAllValuesForRole = function (roleName, categoryIndex, seriesIndex) {\n if (seriesIndex === void 0) { seriesIndex = 0; }\n if (this.hasValues(roleName)) {\n var valuesInRole = [];\n for (var roleValueIndex = void 0, roleValueCount = this.valueRoleIndexMapping[roleName].length; roleValueIndex < roleValueCount; roleValueIndex++) {\n valuesInRole.push(this.getValueInternal(roleName, categoryIndex, seriesIndex, roleValueIndex, false /* getHighlight */));\n }\n return valuesInRole;\n }\n };\n DataViewCategoricalReader.prototype.getAllHighlightsForRole = function (roleName, categoryIndex, seriesIndex) {\n if (seriesIndex === void 0) { seriesIndex = 0; }\n if (this.hasValues(roleName)) {\n var valuesInRole = [];\n for (var roleValueIndex = void 0, roleValueCount = this.valueRoleIndexMapping[roleName].length; roleValueIndex < roleValueCount; roleValueIndex++) {\n valuesInRole.push(this.getValueInternal(roleName, categoryIndex, seriesIndex, roleValueIndex, true /* getHighlight */));\n }\n return valuesInRole;\n }\n };\n /**\n * Obtains the value from grouped.\n *\n * Grouped: [0] [1] [2] [3] (seriesIndex)\n * / \\\n * .values: [T0] [V0] [V1] [T1] [V2] (valueColumnIndex)\n * / \\ \\ \\\n * v.values: [0, 1, 2, 3, 4] [5, 6, 7, 8, 9] (categoryIndex)\n *\n *--------------------------------|\n * |Category |\n * Series|Value Columns |A B C D E|\n *--------------------------------|\n * 0|col0 (tooltip)| |\n * |col1 (value) | |\n * |col2 (value) | |\n * |col3 (tooltip)| |\n * |col4 (value) | |\n *--------------------------------|\n * 1|col0 (tooltip)| |\n * |col1 (value) |0 1 2 3 4|\n * |col2 (value) |5 6 7 8 9|\n * |col3 (tooltip)| |\n * |col4 (value) | |\n *--------------------------------|\n * 2|col0 (tooltip)|... |\n *\n * valueColumnIndexInRole is for indexing into the values for a single role\n * valueColumnIndex is for indexing into the entire value array including\n * all roles\n *\n * The valueRoleIndexMapping converts roleValueIndex and role (value role\n * with an index of 1) into groupedValueIndex (2)\n *\n * Example: getValueInternal(V, 3, 1, 1) returns 8: The second group,\n * the second value column with role \"value\" (which is converted to a\n * groupedValueIndex of 2) and the fourth value within that value column.\n */\n DataViewCategoricalReader.prototype.getValueInternal = function (roleName, categoryIndex, groupIndex, valueColumnIndexInRole, getHighlight) {\n if (this.hasValues(roleName)) {\n var valueColumnIndex = this.valueRoleIndexMapping[roleName][valueColumnIndexInRole];\n var groupedValues = this.grouped[groupIndex].values[valueColumnIndex];\n return getHighlight ? groupedValues.highlights[categoryIndex] : groupedValues.values[categoryIndex];\n }\n };\n DataViewCategoricalReader.prototype.getFirstNonNullValueForCategory = function (roleName, categoryIndex) {\n if (this.hasValues(roleName)) {\n if (!this.dataHasDynamicSeries) {\n debug.assert(this.grouped.length === 1, \"getFirstNonNullValueForCategory shouldn't be called if you have a static series\");\n return this.getValue(roleName, categoryIndex);\n }\n for (var seriesIndex = 0, seriesCount = this.grouped.length; seriesIndex < seriesCount; seriesIndex++) {\n var value = this.getValue(roleName, categoryIndex, seriesIndex);\n if (value != null) {\n return value;\n }\n }\n }\n };\n DataViewCategoricalReader.prototype.getMeasureQueryName = function (roleName) {\n if (this.hasValues(roleName))\n return this.grouped[0].values[this.valueRoleIndexMapping[roleName][0]].source.queryName;\n };\n DataViewCategoricalReader.prototype.getValueColumn = function (roleName, seriesIndex) {\n if (seriesIndex === void 0) { seriesIndex = 0; }\n if (this.hasValues(roleName)) {\n if (this.dataHasDynamicSeries) {\n return this.grouped[seriesIndex].values[this.valueRoleIndexMapping[roleName][0]];\n }\n else {\n return this.grouped[0].values[this.valueRoleIndexMapping[roleName][seriesIndex]];\n }\n }\n };\n DataViewCategoricalReader.prototype.getValueMetadataColumn = function (roleName, seriesIndex) {\n if (seriesIndex === void 0) { seriesIndex = 0; }\n var valueColumn = this.getValueColumn(roleName, seriesIndex);\n if (valueColumn) {\n return valueColumn.source;\n }\n };\n DataViewCategoricalReader.prototype.getValueDisplayName = function (roleName, seriesIndex) {\n if (this.hasValues(roleName)) {\n var targetColumn = this.getValueColumn(roleName, seriesIndex);\n if (targetColumn && targetColumn.source) {\n return targetColumn.source.displayName;\n }\n }\n };\n // Series methods\n DataViewCategoricalReader.prototype.hasDynamicSeries = function () {\n return this.dataHasDynamicSeries;\n };\n DataViewCategoricalReader.prototype.getSeriesCount = function (valueRoleName) {\n if (this.hasAnyValidValues) {\n if (this.dataHasDynamicSeries) {\n return this.grouped.length;\n }\n else if (valueRoleName) {\n return this.valueRoleIndexMapping[valueRoleName].length;\n }\n else {\n return 1;\n }\n }\n };\n DataViewCategoricalReader.prototype.getSeriesObjects = function (seriesIndex) {\n if (this.hasAnyValidValues)\n return this.grouped[seriesIndex].objects;\n };\n DataViewCategoricalReader.prototype.getSeriesValueColumns = function () {\n if (this.hasAnyValidValues)\n return this.dataView.categorical.values;\n };\n DataViewCategoricalReader.prototype.getSeriesValueColumnGroup = function (seriesIndex) {\n if (this.hasAnyValidValues)\n return this.grouped[seriesIndex];\n };\n DataViewCategoricalReader.prototype.getSeriesMetadataColumn = function () {\n if (this.hasAnyValidValues)\n return this.dataView.categorical.values.source;\n };\n DataViewCategoricalReader.prototype.getSeriesColumnIdentityFields = function () {\n if (this.hasAnyValidValues)\n return this.dataView.categorical.values.identityFields;\n };\n DataViewCategoricalReader.prototype.getSeriesName = function (seriesIndex) {\n if (this.hasAnyValidValues)\n return this.grouped[seriesIndex].name;\n };\n DataViewCategoricalReader.prototype.getSeriesDisplayName = function () {\n if (this.hasAnyValidValues && this.dataHasDynamicSeries)\n return this.dataView.categorical.values.source.displayName;\n };\n return DataViewCategoricalReader;\n }());\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var inherit = powerbi.Prototype.inherit;\n var inheritSingle = powerbi.Prototype.inheritSingle;\n var valueFormatter = powerbi.visuals.valueFormatter;\n var DataViewConcatenateCategoricalColumns;\n (function (DataViewConcatenateCategoricalColumns) {\n function detectAndApply(dataView, objectDescriptors, roleMappings, projectionOrdering, selects, projectionActiveItems) {\n debug.assertValue(dataView, 'dataView');\n debug.assertAnyValue(roleMappings, 'roleMappings');\n debug.assertAnyValue(projectionOrdering, 'projectionOrdering');\n var result = dataView;\n var dataViewCategorical = dataView.categorical;\n if (dataViewCategorical) {\n var concatenationSource = detectCategoricalRoleForHierarchicalGroup(dataViewCategorical, dataView.metadata, roleMappings, selects, projectionActiveItems);\n if (concatenationSource) {\n // Consider: Perhaps the re-ordering of categorical columns should happen in the function transformSelects(...) of dataViewTransform?\n var columnsSortedByProjectionOrdering = sortColumnsByProjectionOrdering(projectionOrdering, concatenationSource.roleName, concatenationSource.categories);\n if (columnsSortedByProjectionOrdering.length >= 2) {\n var activeItemsToIgnoreInConcatenation = _.chain(projectionActiveItems[concatenationSource.roleName])\n .filter(function (activeItemInfo) { return activeItemInfo.suppressConcat; })\n .map(function (activeItemInfo) { return activeItemInfo.queryRef; })\n .value();\n result = applyConcatenation(dataView, objectDescriptors, concatenationSource.roleName, columnsSortedByProjectionOrdering, activeItemsToIgnoreInConcatenation);\n }\n }\n }\n return result;\n }\n DataViewConcatenateCategoricalColumns.detectAndApply = detectAndApply;\n /** For applying concatenation to the DataViewCategorical that is the data for one of the frames in a play chart. */\n function applyToPlayChartCategorical(metadata, objectDescriptors, categoryRoleName, categorical) {\n debug.assertValue(metadata, 'metadata');\n debug.assertAnyValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(categorical, 'categorical');\n var result;\n if (!_.isEmpty(categorical.categories) && categorical.categories.length >= 2) {\n // In PlayChart, the code converts the Visual DataView with a matrix into multiple Visual DataViews, each with a categorical.\n // metadata and metadata.columns could already be inherited objects as they come from the Visual DataView with a matrix.\n // To guarantee that this method does not have any side effect on prototypeMetadata (which might already be an inherited obj),\n // use inherit() rather than inheritSingle() here.\n var transformingColumns_1 = inherit(metadata.columns);\n var transformingMetadata = inherit(metadata, function (m) { m.columns = transformingColumns_1; });\n var transformingDataView = { metadata: transformingMetadata, categorical: categorical };\n result = applyConcatenation(transformingDataView, objectDescriptors, categoryRoleName, categorical.categories, []);\n }\n else {\n result = { metadata: metadata, categorical: categorical };\n }\n return result;\n }\n DataViewConcatenateCategoricalColumns.applyToPlayChartCategorical = applyToPlayChartCategorical;\n /**\n * Returns the role and its assocated category columns (from dataViewCategorical.categories)\n * that should be concatenated for the case of hierarchical group.\n *\n * Note: In the future if we support sibling hierarchical groups in categorical,\n * change the return type to CategoryColumnsByRole[] and update detection logic.\n */\n function detectCategoricalRoleForHierarchicalGroup(dataViewCategorical, metadata, dataViewMappings, selects, projectionActiveItems) {\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\n debug.assertAnyValue(dataViewMappings, 'dataViewMappings');\n var result;\n var roleKinds = data.DataViewSelectTransform.createRoleKindFromMetadata(selects, metadata);\n var projections = data.DataViewSelectTransform.projectionsFromSelects(selects, projectionActiveItems);\n var supportedRoleMappings = powerbi.DataViewAnalysis.chooseDataViewMappings(projections, dataViewMappings, roleKinds).supportedMappings;\n // The following code will choose a role name only if all supportedRoleMappings share the same role for Categorical Category.\n // Handling multiple supportedRoleMappings is necessary for TransformActions with splits, which can happen in scenarios such as:\n // 1. combo chart with a field for both Line and Column values, and\n // 2. chart with regression line enabled.\n // In case 1, you can pretty much get exactly the one from supportedRoleMappings for which this code is currently processing for,\n // by looking at the index of the current split in DataViewTransformActions.splits.\n // In case 2, however, supportedRoleMappings.length will be different than DataViewTransformActions.splits.length, hence it is\n // not straight forward to figure out for which one in supportedRoleMappings is this code currently processing.\n // SO... This code will just choose the category role name if it is consistent across all supportedRoleMappings.\n var isEveryRoleMappingForCategorical = !_.isEmpty(supportedRoleMappings) &&\n _.every(supportedRoleMappings, function (roleMapping) { return !!roleMapping.categorical; });\n if (isEveryRoleMappingForCategorical) {\n var targetRoleName_1 = getSingleCategoryRoleNameInEveryRoleMapping(supportedRoleMappings);\n if (targetRoleName_1 &&\n isVisualExpectingMaxOneCategoryColumn(targetRoleName_1, supportedRoleMappings)) {\n var categoryColumnsForTargetRole_1 = _.filter(dataViewCategorical.categories, function (categoryColumn) { return categoryColumn.source.roles && !!categoryColumn.source.roles[targetRoleName_1]; });\n // There is no need to concatenate columns unless there is actually more than one column\n if (categoryColumnsForTargetRole_1.length >= 2) {\n // At least for now, we expect all category columns for the same role to have the same number of value entries.\n // If that's not the case, we won't run the concatenate logic for that role at all...\n var areValuesCountsEqual = _.every(categoryColumnsForTargetRole_1, function (categoryColumn) { return categoryColumn.values.length === categoryColumnsForTargetRole_1[0].values.length; });\n if (areValuesCountsEqual) {\n result = {\n roleName: targetRoleName_1,\n categories: categoryColumnsForTargetRole_1,\n };\n }\n }\n }\n }\n return result;\n }\n /** If all mappings in the specified roleMappings have the same single role name for their categorical category roles, return that role name, else returns undefined. */\n function getSingleCategoryRoleNameInEveryRoleMapping(categoricalRoleMappings) {\n debug.assertNonEmpty(categoricalRoleMappings, 'categoricalRoleMappings');\n debug.assert(_.every(categoricalRoleMappings, function (roleMapping) { return !!roleMapping.categorical; }), 'All mappings in categoricalRoleMappings must contain a DataViewCategoricalMapping');\n var result;\n // With \"list\" in role mapping, it is possible to have multiple role names for category.\n // For now, proceed to concatenate category columns only when categories are bound to 1 Role.\n // We can change this if we want to support independent (sibling) group hierarchies in categorical.\n var uniqueCategoryRoles = _.chain(categoricalRoleMappings)\n .map(function (roleMapping) {\n var categoryRoles = getAllRolesInCategories(roleMapping.categorical);\n return categoryRoles.length === 1 ? categoryRoles[0] : undefined;\n })\n .uniq() // Note: _.uniq() does not treat two arrays with same elements as equal\n .value();\n var isSameCategoryRoleNameInAllRoleMappings = uniqueCategoryRoles.length === 1 && !_.isUndefined(uniqueCategoryRoles[0]);\n if (isSameCategoryRoleNameInAllRoleMappings) {\n result = uniqueCategoryRoles[0];\n }\n return result;\n }\n function isVisualExpectingMaxOneCategoryColumn(categoricalRoleName, roleMappings) {\n debug.assertValue(categoricalRoleName, 'categoricalRoleName');\n debug.assertNonEmpty(roleMappings, 'roleMappings');\n var isVisualExpectingMaxOneCategoryColumn = _.every(roleMappings, function (roleMapping) {\n return !_.isEmpty(roleMapping.conditions) &&\n _.every(roleMapping.conditions, function (condition) { return condition[categoricalRoleName] && condition[categoricalRoleName].max === 1; });\n });\n return isVisualExpectingMaxOneCategoryColumn;\n }\n /**\n * Returns the array of role names that are mapped to categorical categories.\n * Returns an empty array if none exists.\n */\n function getAllRolesInCategories(categoricalRoleMapping) {\n debug.assertValue(categoricalRoleMapping, 'categoricalRoleMapping');\n var roleNames = [];\n powerbi.DataViewMapping.visitCategoricalCategories(categoricalRoleMapping.categories, {\n visitRole: function (roleName) {\n roleNames.push(roleName);\n }\n });\n return roleNames;\n }\n function applyConcatenation(dataView, objectDescriptors, roleName, columnsSortedByProjectionOrdering, queryRefsToIgnore) {\n debug.assertValue(dataView, 'dataView');\n debug.assertAnyValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(roleName, 'roleName');\n debug.assert(columnsSortedByProjectionOrdering && columnsSortedByProjectionOrdering.length >= 2, 'columnsSortedByProjectionOrdering && columnsSortedByProjectionOrdering.length >= 2');\n var formatStringPropId = data.DataViewObjectDescriptors.findFormatString(objectDescriptors);\n var concatenatedValues = concatenateValues(columnsSortedByProjectionOrdering, queryRefsToIgnore, formatStringPropId);\n var columnsSourceSortedByProjectionOrdering = _.map(columnsSortedByProjectionOrdering, function (categoryColumn) { return categoryColumn.source; });\n var concatenatedColumnMetadata = createConcatenatedColumnMetadata(roleName, columnsSourceSortedByProjectionOrdering, queryRefsToIgnore);\n var transformedDataView = inheritSingle(dataView);\n addToMetadata(transformedDataView, concatenatedColumnMetadata);\n var concatenatedCategoryColumn = createConcatenatedCategoryColumn(columnsSortedByProjectionOrdering, concatenatedColumnMetadata, concatenatedValues);\n var dataViewCategorical = dataView.categorical;\n var transformedCategoricalCategories = _.difference(dataViewCategorical.categories, columnsSortedByProjectionOrdering);\n transformedCategoricalCategories.push(concatenatedCategoryColumn);\n var transformedCategorical = inheritSingle(dataViewCategorical);\n transformedCategorical.categories = transformedCategoricalCategories;\n transformedDataView.categorical = transformedCategorical;\n return transformedDataView;\n }\n function concatenateValues(columnsSortedByProjectionOrdering, queryRefsToIgnore, formatStringPropId) {\n debug.assertValue(columnsSortedByProjectionOrdering, 'columnsSortedByProjectionOrdering');\n debug.assertAnyValue(queryRefsToIgnore, 'queryRefsToIgnore');\n debug.assertAnyValue(formatStringPropId, 'formatStringPropId');\n var concatenatedValues = [];\n // concatenate the values in dataViewCategorical.categories[0..length-1].values[j], and store it in combinedValues[j]\n for (var _i = 0, columnsSortedByProjectionOrdering_1 = columnsSortedByProjectionOrdering; _i < columnsSortedByProjectionOrdering_1.length; _i++) {\n var categoryColumn = columnsSortedByProjectionOrdering_1[_i];\n var formatString = valueFormatter.getFormatString(categoryColumn.source, formatStringPropId);\n for (var i = 0, len = categoryColumn.values.length; i < len; i++) {\n if (!_.contains(queryRefsToIgnore, categoryColumn.source.queryName)) {\n var value = categoryColumn.values && categoryColumn.values[i];\n var formattedValue = valueFormatter.format(value, formatString);\n concatenatedValues[i] = (concatenatedValues[i] === undefined) ? formattedValue : (formattedValue + ' ' + concatenatedValues[i]);\n }\n }\n }\n return concatenatedValues;\n }\n /**\n * Returns a new array of elements from columns as they are ordered for the specified roleName in the specified projectionOrdering.\n */\n function sortColumnsByProjectionOrdering(projectionOrdering, roleName, columns) {\n debug.assertAnyValue(projectionOrdering, 'projectionOrdering');\n debug.assertValue(roleName, 'roleName');\n debug.assertValue(columns, 'columns');\n var columnsInProjectionOrdering;\n if (projectionOrdering) {\n // the numeric values in projectionOrdering correspond to the index property of DataViewMetadataColumn\n var columnsByIndex_1 = {};\n for (var _i = 0, columns_1 = columns; _i < columns_1.length; _i++) {\n var column = columns_1[_i];\n if (column.source.roles[roleName]) {\n debug.assert(!columnsByIndex_1[column.source.index], 'The specified columns should not contain multiple columns with same index: ' + column.source.index);\n columnsByIndex_1[column.source.index] = column;\n }\n }\n var columnIndicesInProjectionOrdering = projectionOrdering[roleName];\n columnsInProjectionOrdering = _.chain(columnIndicesInProjectionOrdering)\n .map(function (columnIndex) { return columnsByIndex_1[columnIndex]; })\n .filter(function (column) { return !!column; })\n .value();\n }\n else {\n // If projectionOrder is unspecified, just return the columns for the specified role in their current order\n columnsInProjectionOrdering = _.filter(columns, function (column) { return column.source.roles[roleName]; });\n }\n return columnsInProjectionOrdering;\n }\n /**\n * Creates the column metadata that will back the column with the concatenated values.\n */\n function createConcatenatedColumnMetadata(roleName, sourceColumnsSortedByProjectionOrdering, queryRefsToIgnore) {\n debug.assertValue(roleName, 'roleName');\n debug.assertNonEmpty(sourceColumnsSortedByProjectionOrdering, 'sourceColumnsSortedByProjectionOrdering');\n debug.assert(_.chain(sourceColumnsSortedByProjectionOrdering).map(function (c) { return c.isMeasure; }).uniq().value().length === 1, 'pre-condition: caller code should not attempt to combine a mix of measure columns and non-measure columns');\n var concatenatedDisplayName;\n for (var _i = 0, sourceColumnsSortedByProjectionOrdering_1 = sourceColumnsSortedByProjectionOrdering; _i < sourceColumnsSortedByProjectionOrdering_1.length; _i++) {\n var columnSource = sourceColumnsSortedByProjectionOrdering_1[_i];\n if (!_.contains(queryRefsToIgnore, columnSource.queryName)) {\n concatenatedDisplayName = (concatenatedDisplayName == null) ? columnSource.displayName : (columnSource.displayName + ' ' + concatenatedDisplayName);\n }\n }\n var newRoles = {};\n newRoles[roleName] = true;\n var newColumnMetadata = {\n displayName: concatenatedDisplayName,\n roles: newRoles,\n type: powerbi.ValueType.fromPrimitiveTypeAndCategory(powerbi.PrimitiveType.Text)\n };\n var columnSourceForCurrentDrillLevel = _.last(sourceColumnsSortedByProjectionOrdering);\n if (columnSourceForCurrentDrillLevel.isMeasure !== undefined) {\n newColumnMetadata.isMeasure = columnSourceForCurrentDrillLevel.isMeasure;\n }\n // TODO VSTS 6842046: Investigate whether we should change that property to mandatory or change the Chart visual code.\n // If queryName is not set at all, the column chart visual will only render column for the first group instance.\n // If queryName is set to any string other than columnForCurrentDrillLevel.source.queryName, then drilldown by group instance is broken (VSTS 6847879).\n newColumnMetadata.queryName = columnSourceForCurrentDrillLevel.queryName;\n return newColumnMetadata;\n }\n function addToMetadata(transformedDataView, newColumn) {\n debug.assertValue(transformedDataView, 'transformedDataView');\n debug.assertValue(newColumn, 'newColumn');\n var transformedColumns = inheritSingle(transformedDataView.metadata.columns);\n transformedColumns.push(newColumn);\n var transformedMetadata = inheritSingle(transformedDataView.metadata);\n transformedMetadata.columns = transformedColumns;\n transformedDataView.metadata = transformedMetadata;\n }\n function createConcatenatedCategoryColumn(sourceColumnsSortedByProjectionOrdering, columnMetadata, concatenatedValues) {\n debug.assert(sourceColumnsSortedByProjectionOrdering && sourceColumnsSortedByProjectionOrdering.length >= 2, 'sourceColumnsSortedByProjectionOrdering && sourceColumnsSortedByProjectionOrdering.length >= 2');\n var newCategoryColumn = {\n source: columnMetadata,\n values: concatenatedValues\n };\n // We expect every DataViewCategoryColumn in concatenationSourceColumns to have the same set of identities, always.\n // So, we'll just take the identities and identityFields from the first column\n var firstColumn = sourceColumnsSortedByProjectionOrdering[0];\n if (firstColumn.identity) {\n newCategoryColumn.identity = firstColumn.identity;\n }\n if (firstColumn.identityFields) {\n newCategoryColumn.identityFields = firstColumn.identityFields;\n }\n // It is safe to look at the first column as it is the one that is being set by findSelectedCategoricalColumn\n if (firstColumn.objects) {\n newCategoryColumn.objects = firstColumn.objects;\n }\n return newCategoryColumn;\n }\n })(DataViewConcatenateCategoricalColumns = data.DataViewConcatenateCategoricalColumns || (data.DataViewConcatenateCategoricalColumns = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var DataViewMapping;\n (function (DataViewMapping) {\n function visitMapping(mapping, visitor) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n var categorical = mapping.categorical;\n if (categorical)\n visitCategorical(categorical, visitor);\n var table = mapping.table;\n if (table)\n visitTable(table, visitor);\n var matrix = mapping.matrix;\n if (matrix)\n visitMatrix(matrix, visitor);\n var tree = mapping.tree;\n if (tree)\n visitTree(tree, visitor);\n var single = mapping.single;\n if (single)\n visitSingle(single, visitor);\n }\n DataViewMapping.visitMapping = visitMapping;\n function visitCategorical(mapping, visitor) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n visitCategoricalCategories(mapping.categories, visitor);\n visitCategoricalValues(mapping.values, visitor);\n }\n DataViewMapping.visitCategorical = visitCategorical;\n function visitCategoricalCategories(mapping, visitor) {\n debug.assertAnyValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n if (mapping) {\n visitBind(mapping, visitor);\n visitFor(mapping, visitor);\n visitList(mapping, visitor);\n visitReduction(mapping, visitor);\n }\n }\n DataViewMapping.visitCategoricalCategories = visitCategoricalCategories;\n function visitCategoricalValues(mapping, visitor) {\n debug.assertAnyValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n if (mapping) {\n visitBind(mapping, visitor, 0 /* CategoricalValue */);\n visitFor(mapping, visitor, 0 /* CategoricalValue */);\n visitList(mapping, visitor, 0 /* CategoricalValue */);\n var groupedRoleMapping = mapping;\n visitGrouped(groupedRoleMapping, visitor);\n var group = groupedRoleMapping.group;\n if (group) {\n for (var _i = 0, _a = group.select; _i < _a.length; _i++) {\n var item = _a[_i];\n visitBind(item, visitor, 1 /* CategoricalValueGroup */);\n visitFor(item, visitor, 1 /* CategoricalValueGroup */);\n }\n }\n }\n }\n DataViewMapping.visitCategoricalValues = visitCategoricalValues;\n function visitTable(mapping, visitor) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n var rows = mapping.rows;\n visitBind(rows, visitor);\n visitFor(rows, visitor);\n visitList(rows, visitor);\n visitReduction(rows, visitor);\n }\n DataViewMapping.visitTable = visitTable;\n function visitMatrix(mapping, visitor) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n visitMatrixItems(mapping.rows, visitor);\n visitMatrixItems(mapping.columns, visitor);\n visitMatrixItems(mapping.values, visitor);\n }\n /**\n * For visiting DataViewMatrixMapping.rows, DataViewMatrixMapping.columns, or DataViewMatrixMapping.values.\n *\n * @param mapping Can be one of DataViewMatrixMapping.rows, DataViewMatrixMapping.columns, or DataViewMatrixMapping.values.\n * @param visitor The visitor.\n */\n function visitMatrixItems(mapping, visitor) {\n debug.assertAnyValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n if (mapping) {\n visitFor(mapping, visitor);\n visitList(mapping, visitor);\n visitReduction(mapping, visitor);\n }\n }\n DataViewMapping.visitMatrixItems = visitMatrixItems;\n function visitTree(mapping, visitor) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n visitTreeNodes(mapping.nodes, visitor);\n visitTreeValues(mapping.values, visitor);\n }\n function visitTreeNodes(mapping, visitor) {\n debug.assertAnyValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n if (mapping) {\n visitFor(mapping, visitor);\n visitReduction(mapping, visitor);\n }\n }\n DataViewMapping.visitTreeNodes = visitTreeNodes;\n function visitTreeValues(mapping, visitor) {\n debug.assertAnyValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n if (mapping) {\n visitFor(mapping, visitor);\n }\n }\n DataViewMapping.visitTreeValues = visitTreeValues;\n function visitBind(mapping, visitor, context) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n var bind = mapping.bind;\n if (bind) {\n if (context != null)\n visitor.visitRole(bind.to, context);\n else\n visitor.visitRole(bind.to);\n }\n }\n function visitFor(mapping, visitor, context) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n var forValue = mapping.for;\n if (forValue) {\n if (context != null)\n visitor.visitRole(forValue.in, context);\n else\n visitor.visitRole(forValue.in);\n }\n }\n function visitList(mapping, visitor, context) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n var select = mapping.select;\n if (select) {\n for (var _i = 0, select_1 = select; _i < select_1.length; _i++) {\n var item = select_1[_i];\n visitBind(item, visitor, context);\n visitFor(item, visitor, context);\n }\n }\n }\n function visitGrouped(mapping, visitor) {\n debug.assertAnyValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n if (!mapping)\n return;\n var group = mapping.group;\n if (group) {\n visitor.visitRole(group.by);\n visitReduction(group, visitor);\n }\n }\n DataViewMapping.visitGrouped = visitGrouped;\n function visitReduction(mapping, visitor) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n if (visitor.visitReduction) {\n var reductionAlgorithm = mapping.dataReductionAlgorithm;\n if (reductionAlgorithm) {\n visitor.visitReduction(reductionAlgorithm);\n }\n }\n }\n function visitSingle(mapping, visitor) {\n debug.assertValue(mapping, 'mapping');\n debug.assertValue(visitor, 'visitor');\n visitor.visitRole(mapping.role);\n }\n })(DataViewMapping = powerbi.DataViewMapping || (powerbi.DataViewMapping = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var inheritSingle = powerbi.Prototype.inheritSingle;\n var DataViewNormalizeValues;\n (function (DataViewNormalizeValues) {\n function apply(options) {\n debug.assertValue(options, 'options');\n var rolesToNormalize = _.filter(options.dataRoles, function (role) { return !_.isEmpty(role.requiredTypes); });\n filterVariantMeasures(options.dataview, options.dataViewMappings, rolesToNormalize);\n }\n DataViewNormalizeValues.apply = apply;\n function filterVariantMeasures(dataview, dataViewMappings, rolesToNormalize) {\n debug.assertValue(dataview, 'dataview');\n // Don't perform this unless we actually have dataViewMappings and variant measures to suppress\n // When we switch to lazy per-visual DataView creation, we'll be able to remove this check.\n if (_.isEmpty(dataViewMappings) || _.isEmpty(rolesToNormalize))\n return;\n var columnFilter = generateMetadataColumnFilter(dataview.metadata.columns, rolesToNormalize);\n var valueFilter = generateValueFilter(dataview.metadata.columns, rolesToNormalize);\n var usedMappings = {};\n for (var _i = 0, dataViewMappings_1 = dataViewMappings; _i < dataViewMappings_1.length; _i++) {\n var dataViewMapping = dataViewMappings_1[_i];\n // Get dataview specified in mappings which are also in dataview\n for (var dataViewMappingProp in dataViewMapping) {\n if (dataview[dataViewMappingProp] != null)\n usedMappings[dataViewMappingProp] = true;\n }\n }\n if (usedMappings['categorical'])\n filterVariantMeasuresCategorical(dataview.categorical, columnFilter, valueFilter);\n if (usedMappings['table'])\n filterVariantMeasuresTable(dataview.table, columnFilter, valueFilter);\n if (usedMappings['tree'])\n filterVariantMeasuresTreeNode(dataview.tree.root, columnFilter, valueFilter);\n if (usedMappings['matrix'])\n filterVariantMeasuresMatrix(dataview.matrix, columnFilter, valueFilter);\n if (usedMappings['single'])\n filterVariantMeasuresSingle(dataview, dataViewMappings, rolesToNormalize, valueFilter);\n }\n DataViewNormalizeValues.filterVariantMeasures = filterVariantMeasures;\n function generateMetadataColumnFilter(columns, rolesToNormalize) {\n if (!columns || !rolesToNormalize)\n return function () { return false; };\n var columnsToNormalize = {};\n for (var _i = 0, columns_2 = columns; _i < columns_2.length; _i++) {\n var column = columns_2[_i];\n var roles = column.roles;\n if (!roles)\n continue;\n for (var _a = 0, rolesToNormalize_1 = rolesToNormalize; _a < rolesToNormalize_1.length; _a++) {\n var role = rolesToNormalize_1[_a];\n if (!roles[role.name])\n continue;\n columnsToNormalize[column.index] = true;\n break;\n }\n }\n return function (columnIndex) {\n if (isNaN(columnIndex))\n return false;\n return !!columnsToNormalize[columnIndex];\n };\n }\n DataViewNormalizeValues.generateMetadataColumnFilter = generateMetadataColumnFilter;\n function generateValueFilter(columns, rolesToNormalize) {\n if (!columns || !rolesToNormalize)\n return function () { return true; };\n var columnValueFilters = [];\n // Build columnValueFilters based on role requiredTypes\n for (var _i = 0, columns_3 = columns; _i < columns_3.length; _i++) {\n var column = columns_3[_i];\n var columnValueFilter = generateColumnValueFilter(column, rolesToNormalize);\n if (columnValueFilter)\n columnValueFilters[column.index] = columnValueFilter;\n }\n return function (columnIndex, value) {\n if (columnValueFilters[columnIndex])\n return columnValueFilters[columnIndex](value);\n return true;\n };\n }\n DataViewNormalizeValues.generateValueFilter = generateValueFilter;\n function generateColumnValueFilter(column, rolesToNormalize) {\n var requiredTypes = getColumnRequiredTypes(column, rolesToNormalize);\n if (_.isEmpty(requiredTypes))\n return;\n return function (value) {\n return doesValueMatchTypes(value, requiredTypes);\n };\n }\n function getColumnRequiredTypes(column, rolesToNormalize) {\n var requiredTypes = [];\n var columnRoles = column && column.roles;\n if (!columnRoles)\n return requiredTypes;\n for (var _i = 0, rolesToNormalize_2 = rolesToNormalize; _i < rolesToNormalize_2.length; _i++) {\n var role = rolesToNormalize_2[_i];\n if (!columnRoles[role.name])\n continue;\n for (var _a = 0, _b = role.requiredTypes; _a < _b.length; _a++) {\n var typeDescriptor = _b[_a];\n var type = powerbi.ValueType.fromDescriptor(typeDescriptor);\n requiredTypes.push(type);\n }\n }\n return requiredTypes;\n }\n DataViewNormalizeValues.getColumnRequiredTypes = getColumnRequiredTypes;\n function filterVariantMeasuresCategorical(dataview, columnFilter, valueFilter) {\n var values = dataview && dataview.values;\n if (!values)\n return;\n var valuesGrouped = values.grouped();\n if (!valuesGrouped)\n return;\n for (var _i = 0, valuesGrouped_1 = valuesGrouped; _i < valuesGrouped_1.length; _i++) {\n var valueGroup = valuesGrouped_1[_i];\n var valuesInGroup = valueGroup.values;\n for (var _a = 0, valuesInGroup_1 = valuesInGroup; _a < valuesInGroup_1.length; _a++) {\n var valueColumn = valuesInGroup_1[_a];\n var columnIndex = valueColumn.source.index;\n if (!columnFilter(columnIndex))\n continue;\n for (var i = 0, ilen = valueColumn.values.length; i < ilen; i++) {\n valueColumn.values = normalizeVariant(valueColumn.values, i, columnIndex, valueFilter);\n }\n }\n }\n }\n function filterVariantMeasuresTable(dataview, columnFilter, valueFilter) {\n var columns = dataview && dataview.columns;\n if (!columns)\n return;\n var filteredColumns = [];\n for (var _i = 0, columns_4 = columns; _i < columns_4.length; _i++) {\n var column = columns_4[_i];\n if (columnFilter(column.index))\n filteredColumns.push(column.index);\n }\n var rows = dataview.rows;\n for (var i = 0, ilen = rows.length; i < ilen; i++) {\n for (var _a = 0, filteredColumns_1 = filteredColumns; _a < filteredColumns_1.length; _a++) {\n var index = filteredColumns_1[_a];\n rows[i] = normalizeVariant(rows[i], index, index, valueFilter);\n }\n }\n }\n function filterVariantMeasuresTreeNode(node, columnFilter, valueFilter) {\n if (node.values) {\n for (var columnIndex in node.values) {\n // In dataView.tree, the keys in node.values correspond to columnIndex of the node value\n if (columnFilter(columnIndex)) {\n // According to nojorgen, it is possible to have primitive values as values in the node.values dictionary.\n if (typeof (node.values[columnIndex]) === 'object' && ('value' in node.values[columnIndex]))\n node.values[columnIndex] = normalizeVariant(node.values[columnIndex], 'value', columnIndex, valueFilter);\n else\n node.values = normalizeVariant(node.values, columnIndex, columnIndex, valueFilter);\n }\n }\n }\n else if (node.children) {\n for (var _i = 0, _a = node.children; _i < _a.length; _i++) {\n var child = _a[_i];\n filterVariantMeasuresTreeNode(child, columnFilter, valueFilter);\n }\n }\n }\n function filterVariantMeasuresMatrix(dataview, columnFilter, valueFilter) {\n var root = dataview && dataview.rows && dataview.rows.root;\n if (!root)\n return;\n // Recurse into rows.children\n // e.g. rows.children -> .children -> .children.values\n filterVariantMeasuresMatrixRecursive(dataview, root, columnFilter, valueFilter);\n }\n function filterVariantMeasuresMatrixRecursive(dataviewMatrix, node, columnFilter, valueFilter) {\n if (node.values) {\n for (var id in node.values) {\n // Note related to VSTS 6547124: In dataView.matrix, the keys in node.values are NOT equivalent to value.valueSourceIndex.\n var nodeValue = node.values[id];\n // the property DataViewMatrixNodeValue.valueSourceIndex will not exist if valueSourceIndex is 0 for that value\n var valueSourceIndex = nodeValue.valueSourceIndex || 0;\n // index is an optional property on DataViewMetadataColumn, but I am not sure when it will ever be undefined in a matrix' column metadata\n var columnIndex = dataviewMatrix.valueSources[valueSourceIndex].index;\n if (_.isNumber(columnIndex) && columnFilter(columnIndex)) {\n node.values[id] = normalizeVariant(nodeValue, 'value', columnIndex, valueFilter);\n }\n }\n }\n else if (node.children) {\n for (var _i = 0, _a = node.children; _i < _a.length; _i++) {\n var child = _a[_i];\n filterVariantMeasuresMatrixRecursive(dataviewMatrix, child, columnFilter, valueFilter);\n }\n }\n }\n function filterVariantMeasuresSingle(dataview, dataViewMappings, rolesToNormalize, valueFilter) {\n if (!dataview.single)\n return;\n var roleNames = [];\n for (var _i = 0, rolesToNormalize_3 = rolesToNormalize; _i < rolesToNormalize_3.length; _i++) {\n var role = rolesToNormalize_3[_i];\n if (role.name)\n roleNames.push(role.name);\n }\n var columns = dataview.metadata.columns;\n for (var _a = 0, dataViewMappings_2 = dataViewMappings; _a < dataViewMappings_2.length; _a++) {\n var dataViewMapping = dataViewMappings_2[_a];\n var roleName = dataViewMapping.single.role;\n if (roleNames.indexOf(roleName) !== -1) {\n var column = firstColumnByRoleName(columns, roleName);\n if (column)\n dataview.single = normalizeVariant(dataview.single, 'value', column.index, valueFilter);\n return;\n }\n }\n }\n function normalizeVariant(object, key, columnIndex, valueFilter) {\n if (!object)\n return;\n var value = object[key];\n if (value !== null && !valueFilter(columnIndex, value)) {\n object = inheritSingle(object);\n object[key] = null;\n }\n return object;\n }\n DataViewNormalizeValues.normalizeVariant = normalizeVariant;\n function doesValueMatchTypes(value, types) {\n for (var _i = 0, types_1 = types; _i < types_1.length; _i++) {\n var type = types_1[_i];\n if (type.numeric || type.integer)\n return typeof (value) === 'number';\n }\n return false;\n }\n function firstColumnByRoleName(columns, roleName) {\n for (var _i = 0, columns_5 = columns; _i < columns_5.length; _i++) {\n var column = columns_5[_i];\n var columnRoles = column && column.roles;\n if (columnRoles && columnRoles[roleName])\n return column;\n }\n }\n })(DataViewNormalizeValues = data.DataViewNormalizeValues || (data.DataViewNormalizeValues = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var DataViewObjects;\n (function (DataViewObjects) {\n /** Gets the value of the given object/property pair. */\n function getValue(objects, propertyId, defaultValue) {\n debug.assertAnyValue(objects, 'objects');\n debug.assertValue(propertyId, 'propertyId');\n if (!objects)\n return defaultValue;\n var objectOrMap = objects[propertyId.objectName];\n debug.assert(!isUserDefined(objectOrMap), 'expected DataViewObject');\n var object = objectOrMap;\n return DataViewObject.getValue(object, propertyId.propertyName, defaultValue);\n }\n DataViewObjects.getValue = getValue;\n /** Gets an object from objects. */\n function getObject(objects, objectName, defaultValue) {\n if (objects && objects[objectName]) {\n var object = objects[objectName];\n debug.assert(!isUserDefined(object), 'expected DataViewObject');\n return object;\n }\n else {\n return defaultValue;\n }\n }\n DataViewObjects.getObject = getObject;\n /** Gets a map of user-defined objects. */\n function getUserDefinedObjects(objects, objectName) {\n if (objects && objects[objectName]) {\n var map = objects[objectName];\n debug.assert(isUserDefined(map), 'expected DataViewObjectMap');\n return map;\n }\n }\n DataViewObjects.getUserDefinedObjects = getUserDefinedObjects;\n /** Gets the solid color from a fill property. */\n function getFillColor(objects, propertyId, defaultColor) {\n var value = getValue(objects, propertyId);\n if (!value || !value.solid)\n return defaultColor;\n return value.solid.color;\n }\n DataViewObjects.getFillColor = getFillColor;\n /** Returns true if the given object represents a collection of user-defined objects */\n function isUserDefined(objectOrMap) {\n return _.isArray(objectOrMap);\n }\n DataViewObjects.isUserDefined = isUserDefined;\n })(DataViewObjects = powerbi.DataViewObjects || (powerbi.DataViewObjects = {}));\n var DataViewObject;\n (function (DataViewObject) {\n function getValue(object, propertyName, defaultValue) {\n debug.assertAnyValue(object, 'object');\n debug.assertValue(propertyName, 'propertyName');\n if (!object)\n return defaultValue;\n var propertyValue = object[propertyName];\n if (propertyValue === undefined)\n return defaultValue;\n return propertyValue;\n }\n DataViewObject.getValue = getValue;\n /** Gets the solid color from a fill property using only a propertyName */\n function getFillColorByPropertyName(objects, propertyName, defaultColor) {\n var value = DataViewObject.getValue(objects, propertyName);\n if (!value || !value.solid)\n return defaultColor;\n return value.solid.color;\n }\n DataViewObject.getFillColorByPropertyName = getFillColorByPropertyName;\n })(DataViewObject = powerbi.DataViewObject || (powerbi.DataViewObject = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var JsonComparer = jsCommon.JsonComparer;\n var DataViewObjectDefinitions;\n (function (DataViewObjectDefinitions) {\n /** Creates or reuses a DataViewObjectDefinition for matching the given objectName and selector within the defns. */\n function ensure(defns, objectName, selector) {\n debug.assertValue(defns, 'defns');\n var defnsForObject = defns[objectName];\n if (!defnsForObject)\n defns[objectName] = defnsForObject = [];\n for (var i = 0, len = defnsForObject.length; i < len; i++) {\n var defn = defnsForObject[i];\n if (data.Selector.equals(defn.selector, selector))\n return defn;\n }\n var newDefn = {\n selector: selector,\n properties: {},\n };\n defnsForObject.push(newDefn);\n return newDefn;\n }\n DataViewObjectDefinitions.ensure = ensure;\n function deleteProperty(defns, objectName, selector, propertyName) {\n debug.assertValue(defns, 'defns');\n var defn = getObjectDefinition(defns, objectName, selector);\n if (!defn)\n return;\n DataViewObjectDefinition.deleteSingleProperty(defn, propertyName);\n }\n DataViewObjectDefinitions.deleteProperty = deleteProperty;\n function setValue(defns, propertyId, selector, value) {\n debug.assertValue(defns, 'defns');\n debug.assertValue(propertyId, 'propertyId');\n ensure(defns, propertyId.objectName, selector).properties[propertyId.propertyName] = value;\n }\n DataViewObjectDefinitions.setValue = setValue;\n function getValue(defns, propertyId, selector) {\n var properties = getPropertyContainer(defns, propertyId, selector);\n if (!properties)\n return;\n return properties[propertyId.propertyName];\n }\n DataViewObjectDefinitions.getValue = getValue;\n function getPropertyContainer(defns, propertyId, selector) {\n var defn = getObjectDefinition(defns, propertyId.objectName, selector);\n if (!defn)\n return;\n return defn.properties;\n }\n DataViewObjectDefinitions.getPropertyContainer = getPropertyContainer;\n function getObjectDefinition(defns, objectName, selector) {\n debug.assertAnyValue(defns, 'defns');\n debug.assertValue(objectName, 'objectName');\n debug.assertAnyValue(selector, 'selector');\n if (!defns)\n return;\n var defnsForObject = defns[objectName];\n if (!defnsForObject)\n return;\n for (var i = 0, len = defnsForObject.length; i < len; i++) {\n var defn = defnsForObject[i];\n if (data.Selector.equals(defn.selector, selector))\n return defn;\n }\n }\n DataViewObjectDefinitions.getObjectDefinition = getObjectDefinition;\n function propertiesAreEqual(a, b) {\n if (a instanceof data.SemanticFilter && b instanceof data.SemanticFilter) {\n return data.SemanticFilter.isSameFilter(a, b);\n }\n return JsonComparer.equals(a, b);\n }\n DataViewObjectDefinitions.propertiesAreEqual = propertiesAreEqual;\n function allPropertiesAreEqual(a, b) {\n debug.assertValue(a, 'a');\n debug.assertValue(b, 'b');\n if (Object.keys(a).length !== Object.keys(b).length)\n return false;\n for (var property in a) {\n if (!propertiesAreEqual(a[property], b[property]))\n return false;\n }\n return true;\n }\n DataViewObjectDefinitions.allPropertiesAreEqual = allPropertiesAreEqual;\n function encodePropertyValue(value, valueTypeDescriptor) {\n debug.assertAnyValue(value, 'value');\n debug.assertValue(valueTypeDescriptor, 'valueTypeDescriptor');\n if (valueTypeDescriptor.bool) {\n if (typeof (value) !== 'boolean')\n value = false; // This is fallback, which doesn't really belong here.\n return data.SQExprBuilder.boolean(value);\n }\n else if (valueTypeDescriptor.text || (valueTypeDescriptor.scripting && valueTypeDescriptor.scripting.source)) {\n return data.SQExprBuilder.text(value);\n }\n else if (valueTypeDescriptor.numeric) {\n if ($.isNumeric(value))\n return data.SQExprBuilder.double(+value);\n }\n else if (valueTypeDescriptor.fill) {\n if (value) {\n return {\n solid: { color: data.SQExprBuilder.text(value) }\n };\n }\n }\n else if (valueTypeDescriptor.formatting) {\n if (valueTypeDescriptor.formatting.labelDisplayUnits) {\n return data.SQExprBuilder.double(+value);\n }\n else {\n return data.SQExprBuilder.text(value);\n }\n }\n else if (valueTypeDescriptor.enumeration) {\n if ($.isNumeric(value))\n return data.SQExprBuilder.double(+value);\n else\n return data.SQExprBuilder.text(value);\n }\n else if (valueTypeDescriptor.misc) {\n if (value) {\n value = data.SQExprBuilder.text(value);\n }\n else {\n value = null;\n }\n }\n else if (valueTypeDescriptor.image) {\n if (value) {\n var imageValue = value;\n var imageDefinition = {\n name: data.SQExprBuilder.text(imageValue.name),\n url: data.SQExprBuilder.text(imageValue.url),\n };\n if (imageValue.scaling)\n imageDefinition.scaling = data.SQExprBuilder.text(imageValue.scaling);\n return imageDefinition;\n }\n }\n return value;\n }\n DataViewObjectDefinitions.encodePropertyValue = encodePropertyValue;\n function clone(original) {\n debug.assertValue(original, 'original');\n var cloned = {};\n for (var objectName in original) {\n var originalDefns = original[objectName];\n if (_.isEmpty(originalDefns))\n continue;\n var clonedDefns = [];\n for (var _i = 0, originalDefns_1 = originalDefns; _i < originalDefns_1.length; _i++) {\n var originalDefn = originalDefns_1[_i];\n clonedDefns.push({\n properties: cloneProperties(originalDefn.properties),\n selector: originalDefn.selector,\n });\n }\n cloned[objectName] = clonedDefns;\n }\n return cloned;\n }\n DataViewObjectDefinitions.clone = clone;\n function cloneProperties(original) {\n debug.assertValue(original, 'original');\n // NOTE: properties are considered atomic, so a shallow clone is appropriate here.\n return _.clone(original);\n }\n })(DataViewObjectDefinitions = data.DataViewObjectDefinitions || (data.DataViewObjectDefinitions = {}));\n var DataViewObjectDefinition;\n (function (DataViewObjectDefinition) {\n function deleteSingleProperty(defn, propertyName) {\n //note: We decided that delete is acceptable here and that we don't need optimization here\n delete defn.properties[propertyName];\n }\n DataViewObjectDefinition.deleteSingleProperty = deleteSingleProperty;\n })(DataViewObjectDefinition = data.DataViewObjectDefinition || (data.DataViewObjectDefinition = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataViewObjectDescriptors;\n (function (DataViewObjectDescriptors) {\n /** Attempts to find the format string property. This can be useful for upgrade and conversion. */\n function findFormatString(descriptors) {\n return findProperty(descriptors, function (propDesc) {\n var formattingTypeDesc = powerbi.ValueType.fromDescriptor(propDesc.type).formatting;\n return formattingTypeDesc && formattingTypeDesc.formatString;\n });\n }\n DataViewObjectDescriptors.findFormatString = findFormatString;\n /** Attempts to find the filter property. This can be useful for propagating filters from one visual to others. */\n function findFilterOutput(descriptors) {\n return findProperty(descriptors, function (propDesc) {\n var propType = propDesc.type;\n return propType && !!propType.filter;\n });\n }\n DataViewObjectDescriptors.findFilterOutput = findFilterOutput;\n /** Attempts to find the default value property. This can be useful for propagating schema default value. */\n function findDefaultValue(descriptors) {\n return findProperty(descriptors, function (propDesc) {\n var propType = propDesc.type;\n return propType && !!propType.expression && propType.expression.defaultValue;\n });\n }\n DataViewObjectDescriptors.findDefaultValue = findDefaultValue;\n function findProperty(descriptors, propPredicate) {\n debug.assertAnyValue(descriptors, 'descriptors');\n debug.assertAnyValue(propPredicate, 'propPredicate');\n if (!descriptors)\n return;\n for (var objectName in descriptors) {\n var objPropDescs = descriptors[objectName].properties;\n for (var propertyName in objPropDescs) {\n if (propPredicate(objPropDescs[propertyName])) {\n return {\n objectName: objectName,\n propertyName: propertyName,\n };\n }\n }\n }\n }\n })(DataViewObjectDescriptors = data.DataViewObjectDescriptors || (data.DataViewObjectDescriptors = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n * MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n*\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataViewObjectEvaluationUtils;\n (function (DataViewObjectEvaluationUtils) {\n function evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(objectDefns, 'objectDefns');\n var objects;\n for (var j = 0, jlen = objectDefns.length; j < jlen; j++) {\n var objectDefinition = objectDefns[j], objectName = objectDefinition.name;\n var evaluatedObject = data.DataViewObjectEvaluator.run(evalContext, objectDescriptors[objectName], objectDefinition.properties);\n if (!evaluatedObject)\n continue;\n if (!objects)\n objects = {};\n // NOTE: this currently has last-object-wins semantics.\n objects[objectName] = evaluatedObject;\n }\n return objects;\n }\n DataViewObjectEvaluationUtils.evaluateDataViewObjects = evaluateDataViewObjects;\n function groupObjectsBySelector(objectDefinitions) {\n debug.assertAnyValue(objectDefinitions, 'objectDefinitions');\n var grouped = {\n data: [],\n };\n if (objectDefinitions) {\n for (var objectName in objectDefinitions) {\n var objectDefnList = objectDefinitions[objectName];\n for (var i = 0, len = objectDefnList.length; i < len; i++) {\n var objectDefn = objectDefnList[i];\n ensureDefinitionListForSelector(grouped, objectDefn.selector).objects.push({\n name: objectName,\n properties: objectDefn.properties,\n });\n }\n }\n }\n return grouped;\n }\n DataViewObjectEvaluationUtils.groupObjectsBySelector = groupObjectsBySelector;\n function ensureDefinitionListForSelector(grouped, selector) {\n debug.assertValue(grouped, 'grouped');\n debug.assertAnyValue(selector, 'selector');\n if (!selector) {\n if (!grouped.metadataOnce)\n grouped.metadataOnce = { objects: [] };\n return grouped.metadataOnce;\n }\n var groupedObjects;\n if (selector.data) {\n groupedObjects = grouped.data;\n }\n else if (selector.metadata) {\n if (!grouped.metadata)\n grouped.metadata = [];\n groupedObjects = grouped.metadata;\n }\n else if (selector.id) {\n if (!grouped.userDefined)\n grouped.userDefined = [];\n groupedObjects = grouped.userDefined;\n }\n debug.assert(!!groupedObjects, 'GroupedObjects is not defined. Indicates malformed selector.');\n for (var _i = 0, groupedObjects_1 = groupedObjects; _i < groupedObjects_1.length; _i++) {\n var item_1 = groupedObjects_1[_i];\n if (data.Selector.equals(selector, item_1.selector))\n return item_1;\n }\n var item = {\n selector: selector,\n objects: [],\n };\n groupedObjects.push(item);\n return item;\n }\n function addImplicitObjects(objectsForAllSelectors, objectDescriptors, columns, selectTransforms) {\n debug.assertValue(objectsForAllSelectors, 'objectsForAllSelectors');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(columns, 'columns');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n if (selectTransforms) {\n addDefaultFormatString(objectsForAllSelectors, objectDescriptors, columns, selectTransforms);\n addDefaultValue(objectsForAllSelectors, objectDescriptors, columns, selectTransforms);\n }\n }\n DataViewObjectEvaluationUtils.addImplicitObjects = addImplicitObjects;\n function addDefaultFormatString(objectsForAllSelectors, objectDescriptors, columns, selectTransforms) {\n debug.assertValue(objectsForAllSelectors, 'objectsForAllSelectors');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(columns, 'columns');\n debug.assertValue(selectTransforms, 'selectTransforms');\n var formatStringProp = data.DataViewObjectDescriptors.findFormatString(objectDescriptors);\n if (!formatStringProp)\n return;\n for (var selectIdx = 0, selectLen = selectTransforms.length; selectIdx < selectLen; selectIdx++) {\n var selectTransform = selectTransforms[selectIdx];\n if (!selectTransform)\n continue;\n debug.assertValue(selectTransform.queryName, 'selectTransform.queryName');\n applyFormatString(objectsForAllSelectors, formatStringProp, selectTransform.queryName, selectTransform.format || getColumnFormatForIndex(columns, selectIdx));\n }\n }\n /** Registers properties for default value, if the properties are not explicitly provided. */\n function addDefaultValue(objectsForAllSelectors, objectDescriptors, columns, selectTransforms) {\n debug.assertValue(objectsForAllSelectors, 'objectsForAllSelectors');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(columns, 'columns');\n debug.assertValue(selectTransforms, 'selectTransforms');\n var defaultValueProp = data.DataViewObjectDescriptors.findDefaultValue(objectDescriptors);\n if (!defaultValueProp)\n return;\n for (var _i = 0, selectTransforms_1 = selectTransforms; _i < selectTransforms_1.length; _i++) {\n var selectTransform = selectTransforms_1[_i];\n if (!selectTransform)\n continue;\n debug.assertValue(selectTransform.queryName, 'selectTransform.queryName');\n applyDefaultValue(objectsForAllSelectors, defaultValueProp, selectTransform.queryName, selectTransform.defaultValue);\n }\n }\n function getColumnFormatForIndex(columns, selectIdx) {\n for (var columnIdx = 0, columnLen = columns.length; columnIdx < columnLen; columnIdx++) {\n var column = columns[columnIdx];\n if (!column || column.index !== selectIdx)\n continue;\n return column.format;\n }\n }\n function applyFormatString(objectsForAllSelectors, formatStringProp, queryName, formatStringValue) {\n if (!formatStringValue)\n return;\n // There is a format string specified -- apply it as an object property, if there is not already one specified.\n applyMetadataProperty(objectsForAllSelectors, formatStringProp, { metadata: queryName }, data.SQExprBuilder.text(formatStringValue));\n }\n function applyDefaultValue(objectsForAllSelectors, defaultValueProp, queryName, defaultValue) {\n if (!defaultValue)\n return;\n // There is a default value specified -- apply it as an object property, if there is not already one specified.\n applyMetadataProperty(objectsForAllSelectors, defaultValueProp, { metadata: queryName }, defaultValue);\n }\n function applyMetadataProperty(objectsForAllSelectors, propertyId, selector, value) {\n var objectDefns;\n if (selector) {\n var metadataObjects = objectsForAllSelectors.metadata;\n if (!metadataObjects)\n metadataObjects = objectsForAllSelectors.metadata = [];\n objectDefns = metadataObjects;\n }\n else {\n var metadataOnce = objectsForAllSelectors.metadataOnce;\n if (!metadataOnce)\n metadataOnce = objectsForAllSelectors.metadataOnce = { selector: selector, objects: [] };\n objectDefns = [metadataOnce];\n }\n var targetMetadataObject = findWithMatchingSelector(objectDefns, selector);\n var targetObjectDefn;\n if (targetMetadataObject) {\n var targetObjectDefns = targetMetadataObject.objects;\n targetObjectDefn = findExistingObject(targetObjectDefns, propertyId.objectName);\n if (targetObjectDefn) {\n if (targetObjectDefn.properties[propertyId.propertyName])\n return;\n }\n else {\n targetObjectDefn = {\n name: propertyId.objectName,\n properties: {},\n };\n targetObjectDefns.push(targetObjectDefn);\n }\n }\n else {\n targetObjectDefn = {\n name: propertyId.objectName,\n properties: {}\n };\n objectDefns.push({\n selector: selector,\n objects: [targetObjectDefn],\n });\n }\n targetObjectDefn.properties[propertyId.propertyName] = value;\n }\n function findWithMatchingSelector(objects, selector) {\n debug.assertValue(objects, 'objects');\n debug.assertAnyValue(selector, 'selector');\n for (var i = 0, len = objects.length; i < len; i++) {\n var object = objects[i];\n if (data.Selector.equals(object.selector, selector))\n return object;\n }\n }\n function findExistingObject(objectDefns, objectName) {\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(objectName, 'objectName');\n for (var i = 0, len = objectDefns.length; i < len; i++) {\n var objectDefn = objectDefns[i];\n if (objectDefn.name === objectName)\n return objectDefn;\n }\n }\n })(DataViewObjectEvaluationUtils = data.DataViewObjectEvaluationUtils || (data.DataViewObjectEvaluationUtils = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n /** Responsible for evaluating object property expressions to be applied at various scopes in a DataView. */\n var DataViewObjectEvaluator;\n (function (DataViewObjectEvaluator) {\n var colorValueType = powerbi.ValueType.fromDescriptor({ formatting: { color: true } });\n var numericType = powerbi.ValueType.fromDescriptor({ numeric: true });\n var textType = powerbi.ValueType.fromDescriptor({ text: true });\n function run(evalContext, objectDescriptor, propertyDefinitions) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertAnyValue(objectDescriptor, 'objectDescriptor');\n debug.assertValue(propertyDefinitions, 'propertyDefinitions');\n if (!objectDescriptor)\n return;\n var object, propertyDescriptors = objectDescriptor.properties;\n for (var propertyName in propertyDefinitions) {\n var propertyDefinition = propertyDefinitions[propertyName], propertyDescriptor = propertyDescriptors[propertyName];\n if (!propertyDescriptor)\n continue;\n var propertyValue = evaluateProperty(evalContext, propertyDescriptor, propertyDefinition);\n if (propertyValue === undefined)\n continue;\n if (!object)\n object = {};\n object[propertyName] = propertyValue;\n }\n return object;\n }\n DataViewObjectEvaluator.run = run;\n /** Note: Exported for testability */\n function evaluateProperty(evalContext, propertyDescriptor, propertyDefinition) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(propertyDescriptor, 'propertyDescriptor');\n debug.assertValue(propertyDefinition, 'propertyDefinition');\n var structuralType = propertyDescriptor.type;\n if (structuralType && structuralType.expression)\n return propertyDefinition;\n var value = evaluateValue(evalContext, propertyDefinition, powerbi.ValueType.fromDescriptor(propertyDescriptor.type));\n if (value !== undefined || (propertyDefinition instanceof data.RuleEvaluation))\n return value;\n return evaluateFill(evalContext, propertyDefinition, structuralType)\n || evaluateFillRule(evalContext, propertyDefinition, structuralType)\n || evaluateImage(evalContext, propertyDefinition, structuralType)\n || evaluateParagraphs(evalContext, propertyDefinition, structuralType)\n || propertyDefinition;\n }\n DataViewObjectEvaluator.evaluateProperty = evaluateProperty;\n function evaluateFill(evalContext, fillDefn, type) {\n var fillType = type.fill;\n if (!fillType)\n return;\n if (fillType && fillType.solid && fillType.solid.color && fillDefn.solid) {\n return {\n solid: {\n color: evaluateValue(evalContext, fillDefn.solid.color, powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Color)),\n }\n };\n }\n }\n function evaluateFillRule(evalContext, fillRuleDefn, type) {\n if (!type.fillRule)\n return;\n if (fillRuleDefn.linearGradient2) {\n var linearGradient2 = fillRuleDefn.linearGradient2;\n return {\n linearGradient2: {\n min: evaluateColorStop(evalContext, linearGradient2.min),\n max: evaluateColorStop(evalContext, linearGradient2.max),\n }\n };\n }\n if (fillRuleDefn.linearGradient3) {\n var linearGradient3 = fillRuleDefn.linearGradient3;\n return {\n linearGradient3: {\n min: evaluateColorStop(evalContext, linearGradient3.min),\n mid: evaluateColorStop(evalContext, linearGradient3.mid),\n max: evaluateColorStop(evalContext, linearGradient3.max),\n }\n };\n }\n }\n function evaluateColorStop(evalContext, colorStop) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(colorStop, 'colorStop');\n var step = {\n color: evaluateValue(evalContext, colorStop.color, colorValueType),\n };\n var value = evaluateValue(evalContext, colorStop.value, numericType);\n if (value != null)\n step.value = value;\n return step;\n }\n function evaluateImage(evalContext, definition, type) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertAnyValue(definition, 'definition');\n debug.assertValue(type, 'type');\n if (!type.image || !definition)\n return;\n var value = {\n name: evaluateValue(evalContext, definition.name, textType),\n url: evaluateValue(evalContext, definition.url, powerbi.ValueType.fromDescriptor(powerbi.ImageDefinition.urlType)),\n };\n if (definition.scaling)\n value.scaling = evaluateValue(evalContext, definition.scaling, textType);\n return value;\n }\n function evaluateParagraphs(evalContext, definition, type) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertAnyValue(definition, 'definition');\n debug.assertValue(type, 'type');\n if (!type.paragraphs || !definition)\n return;\n return evaluateArrayCopyOnChange(evalContext, definition, evaluateParagraph);\n }\n function evaluateParagraph(evalContext, definition) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(definition, 'definition');\n var evaluated;\n var definitionTextRuns = definition.textRuns;\n var evaluatedTextRuns = evaluateArrayCopyOnChange(evalContext, definitionTextRuns, evaluateTextRun);\n if (definitionTextRuns !== evaluatedTextRuns) {\n evaluated = _.clone(definition);\n evaluated.textRuns = evaluatedTextRuns;\n }\n return evaluated || definition;\n }\n function evaluateTextRun(evalContext, definition) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(definition, 'definition');\n var evaluated;\n var definitionValue = definition.value;\n var evaluatedValue = evaluateValue(evalContext, definitionValue, textType);\n if (evaluatedValue !== undefined) {\n evaluated = _.clone(definition);\n evaluated.value = evaluatedValue;\n }\n return evaluated || definition;\n }\n /**\n * Evaluates an array, and lazily copies on write whenever the evaluator function returns something\n * other than the input to it.\n */\n function evaluateArrayCopyOnChange(evalContext, definitions, evaluator) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(definitions, 'definitions');\n debug.assertValue(evaluator, 'evaluator');\n var evaluatedValues;\n for (var i = 0, len = definitions.length; i < len; i++) {\n var definition = definitions[i];\n var evaluated = evaluator(evalContext, definition);\n // NOTE: the any casts here are necessary due to the compiler not knowing the relationship\n // between TEvaluated & TDefinition\n if (!evaluatedValues && definition !== evaluated) {\n evaluatedValues = _.take(definitions, i);\n }\n if (evaluatedValues) {\n evaluatedValues.push(evaluated);\n }\n }\n return evaluatedValues || definitions;\n }\n function evaluateValue(evalContext, definition, valueType) {\n if (definition instanceof data.SQExpr)\n return ExpressionEvaluator.evaluate(definition, evalContext);\n if (definition instanceof data.RuleEvaluation)\n return definition.evaluate(evalContext);\n }\n /** Responsible for evaluating SQExprs into values. */\n var ExpressionEvaluator = (function (_super) {\n __extends(ExpressionEvaluator, _super);\n function ExpressionEvaluator() {\n _super.apply(this, arguments);\n }\n ExpressionEvaluator.evaluate = function (expr, evalContext) {\n if (expr == null)\n return;\n return expr.accept(ExpressionEvaluator.instance, evalContext);\n };\n ExpressionEvaluator.prototype.visitColumnRef = function (expr, evalContext) {\n return evalContext.getExprValue(expr);\n };\n ExpressionEvaluator.prototype.visitConstant = function (expr, evalContext) {\n return expr.value;\n };\n ExpressionEvaluator.prototype.visitMeasureRef = function (expr, evalContext) {\n return evalContext.getExprValue(expr);\n };\n ExpressionEvaluator.prototype.visitAggr = function (expr, evalContext) {\n return evalContext.getExprValue(expr);\n };\n ExpressionEvaluator.prototype.visitFillRule = function (expr, evalContext) {\n var inputValue = expr.input.accept(this, evalContext);\n if (inputValue !== undefined) {\n var colorAllocator = evalContext.getColorAllocator(expr);\n if (colorAllocator) {\n return colorAllocator.color(inputValue);\n }\n }\n };\n ExpressionEvaluator.prototype.visitSelectRef = function (expr, evalContext) {\n return evalContext.getExprValue(expr);\n };\n ExpressionEvaluator.instance = new ExpressionEvaluator();\n return ExpressionEvaluator;\n }(data.DefaultSQExprVisitorWithArg));\n })(DataViewObjectEvaluator = data.DataViewObjectEvaluator || (data.DataViewObjectEvaluator = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var inherit = powerbi.Prototype.inherit;\n var DataViewPivotCategorical;\n (function (DataViewPivotCategorical) {\n /**\n * Pivots categories in a categorical DataView into valueGroupings.\n * This is akin to a mathematical matrix transpose.\n */\n function apply(dataView) {\n debug.assertValue(dataView, 'dataView');\n var categorical = dataView.categorical;\n if (!categorical)\n return null;\n var categories = categorical.categories;\n if (!categories || categories.length !== 1)\n return null;\n var values = categorical.values;\n if (_.isEmpty(values) || values.source)\n return null;\n var category = categories[0], categoryIdentities = category.identity, categoryValues = category.values, pivotedColumns = [], pivotedValues = [];\n for (var rowIdx = 0, rowCount = categoryValues.length; rowIdx < rowCount; rowIdx++) {\n var categoryValue = categoryValues[rowIdx], categoryIdentity = categoryIdentities[rowIdx];\n for (var colIdx = 0, colCount = values.length; colIdx < colCount; colIdx++) {\n var value = values[colIdx], pivotedColumn = inherit(value.source);\n // A value has a series group, which is not implemented for pivoting -- just give up.\n if (value.identity)\n return null;\n pivotedColumn.groupName = categoryValue;\n var pivotedValue = {\n source: pivotedColumn,\n values: [value.values[rowIdx]],\n identity: categoryIdentity,\n min: value.min,\n max: value.max,\n subtotal: value.subtotal\n };\n var highlights = value.highlights;\n if (highlights) {\n pivotedValue.highlights = [highlights[rowIdx]];\n }\n pivotedColumns.push(pivotedColumn);\n pivotedValues.push(pivotedValue);\n }\n }\n var pivotedMetadata = inherit(dataView.metadata);\n pivotedMetadata.columns = pivotedColumns;\n values = data.DataViewTransform.createValueColumns(pivotedValues, category.identityFields, category.source);\n return {\n metadata: pivotedMetadata,\n categorical: {\n values: values,\n },\n matrix: dataView.matrix\n };\n }\n DataViewPivotCategorical.apply = apply;\n })(DataViewPivotCategorical = data.DataViewPivotCategorical || (data.DataViewPivotCategorical = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataViewPivotMatrix;\n (function (DataViewPivotMatrix) {\n /** Pivots row hierarchy members in a matrix DataView into column hierarchy. */\n function apply(dataViewMatrix, context) {\n debug.assertValue(dataViewMatrix, 'dataViewMatrix');\n if (!context.columnHierarchyRewritten)\n dataViewMatrix.columns = powerbi.Prototype.inherit(dataViewMatrix.columns);\n var columns = dataViewMatrix.columns;\n if (!context.rowHierarchyRewritten)\n dataViewMatrix.rows = powerbi.Prototype.inherit(dataViewMatrix.rows);\n var rows = dataViewMatrix.rows;\n if (columns.levels.length > 1)\n return;\n var pivotedRowNode = {\n level: 0\n };\n var columnLeafNodes = columns.root.children;\n var measureCount = columnLeafNodes.length;\n // Notes related to VSTS 6999369: The level value of Measure Header nodes is not necessarily its parent node's level + 1.\n // In particular, the Measure Header column nodes directly under the Grand Total node at level 0 (i.e. _.last(pivotResultMatrix.columns.root.children))\n // will have level === (pivotResultMatrix.columns.levels.length - 1), which will be greater than the Grand Total node's 'level + 1' \n // in a matrix with 2+ column fields and 2+ measure fields.\n // In this code, all row levels will get pivoted over to the columns hierarchy, hence the level of any Measure Header nodes in the pivot result\n // is just (1 + the level of the deepest row node's level), which === rows.levels.length.\n var pivotResultMeasureHeaderLevel = rows.levels.length;\n if (measureCount > 0) {\n var index_1 = 0;\n var callback = function (node) {\n // Collect values and remove them from row leaves\n if (node.values) {\n if (!pivotedRowNode.values)\n pivotedRowNode.values = {};\n for (var i = 0; i < measureCount; i++)\n pivotedRowNode.values[index_1++] = node.values[i];\n delete node.values;\n }\n // Create measure headers if there are more than one measures\n if (measureCount > 1) {\n if (!node.children)\n node.children = [];\n for (var j = 0; j < measureCount; j++) {\n var measureHeaderLeaf = { level: pivotResultMeasureHeaderLevel };\n // Copy levelSourceIndex from columnLeafNodes (as they might have been reordered)\n var columnLeafNode = columnLeafNodes[j];\n measureHeaderLeaf.levelSourceIndex = columnLeafNode.levelSourceIndex;\n if (node.isSubtotal)\n measureHeaderLeaf.isSubtotal = true;\n node.children.push(measureHeaderLeaf);\n }\n }\n };\n if (context.hierarchyTreesRewritten) {\n forEachLeaf(rows.root, callback);\n }\n else {\n dataViewMatrix.columns.root = cloneTreeExecuteOnLeaf(rows.root, callback);\n }\n }\n else {\n if (!context.hierarchyTreesRewritten) {\n dataViewMatrix.columns.root = cloneTree(rows.root);\n }\n }\n if (measureCount > 1) {\n // Keep measure headers, but move them to the innermost level\n var level = { sources: columns.levels[0].sources };\n rows.levels.push(level);\n columns.levels.length = 0;\n }\n if (context.hierarchyTreesRewritten) {\n dataViewMatrix.columns.root = rows.root;\n dataViewMatrix.rows.root = {\n children: [pivotedRowNode]\n };\n }\n else {\n var updatedRowRoot = powerbi.Prototype.inherit(dataViewMatrix.rows.root);\n updatedRowRoot.children = [pivotedRowNode];\n dataViewMatrix.rows.root = updatedRowRoot;\n }\n dataViewMatrix.columns.levels = rows.levels;\n dataViewMatrix.rows.levels = [];\n }\n DataViewPivotMatrix.apply = apply;\n function forEachLeaf(root, callback) {\n var children = root.children;\n if (children && children.length > 0) {\n for (var i = 0, ilen = children.length; i < ilen; i++)\n forEachLeaf(children[i], callback);\n return;\n }\n callback(root);\n }\n function cloneTree(node) {\n return cloneTreeExecuteOnLeaf(node);\n }\n DataViewPivotMatrix.cloneTree = cloneTree;\n function cloneTreeExecuteOnLeaf(node, callback) {\n var updatedNode = powerbi.Prototype.inherit(node);\n var children = node.children;\n if (children && children.length > 0) {\n var newChildren = [];\n for (var i = 0, ilen = children.length; i < ilen; i++) {\n var updatedChild = cloneTreeExecuteOnLeaf(children[i], callback);\n newChildren.push(updatedChild);\n }\n updatedNode.children = newChildren;\n }\n else {\n if (callback)\n callback(updatedNode);\n }\n return updatedNode;\n }\n DataViewPivotMatrix.cloneTreeExecuteOnLeaf = cloneTreeExecuteOnLeaf;\n })(DataViewPivotMatrix = data.DataViewPivotMatrix || (data.DataViewPivotMatrix = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataViewSelfCrossJoin;\n (function (DataViewSelfCrossJoin) {\n /**\n * Returns a new DataView based on the original, with a single DataViewCategorical category that is \"cross joined\"\n * to itself as a value grouping.\n * This is the mathematical equivalent of taking an array and turning it into an identity matrix.\n */\n function apply(dataView) {\n debug.assertValue(dataView, 'dataView');\n if (!dataView.categorical)\n return;\n var dataViewCategorical = dataView.categorical;\n if (!dataViewCategorical.categories || dataViewCategorical.categories.length !== 1)\n return;\n if (dataViewCategorical.values && dataViewCategorical.values.source)\n return;\n return applyCategorical(dataView.metadata, dataViewCategorical);\n }\n DataViewSelfCrossJoin.apply = apply;\n function applyCategorical(dataViewMetadata, dataViewCategorical) {\n debug.assertValue(dataViewMetadata, 'dataViewMetadata');\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\n debug.assertValue(dataViewCategorical.categories, 'dataViewCategorical.categories');\n var category = dataViewCategorical.categories[0], categoryValues = category.values, categoryLength = categoryValues.length;\n if (categoryLength === 0)\n return;\n var valuesArray = dataViewCategorical.values\n ? dataViewCategorical.values.grouped()[0].values\n : [];\n var transformedDataView = data.createCategoricalDataViewBuilder()\n .withCategories(dataViewCategorical.categories)\n .withGroupedValues(createGroupedValues(category, categoryValues, categoryLength, valuesArray))\n .build();\n dataViewMetadata = powerbi.Prototype.inherit(dataViewMetadata);\n dataViewMetadata.columns = transformedDataView.metadata.columns;\n return {\n metadata: dataViewMetadata,\n categorical: transformedDataView.categorical,\n };\n }\n function createGroupedValues(category, categoryValues, categoryLength, valuesArray) {\n debug.assertValue(category, 'category');\n debug.assertValue(categoryValues, 'categoryValues');\n debug.assertValue(categoryLength, 'categoryLength');\n debug.assertValue(valuesArray, 'valuesArray');\n var nullValuesArray = createNullValues(categoryLength), valuesArrayLen = valuesArray.length, seriesData = [];\n for (var i = 0; i < categoryLength; i++) {\n var seriesDataItem = [];\n for (var j = 0; j < valuesArrayLen; j++) {\n var originalValueColumn = valuesArray[j], originalHighlightValues = originalValueColumn.highlights;\n var seriesDataItemCategory = {\n values: inheritArrayWithValue(nullValuesArray, originalValueColumn.values, i),\n };\n if (originalHighlightValues)\n seriesDataItemCategory.highlights = inheritArrayWithValue(nullValuesArray, originalHighlightValues, i);\n seriesDataItem.push(seriesDataItemCategory);\n }\n seriesData.push(seriesDataItem);\n }\n return {\n groupColumn: {\n source: category.source,\n identityFrom: { fields: category.identityFields, identities: category.identity },\n values: category.values,\n },\n valueColumns: _.map(valuesArray, function (v) { return { source: v.source }; }),\n data: seriesData,\n };\n }\n })(DataViewSelfCrossJoin = data.DataViewSelfCrossJoin || (data.DataViewSelfCrossJoin = {}));\n function createNullValues(length) {\n debug.assertValue(length, 'length');\n var array = new Array(length);\n for (var i = 0; i < length; i++)\n array[i] = null;\n return array;\n }\n function inheritArrayWithValue(nullValues, original, index) {\n var inherited = powerbi.Prototype.inherit(nullValues);\n inherited[index] = original[index];\n return inherited;\n }\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n var DataShapeBindingDataReduction = powerbi.data.DataShapeBindingDataReduction;\n var inheritSingle = powerbi.Prototype.inheritSingle;\n var DataViewPivotCategoricalToPrimaryGroups;\n (function (DataViewPivotCategoricalToPrimaryGroups) {\n /**\n * If mapping requests cross axis data reduction and the binding has secondary grouping, mutates the binding to\n * pivot the secondary before the primary.\n */\n function pivotBinding(binding, allMappings, finalMapping, defaultDataVolume) {\n // unpivot is inferred from result in DataViewTransform.apply but it does not have the\n // compiled mappings available, let alone the merged mapping, only the original\n // DataViewMappings. to keep that inference easy, only apply pivot when there's\n // only one matching mapping\n if (!allMappings || allMappings.length !== 1)\n return;\n if (!finalMapping.categorical || !finalMapping.categorical.dataReductionAlgorithm)\n return;\n if (!binding)\n return;\n if (!canPivotCategorical(binding, finalMapping))\n return;\n // pivot secondary onto front of primary\n binding.Primary.Groupings = [binding.Secondary.Groupings[0], binding.Primary.Groupings[0]];\n binding.Secondary = undefined;\n // set primary to pivot reduction\n binding.DataReduction = {\n Primary: DataShapeBindingDataReduction.createFrom(finalMapping.categorical.dataReductionAlgorithm),\n DataVolume: finalMapping.categorical.dataVolume || defaultDataVolume,\n };\n }\n DataViewPivotCategoricalToPrimaryGroups.pivotBinding = pivotBinding;\n /** narrowly targets scatter chart scenario for now to keep code simple */\n function isPivotableAxis(axis) {\n return axis\n && axis.Groupings\n && axis.Groupings.length === 1\n && !_.isEmpty(axis.Groupings[0].Projections)\n && !axis.Groupings[0].Subtotal\n && _.isEmpty(axis.Groupings[0].SuppressedProjections);\n }\n function canPivotCategorical(binding, mapping) {\n if (!isPivotableAxis(binding.Primary))\n return false;\n if (!isPivotableAxis(binding.Secondary) || binding.Secondary.Groupings[0].Projections.length !== 1)\n return false;\n // don't pivot if either axis has a data reduction\n if (binding.DataReduction && (binding.DataReduction.Primary || binding.DataReduction.Secondary))\n return false;\n return true;\n }\n function unpivotResult(oldDataView, selects, dataViewMappings, projectionActiveItems) {\n if (!inferUnpivotTransform(selects, dataViewMappings, oldDataView, projectionActiveItems))\n return oldDataView;\n // This returns a subsetted version of the DataView rather than using prototypal inheritance because\n // any dataviews in the old one (including ones invented after this code is written) will correspond\n // to a pivoted query result and therefore will be in the wrong shape for the unpivoted query the\n // querying code made.\n var newDataView = {\n metadata: {\n columns: ArrayExtensions.copy(oldDataView.metadata.columns),\n },\n };\n // preserve view types that aren't affected by pivoting\n if (oldDataView.single)\n newDataView.single = oldDataView.single;\n if (oldDataView.table)\n newDataView.table = oldDataView.table;\n // other views are derived from matrix\n if (oldDataView.matrix) {\n var newDataViewMatrix = unpivotMatrix(oldDataView.matrix);\n // categorical only if there's data\n if (!_.isEmpty(newDataViewMatrix.valueSources)) {\n // Guard against a DataViewMatrix with composite grouping in columns, because composite group in Series is \n // not yet expressible in the current version of DataViewValueColumns and DataViewValueColumnGroup interfaces.\n // this.canPivotCategorical() would have returned false in the first place for this query.\n var hasCompositeGroupInSeries = data.utils.DataViewMatrixUtils.containsCompositeGroup(newDataViewMatrix.columns);\n if (!hasCompositeGroupInSeries) {\n newDataView.categorical = categoricalFromUnpivotedMatrix(newDataViewMatrix, newDataView.metadata.columns);\n }\n }\n }\n return newDataView;\n }\n DataViewPivotCategoricalToPrimaryGroups.unpivotResult = unpivotResult;\n /**\n * Infer from the query result and the visual mappings whether the query was pivoted.\n * Narrowly targets scatter chart scenario for now to keep code simple\n */\n function inferUnpivotTransform(selects, dataViewMappings, dataView, projectionActiveItems) {\n if (_.isEmpty(selects) || _.isEmpty(dataViewMappings) || !dataView)\n return false;\n // select applicable mappings based on select roles\n var roleKinds = data.DataViewSelectTransform.createRoleKindFromMetadata(selects, dataView.metadata);\n var projections = data.DataViewSelectTransform.projectionsFromSelects(selects, projectionActiveItems);\n var supportedDataViewMappings = powerbi.DataViewAnalysis.chooseDataViewMappings(projections, dataViewMappings, roleKinds).supportedMappings;\n // NOTE: limiting to simple situation that handles scatter for now - see the other side in canPivotCategorical\n if (!supportedDataViewMappings || supportedDataViewMappings.length !== 1)\n return false;\n var categoricalMapping = supportedDataViewMappings[0].categorical;\n if (!categoricalMapping)\n return false;\n // pivoted query will have produced a matrix\n var matrixDataview = dataView.matrix;\n if (!matrixDataview)\n return false;\n // matrix must have two levels of grouping\n if (!matrixDataview.rows || !matrixDataview.rows.levels || matrixDataview.rows.levels.length !== 2)\n return false;\n // get category and value grouping roles\n var categoryGroups = [];\n var valueGroups = [];\n var addGroupingRole = function (roleName, groups) {\n var roleProjections = projections[roleName];\n if (!roleProjections)\n return;\n for (var _i = 0, _a = roleProjections.all(); _i < _a.length; _i++) {\n var roleProjection = _a[_i];\n if (roleKinds[roleProjection.queryRef] === powerbi.VisualDataRoleKind.Grouping)\n groups.push(roleProjection.queryRef);\n }\n };\n powerbi.DataViewMapping.visitCategoricalCategories(categoricalMapping.categories, {\n visitRole: function (roleName) { addGroupingRole(roleName, categoryGroups); }\n });\n powerbi.DataViewMapping.visitCategoricalValues(categoricalMapping.values, {\n visitRole: function (roleName) { addGroupingRole(roleName, valueGroups); }\n });\n // need both for pivot to have been done\n if (_.isEmpty(categoryGroups) || _.isEmpty(valueGroups))\n return false;\n // if there was a pivot, there won't be any measures left in the columns\n for (var _i = 0, _a = matrixDataview.columns.levels; _i < _a.length; _i++) {\n var level = _a[_i];\n for (var _b = 0, _c = level.sources; _b < _c.length; _b++) {\n var source = _c[_b];\n if (!source.isMeasure)\n return false;\n }\n }\n return true;\n }\n /**\n * matrix will have two groupings in the rows, outer (series) and inner (categories), and none in the columns.\n * this function changes that so that the categories become the rows and the series the columns.\n */\n function unpivotMatrix(oldMatrix) {\n var oldRows = oldMatrix.rows;\n var oldRoot = oldRows.root;\n var oldChildren = oldRoot.children;\n // series are the outer grouping\n var series = [];\n var seriesIdLevel = oldRows.levels[0];\n var seriesIdFields = oldRoot.childIdentityFields;\n // categories are the inner grouping. \n var categoryIndex = {};\n var categories = [];\n var categoryIdLevel = oldRows.levels[1];\n var categoryIdFields = _.isEmpty(oldChildren) ? undefined : oldChildren[0].childIdentityFields;\n var measureCount = oldMatrix.valueSources.length;\n // within each series value, the category list may not be complete so cannot simply use the inner loop index\n // to reference it.\n var findCategory = function (identity) {\n var index = categoryIndex[identity.key];\n debug.assert(index !== undefined, \"findcat() !== undefined\");\n return index;\n };\n // collect series and categories from the row hierarchy\n if (oldChildren) {\n var addCategory = function (categoryNode) {\n var key = categoryNode.identity.key;\n var index = categoryIndex[key];\n if (index === undefined) {\n index = categories.length;\n categoryIndex[key] = index;\n categories.push(categoryNode);\n }\n };\n for (var _i = 0, oldChildren_1 = oldChildren; _i < oldChildren_1.length; _i++) {\n var seriesNode = oldChildren_1[_i];\n series.push(seriesNode);\n for (var _a = 0, _b = seriesNode.children; _a < _b.length; _a++) {\n var categoryNode = _b[_a];\n addCategory(categoryNode);\n }\n }\n }\n // extract intersection values from pivoted matrix\n // values will be indexed by categories then series\n var matrixValues = new Array(categories.length);\n for (var j = 0; j < series.length; ++j) {\n var seriesNode = oldChildren[j];\n for (var _c = 0, _d = seriesNode.children; _c < _d.length; _c++) {\n var categoryNode = _d[_c];\n var i = findCategory(categoryNode.identity); // must lookup actual category index\n if (!matrixValues[i])\n matrixValues[i] = new Array(series.length);\n matrixValues[i][j] = categoryNode.values;\n }\n }\n // columns of the unpivoted matrix are the series\n var newColumns = {\n root: {\n children: _.map(series, function (s) {\n var inheritedNode = inheritSingle(s);\n inheritedNode.level = 0; // s.level should already be 0, but just in case...\n inheritedNode.children = undefined; // if Measure Headers exist in oldMatrix.columns, newColumns.root.children will get populated later in this function\n inheritedNode.childIdentityFields = undefined;\n return inheritedNode;\n }),\n childIdentityFields: seriesIdFields,\n },\n levels: [\n seriesIdLevel,\n ],\n };\n // Re-add any Measure Headers from oldMatrix.columns as leaf nodes under newColumns\n if (measureCount > 0) {\n var newColChildren = _.map(oldMatrix.columns.root.children, function (srcnode) {\n var dstnode = { level: 1 };\n if (srcnode.levelSourceIndex)\n dstnode.levelSourceIndex = srcnode.levelSourceIndex;\n return dstnode;\n });\n for (var i = 0; i < newColumns.root.children.length; ++i)\n newColumns.root.children[i].children = newColChildren;\n newColumns.levels.push(oldMatrix.columns.levels[0]);\n }\n // rows of the unpivoted matrix are the categories\n var newRows = {\n root: {\n children: _.map(categories, function (c) {\n var inheritedNode = inheritSingle(c);\n inheritedNode.level = 0;\n inheritedNode.children = undefined; // c.children should already be undefined, but just in case...\n inheritedNode.childIdentityFields = undefined; // c.children should already be undefined, but just in case...\n return inheritedNode;\n }),\n childIdentityFields: categoryIdFields,\n },\n levels: [\n categoryIdLevel,\n ],\n };\n // put values into rows\n if (measureCount > 0) {\n for (var i = 0; i < categories.length; ++i) {\n var row = newRows.root.children[i];\n var rowValues = {};\n for (var j = 0; j < series.length; ++j) {\n var mvalues = matrixValues[i] && matrixValues[i][j];\n for (var k = 0; k < measureCount; ++k) {\n var l = j * measureCount + k;\n rowValues[l] = !mvalues\n ? (k === 0 ? { value: null } : { value: null, valueSourceIndex: k })\n : mvalues[k];\n }\n }\n row.values = rowValues;\n }\n }\n var newMatrix = {\n rows: newRows,\n columns: newColumns,\n valueSources: oldMatrix.valueSources,\n };\n return newMatrix;\n }\n /** build a categorical data view from an unpivoted matrix. */\n function categoricalFromUnpivotedMatrix(matrix, columnMetadata) {\n var seriesCount = matrix.columns.root.children.length;\n var measureMetadata = matrix.valueSources;\n var measureCount = measureMetadata.length;\n var categories = createCategoryColumnsFromUnpivotedMatrix(matrix);\n // create grouped values\n var groups = [];\n for (var j = 0; j < seriesCount; ++j) {\n var seriesColumn = matrix.columns.root.children[j];\n var group = {\n values: [],\n identity: seriesColumn.identity,\n name: seriesColumn.value || null,\n };\n groups.push(group);\n for (var k = 0; k < measureCount; ++k) {\n var valueColumnMetadataSrc = measureMetadata[k];\n var valueColumnMetadataDst = {};\n for (var key in valueColumnMetadataSrc)\n valueColumnMetadataDst[key] = valueColumnMetadataSrc[key];\n valueColumnMetadataDst.groupName = group.name;\n columnMetadata.push(valueColumnMetadataDst);\n var valueColumn = {\n source: valueColumnMetadataDst,\n values: [],\n identity: group.identity,\n };\n group.values.push(valueColumn);\n // grab measure values in the group from across rows of matrix\n var index = k + j * measureCount;\n for (var _i = 0, _a = matrix.rows.root.children; _i < _a.length; _i++) {\n var categoryNode = _a[_i];\n var value = categoryNode.values[index].value;\n valueColumn.values.push(value);\n }\n }\n }\n // and now ungrouped\n var values = [];\n for (var _b = 0, groups_1 = groups; _b < groups_1.length; _b++) {\n var group = groups_1[_b];\n for (var k = 0; k < measureCount; ++k) {\n values.push(group.values[k]);\n }\n }\n values.grouped = function () { return groups; };\n values.identityFields = matrix.columns.root.childIdentityFields;\n values.source = matrix.columns.levels[0].sources[0];\n // final assembly\n var categorical = {\n categories: categories,\n values: values,\n };\n return categorical;\n }\n function createCategoryColumnsFromUnpivotedMatrix(unpivotedMatrix) {\n debug.assertValue(unpivotedMatrix, 'unpivotedMatrix');\n debug.assert(unpivotedMatrix && unpivotedMatrix.rows && unpivotedMatrix.rows.levels && (unpivotedMatrix.rows.levels.length === 1), 'pre-condition: unpivotedMatrix should have exactly one level in row hierarchy');\n // Create categories from rows. If matrix.rows.levels[0].sources represents a composite group, expand each column in the \n // composite group into a separate DataViewCategoryColumn. The identity and childIdentityFields properties will be the \n // same amongst the resulting DataViewCategoryColumns.\n var categoryIdentity = _.map(unpivotedMatrix.rows.root.children, function (x) { return x.identity; });\n var categoryIdentityFields = unpivotedMatrix.rows.root.childIdentityFields;\n var categorySourceColumns = unpivotedMatrix.rows.levels[0].sources;\n var categories = [];\n for (var i = 0, ilen = categorySourceColumns.length; i < ilen; i++) {\n var groupLevelValues = _.map(unpivotedMatrix.rows.root.children, function (categoryNode) {\n var levelValues = categoryNode.levelValues;\n // Please refer to the interface comments on when this is undefined... But in today's code\n // I believe we will not see undefined levelValues in the rows of any unpivotedMatrix. \n if (levelValues !== undefined) {\n debug.assert(levelValues[i] && (levelValues[i].levelSourceIndex === i), 'pre-condition: DataViewMatrixNode.levelValues is expected to have one DataViewMatrixGroupValue node per level source column, sorted by levelSourceIndex.');\n return levelValues[i].value;\n }\n });\n categories.push({\n source: categorySourceColumns[i],\n values: groupLevelValues,\n identity: categoryIdentity,\n identityFields: categoryIdentityFields,\n });\n }\n return categories;\n }\n })(DataViewPivotCategoricalToPrimaryGroups = data.DataViewPivotCategoricalToPrimaryGroups || (data.DataViewPivotCategoricalToPrimaryGroups = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var inherit = powerbi.Prototype.inherit;\n var inheritSingle = powerbi.Prototype.inheritSingle;\n var ArrayExtensions = jsCommon.ArrayExtensions;\n var EnumExtensions = jsCommon.EnumExtensions;\n // TODO: refactor & focus DataViewTransform into a service with well-defined dependencies.\n var DataViewTransform;\n (function (DataViewTransform) {\n var fillRulePropertyDescriptor = { type: { fillRule: {} } };\n function apply(options) {\n debug.assertValue(options, 'options');\n // TODO: Flow a context object through to capture errors/warnings about what happens here for better diagnosability.\n var prototype = options.prototype, objectDescriptors = options.objectDescriptors, dataViewMappings = options.dataViewMappings, transforms = options.transforms, projectionActiveItems = transforms && transforms.roles && transforms.roles.activeItems, colorAllocatorFactory = options.colorAllocatorFactory, dataRoles = options.dataRoles;\n if (!prototype)\n return transformEmptyDataView(objectDescriptors, transforms, colorAllocatorFactory);\n if (!transforms)\n return [prototype];\n // Transform Query DataView\n prototype = data.DataViewPivotCategoricalToPrimaryGroups.unpivotResult(prototype, transforms.selects, dataViewMappings, projectionActiveItems);\n var visualDataViews = transformQueryToVisualDataView(prototype, transforms, objectDescriptors, dataViewMappings, colorAllocatorFactory, dataRoles);\n // Transform and generate derived visual DataViews\n visualDataViews = data.DataViewRegression.run({\n dataViewMappings: dataViewMappings,\n visualDataViews: visualDataViews,\n dataRoles: dataRoles,\n objectDescriptors: objectDescriptors,\n objectDefinitions: transforms.objects,\n colorAllocatorFactory: colorAllocatorFactory,\n transformSelects: transforms.selects,\n metadata: prototype.metadata,\n projectionActiveItems: projectionActiveItems,\n });\n return visualDataViews;\n }\n DataViewTransform.apply = apply;\n function transformQueryToVisualDataView(prototype, transforms, objectDescriptors, dataViewMappings, colorAllocatorFactory, dataRoles) {\n var transformedDataViews = [];\n var splits = transforms.splits;\n if (_.isEmpty(splits)) {\n transformedDataViews.push(transformDataView(prototype, objectDescriptors, dataViewMappings, transforms, colorAllocatorFactory, dataRoles));\n }\n else {\n for (var _i = 0, splits_1 = splits; _i < splits_1.length; _i++) {\n var split = splits_1[_i];\n var transformed = transformDataView(prototype, objectDescriptors, dataViewMappings, transforms, colorAllocatorFactory, dataRoles, split.selects);\n transformedDataViews.push(transformed);\n }\n }\n return transformedDataViews;\n }\n function transformEmptyDataView(objectDescriptors, transforms, colorAllocatorFactory) {\n if (transforms && transforms.objects) {\n var emptyDataView = {\n metadata: {\n columns: [],\n }\n };\n transformObjects(emptyDataView, 0 /* None */, objectDescriptors, transforms.objects, transforms.selects, colorAllocatorFactory);\n return [emptyDataView];\n }\n return [];\n }\n function transformDataView(prototype, objectDescriptors, roleMappings, transforms, colorAllocatorFactory, dataRoles, selectsToInclude) {\n debug.assertValue(prototype, 'prototype');\n debug.assertValue(transforms, 'transforms');\n debug.assert(!selectsToInclude ||\n _.filter(Object.keys(selectsToInclude), function (selectIndex) { return selectsToInclude[selectIndex] && (!transforms.selects || !transforms.selects[selectIndex]); })\n .length === 0, // asserts that the number of select indices in selectsToInclude without a corresponding Select Transform === 0\n 'If selectsToInclude is specified, every Select Index in it must have a corresponding Select Transform.');\n var targetKinds = getTargetKinds(roleMappings);\n var transformed = inherit(prototype);\n transformed.metadata = inherit(prototype.metadata);\n var projectionOrdering = transforms.roles && transforms.roles.ordering;\n var projectionActiveItems = transforms.roles && transforms.roles.activeItems;\n transformed = transformSelects(transformed, targetKinds, roleMappings, transforms.selects, projectionOrdering, selectsToInclude);\n transformObjects(transformed, targetKinds, objectDescriptors, transforms.objects, transforms.selects, colorAllocatorFactory);\n // Note: Do this step after transformObjects() so that metadata columns in 'transformed' have roles and objects.general.formatString populated\n transformed = data.DataViewConcatenateCategoricalColumns.detectAndApply(transformed, objectDescriptors, roleMappings, projectionOrdering, transforms.selects, projectionActiveItems);\n data.DataViewNormalizeValues.apply({\n dataview: transformed,\n dataViewMappings: roleMappings,\n dataRoles: dataRoles,\n });\n return transformed;\n }\n function getTargetKinds(roleMappings) {\n debug.assertAnyValue(roleMappings, 'roleMappings');\n if (!roleMappings)\n return 0 /* None */;\n var result = 0 /* None */;\n for (var _i = 0, roleMappings_1 = roleMappings; _i < roleMappings_1.length; _i++) {\n var roleMapping = roleMappings_1[_i];\n if (roleMapping.categorical)\n result |= 1 /* Categorical */;\n if (roleMapping.matrix)\n result |= 2 /* Matrix */;\n if (roleMapping.single)\n result |= 4 /* Single */;\n if (roleMapping.table)\n result |= 8 /* Table */;\n if (roleMapping.tree)\n result |= 16 /* Tree */;\n }\n return result;\n }\n function transformSelects(dataView, targetDataViewKinds, roleMappings, selectTransforms, projectionOrdering, selectsToInclude) {\n var columnRewrites = [];\n if (selectTransforms) {\n dataView.metadata.columns = applyTransformsToColumns(dataView.metadata.columns, selectTransforms, columnRewrites);\n }\n // NOTE: no rewrites necessary for Tree (it doesn't reference the columns)\n if (dataView.categorical && EnumExtensions.hasFlag(targetDataViewKinds, 1 /* Categorical */)) {\n dataView.categorical = applyRewritesToCategorical(dataView.categorical, columnRewrites, selectsToInclude);\n // TODO VSTS 7024199: separate out structural transformations from dataViewTransform.transformSelects(...)\n // NOTE: This is slightly DSR-specific.\n dataView = pivotIfNecessary(dataView, roleMappings);\n }\n // Don't perform this potentially expensive transform unless we actually have a matrix.\n // When we switch to lazy per-visual DataView creation, we'll be able to remove this check.\n if (dataView.matrix && EnumExtensions.hasFlag(targetDataViewKinds, 2 /* Matrix */)) {\n var matrixTransformationContext = {\n rowHierarchyRewritten: false,\n columnHierarchyRewritten: false,\n hierarchyTreesRewritten: false\n };\n dataView.matrix = applyRewritesToMatrix(dataView.matrix, columnRewrites, roleMappings, projectionOrdering, matrixTransformationContext);\n // TODO VSTS 7024199: separate out structural transformations from dataViewTransform.transformSelects(...)\n if (shouldPivotMatrix(dataView.matrix, roleMappings))\n data.DataViewPivotMatrix.apply(dataView.matrix, matrixTransformationContext);\n }\n // Don't perform this potentially expensive transform unless we actually have a table.\n // When we switch to lazy per-visual DataView creation, we'll be able to remove this check.\n if (dataView.table && EnumExtensions.hasFlag(targetDataViewKinds, 8 /* Table */)) {\n dataView.table = applyRewritesToTable(dataView.table, columnRewrites, projectionOrdering);\n }\n return dataView;\n }\n function applyTransformsToColumns(prototypeColumns, selects, rewrites) {\n debug.assertValue(prototypeColumns, 'columns');\n if (!selects)\n return prototypeColumns;\n //column may contain undefined entries\n var columns = inherit(prototypeColumns);\n for (var i = 0, len = prototypeColumns.length; i < len; i++) {\n var prototypeColumn = prototypeColumns[i];\n var select = selects[prototypeColumn.index];\n if (!select)\n continue;\n var column = columns[i] = inherit(prototypeColumn);\n if (select.roles)\n column.roles = select.roles;\n if (select.type)\n column.type = select.type;\n column.format = getFormatForColumn(select, column);\n if (select.displayName)\n column.displayName = select.displayName;\n if (select.queryName)\n column.queryName = select.queryName;\n if (select.kpi)\n column.kpi = select.kpi;\n if (select.sort)\n column.sort = select.sort;\n if (select.discourageAggregationAcrossGroups)\n column.discourageAggregationAcrossGroups = select.discourageAggregationAcrossGroups;\n rewrites.push({\n from: prototypeColumn,\n to: column,\n });\n }\n return columns;\n }\n /**\n * Get the column format. Order of precendence is:\n * 1. Select format\n * 2. Column format\n */\n function getFormatForColumn(select, column) {\n // TODO: we already copied the select.Format to column.format, we probably don't need this check\n return select.format || column.format;\n }\n function applyRewritesToCategorical(prototype, columnRewrites, selectsToInclude) {\n debug.assertValue(prototype, 'prototype');\n debug.assertValue(columnRewrites, 'columnRewrites');\n var categorical = inherit(prototype);\n function override(value) {\n var rewrittenSource = findOverride(value.source, columnRewrites);\n if (rewrittenSource) {\n var rewritten = inherit(value);\n rewritten.source = rewrittenSource;\n return rewritten;\n }\n }\n var categories = powerbi.Prototype.overrideArray(prototype.categories, override);\n if (categories)\n categorical.categories = categories;\n var valuesOverride = powerbi.Prototype.overrideArray(prototype.values, override);\n var valueColumns = valuesOverride || prototype.values;\n if (valueColumns) {\n if (valueColumns.source) {\n if (selectsToInclude && !selectsToInclude[valueColumns.source.index]) {\n // if processing a split and this is the split without series...\n valueColumns.source = undefined;\n }\n else {\n var rewrittenValuesSource = findOverride(valueColumns.source, columnRewrites);\n if (rewrittenValuesSource)\n valueColumns.source = rewrittenValuesSource;\n }\n }\n if (selectsToInclude) {\n // Apply selectsToInclude to values by removing value columns not included\n for (var i = valueColumns.length - 1; i >= 0; i--) {\n if (!selectsToInclude[valueColumns[i].source.index]) {\n valueColumns.splice(i, 1);\n }\n }\n }\n var isDynamicSeries_1 = !!valueColumns.source;\n debug.assert(_.every(valueColumns, function (valueColumn) { return isDynamicSeries_1 === !!valueColumn.identity; }), 'After applying selectsToInclude, all remaining DataViewValueColumn objects should have a consistent scope type (static vs. dynamic) with the parent DataViewValueColumns object.');\n // Dynamic or not, always update the return values of grouped() to have the rewritten 'source' property\n var seriesGroups_1;\n if (isDynamicSeries_1) {\n // We have a dynamic series, so update the return value of grouped() to have the DataViewValueColumn objects with rewritten 'source'.\n // Also, exclude any column that belongs to a static series.\n seriesGroups_1 = inherit(valueColumns.grouped());\n // The following assert is not a rule that's set in stone. If it becomes false someday, update the code below to remove static series from seriesGroups.\n debug.assert(_.every(seriesGroups_1, function (group) { return !!group.identity; }), 'If the categorical has a dynamic series, query DataView is expected to have a grouped() function that returns only dynamic series groups, even when there is any column that belongs to a static group (in the case of combo chart and splits). If this assertion becomes false someday, update the code below to remove static series from seriesGroups.');\n var nextSeriesGroupIndex = 0;\n var currentSeriesGroup = void 0;\n for (var i = 0, ilen = valueColumns.length; i < ilen; i++) {\n var currentValueColumn = valueColumns[i];\n if (!currentSeriesGroup || (currentValueColumn.identity !== currentSeriesGroup.identity)) {\n currentSeriesGroup = inherit(seriesGroups_1[nextSeriesGroupIndex]);\n seriesGroups_1[nextSeriesGroupIndex] = currentSeriesGroup;\n currentSeriesGroup.values = [];\n nextSeriesGroupIndex++;\n debug.assert(currentValueColumn.identity === currentSeriesGroup.identity, 'expecting the value columns are sequenced by series groups');\n }\n currentSeriesGroup.values.push(currentValueColumn);\n }\n }\n else {\n // We are in a static series, so we should throw away the grouped and recreate it using the static values\n // which have already been filtered\n seriesGroups_1 = [{ values: valueColumns }];\n }\n valueColumns.grouped = function () { return seriesGroups_1; };\n categorical.values = valueColumns;\n }\n return categorical;\n }\n function applyRewritesToTable(prototype, columnRewrites, projectionOrdering) {\n debug.assertValue(prototype, 'prototype');\n debug.assertValue(columnRewrites, 'columnRewrites');\n var table = inherit(prototype);\n // Copy the rewritten columns into the table view\n var override = function (metadata) { return findOverride(metadata, columnRewrites); };\n var columns = powerbi.Prototype.overrideArray(prototype.columns, override);\n if (columns)\n table.columns = columns;\n if (!projectionOrdering)\n return table;\n var newToOldPositions = createTableColumnPositionMapping(projectionOrdering, columnRewrites);\n if (!newToOldPositions)\n return table;\n // Reorder the columns\n var columnsClone = columns.slice(0);\n var keys = Object.keys(newToOldPositions);\n for (var i = 0, len = keys.length; i < len; i++) {\n var sourceColumn = columnsClone[newToOldPositions[keys[i]]];\n // In the case we've hit the end of our columns array, but still have position reordering keys,\n // there is a duplicate column so we will need to add a new column for the duplicate data\n if (i === columns.length)\n columns.push(sourceColumn);\n else {\n debug.assert(i < columns.length, 'The column index is out of range for reordering.');\n columns[i] = sourceColumn;\n }\n }\n // Reorder the rows\n var rows = powerbi.Prototype.overrideArray(table.rows, function (row) {\n var newRow = [];\n for (var i = 0, len = keys.length; i < len; ++i)\n newRow[i] = row[newToOldPositions[keys[i]]];\n return newRow;\n });\n if (rows)\n table.rows = rows;\n return table;\n }\n /** Creates a mapping of new position to original position. */\n function createTableColumnPositionMapping(projectionOrdering, columnRewrites) {\n var roles = Object.keys(projectionOrdering);\n // If we have more than one role then the ordering of columns between roles is ambiguous, so don't reorder anything.\n if (roles.length !== 1)\n return;\n var role = roles[0], originalOrder = _.map(columnRewrites, function (rewrite) { return rewrite.from.index; }), newOrder = projectionOrdering[role];\n return createOrderMapping(originalOrder, newOrder);\n }\n function applyRewritesToMatrix(prototype, columnRewrites, roleMappings, projectionOrdering, context) {\n debug.assertValue(prototype, 'prototype');\n debug.assertValue(columnRewrites, 'columnRewrites');\n debug.assertValue(roleMappings, 'roleMappings');\n var firstRoleMappingWithMatrix = _.find(roleMappings, function (roleMapping) { return !!roleMapping.matrix; });\n debug.assertValue(firstRoleMappingWithMatrix, 'roleMappings - at least one role mapping is expected to target DataViewMatrix');\n var matrixMapping = firstRoleMappingWithMatrix.matrix;\n var matrix = inherit(prototype);\n function override(metadata) {\n return findOverride(metadata, columnRewrites);\n }\n function overrideHierarchy(hierarchy) {\n var rewrittenHierarchy = null;\n var newLevels = powerbi.Prototype.overrideArray(hierarchy.levels, function (level) {\n var newLevel = null;\n var levelSources = powerbi.Prototype.overrideArray(level.sources, override);\n if (levelSources)\n newLevel = ensureRewritten(newLevel, level, function (h) { return h.sources = levelSources; });\n return newLevel;\n });\n if (newLevels)\n rewrittenHierarchy = ensureRewritten(rewrittenHierarchy, hierarchy, function (r) { return r.levels = newLevels; });\n return rewrittenHierarchy;\n }\n var rows = overrideHierarchy(matrix.rows);\n if (rows) {\n matrix.rows = rows;\n context.rowHierarchyRewritten = true;\n }\n var columns = overrideHierarchy(matrix.columns);\n if (columns) {\n matrix.columns = columns;\n context.columnHierarchyRewritten = true;\n }\n var valueSources = powerbi.Prototype.overrideArray(matrix.valueSources, override);\n if (valueSources) {\n matrix.valueSources = valueSources;\n // Only need to reorder if we have more than one value source, and they are all bound to the same role\n var matrixValues = matrixMapping.values;\n if (projectionOrdering && valueSources.length > 1 && matrixValues && matrixValues.for) {\n var columnLevels = columns.levels.length;\n if (columnLevels > 0) {\n var newToOldPositions_1 = createMatrixValuesPositionMapping(matrixValues, projectionOrdering, valueSources, columnRewrites);\n if (newToOldPositions_1) {\n var keys_1 = Object.keys(newToOldPositions_1);\n var numKeys_1 = keys_1.length;\n // Reorder the value columns\n columns.root = data.DataViewPivotMatrix.cloneTree(columns.root);\n if (columnLevels === 1)\n reorderChildNodes(columns.root, newToOldPositions_1);\n else\n forEachNodeAtLevel(columns.root, columnLevels - 2, function (node) { return reorderChildNodes(node, newToOldPositions_1); });\n // Reorder the value rows\n matrix.rows.root = data.DataViewPivotMatrix.cloneTreeExecuteOnLeaf(matrix.rows.root, function (node) {\n if (!node.values)\n return;\n var newValues = {};\n var iterations = Object.keys(node.values).length / numKeys_1;\n for (var i = 0, len = iterations; i < len; i++) {\n var offset = i * numKeys_1;\n for (var keysIndex = 0; keysIndex < numKeys_1; keysIndex++)\n newValues[offset + keysIndex] = node.values[offset + newToOldPositions_1[keys_1[keysIndex]]];\n }\n node.values = newValues;\n });\n context.hierarchyTreesRewritten = true;\n }\n }\n }\n }\n reorderMatrixCompositeGroups(matrix, matrixMapping, projectionOrdering);\n return matrix;\n }\n function reorderChildNodes(node, newToOldPositions) {\n var keys = Object.keys(newToOldPositions);\n var numKeys = keys.length;\n var children = node.children;\n var childrenClone = children.slice(0);\n for (var i = 0, len = numKeys; i < len; i++) {\n var sourceColumn = childrenClone[newToOldPositions[keys[i]]];\n // In the case we've hit the end of our columns array, but still have position reordering keys,\n // there is a duplicate column so we will need to add a new column for the duplicate data\n if (i === children.length)\n children.push(sourceColumn);\n else {\n debug.assert(i < children.length, 'The column index is out of range for reordering.');\n children[i] = sourceColumn;\n }\n }\n }\n /**\n * Returns a inheritSingle() version of the specified prototype DataViewMatrix with any composite group levels\n * and values re-ordered by projection ordering.\n * Returns undefined if no re-ordering under the specified prototype is necessary.\n */\n function reorderMatrixCompositeGroups(prototype, supportedDataViewMapping, projection) {\n var transformedDataView;\n if (prototype && supportedDataViewMapping && projection) {\n // reorder levelValues in any composite groups in rows hierarchy\n var transformedRowsHierarchy_1;\n powerbi.DataViewMapping.visitMatrixItems(supportedDataViewMapping.rows, {\n visitRole: function (role, context) {\n transformedRowsHierarchy_1 = reorderMatrixHierarchyCompositeGroups(transformedRowsHierarchy_1 || prototype.rows, role, projection);\n }\n });\n // reorder levelValues in any composite groups in columns hierarchy\n var transformedColumnsHierarchy_1;\n powerbi.DataViewMapping.visitMatrixItems(supportedDataViewMapping.columns, {\n visitRole: function (role, context) {\n transformedColumnsHierarchy_1 = reorderMatrixHierarchyCompositeGroups(transformedColumnsHierarchy_1 || prototype.columns, role, projection);\n }\n });\n if (transformedRowsHierarchy_1 || transformedColumnsHierarchy_1) {\n transformedDataView = inheritSingle(prototype);\n transformedDataView.rows = transformedRowsHierarchy_1 || transformedDataView.rows;\n transformedDataView.columns = transformedColumnsHierarchy_1 || transformedDataView.columns;\n }\n }\n return transformedDataView;\n }\n /**\n * Returns a inheritSingle() version of the specified matrixHierarchy with any composite group levels and\n * values re-ordered by projection ordering.\n * Returns undefined if no re-ordering under the specified matrixHierarchy is necessary.\n */\n function reorderMatrixHierarchyCompositeGroups(matrixHierarchy, hierarchyRole, projection) {\n debug.assertValue(matrixHierarchy, 'matrixHierarchy');\n debug.assertValue(hierarchyRole, 'hierarchyRole');\n debug.assertValue(projection, 'projection');\n var transformedHierarchy;\n var selectIndicesInProjectionOrder = projection[hierarchyRole];\n // reordering needs to happen only if there are multiple columns for the hierarchy's role in the projection\n var hasMultipleColumnsInProjection = selectIndicesInProjectionOrder && selectIndicesInProjectionOrder.length >= 2;\n if (hasMultipleColumnsInProjection && !_.isEmpty(matrixHierarchy.levels)) {\n for (var i = matrixHierarchy.levels.length - 1; i >= 0; i--) {\n var hierarchyLevel = matrixHierarchy.levels[i];\n // compute a mapping for any necessary reordering of columns at this given level, based on projection ordering\n var newToOldLevelSourceIndicesMapping = createMatrixHierarchyLevelSourcesPositionMapping(hierarchyLevel, hierarchyRole, projection);\n if (newToOldLevelSourceIndicesMapping) {\n if (_.isUndefined(transformedHierarchy)) {\n // Because we start inspecting the hierarchy from the deepest level and work backwards to the root,\n // the current hierarchyLevel is therefore the inner-most level that needs re-ordering of composite group values...\n transformedHierarchy = inheritSingle(matrixHierarchy);\n transformedHierarchy.levels = inheritSingle(matrixHierarchy.levels);\n // Because the current hierarchyLevel is the inner-most level that needs re-ordering of composite group values,\n // inheriting all nodes from root down to this level will also prepare the nodes for any transform that needs to\n // happen in other hierarchy levels in the later iterations of this for-loop.\n transformedHierarchy.root = data.utils.DataViewMatrixUtils.inheritMatrixNodeHierarchy(matrixHierarchy.root, i, true);\n }\n // reorder the metadata columns in the sources array at that level\n var transformingHierarchyLevel = inheritSingle(matrixHierarchy.levels[i]); // inherit at most once during the whole dataViewTransform for this obj...\n transformedHierarchy.levels[i] = reorderMatrixHierarchyLevelColumnSources(transformingHierarchyLevel, newToOldLevelSourceIndicesMapping);\n // reorder the level values in the composite group nodes at the current hierarchy level\n reorderMatrixHierarchyLevelValues(transformedHierarchy.root, i, newToOldLevelSourceIndicesMapping);\n }\n }\n }\n return transformedHierarchy;\n }\n /**\n * If reordering is needed on the level's metadata column sources (i.e. hierarchyLevel.sources),\n * returns the mapping from the target LevelSourceIndex (based on projection order) to original LevelSourceIndex.\n *\n * The returned value maps level source indices from the new target order (calculated from projection order)\n * back to the original order as they appear in the specified hierarchyLevel's sources.\n * Please refer to comments on the createOrderMapping() function for more explanation on the mappings in the return value.\n *\n * Note: The return value is the mapping from new index to old index, for consistency with existing and similar functions in this module.\n *\n * @param hierarchyLevel The hierarchy level that contains the metadata column sources.\n * @param hierarchyRoleName The role name for the hierarchy where the specified hierarchyLevel belongs.\n * @param projection The projection ordering that includes an ordering for the specified hierarchyRoleName.\n */\n function createMatrixHierarchyLevelSourcesPositionMapping(hierarchyLevel, hierarchyRole, projection) {\n debug.assertValue(hierarchyLevel, 'hierarchyLevel');\n debug.assertValue(hierarchyRole, 'hierarchyRole');\n debug.assertValue(projection, 'projection');\n debug.assertValue(projection[hierarchyRole], 'pre-condition: The specified projection must contain an ordering for the specified hierarchyRoleName.');\n var newToOldLevelSourceIndicesMapping;\n var levelSourceColumns = hierarchyLevel.sources;\n if (levelSourceColumns && levelSourceColumns.length >= 2) {\n // The hierarchy level has multiple columns, so it is possible to have composite group, go on to check other conditions...\n var columnsForHierarchyRoleOrderedByLevelSourceIndex = data.utils.DataViewMetadataColumnUtils.joinMetadataColumnsAndProjectionOrder(levelSourceColumns, projection, hierarchyRole);\n if (columnsForHierarchyRoleOrderedByLevelSourceIndex && columnsForHierarchyRoleOrderedByLevelSourceIndex.length >= 2) {\n // The hierarchy level has multiple columns for the hierarchy's role, go on to calculate newToOldLevelSourceIndicesMapping...\n var columnsForHierarchyRoleOrderedByProjection = _.sortBy(columnsForHierarchyRoleOrderedByLevelSourceIndex, function (columnInfo) { return columnInfo.projectionOrderIndex; });\n newToOldLevelSourceIndicesMapping = createOrderMapping(_.map(columnsForHierarchyRoleOrderedByLevelSourceIndex, function (columnInfo) { return columnInfo.sourceIndex; }), _.map(columnsForHierarchyRoleOrderedByProjection, function (columnInfo) { return columnInfo.sourceIndex; }));\n }\n }\n return newToOldLevelSourceIndicesMapping;\n }\n /**\n * Applies re-ordering on the specified transformingHierarchyLevel's sources.\n * Returns the same object as the specified transformingHierarchyLevel.\n */\n function reorderMatrixHierarchyLevelColumnSources(transformingHierarchyLevel, newToOldLevelSourceIndicesMapping) {\n debug.assertValue(transformingHierarchyLevel, 'transformingHierarchyLevel');\n debug.assertValue(newToOldLevelSourceIndicesMapping, 'newToOldLevelSourceIndicesMapping');\n var originalLevelSources = transformingHierarchyLevel.sources;\n transformingHierarchyLevel.sources = originalLevelSources.slice(0); // make a clone of the array before modifying it, because the for-loop depends on the origin array.\n var newLevelSourceIndices = Object.keys(newToOldLevelSourceIndicesMapping);\n for (var i = 0, ilen = newLevelSourceIndices.length; i < ilen; i++) {\n var newLevelSourceIndex = newLevelSourceIndices[i];\n var oldLevelSourceIndex = newToOldLevelSourceIndicesMapping[newLevelSourceIndex];\n debug.assert(oldLevelSourceIndex < originalLevelSources.length, 'pre-condition: The value in every mapping in the specified levelSourceIndicesReorderingMap must be a valid index to the specified hierarchyLevel.sources array property');\n transformingHierarchyLevel.sources[newLevelSourceIndex] = originalLevelSources[oldLevelSourceIndex];\n }\n return transformingHierarchyLevel;\n }\n /**\n * Reorders the elements in levelValues in each node under transformingHierarchyRootNode at the specified hierarchyLevel,\n * and updates their DataViewMatrixGroupValue.levelSourceIndex property.\n *\n * Returns the same object as the specified transformingHierarchyRootNode.\n */\n function reorderMatrixHierarchyLevelValues(transformingHierarchyRootNode, transformingHierarchyLevelIndex, newToOldLevelSourceIndicesMapping) {\n debug.assertValue(transformingHierarchyRootNode, 'transformingHierarchyRootNode');\n debug.assertValue(newToOldLevelSourceIndicesMapping, 'newToOldLevelSourceIndicesMapping');\n var oldToNewLevelSourceIndicesMapping = createReversedMapping(newToOldLevelSourceIndicesMapping);\n forEachNodeAtLevel(transformingHierarchyRootNode, transformingHierarchyLevelIndex, function (transformingMatrixNode) {\n var originalLevelValues = transformingMatrixNode.levelValues;\n // Note: Technically this function is incorrect, because the driving source of the new LevelValues is really\n // the \"projection for this composite group\", a concept that isn't yet implemented in DataViewProjectionOrdering.\n // The following code isn't correct in the special case where a column is projected twice in this composite group,\n // in which case the DSR will not have the duplicate columns; DataViewTransform is supposed to expand the duplicates.\n // Until we fully implement composite group projection, though, we'll just sort what we have in transformingMatrixNode.levelValues.\n if (!_.isEmpty(originalLevelValues)) {\n // First, re-order the elements in transformingMatrixNode.levelValues by the new levelSourceIndex order.\n // _.sortBy() also creates a new array, which we want to do for all nodes (including when levelValues.length === 1)\n // because we don't want to accidentally modify the array AND its value references in Query DataView\n var newlyOrderedLevelValues = _.sortBy(originalLevelValues, function (levelValue) { return oldToNewLevelSourceIndicesMapping[levelValue.levelSourceIndex]; });\n for (var i = 0, ilen = newlyOrderedLevelValues.length; i < ilen; i++) {\n var transformingLevelValue = inheritSingle(newlyOrderedLevelValues[i]);\n transformingLevelValue.levelSourceIndex = oldToNewLevelSourceIndicesMapping[transformingLevelValue.levelSourceIndex];\n newlyOrderedLevelValues[i] = transformingLevelValue;\n }\n transformingMatrixNode.levelValues = newlyOrderedLevelValues;\n // For consistency with how DataViewTreeNode.value works, and for a bit of backward compatibility,\n // copy the last value from DataViewMatrixNode.levelValues to DataViewMatrixNode.value.\n var newlyOrderedLastLevelValue = _.last(newlyOrderedLevelValues);\n if (transformingMatrixNode.value !== newlyOrderedLastLevelValue.value) {\n transformingMatrixNode.value = newlyOrderedLastLevelValue.value;\n }\n if ((transformingMatrixNode.levelSourceIndex || 0) !== newlyOrderedLastLevelValue.levelSourceIndex) {\n transformingMatrixNode.levelSourceIndex = newlyOrderedLastLevelValue.levelSourceIndex;\n }\n }\n });\n return transformingHierarchyRootNode;\n }\n /**\n * Creates a mapping of new position to original position.\n *\n * The return value is a mapping where each key-value pair represent the order mapping of a particular column:\n * - the key in the key-value pair is the index of the particular column in the new order (e.g. projection order)\n * - the value in the key-value pair is the index of the particular column in the original order\n */\n function createMatrixValuesPositionMapping(matrixValues, projectionOrdering, valueSources, columnRewrites) {\n var role = matrixValues.for.in;\n var newOrder = projectionOrdering[role];\n var originalOrder = _.chain(columnRewrites)\n .filter(function (rewrite) { return _.contains(valueSources, rewrite.to); })\n .map(function (rewrite) { return rewrite.from.index; })\n .value();\n return createOrderMapping(originalOrder, newOrder);\n }\n /**\n * Creates a mapping of indices, from indices to the specified newOrder array, back to indices to the specified\n * originalOrder array.\n * Each of the number value in originalOrder and newOrder is actually the unique key of a column (unqiue\n * under the context of the caller code), e.g. the Select Index in projection ordering array.\n * Also, the specified originalOrder must contain every value that exists in newOrder.\n *\n * If the specified originalOrder and newOrder are different in sequence order, then this function returns a collection of\n * key-value pair, each of which represents the new and old indices of a particular column:\n * - the key in each key-value pair is the index of the particular column key as it exists in the specified newOrder array\n * - the value in each key-value pair is the index of the particular column key as it exists in the specified originalOrder array\n *\n * For example on how the return value is consumed, see functions such as reorderMatrixHierarchyLevelColumnSources(...).\n *\n * If the specified originalOrder and newOrder are same, then this function returns undefined.\n *\n * @param originalOrder E.g. an array of metadata column \"select indices\", in the original order as they exist in Query DataView.\n * @param newOrder E.g. an array of metadata column \"select indices\", in rojection ordering.\n */\n function createOrderMapping(originalOrder, newOrder) {\n // Optimization: avoid rewriting if the current order is correct\n if (ArrayExtensions.sequenceEqual(originalOrder, newOrder, function (x, y) { return x === y; }))\n return;\n var mapping = {};\n for (var i = 0, len = newOrder.length; i < len; ++i) {\n var newPosition = newOrder[i];\n mapping[i] = originalOrder.indexOf(newPosition);\n }\n return mapping;\n }\n function createReversedMapping(mapping) {\n debug.assertValue(mapping, 'mapping');\n var reversed = {};\n for (var key in mapping) {\n // Note: key is a string after we get it out from mapping, thus we need to parse it\n // back into a number before putting it as the value in the reversed mapping\n var value = mapping[key];\n var keyAsNumber = parseInt(key, 10);\n reversed[value] = keyAsNumber;\n }\n debug.assertValue(Object.keys(mapping).length === Object.keys(reversed).length, 'pre-condition: The specified mapping must not contain any duplicate value because duplicate values are obmitted from the reversed mapping.');\n return reversed;\n }\n function forEachNodeAtLevel(node, targetLevel, callback) {\n debug.assertValue(node, 'node');\n debug.assert(targetLevel >= 0, 'argetLevel >= 0');\n debug.assertValue(callback, 'callback');\n if (node.level === targetLevel) {\n callback(node);\n return;\n }\n var children = node.children;\n if (children && children.length > 0) {\n for (var i = 0, ilen = children.length; i < ilen; i++)\n forEachNodeAtLevel(children[i], targetLevel, callback);\n }\n }\n DataViewTransform.forEachNodeAtLevel = forEachNodeAtLevel;\n function findOverride(source, columnRewrites) {\n for (var i = 0, len = columnRewrites.length; i < len; i++) {\n var columnRewrite = columnRewrites[i];\n if (columnRewrite.from === source)\n return columnRewrite.to;\n }\n }\n function ensureRewritten(rewritten, prototype, callback) {\n if (!rewritten)\n rewritten = inherit(prototype);\n if (callback)\n callback(rewritten);\n return rewritten;\n }\n function transformObjects(dataView, targetDataViewKinds, objectDescriptors, objectDefinitions, selectTransforms, colorAllocatorFactory) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(targetDataViewKinds, 'targetDataViewKinds');\n debug.assertAnyValue(objectDescriptors, 'objectDescriptors');\n debug.assertAnyValue(objectDefinitions, 'objectDefinitions');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n if (!objectDescriptors)\n return;\n var objectsForAllSelectors = data.DataViewObjectEvaluationUtils.groupObjectsBySelector(objectDefinitions);\n data.DataViewObjectEvaluationUtils.addImplicitObjects(objectsForAllSelectors, objectDescriptors, dataView.metadata.columns, selectTransforms);\n var metadataOnce = objectsForAllSelectors.metadataOnce;\n var dataObjects = objectsForAllSelectors.data;\n if (metadataOnce)\n evaluateMetadataObjects(dataView, selectTransforms, objectDescriptors, metadataOnce.objects, dataObjects, colorAllocatorFactory);\n var metadataObjects = objectsForAllSelectors.metadata;\n if (metadataObjects) {\n for (var i = 0, len = metadataObjects.length; i < len; i++) {\n var metadataObject = metadataObjects[i];\n var objectDefns = metadataObject.objects;\n var colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefns, colorAllocatorFactory);\n evaluateMetadataRepetition(dataView, selectTransforms, objectDescriptors, metadataObject.selector, objectDefns, colorAllocatorCache);\n }\n }\n for (var i = 0, len = dataObjects.length; i < len; i++) {\n var dataObject = dataObjects[i];\n var objectDefns = dataObject.objects;\n var colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefns, colorAllocatorFactory);\n evaluateDataRepetition(dataView, targetDataViewKinds, selectTransforms, objectDescriptors, dataObject.selector, dataObject.rules, objectDefns, colorAllocatorCache);\n }\n var userDefined = objectsForAllSelectors.userDefined;\n if (userDefined) {\n // TODO: We only handle user defined objects at the metadata level, but should be able to support them with arbitrary repetition.\n evaluateUserDefinedObjects(dataView, selectTransforms, objectDescriptors, userDefined, colorAllocatorFactory);\n }\n }\n DataViewTransform.transformObjects = transformObjects;\n function evaluateUserDefinedObjects(dataView, selectTransforms, objectDescriptors, objectDefns, colorAllocatorFactory) {\n debug.assertValue(dataView, 'dataView');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n var dataViewObjects = dataView.metadata.objects;\n if (!dataViewObjects) {\n dataViewObjects = dataView.metadata.objects = {};\n }\n for (var _i = 0, objectDefns_1 = objectDefns; _i < objectDefns_1.length; _i++) {\n var objectDefn = objectDefns_1[_i];\n var id = objectDefn.selector.id;\n var colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefn.objects, colorAllocatorFactory);\n var evalContext = data.createStaticEvalContext(colorAllocatorCache, dataView, selectTransforms);\n var objects = data.DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefn.objects);\n for (var objectName in objects) {\n var object = objects[objectName];\n var map = dataViewObjects[objectName];\n if (!map)\n map = dataViewObjects[objectName] = [];\n debug.assert(powerbi.DataViewObjects.isUserDefined(map), 'expected DataViewObjectMap');\n // NOTE: We do not check for duplicate ids.\n map.push({ id: id, object: object });\n }\n }\n }\n /** Evaluates and sets properties on the DataView metadata. */\n function evaluateMetadataObjects(dataView, selectTransforms, objectDescriptors, objectDefns, dataObjects, colorAllocatorFactory) {\n debug.assertValue(dataView, 'dataView');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(dataObjects, 'dataObjects');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n var colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefns, colorAllocatorFactory);\n var evalContext = data.createStaticEvalContext(colorAllocatorCache, dataView, selectTransforms);\n var objects = data.DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\n if (objects) {\n dataView.metadata.objects = objects;\n for (var objectName in objects) {\n var object = objects[objectName], objectDesc = objectDescriptors[objectName];\n for (var propertyName in object) {\n var propertyDesc = objectDesc.properties[propertyName], ruleDesc = propertyDesc.rule;\n if (!ruleDesc)\n continue;\n var definition = createRuleEvaluationInstance(dataView, colorAllocatorFactory, ruleDesc, objectName, object[propertyName], propertyDesc.type);\n if (!definition)\n continue;\n dataObjects.push(definition);\n }\n }\n }\n }\n function createRuleEvaluationInstance(dataView, colorAllocatorFactory, ruleDesc, objectName, propertyValue, ruleType) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n debug.assertValue(ruleDesc, 'ruleDesc');\n debug.assertValue(propertyValue, 'propertyValue');\n debug.assertValue(ruleType, 'ruleType');\n var ruleOutput = ruleDesc.output;\n if (!ruleOutput)\n return;\n var selectorToCreate = findSelectorForRuleInput(dataView, ruleOutput.selector);\n if (!selectorToCreate)\n return;\n if (ruleType.fillRule) {\n return createRuleEvaluationInstanceFillRule(dataView, colorAllocatorFactory, ruleDesc, selectorToCreate, objectName, propertyValue);\n }\n }\n function createRuleEvaluationInstanceFillRule(dataView, colorAllocatorFactory, ruleDesc, selectorToCreate, objectName, propertyValue) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n debug.assertValue(ruleDesc, 'ruleDesc');\n debug.assertValue(selectorToCreate, 'selectorToCreate');\n debug.assertValue(propertyValue, 'propertyValue');\n var colorAllocator = tryCreateColorAllocatorForFillRule(dataView, colorAllocatorFactory, ruleDesc.inputRole, 1 /* Role */, propertyValue);\n if (!colorAllocator)\n return;\n var rule = new data.ColorRuleEvaluation(ruleDesc.inputRole, colorAllocator);\n var fillRuleProperties = {};\n fillRuleProperties[ruleDesc.output.property] = {\n solid: { color: rule }\n };\n return {\n selector: selectorToCreate,\n rules: [rule],\n objects: [{\n name: objectName,\n properties: fillRuleProperties,\n }]\n };\n }\n function tryCreateColorAllocatorForFillRule(dataView, colorAllocatorFactory, identifier, identifierKind, propertyValue) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n debug.assertValue(identifier, 'identifier');\n debug.assertValue(identifierKind, 'identifierKind');\n debug.assertValue(propertyValue, 'propertyValue');\n if (propertyValue.linearGradient2)\n return createColorAllocatorLinearGradient2(dataView, colorAllocatorFactory, identifier, identifierKind, propertyValue, propertyValue.linearGradient2);\n if (propertyValue.linearGradient3)\n return createColorAllocatorLinearGradient3(dataView, colorAllocatorFactory, identifier, identifierKind, propertyValue, propertyValue.linearGradient3);\n }\n function createColorAllocatorLinearGradient2(dataView, colorAllocatorFactory, identifier, identifierKind, propertyValueFillRule, linearGradient2) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n debug.assertValue(identifier, 'identifier');\n debug.assertValue(identifierKind, 'identifierKind');\n debug.assertValue(linearGradient2, 'linearGradient2');\n linearGradient2 = propertyValueFillRule.linearGradient2;\n if (linearGradient2.min.value === undefined ||\n linearGradient2.max.value === undefined) {\n var inputRange = findRuleInputColumnNumberRange(dataView, identifier, identifierKind);\n if (!inputRange)\n return;\n if (linearGradient2.min.value === undefined)\n linearGradient2.min.value = inputRange.min;\n if (linearGradient2.max.value === undefined)\n linearGradient2.max.value = inputRange.max;\n }\n return colorAllocatorFactory.linearGradient2(propertyValueFillRule.linearGradient2);\n }\n function createColorAllocatorLinearGradient3(dataView, colorAllocatorFactory, identifier, identifierKind, propertyValueFillRule, linearGradient3) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n debug.assertValue(identifier, 'identifier');\n debug.assertValue(identifierKind, 'identifierKind');\n debug.assertValue(linearGradient3, 'linearGradient3');\n var splitScales;\n linearGradient3 = propertyValueFillRule.linearGradient3;\n if (linearGradient3.min.value === undefined ||\n linearGradient3.mid.value === undefined ||\n linearGradient3.max.value === undefined) {\n var inputRange = findRuleInputColumnNumberRange(dataView, identifier, identifierKind);\n if (!inputRange)\n return;\n splitScales =\n linearGradient3.min.value === undefined &&\n linearGradient3.max.value === undefined &&\n linearGradient3.mid.value !== undefined;\n if (linearGradient3.min.value === undefined) {\n linearGradient3.min.value = inputRange.min;\n }\n if (linearGradient3.max.value === undefined) {\n linearGradient3.max.value = inputRange.max;\n }\n if (linearGradient3.mid.value === undefined) {\n var midValue = (linearGradient3.max.value + linearGradient3.min.value) / 2;\n linearGradient3.mid.value = midValue;\n }\n }\n return colorAllocatorFactory.linearGradient3(propertyValueFillRule.linearGradient3, splitScales);\n }\n function populateColorAllocatorCache(dataView, selectTransforms, objectDefns, colorAllocatorFactory) {\n debug.assertValue(dataView, 'dataView');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n var cache = data.createColorAllocatorCache();\n var staticEvalContext = data.createStaticEvalContext();\n for (var i = 0, len = objectDefns.length; i < len; i++) {\n var objectDefnProperties = objectDefns[i].properties;\n for (var propertyName in objectDefnProperties) {\n var fillProperty = objectDefnProperties[propertyName];\n if (fillProperty &&\n fillProperty.solid &&\n fillProperty.solid.color &&\n fillProperty.solid.color.kind === 23 /* FillRule */) {\n var fillRuleExpr = fillProperty.solid.color;\n var inputExprQueryName = findFirstQueryNameForExpr(selectTransforms, fillRuleExpr.input);\n if (!inputExprQueryName)\n continue;\n var fillRule = data.DataViewObjectEvaluator.evaluateProperty(staticEvalContext, fillRulePropertyDescriptor, fillRuleExpr.rule);\n var colorAllocator = tryCreateColorAllocatorForFillRule(dataView, colorAllocatorFactory, inputExprQueryName, 0 /* QueryName */, fillRule);\n if (colorAllocator)\n cache.register(fillRuleExpr, colorAllocator);\n }\n }\n }\n return cache;\n }\n function evaluateDataRepetition(dataView, targetDataViewKinds, selectTransforms, objectDescriptors, selector, rules, objectDefns, colorAllocatorCache) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(targetDataViewKinds, 'targetDataViewKinds');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertAnyValue(rules, 'rules');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(colorAllocatorCache, 'colorAllocatorFactory');\n var containsWildcard = data.Selector.containsWildcard(selector);\n var dataViewCategorical = dataView.categorical;\n if (dataViewCategorical && EnumExtensions.hasFlag(targetDataViewKinds, 1 /* Categorical */)) {\n // 1) Match against categories\n evaluateDataRepetitionCategoricalCategory(dataViewCategorical, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache);\n // 2) Match against valueGrouping\n evaluateDataRepetitionCategoricalValueGrouping(dataViewCategorical, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache);\n }\n var dataViewMatrix = dataView.matrix;\n if (dataViewMatrix && EnumExtensions.hasFlag(targetDataViewKinds, 2 /* Matrix */)) {\n var rewrittenMatrix = evaluateDataRepetitionMatrix(dataViewMatrix, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache);\n if (rewrittenMatrix) {\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\n // revisit this, likely when we do lazy evaluation of DataView.\n dataView.matrix = rewrittenMatrix;\n }\n }\n var dataViewTable = dataView.table;\n if (dataViewTable && EnumExtensions.hasFlag(targetDataViewKinds, 8 /* Table */)) {\n var rewrittenSelector = rewriteTableRoleSelector(dataViewTable, selector);\n var rewrittenTable = evaluateDataRepetitionTable(dataViewTable, selectTransforms, objectDescriptors, rewrittenSelector, rules, containsWildcard, objectDefns, colorAllocatorCache);\n if (rewrittenTable) {\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\n // revisit this, likely when we do lazy evaluation of DataView.\n dataView.table = rewrittenTable;\n }\n }\n }\n function rewriteTableRoleSelector(dataViewTable, selector) {\n if (data.Selector.hasRoleWildcard(selector)) {\n selector = findSelectorForRoleWildcard(dataViewTable, selector);\n }\n return selector;\n }\n function findSelectorForRoleWildcard(dataViewTable, selector) {\n var resultingSelector = {\n data: [],\n id: selector.id,\n metadata: selector.metadata\n };\n for (var _i = 0, _a = selector.data; _i < _a.length; _i++) {\n var dataSelector = _a[_i];\n if (data.Selector.isRoleWildcard(dataSelector)) {\n var selectorRoles = dataSelector.roles;\n var allColumnsBelongToSelectorRole = allColumnsBelongToRole(dataViewTable.columns, selectorRoles);\n var exprs = dataViewTable.identityFields;\n if (allColumnsBelongToSelectorRole && exprs) {\n resultingSelector.data.push(data.DataViewScopeWildcard.fromExprs(exprs));\n continue;\n }\n }\n if (isUniqueDataSelector(resultingSelector.data, dataSelector)) {\n resultingSelector.data.push(dataSelector);\n }\n }\n return resultingSelector;\n }\n function isUniqueDataSelector(dataSelectors, newSelector) {\n if (_.isEmpty(dataSelectors))\n return true;\n return !_.any(dataSelectors, function (dataSelector) { return dataSelector.key === newSelector.key; });\n }\n function allColumnsBelongToRole(columns, selectorRoles) {\n for (var _i = 0, columns_6 = columns; _i < columns_6.length; _i++) {\n var column = columns_6[_i];\n var roles = column.roles;\n if (!roles || !_.any(selectorRoles, function (selectorRole) { return roles[selectorRole]; }))\n return false;\n }\n return true;\n }\n function evaluateDataRepetitionCategoricalCategory(dataViewCategorical, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache) {\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertAnyValue(rules, 'rules');\n debug.assertValue(containsWildcard, 'containsWildcard');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\n if (!dataViewCategorical.categories || dataViewCategorical.categories.length === 0)\n return;\n var targetColumn = findSelectedCategoricalColumn(dataViewCategorical, selector);\n if (!targetColumn)\n return;\n var identities = targetColumn.identities, foundMatch, evalContext = data.createCategoricalEvalContext(colorAllocatorCache, dataViewCategorical);\n if (!identities)\n return;\n debug.assert(targetColumn.column.values.length === identities.length, 'Column length mismatch');\n for (var i = 0, len = identities.length; i < len; i++) {\n var identity = identities[i];\n if (containsWildcard || data.Selector.matchesData(selector, [identity])) {\n evalContext.setCurrentRowIndex(i);\n var objects = data.DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\n if (objects) {\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\n // revisit this, likely when we do lazy evaluation of DataView.\n if (!targetColumn.column.objects) {\n targetColumn.column.objects = [];\n targetColumn.column.objects.length = len;\n }\n targetColumn.column.objects[i] = objects;\n }\n if (!containsWildcard)\n return true;\n foundMatch = true;\n }\n }\n return foundMatch;\n }\n function evaluateDataRepetitionCategoricalValueGrouping(dataViewCategorical, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache) {\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertAnyValue(rules, 'rules');\n debug.assertValue(containsWildcard, 'containsWildcard');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\n var dataViewCategoricalValues = dataViewCategorical.values;\n if (!dataViewCategoricalValues || !dataViewCategoricalValues.identityFields)\n return;\n if (!data.Selector.matchesKeys(selector, [dataViewCategoricalValues.identityFields]))\n return;\n var valuesGrouped = dataViewCategoricalValues.grouped();\n if (!valuesGrouped)\n return;\n // NOTE: We do not set the evalContext row index below because iteration is over value groups (i.e., columns, no rows).\n // This should be enhanced in the future.\n var evalContext = data.createCategoricalEvalContext(colorAllocatorCache, dataViewCategorical);\n var foundMatch;\n for (var i = 0, len = valuesGrouped.length; i < len; i++) {\n var valueGroup = valuesGrouped[i];\n var selectorMetadata = selector.metadata;\n var valuesInGroup = valueGroup.values;\n if (containsWildcard || data.Selector.matchesData(selector, [valueGroup.identity])) {\n var objects = data.DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\n if (objects) {\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\n // revisit this, likely when we do lazy evaluation of DataView.\n if (selectorMetadata) {\n for (var j = 0, jlen = valuesInGroup.length; j < jlen; j++) {\n var valueColumn = valuesInGroup[j], valueSource = valueColumn.source;\n if (valueSource.queryName === selectorMetadata) {\n var valueSourceOverwrite = powerbi.Prototype.inherit(valueSource);\n valueSourceOverwrite.objects = objects;\n valueColumn.source = valueSourceOverwrite;\n foundMatch = true;\n break;\n }\n }\n }\n else {\n valueGroup.objects = objects;\n setGrouped(dataViewCategoricalValues, valuesGrouped);\n foundMatch = true;\n }\n }\n if (!containsWildcard)\n return true;\n }\n }\n return foundMatch;\n }\n function evaluateDataRepetitionMatrix(dataViewMatrix, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache) {\n var evalContext = data.createMatrixEvalContext(colorAllocatorCache, dataViewMatrix);\n var rewrittenRows = evaluateDataRepetitionMatrixHierarchy(evalContext, dataViewMatrix.rows, objectDescriptors, selector, rules, containsWildcard, objectDefns);\n var rewrittenCols = evaluateDataRepetitionMatrixHierarchy(evalContext, dataViewMatrix.columns, objectDescriptors, selector, rules, containsWildcard, objectDefns);\n if (rewrittenRows || rewrittenCols) {\n var rewrittenMatrix = inheritSingle(dataViewMatrix);\n if (rewrittenRows)\n rewrittenMatrix.rows = rewrittenRows;\n if (rewrittenCols)\n rewrittenMatrix.columns = rewrittenCols;\n return rewrittenMatrix;\n }\n }\n function evaluateDataRepetitionMatrixHierarchy(evalContext, dataViewMatrixHierarchy, objectDescriptors, selector, rules, containsWildcard, objectDefns) {\n debug.assertAnyValue(dataViewMatrixHierarchy, 'dataViewMatrixHierarchy');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertAnyValue(rules, 'rules');\n debug.assertValue(objectDefns, 'objectDefns');\n if (!dataViewMatrixHierarchy)\n return;\n var root = dataViewMatrixHierarchy.root;\n if (!root)\n return;\n var rewrittenRoot = evaluateDataRepetitionMatrixNode(evalContext, root, objectDescriptors, selector, rules, containsWildcard, objectDefns);\n if (rewrittenRoot) {\n var rewrittenHierarchy = inheritSingle(dataViewMatrixHierarchy);\n rewrittenHierarchy.root = rewrittenRoot;\n return rewrittenHierarchy;\n }\n }\n function evaluateDataRepetitionMatrixNode(evalContext, dataViewNode, objectDescriptors, selector, rules, containsWildcard, objectDefns) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(dataViewNode, 'dataViewNode');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertAnyValue(rules, 'rules');\n debug.assertValue(objectDefns, 'objectDefns');\n var childNodes = dataViewNode.children;\n if (!childNodes)\n return;\n var rewrittenNode;\n var shouldSearchChildren;\n var childIdentityFields = dataViewNode.childIdentityFields;\n if (childIdentityFields) {\n // NOTE: selector matching in matrix currently only considers the current node, and does not consider parents as part of the match.\n shouldSearchChildren = data.Selector.matchesKeys(selector, [childIdentityFields]);\n }\n for (var i = 0, len = childNodes.length; i < len; i++) {\n var childNode = childNodes[i], identity = childNode.identity, rewrittenChildNode = null;\n if (shouldSearchChildren) {\n if (containsWildcard || data.Selector.matchesData(selector, [identity])) {\n // TODO: Need to initialize context for rule-based properties. Rule-based properties\n // (such as fillRule/gradients) are not currently implemented.\n var objects = data.DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\n if (objects) {\n rewrittenChildNode = inheritSingle(childNode);\n rewrittenChildNode.objects = objects;\n }\n }\n }\n else {\n rewrittenChildNode = evaluateDataRepetitionMatrixNode(evalContext, childNode, objectDescriptors, selector, rules, containsWildcard, objectDefns);\n }\n if (rewrittenChildNode) {\n if (!rewrittenNode)\n rewrittenNode = inheritNodeAndChildren(dataViewNode);\n rewrittenNode.children[i] = rewrittenChildNode;\n if (!containsWildcard) {\n // NOTE: once we find a match for a non-wildcard selector, stop looking.\n break;\n }\n }\n }\n return rewrittenNode;\n }\n function inheritNodeAndChildren(node) {\n if (Object.getPrototypeOf(node) !== Object.prototype) {\n return node;\n }\n var inherited = inheritSingle(node);\n inherited.children = inherit(node.children);\n return inherited;\n }\n function evaluateDataRepetitionTable(dataViewTable, selectTransforms, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache) {\n debug.assertValue(dataViewTable, 'dataViewTable');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertAnyValue(rules, 'rules');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\n var evalContext = data.createTableEvalContext(colorAllocatorCache, dataViewTable, selectTransforms);\n var rewrittenRows = evaluateDataRepetitionTableRows(evalContext, dataViewTable.columns, dataViewTable.rows, dataViewTable.identity, dataViewTable.identityFields, objectDescriptors, selector, rules, containsWildcard, objectDefns);\n if (rewrittenRows) {\n var rewrittenTable = inheritSingle(dataViewTable);\n rewrittenTable.rows = rewrittenRows;\n return rewrittenTable;\n }\n }\n function evaluateDataRepetitionTableRows(evalContext, columns, rows, identities, identityFields, objectDescriptors, selector, rules, containsWildcard, objectDefns) {\n debug.assertValue(evalContext, 'evalContext');\n debug.assertValue(columns, 'columns');\n debug.assertValue(rows, 'rows');\n debug.assertAnyValue(identities, 'identities');\n debug.assertAnyValue(identityFields, 'identityFields');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertAnyValue(rules, 'rules');\n debug.assertValue(objectDefns, 'objectDefns');\n if (_.isEmpty(identities) || _.isEmpty(identityFields))\n return;\n if (!selector.metadata ||\n !data.Selector.matchesKeys(selector, [identityFields]))\n return;\n var colIdx = _.findIndex(columns, function (col) { return col.queryName === selector.metadata; });\n if (colIdx < 0)\n return;\n debug.assert(rows.length === identities.length, 'row length mismatch');\n var colLen = columns.length;\n var inheritedRows;\n for (var rowIdx = 0, rowLen = identities.length; rowIdx < rowLen; rowIdx++) {\n var identity = identities[rowIdx];\n if (containsWildcard || data.Selector.matchesData(selector, [identity])) {\n evalContext.setCurrentRowIndex(rowIdx);\n var objects = data.DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\n if (objects) {\n if (!inheritedRows)\n inheritedRows = inheritSingle(rows);\n var inheritedRow = inheritedRows[rowIdx] = inheritSingle(inheritedRows[rowIdx]);\n var objectsForColumns = inheritedRow.objects;\n if (!objectsForColumns)\n inheritedRow.objects = objectsForColumns = new Array(colLen);\n objectsForColumns[colIdx] = objects;\n }\n if (!containsWildcard)\n break;\n }\n }\n return inheritedRows;\n }\n function evaluateMetadataRepetition(dataView, selectTransforms, objectDescriptors, selector, objectDefns, colorAllocatorCache) {\n debug.assertValue(dataView, 'dataView');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(selector, 'selector');\n debug.assertValue(objectDefns, 'objectDefns');\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\n // revisit this, likely when we do lazy evaluation of DataView.\n var columns = dataView.metadata.columns, metadataId = selector.metadata, evalContext = data.createStaticEvalContext(colorAllocatorCache, dataView, selectTransforms);\n for (var i = 0, len = columns.length; i < len; i++) {\n var column = columns[i];\n if (column.queryName === metadataId) {\n var objects = data.DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\n if (objects)\n column.objects = objects;\n }\n }\n }\n /** Attempts to find a column that can possibly match the selector. */\n function findSelectedCategoricalColumn(dataViewCategorical, selector) {\n debug.assertValue(dataViewCategorical.categories[0], 'dataViewCategorical.categories[0]');\n var categoricalColumn = dataViewCategorical.categories[0];\n if (!categoricalColumn.identityFields)\n return;\n if (!data.Selector.matchesKeys(selector, [categoricalColumn.identityFields]))\n return;\n var identities = categoricalColumn.identity, targetColumn = categoricalColumn;\n var selectedMetadataId = selector.metadata;\n if (selectedMetadataId) {\n var valueColumns = dataViewCategorical.values;\n if (valueColumns) {\n for (var i = 0, len = valueColumns.length; i < len; i++) {\n var valueColumn = valueColumns[i];\n if (valueColumn.source.queryName === selectedMetadataId) {\n targetColumn = valueColumn;\n break;\n }\n }\n }\n }\n return {\n column: targetColumn,\n identities: identities,\n };\n }\n function findSelectorForRuleInput(dataView, selectorRoles) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(selectorRoles, 'selectorRoles');\n if (selectorRoles.length !== 1)\n return;\n var dataViewCategorical = dataView.categorical;\n if (!dataViewCategorical)\n return;\n var categories = dataViewCategorical.categories;\n if (!categories || categories.length !== 1)\n return;\n var categoryColumn = categories[0], categoryRoles = categoryColumn.source.roles, categoryIdentityFields = categoryColumn.identityFields;\n if (!categoryRoles || !categoryIdentityFields || !categoryRoles[selectorRoles[0]])\n return;\n return { data: [data.DataViewScopeWildcard.fromExprs(categoryIdentityFields)] };\n }\n function findFirstQueryNameForExpr(selectTransforms, expr) {\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n debug.assertValue(expr, 'expr');\n if (data.SQExpr.isSelectRef(expr))\n return expr.expressionName;\n if (!selectTransforms)\n return;\n for (var i = 0, len = selectTransforms.length; i < len; i++) {\n var select = selectTransforms[i], columnExpr = select.expr;\n if (!columnExpr || !data.SQExpr.equals(expr, select.expr))\n continue;\n return select.queryName;\n }\n }\n /** Attempts to find the value range for the single column with the given identifier/identifierKind. */\n function findRuleInputColumnNumberRange(dataView, identifier, identifierKind) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(identifier, 'identifier');\n debug.assertValue(identifierKind, 'identifierKind');\n var columns = dataView.metadata.columns;\n for (var i = 0, len = columns.length; i < len; i++) {\n var column = columns[i];\n if (identifierKind === 1 /* Role */) {\n var valueColRoles = column.roles;\n if (!valueColRoles || !valueColRoles[identifier])\n continue;\n }\n else {\n debug.assert(identifierKind === 0 /* QueryName */, 'identifierKind === ColumnIdentifierKind.QueryName');\n if (column.queryName !== identifier)\n continue;\n }\n var aggregates = column.aggregates;\n if (!aggregates)\n continue;\n var min = aggregates.min;\n if (min === undefined)\n min = aggregates.minLocal;\n if (min === undefined)\n continue;\n var max = aggregates.max;\n if (max === undefined)\n max = aggregates.maxLocal;\n if (max === undefined)\n continue;\n return { min: min, max: max };\n }\n }\n // TODO: refactor this, setGrouped, and groupValues to a test helper to stop using it in the product\n function createValueColumns(values, valueIdentityFields, source) {\n if (values === void 0) { values = []; }\n var result = values;\n setGrouped(values);\n if (valueIdentityFields)\n result.identityFields = valueIdentityFields;\n if (source)\n result.source = source;\n return result;\n }\n DataViewTransform.createValueColumns = createValueColumns;\n function setGrouped(values, groupedResult) {\n values.grouped = groupedResult\n ? function () { return groupedResult; }\n : function () { return groupValues(values); };\n }\n DataViewTransform.setGrouped = setGrouped;\n /** Group together the values with a common identity. */\n function groupValues(values) {\n debug.assertValue(values, 'values');\n var groups = [], currentGroup;\n for (var i = 0, len = values.length; i < len; i++) {\n var value = values[i];\n if (!currentGroup || currentGroup.identity !== value.identity) {\n currentGroup = {\n values: []\n };\n if (value.identity) {\n currentGroup.identity = value.identity;\n var source = value.source;\n // allow null, which will be formatted as (Blank).\n if (source.groupName !== undefined)\n currentGroup.name = source.groupName;\n else if (source.displayName)\n currentGroup.name = source.displayName;\n }\n groups.push(currentGroup);\n }\n currentGroup.values.push(value);\n }\n return groups;\n }\n function pivotIfNecessary(dataView, dataViewMappings) {\n debug.assertValue(dataView, 'dataView');\n var transformedDataView;\n switch (determineCategoricalTransformation(dataView.categorical, dataViewMappings)) {\n case 1 /* Pivot */:\n transformedDataView = data.DataViewPivotCategorical.apply(dataView);\n break;\n case 2 /* SelfCrossJoin */:\n transformedDataView = data.DataViewSelfCrossJoin.apply(dataView);\n break;\n }\n return transformedDataView || dataView;\n }\n function determineCategoricalTransformation(categorical, dataViewMappings) {\n if (!categorical || _.isEmpty(dataViewMappings))\n return;\n var categories = categorical.categories;\n if (!categories || categories.length !== 1)\n return;\n var values = categorical.values;\n if (_.isEmpty(values))\n return;\n if (values.grouped().some(function (vg) { return !!vg.identity; }))\n return;\n // If we made it here, the DataView has a single category and no valueGrouping.\n var categoryRoles = categories[0].source.roles;\n for (var i = 0, len = dataViewMappings.length; i < len; i++) {\n var roleMappingCategorical = dataViewMappings[i].categorical;\n if (!roleMappingCategorical)\n continue;\n if (!hasRolesGrouped(categoryRoles, roleMappingCategorical.values))\n continue;\n // If we made it here, the DataView's single category has the value grouping role.\n var categoriesMapping = roleMappingCategorical.categories;\n var hasCategoryRole = hasRolesBind(categoryRoles, categoriesMapping) ||\n hasRolesFor(categoryRoles, categoriesMapping);\n if (hasCategoryRole)\n return 2 /* SelfCrossJoin */;\n return 1 /* Pivot */;\n }\n }\n function shouldPivotMatrix(matrix, dataViewMappings) {\n if (!matrix || _.isEmpty(dataViewMappings))\n return;\n var rowLevels = matrix.rows.levels;\n if (rowLevels.length < 1)\n return;\n var rows = matrix.rows.root.children;\n if (!rows || rows.length === 0)\n return;\n var rowRoles = rowLevels[0].sources[0].roles;\n for (var i = 0, len = dataViewMappings.length; i < len; i++) {\n var roleMappingMatrix = dataViewMappings[i].matrix;\n if (!roleMappingMatrix)\n continue;\n if (!hasRolesFor(rowRoles, roleMappingMatrix.rows) &&\n hasRolesFor(rowRoles, roleMappingMatrix.columns)) {\n return true;\n }\n }\n }\n function hasRolesBind(roles, roleMapping) {\n if (roles && roleMapping && roleMapping.bind)\n return roles[roleMapping.bind.to];\n }\n function hasRolesFor(roles, roleMapping) {\n if (roles && roleMapping && roleMapping.for)\n return roles[roleMapping.for.in];\n }\n function hasRolesGrouped(roles, roleMapping) {\n if (roles && roleMapping && roleMapping.group)\n return roles[roleMapping.group.by];\n }\n })(DataViewTransform = data.DataViewTransform || (data.DataViewTransform = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n function createDisplayNameGetter(displayNameKey) {\n return function (resourceProvider) { return resourceProvider.get(displayNameKey); };\n }\n data.createDisplayNameGetter = createDisplayNameGetter;\n function getDisplayName(displayNameGetter, resourceProvider) {\n if (typeof displayNameGetter === 'function')\n return displayNameGetter(resourceProvider);\n if (typeof displayNameGetter === 'string')\n return displayNameGetter;\n }\n data.getDisplayName = getDisplayName;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n /** Enumeration of DateTimeUnits */\n (function (DateTimeUnit) {\n DateTimeUnit[DateTimeUnit[\"Year\"] = 0] = \"Year\";\n DateTimeUnit[DateTimeUnit[\"Month\"] = 1] = \"Month\";\n DateTimeUnit[DateTimeUnit[\"Week\"] = 2] = \"Week\";\n DateTimeUnit[DateTimeUnit[\"Day\"] = 3] = \"Day\";\n DateTimeUnit[DateTimeUnit[\"Hour\"] = 4] = \"Hour\";\n DateTimeUnit[DateTimeUnit[\"Minute\"] = 5] = \"Minute\";\n DateTimeUnit[DateTimeUnit[\"Second\"] = 6] = \"Second\";\n DateTimeUnit[DateTimeUnit[\"Millisecond\"] = 7] = \"Millisecond\";\n })(powerbi.DateTimeUnit || (powerbi.DateTimeUnit = {}));\n var DateTimeUnit = powerbi.DateTimeUnit;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var SQExprBuilder;\n (function (SQExprBuilder) {\n function fieldExpr(fieldExpr) {\n var sqExpr = FieldExprPattern.visit(fieldExpr, FieldExprToSQExprVisitor.instance);\n debug.assertValue(sqExpr, 'Failed to convert FieldExprPattern into SQExpr');\n return sqExpr;\n }\n SQExprBuilder.fieldExpr = fieldExpr;\n function fromColumnAggr(columnAggr) {\n return SQExprBuilder.aggregate(fromColumn(columnAggr), columnAggr.aggregate);\n }\n SQExprBuilder.fromColumnAggr = fromColumnAggr;\n function fromColumn(column) {\n return SQExprBuilder.columnRef(fromEntity(column), column.name);\n }\n SQExprBuilder.fromColumn = fromColumn;\n function fromEntity(entityPattern) {\n return SQExprBuilder.entity(entityPattern.schema, entityPattern.entity, entityPattern.entityVar);\n }\n SQExprBuilder.fromEntity = fromEntity;\n function fromEntityAggr(entityAggr) {\n return SQExprBuilder.aggregate(fromEntity(entityAggr), entityAggr.aggregate);\n }\n SQExprBuilder.fromEntityAggr = fromEntityAggr;\n function fromHierarchyLevelAggr(hierarchyLevelAggr) {\n return SQExprBuilder.aggregate(fromHierarchyLevel(hierarchyLevelAggr), hierarchyLevelAggr.aggregate);\n }\n SQExprBuilder.fromHierarchyLevelAggr = fromHierarchyLevelAggr;\n function fromHierarchyLevel(hierarchyLevelPattern) {\n return SQExprBuilder.hierarchyLevel(fromHierarchy(hierarchyLevelPattern), hierarchyLevelPattern.level);\n }\n SQExprBuilder.fromHierarchyLevel = fromHierarchyLevel;\n function fromHierarchy(hierarchyPattern) {\n return SQExprBuilder.hierarchy(fromEntity(hierarchyPattern), hierarchyPattern.name);\n }\n SQExprBuilder.fromHierarchy = fromHierarchy;\n var FieldExprToSQExprVisitor = (function () {\n function FieldExprToSQExprVisitor() {\n }\n FieldExprToSQExprVisitor.prototype.visitColumn = function (column) {\n return fromColumn(column);\n };\n FieldExprToSQExprVisitor.prototype.visitColumnAggr = function (columnAggr) {\n return fromColumnAggr(columnAggr);\n };\n FieldExprToSQExprVisitor.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariationPattern) {\n return SQExprBuilder.propertyVariationSource(this.visitEntity(columnHierarchyLevelVariationPattern.source), columnHierarchyLevelVariationPattern.source.name, columnHierarchyLevelVariationPattern.level.name);\n };\n FieldExprToSQExprVisitor.prototype.visitEntity = function (entityPattern) {\n return fromEntity(entityPattern);\n };\n FieldExprToSQExprVisitor.prototype.visitEntityAggr = function (entityAggr) {\n return fromEntityAggr(entityAggr);\n };\n FieldExprToSQExprVisitor.prototype.visitHierarchy = function (hierarchyPattern) {\n return fromHierarchy(hierarchyPattern);\n };\n FieldExprToSQExprVisitor.prototype.visitHierarchyLevel = function (level) {\n return fromHierarchyLevel(level);\n };\n FieldExprToSQExprVisitor.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return fromHierarchyLevelAggr(hierarchyLevelAggr);\n };\n FieldExprToSQExprVisitor.prototype.visitMeasure = function (measure) {\n return SQExprBuilder.measureRef(this.visitEntity(measure), measure.name);\n };\n FieldExprToSQExprVisitor.prototype.visitPercentile = function (percentile) {\n var arg = SQExprBuilder.fieldExpr(percentile.arg);\n return SQExprBuilder.percentile(arg, percentile.k, percentile.exclusive);\n };\n FieldExprToSQExprVisitor.prototype.visitPercentOfGrandTotal = function (percentOfGrandTotal) {\n var baseSQExpr = SQExprBuilder.fieldExpr(percentOfGrandTotal.baseExpr);\n return SQExprBuilder.arithmetic(baseSQExpr, SQExprBuilder.scopedEval(baseSQExpr, []), 3 /* Divide */);\n };\n FieldExprToSQExprVisitor.prototype.visitSelectRef = function (selectRef) {\n return SQExprBuilder.selectRef(selectRef.expressionName);\n };\n FieldExprToSQExprVisitor.instance = new FieldExprToSQExprVisitor();\n return FieldExprToSQExprVisitor;\n }());\n })(SQExprBuilder = data.SQExprBuilder || (data.SQExprBuilder = {}));\n var SQExprConverter;\n (function (SQExprConverter) {\n function asFieldPattern(sqExpr) {\n return sqExpr.accept(FieldExprPatternBuilder.instance);\n }\n SQExprConverter.asFieldPattern = asFieldPattern;\n })(SQExprConverter = data.SQExprConverter || (data.SQExprConverter = {}));\n var FieldExprPatternBuilder = (function (_super) {\n __extends(FieldExprPatternBuilder, _super);\n function FieldExprPatternBuilder() {\n _super.apply(this, arguments);\n }\n FieldExprPatternBuilder.prototype.visitColumnRef = function (expr) {\n var sourceRef = expr.source.accept(SourceExprPatternBuilder.instance);\n if (!sourceRef)\n return;\n if (sourceRef.entity) {\n var columnRef = sourceRef.entity;\n columnRef.name = expr.ref;\n return { column: columnRef };\n }\n };\n FieldExprPatternBuilder.prototype.visitMeasureRef = function (expr) {\n var sourceRef = expr.source.accept(SourceExprPatternBuilder.instance);\n if (!sourceRef)\n return;\n if (sourceRef.entity) {\n var measureRef = sourceRef.entity;\n measureRef.name = expr.ref;\n return { measure: measureRef };\n }\n };\n FieldExprPatternBuilder.prototype.visitEntity = function (expr) {\n var entityRef = {\n schema: expr.schema,\n entity: expr.entity\n };\n if (expr.variable)\n entityRef.entityVar = expr.variable;\n return { entity: entityRef };\n };\n FieldExprPatternBuilder.prototype.visitAggr = function (expr) {\n var fieldPattern = expr.arg.accept(this);\n if (fieldPattern && fieldPattern.column) {\n var argAggr = fieldPattern.column;\n argAggr.aggregate = expr.func;\n return { columnAggr: argAggr };\n }\n else if (fieldPattern && fieldPattern.columnAggr) {\n var argAggr = fieldPattern.columnAggr;\n argAggr.aggregate = expr.func;\n return { columnAggr: argAggr };\n }\n else if (fieldPattern && fieldPattern.hierarchyLevel) {\n var argAggr = fieldPattern.hierarchyLevel;\n argAggr.aggregate = expr.func;\n return { hierarchyLevelAggr: argAggr };\n }\n var sourcePattern = expr.arg.accept(SourceExprPatternBuilder.instance);\n if (sourcePattern && sourcePattern.entity) {\n var argAggr = sourcePattern.entity;\n argAggr.aggregate = expr.func;\n return { entityAggr: argAggr };\n }\n };\n FieldExprPatternBuilder.prototype.visitPercentile = function (expr) {\n return {\n percentile: {\n arg: expr.arg.accept(this),\n k: expr.k,\n exclusive: expr.exclusive,\n }\n };\n };\n FieldExprPatternBuilder.prototype.visitHierarchy = function (expr) {\n var sourcePattern = expr.arg.accept(SourceExprPatternBuilder.instance);\n if (sourcePattern && sourcePattern.entity) {\n var hierarchyRef = (sourcePattern.entity);\n hierarchyRef.name = expr.hierarchy;\n return { hierarchy: hierarchyRef };\n }\n };\n FieldExprPatternBuilder.prototype.visitHierarchyLevel = function (expr) {\n var hierarchySourceExprPattern = expr.arg.accept(HierarchyExprPatternBuiler.instance);\n if (!hierarchySourceExprPattern)\n return;\n var hierarchyLevel;\n if (hierarchySourceExprPattern.hierarchy) {\n hierarchyLevel = {\n entity: hierarchySourceExprPattern.hierarchy.entity,\n schema: hierarchySourceExprPattern.hierarchy.schema,\n name: hierarchySourceExprPattern.hierarchy.name,\n level: expr.level,\n };\n }\n if (hierarchySourceExprPattern.variation) {\n return {\n columnHierarchyLevelVariation: {\n source: {\n entity: hierarchySourceExprPattern.variation.column.entity,\n schema: hierarchySourceExprPattern.variation.column.schema,\n name: hierarchySourceExprPattern.variation.column.name,\n },\n level: hierarchyLevel,\n variationName: hierarchySourceExprPattern.variation.variationName,\n }\n };\n }\n return { hierarchyLevel: hierarchyLevel };\n };\n FieldExprPatternBuilder.prototype.visitArithmetic = function (expr) {\n var percentOfGrandTotalPattern = {\n percentOfGrandTotal: {\n baseExpr: expr.left.accept(this)\n }\n };\n if (data.SQExpr.equals(expr, SQExprBuilder.fieldExpr(percentOfGrandTotalPattern))) {\n return percentOfGrandTotalPattern;\n }\n };\n FieldExprPatternBuilder.prototype.visitSelectRef = function (expr) {\n return {\n selectRef: {\n expressionName: expr.expressionName,\n }\n };\n };\n FieldExprPatternBuilder.instance = new FieldExprPatternBuilder();\n return FieldExprPatternBuilder;\n }(data.DefaultSQExprVisitor));\n var SourceExprPatternBuilder = (function (_super) {\n __extends(SourceExprPatternBuilder, _super);\n function SourceExprPatternBuilder() {\n _super.apply(this, arguments);\n }\n SourceExprPatternBuilder.prototype.visitEntity = function (expr) {\n var entityRef = {\n schema: expr.schema,\n entity: expr.entity\n };\n if (expr.variable)\n entityRef.entityVar = expr.variable;\n return { entity: entityRef };\n };\n SourceExprPatternBuilder.prototype.visitPropertyVariationSource = function (expr) {\n var entityExpr = expr.arg;\n if (entityExpr instanceof data.SQEntityExpr) {\n var propertyVariationSource = {\n schema: entityExpr.schema,\n entity: entityExpr.entity,\n name: expr.property,\n };\n if (entityExpr.variable)\n propertyVariationSource.entityVar = entityExpr.variable;\n return {\n variation: {\n column: propertyVariationSource,\n variationName: expr.name,\n }\n };\n }\n };\n SourceExprPatternBuilder.instance = new SourceExprPatternBuilder();\n return SourceExprPatternBuilder;\n }(data.DefaultSQExprVisitor));\n var HierarchyExprPatternBuiler = (function (_super) {\n __extends(HierarchyExprPatternBuiler, _super);\n function HierarchyExprPatternBuiler() {\n _super.apply(this, arguments);\n }\n HierarchyExprPatternBuiler.prototype.visitHierarchy = function (expr) {\n var exprPattern = expr.arg.accept(SourceExprPatternBuilder.instance);\n var hierarchyRef;\n var variationRef;\n if (exprPattern.variation) {\n hierarchyRef = {\n name: expr.hierarchy,\n schema: exprPattern.variation.column.schema,\n entity: exprPattern.variation.column.entity,\n };\n variationRef = exprPattern.variation;\n }\n else\n hierarchyRef = {\n name: expr.hierarchy,\n schema: exprPattern.entity.schema,\n entity: exprPattern.entity.entity,\n };\n return {\n hierarchy: hierarchyRef,\n variation: variationRef\n };\n };\n HierarchyExprPatternBuiler.instance = new HierarchyExprPatternBuiler();\n return HierarchyExprPatternBuiler;\n }(data.DefaultSQExprVisitor));\n var FieldExprPattern;\n (function (FieldExprPattern) {\n function visit(expr, visitor) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(visitor, 'visitor');\n var fieldExprPattern = expr instanceof data.SQExpr ? SQExprConverter.asFieldPattern(expr) : expr;\n debug.assertValue(fieldExprPattern, 'expected sqExpr to conform to a fieldExprPattern');\n if (fieldExprPattern.column)\n return visitColumn(fieldExprPattern.column, visitor);\n if (fieldExprPattern.columnAggr)\n return visitColumnAggr(fieldExprPattern.columnAggr, visitor);\n if (fieldExprPattern.columnHierarchyLevelVariation)\n return visitColumnHierarchyLevelVariation(fieldExprPattern.columnHierarchyLevelVariation, visitor);\n if (fieldExprPattern.entity)\n return visitEntity(fieldExprPattern.entity, visitor);\n if (fieldExprPattern.entityAggr)\n return visitEntityAggr(fieldExprPattern.entityAggr, visitor);\n if (fieldExprPattern.hierarchy)\n return visitHierarchy(fieldExprPattern.hierarchy, visitor);\n if (fieldExprPattern.hierarchyLevel)\n return visitHierarchyLevel(fieldExprPattern.hierarchyLevel, visitor);\n if (fieldExprPattern.hierarchyLevelAggr)\n return visitHierarchyLevelAggr(fieldExprPattern.hierarchyLevelAggr, visitor);\n if (fieldExprPattern.measure)\n return visitMeasure(fieldExprPattern.measure, visitor);\n if (fieldExprPattern.percentile)\n return visitPercentile(fieldExprPattern.percentile, visitor);\n if (fieldExprPattern.percentOfGrandTotal)\n return visitPercentOfGrandTotal(fieldExprPattern.percentOfGrandTotal, visitor);\n if (fieldExprPattern.selectRef)\n return visitSelectRef(fieldExprPattern.selectRef, visitor);\n debug.assertFail('failed to visit a fieldExprPattern.');\n return;\n }\n FieldExprPattern.visit = visit;\n function visitColumn(column, visitor) {\n debug.assertValue(column, 'column');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitColumn(column);\n }\n function visitColumnAggr(columnAggr, visitor) {\n debug.assertValue(columnAggr, 'columnAggr');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitColumnAggr(columnAggr);\n }\n function visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation, visitor) {\n debug.assertValue(columnHierarchyLevelVariation, 'columnHierarchyLevelVariation');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation);\n }\n function visitEntity(entity, visitor) {\n debug.assertValue(entity, 'entity');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitEntity(entity);\n }\n function visitEntityAggr(entityAggr, visitor) {\n debug.assertValue(entityAggr, 'entityAggr');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitEntityAggr(entityAggr);\n }\n function visitHierarchy(hierarchy, visitor) {\n debug.assertValue(hierarchy, 'hierarchy');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitHierarchy(hierarchy);\n }\n function visitHierarchyLevel(hierarchyLevel, visitor) {\n debug.assertValue(hierarchyLevel, 'hierarchyLevel');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitHierarchyLevel(hierarchyLevel);\n }\n function visitHierarchyLevelAggr(hierarchyLevelAggr, visitor) {\n debug.assertValue(hierarchyLevelAggr, 'hierarchyLevelAggr');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitHierarchyLevelAggr(hierarchyLevelAggr);\n }\n function visitMeasure(measure, visitor) {\n debug.assertValue(measure, 'measure');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitMeasure(measure);\n }\n function visitSelectRef(selectRef, visitor) {\n debug.assertValue(selectRef, 'selectRef');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitSelectRef(selectRef);\n }\n function visitPercentile(percentile, visitor) {\n debug.assertValue(percentile, 'percentile');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitPercentile(percentile);\n }\n function visitPercentOfGrandTotal(percentOfGrandTotal, visitor) {\n debug.assertValue(percentOfGrandTotal, 'percentOfGrandTotal');\n debug.assertValue(visitor, 'visitor');\n return visitor.visitPercentOfGrandTotal(percentOfGrandTotal);\n }\n function toColumnRefSQExpr(columnPattern) {\n return SQExprBuilder.columnRef(SQExprBuilder.entity(columnPattern.schema, columnPattern.entity, columnPattern.entityVar), columnPattern.name);\n }\n FieldExprPattern.toColumnRefSQExpr = toColumnRefSQExpr;\n function getAggregate(fieldExpr) {\n debug.assertValue(fieldExpr, 'fieldExpr');\n return visit(fieldExpr, FieldExprPatternAggregateVisitor.instance);\n }\n FieldExprPattern.getAggregate = getAggregate;\n function isAggregation(fieldExpr) {\n debug.assertValue(fieldExpr, 'fieldExpr');\n return visit(fieldExpr, FieldExprPatternIsAggregationVisitor.instance);\n }\n FieldExprPattern.isAggregation = isAggregation;\n function hasFieldExprName(fieldExpr) {\n return (fieldExpr.column ||\n fieldExpr.columnAggr ||\n fieldExpr.measure) !== undefined;\n }\n FieldExprPattern.hasFieldExprName = hasFieldExprName;\n function getPropertyName(fieldExpr) {\n return FieldExprPattern.visit(fieldExpr, FieldExprPropertyNameVisitor.instance);\n }\n FieldExprPattern.getPropertyName = getPropertyName;\n function getHierarchyName(fieldExpr) {\n var hierarchy = fieldExpr.hierarchy;\n if (hierarchy)\n return hierarchy.name;\n }\n FieldExprPattern.getHierarchyName = getHierarchyName;\n function getColumnRef(fieldExpr) {\n if (fieldExpr.columnHierarchyLevelVariation)\n return fieldExpr.columnHierarchyLevelVariation.source;\n return fieldExpr.column || fieldExpr.measure || fieldExpr.columnAggr;\n }\n FieldExprPattern.getColumnRef = getColumnRef;\n function getFieldExprName(fieldExpr) {\n var name = getPropertyName(fieldExpr);\n if (name)\n return name;\n // In case it is an entity\n return toFieldExprEntityPattern(fieldExpr).entity;\n }\n FieldExprPattern.getFieldExprName = getFieldExprName;\n function getSchema(fieldExpr) {\n debug.assertValue(fieldExpr, 'fieldExpr');\n var item = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n debug.assertAnyValue(item, 'expected fieldExpr to be an entity item');\n return item.schema;\n }\n FieldExprPattern.getSchema = getSchema;\n function toFieldExprEntityPattern(fieldExpr) {\n return FieldExprPattern.visit(fieldExpr, FieldExprToEntityExprPatternBuilder.instance);\n }\n FieldExprPattern.toFieldExprEntityPattern = toFieldExprEntityPattern;\n function toFieldExprEntityItemPattern(fieldExpr) {\n return FieldExprPattern.visit(fieldExpr, FieldExprToEntityExprPatternBuilder.instance);\n }\n FieldExprPattern.toFieldExprEntityItemPattern = toFieldExprEntityItemPattern;\n var FieldExprPatternAggregateVisitor = (function () {\n function FieldExprPatternAggregateVisitor() {\n }\n FieldExprPatternAggregateVisitor.prototype.visitColumn = function (column) {\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitColumnAggr = function (columnAggr) {\n return columnAggr.aggregate;\n };\n FieldExprPatternAggregateVisitor.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariation) {\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitEntity = function (entity) {\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitEntityAggr = function (entityAggr) {\n return entityAggr.aggregate;\n };\n FieldExprPatternAggregateVisitor.prototype.visitHierarchy = function (hierarchy) {\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitHierarchyLevel = function (hierarchyLevel) {\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return hierarchyLevelAggr.aggregate;\n };\n FieldExprPatternAggregateVisitor.prototype.visitMeasure = function (measure) {\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitSelectRef = function (selectRef) {\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitPercentile = function (percentile) {\n // NOTE: Percentile behaves like an aggregate (i.e., can be performed over numeric columns like a SUM), but\n // this function can't really convey that because percentile (intentionally) isn't in QueryAggregateFunction enum.\n // This should be revisited when we have UI support for the Percentile aggregate.\n return;\n };\n FieldExprPatternAggregateVisitor.prototype.visitPercentOfGrandTotal = function (percentOfGrandTotal) {\n return data.SQExprInfo.getAggregate(SQExprBuilder.fieldExpr(percentOfGrandTotal.baseExpr));\n };\n FieldExprPatternAggregateVisitor.instance = new FieldExprPatternAggregateVisitor();\n return FieldExprPatternAggregateVisitor;\n }());\n var FieldExprPatternIsAggregationVisitor = (function () {\n function FieldExprPatternIsAggregationVisitor() {\n }\n FieldExprPatternIsAggregationVisitor.prototype.visitColumn = function (column) {\n return false;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitColumnAggr = function (columnAggr) {\n return true;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariation) {\n return false;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitEntity = function (entity) {\n return false;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitEntityAggr = function (entityAggr) {\n return true;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitHierarchy = function (hierarchy) {\n return false;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitHierarchyLevel = function (hierarchyLevel) {\n return false;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return true;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitMeasure = function (measure) {\n return true;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitSelectRef = function (selectRef) {\n return false;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitPercentile = function (percentile) {\n return true;\n };\n FieldExprPatternIsAggregationVisitor.prototype.visitPercentOfGrandTotal = function (percentOfGrandTotal) {\n return true;\n };\n FieldExprPatternIsAggregationVisitor.instance = new FieldExprPatternIsAggregationVisitor();\n return FieldExprPatternIsAggregationVisitor;\n }());\n var FieldExprToEntityExprPatternBuilder = (function () {\n function FieldExprToEntityExprPatternBuilder() {\n }\n FieldExprToEntityExprPatternBuilder.prototype.visitColumn = function (column) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(column);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitColumnAggr = function (columnAggr) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(columnAggr);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariation) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(columnHierarchyLevelVariation.source);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitEntity = function (entity) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(entity);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitEntityAggr = function (entityAggr) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(entityAggr);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitHierarchy = function (hierarchy) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(hierarchy);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitHierarchyLevel = function (hierarchyLevel) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(hierarchyLevel);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(hierarchyLevelAggr);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitMeasure = function (measure) {\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(measure);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitSelectRef = function (selectRef) {\n return;\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitPercentile = function (percentile) {\n return FieldExprPattern.visit(percentile.arg, this);\n };\n FieldExprToEntityExprPatternBuilder.prototype.visitPercentOfGrandTotal = function (percentOfGrandTotal) {\n return FieldExprPattern.visit(percentOfGrandTotal.baseExpr, this);\n };\n FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern = function (exprPattern) {\n debug.assertValue(exprPattern, 'exprPattern');\n var pattern = { schema: exprPattern.schema, entity: exprPattern.entity };\n if (exprPattern.entityVar) {\n pattern.entityVar = exprPattern.entityVar;\n }\n return pattern;\n };\n FieldExprToEntityExprPatternBuilder.instance = new FieldExprToEntityExprPatternBuilder();\n return FieldExprToEntityExprPatternBuilder;\n }());\n var FieldExprPropertyNameVisitor = (function () {\n function FieldExprPropertyNameVisitor() {\n }\n FieldExprPropertyNameVisitor.prototype.visitColumn = function (column) {\n return column.name;\n };\n FieldExprPropertyNameVisitor.prototype.visitColumnAggr = function (columnAggr) {\n return columnAggr.name;\n };\n FieldExprPropertyNameVisitor.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariation) {\n return;\n };\n FieldExprPropertyNameVisitor.prototype.visitEntity = function (entity) {\n return;\n };\n FieldExprPropertyNameVisitor.prototype.visitEntityAggr = function (entityAggr) {\n return;\n };\n FieldExprPropertyNameVisitor.prototype.visitHierarchy = function (hierarchy) {\n return;\n };\n FieldExprPropertyNameVisitor.prototype.visitHierarchyLevel = function (hierarchyLevel) {\n return;\n };\n FieldExprPropertyNameVisitor.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return;\n };\n FieldExprPropertyNameVisitor.prototype.visitMeasure = function (measure) {\n return measure.name;\n };\n FieldExprPropertyNameVisitor.prototype.visitSelectRef = function (selectRef) {\n return;\n };\n FieldExprPropertyNameVisitor.prototype.visitPercentile = function (percentile) {\n return FieldExprPattern.visit(percentile.arg, this);\n };\n FieldExprPropertyNameVisitor.prototype.visitPercentOfGrandTotal = function (percentOfGrandTotal) {\n return FieldExprPattern.visit(percentOfGrandTotal.baseExpr, this);\n };\n FieldExprPropertyNameVisitor.instance = new FieldExprPropertyNameVisitor();\n return FieldExprPropertyNameVisitor;\n }());\n })(FieldExprPattern = data.FieldExprPattern || (data.FieldExprPattern = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var DataViewAnalysis;\n (function (DataViewAnalysis) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n var DataViewObjectDefinitions = powerbi.data.DataViewObjectDefinitions;\n (function (DataViewMappingMatchErrorCode) {\n DataViewMappingMatchErrorCode[DataViewMappingMatchErrorCode[\"conditionRangeTooLarge\"] = 0] = \"conditionRangeTooLarge\";\n DataViewMappingMatchErrorCode[DataViewMappingMatchErrorCode[\"conditionRangeTooSmall\"] = 1] = \"conditionRangeTooSmall\";\n DataViewMappingMatchErrorCode[DataViewMappingMatchErrorCode[\"conditionKindExpectedMeasure\"] = 2] = \"conditionKindExpectedMeasure\";\n DataViewMappingMatchErrorCode[DataViewMappingMatchErrorCode[\"conditionKindExpectedGrouping\"] = 3] = \"conditionKindExpectedGrouping\";\n DataViewMappingMatchErrorCode[DataViewMappingMatchErrorCode[\"conditionKindExpectedGroupingOrMeasure\"] = 4] = \"conditionKindExpectedGroupingOrMeasure\";\n })(DataViewAnalysis.DataViewMappingMatchErrorCode || (DataViewAnalysis.DataViewMappingMatchErrorCode = {}));\n var DataViewMappingMatchErrorCode = DataViewAnalysis.DataViewMappingMatchErrorCode;\n /** Reshapes the data view to match the provided schema if possible. If not, returns null */\n function validateAndReshape(dataView, dataViewMappings) {\n if (!dataViewMappings || dataViewMappings.length === 0)\n return { dataView: dataView, isValid: true };\n if (dataView) {\n for (var _i = 0, dataViewMappings_3 = dataViewMappings; _i < dataViewMappings_3.length; _i++) {\n var dataViewMapping = dataViewMappings_3[_i];\n // Keep the original when possible.\n if (supports(dataView, dataViewMapping))\n return { dataView: dataView, isValid: true };\n if (dataViewMapping.categorical && dataView.categorical)\n return reshapeCategorical(dataView, dataViewMapping);\n if (dataViewMapping.tree && dataView.tree)\n return reshapeTree(dataView, dataViewMapping.tree);\n if (dataViewMapping.single && dataView.single)\n return reshapeSingle(dataView, dataViewMapping.single);\n if (dataViewMapping.table && dataView.table)\n return reshapeTable(dataView, dataViewMapping.table);\n }\n }\n else if (powerbi.ScriptResultUtil.findScriptResult(dataViewMappings)) {\n // Currently, PBI Service treats R Script Visuals as static images.\n // This causes validation to fail, since in PBI service no DataView is generated, but there are DataViewMappings,\n // to support the PBI Desktop scenario.\n // This code will be removed once PBI Service fully supports R Script Visuals.\n // VSTS: 6217994 - [R Viz] Remove temporary DataViewAnalysis validation workaround of static R Script Visual mappings\n return { dataView: dataView, isValid: true };\n }\n return { isValid: false };\n }\n DataViewAnalysis.validateAndReshape = validateAndReshape;\n function reshapeCategorical(dataView, dataViewMapping) {\n debug.assertValue(dataViewMapping, 'dataViewMapping');\n //The functionality that used to compare categorical.values.length to schema.values doesn't apply any more, we don't want to use the same logic for re-shaping.\n var categoryRoleMapping = dataViewMapping.categorical;\n var categorical = dataView.categorical;\n if (!categorical)\n return { isValid: false };\n var rowCount;\n if (categoryRoleMapping.rowCount) {\n rowCount = categoryRoleMapping.rowCount.supported;\n if (rowCount && rowCount.max) {\n var updated = void 0;\n var categories = categorical.categories;\n var maxRowCount = rowCount.max;\n var originalLength = undefined;\n if (categories) {\n for (var i = 0, len = categories.length; i < len; i++) {\n var category = categories[i];\n originalLength = category.values.length;\n if (maxRowCount !== undefined && originalLength > maxRowCount) {\n // Row count too large: Trim it to fit.\n var updatedCategories = ArrayExtensions.range(category.values, 0, maxRowCount - 1);\n updated = updated || { categories: [] };\n updated.categories.push({\n source: category.source,\n values: updatedCategories\n });\n }\n }\n }\n if (categorical.values && categorical.values.length > 0 && maxRowCount) {\n if (!originalLength)\n originalLength = categorical.values[0].values.length;\n if (maxRowCount !== undefined && originalLength > maxRowCount) {\n updated = updated || {};\n updated.values = powerbi.data.DataViewTransform.createValueColumns();\n for (var i = 0, len = categorical.values.length; i < len; i++) {\n var column = categorical.values[i], updatedColumn = {\n source: column.source,\n values: ArrayExtensions.range(column.values, 0, maxRowCount - 1)\n };\n if (column.min !== undefined)\n updatedColumn.min = column.min;\n if (column.max !== undefined)\n updatedColumn.max = column.max;\n if (column.subtotal !== undefined)\n updatedColumn.subtotal = column.subtotal;\n updated.values.push(updatedColumn);\n }\n }\n }\n if (updated) {\n dataView = {\n metadata: dataView.metadata,\n categorical: updated,\n };\n }\n }\n }\n if (supportsCategorical(dataView, dataViewMapping))\n return { dataView: dataView, isValid: true };\n return null;\n }\n function reshapeSingle(dataView, singleRoleMapping) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(singleRoleMapping, 'singleRoleMapping');\n if (dataView.single)\n return { dataView: dataView, isValid: true };\n return { isValid: false };\n }\n function reshapeTree(dataView, treeRoleMapping) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(treeRoleMapping, 'treeRoleMapping');\n // TODO: Need to implement the reshaping of Tree\n var metadata = dataView.metadata;\n if (validateRange(countGroups(metadata.columns), treeRoleMapping.depth) == null /*&& conforms(countMeasures(metadata.columns), treeRoleMapping.aggregates)*/)\n return { dataView: dataView, isValid: true };\n return { isValid: false };\n }\n function reshapeTable(dataView, tableRoleMapping) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(tableRoleMapping, 'tableRoleMapping');\n if (dataView.table)\n return { dataView: dataView, isValid: true };\n return { isValid: false };\n }\n function countGroups(columns) {\n var count = 0;\n for (var i = 0, len = columns.length; i < len; i++) {\n if (!columns[i].isMeasure)\n ++count;\n }\n return count;\n }\n DataViewAnalysis.countGroups = countGroups;\n function countMeasures(columns) {\n var count = 0;\n for (var i = 0, len = columns.length; i < len; i++) {\n if (columns[i].isMeasure)\n ++count;\n }\n return count;\n }\n DataViewAnalysis.countMeasures = countMeasures;\n /** Indicates whether the dataView conforms to the specified schema. */\n function supports(dataView, roleMapping, usePreferredDataViewSchema) {\n if (!roleMapping || !dataView)\n return false;\n if (roleMapping.scriptResult && !supportsScriptResult(dataView.scriptResult, roleMapping.scriptResult))\n return false;\n if (roleMapping.categorical && !supportsCategorical(dataView, roleMapping.categorical, usePreferredDataViewSchema))\n return false;\n if (roleMapping.tree && !supportsTree(dataView, roleMapping.tree))\n return false;\n if (roleMapping.single && !supportsSingle(dataView.single, roleMapping.single))\n return false;\n if (roleMapping.table && !supportsTable(dataView.table, roleMapping.table, usePreferredDataViewSchema))\n return false;\n return true;\n }\n DataViewAnalysis.supports = supports;\n function supportsCategorical(dataView, categoryRoleMapping, usePreferredDataViewSchema) {\n debug.assertValue(categoryRoleMapping, 'categoryRoleMapping');\n var dataViewCategorical = dataView.categorical;\n if (!dataViewCategorical)\n return false;\n // TODO: Disabling this implementation isn't right.\n //if (!conforms(countMeasures(dataView.metadata.columns), categoryRoleMapping.values.roles.length))\n // return false;\n if (categoryRoleMapping.rowCount) {\n var rowCount = categoryRoleMapping.rowCount.supported;\n if (usePreferredDataViewSchema && categoryRoleMapping.rowCount.preferred)\n rowCount = categoryRoleMapping.rowCount.preferred;\n if (rowCount) {\n var len = 0;\n if (dataViewCategorical.values && dataViewCategorical.values.length)\n len = dataViewCategorical.values[0].values.length;\n else if (dataViewCategorical.categories && dataViewCategorical.categories.length)\n len = dataViewCategorical.categories[0].values.length;\n if (validateRange(len, rowCount) != null)\n return false;\n }\n }\n return true;\n }\n function supportsSingle(dataViewSingle, singleRoleMapping) {\n debug.assertValue(singleRoleMapping, 'singleRoleMapping');\n if (!dataViewSingle)\n return false;\n return true;\n }\n function supportsTree(dataView, treeRoleMapping) {\n debug.assertValue(treeRoleMapping, 'treeRoleMapping');\n var metadata = dataView.metadata;\n return validateRange(countGroups(metadata.columns), treeRoleMapping.depth) == null;\n }\n function supportsTable(dataViewTable, tableRoleMapping, usePreferredDataViewSchema) {\n debug.assertValue(tableRoleMapping, 'tableRoleMapping');\n if (!dataViewTable)\n return false;\n if (tableRoleMapping.rowCount) {\n var rowCount = tableRoleMapping.rowCount.supported;\n if (usePreferredDataViewSchema && tableRoleMapping.rowCount.preferred)\n rowCount = tableRoleMapping.rowCount.preferred;\n if (rowCount) {\n var len = 0;\n if (dataViewTable.rows && dataViewTable.rows.length)\n len = dataViewTable.rows.length;\n if (validateRange(len, rowCount) != null)\n return false;\n }\n }\n return true;\n }\n function supportsScriptResult(dataView, scriptResultRoleMapping) {\n debug.assertValue(scriptResultRoleMapping, 'scriptResultRoleMapping');\n if (!dataView)\n return false;\n if (!dataView.imageBase64)\n return false;\n return true;\n }\n /**\n * Determines whether the value conforms to the range in the role condition, returning undefined\n * if so or an appropriate error code if not.\n */\n function validateRange(value, roleCondition, ignoreMin) {\n debug.assertValue(value, 'value');\n if (!roleCondition)\n return;\n if (!ignoreMin && roleCondition.min !== undefined && roleCondition.min > value)\n return DataViewMappingMatchErrorCode.conditionRangeTooSmall;\n if (roleCondition.max !== undefined && roleCondition.max < value)\n return DataViewMappingMatchErrorCode.conditionRangeTooLarge;\n }\n DataViewAnalysis.validateRange = validateRange;\n /**\n * Determines whether the value conforms to the kind in the role condition, returning undefined\n * if so or an appropriate error code if not.\n */\n function validateKind(roleCondition, roleName, projections, roleKindByQueryRef) {\n if (!roleCondition || roleCondition.kind === undefined) {\n return;\n }\n var expectedKind = roleCondition.kind;\n var roleCollection = projections[roleName];\n if (roleCollection) {\n var roleProjections = roleCollection.all();\n for (var _i = 0, roleProjections_1 = roleProjections; _i < roleProjections_1.length; _i++) {\n var roleProjection = roleProjections_1[_i];\n if (roleKindByQueryRef[roleProjection.queryRef] !== expectedKind) {\n switch (expectedKind) {\n case powerbi.VisualDataRoleKind.Measure:\n return DataViewMappingMatchErrorCode.conditionKindExpectedMeasure;\n case powerbi.VisualDataRoleKind.Grouping:\n return DataViewMappingMatchErrorCode.conditionKindExpectedGrouping;\n case powerbi.VisualDataRoleKind.GroupingOrMeasure:\n return DataViewMappingMatchErrorCode.conditionKindExpectedGroupingOrMeasure;\n }\n }\n }\n }\n }\n /** Determines the appropriate DataViewMappings for the projections. */\n function chooseDataViewMappings(projections, mappings, roleKindByQueryRef, objectDescriptors, objectDefinitions) {\n debug.assertValue(projections, 'projections');\n debug.assertAnyValue(mappings, 'mappings');\n var supportedMappings = [];\n var errors = [];\n if (!_.isEmpty(mappings)) {\n for (var mappingIndex = 0, mappingCount = mappings.length; mappingIndex < mappingCount; mappingIndex++) {\n var mapping = mappings[mappingIndex], mappingConditions = mapping.conditions, requiredProperties = mapping.requiredProperties;\n var allPropertiesValid = areAllPropertiesValid(requiredProperties, objectDescriptors, objectDefinitions);\n var conditionsMet = [];\n if (!_.isEmpty(mappingConditions)) {\n for (var conditionIndex = 0, conditionCount = mappingConditions.length; conditionIndex < conditionCount; conditionIndex++) {\n var condition = mappingConditions[conditionIndex];\n var currentConditionErrors = checkForConditionErrors(projections, condition, roleKindByQueryRef);\n if (!_.isEmpty(currentConditionErrors)) {\n for (var _i = 0, currentConditionErrors_1 = currentConditionErrors; _i < currentConditionErrors_1.length; _i++) {\n var error = currentConditionErrors_1[_i];\n error.mappingIndex = mappingIndex;\n error.conditionIndex = conditionIndex;\n errors.push(error);\n }\n }\n else\n conditionsMet.push(condition);\n }\n }\n else {\n conditionsMet.push({});\n }\n if (!_.isEmpty(conditionsMet) && allPropertiesValid) {\n var supportedMapping = _.cloneDeep(mapping);\n var updatedConditions = _.filter(conditionsMet, function (condition) { return Object.keys(condition).length > 0; });\n if (!_.isEmpty(updatedConditions))\n supportedMapping.conditions = updatedConditions;\n supportedMappings.push(supportedMapping);\n }\n }\n }\n return {\n supportedMappings: ArrayExtensions.emptyToNull(supportedMappings),\n mappingErrors: ArrayExtensions.emptyToNull(errors),\n };\n }\n DataViewAnalysis.chooseDataViewMappings = chooseDataViewMappings;\n function checkForConditionErrors(projections, condition, roleKindByQueryRef) {\n debug.assertValue(projections, 'projections');\n debug.assertValue(condition, 'condition');\n var conditionRoles = Object.keys(condition);\n var errors = [];\n for (var i = 0, len = conditionRoles.length; i < len; i++) {\n var roleName = conditionRoles[i], isDrillable = projections[roleName] && !_.isEmpty(projections[roleName].activeProjectionRefs), roleCondition = condition[roleName];\n var roleCount = getPropertyCount(roleName, projections, isDrillable);\n var rangeError = validateRange(roleCount, roleCondition);\n if (rangeError != null) {\n errors.push({\n code: rangeError,\n roleName: roleName,\n });\n }\n var kindError = validateKind(roleCondition, roleName, projections, roleKindByQueryRef);\n if (kindError != null) {\n errors.push({\n code: kindError,\n roleName: roleName,\n });\n }\n }\n return errors;\n }\n function areAllPropertiesValid(requiredProperties, objectDescriptors, objectDefinitions) {\n if (_.isEmpty(requiredProperties))\n return true;\n if (!objectDescriptors || !objectDefinitions)\n return false;\n var staticEvalContext = powerbi.data.createStaticEvalContext();\n return _.every(requiredProperties, function (requiredProperty) {\n var objectDescriptorValue = null;\n var objectDescriptorProperty = objectDescriptors[requiredProperty.objectName];\n if (objectDescriptorProperty)\n objectDescriptorValue = objectDescriptorProperty.properties[requiredProperty.propertyName];\n var objectDefinitionValue = DataViewObjectDefinitions.getValue(objectDefinitions, requiredProperty, null);\n if (!objectDescriptorValue || !objectDefinitionValue)\n return false;\n return powerbi.data.DataViewObjectEvaluator.evaluateProperty(staticEvalContext, objectDescriptorValue, objectDefinitionValue);\n });\n }\n function getPropertyCount(roleName, projections, useActiveIfAvailable) {\n debug.assertValue(roleName, 'roleName');\n debug.assertValue(projections, 'projections');\n var projectionsForRole = projections[roleName];\n if (projectionsForRole) {\n if (useActiveIfAvailable)\n return 1;\n return projectionsForRole.all().length;\n }\n return 0;\n }\n DataViewAnalysis.getPropertyCount = getPropertyCount;\n function hasSameCategoryIdentity(dataView1, dataView2) {\n if (dataView1\n && dataView2\n && dataView1.categorical\n && dataView2.categorical) {\n var dv1Categories = dataView1.categorical.categories;\n var dv2Categories = dataView2.categorical.categories;\n if (dv1Categories\n && dv2Categories\n && dv1Categories.length === dv2Categories.length) {\n for (var i = 0, len = dv1Categories.length; i < len; i++) {\n var dv1Identity = dv1Categories[i].identity;\n var dv2Identity = dv2Categories[i].identity;\n var dv1Length = getLengthOptional(dv1Identity);\n if (dv1Length !== getLengthOptional(dv2Identity))\n return false;\n for (var j = 0; j < dv1Length; j++) {\n if (!powerbi.DataViewScopeIdentity.equals(dv1Identity[j], dv2Identity[j]))\n return false;\n }\n }\n return true;\n }\n }\n return false;\n }\n DataViewAnalysis.hasSameCategoryIdentity = hasSameCategoryIdentity;\n function getLengthOptional(identity) {\n if (identity)\n return identity.length;\n return 0;\n }\n function areMetadataColumnsEquivalent(column1, column2) {\n if (!column1 && !column2)\n return true;\n if (!column1 || !column2)\n return false;\n if (column1.displayName !== column2.displayName)\n return false;\n if (column1.queryName !== column2.queryName)\n return false;\n if (column1.isMeasure !== column2.isMeasure)\n return false;\n if (column1.type !== column2.type)\n return false;\n if (column1.sort !== column2.sort)\n return false;\n return true;\n }\n DataViewAnalysis.areMetadataColumnsEquivalent = areMetadataColumnsEquivalent;\n /* Returns true if the metadata columns at the same positions in the array are equivalent. */\n function isMetadataEquivalent(metadata1, metadata2) {\n if (!metadata1 && !metadata2)\n return true;\n if (!metadata1 || !metadata2)\n return false;\n var previousColumnsLength = metadata1.columns.length;\n var newColumnsLength = metadata2.columns.length;\n if (previousColumnsLength !== newColumnsLength)\n return false;\n for (var i = 0; i < newColumnsLength; i++) {\n if (!DataViewAnalysis.areMetadataColumnsEquivalent(metadata1.columns[i], metadata2.columns[i]))\n return false;\n }\n return true;\n }\n DataViewAnalysis.isMetadataEquivalent = isMetadataEquivalent;\n })(DataViewAnalysis = powerbi.DataViewAnalysis || (powerbi.DataViewAnalysis = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n var Lazy = jsCommon.Lazy;\n var DataViewRoleWildcard;\n (function (DataViewRoleWildcard) {\n function fromRoles(roles) {\n return new DataViewRoleWildcardImpl(roles);\n }\n DataViewRoleWildcard.fromRoles = fromRoles;\n function equals(firstRoleWildcard, secondRoleWildcard) {\n return firstRoleWildcard.key &&\n secondRoleWildcard.key &&\n firstRoleWildcard.key === secondRoleWildcard.key &&\n ArrayExtensions.sequenceEqual(firstRoleWildcard.roles, secondRoleWildcard.roles, function (role1, role2) { return role1 === role2; });\n }\n DataViewRoleWildcard.equals = equals;\n var DataViewRoleWildcardImpl = (function () {\n function DataViewRoleWildcardImpl(roles) {\n var _this = this;\n debug.assertNonEmpty(roles, 'roles');\n this._roles = roles;\n this._key = new Lazy(function () { return JSON.stringify(_this.roles); });\n }\n Object.defineProperty(DataViewRoleWildcardImpl.prototype, \"roles\", {\n get: function () {\n return this._roles;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DataViewRoleWildcardImpl.prototype, \"key\", {\n get: function () {\n return this._key.getValue();\n },\n enumerable: true,\n configurable: true\n });\n return DataViewRoleWildcardImpl;\n }());\n })(DataViewRoleWildcard = data.DataViewRoleWildcard || (data.DataViewRoleWildcard = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var DataViewScopeIdentity;\n (function (DataViewScopeIdentity) {\n /** Compares the two DataViewScopeIdentity values for equality. */\n function equals(x, y, ignoreCase) {\n // Normalize falsy to null\n x = x || null;\n y = y || null;\n if (x === y)\n return true;\n if (!x !== !y)\n return false;\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n return data.SQExpr.equals(x.expr, y.expr, ignoreCase);\n }\n DataViewScopeIdentity.equals = equals;\n function filterFromIdentity(identities, isNot) {\n if (_.isEmpty(identities))\n return;\n var exprs = [];\n for (var _i = 0, identities_1 = identities; _i < identities_1.length; _i++) {\n var identity = identities_1[_i];\n exprs.push(identity.expr);\n }\n return filterFromExprs(exprs, isNot);\n }\n DataViewScopeIdentity.filterFromIdentity = filterFromIdentity;\n function filterFromExprs(orExprs, isNot) {\n if (_.isEmpty(orExprs))\n return;\n var resultExpr;\n for (var _i = 0, orExprs_1 = orExprs; _i < orExprs_1.length; _i++) {\n var orExpr = orExprs_1[_i];\n var inExpr = data.ScopeIdentityExtractor.getInExpr(orExpr);\n if (resultExpr)\n resultExpr = data.SQExprBuilder.or(resultExpr, inExpr);\n else\n resultExpr = inExpr || orExpr;\n }\n if (resultExpr) {\n if (isNot)\n resultExpr = powerbi.data.SQExprBuilder.not(resultExpr);\n }\n return powerbi.data.SemanticFilter.fromSQExpr(resultExpr);\n }\n DataViewScopeIdentity.filterFromExprs = filterFromExprs;\n })(DataViewScopeIdentity = powerbi.DataViewScopeIdentity || (powerbi.DataViewScopeIdentity = {}));\n var data;\n (function (data) {\n var Lazy = jsCommon.Lazy;\n function createDataViewScopeIdentity(expr) {\n return new DataViewScopeIdentityImpl(expr);\n }\n data.createDataViewScopeIdentity = createDataViewScopeIdentity;\n var DataViewScopeIdentityImpl = (function () {\n function DataViewScopeIdentityImpl(expr) {\n debug.assertValue(expr, 'expr');\n this._expr = expr;\n this._key = new Lazy(function () { return data.SQExprShortSerializer.serialize(expr); });\n }\n Object.defineProperty(DataViewScopeIdentityImpl.prototype, \"expr\", {\n get: function () {\n return this._expr;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DataViewScopeIdentityImpl.prototype, \"key\", {\n get: function () {\n return this._key.getValue();\n },\n enumerable: true,\n configurable: true\n });\n return DataViewScopeIdentityImpl;\n }());\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var Lazy = jsCommon.Lazy;\n var DataViewScopeWildcard;\n (function (DataViewScopeWildcard) {\n function matches(wildcard, instance) {\n var instanceExprs = data.ScopeIdentityExtractor.getKeys(instance.expr);\n if (!instanceExprs)\n return false;\n return data.SQExprUtils.sequenceEqual(wildcard.exprs, instanceExprs);\n }\n DataViewScopeWildcard.matches = matches;\n function equals(firstScopeWildcard, secondScopeWildcard) {\n return firstScopeWildcard.key === secondScopeWildcard.key &&\n data.SQExprUtils.sequenceEqual(firstScopeWildcard.exprs, secondScopeWildcard.exprs);\n }\n DataViewScopeWildcard.equals = equals;\n function fromExprs(exprs) {\n return new DataViewScopeWildcardImpl(exprs);\n }\n DataViewScopeWildcard.fromExprs = fromExprs;\n var DataViewScopeWildcardImpl = (function () {\n function DataViewScopeWildcardImpl(exprs) {\n debug.assertValue(exprs, 'exprs');\n this._exprs = exprs;\n this._key = new Lazy(function () { return data.SQExprShortSerializer.serializeArray(exprs); });\n }\n Object.defineProperty(DataViewScopeWildcardImpl.prototype, \"exprs\", {\n get: function () {\n return this._exprs;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DataViewScopeWildcardImpl.prototype, \"key\", {\n get: function () {\n return this._key.getValue();\n },\n enumerable: true,\n configurable: true\n });\n return DataViewScopeWildcardImpl;\n }());\n })(DataViewScopeWildcard = data.DataViewScopeWildcard || (data.DataViewScopeWildcard = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n function createColorAllocatorCache() {\n return new ColorAllocatorProvider();\n }\n data.createColorAllocatorCache = createColorAllocatorCache;\n var ColorAllocatorProvider = (function () {\n function ColorAllocatorProvider() {\n this.cache = [];\n }\n ColorAllocatorProvider.prototype.get = function (key) {\n debug.assertValue(key, 'key');\n for (var _i = 0, _a = this.cache; _i < _a.length; _i++) {\n var entry = _a[_i];\n if (entry.key === key)\n return entry.allocator;\n }\n };\n ColorAllocatorProvider.prototype.register = function (key, colorAllocator) {\n debug.assertValue(key, 'key');\n debug.assertValue(colorAllocator, 'colorAllocator');\n debug.assert(this.get(key) == null, 'Trying to re-register for same key expr.');\n this.cache.push({\n key: key,\n allocator: colorAllocator,\n });\n return this;\n };\n return ColorAllocatorProvider;\n }());\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataViewRegression;\n (function (DataViewRegression) {\n // TODO VSTS 6842046: Currently we are using a constant queryName since we don't have a way to generate\n // unique ones. There is a bug filed to do this by lawong, so this part will be fixed with that bug.\n var regressionXQueryName = 'RegressionX';\n var regressionSeriesQueryName = 'RegressionSeries';\n DataViewRegression.regressionYQueryName = 'RegressionY';\n function run(options) {\n debug.assertValue(options, 'options');\n var dataViewMappings = options.dataViewMappings;\n var visualDataViews = options.visualDataViews;\n var dataRoles = options.dataRoles;\n var objectDescriptors = options.objectDescriptors;\n var objectDefinitions = options.objectDefinitions;\n var colorAllocatorFactory = options.colorAllocatorFactory;\n var transformSelects = options.transformSelects;\n var projectionActiveItems = options.projectionActiveItems;\n var metadata = options.metadata;\n if (!_.isEmpty(visualDataViews) && transformSelects && metadata) {\n // compute linear regression line if applicable\n var roleKindByQueryRef = data.DataViewSelectTransform.createRoleKindFromMetadata(transformSelects, metadata);\n var projections = data.DataViewSelectTransform.projectionsFromSelects(transformSelects, projectionActiveItems);\n if (!roleKindByQueryRef || !projections || _.isEmpty(dataViewMappings) || !objectDescriptors || !objectDefinitions)\n return visualDataViews;\n var applicableDataViewMappings = powerbi.DataViewAnalysis.chooseDataViewMappings(projections, dataViewMappings, roleKindByQueryRef, objectDescriptors, objectDefinitions).supportedMappings;\n if (applicableDataViewMappings) {\n var regressionDataViewMapping = _.find(applicableDataViewMappings, function (dataViewMapping) {\n return dataViewMapping.usage && dataViewMapping.usage.regression;\n });\n if (regressionDataViewMapping) {\n var regressionDataViews = [];\n for (var _i = 0, visualDataViews_1 = visualDataViews; _i < visualDataViews_1.length; _i++) {\n var visualDataView = visualDataViews_1[_i];\n var regressionDataView = this.linearRegressionTransform(visualDataView, dataRoles, regressionDataViewMapping, objectDescriptors, objectDefinitions, colorAllocatorFactory);\n if (regressionDataView)\n regressionDataViews.push(regressionDataView);\n }\n if (!_.isEmpty(regressionDataViews))\n visualDataViews.push.apply(visualDataViews, regressionDataViews);\n }\n }\n }\n return visualDataViews;\n }\n DataViewRegression.run = run;\n /**\n * This function will compute the linear regression algorithm on the sourceDataView and create a new dataView.\n * It works on scalar axis only.\n * The algorithm is as follows\n *\n * 1. Find the cartesian X and Y roles and the columns that correspond to those roles\n * 2. Get the data points, (X, Y) pairs, for each series, combining if needed.\n * 3. Compute the X and Y points for regression line using Y = Slope * X + Intercept\n * If highlights values are present, repeat steps 2 & 3 using highlight values.\n * 4. Create the new dataView using the points computed above\n */\n function linearRegressionTransform(sourceDataView, dataRoles, regressionDataViewMapping, objectDescriptors, objectDefinitions, colorAllocatorFactory) {\n debug.assertValue(sourceDataView, 'sourceDataView');\n debug.assertValue(sourceDataView.categorical, 'sourceDataView.categorical');\n debug.assertValue(dataRoles, 'dataRoles');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(objectDefinitions, 'objectDefinitions');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n if (!sourceDataView.categorical)\n return;\n // Step 1\n var xColumns = getColumnsForCartesianRoleKind(0 /* X */, sourceDataView.categorical, dataRoles);\n var yColumns = getColumnsForCartesianRoleKind(1 /* Y */, sourceDataView.categorical, dataRoles);\n if (_.isEmpty(xColumns) || _.isEmpty(yColumns))\n return;\n var xColumnSource = xColumns[0].source;\n var yColumnSource = yColumns[0].source;\n var combineSeries = true;\n if (regressionDataViewMapping.usage && regressionDataViewMapping.usage.regression && sourceDataView.metadata.objects) {\n var regressionUsage = regressionDataViewMapping.usage.regression;\n var combineSeriesPropertyId = regressionUsage['combineSeries'];\n if (combineSeriesPropertyId) {\n combineSeries = powerbi.DataViewObjects.getValue(sourceDataView.metadata.objects, combineSeriesPropertyId, true);\n }\n }\n // Step 2\n var dataPointsBySeries = getDataPointsBySeries(xColumns, yColumns, combineSeries, /* preferHighlights */ false);\n var lineDefSet = calculateLineDefinitions(dataPointsBySeries);\n var xMin = lineDefSet.xMin;\n var xMax = lineDefSet.xMax;\n var shouldComputeHightlights = hasHighlightValues(yColumns) || hasHighlightValues(xColumns);\n var highlightsLineDefSet;\n if (shouldComputeHightlights) {\n var highlightDataPointsBySeries = getDataPointsBySeries(xColumns, yColumns, combineSeries, /* preferHighlights */ true);\n highlightsLineDefSet = calculateLineDefinitions(highlightDataPointsBySeries);\n if (highlightsLineDefSet) {\n xMin = _.min([xMin, highlightsLineDefSet.xMin]);\n xMax = _.max([xMax, highlightsLineDefSet.xMax]);\n }\n else {\n shouldComputeHightlights = false;\n }\n }\n // Step 3\n var valuesByTrend = [];\n for (var _i = 0, _a = lineDefSet.lineDefs; _i < _a.length; _i++) {\n var trend = _a[_i];\n valuesByTrend.push(computeLineYValues(trend, +xMin, +xMax));\n }\n var highlightsByTrend;\n if (shouldComputeHightlights) {\n highlightsByTrend = [];\n for (var _b = 0, _c = highlightsLineDefSet.lineDefs; _b < _c.length; _b++) {\n var trend = _c[_b];\n highlightsByTrend.push(computeLineYValues(trend, +xMin, +xMax));\n }\n }\n // Step 4\n var groupValues;\n if (combineSeries) {\n groupValues = ['combinedRegressionSeries'];\n }\n else {\n // If we are producing a trend line per series we need to maintain the group identities so that we can map between the \n // trend line and the original series (to match the color for example).\n if (sourceDataView.categorical.values.source) {\n // Source data view has dynamic series.\n var groups = sourceDataView.categorical.values.grouped();\n groupValues = _.map(groups, function (group) { return group.name; });\n }\n else {\n // Source data view has static or no series.\n groupValues = _.map(yColumns, function (column) { return column.source.queryName; });\n }\n }\n // Step 5\n var regressionDataView = createRegressionDataView(xColumnSource, yColumnSource, groupValues, [xMin, xMax], valuesByTrend, highlightsByTrend, sourceDataView, regressionDataViewMapping, objectDescriptors, objectDefinitions, colorAllocatorFactory);\n return regressionDataView;\n }\n DataViewRegression.linearRegressionTransform = linearRegressionTransform;\n function calculateLineDefinitions(dataPointsBySeries) {\n var xMin;\n var xMax;\n var lineDefs = [];\n for (var _i = 0, dataPointsBySeries_1 = dataPointsBySeries; _i < dataPointsBySeries_1.length; _i++) {\n var dataPointSet = dataPointsBySeries_1[_i];\n var unsortedXValues = dataPointSet.xValues;\n var unsortedYValues = dataPointSet.yValues;\n if (_.isEmpty(unsortedXValues) || _.isEmpty(unsortedYValues))\n return;\n // get the data type for each column; we will have null type when dataPoints have different type or if a value is null\n var xDataType = getDataType(unsortedXValues);\n if (!xDataType)\n return;\n var yDataType = getDataType(unsortedYValues);\n if (!yDataType)\n return;\n var sortedDataPointSet = sortValues(unsortedXValues, unsortedYValues);\n var minCategoryValue = sortedDataPointSet.xValues[0];\n var maxCategoryValue = sortedDataPointSet.xValues[sortedDataPointSet.xValues.length - 1];\n var lineDef = computeRegressionLine(sortedDataPointSet.xValues, sortedDataPointSet.yValues);\n xMin = _.min([xMin, minCategoryValue]);\n xMax = _.max([xMax, maxCategoryValue]);\n lineDefs.push(lineDef);\n }\n return {\n lineDefs: lineDefs,\n xMin: xMin,\n xMax: xMax,\n };\n }\n function getColumnsForCartesianRoleKind(roleKind, categorical, roles) {\n debug.assertValue(roleKind, 'roleKind');\n debug.assertValue(categorical, 'categorical');\n var columns = getColumnsWithRoleKind(roleKind, categorical.values, roles);\n if (!_.isEmpty(columns))\n return columns;\n var categories = categorical.categories;\n if (_.isEmpty(categories))\n return;\n debug.assert(categories.length === 1, 'composite category columns not supported');\n var categoryColumn = categories[0];\n columns = getColumnsWithRoleKind(roleKind, [categoryColumn], roles);\n if (!_.isEmpty(columns))\n return columns;\n }\n function getColumnsWithRoleKind(roleKind, columns, roles) {\n if (_.isEmpty(columns))\n return;\n return _.filter(columns, function (column) {\n var _loop_1 = function(roleName) {\n if (!column.source.roles[roleName])\n return \"continue\";\n var role = _.find(roles, function (role) { return role.name === roleName; });\n if (role && role.cartesianKind === roleKind)\n return { value: true };\n };\n for (var roleName in column.source.roles) {\n var state_1 = _loop_1(roleName);\n if (typeof state_1 === \"object\") return state_1.value;\n if (state_1 === \"continue\") continue;\n }\n return false;\n });\n }\n function getDataType(values) {\n var firstNonNull = _.find(values, function (value) { return value != null; });\n if (firstNonNull == null)\n return;\n var dataType = typeof firstNonNull;\n if (_.some(values, function (value) { return value != null && typeof value !== dataType; }))\n return;\n return dataType;\n }\n function sortValues(unsortedXValues, unsortedYValues) {\n debug.assertValue(unsortedXValues, 'unsortedXValues');\n debug.assertValue(unsortedYValues, 'unsortedYValues');\n var zippedValues = _.zip(unsortedXValues, unsortedYValues);\n var _a = _.chain(zippedValues)\n .filter(function (valuePair) { return valuePair[0] != null && valuePair[1] != null; })\n .sortBy(function (valuePair) { return valuePair[0]; })\n .unzip()\n .value(), xValues = _a[0], yValues = _a[1];\n return {\n xValues: xValues,\n yValues: yValues\n };\n }\n /**\n * Computes a line definition using linear regression.\n * xBar: average of X values, yBar: average of Y values\n * ssXX: sum of squares of X values = Sum(xi - xBar)^2\n * ssXY: sum of squares of X and Y values = Sum((xi - xBar)(yi - yBar)\n * Slope: ssXY / ssXX\n * Intercept: yBar - xBar * slope\n */\n function computeRegressionLine(xValues, yValues) {\n debug.assertValue(xValues, 'xValues');\n debug.assertValue(yValues, 'yValues');\n var xBar = _.sum(xValues) / xValues.length;\n var yBar = _.sum(yValues) / yValues.length;\n var ssXX = _.chain(xValues)\n .map(function (x) {\n return Math.pow((x - xBar), 2);\n })\n .sum();\n var ssXY = _.chain(xValues)\n .map(function (x, i) {\n return (x - xBar) * (yValues[i] - yBar);\n })\n .sum();\n var slope = ssXY / ssXX;\n var intercept = yBar - (xBar * slope);\n return {\n slope: slope,\n intercept: intercept\n };\n }\n function computeLineYValues(lineDef, x1, x2) {\n return [x1 * lineDef.slope + lineDef.intercept, x2 * lineDef.slope + lineDef.intercept];\n }\n function getValuesFromColumn(column, preferHighlights) {\n if (preferHighlights) {\n // Attempt to use highlight values. When X is categorical, we may not have highlight values so we should fall back to the non-highlight values.\n var valueColumn = column;\n if (valueColumn.highlights) {\n return valueColumn.highlights;\n }\n }\n return column.values;\n }\n function getDataPointsBySeries(xColumns, yColumns, combineSeries, preferHighlights) {\n var dataPointsBySeries = [];\n var xValueArray = _.map(xColumns, function (column) { return getValuesFromColumn(column, preferHighlights); });\n var seriesYValues = _.map(yColumns, function (column) { return getValuesFromColumn(column, preferHighlights); });\n var multipleXValueColumns = xColumns.length > 1;\n for (var i = 0; i < seriesYValues.length; i++) {\n var xValues = multipleXValueColumns ? xValueArray[i] : xValueArray[0];\n var yValues = seriesYValues[i];\n if (combineSeries && dataPointsBySeries.length > 0) {\n dataPointsBySeries[0].xValues = dataPointsBySeries[0].xValues.concat(xValues);\n dataPointsBySeries[0].yValues = dataPointsBySeries[0].yValues.concat(yValues);\n }\n else {\n dataPointsBySeries.push({\n xValues: xValues,\n yValues: yValues,\n });\n }\n }\n return dataPointsBySeries;\n }\n function createRegressionDataView(xColumnSource, yColumnSource, groupValues, categories, values, highlights, sourceDataView, regressionDataViewMapping, objectDescriptors, objectDefinitions, colorAllocatorFactory) {\n debug.assertValue(xColumnSource, 'xColumnSource');\n debug.assertValue(yColumnSource, 'yColumnSource');\n debug.assertValue(categories, 'categories');\n debug.assertValue(values, 'values');\n debug.assertValue(sourceDataView, 'sourceDataView');\n debug.assertValue(objectDescriptors, 'objectDescriptors');\n debug.assertValue(objectDefinitions, 'objectDefinitions');\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\n debug.assertAnyValue(highlights, 'highlights');\n debug.assert(!highlights || highlights.length === values.length, 'highlights should have the same length as values');\n var xRole = regressionDataViewMapping.categorical.categories.for.in;\n var grouped = regressionDataViewMapping.categorical.values.group;\n var yRole;\n var seriesRole;\n if (grouped && !_.isEmpty(grouped.select)) {\n yRole = grouped.select[0].for ?\n grouped.select[0].for.in :\n grouped.select[0].bind.to;\n seriesRole = grouped.by;\n }\n if (!yRole || !seriesRole)\n return;\n var categoricalRoles = (_a = {}, _a[xRole] = true, _a);\n var valueRoles = (_b = {}, _b[yRole] = true, _b);\n var seriesRoles = (_c = {}, _c[seriesRole] = true, _c);\n var valuesBySeries = [];\n for (var index in values) {\n var seriesData = {\n values: values[index],\n };\n if (highlights)\n seriesData.highlights = highlights[index];\n valuesBySeries.push([seriesData]);\n }\n var regressionDataView = data.createCategoricalDataViewBuilder()\n .withCategory({\n source: {\n displayName: xColumnSource.displayName,\n queryName: regressionXQueryName,\n type: xColumnSource.type,\n isMeasure: false,\n roles: categoricalRoles\n },\n values: categories,\n identityFrom: {\n fields: [data.SQExprBuilder.columnRef(data.SQExprBuilder.entity('s', 'RegressionEntity'), 'RegressionCategories')],\n },\n })\n .withGroupedValues({\n groupColumn: {\n source: {\n displayName: yColumnSource.displayName + 'Regression',\n queryName: regressionSeriesQueryName,\n type: yColumnSource.type,\n isMeasure: yColumnSource.isMeasure,\n roles: seriesRoles\n },\n values: groupValues,\n identityFrom: {\n fields: [data.SQExprBuilder.columnRef(data.SQExprBuilder.entity('s', 'RegressionEntity'), 'RegressionSeries')],\n }\n },\n valueColumns: [{\n source: {\n displayName: yColumnSource.displayName,\n queryName: DataViewRegression.regressionYQueryName,\n type: yColumnSource.type,\n isMeasure: yColumnSource.isMeasure,\n roles: valueRoles\n },\n }],\n data: valuesBySeries\n })\n .build();\n data.DataViewTransform.transformObjects(regressionDataView, 1 /* Categorical */, objectDescriptors, objectDefinitions, [], colorAllocatorFactory);\n return regressionDataView;\n var _a, _b, _c;\n }\n function hasHighlightValues(columns) {\n return _.any(columns, function (column) {\n var valueColumn = column;\n return valueColumn.highlights != null;\n });\n }\n })(DataViewRegression = data.DataViewRegression || (data.DataViewRegression = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataViewSelectTransform;\n (function (DataViewSelectTransform) {\n /** Convert selection info to projections */\n function projectionsFromSelects(selects, projectionActiveItems) {\n debug.assertAnyValue(selects, \"selects\");\n debug.assertAnyValue(projectionActiveItems, \"projectionActiveItems\");\n var projections = {};\n for (var _i = 0, selects_1 = selects; _i < selects_1.length; _i++) {\n var select = selects_1[_i];\n var roles = select.roles;\n if (!roles)\n continue;\n for (var roleName in roles) {\n if (roles[roleName]) {\n var qp = projections[roleName];\n if (!qp)\n qp = projections[roleName] = new data.QueryProjectionCollection([]);\n qp.all().push({ queryRef: select.queryName });\n if (projectionActiveItems && projectionActiveItems[roleName])\n qp.activeProjectionRefs = _.map(projectionActiveItems[roleName], function (activeItem) { return activeItem.queryRef; });\n }\n }\n }\n return projections;\n }\n DataViewSelectTransform.projectionsFromSelects = projectionsFromSelects;\n /** Use selections and metadata to fashion query role kinds */\n function createRoleKindFromMetadata(selects, metadata) {\n var roleKindByQueryRef = {};\n for (var _i = 0, _a = metadata.columns; _i < _a.length; _i++) {\n var column = _a[_i];\n if ((!column.index && column.index !== 0) || column.index < 0 || column.index >= selects.length)\n continue;\n var select = selects[column.index];\n if (select) {\n var queryRef = select.queryName;\n if (queryRef && roleKindByQueryRef[queryRef] === undefined) {\n roleKindByQueryRef[queryRef] = column.isMeasure ? powerbi.VisualDataRoleKind.Measure : powerbi.VisualDataRoleKind.Grouping;\n }\n }\n }\n return roleKindByQueryRef;\n }\n DataViewSelectTransform.createRoleKindFromMetadata = createRoleKindFromMetadata;\n })(DataViewSelectTransform = data.DataViewSelectTransform || (data.DataViewSelectTransform = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n function createCategoricalEvalContext(colorAllocatorProvider, dataViewCategorical) {\n return new CategoricalEvalContext(colorAllocatorProvider, dataViewCategorical);\n }\n data.createCategoricalEvalContext = createCategoricalEvalContext;\n var CategoricalEvalContext = (function () {\n function CategoricalEvalContext(colorAllocatorProvider, dataView) {\n debug.assertValue(colorAllocatorProvider, 'colorAllocatorProvider');\n debug.assertValue(dataView, 'dataView');\n this.colorAllocatorProvider = colorAllocatorProvider;\n this.dataView = dataView;\n this.columnsByRole = {};\n }\n CategoricalEvalContext.prototype.getColorAllocator = function (expr) {\n return this.colorAllocatorProvider.get(expr);\n };\n CategoricalEvalContext.prototype.getExprValue = function (expr) {\n return;\n };\n CategoricalEvalContext.prototype.getRoleValue = function (roleName) {\n var columnsByRole = this.columnsByRole;\n var column = columnsByRole[roleName];\n if (!column)\n column = columnsByRole[roleName] = findRuleInputColumn(this.dataView, roleName);\n if (!column)\n return;\n var index = this.index;\n if (index != null)\n return column.values[this.index];\n };\n CategoricalEvalContext.prototype.setCurrentRowIndex = function (index) {\n debug.assertValue(index, 'index');\n this.index = index;\n };\n return CategoricalEvalContext;\n }());\n function findRuleInputColumn(dataViewCategorical, inputRole) {\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\n return findRuleInputInColumns(dataViewCategorical.values, inputRole) ||\n findRuleInputInColumns(dataViewCategorical.categories, inputRole);\n }\n function findRuleInputInColumns(columns, inputRole) {\n debug.assertAnyValue(columns, 'columns');\n if (!columns)\n return;\n for (var _i = 0, columns_7 = columns; _i < columns_7.length; _i++) {\n var column = columns_7[_i];\n var roles = column.source.roles;\n if (!roles || !roles[inputRole])\n continue;\n return column;\n }\n }\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n function createTableEvalContext(colorAllocatorProvider, dataViewTable, selectTransforms) {\n return new TableEvalContext(colorAllocatorProvider, dataViewTable, selectTransforms);\n }\n data.createTableEvalContext = createTableEvalContext;\n var TableEvalContext = (function () {\n function TableEvalContext(colorAllocatorProvider, dataView, selectTransforms) {\n debug.assertValue(colorAllocatorProvider, 'colorAllocatorProvider');\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(selectTransforms, 'selectTransforms');\n this.colorAllocatorProvider = colorAllocatorProvider;\n this.dataView = dataView;\n this.selectTransforms = selectTransforms;\n }\n TableEvalContext.prototype.getColorAllocator = function (expr) {\n return this.colorAllocatorProvider.get(expr);\n };\n TableEvalContext.prototype.getExprValue = function (expr) {\n debug.assertValue(expr, 'expr');\n var rowIdx = this.rowIdx;\n if (rowIdx == null)\n return;\n return data.getExprValueFromTable(expr, this.selectTransforms, this.dataView, rowIdx);\n };\n TableEvalContext.prototype.getRoleValue = function (roleName) {\n return;\n };\n TableEvalContext.prototype.setCurrentRowIndex = function (index) {\n debug.assertValue(index, 'index');\n this.rowIdx = index;\n };\n return TableEvalContext;\n }());\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var RuleEvaluation = (function () {\n function RuleEvaluation() {\n }\n // NOTE: even though this class has no behaviour, we still use a class to facilitate instanceof checks.\n RuleEvaluation.prototype.evaluate = function (evalContext) {\n debug.assertFail('Abstract method RuleEvaluation.evaluate not implemented.');\n };\n return RuleEvaluation;\n }());\n data.RuleEvaluation = RuleEvaluation;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ColorRuleEvaluation = (function (_super) {\n __extends(ColorRuleEvaluation, _super);\n function ColorRuleEvaluation(inputRole, allocator) {\n debug.assertValue(inputRole, 'inputRole');\n debug.assertValue(allocator, 'allocator');\n _super.call(this);\n this.inputRole = inputRole;\n this.allocator = allocator;\n }\n ColorRuleEvaluation.prototype.evaluate = function (evalContext) {\n debug.assertValue(evalContext, 'evalContext');\n var value = evalContext.getRoleValue(this.inputRole);\n if (value !== undefined)\n return this.allocator.color(value);\n };\n return ColorRuleEvaluation;\n }(data.RuleEvaluation));\n data.ColorRuleEvaluation = ColorRuleEvaluation;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var utils;\n (function (utils) {\n var inherit = powerbi.Prototype.inherit;\n var inheritSingle = powerbi.Prototype.inheritSingle;\n var ArrayExtensions = jsCommon.ArrayExtensions;\n var DataViewMatrixUtils;\n (function (DataViewMatrixUtils) {\n /**\n * Invokes the specified callback once per leaf nodes (including root-level leaves and descendent leaves) of the\n * specified rootNodes, with an optional index parameter in the callback that is the 0-based index of the\n * particular leaf node in the context of this forEachLeafNode(...) invocation.\n *\n * If rootNodes is null or undefined or empty, the specified callback will not get invoked.\n *\n * The treePath parameter in the callback is an ordered set of nodes that form the path from the specified\n * rootNodes down to the leafNode argument itself. If callback leafNode is one of the specified rootNodes,\n * then treePath will be an array of length 1 containing that very node.\n *\n * IMPORTANT: The treePath array passed to the callback will be modified after the callback function returns!\n * If your callback needs to retain a copy of the treePath, please clone the array before returning.\n */\n function forEachLeafNode(rootNodes, callback) {\n debug.assertAnyValue(rootNodes, 'rootNodes');\n debug.assertValue(callback, 'callback');\n // Note: Don't do \"if (!_.isEmpty(rootNodes))\" for checking whether rootNodes is an empty array DataViewMatrixNode[],\n // because rootNodes can also be an non-array DataViewMatrixNode, and an empty object can be a valid root node DataViewMatrixNode, \n // for the fact that all the properties on DataViewMatrixNode are optional...\n if (rootNodes) {\n if (isNodeArray(rootNodes)) {\n var index = 0;\n for (var _i = 0, rootNodes_1 = rootNodes; _i < rootNodes_1.length; _i++) {\n var rootNode = rootNodes_1[_i];\n if (rootNode) {\n index = forEachLeafNodeRecursive(rootNode, index, [], callback);\n }\n }\n }\n else {\n forEachLeafNodeRecursive(rootNodes, 0, [], callback);\n }\n }\n }\n DataViewMatrixUtils.forEachLeafNode = forEachLeafNode;\n function isNodeArray(nodeOrNodeArray) {\n return ArrayExtensions.isArrayOrInheritedArray(nodeOrNodeArray);\n }\n /**\n * Recursively traverses to each leaf node of the specified matrixNode and invokes callback with each of them.\n * Returns the index for the next node after the last node that this function invokes callback with.\n *\n * @treePath an array that contains the path from the specified rootNodes in forEachLeafNode() down to the parent of the argument matrixNode (i.e. treePath does not contain the matrixNode argument yet).\n */\n function forEachLeafNodeRecursive(matrixNode, nextIndex, treePath, callback) {\n debug.assertValue(matrixNode, 'matrixNode');\n debug.assertValue(treePath, 'treePath');\n debug.assertValue(callback, 'callback');\n // If treePath already contains matrixNode, then either one of the following errors has happened:\n // 1. the caller code mistakenly added matrixNode to treePath, or\n // 2. the callback modified treePath by adding a node to it, or\n // 3. the matrix hierarchy contains a cyclical node reference.');\n debug.assert(!_.contains(treePath, matrixNode), 'pre-condition: treePath must not already contain matrixNode');\n treePath.push(matrixNode);\n if (_.isEmpty(matrixNode.children)) {\n callback(matrixNode, nextIndex, treePath);\n nextIndex++;\n }\n else {\n var children = matrixNode.children;\n for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {\n var nextChild = children_1[_i];\n if (nextChild) {\n nextIndex = forEachLeafNodeRecursive(nextChild, nextIndex, treePath, callback);\n }\n }\n }\n debug.assert(_.last(treePath) === matrixNode, 'pre-condition: the callback given to forEachLeafNode() is not supposed to modify the treePath argument array.');\n treePath.pop();\n return nextIndex;\n }\n /**\n * Returned an object tree where each node and its children property are inherited from the specified node\n * hierarchy, from the root down to the nodes at the specified deepestLevelToInherit, inclusively.\n *\n * The inherited nodes at level === deepestLevelToInherit will NOT get an inherited version of children array\n * property, i.e. its children property is the same array object referenced in the input node's object tree.\n *\n * @param node The input node with the hierarchy object tree.\n * @param deepestLevelToInherit The highest level for a node to get inherited. See DataViewMatrixNode.level property.\n * @param useInheritSingle If true, then a node will get inherited in the returned object tree only if it is\n * not already an inherited object. Same goes for the node's children property. This is useful for creating\n * \"visual DataView\" objects from \"query DataView\" objects, as object inheritance is the mechanism for\n * \"visual DataView\" to override properties in \"query DataView\", and that \"query DataView\" never contains\n * inherited objects.\n */\n function inheritMatrixNodeHierarchy(node, deepestLevelToInherit, useInheritSingle) {\n debug.assertValue(node, 'node');\n debug.assert(deepestLevelToInherit >= 0, 'deepestLevelToInherit >= 0');\n debug.assertValue(useInheritSingle, 'useInheritSingle');\n var returnNode = node;\n // Note: The level property of DataViewMatrix.rows.root and DataViewMatrix.columns.root are always undefined.\n // Also, in a matrix with multiple column grouping fields and multiple value fields, the DataViewMatrixNode\n // for the Grand Total column in the column hierarchy will have children nodes where level > (parent.level + 1):\n // {\n // \"level\": 0,\n // \"isSubtotal\": true,\n // \"children\": [\n // { \"level\": 2, \"isSubtotal\": true },\n // { \"level\": 2, \"levelSourceIndex\": 1, \"isSubtotal\": true }\n // ]\n // }\n var isRootNode = _.isUndefined(node.level);\n var shouldInheritCurrentNode = isRootNode || (node.level <= deepestLevelToInherit);\n if (shouldInheritCurrentNode) {\n var inheritFunc = useInheritSingle ? inheritSingle : inherit;\n var inheritedNode = inheritFunc(node);\n var shouldInheritChildNodes = isRootNode || (node.level < deepestLevelToInherit);\n if (shouldInheritChildNodes && !_.isEmpty(node.children)) {\n inheritedNode.children = inheritFunc(node.children); // first, make an inherited array\n for (var i = 0, ilen = inheritedNode.children.length; i < ilen; i++) {\n inheritedNode.children[i] =\n inheritMatrixNodeHierarchy(inheritedNode.children[i], deepestLevelToInherit, useInheritSingle);\n }\n }\n returnNode = inheritedNode;\n }\n return returnNode;\n }\n DataViewMatrixUtils.inheritMatrixNodeHierarchy = inheritMatrixNodeHierarchy;\n /**\n * Returns true if the specified matrixOrHierarchy contains any composite grouping, i.e. a grouping on multiple columns.\n * An example of composite grouping is one on [Year, Quarter, Month], where a particular group instance can have\n * Year === 2016, Quarter === 'Qtr 1', Month === 1.\n *\n * Returns false if the specified matrixOrHierarchy does not contain any composite group,\n * or if matrixOrHierarchy is null or undefined.\n */\n function containsCompositeGroup(matrixOrHierarchy) {\n debug.assertAnyValue(matrixOrHierarchy, 'matrixOrHierarchy');\n var hasCompositeGroup = false;\n if (matrixOrHierarchy) {\n if (isMatrix(matrixOrHierarchy)) {\n hasCompositeGroup = containsCompositeGroup(matrixOrHierarchy.rows) ||\n containsCompositeGroup(matrixOrHierarchy.columns);\n }\n else {\n var hierarchyLevels = matrixOrHierarchy.levels;\n if (!_.isEmpty(hierarchyLevels)) {\n for (var _i = 0, hierarchyLevels_1 = hierarchyLevels; _i < hierarchyLevels_1.length; _i++) {\n var level = hierarchyLevels_1[_i];\n // it takes at least 2 columns at the same hierarchy level to form a composite group...\n if (level.sources && (level.sources.length >= 2)) {\n debug.assert(_.all(level.sources, function (sourceColumn) { return sourceColumn.isMeasure === level.sources[0].isMeasure; }), 'pre-condition: in a valid DataViewMatrix, the source columns in each of its hierarchy levels must either be all non-measure columns (i.e. a grouping level) or all measure columns (i.e. a measure headers level)');\n // Measure headers are not group\n var isMeasureHeadersLevel = level.sources[0].isMeasure;\n if (!isMeasureHeadersLevel) {\n hasCompositeGroup = true;\n break;\n }\n }\n }\n }\n }\n }\n return hasCompositeGroup;\n }\n DataViewMatrixUtils.containsCompositeGroup = containsCompositeGroup;\n function isMatrix(matrixOrHierarchy) {\n return 'rows' in matrixOrHierarchy &&\n 'columns' in matrixOrHierarchy &&\n 'valueSources' in matrixOrHierarchy;\n }\n })(DataViewMatrixUtils = utils.DataViewMatrixUtils || (utils.DataViewMatrixUtils = {}));\n })(utils = data.utils || (data.utils = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var utils;\n (function (utils) {\n var DataViewMetadataColumnUtils;\n (function (DataViewMetadataColumnUtils) {\n /**\n * Returns true iff the specified metadataColumn is assigned to the specified targetRole.\n */\n function isForRole(metadataColumn, targetRole) {\n debug.assertValue(metadataColumn, 'metadataColumn');\n debug.assertValue(targetRole, 'targetRole');\n var roles = metadataColumn.roles;\n return roles && roles[targetRole];\n }\n DataViewMetadataColumnUtils.isForRole = isForRole;\n /**\n * Joins each column in the specified columnSources with projection ordering index into a wrapper object.\n *\n * Note: In order for this function to reliably calculate the \"source index\" of a particular column, the\n * specified columnSources must be a non-filtered array of column sources from the DataView, such as\n * the DataViewHierarchyLevel.sources and DataViewMatrix.valueSources array properties.\n *\n * @param columnSources E.g. DataViewHierarchyLevel.sources, DataViewMatrix.valueSources...\n * @param projection The projection ordering. It must contain an ordering for the specified role.\n * @param role The role for getting the relevant projection ordering, as well as for filtering out the irrevalent columns in columnSources.\n */\n function joinMetadataColumnsAndProjectionOrder(columnSources, projection, role) {\n debug.assertAnyValue(columnSources, 'columnSources');\n debug.assert(_.all(columnSources, function (column) { return _.isNumber(column.index); }), 'pre-condition: Every value in columnSources must already have its Select Index property initialized.');\n debug.assertNonEmpty(projection[role], 'projection[role]');\n debug.assert(_.all(columnSources, function (column) { return !isForRole(column, role) || _.contains(projection[role], column.index); }), 'pre-condition: The projection order for the specified role must contain the Select Index of every column with matching role in the specified columnSources.');\n var jointResult = [];\n if (!_.isEmpty(columnSources)) {\n var projectionOrderSelectIndices = projection[role];\n var selectIndexToProjectionIndexMap = {};\n for (var i = 0, ilen = projectionOrderSelectIndices.length; i < ilen; i++) {\n var selectIndex = projectionOrderSelectIndices[i];\n selectIndexToProjectionIndexMap[selectIndex] = i;\n }\n for (var j = 0, jlen = columnSources.length; j < jlen; j++) {\n var column = columnSources[j];\n if (isForRole(column, role)) {\n var jointColumnInfo = {\n metadataColumn: column,\n sourceIndex: j,\n projectionOrderIndex: selectIndexToProjectionIndexMap[column.index]\n };\n jointResult.push(jointColumnInfo);\n }\n }\n }\n return jointResult;\n }\n DataViewMetadataColumnUtils.joinMetadataColumnsAndProjectionOrder = joinMetadataColumnsAndProjectionOrder;\n })(DataViewMetadataColumnUtils = utils.DataViewMetadataColumnUtils || (utils.DataViewMetadataColumnUtils = {}));\n })(utils = data.utils || (data.utils = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ConceptualSchema = (function () {\n function ConceptualSchema() {\n }\n ConceptualSchema.prototype.findProperty = function (entityName, propertyName) {\n var entity = this.entities.withName(entityName);\n if (!entity || _.isEmpty(entity.properties))\n return;\n return entity.properties.withName(propertyName);\n };\n ConceptualSchema.prototype.findHierarchy = function (entityName, name) {\n var entity = this.entities.withName(entityName);\n if (!entity || _.isEmpty(entity.hierarchies))\n return;\n return entity.hierarchies.withName(name);\n };\n ConceptualSchema.prototype.findHierarchyByVariation = function (variationEntityName, variationColumnName, variationName, hierarchyName) {\n var variationEntity = this.entities.withName(variationEntityName);\n if (!variationEntity || _.isEmpty(variationEntity.properties))\n return;\n var variationProperty = variationEntity.properties.withName(variationColumnName);\n if (!variationProperty)\n return;\n var variationColumn = variationProperty.column;\n if (!variationColumn || _.isEmpty(variationColumn.variations))\n return;\n var variation = variationColumn.variations.withName(variationName);\n if (variation) {\n var targetEntity = variation.navigationProperty ? variation.navigationProperty.targetEntity : variationEntity;\n if (!targetEntity || _.isEmpty(targetEntity.hierarchies))\n return;\n return targetEntity.hierarchies.withName(hierarchyName);\n }\n };\n /**\n * Returns the first property of the entity whose kpi is tied to kpiProperty\n */\n ConceptualSchema.prototype.findPropertyWithKpi = function (entityName, kpiProperty) {\n debug.assertValue(kpiProperty, 'kpiProperty');\n var entity = this.entities.withName(entityName);\n if (!entity || _.isEmpty(entity.properties))\n return;\n for (var _i = 0, _a = entity.properties; _i < _a.length; _i++) {\n var prop = _a[_i];\n if (prop &&\n prop.measure &&\n prop.measure.kpi &&\n (prop.measure.kpi.status === kpiProperty || prop.measure.kpi.goal === kpiProperty))\n return prop;\n }\n return;\n };\n return ConceptualSchema;\n }());\n data.ConceptualSchema = ConceptualSchema;\n // TODO: Remove this (replaced by ValueType)\n (function (ConceptualDataCategory) {\n ConceptualDataCategory[ConceptualDataCategory[\"None\"] = 0] = \"None\";\n ConceptualDataCategory[ConceptualDataCategory[\"Address\"] = 1] = \"Address\";\n ConceptualDataCategory[ConceptualDataCategory[\"City\"] = 2] = \"City\";\n ConceptualDataCategory[ConceptualDataCategory[\"Company\"] = 3] = \"Company\";\n ConceptualDataCategory[ConceptualDataCategory[\"Continent\"] = 4] = \"Continent\";\n ConceptualDataCategory[ConceptualDataCategory[\"Country\"] = 5] = \"Country\";\n ConceptualDataCategory[ConceptualDataCategory[\"County\"] = 6] = \"County\";\n ConceptualDataCategory[ConceptualDataCategory[\"Date\"] = 7] = \"Date\";\n ConceptualDataCategory[ConceptualDataCategory[\"Image\"] = 8] = \"Image\";\n ConceptualDataCategory[ConceptualDataCategory[\"ImageUrl\"] = 9] = \"ImageUrl\";\n ConceptualDataCategory[ConceptualDataCategory[\"Latitude\"] = 10] = \"Latitude\";\n ConceptualDataCategory[ConceptualDataCategory[\"Longitude\"] = 11] = \"Longitude\";\n ConceptualDataCategory[ConceptualDataCategory[\"Organization\"] = 12] = \"Organization\";\n ConceptualDataCategory[ConceptualDataCategory[\"Place\"] = 13] = \"Place\";\n ConceptualDataCategory[ConceptualDataCategory[\"PostalCode\"] = 14] = \"PostalCode\";\n ConceptualDataCategory[ConceptualDataCategory[\"Product\"] = 15] = \"Product\";\n ConceptualDataCategory[ConceptualDataCategory[\"StateOrProvince\"] = 16] = \"StateOrProvince\";\n ConceptualDataCategory[ConceptualDataCategory[\"WebUrl\"] = 17] = \"WebUrl\";\n })(data.ConceptualDataCategory || (data.ConceptualDataCategory = {}));\n var ConceptualDataCategory = data.ConceptualDataCategory;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var StringExtensions = jsCommon.StringExtensions;\n var FieldExprPattern = powerbi.data.FieldExprPattern;\n var ScriptResultUtil;\n (function (ScriptResultUtil) {\n function findScriptResult(dataViewMappings) {\n if (dataViewMappings && dataViewMappings.length === 1) {\n return dataViewMappings[0].scriptResult;\n }\n return undefined;\n }\n ScriptResultUtil.findScriptResult = findScriptResult;\n function extractScriptResult(dataViewMappings) {\n var scriptResult = findScriptResult(dataViewMappings);\n if (scriptResult) {\n var objects = dataViewMappings[0].metadata.objects;\n var source = powerbi.DataViewObjects.getValue(objects, scriptResult.script.source);\n var provider = powerbi.DataViewObjects.getValue(objects, scriptResult.script.provider);\n return {\n source: source,\n provider: provider\n };\n }\n return undefined;\n }\n ScriptResultUtil.extractScriptResult = extractScriptResult;\n function extractScriptResultFromVisualConfig(dataViewMappings, objects) {\n var scriptResult = findScriptResult(dataViewMappings);\n if (scriptResult && objects) {\n var scriptSource = powerbi.data.DataViewObjectDefinitions.getValue(objects, scriptResult.script.source, null);\n var provider = powerbi.data.DataViewObjectDefinitions.getValue(objects, scriptResult.script.provider, null);\n return {\n source: scriptSource ? scriptSource.value : null,\n provider: provider ? provider.value : null\n };\n }\n return undefined;\n }\n ScriptResultUtil.extractScriptResultFromVisualConfig = extractScriptResultFromVisualConfig;\n function getScriptInput(projections, selects, schema) {\n var scriptInput = {\n VariableName: \"dataset\",\n Columns: []\n };\n // Go over all the projections, and create an input column according to the order\n // of the projections (including duplicate expressions)\n if (projections && selects && !_.isEmpty(selects)) {\n var scriptInputColumnNames = [];\n var scriptInputColumns = [];\n for (var role in projections) {\n for (var _i = 0, _a = projections[role].all(); _i < _a.length; _i++) {\n var projection = _a[_i];\n var select = selects.withName(projection.queryRef);\n if (select) {\n var scriptInputColumn = {\n QueryName: select.name,\n Name: FieldExprPattern.visit(select.expr, new ScriptInputColumnNameVisitor(schema))\n };\n scriptInputColumns.push(scriptInputColumn);\n scriptInputColumnNames.push(scriptInputColumn.Name);\n }\n }\n }\n // Make sure the names of the columns are unique\n scriptInputColumnNames = StringExtensions.ensureUniqueNames(scriptInputColumnNames);\n // Update the names of the columns\n for (var i = 0; i < scriptInputColumnNames.length; i++) {\n var scriptInputColumn = scriptInputColumns[i];\n scriptInputColumn.Name = scriptInputColumnNames[i];\n }\n scriptInput.Columns = scriptInputColumns;\n }\n return scriptInput;\n }\n ScriptResultUtil.getScriptInput = getScriptInput;\n var ScriptInputColumnNameVisitor = (function () {\n function ScriptInputColumnNameVisitor(federatedSchema) {\n this.federatedSchema = federatedSchema;\n }\n ScriptInputColumnNameVisitor.prototype.visitColumn = function (column) {\n return ScriptInputColumnNameVisitor.getNameForProperty(column, this.federatedSchema);\n };\n ScriptInputColumnNameVisitor.prototype.visitColumnAggr = function (columnAggr) {\n return ScriptInputColumnNameVisitor.getNameForProperty(columnAggr, this.federatedSchema);\n };\n ScriptInputColumnNameVisitor.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariation) {\n return ScriptInputColumnNameVisitor.getVariationLevelName(columnHierarchyLevelVariation, this.federatedSchema);\n };\n ScriptInputColumnNameVisitor.prototype.visitEntity = function (entity) {\n return entity.entity;\n };\n ScriptInputColumnNameVisitor.prototype.visitEntityAggr = function (entityAggr) {\n return entityAggr.entity;\n };\n ScriptInputColumnNameVisitor.prototype.visitHierarchy = function (hierarchy) {\n return ScriptInputColumnNameVisitor.getNameForHierarchy(hierarchy, this.federatedSchema);\n };\n ScriptInputColumnNameVisitor.prototype.visitHierarchyLevel = function (hierarchyLevel) {\n /*Hierarchy levels are not supported yet*/\n return;\n };\n ScriptInputColumnNameVisitor.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return ScriptInputColumnNameVisitor.getNameForProperty(hierarchyLevelAggr, this.federatedSchema);\n };\n ScriptInputColumnNameVisitor.prototype.visitMeasure = function (measure) {\n return ScriptInputColumnNameVisitor.getNameForProperty(measure, this.federatedSchema);\n };\n ScriptInputColumnNameVisitor.prototype.visitSelectRef = function (selectRef) {\n return FieldExprPattern.visit(selectRef, this);\n };\n ScriptInputColumnNameVisitor.prototype.visitPercentile = function (percentile) {\n return FieldExprPattern.visit(percentile.arg, this);\n };\n ScriptInputColumnNameVisitor.prototype.visitPercentOfGrandTotal = function (percentOfGrandTotal) {\n return FieldExprPattern.visit(percentOfGrandTotal.baseExpr, this);\n };\n ScriptInputColumnNameVisitor.getNameForHierarchy = function (pattern, federatedScheam) {\n debug.assertValue(pattern, 'pattern');\n var schema = federatedScheam.schema(pattern.schema), hierarchy = schema.findHierarchy(pattern.entity, pattern.name);\n if (hierarchy)\n return hierarchy.name;\n };\n ScriptInputColumnNameVisitor.getNameForProperty = function (pattern, federatedSchema) {\n debug.assertValue(pattern, 'pattern');\n var schema = federatedSchema.schema(pattern.schema), property = schema.findProperty(pattern.entity, pattern.name);\n if (property)\n return property.name;\n };\n ScriptInputColumnNameVisitor.getVariationLevelName = function (pattern, federatedSchema) {\n debug.assertValue(pattern, 'pattern');\n var source = pattern.source;\n var prop = federatedSchema.schema(source.schema).findProperty(source.entity, source.name);\n if (!prop)\n return;\n var variations = prop.column.variations;\n for (var _i = 0, variations_1 = variations; _i < variations_1.length; _i++) {\n var variation = variations_1[_i];\n if (variation.name === pattern.variationName)\n for (var _a = 0, _b = variation.defaultHierarchy.levels; _a < _b.length; _a++) {\n var level = _b[_a];\n if (level.name === pattern.level.level)\n return level.column.name;\n }\n }\n };\n return ScriptInputColumnNameVisitor;\n }());\n })(ScriptResultUtil = powerbi.ScriptResultUtil || (powerbi.ScriptResultUtil = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var segmentation;\n (function (segmentation) {\n var DataViewMerger;\n (function (DataViewMerger) {\n function mergeDataViews(source, segment) {\n if (!powerbi.DataViewAnalysis.isMetadataEquivalent(source.metadata, segment.metadata)) {\n debug.assertFail(\"Cannot merge data views with different metadata columns\");\n }\n // The last segment is complete. We mark the source as complete.\n if (!segment.metadata.segment)\n delete source.metadata.segment;\n if (source.table && segment.table)\n mergeTables(source.table, segment.table);\n if (source.categorical && segment.categorical)\n mergeCategorical(source.categorical, segment.categorical);\n // Tree cannot support subtotals hence we can get into situations\n // where a node has no children in one segment and more than 1 child\n // in another segment.\n if (source.tree && segment.tree)\n mergeTreeNodes(source.tree.root, segment.tree.root, true /*allowDifferentStructure*/);\n if (source.matrix && segment.matrix)\n mergeTreeNodes(source.matrix.rows.root, segment.matrix.rows.root, false /*allowDifferentStructure*/);\n }\n DataViewMerger.mergeDataViews = mergeDataViews;\n /** Note: Public for testability */\n function mergeTables(source, segment) {\n debug.assertValue(source, 'source');\n debug.assertValue(segment, 'segment');\n if (_.isEmpty(segment.rows))\n return;\n var mergeIndex = segment.lastMergeIndex + 1;\n merge(source.rows, segment.rows, mergeIndex);\n debug.assert(!source.identity === !segment.identity, 'The existence of identity in the new segment is different than the source');\n if (segment.identity)\n merge(source.identity, segment.identity, mergeIndex);\n }\n DataViewMerger.mergeTables = mergeTables;\n /**\n * Merge categories values and identities\n *\n * Note: Public for testability\n */\n function mergeCategorical(source, segment) {\n debug.assertValue(source, 'source');\n debug.assertValue(segment, 'segment');\n // Merge categories values and identities\n if (source.categories && segment.categories) {\n var segmentCategoriesLength = segment.categories.length;\n debug.assert(source.categories.length === segmentCategoriesLength, \"Source and segment categories have different lengths.\");\n for (var categoryIndex = 0; categoryIndex < segmentCategoriesLength; categoryIndex++) {\n var segmentCategory = segment.categories[categoryIndex];\n var sourceCategory = source.categories[categoryIndex];\n debug.assert(powerbi.DataViewAnalysis.areMetadataColumnsEquivalent(sourceCategory.source, segmentCategory.source), \"Source and segment category have different sources.\");\n debug.assert(_.isUndefined(sourceCategory.values) ? _.isUndefined(sourceCategory.identity) : true, 'Source category is missing values but has identities.');\n var mergeIndex = segment.lastMergeIndex + 1;\n if (segmentCategory.values) {\n merge(sourceCategory.values, segmentCategory.values, mergeIndex);\n }\n if (segmentCategory.identity) {\n merge(sourceCategory.identity, segmentCategory.identity, mergeIndex);\n }\n }\n }\n // Merge values for each value column\n if (source.values && segment.values) {\n var segmentValuesLength = segment.values.length;\n debug.assert(source.values.length === segmentValuesLength, \"Source and segment values have different lengths.\");\n for (var valueIndex = 0; valueIndex < segmentValuesLength; valueIndex++) {\n var segmentValue = segment.values[valueIndex];\n var sourceValue = source.values[valueIndex];\n debug.assert(powerbi.DataViewAnalysis.areMetadataColumnsEquivalent(sourceValue.source, segmentValue.source), \"Source and segment value have different sources.\");\n if (!sourceValue.values && segmentValue.values) {\n sourceValue.values = [];\n }\n var mergeIndex = segment.lastMergeIndex + 1;\n if (segmentValue.values) {\n merge(sourceValue.values, segmentValue.values, mergeIndex);\n }\n if (segmentValue.highlights) {\n merge(sourceValue.highlights, segmentValue.highlights, mergeIndex);\n }\n }\n }\n }\n DataViewMerger.mergeCategorical = mergeCategorical;\n /**\n * Merges the segment array starting at the specified index into the source array\n * and returns the segment slice that wasn't merged.\n * The segment array is spliced up to specified index in the process.\n */\n function merge(source, segment, index) {\n if (index >= segment.length)\n return segment;\n var result = [];\n if (index !== undefined)\n result = segment.splice(0, index);\n Array.prototype.push.apply(source, segment);\n return result;\n }\n /** Note: Public for testability */\n function mergeTreeNodes(sourceRoot, segmentRoot, allowDifferentStructure) {\n debug.assertValue(sourceRoot, 'sourceRoot');\n debug.assertValue(segmentRoot, 'segmentRoot');\n if (!segmentRoot.children || segmentRoot.children.length === 0)\n return;\n if (allowDifferentStructure && (!sourceRoot.children || sourceRoot.children.length === 0)) {\n sourceRoot.children = segmentRoot.children;\n return;\n }\n debug.assert(sourceRoot.children && sourceRoot.children.length >= 0, \"Source tree has different structure than segment.\");\n var firstAppendIndex = findFirstAppendIndex(segmentRoot.children);\n var lastSourceChild = sourceRoot.children[sourceRoot.children.length - 1];\n var mergedChildren = merge(sourceRoot.children, segmentRoot.children, firstAppendIndex);\n if (mergedChildren.length > 0)\n mergeTreeNodes(lastSourceChild, mergedChildren[mergedChildren.length - 1], allowDifferentStructure);\n }\n DataViewMerger.mergeTreeNodes = mergeTreeNodes;\n function findFirstAppendIndex(children) {\n if (children.length === 0)\n return 0;\n var i = 0;\n for (; i < children.length; i++) {\n var childSegment = children[i];\n if (!childSegment.isMerge)\n break;\n }\n return i;\n }\n })(DataViewMerger = segmentation.DataViewMerger || (segmentation.DataViewMerger = {}));\n })(segmentation = data.segmentation || (data.segmentation = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n /** Rewrites an expression tree, including all descendant nodes. */\n var SQExprRewriter = (function () {\n function SQExprRewriter() {\n }\n SQExprRewriter.prototype.visitColumnRef = function (expr) {\n var origArg = expr.source, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return expr;\n return new data.SQColumnRefExpr(rewrittenArg, expr.ref);\n };\n SQExprRewriter.prototype.visitMeasureRef = function (expr) {\n var origArg = expr.source, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return expr;\n return new data.SQMeasureRefExpr(rewrittenArg, expr.ref);\n };\n SQExprRewriter.prototype.visitAggr = function (expr) {\n var origArg = expr.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return expr;\n return new data.SQAggregationExpr(rewrittenArg, expr.func);\n };\n SQExprRewriter.prototype.visitSelectRef = function (expr) {\n return expr;\n };\n SQExprRewriter.prototype.visitPercentile = function (expr) {\n var origArg = expr.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return expr;\n return new data.SQPercentileExpr(rewrittenArg, expr.k, expr.exclusive);\n };\n SQExprRewriter.prototype.visitHierarchy = function (expr) {\n var origArg = expr.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return expr;\n return new data.SQHierarchyExpr(rewrittenArg, expr.hierarchy);\n };\n SQExprRewriter.prototype.visitHierarchyLevel = function (expr) {\n var origArg = expr.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return expr;\n return new data.SQHierarchyLevelExpr(rewrittenArg, expr.level);\n };\n SQExprRewriter.prototype.visitPropertyVariationSource = function (expr) {\n var origArg = expr.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return expr;\n return new data.SQPropertyVariationSourceExpr(rewrittenArg, expr.name, expr.property);\n };\n SQExprRewriter.prototype.visitEntity = function (expr) {\n return expr;\n };\n SQExprRewriter.prototype.visitAnd = function (orig) {\n var origLeft = orig.left, rewrittenLeft = origLeft.accept(this), origRight = orig.right, rewrittenRight = origRight.accept(this);\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\n return orig;\n return new data.SQAndExpr(rewrittenLeft, rewrittenRight);\n };\n SQExprRewriter.prototype.visitBetween = function (orig) {\n var origArg = orig.arg, rewrittenArg = origArg.accept(this), origLower = orig.lower, rewrittenLower = origLower.accept(this), origUpper = orig.upper, rewrittenUpper = origUpper.accept(this);\n if (origArg === rewrittenArg && origLower === rewrittenLower && origUpper === rewrittenUpper)\n return orig;\n return new data.SQBetweenExpr(rewrittenArg, rewrittenLower, rewrittenUpper);\n };\n SQExprRewriter.prototype.visitIn = function (orig) {\n var origArgs = orig.args, rewrittenArgs = this.rewriteAll(origArgs), origValues = orig.values, rewrittenValues;\n for (var i = 0, len = origValues.length; i < len; i++) {\n var origValueTuple = origValues[i], rewrittenValueTuple = this.rewriteAll(origValueTuple);\n if (origValueTuple !== rewrittenValueTuple && !rewrittenValues)\n rewrittenValues = ArrayExtensions.take(origValues, i);\n if (rewrittenValues)\n rewrittenValues.push(rewrittenValueTuple);\n }\n if (origArgs === rewrittenArgs && !rewrittenValues)\n return orig;\n return new data.SQInExpr(rewrittenArgs, rewrittenValues || origValues);\n };\n SQExprRewriter.prototype.rewriteAll = function (origExprs) {\n debug.assertValue(origExprs, 'origExprs');\n var rewrittenResult;\n for (var i = 0, len = origExprs.length; i < len; i++) {\n var origExpr = origExprs[i], rewrittenExpr = origExpr.accept(this);\n if (origExpr !== rewrittenExpr && !rewrittenResult)\n rewrittenResult = ArrayExtensions.take(origExprs, i);\n if (rewrittenResult)\n rewrittenResult.push(rewrittenExpr);\n }\n return rewrittenResult || origExprs;\n };\n SQExprRewriter.prototype.visitOr = function (orig) {\n var origLeft = orig.left, rewrittenLeft = origLeft.accept(this), origRight = orig.right, rewrittenRight = origRight.accept(this);\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\n return orig;\n return new data.SQOrExpr(rewrittenLeft, rewrittenRight);\n };\n SQExprRewriter.prototype.visitCompare = function (orig) {\n var origLeft = orig.left, rewrittenLeft = origLeft.accept(this), origRight = orig.right, rewrittenRight = origRight.accept(this);\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\n return orig;\n return new data.SQCompareExpr(orig.comparison, rewrittenLeft, rewrittenRight);\n };\n SQExprRewriter.prototype.visitContains = function (orig) {\n var origLeft = orig.left, rewrittenLeft = origLeft.accept(this), origRight = orig.right, rewrittenRight = origRight.accept(this);\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\n return orig;\n return new data.SQContainsExpr(rewrittenLeft, rewrittenRight);\n };\n SQExprRewriter.prototype.visitExists = function (orig) {\n var origArg = orig.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return orig;\n return new data.SQExistsExpr(rewrittenArg);\n };\n SQExprRewriter.prototype.visitNot = function (orig) {\n var origArg = orig.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return orig;\n return new data.SQNotExpr(rewrittenArg);\n };\n SQExprRewriter.prototype.visitStartsWith = function (orig) {\n var origLeft = orig.left, rewrittenLeft = origLeft.accept(this), origRight = orig.right, rewrittenRight = origRight.accept(this);\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\n return orig;\n return new data.SQStartsWithExpr(rewrittenLeft, rewrittenRight);\n };\n SQExprRewriter.prototype.visitConstant = function (expr) {\n return expr;\n };\n SQExprRewriter.prototype.visitDateSpan = function (orig) {\n var origArg = orig.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return orig;\n return new data.SQDateSpanExpr(orig.unit, rewrittenArg);\n };\n SQExprRewriter.prototype.visitDateAdd = function (orig) {\n var origArg = orig.arg, rewrittenArg = origArg.accept(this);\n if (origArg === rewrittenArg)\n return orig;\n return new data.SQDateAddExpr(orig.unit, orig.amount, rewrittenArg);\n };\n SQExprRewriter.prototype.visitNow = function (orig) {\n return orig;\n };\n SQExprRewriter.prototype.visitDefaultValue = function (orig) {\n return orig;\n };\n SQExprRewriter.prototype.visitAnyValue = function (orig) {\n return orig;\n };\n SQExprRewriter.prototype.visitArithmetic = function (orig) {\n var origLeft = orig.left, rewrittenLeft = origLeft.accept(this), origRight = orig.right, rewrittenRight = origRight.accept(this);\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\n return orig;\n return new data.SQArithmeticExpr(rewrittenLeft, rewrittenRight, orig.operator);\n };\n SQExprRewriter.prototype.visitScopedEval = function (orig) {\n var origExpression = orig.expression, rewrittenExpression = origExpression.accept(this), origScope = orig.scope, rewrittenScope = this.rewriteAll(origScope);\n if (origExpression === rewrittenExpression && origScope === rewrittenScope)\n return orig;\n return new data.SQScopedEvalExpr(rewrittenExpression, rewrittenScope);\n };\n SQExprRewriter.prototype.visitFillRule = function (orig) {\n var origInput = orig.input, rewrittenInput = origInput.accept(this);\n var origRule = orig.rule;\n var origGradient2 = origRule.linearGradient2, rewrittenGradient2 = origGradient2;\n if (origGradient2) {\n rewrittenGradient2 = this.visitLinearGradient2(origGradient2);\n }\n var origGradient3 = origRule.linearGradient3, rewrittenGradient3 = origGradient3;\n if (origGradient3) {\n rewrittenGradient3 = this.visitLinearGradient3(origGradient3);\n }\n if (origInput !== rewrittenInput ||\n origGradient2 !== rewrittenGradient2 ||\n origGradient3 !== rewrittenGradient3) {\n var rewrittenRule = {};\n if (rewrittenGradient2)\n rewrittenRule.linearGradient2 = rewrittenGradient2;\n if (rewrittenGradient3)\n rewrittenRule.linearGradient3 = rewrittenGradient3;\n return new data.SQFillRuleExpr(rewrittenInput, rewrittenRule);\n }\n return orig;\n };\n SQExprRewriter.prototype.visitLinearGradient2 = function (origGradient2) {\n debug.assertValue(origGradient2, 'origGradient2');\n var origMin = origGradient2.min, rewrittenMin = this.visitFillRuleStop(origMin), origMax = origGradient2.max, rewrittenMax = this.visitFillRuleStop(origMax);\n if (origMin !== rewrittenMin || origMax !== rewrittenMax) {\n return {\n min: rewrittenMin,\n max: rewrittenMax,\n };\n }\n return origGradient2;\n };\n SQExprRewriter.prototype.visitLinearGradient3 = function (origGradient3) {\n debug.assertValue(origGradient3, 'origGradient3');\n var origMin = origGradient3.min, rewrittenMin = this.visitFillRuleStop(origMin), origMid = origGradient3.mid, rewrittenMid = this.visitFillRuleStop(origMid), origMax = origGradient3.max, rewrittenMax = this.visitFillRuleStop(origMax);\n if (origMin !== rewrittenMin || origMid !== rewrittenMid || origMax !== rewrittenMax) {\n return {\n min: rewrittenMin,\n mid: rewrittenMid,\n max: rewrittenMax,\n };\n }\n return origGradient3;\n };\n SQExprRewriter.prototype.visitFillRuleStop = function (stop) {\n debug.assertValue(stop, 'stop');\n var origColor = stop.color, rewrittenColor = stop.color.accept(this);\n var origValue = stop.value, rewrittenValue = origValue;\n if (origValue)\n rewrittenValue = origValue.accept(this);\n if (origColor !== rewrittenColor || origValue !== rewrittenValue) {\n var rewrittenStop = {\n color: rewrittenColor\n };\n if (rewrittenValue)\n rewrittenStop.value = rewrittenValue;\n return rewrittenStop;\n }\n return stop;\n };\n SQExprRewriter.prototype.visitResourcePackageItem = function (orig) {\n return orig;\n };\n return SQExprRewriter;\n }());\n data.SQExprRewriter = SQExprRewriter;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n /** Responsible for writing equality comparisons against a field to an SQInExpr. */\n var EqualsToInRewriter;\n (function (EqualsToInRewriter) {\n function run(expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(new Rewriter());\n }\n EqualsToInRewriter.run = run;\n var Rewriter = (function (_super) {\n __extends(Rewriter, _super);\n function Rewriter() {\n _super.call(this);\n }\n Rewriter.prototype.visitCompare = function (expr) {\n if (expr.comparison !== data.QueryComparisonKind.Equal)\n return this.visitUnsupported(expr);\n if (!this.isSupported(expr.left) || !this.isSupported(expr.right))\n return this.visitUnsupported(expr);\n var leftIsComparand = this.isComparand(expr.left);\n var rightIsComparand = this.isComparand(expr.right);\n if (leftIsComparand === rightIsComparand)\n return this.visitUnsupported(expr);\n var operand = leftIsComparand\n ? expr.left\n : expr.right;\n var value = leftIsComparand\n ? expr.right\n : expr.left;\n var current = this.current;\n if (!current) {\n return data.SQExprBuilder.inExpr([operand], [[value]]);\n }\n current.add(operand, value);\n return expr;\n };\n Rewriter.prototype.visitOr = function (expr) {\n if (!this.isSupported(expr.left) || !this.isSupported(expr.right))\n return this.visitUnsupported(expr);\n var current;\n if (!this.current) {\n current = this.current = new InBuilder();\n }\n expr.left.accept(this);\n expr.right.accept(this);\n if (current) {\n this.current = null;\n return current.complete() || expr;\n }\n return expr;\n };\n Rewriter.prototype.visitAnd = function (expr) {\n if (!this.isSupported(expr.left) || !this.isSupported(expr.right))\n return this.visitUnsupported(expr);\n var current = this.current;\n if (current) {\n // NOTE: Composite keys are not supported by this algorithm.\n current.cancel();\n return expr;\n }\n return _super.prototype.visitAnd.call(this, expr);\n };\n Rewriter.prototype.visitUnsupported = function (expr) {\n var current = this.current;\n if (current)\n current.cancel();\n return expr;\n };\n Rewriter.prototype.isSupported = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr instanceof data.SQCompareExpr\n || expr instanceof data.SQColumnRefExpr\n || expr instanceof data.SQConstantExpr\n || expr instanceof data.SQHierarchyLevelExpr\n || expr instanceof data.SQOrExpr\n || expr instanceof data.SQAndExpr;\n };\n Rewriter.prototype.isComparand = function (expr) {\n return expr instanceof data.SQColumnRefExpr\n || expr instanceof data.SQHierarchyLevelExpr;\n };\n return Rewriter;\n }(data.SQExprRewriter));\n var InBuilder = (function () {\n function InBuilder() {\n }\n InBuilder.prototype.add = function (operand, value) {\n debug.assertValue(operand, 'operand');\n debug.assertValue(value, 'value');\n if (this.cancelled)\n return;\n if (this.operand && !data.SQExpr.equals(operand, this.operand)) {\n this.cancel();\n return;\n }\n this.operand = operand;\n var values = this.values;\n if (!values)\n values = this.values = [];\n values.push(value);\n };\n InBuilder.prototype.cancel = function () {\n this.cancelled = true;\n };\n InBuilder.prototype.complete = function () {\n if (this.cancelled || !this.operand)\n return;\n return data.SQExprBuilder.inExpr([this.operand], _.map(this.values, function (v) { return [v]; }));\n };\n return InBuilder;\n }());\n })(EqualsToInRewriter = data.EqualsToInRewriter || (data.EqualsToInRewriter = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var SQExprConverter;\n (function (SQExprConverter) {\n function asScopeIdsContainer(filter, fieldSQExprs) {\n debug.assertValue(filter, 'filter');\n debug.assertValue(fieldSQExprs, 'fieldSQExprs');\n debug.assert(fieldSQExprs.length > 0, 'There should be at least 1 field expression.');\n var filterItems = filter.conditions();\n debug.assert(filterItems.length === 1, 'There should be exactly 1 filter expression.');\n var filterItem = filterItems[0];\n if (filterItem) {\n var visitor = new FilterScopeIdsCollectorVisitor(fieldSQExprs);\n if (filterItem.accept(visitor))\n return visitor.getResult();\n }\n }\n SQExprConverter.asScopeIdsContainer = asScopeIdsContainer;\n /** Gets a comparand value from the given DataViewScopeIdentity. */\n function getFirstComparandValue(identity) {\n debug.assertValue(identity, 'identity');\n var comparandExpr = identity.expr.accept(new FindComparandVisitor());\n if (comparandExpr)\n return comparandExpr.value;\n }\n SQExprConverter.getFirstComparandValue = getFirstComparandValue;\n })(SQExprConverter = data.SQExprConverter || (data.SQExprConverter = {}));\n /** Collect filter values from simple semantic filter that is similar to 'is any of' or 'is not any of', getResult() returns a collection of scopeIds.**/\n var FilterScopeIdsCollectorVisitor = (function (_super) {\n __extends(FilterScopeIdsCollectorVisitor, _super);\n function FilterScopeIdsCollectorVisitor(fieldSQExprs) {\n _super.call(this);\n this.isRoot = true;\n this.isNot = false;\n this.keyExprsCount = null;\n this.valueExprs = [];\n // Need to drop the entitylet before create the scopeIdentity. The ScopeIdentity created on the client is used to\n // compare the ScopeIdentity came from the server. But server doesn't have the entity variable concept, so we will\n // need to drop it in order to use JsonComparer.\n this.fieldExprs = [];\n for (var _i = 0, fieldSQExprs_1 = fieldSQExprs; _i < fieldSQExprs_1.length; _i++) {\n var field = fieldSQExprs_1[_i];\n this.fieldExprs.push(data.SQExprBuilder.removeEntityVariables(field));\n }\n }\n FilterScopeIdsCollectorVisitor.prototype.getResult = function () {\n debug.assert(this.fieldExprs.length > 0, 'fieldExprs has at least one fieldExpr');\n var valueExprs = this.valueExprs, scopeIds = [];\n var valueCount = this.keyExprsCount || 1;\n for (var startIndex = 0, endIndex = valueCount, len = valueExprs.length; startIndex < len && endIndex <= len;) {\n var values = valueExprs.slice(startIndex, endIndex);\n var scopeId = FilterScopeIdsCollectorVisitor.getScopeIdentity(this.fieldExprs, values);\n if (!jsCommon.ArrayExtensions.isInArray(scopeIds, scopeId, powerbi.DataViewScopeIdentity.equals))\n scopeIds.push(scopeId);\n startIndex += valueCount;\n endIndex += valueCount;\n }\n return {\n isNot: this.isNot,\n scopeIds: scopeIds,\n };\n };\n FilterScopeIdsCollectorVisitor.getScopeIdentity = function (fieldExprs, valueExprs) {\n debug.assert(valueExprs.length > 0, 'valueExprs has at least one valueExpr');\n debug.assert(valueExprs.length === fieldExprs.length, 'fieldExpr and valueExpr count should match');\n var compoundSQExpr;\n for (var i = 0, len = fieldExprs.length; i < len; i++) {\n var equalsExpr = data.SQExprBuilder.equal(fieldExprs[i], valueExprs[i]);\n if (!compoundSQExpr)\n compoundSQExpr = equalsExpr;\n else\n compoundSQExpr = data.SQExprBuilder.and(compoundSQExpr, equalsExpr);\n }\n return data.createDataViewScopeIdentity(compoundSQExpr);\n };\n FilterScopeIdsCollectorVisitor.prototype.visitOr = function (expr) {\n if (this.keyExprsCount !== null)\n return this.unsupportedSQExpr();\n this.isRoot = false;\n return expr.left.accept(this) && expr.right.accept(this);\n };\n FilterScopeIdsCollectorVisitor.prototype.visitNot = function (expr) {\n if (!this.isRoot)\n return this.unsupportedSQExpr();\n this.isNot = true;\n return expr.arg.accept(this);\n };\n FilterScopeIdsCollectorVisitor.prototype.visitConstant = function (expr) {\n if (this.isRoot && expr.type.primitiveType === powerbi.PrimitiveType.Null)\n return this.unsupportedSQExpr();\n this.valueExprs.push(expr);\n return true;\n };\n FilterScopeIdsCollectorVisitor.prototype.visitCompare = function (expr) {\n if (this.keyExprsCount !== null)\n return this.unsupportedSQExpr();\n this.isRoot = false;\n if (expr.comparison !== data.QueryComparisonKind.Equal)\n return this.unsupportedSQExpr();\n return expr.left.accept(this) && expr.right.accept(this);\n };\n FilterScopeIdsCollectorVisitor.prototype.visitIn = function (expr) {\n this.keyExprsCount = 0;\n var result;\n this.isRoot = false;\n for (var _i = 0, _a = expr.args; _i < _a.length; _i++) {\n var arg = _a[_i];\n result = arg.accept(this);\n if (!result)\n return this.unsupportedSQExpr();\n this.keyExprsCount++;\n }\n if (this.keyExprsCount !== this.fieldExprs.length)\n return this.unsupportedSQExpr();\n var values = expr.values;\n for (var _b = 0, values_1 = values; _b < values_1.length; _b++) {\n var valueTuple = values_1[_b];\n var jlen = valueTuple.length;\n debug.assert(jlen === this.keyExprsCount, \"keys count and values count should match\");\n for (var _c = 0, valueTuple_1 = valueTuple; _c < valueTuple_1.length; _c++) {\n var value = valueTuple_1[_c];\n result = value.accept(this);\n if (!result)\n return this.unsupportedSQExpr();\n }\n }\n return result;\n };\n FilterScopeIdsCollectorVisitor.prototype.visitColumnRef = function (expr) {\n if (this.isRoot)\n return this.unsupportedSQExpr();\n var fixedExpr = data.SQExprBuilder.removeEntityVariables(expr);\n if (this.keyExprsCount !== null)\n return data.SQExpr.equals(this.fieldExprs[this.keyExprsCount], fixedExpr);\n return data.SQExpr.equals(this.fieldExprs[0], fixedExpr);\n };\n FilterScopeIdsCollectorVisitor.prototype.visitDefaultValue = function (expr) {\n if (this.isRoot || this.keyExprsCount !== null)\n return this.unsupportedSQExpr();\n this.valueExprs.push(expr);\n return true;\n };\n FilterScopeIdsCollectorVisitor.prototype.visitAnyValue = function (expr) {\n if (this.isRoot || this.keyExprsCount !== null)\n return this.unsupportedSQExpr();\n this.valueExprs.push(expr);\n return true;\n };\n FilterScopeIdsCollectorVisitor.prototype.visitDefault = function (expr) {\n return this.unsupportedSQExpr();\n };\n FilterScopeIdsCollectorVisitor.prototype.unsupportedSQExpr = function () {\n return false;\n };\n return FilterScopeIdsCollectorVisitor;\n }(data.DefaultSQExprVisitor));\n var FindComparandVisitor = (function (_super) {\n __extends(FindComparandVisitor, _super);\n function FindComparandVisitor() {\n _super.apply(this, arguments);\n }\n FindComparandVisitor.prototype.visitAnd = function (expr) {\n return expr.left.accept(this) || expr.right.accept(this);\n };\n FindComparandVisitor.prototype.visitCompare = function (expr) {\n if (expr.comparison === data.QueryComparisonKind.Equal) {\n if (expr.right instanceof data.SQConstantExpr)\n return expr.right;\n if (expr.left instanceof data.SQConstantExpr)\n return expr.left;\n }\n };\n return FindComparandVisitor;\n }(data.DefaultSQExprVisitor));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n /** Recognizes DataViewScopeIdentity expression trees to extract comparison keys. */\n var ScopeIdentityExtractor;\n (function (ScopeIdentityExtractor) {\n function getKeys(expr) {\n var extractor = new ScopeIdExtractorImpl();\n expr.accept(extractor);\n if (extractor.malformed)\n return null;\n return ArrayExtensions.emptyToNull(extractor.keys);\n }\n ScopeIdentityExtractor.getKeys = getKeys;\n function getInExpr(expr) {\n var extractor = new ScopeIdExtractorImpl();\n expr.accept(extractor);\n if (extractor.malformed)\n return;\n var keys = ArrayExtensions.emptyToNull(extractor.keys);\n var keyValues = ArrayExtensions.emptyToNull(extractor.values);\n if (keys && keyValues)\n return data.SQExprBuilder.inExpr(keys, [keyValues]);\n }\n ScopeIdentityExtractor.getInExpr = getInExpr;\n /**\n * Recognizes expressions of the form:\n * 1) Equals(ColRef, Constant)\n * 2) And(Equals(ColRef1, Constant1), Equals(ColRef2, Constant2))\n * or And(And(Equals(ColRef1, Constant1), Equals(ColRef2, Constant2)), Equals(ColRef3, Constant3)) etc..\n */\n var ScopeIdExtractorImpl = (function (_super) {\n __extends(ScopeIdExtractorImpl, _super);\n function ScopeIdExtractorImpl() {\n _super.apply(this, arguments);\n this.keys = [];\n this.values = [];\n }\n ScopeIdExtractorImpl.prototype.visitAnd = function (expr) {\n expr.left.accept(this);\n expr.right.accept(this);\n };\n ScopeIdExtractorImpl.prototype.visitCompare = function (expr) {\n if (expr.comparison !== data.QueryComparisonKind.Equal) {\n this.visitDefault(expr);\n return;\n }\n debug.assert(expr.left instanceof data.SQExpr && expr.right instanceof data.SQConstantExpr, 'invalid compare expr operands');\n expr.left.accept(this);\n expr.right.accept(this);\n };\n ScopeIdExtractorImpl.prototype.visitColumnRef = function (expr) {\n this.keys.push(expr);\n };\n ScopeIdExtractorImpl.prototype.visitHierarchyLevel = function (expr) {\n this.keys.push(expr);\n };\n ScopeIdExtractorImpl.prototype.visitConstant = function (expr) {\n this.values.push(expr);\n };\n ScopeIdExtractorImpl.prototype.visitArithmetic = function (expr) {\n this.keys.push(expr);\n };\n ScopeIdExtractorImpl.prototype.visitDefault = function (expr) {\n this.malformed = true;\n };\n return ScopeIdExtractorImpl;\n }(data.DefaultSQExprVisitor));\n })(ScopeIdentityExtractor = data.ScopeIdentityExtractor || (data.ScopeIdentityExtractor = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var PrimitiveValueEncoding;\n (function (PrimitiveValueEncoding) {\n var SingleQuoteRegex = /'/g;\n function decimal(value) {\n debug.assertValue(value, 'value');\n return value + 'M';\n }\n PrimitiveValueEncoding.decimal = decimal;\n function double(value) {\n debug.assertValue(value, 'value');\n return value + 'D';\n }\n PrimitiveValueEncoding.double = double;\n function integer(value) {\n debug.assertValue(value, 'value');\n return value + 'L';\n }\n PrimitiveValueEncoding.integer = integer;\n function dateTime(value) {\n debug.assertValue(value, 'value');\n // Currently, server doesn't support timezone. All date time data on the server don't have time zone information.\n // So, when we construct a dateTime object on the client, we will need to ignor user's time zone and force it to be UTC time.\n // When we subtract the timeZone offset, the date time object will remain the same value as you entered but dropped the local timeZone.\n var date = new Date(value.getTime() - (value.getTimezoneOffset() * 60000));\n var dateTimeString = date.toISOString();\n // If it ends with Z, we want to get rid of it, because with trailing Z, it will assume the dateTime is UTC, but we don't want any timeZone information, so\n // we will drop it.\n // Also, we need to add Prefix and Suffix to match the dsr value format for dateTime object.\n if (jsCommon.StringExtensions.endsWith(dateTimeString, 'Z'))\n dateTimeString = dateTimeString.substr(0, dateTimeString.length - 1);\n return \"datetime'\" + dateTimeString + \"'\";\n }\n PrimitiveValueEncoding.dateTime = dateTime;\n function text(value) {\n debug.assertValue(value, 'value');\n return \"'\" + value.replace(SingleQuoteRegex, \"''\") + \"'\";\n }\n PrimitiveValueEncoding.text = text;\n function nullEncoding() {\n return 'null';\n }\n PrimitiveValueEncoding.nullEncoding = nullEncoding;\n function boolean(value) {\n return value ? 'true' : 'false';\n }\n PrimitiveValueEncoding.boolean = boolean;\n })(PrimitiveValueEncoding = data.PrimitiveValueEncoding || (data.PrimitiveValueEncoding = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var Agg = powerbi.data.QueryAggregateFunction;\n function createSQAggregationOperations(datetimeMinMaxSupported) {\n return new SQAggregationOperations(datetimeMinMaxSupported);\n }\n data.createSQAggregationOperations = createSQAggregationOperations;\n var SQAggregationOperations = (function () {\n function SQAggregationOperations(datetimeMinMaxSupported) {\n this.datetimeMinMaxSupported = datetimeMinMaxSupported;\n }\n SQAggregationOperations.prototype.getSupportedAggregates = function (expr, schema, targetTypes) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(schema, 'schema');\n debug.assertAnyValue(targetTypes, 'targetTypes');\n var metadata = getMetadataForUnderlyingType(expr, schema);\n // don't use expr.validate as validate will be using this function and we end up in a recursive loop\n if (!metadata)\n return [];\n var valueType = metadata.type, fieldKind = metadata.kind, isPropertyIdentity = metadata.idOnEntityKey;\n if (!valueType)\n return [];\n // Cannot aggregate on model measures\n if (fieldKind === 1 /* Measure */)\n return [];\n if (valueType.numeric || valueType.integer) {\n var aggregates_1 = [Agg.Sum, Agg.Avg, Agg.Min, Agg.Max, Agg.Count, Agg.CountNonNull, Agg.StandardDeviation, Agg.Variance];\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n var currentSchema = schema.schema(fieldExprItem.schema);\n if (currentSchema.capabilities.supportsMedian)\n aggregates_1.push(Agg.Median);\n return aggregates_1;\n }\n var aggregates = [];\n // Min/Max of DateTime\n if (this.datetimeMinMaxSupported &&\n valueType.dateTime &&\n (_.isEmpty(targetTypes) || powerbi.ValueType.isCompatibleTo(valueType, targetTypes))) {\n aggregates.push(Agg.Min);\n aggregates.push(Agg.Max);\n }\n // The supported aggregation types for an identity field are restricted to 'Count Non-Null' (e.g. for the field well aggregation options)\n // but a valid semantic query can return a less-restricted aggregation option which we should honor. (e.g. this results from Q&A)\n var distinctCountAggExists = data.SQExprInfo.getAggregate(expr) === Agg.Count;\n if (!(isPropertyIdentity && !distinctCountAggExists))\n aggregates.push(Agg.Count);\n aggregates.push(Agg.CountNonNull);\n return aggregates;\n };\n SQAggregationOperations.prototype.isSupportedAggregate = function (expr, schema, aggregate, targetTypes) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(schema, 'schema');\n var supportedAggregates = this.getSupportedAggregates(expr, schema, targetTypes);\n return _.contains(supportedAggregates, aggregate);\n };\n SQAggregationOperations.prototype.createExprWithAggregate = function (expr, schema, aggregateNonNumericFields, targetTypes, preferredAggregate) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(schema, 'schema');\n var aggregate;\n if (preferredAggregate != null && this.isSupportedAggregate(expr, schema, preferredAggregate, targetTypes)) {\n aggregate = preferredAggregate;\n }\n else {\n aggregate = expr.getDefaultAggregate(schema, aggregateNonNumericFields);\n }\n if (aggregate !== undefined)\n expr = data.SQExprBuilder.aggregate(expr, aggregate);\n return expr;\n };\n return SQAggregationOperations;\n }());\n function getMetadataForUnderlyingType(expr, schema) {\n // Unwrap the aggregate (if the expr has one), and look at the underlying type.\n var metadata = data.SQExprBuilder.removeAggregate(expr).getMetadata(schema);\n if (!metadata)\n metadata = expr.getMetadata(schema);\n return metadata;\n }\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var SQHierarchyExprUtils;\n (function (SQHierarchyExprUtils) {\n function getConceptualHierarchyLevelFromExpr(conceptualSchema, fieldExpr) {\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n var hierarchyLevel = fieldExpr.hierarchyLevel || fieldExpr.hierarchyLevelAggr;\n if (hierarchyLevel)\n return SQHierarchyExprUtils.getConceptualHierarchyLevel(conceptualSchema, fieldExprItem.schema, fieldExprItem.entity, hierarchyLevel.name, hierarchyLevel.level);\n }\n SQHierarchyExprUtils.getConceptualHierarchyLevelFromExpr = getConceptualHierarchyLevelFromExpr;\n function getConceptualHierarchyLevel(conceptualSchema, schemaName, entity, hierarchy, hierarchyLevel) {\n var schema = conceptualSchema.schema(schemaName);\n var conceptualHierarchy = schema.findHierarchy(entity, hierarchy);\n if (conceptualHierarchy) {\n return conceptualHierarchy.levels.withName(hierarchyLevel);\n }\n }\n SQHierarchyExprUtils.getConceptualHierarchyLevel = getConceptualHierarchyLevel;\n function getConceptualHierarchy(sqExpr, federatedSchema) {\n if (sqExpr instanceof data.SQHierarchyExpr) {\n var hierarchy = sqExpr;\n if (sqExpr.arg instanceof data.SQEntityExpr) {\n var entityExpr = sqExpr.arg;\n return federatedSchema\n .schema(entityExpr.schema)\n .findHierarchy(entityExpr.entity, hierarchy.hierarchy);\n }\n else if (sqExpr.arg instanceof data.SQPropertyVariationSourceExpr) {\n var variationExpr = sqExpr.arg;\n var sourceEntityExpr = variationExpr.arg;\n return federatedSchema\n .schema(sourceEntityExpr.schema)\n .findHierarchyByVariation(sourceEntityExpr.entity, variationExpr.property, variationExpr.name, hierarchy.hierarchy);\n }\n }\n }\n SQHierarchyExprUtils.getConceptualHierarchy = getConceptualHierarchy;\n function expandExpr(schema, expr, suppressHierarchyLevelExpansion) {\n return SQExprHierarchyToHierarchyLevelConverter.convert(expr, schema) ||\n SQExprVariationConverter.expand(expr, schema) ||\n // If we are calling expandExpr from suppressHierarchyLevelExpansion, we should not expand the hierarchylevels\n (!suppressHierarchyLevelExpansion && SQExprHierarchyLevelConverter.expand(expr, schema)) ||\n expr;\n }\n SQHierarchyExprUtils.expandExpr = expandExpr;\n function isHierarchyOrVariation(schema, expr) {\n if (expr instanceof data.SQHierarchyExpr || expr instanceof data.SQHierarchyLevelExpr)\n return true;\n var conceptualProperty = expr.getConceptualProperty(schema);\n if (conceptualProperty) {\n var column = conceptualProperty.column;\n if (column && column.variations && column.variations.length > 0)\n return true;\n }\n return false;\n }\n SQHierarchyExprUtils.isHierarchyOrVariation = isHierarchyOrVariation;\n // Return column reference expression for hierarchy level expression.\n function getSourceVariationExpr(hierarchyLevelExpr) {\n var fieldExprPattern = data.SQExprConverter.asFieldPattern(hierarchyLevelExpr);\n if (fieldExprPattern.columnHierarchyLevelVariation) {\n var entity = data.SQExprBuilder.entity(fieldExprPattern.columnHierarchyLevelVariation.source.schema, fieldExprPattern.columnHierarchyLevelVariation.source.entity);\n return data.SQExprBuilder.columnRef(entity, fieldExprPattern.columnHierarchyLevelVariation.source.name);\n }\n }\n SQHierarchyExprUtils.getSourceVariationExpr = getSourceVariationExpr;\n // Return hierarchy expression for hierarchy level expression.\n function getSourceHierarchy(hierarchyLevelExpr) {\n var fieldExprPattern = data.SQExprConverter.asFieldPattern(hierarchyLevelExpr);\n var hierarchyLevel = fieldExprPattern.hierarchyLevel;\n if (hierarchyLevel) {\n var entity = data.SQExprBuilder.entity(hierarchyLevel.schema, hierarchyLevel.entity, hierarchyLevel.entityVar);\n return data.SQExprBuilder.hierarchy(entity, hierarchyLevel.name);\n }\n }\n SQHierarchyExprUtils.getSourceHierarchy = getSourceHierarchy;\n function getHierarchySourceAsVariationSource(hierarchyLevelExpr) {\n // Make sure the hierarchy level source is a hierarchy\n if (!(hierarchyLevelExpr.arg instanceof data.SQHierarchyExpr))\n return;\n // Check if the hierarchy source if a variation\n var hierarchyRef = hierarchyLevelExpr.arg;\n if (hierarchyRef.arg instanceof data.SQPropertyVariationSourceExpr)\n return hierarchyRef.arg;\n }\n SQHierarchyExprUtils.getHierarchySourceAsVariationSource = getHierarchySourceAsVariationSource;\n /**\n * Returns true if firstExpr and secondExpr are levels in the same hierarchy and firstExpr is before secondExpr in allLevels.\n */\n function areHierarchyLevelsOrdered(allLevels, firstExpr, secondExpr) {\n // Validate that both items hierarchy levels\n if (!(firstExpr instanceof data.SQHierarchyLevelExpr) || !(secondExpr instanceof data.SQHierarchyLevelExpr))\n return false;\n var firstLevel = firstExpr;\n var secondLevel = secondExpr;\n // Validate that both items belong to the same hierarchy\n if (!data.SQExpr.equals(firstLevel.arg, secondLevel.arg))\n return false;\n // Determine the order\n var firstIndex = data.SQExprUtils.indexOfExpr(allLevels, firstLevel);\n var secondIndex = data.SQExprUtils.indexOfExpr(allLevels, secondLevel);\n return firstIndex !== -1 && secondIndex !== -1 && firstIndex < secondIndex;\n }\n SQHierarchyExprUtils.areHierarchyLevelsOrdered = areHierarchyLevelsOrdered;\n /**\n * Given an ordered set of levels and an ordered subset of those levels, returns the index where\n * expr should be inserted into the subset to maintain the correct order.\n */\n function getInsertionIndex(allLevels, orderedSubsetOfLevels, expr) {\n var insertIndex = 0;\n // Loop through the supplied levels until the insertion would no longer be in the correct order\n while (insertIndex < orderedSubsetOfLevels.length &&\n areHierarchyLevelsOrdered(allLevels, orderedSubsetOfLevels[insertIndex], expr)) {\n insertIndex++;\n }\n return insertIndex;\n }\n SQHierarchyExprUtils.getInsertionIndex = getInsertionIndex;\n })(SQHierarchyExprUtils = data.SQHierarchyExprUtils || (data.SQHierarchyExprUtils = {}));\n var SQExprHierarchyToHierarchyLevelConverter;\n (function (SQExprHierarchyToHierarchyLevelConverter) {\n function convert(sqExpr, federatedSchema) {\n debug.assertValue(sqExpr, 'sqExpr');\n debug.assertValue(federatedSchema, 'federatedSchema');\n if (sqExpr instanceof data.SQHierarchyExpr) {\n var hierarchyExpr = sqExpr;\n var conceptualHierarchy = SQHierarchyExprUtils.getConceptualHierarchy(hierarchyExpr, federatedSchema);\n if (conceptualHierarchy)\n return _.map(conceptualHierarchy.levels, function (hierarchyLevel) { return data.SQExprBuilder.hierarchyLevel(sqExpr, hierarchyLevel.name); });\n }\n }\n SQExprHierarchyToHierarchyLevelConverter.convert = convert;\n })(SQExprHierarchyToHierarchyLevelConverter = data.SQExprHierarchyToHierarchyLevelConverter || (data.SQExprHierarchyToHierarchyLevelConverter = {}));\n var SQExprHierarchyLevelConverter;\n (function (SQExprHierarchyLevelConverter) {\n function expand(expr, schema) {\n debug.assertValue(expr, 'sqExpr');\n debug.assertValue(schema, 'federatedSchema');\n var exprs = [];\n if (expr instanceof data.SQHierarchyLevelExpr) {\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n if (fieldExpr.hierarchyLevel) {\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n var hierarchy = schema\n .schema(fieldExprItem.schema)\n .findHierarchy(fieldExprItem.entity, fieldExpr.hierarchyLevel.name);\n if (hierarchy) {\n var hierarchyLevels = hierarchy.levels;\n for (var _i = 0, hierarchyLevels_2 = hierarchyLevels; _i < hierarchyLevels_2.length; _i++) {\n var hierarchyLevel = hierarchyLevels_2[_i];\n if (hierarchyLevel.name === fieldExpr.hierarchyLevel.level) {\n exprs.push(expr);\n break;\n }\n else\n exprs.push(data.SQExprBuilder.hierarchyLevel(data.SQExprBuilder.hierarchy(data.SQExprBuilder.entity(fieldExprItem.schema, fieldExprItem.entity, fieldExprItem.entityVar), hierarchy.name), hierarchyLevel.name));\n }\n }\n }\n }\n if (!_.isEmpty(exprs))\n return exprs;\n }\n SQExprHierarchyLevelConverter.expand = expand;\n })(SQExprHierarchyLevelConverter || (SQExprHierarchyLevelConverter = {}));\n var SQExprVariationConverter;\n (function (SQExprVariationConverter) {\n function expand(expr, schema) {\n debug.assertValue(expr, 'sqExpr');\n debug.assertValue(schema, 'federatedSchema');\n var exprs;\n var conceptualProperty = expr.getConceptualProperty(schema);\n if (conceptualProperty) {\n var column = conceptualProperty.column;\n if (column && column.variations && column.variations.length > 0) {\n var variations = column.variations;\n // for SU11, we support only one variation\n debug.assert(variations.length === 1, \"variations.length\");\n var variation = variations[0];\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n exprs = [];\n if (variation.defaultHierarchy) {\n var hierarchyExpr = data.SQExprBuilder.hierarchy(data.SQExprBuilder.propertyVariationSource(data.SQExprBuilder.entity(fieldExprItem.schema, fieldExprItem.entity, fieldExprItem.entityVar), variation.name, conceptualProperty.name), variation.defaultHierarchy.name);\n for (var _i = 0, _a = variation.defaultHierarchy.levels; _i < _a.length; _i++) {\n var level = _a[_i];\n exprs.push(data.SQExprBuilder.hierarchyLevel(hierarchyExpr, level.name));\n }\n }\n }\n }\n return exprs;\n }\n SQExprVariationConverter.expand = expand;\n })(SQExprVariationConverter || (SQExprVariationConverter = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n ;\n var SQExprGroupUtils;\n (function (SQExprGroupUtils) {\n /** Group all projections. Eacch group can consist of either a single property, or a collection of hierarchy items. */\n function groupExprs(schema, exprs) {\n var groups = [];\n for (var i = 0, len = exprs.length; i < len; i++) {\n var expr = exprs[i];\n debug.assertValue(expr, \"Expression not found\");\n if (!(expr instanceof data.SQHierarchyLevelExpr)) {\n groups.push({ expr: expr, children: null, selectQueryIndex: i });\n }\n else {\n addChildToGroup(schema, groups, expr, i);\n }\n }\n return groups;\n }\n SQExprGroupUtils.groupExprs = groupExprs;\n function addChildToGroup(schema, groups, expr, selectQueryIndex) {\n // shouldAddExpressionToNewGroup is used to control whether we should add the passed expr to \n // a new Group or to the last Group\n var shouldAddExpressionToNewGroup = true;\n var exprSource = data.SQHierarchyExprUtils.getSourceVariationExpr(expr) || data.SQHierarchyExprUtils.getSourceHierarchy(expr);\n var lastGroup = _.last(groups);\n // The relevant group is always the last added. If it has the same source hierarchy,\n // and is properly ordered within that hierarchy, we will need to add to this group.\n if (lastGroup && lastGroup.children && data.SQExpr.equals(lastGroup.expr, exprSource)) {\n var expandedExpr = data.SQHierarchyExprUtils.expandExpr(schema, expr.arg);\n if (expandedExpr instanceof Array) {\n var allHierarchyLevels = expandedExpr;\n shouldAddExpressionToNewGroup = !data.SQHierarchyExprUtils.areHierarchyLevelsOrdered(allHierarchyLevels, _.last(lastGroup.children), expr);\n }\n }\n if (shouldAddExpressionToNewGroup)\n // Use the Sourcevariation as the expression for the group.\n groups.push({ expr: exprSource, children: [expr], selectQueryIndex: selectQueryIndex });\n else {\n debug.assertValue(lastGroup, 'There should be a group to add the variation to');\n debug.assertValue(lastGroup.children, 'The group should have children to add the variation to');\n lastGroup.children.push(expr);\n }\n }\n })(SQExprGroupUtils = data.SQExprGroupUtils || (data.SQExprGroupUtils = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var StringExtensions = jsCommon.StringExtensions;\n /** Represents an immutable expression within a SemanticQuery. */\n var SQExpr = (function () {\n function SQExpr(kind) {\n debug.assertValue(kind, 'kind');\n this._kind = kind;\n }\n SQExpr.equals = function (x, y, ignoreCase) {\n return SQExprEqualityVisitor.run(x, y, ignoreCase);\n };\n SQExpr.prototype.validate = function (schema, aggrUtils, errors) {\n var validator = new SQExprValidationVisitor(schema, aggrUtils, errors);\n this.accept(validator);\n return validator.errors;\n };\n SQExpr.prototype.accept = function (visitor, arg) {\n debug.assertFail('abstract method');\n return;\n };\n Object.defineProperty(SQExpr.prototype, \"kind\", {\n get: function () {\n return this._kind;\n },\n enumerable: true,\n configurable: true\n });\n SQExpr.isColumn = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 1 /* ColumnRef */;\n };\n SQExpr.isConstant = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 16 /* Constant */;\n };\n SQExpr.isEntity = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 0 /* Entity */;\n };\n SQExpr.isHierarchy = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 5 /* Hierarchy */;\n };\n SQExpr.isHierarchyLevel = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 6 /* HierarchyLevel */;\n };\n SQExpr.isAggregation = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 3 /* Aggregation */;\n };\n SQExpr.isMeasure = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 2 /* MeasureRef */;\n };\n SQExpr.isSelectRef = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 28 /* SelectRef */;\n };\n SQExpr.isResourcePackageItem = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.kind === 24 /* ResourcePackageItem */;\n };\n SQExpr.prototype.getMetadata = function (federatedSchema) {\n debug.assertValue(federatedSchema, 'federatedSchema');\n var field = data.SQExprConverter.asFieldPattern(this);\n if (!field)\n return;\n if (field.column || field.columnAggr || field.measure)\n return this.getMetadataForProperty(field, federatedSchema);\n if (field.hierarchyLevel || field.hierarchyLevelAggr)\n return this.getMetadataForHierarchyLevel(field, federatedSchema);\n if (field.columnHierarchyLevelVariation)\n return this.getMetadataForVariation(field, federatedSchema);\n if (field.percentOfGrandTotal)\n return this.getMetadataForPercentOfGrandTotal();\n return SQExpr.getMetadataForEntity(field, federatedSchema);\n };\n SQExpr.prototype.getDefaultAggregate = function (federatedSchema, forceAggregation) {\n if (forceAggregation === void 0) { forceAggregation = false; }\n debug.assertValue(federatedSchema, 'federatedSchema');\n var property = this.getConceptualProperty(federatedSchema) || this.getHierarchyLevelConceptualProperty(federatedSchema);\n if (!property)\n return;\n var aggregate;\n if (property && property.kind === 0 /* Column */) {\n var propertyDefaultAggregate = property.column ? property.column.defaultAggregate : null;\n if ((property.type.integer || property.type.numeric) &&\n propertyDefaultAggregate !== 1 /* None */) {\n aggregate = defaultAggregateToQueryAggregateFunction(propertyDefaultAggregate);\n if (aggregate === undefined)\n aggregate = defaultAggregateForDataType(property.type);\n }\n // If we haven't found an appropriate aggregate, and want to force aggregation anyway, \n // aggregate on CountNonNull.\n if (aggregate === undefined && forceAggregation) {\n aggregate = data.QueryAggregateFunction.CountNonNull;\n }\n }\n return aggregate;\n };\n /** Return the SQExpr[] of group on columns if it has group on keys otherwise return the SQExpr of the column.*/\n SQExpr.prototype.getKeyColumns = function (schema) {\n var columnRefExpr = SQExprColumnRefInfoVisitor.getColumnRefSQExpr(schema, this);\n if (!columnRefExpr)\n return;\n var keySQExprs = [];\n var keys = this.getPropertyKeys(schema);\n if (keys && keys.length > 0) {\n for (var i = 0, len = keys.length; i < len; i++) {\n keySQExprs.push(SQExprBuilder.columnRef(columnRefExpr.source, keys[i].name));\n }\n }\n else\n keySQExprs.push(columnRefExpr);\n return keySQExprs;\n };\n /** Returns a value indicating whether the expression would group on keys other than itself.*/\n SQExpr.prototype.hasGroupOnKeys = function (schema) {\n var columnRefExpr = SQExprColumnRefInfoVisitor.getColumnRefSQExpr(schema, this);\n if (!columnRefExpr)\n return;\n var keys = this.getPropertyKeys(schema);\n if (!keys || keys.length < 1)\n return false;\n if (keys.length > 1)\n return true;\n var keySqExpr = SQExprBuilder.columnRef(columnRefExpr.source, keys[0].name);\n return !SQExpr.equals(keySqExpr, this);\n };\n SQExpr.prototype.getPropertyKeys = function (schema) {\n var property = this.getConceptualProperty(schema) || this.getHierarchyLevelConceptualProperty(schema);\n if (!property)\n return;\n return property.column ? property.column.keys : undefined;\n };\n SQExpr.prototype.getConceptualProperty = function (federatedSchema) {\n var field = data.SQExprConverter.asFieldPattern(this);\n if (!field)\n return;\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(field);\n var propertyName = data.FieldExprPattern.getPropertyName(field);\n if (propertyName)\n return federatedSchema\n .schema(fieldExprItem.schema)\n .findProperty(fieldExprItem.entity, propertyName);\n };\n SQExpr.prototype.getTargetEntityForVariation = function (federatedSchema, variationName) {\n var property = this.getConceptualProperty(federatedSchema);\n if (property && property.column && !_.isEmpty(property.column.variations)) {\n var variations = property.column.variations;\n for (var _i = 0, variations_2 = variations; _i < variations_2.length; _i++) {\n var variation = variations_2[_i];\n if (variation.name === variationName)\n return variation.navigationProperty.targetEntity.name;\n }\n }\n };\n SQExpr.prototype.getTargetEntity = function (federatedSchema) {\n return SQEntityExprInfoVisitor.getEntityExpr(federatedSchema, this);\n };\n SQExpr.prototype.getHierarchyLevelConceptualProperty = function (federatedSchema) {\n var field = data.SQExprConverter.asFieldPattern(this);\n if (!field)\n return;\n var fieldExprHierachyLevel = field.hierarchyLevel || field.hierarchyLevelAggr;\n if (fieldExprHierachyLevel) {\n var fieldExprEntity = data.FieldExprPattern.toFieldExprEntityItemPattern(field);\n var hierarchy = federatedSchema\n .schema(fieldExprEntity.schema)\n .findHierarchy(fieldExprEntity.entity, fieldExprHierachyLevel.name);\n if (hierarchy) {\n var hierarchyLevel = hierarchy.levels.withName(fieldExprHierachyLevel.level);\n if (hierarchyLevel)\n return hierarchyLevel.column;\n }\n }\n };\n SQExpr.prototype.getMetadataForVariation = function (field, federatedSchema) {\n debug.assertValue(field, 'field');\n debug.assertValue(federatedSchema, 'federatedSchema');\n var columnHierarchyLevelVariation = field.columnHierarchyLevelVariation;\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(field);\n var sourceProperty = federatedSchema\n .schema(fieldExprItem.schema)\n .findProperty(fieldExprItem.entity, columnHierarchyLevelVariation.source.name);\n if (sourceProperty && sourceProperty.column && sourceProperty.column.variations) {\n for (var _i = 0, _a = sourceProperty.column.variations; _i < _a.length; _i++) {\n var variation = _a[_i];\n if (variation.defaultHierarchy && variation.defaultHierarchy.levels) {\n for (var _b = 0, _c = variation.defaultHierarchy.levels; _b < _c.length; _b++) {\n var level = _c[_b];\n if (level.name === columnHierarchyLevelVariation.level.level) {\n var property = level.column;\n return {\n kind: (property.kind === 1 /* Measure */) ? 1 /* Measure */ : 0 /* Column */,\n type: property.type,\n format: property.format,\n idOnEntityKey: property.column ? property.column.idOnEntityKey : false,\n defaultAggregate: property.column ? property.column.defaultAggregate : null\n };\n }\n }\n }\n }\n }\n };\n SQExpr.prototype.getMetadataForHierarchyLevel = function (field, federatedSchema) {\n debug.assertValue(field, 'field');\n debug.assertValue(federatedSchema, 'federatedSchema');\n var property = this.getHierarchyLevelConceptualProperty(federatedSchema);\n if (!property)\n return;\n return this.getPropertyMetadata(field, property);\n };\n SQExpr.prototype.getMetadataForPercentOfGrandTotal = function () {\n return {\n kind: 1 /* Measure */,\n format: '#,##0.##%',\n type: powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Double)\n };\n };\n SQExpr.prototype.getPropertyMetadata = function (field, property) {\n var format = property.format;\n var type = property.type;\n var columnAggregate = field.columnAggr || field.hierarchyLevelAggr;\n if (columnAggregate) {\n switch (columnAggregate.aggregate) {\n case data.QueryAggregateFunction.Count:\n case data.QueryAggregateFunction.CountNonNull:\n type = powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Integer);\n format = undefined;\n break;\n case data.QueryAggregateFunction.Avg:\n if (type.integer)\n type = powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Double);\n break;\n }\n }\n return {\n kind: (property.kind === 1 /* Measure */ || (columnAggregate && columnAggregate.aggregate !== undefined)) ? 1 /* Measure */ : 0 /* Column */,\n type: type,\n format: format,\n idOnEntityKey: property.column ? property.column.idOnEntityKey : false,\n aggregate: columnAggregate ? columnAggregate.aggregate : undefined,\n defaultAggregate: property.column ? property.column.defaultAggregate : null\n };\n };\n SQExpr.prototype.getMetadataForProperty = function (field, federatedSchema) {\n debug.assertValue(field, 'field');\n debug.assertValue(federatedSchema, 'federatedSchema');\n var property = this.getConceptualProperty(federatedSchema);\n if (!property)\n return;\n return this.getPropertyMetadata(field, property);\n };\n SQExpr.getMetadataForEntity = function (field, federatedSchema) {\n debug.assertValue(field, 'field');\n debug.assertValue(federatedSchema, 'federatedSchema');\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(field);\n var entity = federatedSchema\n .schema(fieldExprItem.schema)\n .entities\n .withName(fieldExprItem.entity);\n if (!entity)\n return;\n // We only support count and countnonnull for entity.\n if (field.entityAggr) {\n switch (field.entityAggr.aggregate) {\n case data.QueryAggregateFunction.Count:\n case data.QueryAggregateFunction.CountNonNull:\n return {\n kind: 1 /* Measure */,\n type: powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Integer),\n format: undefined,\n idOnEntityKey: false,\n aggregate: field.entityAggr.aggregate\n };\n }\n }\n };\n return SQExpr;\n }());\n data.SQExpr = SQExpr;\n /** Note: Exported for testability */\n function defaultAggregateForDataType(type) {\n if (type.integer || type.numeric)\n return data.QueryAggregateFunction.Sum;\n return data.QueryAggregateFunction.Count;\n }\n data.defaultAggregateForDataType = defaultAggregateForDataType;\n /** Note: Exported for testability */\n function defaultAggregateToQueryAggregateFunction(aggregate) {\n switch (aggregate) {\n case 6 /* Average */:\n return data.QueryAggregateFunction.Avg;\n case 3 /* Count */:\n return data.QueryAggregateFunction.CountNonNull;\n case 7 /* DistinctCount */:\n return data.QueryAggregateFunction.Count;\n case 5 /* Max */:\n return data.QueryAggregateFunction.Max;\n case 4 /* Min */:\n return data.QueryAggregateFunction.Min;\n case 2 /* Sum */:\n return data.QueryAggregateFunction.Sum;\n default:\n return;\n }\n }\n data.defaultAggregateToQueryAggregateFunction = defaultAggregateToQueryAggregateFunction;\n var SQEntityExpr = (function (_super) {\n __extends(SQEntityExpr, _super);\n function SQEntityExpr(schema, entity, variable) {\n debug.assertValue(entity, 'entity');\n _super.call(this, 0 /* Entity */);\n this.schema = schema;\n this.entity = entity;\n if (variable)\n this.variable = variable;\n }\n SQEntityExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitEntity(this, arg);\n };\n return SQEntityExpr;\n }(SQExpr));\n data.SQEntityExpr = SQEntityExpr;\n var SQArithmeticExpr = (function (_super) {\n __extends(SQArithmeticExpr, _super);\n function SQArithmeticExpr(left, right, operator) {\n debug.assertValue(left, 'left');\n debug.assertValue(right, 'right');\n debug.assertValue(operator, 'operator');\n _super.call(this, 22 /* Arithmetic */);\n this.left = left;\n this.right = right;\n this.operator = operator;\n }\n SQArithmeticExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitArithmetic(this, arg);\n };\n return SQArithmeticExpr;\n }(SQExpr));\n data.SQArithmeticExpr = SQArithmeticExpr;\n var SQScopedEvalExpr = (function (_super) {\n __extends(SQScopedEvalExpr, _super);\n function SQScopedEvalExpr(expression, scope) {\n debug.assertValue(expression, 'expression');\n debug.assertValue(scope, 'scope');\n _super.call(this, 25 /* ScopedEval */);\n this.expression = expression;\n this.scope = scope;\n }\n SQScopedEvalExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitScopedEval(this, arg);\n };\n SQScopedEvalExpr.prototype.getMetadata = function (federatedSchema) {\n return this.expression.getMetadata(federatedSchema);\n };\n return SQScopedEvalExpr;\n }(SQExpr));\n data.SQScopedEvalExpr = SQScopedEvalExpr;\n var SQPropRefExpr = (function (_super) {\n __extends(SQPropRefExpr, _super);\n function SQPropRefExpr(kind, source, ref) {\n debug.assertValue(kind, 'kind');\n debug.assertValue(source, 'source');\n debug.assertValue(ref, 'ref');\n _super.call(this, kind);\n this.source = source;\n this.ref = ref;\n }\n return SQPropRefExpr;\n }(SQExpr));\n data.SQPropRefExpr = SQPropRefExpr;\n var SQColumnRefExpr = (function (_super) {\n __extends(SQColumnRefExpr, _super);\n function SQColumnRefExpr(source, ref) {\n _super.call(this, 1 /* ColumnRef */, source, ref);\n }\n SQColumnRefExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitColumnRef(this, arg);\n };\n return SQColumnRefExpr;\n }(SQPropRefExpr));\n data.SQColumnRefExpr = SQColumnRefExpr;\n var SQMeasureRefExpr = (function (_super) {\n __extends(SQMeasureRefExpr, _super);\n function SQMeasureRefExpr(source, ref) {\n _super.call(this, 2 /* MeasureRef */, source, ref);\n }\n SQMeasureRefExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitMeasureRef(this, arg);\n };\n return SQMeasureRefExpr;\n }(SQPropRefExpr));\n data.SQMeasureRefExpr = SQMeasureRefExpr;\n var SQAggregationExpr = (function (_super) {\n __extends(SQAggregationExpr, _super);\n function SQAggregationExpr(arg, func) {\n debug.assertValue(arg, 'arg');\n debug.assertValue(func, 'func');\n _super.call(this, 3 /* Aggregation */);\n this.arg = arg;\n this.func = func;\n }\n SQAggregationExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitAggr(this, arg);\n };\n return SQAggregationExpr;\n }(SQExpr));\n data.SQAggregationExpr = SQAggregationExpr;\n var SQPercentileExpr = (function (_super) {\n __extends(SQPercentileExpr, _super);\n function SQPercentileExpr(arg, k, exclusive) {\n debug.assertValue(arg, 'arg');\n debug.assertValue(k, 'k');\n debug.assert(0 <= k && k <= 1, '0 <= k && k <= 1');\n debug.assertValue(exclusive, 'exclusive');\n _super.call(this, 27 /* Percentile */);\n this.arg = arg;\n this.k = k;\n this.exclusive = exclusive;\n }\n SQPercentileExpr.prototype.getMetadata = function (federatedSchema) {\n debug.assertValue(federatedSchema, 'federatedSchema');\n var argMetadata = this.arg.getMetadata(federatedSchema);\n if (argMetadata) {\n return {\n kind: 1 /* Measure */,\n type: argMetadata.type,\n };\n }\n };\n SQPercentileExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitPercentile(this, arg);\n };\n return SQPercentileExpr;\n }(SQExpr));\n data.SQPercentileExpr = SQPercentileExpr;\n var SQPropertyVariationSourceExpr = (function (_super) {\n __extends(SQPropertyVariationSourceExpr, _super);\n function SQPropertyVariationSourceExpr(arg, name, property) {\n debug.assertValue(arg, 'arg');\n debug.assertValue(name, 'name');\n debug.assertValue(property, 'property');\n _super.call(this, 4 /* PropertyVariationSource */);\n this.arg = arg;\n this.name = name;\n this.property = property;\n }\n SQPropertyVariationSourceExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitPropertyVariationSource(this, arg);\n };\n return SQPropertyVariationSourceExpr;\n }(SQExpr));\n data.SQPropertyVariationSourceExpr = SQPropertyVariationSourceExpr;\n var SQHierarchyExpr = (function (_super) {\n __extends(SQHierarchyExpr, _super);\n function SQHierarchyExpr(arg, hierarchy) {\n debug.assertValue(arg, 'arg');\n debug.assertValue(hierarchy, 'hierarchy');\n _super.call(this, 5 /* Hierarchy */);\n this.arg = arg;\n this.hierarchy = hierarchy;\n }\n SQHierarchyExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitHierarchy(this, arg);\n };\n return SQHierarchyExpr;\n }(SQExpr));\n data.SQHierarchyExpr = SQHierarchyExpr;\n var SQHierarchyLevelExpr = (function (_super) {\n __extends(SQHierarchyLevelExpr, _super);\n function SQHierarchyLevelExpr(arg, level) {\n debug.assertValue(arg, 'arg');\n debug.assertValue(level, 'level');\n _super.call(this, 6 /* HierarchyLevel */);\n this.arg = arg;\n this.level = level;\n }\n SQHierarchyLevelExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitHierarchyLevel(this, arg);\n };\n return SQHierarchyLevelExpr;\n }(SQExpr));\n data.SQHierarchyLevelExpr = SQHierarchyLevelExpr;\n var SQSelectRefExpr = (function (_super) {\n __extends(SQSelectRefExpr, _super);\n function SQSelectRefExpr(expressionName) {\n debug.assertValue(expressionName, 'arg');\n _super.call(this, 28 /* SelectRef */);\n this.expressionName = expressionName;\n }\n SQSelectRefExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitSelectRef(this, arg);\n };\n return SQSelectRefExpr;\n }(SQExpr));\n data.SQSelectRefExpr = SQSelectRefExpr;\n var SQAndExpr = (function (_super) {\n __extends(SQAndExpr, _super);\n function SQAndExpr(left, right) {\n debug.assertValue(left, 'left');\n debug.assertValue(right, 'right');\n _super.call(this, 7 /* And */);\n this.left = left;\n this.right = right;\n }\n SQAndExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitAnd(this, arg);\n };\n return SQAndExpr;\n }(SQExpr));\n data.SQAndExpr = SQAndExpr;\n var SQBetweenExpr = (function (_super) {\n __extends(SQBetweenExpr, _super);\n function SQBetweenExpr(arg, lower, upper) {\n debug.assertValue(arg, 'arg');\n debug.assertValue(lower, 'lower');\n debug.assertValue(upper, 'upper');\n _super.call(this, 8 /* Between */);\n this.arg = arg;\n this.lower = lower;\n this.upper = upper;\n }\n SQBetweenExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitBetween(this, arg);\n };\n return SQBetweenExpr;\n }(SQExpr));\n data.SQBetweenExpr = SQBetweenExpr;\n var SQInExpr = (function (_super) {\n __extends(SQInExpr, _super);\n function SQInExpr(args, values) {\n debug.assertValue(args, 'args');\n debug.assertValue(values, 'values');\n _super.call(this, 9 /* In */);\n this.args = args;\n this.values = values;\n }\n SQInExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitIn(this, arg);\n };\n return SQInExpr;\n }(SQExpr));\n data.SQInExpr = SQInExpr;\n var SQOrExpr = (function (_super) {\n __extends(SQOrExpr, _super);\n function SQOrExpr(left, right) {\n debug.assertValue(left, 'left');\n debug.assertValue(right, 'right');\n _super.call(this, 10 /* Or */);\n this.left = left;\n this.right = right;\n }\n SQOrExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitOr(this, arg);\n };\n return SQOrExpr;\n }(SQExpr));\n data.SQOrExpr = SQOrExpr;\n var SQCompareExpr = (function (_super) {\n __extends(SQCompareExpr, _super);\n function SQCompareExpr(comparison, left, right) {\n debug.assertValue(comparison, 'kind');\n debug.assertValue(left, 'left');\n debug.assertValue(right, 'right');\n _super.call(this, 12 /* Compare */);\n this.comparison = comparison;\n this.left = left;\n this.right = right;\n }\n SQCompareExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitCompare(this, arg);\n };\n return SQCompareExpr;\n }(SQExpr));\n data.SQCompareExpr = SQCompareExpr;\n var SQContainsExpr = (function (_super) {\n __extends(SQContainsExpr, _super);\n function SQContainsExpr(left, right) {\n debug.assertValue(left, 'left');\n debug.assertValue(right, 'right');\n _super.call(this, 11 /* Contains */);\n this.left = left;\n this.right = right;\n }\n SQContainsExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitContains(this, arg);\n };\n return SQContainsExpr;\n }(SQExpr));\n data.SQContainsExpr = SQContainsExpr;\n var SQStartsWithExpr = (function (_super) {\n __extends(SQStartsWithExpr, _super);\n function SQStartsWithExpr(left, right) {\n debug.assertValue(left, 'left');\n debug.assertValue(right, 'right');\n _super.call(this, 13 /* StartsWith */);\n this.left = left;\n this.right = right;\n }\n SQStartsWithExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitStartsWith(this, arg);\n };\n return SQStartsWithExpr;\n }(SQExpr));\n data.SQStartsWithExpr = SQStartsWithExpr;\n var SQExistsExpr = (function (_super) {\n __extends(SQExistsExpr, _super);\n function SQExistsExpr(arg) {\n debug.assertValue(arg, 'arg');\n _super.call(this, 14 /* Exists */);\n this.arg = arg;\n }\n SQExistsExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitExists(this, arg);\n };\n return SQExistsExpr;\n }(SQExpr));\n data.SQExistsExpr = SQExistsExpr;\n var SQNotExpr = (function (_super) {\n __extends(SQNotExpr, _super);\n function SQNotExpr(arg) {\n debug.assertValue(arg, 'arg');\n _super.call(this, 15 /* Not */);\n this.arg = arg;\n }\n SQNotExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitNot(this, arg);\n };\n return SQNotExpr;\n }(SQExpr));\n data.SQNotExpr = SQNotExpr;\n var SQConstantExpr = (function (_super) {\n __extends(SQConstantExpr, _super);\n function SQConstantExpr(type, value, valueEncoded) {\n debug.assertValue(type, 'type');\n _super.call(this, 16 /* Constant */);\n this.type = type;\n this.value = value;\n this.valueEncoded = valueEncoded;\n }\n SQConstantExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitConstant(this, arg);\n };\n SQConstantExpr.prototype.getMetadata = function (federatedSchema) {\n debug.assertValue(federatedSchema, 'federatedSchema');\n return {\n // Returning Measure as the kind for a SQConstantExpr is slightly ambiguous allowing the return object to conform to SQEXprMetadata.\n // A getType or similiar function in the future would be more appropriate. \n kind: 1 /* Measure */,\n type: this.type,\n };\n };\n return SQConstantExpr;\n }(SQExpr));\n data.SQConstantExpr = SQConstantExpr;\n var SQDateSpanExpr = (function (_super) {\n __extends(SQDateSpanExpr, _super);\n function SQDateSpanExpr(unit, arg) {\n debug.assertValue(unit, 'unit');\n debug.assertValue(arg, 'arg');\n _super.call(this, 17 /* DateSpan */);\n this.unit = unit;\n this.arg = arg;\n }\n SQDateSpanExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitDateSpan(this, arg);\n };\n return SQDateSpanExpr;\n }(SQExpr));\n data.SQDateSpanExpr = SQDateSpanExpr;\n var SQDateAddExpr = (function (_super) {\n __extends(SQDateAddExpr, _super);\n function SQDateAddExpr(unit, amount, arg) {\n debug.assertValue(unit, 'unit');\n debug.assertValue(amount, 'amount');\n debug.assertValue(arg, 'arg');\n _super.call(this, 18 /* DateAdd */);\n this.unit = unit;\n this.arg = arg;\n this.amount = amount;\n }\n SQDateAddExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitDateAdd(this, arg);\n };\n return SQDateAddExpr;\n }(SQExpr));\n data.SQDateAddExpr = SQDateAddExpr;\n var SQNowExpr = (function (_super) {\n __extends(SQNowExpr, _super);\n function SQNowExpr() {\n _super.call(this, 19 /* Now */);\n }\n SQNowExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitNow(this, arg);\n };\n return SQNowExpr;\n }(SQExpr));\n data.SQNowExpr = SQNowExpr;\n var SQDefaultValueExpr = (function (_super) {\n __extends(SQDefaultValueExpr, _super);\n function SQDefaultValueExpr() {\n _super.call(this, 21 /* DefaultValue */);\n }\n SQDefaultValueExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitDefaultValue(this, arg);\n };\n return SQDefaultValueExpr;\n }(SQExpr));\n data.SQDefaultValueExpr = SQDefaultValueExpr;\n var SQAnyValueExpr = (function (_super) {\n __extends(SQAnyValueExpr, _super);\n function SQAnyValueExpr() {\n _super.call(this, 20 /* AnyValue */);\n }\n SQAnyValueExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitAnyValue(this, arg);\n };\n return SQAnyValueExpr;\n }(SQExpr));\n data.SQAnyValueExpr = SQAnyValueExpr;\n var SQFillRuleExpr = (function (_super) {\n __extends(SQFillRuleExpr, _super);\n function SQFillRuleExpr(input, fillRule) {\n debug.assertValue(input, 'input');\n debug.assertValue(fillRule, 'fillRule');\n _super.call(this, 23 /* FillRule */);\n this.input = input;\n this.rule = fillRule;\n }\n SQFillRuleExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitFillRule(this, arg);\n };\n return SQFillRuleExpr;\n }(SQExpr));\n data.SQFillRuleExpr = SQFillRuleExpr;\n var SQResourcePackageItemExpr = (function (_super) {\n __extends(SQResourcePackageItemExpr, _super);\n function SQResourcePackageItemExpr(packageName, packageType, itemName) {\n debug.assertValue(packageName, 'packageName');\n debug.assertValue(itemName, 'itemName');\n _super.call(this, 24 /* ResourcePackageItem */);\n this.packageName = packageName;\n this.packageType = packageType;\n this.itemName = itemName;\n }\n SQResourcePackageItemExpr.prototype.accept = function (visitor, arg) {\n return visitor.visitResourcePackageItem(this, arg);\n };\n return SQResourcePackageItemExpr;\n }(SQExpr));\n data.SQResourcePackageItemExpr = SQResourcePackageItemExpr;\n /** Provides utilities for creating & manipulating expressions. */\n var SQExprBuilder;\n (function (SQExprBuilder) {\n function entity(schema, entity, variable) {\n return new SQEntityExpr(schema, entity, variable);\n }\n SQExprBuilder.entity = entity;\n function columnRef(source, prop) {\n return new SQColumnRefExpr(source, prop);\n }\n SQExprBuilder.columnRef = columnRef;\n function measureRef(source, prop) {\n return new SQMeasureRefExpr(source, prop);\n }\n SQExprBuilder.measureRef = measureRef;\n function aggregate(source, aggregate) {\n return new SQAggregationExpr(source, aggregate);\n }\n SQExprBuilder.aggregate = aggregate;\n function selectRef(expressionName) {\n return new SQSelectRefExpr(expressionName);\n }\n SQExprBuilder.selectRef = selectRef;\n function percentile(source, k, exclusive) {\n return new SQPercentileExpr(source, k, exclusive);\n }\n SQExprBuilder.percentile = percentile;\n function arithmetic(left, right, operator) {\n return new SQArithmeticExpr(left, right, operator);\n }\n SQExprBuilder.arithmetic = arithmetic;\n function scopedEval(expression, scope) {\n return new SQScopedEvalExpr(expression, scope);\n }\n SQExprBuilder.scopedEval = scopedEval;\n function hierarchy(source, hierarchy) {\n return new SQHierarchyExpr(source, hierarchy);\n }\n SQExprBuilder.hierarchy = hierarchy;\n function propertyVariationSource(source, name, property) {\n return new SQPropertyVariationSourceExpr(source, name, property);\n }\n SQExprBuilder.propertyVariationSource = propertyVariationSource;\n function hierarchyLevel(source, level) {\n return new SQHierarchyLevelExpr(source, level);\n }\n SQExprBuilder.hierarchyLevel = hierarchyLevel;\n function and(left, right) {\n if (!left)\n return right;\n if (!right)\n return left;\n return new SQAndExpr(left, right);\n }\n SQExprBuilder.and = and;\n function between(arg, lower, upper) {\n return new SQBetweenExpr(arg, lower, upper);\n }\n SQExprBuilder.between = between;\n function inExpr(args, values) {\n return new SQInExpr(args, values);\n }\n SQExprBuilder.inExpr = inExpr;\n function or(left, right) {\n if (!left)\n return right;\n if (!right)\n return left;\n if (left instanceof SQInExpr && right instanceof SQInExpr) {\n var inExpr_1 = tryUseInExprs(left, right);\n if (inExpr_1)\n return inExpr_1;\n }\n return new SQOrExpr(left, right);\n }\n SQExprBuilder.or = or;\n function tryUseInExprs(left, right) {\n if (!left.args || !right.args)\n return;\n var leftArgLen = left.args.length;\n var rightArgLen = right.args.length;\n if (leftArgLen !== rightArgLen)\n return;\n for (var i = 0; i < leftArgLen; ++i) {\n if (!SQExpr.equals(left.args[i], right.args[i]))\n return;\n }\n var combinedValues = left.values.concat(right.values);\n return SQExprBuilder.inExpr(left.args, combinedValues);\n }\n function compare(kind, left, right) {\n return new SQCompareExpr(kind, left, right);\n }\n SQExprBuilder.compare = compare;\n function contains(left, right) {\n return new SQContainsExpr(left, right);\n }\n SQExprBuilder.contains = contains;\n function exists(arg) {\n return new SQExistsExpr(arg);\n }\n SQExprBuilder.exists = exists;\n function equal(left, right) {\n return compare(data.QueryComparisonKind.Equal, left, right);\n }\n SQExprBuilder.equal = equal;\n function not(arg) {\n return new SQNotExpr(arg);\n }\n SQExprBuilder.not = not;\n function startsWith(left, right) {\n return new SQStartsWithExpr(left, right);\n }\n SQExprBuilder.startsWith = startsWith;\n function nullConstant() {\n return new SQConstantExpr(powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Null), null, data.PrimitiveValueEncoding.nullEncoding());\n }\n SQExprBuilder.nullConstant = nullConstant;\n function now() {\n return new SQNowExpr();\n }\n SQExprBuilder.now = now;\n function defaultValue() {\n return new SQDefaultValueExpr();\n }\n SQExprBuilder.defaultValue = defaultValue;\n function anyValue() {\n return new SQAnyValueExpr();\n }\n SQExprBuilder.anyValue = anyValue;\n function boolean(value) {\n return new SQConstantExpr(powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Boolean), value, data.PrimitiveValueEncoding.boolean(value));\n }\n SQExprBuilder.boolean = boolean;\n function dateAdd(unit, amount, arg) {\n return new SQDateAddExpr(unit, amount, arg);\n }\n SQExprBuilder.dateAdd = dateAdd;\n function dateTime(value, valueEncoded) {\n if (valueEncoded === undefined)\n valueEncoded = data.PrimitiveValueEncoding.dateTime(value);\n return new SQConstantExpr(powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.DateTime), value, valueEncoded);\n }\n SQExprBuilder.dateTime = dateTime;\n function dateSpan(unit, arg) {\n return new SQDateSpanExpr(unit, arg);\n }\n SQExprBuilder.dateSpan = dateSpan;\n function decimal(value, valueEncoded) {\n if (valueEncoded === undefined)\n valueEncoded = data.PrimitiveValueEncoding.decimal(value);\n return new SQConstantExpr(powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Decimal), value, valueEncoded);\n }\n SQExprBuilder.decimal = decimal;\n function double(value, valueEncoded) {\n if (valueEncoded === undefined)\n valueEncoded = data.PrimitiveValueEncoding.double(value);\n return new SQConstantExpr(powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Double), value, valueEncoded);\n }\n SQExprBuilder.double = double;\n function integer(value, valueEncoded) {\n if (valueEncoded === undefined)\n valueEncoded = data.PrimitiveValueEncoding.integer(value);\n return new SQConstantExpr(powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Integer), value, valueEncoded);\n }\n SQExprBuilder.integer = integer;\n function text(value, valueEncoded) {\n debug.assert(!valueEncoded || valueEncoded === data.PrimitiveValueEncoding.text(value), 'Incorrect encoded value specified.');\n return new SQConstantExpr(powerbi.ValueType.fromExtendedType(powerbi.ExtendedType.Text), value, valueEncoded || data.PrimitiveValueEncoding.text(value));\n }\n SQExprBuilder.text = text;\n /** Returns an SQExpr that evaluates to the constant value. */\n function typedConstant(value, type) {\n if (value == null)\n return nullConstant();\n if (_.isBoolean(value)) {\n return boolean(value);\n }\n if (_.isString(value)) {\n return text(value);\n }\n if (_.isNumber(value)) {\n if (type.integer && powerbi.Double.isInteger(value))\n return integer(value);\n return double(value);\n }\n if (value instanceof Date) {\n return dateTime(value);\n }\n }\n SQExprBuilder.typedConstant = typedConstant;\n function setAggregate(expr, aggregate) {\n return FieldExprChangeAggregateRewriter.rewrite(expr, aggregate);\n }\n SQExprBuilder.setAggregate = setAggregate;\n function removeAggregate(expr) {\n return FieldExprRemoveAggregateRewriter.rewrite(expr);\n }\n SQExprBuilder.removeAggregate = removeAggregate;\n function setPercentOfGrandTotal(expr) {\n return SQExprSetPercentOfGrandTotalRewriter.rewrite(expr);\n }\n SQExprBuilder.setPercentOfGrandTotal = setPercentOfGrandTotal;\n function removePercentOfGrandTotal(expr) {\n return SQExprRemovePercentOfGrandTotalRewriter.rewrite(expr);\n }\n SQExprBuilder.removePercentOfGrandTotal = removePercentOfGrandTotal;\n function removeEntityVariables(expr) {\n return SQExprRemoveEntityVariablesRewriter.rewrite(expr);\n }\n SQExprBuilder.removeEntityVariables = removeEntityVariables;\n function fillRule(expr, rule) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(rule, 'rule');\n return new SQFillRuleExpr(expr, rule);\n }\n SQExprBuilder.fillRule = fillRule;\n function resourcePackageItem(packageName, packageType, itemName) {\n return new SQResourcePackageItemExpr(packageName, packageType, itemName);\n }\n SQExprBuilder.resourcePackageItem = resourcePackageItem;\n })(SQExprBuilder = data.SQExprBuilder || (data.SQExprBuilder = {}));\n /** Provides utilities for obtaining information about expressions. */\n var SQExprInfo;\n (function (SQExprInfo) {\n function getAggregate(expr) {\n return SQExprAggregateInfoVisitor.getAggregate(expr);\n }\n SQExprInfo.getAggregate = getAggregate;\n })(SQExprInfo = data.SQExprInfo || (data.SQExprInfo = {}));\n var SQExprEqualityVisitor = (function () {\n function SQExprEqualityVisitor(ignoreCase) {\n this.ignoreCase = ignoreCase;\n }\n SQExprEqualityVisitor.run = function (x, y, ignoreCase) {\n // Normalize falsy to null\n x = x || null;\n y = y || null;\n if (x === y)\n return true;\n if (!x !== !y)\n return false;\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n if (ignoreCase)\n return x.accept(SQExprEqualityVisitor.ignoreCaseInstance, y);\n return x.accept(SQExprEqualityVisitor.instance, y);\n };\n SQExprEqualityVisitor.prototype.visitColumnRef = function (expr, comparand) {\n return comparand instanceof SQColumnRefExpr &&\n expr.ref === comparand.ref &&\n this.equals(expr.source, comparand.source);\n };\n SQExprEqualityVisitor.prototype.visitMeasureRef = function (expr, comparand) {\n return comparand instanceof SQMeasureRefExpr &&\n expr.ref === comparand.ref &&\n this.equals(expr.source, comparand.source);\n };\n SQExprEqualityVisitor.prototype.visitAggr = function (expr, comparand) {\n return comparand instanceof SQAggregationExpr &&\n expr.func === comparand.func &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitPercentile = function (expr, comparand) {\n return comparand instanceof SQPercentileExpr &&\n expr.exclusive === comparand.exclusive &&\n expr.k === comparand.k &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitHierarchy = function (expr, comparand) {\n return comparand instanceof SQHierarchyExpr &&\n expr.hierarchy === comparand.hierarchy &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitHierarchyLevel = function (expr, comparand) {\n return comparand instanceof SQHierarchyLevelExpr &&\n expr.level === comparand.level &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitPropertyVariationSource = function (expr, comparand) {\n return comparand instanceof SQPropertyVariationSourceExpr &&\n expr.name === comparand.name &&\n expr.property === comparand.property &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitSelectRef = function (expr, comparand) {\n return comparand instanceof SQSelectRefExpr &&\n expr.expressionName === comparand.expressionName;\n };\n SQExprEqualityVisitor.prototype.visitBetween = function (expr, comparand) {\n return comparand instanceof SQBetweenExpr &&\n this.equals(expr.arg, comparand.arg) &&\n this.equals(expr.lower, comparand.lower) &&\n this.equals(expr.upper, comparand.upper);\n };\n SQExprEqualityVisitor.prototype.visitIn = function (expr, comparand) {\n if (!(comparand instanceof SQInExpr) || !this.equalsAll(expr.args, comparand.args))\n return false;\n var values = expr.values, compareValues = comparand.values;\n if (values.length !== compareValues.length)\n return false;\n for (var i = 0, len = values.length; i < len; i++) {\n if (!this.equalsAll(values[i], compareValues[i]))\n return false;\n }\n return true;\n };\n SQExprEqualityVisitor.prototype.visitEntity = function (expr, comparand) {\n return comparand instanceof SQEntityExpr &&\n expr.schema === comparand.schema &&\n expr.entity === comparand.entity &&\n this.optionalEqual(expr.variable, comparand.variable);\n };\n SQExprEqualityVisitor.prototype.visitAnd = function (expr, comparand) {\n return comparand instanceof SQAndExpr &&\n this.equals(expr.left, comparand.left) &&\n this.equals(expr.right, comparand.right);\n };\n SQExprEqualityVisitor.prototype.visitOr = function (expr, comparand) {\n return comparand instanceof SQOrExpr &&\n this.equals(expr.left, comparand.left) &&\n this.equals(expr.right, comparand.right);\n };\n SQExprEqualityVisitor.prototype.visitCompare = function (expr, comparand) {\n return comparand instanceof SQCompareExpr &&\n expr.comparison === comparand.comparison &&\n this.equals(expr.left, comparand.left) &&\n this.equals(expr.right, comparand.right);\n };\n SQExprEqualityVisitor.prototype.visitContains = function (expr, comparand) {\n return comparand instanceof SQContainsExpr &&\n this.equals(expr.left, comparand.left) &&\n this.equals(expr.right, comparand.right);\n };\n SQExprEqualityVisitor.prototype.visitDateSpan = function (expr, comparand) {\n return comparand instanceof SQDateSpanExpr &&\n expr.unit === comparand.unit &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitDateAdd = function (expr, comparand) {\n return comparand instanceof SQDateAddExpr &&\n expr.unit === comparand.unit &&\n expr.amount === comparand.amount &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitExists = function (expr, comparand) {\n return comparand instanceof SQExistsExpr &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitNot = function (expr, comparand) {\n return comparand instanceof SQNotExpr &&\n this.equals(expr.arg, comparand.arg);\n };\n SQExprEqualityVisitor.prototype.visitNow = function (expr, comparand) {\n return comparand instanceof SQNowExpr;\n };\n SQExprEqualityVisitor.prototype.visitDefaultValue = function (expr, comparand) {\n return comparand instanceof SQDefaultValueExpr;\n };\n SQExprEqualityVisitor.prototype.visitAnyValue = function (expr, comparand) {\n return comparand instanceof SQAnyValueExpr;\n };\n SQExprEqualityVisitor.prototype.visitResourcePackageItem = function (expr, comparand) {\n return comparand instanceof SQResourcePackageItemExpr &&\n expr.packageName === comparand.packageName &&\n expr.packageType === comparand.packageType &&\n expr.itemName === comparand.itemName;\n };\n SQExprEqualityVisitor.prototype.visitStartsWith = function (expr, comparand) {\n return comparand instanceof SQStartsWithExpr &&\n this.equals(expr.left, comparand.left) &&\n this.equals(expr.right, comparand.right);\n };\n SQExprEqualityVisitor.prototype.visitConstant = function (expr, comparand) {\n if (comparand instanceof SQConstantExpr && expr.type === comparand.type)\n return expr.type.text && this.ignoreCase ?\n StringExtensions.equalIgnoreCase(expr.valueEncoded, comparand.valueEncoded) :\n expr.valueEncoded === comparand.valueEncoded;\n return false;\n };\n SQExprEqualityVisitor.prototype.visitFillRule = function (expr, comparand) {\n if (comparand instanceof SQFillRuleExpr && this.equals(expr.input, comparand.input)) {\n var leftRule = expr.rule, rightRule = comparand.rule;\n if (leftRule === rightRule)\n return true;\n var leftLinearGradient2 = leftRule.linearGradient2, rightLinearGradient2 = rightRule.linearGradient2;\n if (leftLinearGradient2 && rightLinearGradient2) {\n return this.visitLinearGradient2(leftLinearGradient2, rightLinearGradient2);\n }\n var leftLinearGradient3 = leftRule.linearGradient3, rightLinearGradient3 = rightRule.linearGradient3;\n if (leftLinearGradient3 && rightLinearGradient3) {\n return this.visitLinearGradient3(leftLinearGradient3, rightLinearGradient3);\n }\n }\n return false;\n };\n SQExprEqualityVisitor.prototype.visitLinearGradient2 = function (left2, right2) {\n debug.assertValue(left2, 'left2');\n debug.assertValue(right2, 'right2');\n return this.equalsFillRuleStop(left2.min, right2.min) &&\n this.equalsFillRuleStop(left2.max, right2.max);\n };\n SQExprEqualityVisitor.prototype.visitLinearGradient3 = function (left3, right3) {\n debug.assertValue(left3, 'left3');\n debug.assertValue(right3, 'right3');\n return this.equalsFillRuleStop(left3.min, right3.min) &&\n this.equalsFillRuleStop(left3.mid, right3.mid) &&\n this.equalsFillRuleStop(left3.max, right3.max);\n };\n SQExprEqualityVisitor.prototype.equalsFillRuleStop = function (stop1, stop2) {\n debug.assertValue(stop1, 'stop1');\n debug.assertValue(stop2, 'stop2');\n if (!this.equals(stop1.color, stop2.color))\n return false;\n if (!stop1.value)\n return stop1.value === stop2.value;\n return this.equals(stop1.value, stop2.value);\n };\n SQExprEqualityVisitor.prototype.visitArithmetic = function (expr, comparand) {\n return comparand instanceof SQArithmeticExpr &&\n expr.operator === comparand.operator &&\n this.equals(expr.left, comparand.left) &&\n this.equals(expr.right, comparand.right);\n };\n SQExprEqualityVisitor.prototype.visitScopedEval = function (expr, comparand) {\n return comparand instanceof SQScopedEvalExpr &&\n this.equals(expr.expression, comparand.expression) &&\n this.equalsAll(expr.scope, comparand.scope);\n };\n SQExprEqualityVisitor.prototype.optionalEqual = function (x, y) {\n // Only check equality if both values are specified.\n if (x && y)\n return x === y;\n return true;\n };\n SQExprEqualityVisitor.prototype.equals = function (x, y) {\n return x.accept(this, y);\n };\n SQExprEqualityVisitor.prototype.equalsAll = function (x, y) {\n var len = x.length;\n if (len !== y.length)\n return false;\n for (var i = 0; i < len; i++) {\n if (!this.equals(x[i], y[i]))\n return false;\n }\n return true;\n };\n SQExprEqualityVisitor.instance = new SQExprEqualityVisitor(/* ignoreCase */ false);\n SQExprEqualityVisitor.ignoreCaseInstance = new SQExprEqualityVisitor(true);\n return SQExprEqualityVisitor;\n }());\n /** Rewrites a root-level expression. */\n var SQExprRootRewriter = (function (_super) {\n __extends(SQExprRootRewriter, _super);\n function SQExprRootRewriter() {\n _super.apply(this, arguments);\n }\n SQExprRootRewriter.prototype.visitDefault = function (expr) {\n return expr;\n };\n return SQExprRootRewriter;\n }(data.DefaultSQExprVisitor));\n var SQExprValidationVisitor = (function (_super) {\n __extends(SQExprValidationVisitor, _super);\n function SQExprValidationVisitor(schema, aggrUtils, errors) {\n debug.assertValue(schema, 'schema');\n debug.assertValue(aggrUtils, 'aggrUtils');\n _super.call(this);\n this.schema = schema;\n this.aggrUtils = aggrUtils;\n if (errors)\n this.errors = errors;\n }\n SQExprValidationVisitor.prototype.visitIn = function (expr) {\n var inExpr = _super.prototype.visitIn.call(this, expr);\n var args = inExpr.args;\n var values = inExpr.values;\n for (var _i = 0, values_2 = values; _i < values_2.length; _i++) {\n var valueTuple = values_2[_i];\n debug.assert(valueTuple.length === args.length, 'args and value tuple are not the same length');\n for (var i = 0, len = valueTuple.length; i < len; ++i)\n this.validateCompatibleType(args[i], valueTuple[i]);\n }\n return inExpr;\n };\n SQExprValidationVisitor.prototype.visitCompare = function (expr) {\n var compareExpr = _super.prototype.visitCompare.call(this, expr);\n this.validateCompatibleType(compareExpr.left, compareExpr.right);\n return compareExpr;\n };\n SQExprValidationVisitor.prototype.visitColumnRef = function (expr) {\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n if (fieldExpr) {\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n var entity = this.validateEntity(fieldExprItem.schema, fieldExprItem.entity);\n if (entity) {\n var prop = entity.properties.withName(fieldExpr.column.name);\n if (!prop ||\n prop.kind !== 0 /* Column */ ||\n !this.isQueryable(fieldExpr))\n this.register(3 /* invalidColumnReference */);\n }\n }\n return expr;\n };\n SQExprValidationVisitor.prototype.visitMeasureRef = function (expr) {\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n if (fieldExpr) {\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n var entity = this.validateEntity(fieldExprItem.schema, fieldExprItem.entity);\n if (entity) {\n var prop = entity.properties.withName(fieldExpr.measure.name);\n if (!prop ||\n prop.kind !== 1 /* Measure */ ||\n !this.isQueryable(fieldExpr))\n this.register(4 /* invalidMeasureReference */);\n }\n }\n return expr;\n };\n SQExprValidationVisitor.prototype.visitAggr = function (expr) {\n var aggregateExpr = _super.prototype.visitAggr.call(this, expr);\n var columnRefExpr = SQExprColumnRefInfoVisitor.getColumnRefSQExpr(this.schema, aggregateExpr.arg);\n if (columnRefExpr) {\n if (!this.aggrUtils.isSupportedAggregate(expr, this.schema, expr.func, /*targetTypes*/ null))\n this.register(0 /* invalidAggregateFunction */);\n }\n return aggregateExpr;\n };\n SQExprValidationVisitor.prototype.visitHierarchy = function (expr) {\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n if (fieldExpr) {\n var fieldExprItem = fieldExpr.hierarchy;\n if (fieldExprItem) {\n this.validateHierarchy(fieldExprItem.schema, fieldExprItem.entity, fieldExprItem.name);\n }\n else {\n this.register(5 /* invalidHierarchyReference */);\n }\n }\n return expr;\n };\n SQExprValidationVisitor.prototype.visitHierarchyLevel = function (expr) {\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n if (fieldExpr) {\n var hierarchyLevelFieldExprItem = fieldExpr.hierarchyLevel;\n if (hierarchyLevelFieldExprItem) {\n this.validateHierarchyLevel(hierarchyLevelFieldExprItem.schema, hierarchyLevelFieldExprItem.entity, hierarchyLevelFieldExprItem.name, hierarchyLevelFieldExprItem.level);\n }\n else if (!fieldExpr.columnHierarchyLevelVariation) {\n this.register(6 /* invalidHierarchyLevelReference */);\n }\n }\n return expr;\n };\n SQExprValidationVisitor.prototype.visitPercentile = function (expr) {\n expr.arg.accept(this);\n if (_.isEmpty(this.errors)) {\n var argMetadata = expr.arg.getMetadata(this.schema);\n if (!argMetadata ||\n argMetadata.kind !== 0 /* Column */ ||\n !(argMetadata.type && (argMetadata.type.integer || argMetadata.type.numeric))) {\n this.register(10 /* invalidPercentileArgument */);\n }\n }\n return expr;\n };\n SQExprValidationVisitor.prototype.visitEntity = function (expr) {\n this.validateEntity(expr.schema, expr.entity);\n return expr;\n };\n SQExprValidationVisitor.prototype.visitContains = function (expr) {\n this.validateOperandsAndTypeForStartOrContains(expr.left, expr.right);\n return expr;\n };\n SQExprValidationVisitor.prototype.visitStartsWith = function (expr) {\n this.validateOperandsAndTypeForStartOrContains(expr.left, expr.right);\n return expr;\n };\n SQExprValidationVisitor.prototype.visitArithmetic = function (expr) {\n this.validateArithmeticTypes(expr.left, expr.right);\n return expr;\n };\n SQExprValidationVisitor.prototype.visitScopedEval = function (expr) {\n // No validation necessary\n return expr;\n };\n SQExprValidationVisitor.prototype.validateOperandsAndTypeForStartOrContains = function (left, right) {\n if (left instanceof SQColumnRefExpr) {\n this.visitColumnRef(left);\n }\n else if (left instanceof SQHierarchyLevelExpr) {\n this.visitHierarchyLevel(left);\n }\n else {\n this.register(7 /* invalidLeftOperandType */);\n }\n if (!(right instanceof SQConstantExpr) || !right.type.text)\n this.register(8 /* invalidRightOperandType */);\n else\n this.validateCompatibleType(left, right);\n };\n SQExprValidationVisitor.prototype.validateArithmeticTypes = function (left, right) {\n if (!data.SQExprUtils.supportsArithmetic(left, this.schema))\n this.register(7 /* invalidLeftOperandType */);\n if (!data.SQExprUtils.supportsArithmetic(right, this.schema))\n this.register(8 /* invalidRightOperandType */);\n };\n SQExprValidationVisitor.prototype.validateCompatibleType = function (left, right) {\n var leftMetadata = left.getMetadata(this.schema), leftType = leftMetadata && leftMetadata.type, rightMetadata = right.getMetadata(this.schema), rightType = rightMetadata && rightMetadata.type;\n if (leftType && rightType && !leftType.isCompatibleFrom(rightType))\n this.register(9 /* invalidValueType */);\n };\n SQExprValidationVisitor.prototype.validateEntity = function (schemaName, entityName) {\n var schema = this.schema.schema(schemaName);\n if (schema) {\n var entity = schema.entities.withName(entityName);\n if (entity)\n return entity;\n this.register(2 /* invalidEntityReference */);\n }\n else {\n this.register(1 /* invalidSchemaReference */);\n }\n };\n SQExprValidationVisitor.prototype.validateHierarchy = function (schemaName, entityName, hierarchyName) {\n var entity = this.validateEntity(schemaName, entityName);\n if (entity) {\n var hierarchy = entity.hierarchies.withName(hierarchyName);\n if (hierarchy)\n return hierarchy;\n this.register(5 /* invalidHierarchyReference */);\n }\n };\n SQExprValidationVisitor.prototype.validateHierarchyLevel = function (schemaName, entityName, hierarchyName, levelName) {\n var hierarchy = this.validateHierarchy(schemaName, entityName, hierarchyName);\n if (hierarchy) {\n var hierarchyLevel = hierarchy.levels.withName(levelName);\n if (hierarchyLevel)\n return hierarchyLevel;\n this.register(6 /* invalidHierarchyLevelReference */);\n }\n };\n SQExprValidationVisitor.prototype.register = function (error) {\n if (!this.errors)\n this.errors = [];\n this.errors.push(error);\n };\n SQExprValidationVisitor.prototype.isQueryable = function (fieldExpr) {\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\n if (fieldExpr.hierarchyLevel || fieldExpr.hierarchyLevelAggr) {\n var hierarchyLevelConceptualProperty = data.SQHierarchyExprUtils.getConceptualHierarchyLevelFromExpr(this.schema, fieldExpr);\n return hierarchyLevelConceptualProperty && hierarchyLevelConceptualProperty.column.queryable !== 1 /* Error */;\n }\n return this.schema.schema(fieldExprItem.schema).findProperty(fieldExprItem.entity, data.FieldExprPattern.getPropertyName(fieldExpr)).queryable !== 1 /* Error */;\n };\n return SQExprValidationVisitor;\n }(data.SQExprRewriter));\n data.SQExprValidationVisitor = SQExprValidationVisitor;\n /** Returns an expression's aggregate function, or undefined if it doesn't have one. */\n var SQExprAggregateInfoVisitor = (function (_super) {\n __extends(SQExprAggregateInfoVisitor, _super);\n function SQExprAggregateInfoVisitor() {\n _super.apply(this, arguments);\n }\n SQExprAggregateInfoVisitor.prototype.visitAggr = function (expr) {\n return expr.func;\n };\n SQExprAggregateInfoVisitor.prototype.visitDefault = function (expr) {\n return;\n };\n SQExprAggregateInfoVisitor.getAggregate = function (expr) {\n var visitor = new SQExprAggregateInfoVisitor();\n return expr.accept(visitor);\n };\n return SQExprAggregateInfoVisitor;\n }(data.DefaultSQExprVisitor));\n /** Returns a SQExprColumnRef expression or undefined.*/\n var SQExprColumnRefInfoVisitor = (function (_super) {\n __extends(SQExprColumnRefInfoVisitor, _super);\n function SQExprColumnRefInfoVisitor(schema) {\n _super.call(this);\n this.schema = schema;\n }\n SQExprColumnRefInfoVisitor.prototype.visitColumnRef = function (expr) {\n return expr;\n };\n SQExprColumnRefInfoVisitor.prototype.visitHierarchyLevel = function (expr) {\n var ref = expr.level;\n var hierarchy = (expr.arg);\n var sourceExpr = hierarchy.accept(this);\n if (hierarchy && hierarchy.arg instanceof SQPropertyVariationSourceExpr) {\n var propertyVariationSource = hierarchy.arg;\n var targetEntity = sourceExpr.getTargetEntityForVariation(this.schema, propertyVariationSource.name);\n if (sourceExpr && targetEntity) {\n var schemaName = (sourceExpr.source).schema;\n var targetEntityExpr = SQExprBuilder.entity(schemaName, targetEntity);\n var schemaHierarchy = this.schema.schema(schemaName).findHierarchy(targetEntity, hierarchy.hierarchy);\n if (schemaHierarchy) {\n for (var _i = 0, _a = schemaHierarchy.levels; _i < _a.length; _i++) {\n var level = _a[_i];\n if (level.name === ref)\n return new SQColumnRefExpr(targetEntityExpr, level.column.name);\n }\n }\n }\n }\n else {\n var entityExpr = (hierarchy.arg);\n var hierarchyLevelRef = data.SQHierarchyExprUtils.getConceptualHierarchyLevel(this.schema, entityExpr.schema, entityExpr.entity, hierarchy.hierarchy, expr.level);\n if (hierarchyLevelRef)\n return new SQColumnRefExpr(hierarchy.arg, hierarchyLevelRef.column.name);\n }\n };\n SQExprColumnRefInfoVisitor.prototype.visitHierarchy = function (expr) {\n return expr.arg.accept(this);\n };\n SQExprColumnRefInfoVisitor.prototype.visitPropertyVariationSource = function (expr) {\n var propertyName = expr.property;\n return new SQColumnRefExpr(expr.arg, propertyName);\n };\n SQExprColumnRefInfoVisitor.prototype.visitAggr = function (expr) {\n return expr.arg.accept(this);\n };\n SQExprColumnRefInfoVisitor.prototype.visitDefault = function (expr) {\n return;\n };\n SQExprColumnRefInfoVisitor.getColumnRefSQExpr = function (schema, expr) {\n var visitor = new SQExprColumnRefInfoVisitor(schema);\n return expr.accept(visitor);\n };\n return SQExprColumnRefInfoVisitor;\n }(data.DefaultSQExprVisitor));\n /** Returns a SQEntityExpr expression or undefined.*/\n var SQEntityExprInfoVisitor = (function (_super) {\n __extends(SQEntityExprInfoVisitor, _super);\n function SQEntityExprInfoVisitor(schema) {\n _super.call(this);\n this.schema = schema;\n }\n SQEntityExprInfoVisitor.prototype.visitEntity = function (expr) {\n return expr;\n };\n SQEntityExprInfoVisitor.prototype.visitColumnRef = function (expr) {\n return SQEntityExprInfoVisitor.getEntity(expr);\n };\n SQEntityExprInfoVisitor.prototype.visitHierarchyLevel = function (expr) {\n var columnRef = SQEntityExprInfoVisitor.getColumnRefSQExpr(this.schema, expr);\n return SQEntityExprInfoVisitor.getEntity(columnRef);\n };\n SQEntityExprInfoVisitor.prototype.visitHierarchy = function (expr) {\n return expr.arg.accept(this);\n };\n SQEntityExprInfoVisitor.prototype.visitPropertyVariationSource = function (expr) {\n var columnRef = SQEntityExprInfoVisitor.getColumnRefSQExpr(this.schema, expr);\n return SQEntityExprInfoVisitor.getEntity(columnRef);\n };\n SQEntityExprInfoVisitor.prototype.visitAggr = function (expr) {\n var columnRef = SQEntityExprInfoVisitor.getColumnRefSQExpr(this.schema, expr);\n return SQEntityExprInfoVisitor.getEntity(columnRef);\n };\n SQEntityExprInfoVisitor.prototype.visitMeasureRef = function (expr) {\n return expr.source.accept(this);\n };\n SQEntityExprInfoVisitor.getColumnRefSQExpr = function (schema, expr) {\n var visitor = new SQExprColumnRefInfoVisitor(schema);\n return expr.accept(visitor);\n };\n SQEntityExprInfoVisitor.getEntity = function (columnRef) {\n var field = data.SQExprConverter.asFieldPattern(columnRef);\n var column = field.column;\n return SQExprBuilder.entity(column.schema, column.entity, column.entityVar);\n };\n SQEntityExprInfoVisitor.getEntityExpr = function (schema, expr) {\n var visitor = new SQEntityExprInfoVisitor(schema);\n return expr.accept(visitor);\n };\n return SQEntityExprInfoVisitor;\n }(data.DefaultSQExprVisitor));\n var SQExprChangeAggregateRewriter = (function (_super) {\n __extends(SQExprChangeAggregateRewriter, _super);\n function SQExprChangeAggregateRewriter(func) {\n debug.assertValue(func, 'func');\n _super.call(this);\n this.func = func;\n }\n SQExprChangeAggregateRewriter.prototype.visitAggr = function (expr) {\n if (expr.func === this.func)\n return expr;\n return new SQAggregationExpr(expr.arg, this.func);\n };\n SQExprChangeAggregateRewriter.prototype.visitColumnRef = function (expr) {\n return new SQAggregationExpr(expr, this.func);\n };\n SQExprChangeAggregateRewriter.rewrite = function (expr, func) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(func, 'func');\n var rewriter = new SQExprChangeAggregateRewriter(func);\n return expr.accept(rewriter);\n };\n return SQExprChangeAggregateRewriter;\n }(SQExprRootRewriter));\n var FieldExprChangeAggregateRewriter = (function () {\n function FieldExprChangeAggregateRewriter(sqExpr, aggregate) {\n this.sqExpr = sqExpr;\n this.aggregate = aggregate;\n }\n FieldExprChangeAggregateRewriter.rewrite = function (sqExpr, aggregate) {\n return data.FieldExprPattern.visit(sqExpr, new FieldExprChangeAggregateRewriter(sqExpr, aggregate));\n };\n FieldExprChangeAggregateRewriter.prototype.visitPercentOfGrandTotal = function (pattern) {\n pattern.baseExpr = data.SQExprConverter.asFieldPattern(SQExprChangeAggregateRewriter.rewrite(SQExprBuilder.fieldExpr(pattern.baseExpr), this.aggregate));\n return SQExprBuilder.fieldExpr({ percentOfGrandTotal: pattern });\n };\n FieldExprChangeAggregateRewriter.prototype.visitColumn = function (column) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitColumnAggr = function (columnAggr) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariation) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitSelectRef = function (selectRef) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitEntity = function (entity) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitEntityAggr = function (entityAggr) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitHierarchy = function (hierarchy) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitHierarchyLevel = function (hierarchyLevel) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitMeasure = function (measure) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.visitPercentile = function (percentile) {\n return this.defaultRewrite();\n };\n FieldExprChangeAggregateRewriter.prototype.defaultRewrite = function () {\n return SQExprChangeAggregateRewriter.rewrite(this.sqExpr, this.aggregate);\n };\n return FieldExprChangeAggregateRewriter;\n }());\n var FieldExprRemoveAggregateRewriter = (function () {\n function FieldExprRemoveAggregateRewriter(sqExpr) {\n this.sqExpr = sqExpr;\n }\n FieldExprRemoveAggregateRewriter.rewrite = function (sqExpr) {\n return data.FieldExprPattern.visit(sqExpr, new FieldExprRemoveAggregateRewriter(sqExpr));\n };\n FieldExprRemoveAggregateRewriter.prototype.visitPercentOfGrandTotal = function (pattern) {\n return FieldExprRemoveAggregateRewriter.rewrite(SQExprBuilder.fieldExpr(pattern.baseExpr));\n };\n FieldExprRemoveAggregateRewriter.prototype.visitColumn = function (column) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitColumnAggr = function (columnAggr) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitColumnHierarchyLevelVariation = function (columnHierarchyLevelVariation) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitSelectRef = function (selectRef) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitEntity = function (entity) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitEntityAggr = function (entityAggr) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitHierarchy = function (hierarchy) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitHierarchyLevel = function (hierarchyLevel) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitHierarchyLevelAggr = function (hierarchyLevelAggr) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitMeasure = function (measure) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.visitPercentile = function (percentile) {\n return this.defaultRewrite();\n };\n FieldExprRemoveAggregateRewriter.prototype.defaultRewrite = function () {\n return SQExprRemoveAggregateRewriter.rewrite(this.sqExpr);\n };\n return FieldExprRemoveAggregateRewriter;\n }());\n var SQExprRemoveAggregateRewriter = (function (_super) {\n __extends(SQExprRemoveAggregateRewriter, _super);\n function SQExprRemoveAggregateRewriter() {\n _super.apply(this, arguments);\n }\n SQExprRemoveAggregateRewriter.prototype.visitAggr = function (expr) {\n return expr.arg;\n };\n SQExprRemoveAggregateRewriter.rewrite = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(SQExprRemoveAggregateRewriter.instance);\n };\n SQExprRemoveAggregateRewriter.instance = new SQExprRemoveAggregateRewriter();\n return SQExprRemoveAggregateRewriter;\n }(SQExprRootRewriter));\n var SQExprRemoveEntityVariablesRewriter = (function (_super) {\n __extends(SQExprRemoveEntityVariablesRewriter, _super);\n function SQExprRemoveEntityVariablesRewriter() {\n _super.apply(this, arguments);\n }\n SQExprRemoveEntityVariablesRewriter.prototype.visitEntity = function (expr) {\n if (expr.variable)\n return SQExprBuilder.entity(expr.schema, expr.entity);\n return expr;\n };\n SQExprRemoveEntityVariablesRewriter.rewrite = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(SQExprRemoveEntityVariablesRewriter.instance);\n };\n SQExprRemoveEntityVariablesRewriter.instance = new SQExprRemoveEntityVariablesRewriter();\n return SQExprRemoveEntityVariablesRewriter;\n }(data.SQExprRewriter));\n var SQExprRemovePercentOfGrandTotalRewriter = (function (_super) {\n __extends(SQExprRemovePercentOfGrandTotalRewriter, _super);\n function SQExprRemovePercentOfGrandTotalRewriter() {\n _super.apply(this, arguments);\n }\n SQExprRemovePercentOfGrandTotalRewriter.rewrite = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(SQExprRemovePercentOfGrandTotalRewriter.instance);\n };\n SQExprRemovePercentOfGrandTotalRewriter.prototype.visitDefault = function (expr) {\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n if (fieldExpr && fieldExpr.percentOfGrandTotal)\n expr = SQExprBuilder.fieldExpr(fieldExpr.percentOfGrandTotal.baseExpr);\n return expr;\n };\n SQExprRemovePercentOfGrandTotalRewriter.instance = new SQExprRemovePercentOfGrandTotalRewriter();\n return SQExprRemovePercentOfGrandTotalRewriter;\n }(SQExprRootRewriter));\n var SQExprSetPercentOfGrandTotalRewriter = (function (_super) {\n __extends(SQExprSetPercentOfGrandTotalRewriter, _super);\n function SQExprSetPercentOfGrandTotalRewriter() {\n _super.apply(this, arguments);\n }\n SQExprSetPercentOfGrandTotalRewriter.rewrite = function (expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(SQExprSetPercentOfGrandTotalRewriter.instance);\n };\n SQExprSetPercentOfGrandTotalRewriter.prototype.visitDefault = function (expr) {\n var fieldExpr = data.SQExprConverter.asFieldPattern(expr);\n if (fieldExpr && !fieldExpr.percentOfGrandTotal)\n expr = SQExprBuilder.fieldExpr({ percentOfGrandTotal: { baseExpr: data.SQExprConverter.asFieldPattern(expr) } });\n return expr;\n };\n SQExprSetPercentOfGrandTotalRewriter.instance = new SQExprSetPercentOfGrandTotalRewriter();\n return SQExprSetPercentOfGrandTotalRewriter;\n }(SQExprRootRewriter));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n var StringExtensions = jsCommon.StringExtensions;\n var SQExprUtils;\n (function (SQExprUtils) {\n function supportsArithmetic(expr, schema) {\n var metadata = expr.getMetadata(schema), type = metadata && metadata.type;\n if (!metadata || !type) {\n return false;\n }\n return type.numeric || type.dateTime || type.duration;\n }\n SQExprUtils.supportsArithmetic = supportsArithmetic;\n function indexOfExpr(items, searchElement) {\n debug.assertValue(items, 'items');\n debug.assertValue(searchElement, 'searchElement');\n for (var i = 0, len = items.length; i < len; i++) {\n if (data.SQExpr.equals(items[i], searchElement))\n return i;\n }\n return -1;\n }\n SQExprUtils.indexOfExpr = indexOfExpr;\n function sequenceEqual(x, y) {\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n var len = x.length;\n if (len !== y.length)\n return false;\n for (var i = 0; i < len; i++) {\n if (!data.SQExpr.equals(x[i], y[i]))\n return false;\n }\n return true;\n }\n SQExprUtils.sequenceEqual = sequenceEqual;\n function uniqueName(namedItems, expr, exprDefaultName) {\n debug.assertValue(namedItems, 'namedItems');\n // Determine all names\n var names = {};\n for (var i = 0, len = namedItems.length; i < len; i++)\n names[namedItems[i].name] = true;\n return StringExtensions.findUniqueName(names, exprDefaultName || defaultName(expr));\n }\n SQExprUtils.uniqueName = uniqueName;\n /** Generates a default expression name */\n function defaultName(expr, fallback) {\n if (fallback === void 0) { fallback = 'select'; }\n if (!expr)\n return fallback;\n return expr.accept(SQExprDefaultNameGenerator.instance, fallback);\n }\n SQExprUtils.defaultName = defaultName;\n /** Gets a value indicating whether the expr is a model measure or an aggregate. */\n function isMeasure(expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(IsMeasureVisitor.instance);\n }\n SQExprUtils.isMeasure = isMeasure;\n /** Gets a value indicating whether the expr is an AnyValue or equals comparison to AnyValue*/\n function isAnyValue(expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(IsAnyValueVisitor.instance);\n }\n SQExprUtils.isAnyValue = isAnyValue;\n /** Gets a value indicating whether the expr is a DefaultValue or equals comparison to DefaultValue*/\n function isDefaultValue(expr) {\n debug.assertValue(expr, 'expr');\n return expr.accept(IsDefaultValueVisitor.instance);\n }\n SQExprUtils.isDefaultValue = isDefaultValue;\n function discourageAggregation(expr, schema) {\n var capabilities = getSchemaCapabilities(expr, schema);\n return capabilities && capabilities.discourageQueryAggregateUsage;\n }\n SQExprUtils.discourageAggregation = discourageAggregation;\n function getAggregateBehavior(expr, schema) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(schema, 'schema');\n var column = getConceptualColumn(expr, schema);\n if (column)\n return column.aggregateBehavior;\n }\n SQExprUtils.getAggregateBehavior = getAggregateBehavior;\n function getSchemaCapabilities(expr, schema) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(schema, 'schema');\n var field = data.SQExprConverter.asFieldPattern(expr);\n if (!field)\n return;\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(field);\n var conceptualSchema = schema.schema(fieldExprItem.schema);\n if (conceptualSchema)\n return conceptualSchema.capabilities;\n }\n SQExprUtils.getSchemaCapabilities = getSchemaCapabilities;\n function getKpiMetadata(expr, schema) {\n var kpiStatusProperty = getKpiStatusProperty(expr, schema);\n if (kpiStatusProperty)\n return kpiStatusProperty.kpiValue.measure.kpi.statusMetadata;\n var kpiTrendProperty = getKpiTrendProperty(expr, schema);\n if (kpiTrendProperty)\n return kpiTrendProperty.kpiValue.measure.kpi.trendMetadata;\n }\n SQExprUtils.getKpiMetadata = getKpiMetadata;\n function getConceptualEntity(entityExpr, schema) {\n debug.assertValue(entityExpr, 'entityExpr');\n var conceptualEntity = schema\n .schema(entityExpr.schema)\n .entities\n .withName(entityExpr.entity);\n return conceptualEntity;\n }\n SQExprUtils.getConceptualEntity = getConceptualEntity;\n function getKpiStatusProperty(expr, schema) {\n var property = expr.getConceptualProperty(schema);\n if (!property)\n return;\n var kpiValue = property.kpiValue;\n if (kpiValue && kpiValue.measure.kpi.status === property)\n return property;\n }\n function getKpiTrendProperty(expr, schema) {\n var property = expr.getConceptualProperty(schema);\n if (!property)\n return;\n var kpiValue = property.kpiValue;\n if (kpiValue && kpiValue.measure.kpi.trend === property)\n return property;\n }\n function getDefaultValue(fieldSQExpr, schema) {\n var column = getConceptualColumn(fieldSQExpr, schema);\n if (column)\n return column.defaultValue;\n }\n SQExprUtils.getDefaultValue = getDefaultValue;\n function getConceptualColumn(fieldSQExpr, schema) {\n if (!fieldSQExpr || !schema)\n return;\n var sqField = data.SQExprConverter.asFieldPattern(fieldSQExpr);\n if (!sqField)\n return;\n var column = sqField.column;\n if (column) {\n if (schema.schema(column.schema) && sqField.column.name) {\n var property = schema.schema(column.schema).findProperty(column.entity, sqField.column.name);\n if (property)\n return property.column;\n }\n }\n else {\n var hierarchyLevelField = sqField.hierarchyLevel;\n if (hierarchyLevelField) {\n var fieldExprItem = data.FieldExprPattern.toFieldExprEntityItemPattern(sqField);\n var schemaName = fieldExprItem.schema;\n if (schema.schema(schemaName)) {\n var hierarchy = schema.schema(schemaName)\n .findHierarchy(fieldExprItem.entity, hierarchyLevelField.name);\n if (hierarchy) {\n var hierarchyLevel = hierarchy.levels.withName(hierarchyLevelField.level);\n if (hierarchyLevel && hierarchyLevel.column)\n return hierarchyLevel.column.column;\n }\n }\n }\n }\n }\n function getDefaultValues(fieldSQExprs, schema) {\n if (_.isEmpty(fieldSQExprs) || !schema)\n return;\n var result = [];\n for (var _i = 0, fieldSQExprs_2 = fieldSQExprs; _i < fieldSQExprs_2.length; _i++) {\n var sqExpr = fieldSQExprs_2[_i];\n var defaultValue = getDefaultValue(sqExpr, schema);\n if (defaultValue)\n result.push(defaultValue);\n }\n return result;\n }\n SQExprUtils.getDefaultValues = getDefaultValues;\n /** Return compare or and expression for key value pairs. */\n function getDataViewScopeIdentityComparisonExpr(fieldsExpr, values) {\n debug.assert(fieldsExpr.length === values.length, \"fileds and values need to be the same size\");\n var compareExprs = [];\n for (var i = 0; i < fieldsExpr.length; i++) {\n compareExprs.push(data.SQExprBuilder.compare(data.QueryComparisonKind.Equal, fieldsExpr[i], values[i]));\n }\n if (_.isEmpty(compareExprs))\n return;\n var resultExpr;\n for (var _i = 0, compareExprs_1 = compareExprs; _i < compareExprs_1.length; _i++) {\n var compareExpr = compareExprs_1[_i];\n resultExpr = data.SQExprBuilder.and(resultExpr, compareExpr);\n }\n return resultExpr;\n }\n SQExprUtils.getDataViewScopeIdentityComparisonExpr = getDataViewScopeIdentityComparisonExpr;\n function getActiveTablesNames(queryDefn) {\n var tables = [];\n if (queryDefn) {\n var selectedItems = queryDefn.from();\n if (selectedItems !== undefined) {\n for (var _i = 0, _a = selectedItems.keys(); _i < _a.length; _i++) {\n var key = _a[_i];\n var entityObj = selectedItems.entity(key);\n if (tables.indexOf(entityObj.entity) < 0)\n tables.push(entityObj.entity);\n }\n }\n }\n return tables;\n }\n SQExprUtils.getActiveTablesNames = getActiveTablesNames;\n function isRelatedToMany(schema, sourceExpr, targetExpr) {\n return isRelated(schema, sourceExpr, targetExpr, 0 /* ZeroOrOne */, 2 /* Many */) ||\n isRelated(schema, targetExpr, sourceExpr, 2 /* Many */, 0 /* ZeroOrOne */);\n }\n SQExprUtils.isRelatedToMany = isRelatedToMany;\n function isRelatedToOne(schema, sourceExpr, targetExpr) {\n return isRelated(schema, sourceExpr, targetExpr, 2 /* Many */, 0 /* ZeroOrOne */) ||\n isRelated(schema, targetExpr, sourceExpr, 0 /* ZeroOrOne */, 2 /* Many */);\n }\n SQExprUtils.isRelatedToOne = isRelatedToOne;\n function isRelated(schema, sourceExpr, targetExpr, sourceMultiplicity, targetMultiplicity) {\n var source = SQExprUtils.getConceptualEntity(sourceExpr, schema);\n debug.assertValue(source, \"could not resolve conceptual entity form sourceExpr.\");\n if (_.isEmpty(source.navigationProperties))\n return false;\n var target = SQExprUtils.getConceptualEntity(targetExpr, schema);\n debug.assertValue(target, \"could not resolve conceptual entity form targetExpr.\");\n var queue = [];\n queue.push(source);\n // walk the relationship path from source.\n while (!_.isEmpty(queue)) {\n var current = queue.shift();\n var navProperties = current.navigationProperties;\n if (_.isEmpty(navProperties))\n continue;\n for (var _i = 0, navProperties_1 = navProperties; _i < navProperties_1.length; _i++) {\n var navProperty = navProperties_1[_i];\n if (!navProperty.isActive)\n continue;\n if (navProperty.targetMultiplicity === targetMultiplicity && navProperty.sourceMultiplicity === sourceMultiplicity) {\n if (navProperty.targetEntity === target)\n return true;\n queue.push(navProperty.targetEntity);\n }\n }\n }\n return false;\n }\n function isRelatedOneToOne(schema, sourceExpr, targetExpr) {\n var source = SQExprUtils.getConceptualEntity(sourceExpr, schema);\n debug.assertValue(source, \"could not resolve conceptual entity form sourceExpr.\");\n var target = SQExprUtils.getConceptualEntity(targetExpr, schema);\n debug.assertValue(target, \"could not resolve conceptual entity form targetExpr.\");\n var sourceNavigations = source.navigationProperties;\n var targetNavigations = target.navigationProperties;\n if (_.isEmpty(sourceNavigations) && _.isEmpty(targetNavigations))\n return false;\n return hasOneToOneNavigation(sourceNavigations, target) || hasOneToOneNavigation(targetNavigations, source);\n }\n SQExprUtils.isRelatedOneToOne = isRelatedOneToOne;\n function hasOneToOneNavigation(navigationProperties, targetEntity) {\n if (_.isEmpty(navigationProperties))\n return false;\n for (var _i = 0, navigationProperties_1 = navigationProperties; _i < navigationProperties_1.length; _i++) {\n var navigationProperty = navigationProperties_1[_i];\n if (!navigationProperty.isActive)\n continue;\n if (navigationProperty.targetEntity !== targetEntity)\n continue;\n if (navigationProperty.sourceMultiplicity === 0 /* ZeroOrOne */ &&\n navigationProperty.targetMultiplicity === 0 /* ZeroOrOne */) {\n return true;\n }\n }\n return false;\n }\n /** Performs a union of the 2 arrays with SQExpr.equals as comparator to skip duplicate items,\n and returns a new array. When available, we should use _.unionWith from lodash. */\n function concatUnique(leftExprs, rightExprs) {\n debug.assertValue(leftExprs, 'leftExprs');\n debug.assertValue(rightExprs, 'rightExprs');\n var concatExprs = ArrayExtensions.copy(leftExprs);\n for (var _i = 0, rightExprs_1 = rightExprs; _i < rightExprs_1.length; _i++) {\n var expr = rightExprs_1[_i];\n if (indexOfExpr(concatExprs, expr) === -1) {\n concatExprs.push(expr);\n }\n }\n return concatExprs;\n }\n SQExprUtils.concatUnique = concatUnique;\n var SQExprDefaultNameGenerator = (function (_super) {\n __extends(SQExprDefaultNameGenerator, _super);\n function SQExprDefaultNameGenerator() {\n _super.apply(this, arguments);\n }\n SQExprDefaultNameGenerator.prototype.visitEntity = function (expr) {\n return expr.entity;\n };\n SQExprDefaultNameGenerator.prototype.visitColumnRef = function (expr) {\n return expr.source.accept(this) + '.' + expr.ref;\n };\n SQExprDefaultNameGenerator.prototype.visitMeasureRef = function (expr, fallback) {\n return expr.source.accept(this) + '.' + expr.ref;\n };\n SQExprDefaultNameGenerator.prototype.visitAggr = function (expr, fallback) {\n return data.QueryAggregateFunction[expr.func] + '(' + expr.arg.accept(this) + ')';\n };\n SQExprDefaultNameGenerator.prototype.visitPercentile = function (expr, fallback) {\n var func = expr.exclusive\n ? 'Percentile.Exc('\n : 'Percentile.Inc(';\n return func + expr.arg.accept(this) + ', ' + expr.k + ')';\n };\n SQExprDefaultNameGenerator.prototype.visitArithmetic = function (expr, fallback) {\n return powerbi.data.getArithmeticOperatorName(expr.operator) + '(' + expr.left.accept(this) + ', ' + expr.right.accept(this) + ')';\n };\n SQExprDefaultNameGenerator.prototype.visitConstant = function (expr) {\n return 'const';\n };\n SQExprDefaultNameGenerator.prototype.visitDefault = function (expr, fallback) {\n return fallback || 'expr';\n };\n SQExprDefaultNameGenerator.instance = new SQExprDefaultNameGenerator();\n return SQExprDefaultNameGenerator;\n }(data.DefaultSQExprVisitorWithArg));\n var IsMeasureVisitor = (function (_super) {\n __extends(IsMeasureVisitor, _super);\n function IsMeasureVisitor() {\n _super.apply(this, arguments);\n }\n IsMeasureVisitor.prototype.visitMeasureRef = function (expr) {\n return true;\n };\n IsMeasureVisitor.prototype.visitAggr = function (expr) {\n return true;\n };\n IsMeasureVisitor.prototype.visitArithmetic = function (expr) {\n return true;\n };\n IsMeasureVisitor.prototype.visitDefault = function (expr) {\n return false;\n };\n IsMeasureVisitor.instance = new IsMeasureVisitor();\n return IsMeasureVisitor;\n }(data.DefaultSQExprVisitor));\n var IsDefaultValueVisitor = (function (_super) {\n __extends(IsDefaultValueVisitor, _super);\n function IsDefaultValueVisitor() {\n _super.apply(this, arguments);\n }\n IsDefaultValueVisitor.prototype.visitCompare = function (expr) {\n if (expr.comparison !== data.QueryComparisonKind.Equal)\n return false;\n return expr.right.accept(this);\n };\n IsDefaultValueVisitor.prototype.visitAnd = function (expr) {\n return expr.left.accept(this) && expr.right.accept(this);\n };\n IsDefaultValueVisitor.prototype.visitDefaultValue = function (expr) {\n return true;\n };\n IsDefaultValueVisitor.prototype.visitDefault = function (expr) {\n return false;\n };\n IsDefaultValueVisitor.instance = new IsDefaultValueVisitor();\n return IsDefaultValueVisitor;\n }(data.DefaultSQExprVisitor));\n var IsAnyValueVisitor = (function (_super) {\n __extends(IsAnyValueVisitor, _super);\n function IsAnyValueVisitor() {\n _super.apply(this, arguments);\n }\n IsAnyValueVisitor.prototype.visitCompare = function (expr) {\n if (expr.comparison !== data.QueryComparisonKind.Equal)\n return false;\n return expr.right.accept(this);\n };\n IsAnyValueVisitor.prototype.visitAnd = function (expr) {\n return expr.left.accept(this) && expr.right.accept(this);\n };\n IsAnyValueVisitor.prototype.visitAnyValue = function (expr) {\n return true;\n };\n IsAnyValueVisitor.prototype.visitDefault = function (expr) {\n return false;\n };\n IsAnyValueVisitor.instance = new IsAnyValueVisitor();\n return IsAnyValueVisitor;\n }(data.DefaultSQExprVisitor));\n })(SQExprUtils = data.SQExprUtils || (data.SQExprUtils = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var SemanticQueryRewriter = (function () {\n function SemanticQueryRewriter(exprRewriter) {\n this.exprRewriter = exprRewriter;\n }\n SemanticQueryRewriter.prototype.rewriteFrom = function (fromValue) {\n var fromContents = {};\n var originalFrom = fromValue, originalFromKeys = originalFrom.keys();\n for (var i = 0, len = originalFromKeys.length; i < len; i++) {\n var keyName = originalFromKeys[i], originalEntityRef = originalFrom.entity(keyName), originalEntityExpr = data.SQExprBuilder.entity(originalEntityRef.schema, originalEntityRef.entity, keyName), updatedEntityExpr = originalEntityExpr.accept(this.exprRewriter);\n fromContents[keyName] = {\n schema: updatedEntityExpr.schema,\n entity: updatedEntityExpr.entity,\n };\n }\n return new data.SQFrom(fromContents);\n };\n SemanticQueryRewriter.prototype.rewriteSelect = function (selectItems, from) {\n debug.assertValue(selectItems, 'selectItems');\n debug.assertValue(from, 'from');\n return this.rewriteNamedSQExpressions(selectItems, from);\n };\n SemanticQueryRewriter.prototype.rewriteGroupBy = function (groupByitems, from) {\n debug.assertAnyValue(groupByitems, 'groupByitems');\n debug.assertValue(from, 'from');\n if (_.isEmpty(groupByitems))\n return;\n return this.rewriteNamedSQExpressions(groupByitems, from);\n };\n SemanticQueryRewriter.prototype.rewriteNamedSQExpressions = function (expressions, from) {\n var _this = this;\n debug.assertValue(expressions, 'expressions');\n return _.map(expressions, function (item) {\n return {\n name: item.name,\n expr: data.SQExprRewriterWithSourceRenames.rewrite(item.expr.accept(_this.exprRewriter), from)\n };\n });\n };\n SemanticQueryRewriter.prototype.rewriteOrderBy = function (orderByItems, from) {\n debug.assertAnyValue(orderByItems, 'orderByItems');\n debug.assertValue(from, 'from');\n if (_.isEmpty(orderByItems))\n return;\n var orderBy = [];\n for (var i = 0, len = orderByItems.length; i < len; i++) {\n var item = orderByItems[i], updatedExpr = data.SQExprRewriterWithSourceRenames.rewrite(item.expr.accept(this.exprRewriter), from);\n orderBy.push({\n direction: item.direction,\n expr: updatedExpr,\n });\n }\n return orderBy;\n };\n SemanticQueryRewriter.prototype.rewriteWhere = function (whereItems, from) {\n var _this = this;\n debug.assertAnyValue(whereItems, 'whereItems');\n debug.assertValue(from, 'from');\n if (_.isEmpty(whereItems))\n return;\n var where = [];\n for (var i = 0, len = whereItems.length; i < len; i++) {\n var originalWhere = whereItems[i];\n var updatedWhere = {\n condition: data.SQExprRewriterWithSourceRenames.rewrite(originalWhere.condition.accept(this.exprRewriter), from),\n };\n if (originalWhere.target)\n updatedWhere.target = _.map(originalWhere.target, function (e) { return data.SQExprRewriterWithSourceRenames.rewrite(e.accept(_this.exprRewriter), from); });\n where.push(updatedWhere);\n }\n return where;\n };\n return SemanticQueryRewriter;\n }());\n data.SemanticQueryRewriter = SemanticQueryRewriter;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n /**\n * Represents a semantic query that is:\n * 1) Round-trippable with a JSON QueryDefinition.\n * 2) Immutable\n * 3) Long-lived and does not have strong references to a conceptual model (only names).\n */\n var SemanticQuery = (function () {\n function SemanticQuery(from, where, orderBy, select, groupBy) {\n debug.assertValue(from, 'from');\n debug.assertValue(select, 'select');\n this.fromValue = from;\n this.whereItems = where;\n this.orderByItems = orderBy;\n this.selectItems = select;\n this.groupByItems = groupBy;\n }\n SemanticQuery.create = function () {\n if (!SemanticQuery.empty)\n SemanticQuery.empty = new SemanticQuery(new SQFrom(), null, null, [], null);\n return SemanticQuery.empty;\n };\n SemanticQuery.createWithTrimmedFrom = function (from, where, orderBy, select, groupBy) {\n var unreferencedKeyFinder = new UnreferencedKeyFinder(from.keys());\n // Where\n if (where) {\n for (var i = 0, len = where.length; i < len; i++) {\n var filter = where[i];\n filter.condition.accept(unreferencedKeyFinder);\n var filterTarget = filter.target;\n if (filterTarget) {\n for (var j = 0, jlen = filterTarget.length; j < jlen; j++)\n if (filterTarget[j])\n filterTarget[j].accept(unreferencedKeyFinder);\n }\n }\n }\n // OrderBy\n if (orderBy) {\n for (var i = 0, len = orderBy.length; i < len; i++)\n orderBy[i].expr.accept(unreferencedKeyFinder);\n }\n // Select\n for (var i = 0, len = select.length; i < len; i++)\n select[i].expr.accept(unreferencedKeyFinder);\n // GroupBy\n if (groupBy) {\n for (var i = 0, len = groupBy.length; i < len; i++)\n groupBy[i].expr.accept(unreferencedKeyFinder);\n }\n var unreferencedKeys = unreferencedKeyFinder.result();\n for (var i = 0, len = unreferencedKeys.length; i < len; i++)\n from.remove(unreferencedKeys[i]);\n return new SemanticQuery(from, where, orderBy, select, groupBy);\n };\n SemanticQuery.prototype.from = function () {\n return this.fromValue.clone();\n };\n SemanticQuery.prototype.select = function (values) {\n if (_.isEmpty(arguments))\n return this.getSelect();\n return this.setSelect(values);\n };\n SemanticQuery.prototype.getSelect = function () {\n return SemanticQuery.createNamedExpressionArray(this.selectItems);\n };\n SemanticQuery.createNamedExpressionArray = function (items) {\n return ArrayExtensions.extendWithName(_.map(items, function (s) {\n return {\n name: s.name,\n expr: s.expr,\n };\n }));\n };\n SemanticQuery.prototype.setSelect = function (values) {\n var from = this.fromValue.clone();\n var selectItems = SemanticQuery.rewriteExpressionsWithSourceRenames(values, from);\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, selectItems, this.groupByItems);\n };\n SemanticQuery.rewriteExpressionsWithSourceRenames = function (values, from) {\n var items = [];\n for (var i = 0, len = values.length; i < len; i++) {\n var value = values[i];\n items.push({\n name: value.name,\n expr: SQExprRewriterWithSourceRenames.rewrite(value.expr, from)\n });\n }\n return items;\n };\n /** Removes the given expression from the select. */\n SemanticQuery.prototype.removeSelect = function (expr) {\n debug.assertValue(expr, 'expr');\n var originalItems = this.selectItems, selectItems = [];\n for (var i = 0, len = originalItems.length; i < len; i++) {\n var originalExpr = originalItems[i];\n if (data.SQExpr.equals(originalExpr.expr, expr))\n continue;\n selectItems.push(originalExpr);\n }\n return SemanticQuery.createWithTrimmedFrom(this.fromValue.clone(), this.whereItems, this.orderByItems, selectItems, this.groupByItems);\n };\n /** Removes the given expression from order by. */\n SemanticQuery.prototype.removeOrderBy = function (expr) {\n var sorts = this.orderBy();\n for (var i = sorts.length - 1; i >= 0; i--) {\n if (data.SQExpr.equals(sorts[i].expr, expr))\n sorts.splice(i, 1);\n }\n return SemanticQuery.createWithTrimmedFrom(this.fromValue.clone(), this.whereItems, sorts, this.selectItems, this.groupByItems);\n };\n SemanticQuery.prototype.selectNameOf = function (expr) {\n var index = data.SQExprUtils.indexOfExpr(_.map(this.selectItems, function (s) { return s.expr; }), expr);\n if (index >= 0)\n return this.selectItems[index].name;\n };\n SemanticQuery.prototype.setSelectAt = function (index, expr) {\n debug.assertValue(expr, 'expr');\n if (index >= this.selectItems.length)\n return;\n var select = this.select(), from = this.fromValue.clone(), originalName = select[index].name;\n select[index] = {\n name: originalName,\n expr: SQExprRewriterWithSourceRenames.rewrite(expr, from)\n };\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, select, this.groupByItems);\n };\n /** Adds a the expression to the select clause. */\n SemanticQuery.prototype.addSelect = function (expr, exprName) {\n debug.assertValue(expr, 'expr');\n var selectItems = this.select(), from = this.fromValue.clone();\n selectItems.push(this.createNamedExpr(selectItems, from, expr, exprName));\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, selectItems, this.groupByItems);\n };\n SemanticQuery.prototype.createNamedExpr = function (currentNames, from, expr, exprName) {\n return {\n name: data.SQExprUtils.uniqueName(currentNames, expr, exprName),\n expr: SQExprRewriterWithSourceRenames.rewrite(expr, from)\n };\n };\n SemanticQuery.prototype.groupBy = function (values) {\n if (_.isEmpty(arguments))\n return this.getGroupBy();\n return this.setGroupBy(values);\n };\n SemanticQuery.prototype.getGroupBy = function () {\n return SemanticQuery.createNamedExpressionArray(this.groupByItems);\n };\n SemanticQuery.prototype.setGroupBy = function (values) {\n var from = this.fromValue.clone();\n var groupByItems = SemanticQuery.rewriteExpressionsWithSourceRenames(values, from);\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, this.selectItems, groupByItems);\n };\n SemanticQuery.prototype.addGroupBy = function (expr) {\n debug.assertValue(expr, 'expr');\n var groupByItems = this.groupBy(), from = this.fromValue.clone();\n groupByItems.push(this.createNamedExpr(groupByItems, from, expr));\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, this.selectItems, groupByItems);\n };\n SemanticQuery.prototype.orderBy = function (values) {\n if (_.isEmpty(arguments))\n return this.getOrderBy();\n return this.setOrderBy(values);\n };\n SemanticQuery.prototype.getOrderBy = function () {\n var result = [];\n var orderBy = this.orderByItems;\n if (orderBy) {\n for (var i = 0, len = orderBy.length; i < len; i++) {\n var clause = orderBy[i];\n result.push({\n expr: clause.expr,\n direction: clause.direction,\n });\n }\n }\n return result;\n };\n SemanticQuery.prototype.setOrderBy = function (values) {\n debug.assertValue(values, 'values');\n var updatedOrderBy = [], from = this.fromValue.clone();\n for (var i = 0, len = values.length; i < len; i++) {\n var clause = values[i];\n updatedOrderBy.push({\n expr: SQExprRewriterWithSourceRenames.rewrite(clause.expr, from),\n direction: clause.direction,\n });\n }\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, updatedOrderBy, this.selectItems, this.groupByItems);\n };\n SemanticQuery.prototype.where = function (values) {\n if (_.isEmpty(arguments))\n return this.getWhere();\n return this.setWhere(values);\n };\n SemanticQuery.prototype.getWhere = function () {\n var result = [];\n var whereItems = this.whereItems;\n if (whereItems) {\n for (var i = 0, len = whereItems.length; i < len; i++)\n result.push(whereItems[i]);\n }\n return result;\n };\n SemanticQuery.prototype.setWhere = function (values) {\n debug.assertValue(values, 'values');\n var updatedWhere = [], from = this.fromValue.clone();\n for (var i = 0, len = values.length; i < len; i++) {\n var filter = values[i];\n var updatedFilter = {\n condition: SQExprRewriterWithSourceRenames.rewrite(filter.condition, from),\n };\n var filterTarget = filter.target;\n if (filterTarget) {\n updatedFilter.target = [];\n for (var j = 0, jlen = filterTarget.length; j < jlen; j++)\n if (filterTarget[j]) {\n var updatedTarget = SQExprRewriterWithSourceRenames.rewrite(filterTarget[j], from);\n updatedFilter.target.push(updatedTarget);\n }\n }\n updatedWhere.push(updatedFilter);\n }\n return SemanticQuery.createWithTrimmedFrom(from, updatedWhere, this.orderByItems, this.selectItems, this.groupByItems);\n };\n SemanticQuery.prototype.addWhere = function (filter) {\n debug.assertValue(filter, 'filter');\n var updatedWhere = this.where(), incomingWhere = filter.where(), from = this.fromValue.clone();\n for (var i = 0, len = incomingWhere.length; i < len; i++) {\n var clause = incomingWhere[i];\n var updatedClause = {\n condition: SQExprRewriterWithSourceRenames.rewrite(clause.condition, from),\n };\n if (clause.target)\n updatedClause.target = _.map(clause.target, function (t) { return SQExprRewriterWithSourceRenames.rewrite(t, from); });\n updatedWhere.push(updatedClause);\n }\n return SemanticQuery.createWithTrimmedFrom(from, updatedWhere, this.orderByItems, this.selectItems, this.groupByItems);\n };\n SemanticQuery.prototype.rewrite = function (exprRewriter) {\n var rewriter = new data.SemanticQueryRewriter(exprRewriter);\n var from = rewriter.rewriteFrom(this.fromValue);\n var where = rewriter.rewriteWhere(this.whereItems, from);\n var orderBy = rewriter.rewriteOrderBy(this.orderByItems, from);\n var select = rewriter.rewriteSelect(this.selectItems, from);\n var groupBy = rewriter.rewriteGroupBy(this.groupByItems, from);\n return SemanticQuery.createWithTrimmedFrom(from, where, orderBy, select, groupBy);\n };\n return SemanticQuery;\n }());\n data.SemanticQuery = SemanticQuery;\n /** Represents a semantic filter condition. Round-trippable with a JSON FilterDefinition. Instances of this class are immutable. */\n var SemanticFilter = (function () {\n function SemanticFilter(from, where) {\n debug.assertValue(from, 'from');\n debug.assertValue(where, 'where');\n this.fromValue = from;\n this.whereItems = where;\n }\n SemanticFilter.fromSQExpr = function (contract) {\n debug.assertValue(contract, 'contract');\n var from = new SQFrom();\n var rewrittenContract = SQExprRewriterWithSourceRenames.rewrite(contract, from);\n // DEVNOTE targets of some filters are visual specific and will get resolved only during query generation.\n // Thus not setting a target here.\n var where = [{\n condition: rewrittenContract\n }];\n return new SemanticFilter(from, where);\n };\n SemanticFilter.getDefaultValueFilter = function (fieldSQExprs) {\n return SemanticFilter.getDataViewScopeIdentityComparisonFilters(fieldSQExprs, data.SQExprBuilder.defaultValue());\n };\n SemanticFilter.getAnyValueFilter = function (fieldSQExprs) {\n return SemanticFilter.getDataViewScopeIdentityComparisonFilters(fieldSQExprs, data.SQExprBuilder.anyValue());\n };\n SemanticFilter.getDataViewScopeIdentityComparisonFilters = function (fieldSQExprs, value) {\n debug.assertValue(fieldSQExprs, 'fieldSQExprs');\n debug.assertValue(value, 'value');\n if (fieldSQExprs instanceof Array) {\n var values = Array.apply(null, Array(fieldSQExprs.length)).map(function () { return value; });\n return SemanticFilter.fromSQExpr(data.SQExprUtils.getDataViewScopeIdentityComparisonExpr(fieldSQExprs, values));\n }\n return SemanticFilter.fromSQExpr(data.SQExprBuilder.equal(fieldSQExprs, value));\n };\n SemanticFilter.prototype.from = function () {\n return this.fromValue.clone();\n };\n SemanticFilter.prototype.conditions = function () {\n var expressions = [];\n var where = this.whereItems;\n for (var i = 0, len = where.length; i < len; i++) {\n var filter = where[i];\n expressions.push(filter.condition);\n }\n return expressions;\n };\n SemanticFilter.prototype.where = function () {\n var result = [];\n var whereItems = this.whereItems;\n for (var i = 0, len = whereItems.length; i < len; i++)\n result.push(whereItems[i]);\n return result;\n };\n SemanticFilter.prototype.rewrite = function (exprRewriter) {\n var rewriter = new data.SemanticQueryRewriter(exprRewriter);\n var from = rewriter.rewriteFrom(this.fromValue);\n var where = rewriter.rewriteWhere(this.whereItems, from);\n return new SemanticFilter(from, where);\n };\n SemanticFilter.prototype.validate = function (schema, aggrUtils, errors) {\n var validator = new data.SQExprValidationVisitor(schema, aggrUtils, errors);\n this.rewrite(validator);\n return validator.errors;\n };\n /** Merges a list of SemanticFilters into one. */\n SemanticFilter.merge = function (filters) {\n if (_.isEmpty(filters))\n return null;\n if (filters.length === 1)\n return filters[0];\n var firstFilter = filters[0];\n var from = firstFilter.from(), where = ArrayExtensions.take(firstFilter.whereItems, firstFilter.whereItems.length);\n for (var i = 1, len = filters.length; i < len; i++)\n SemanticFilter.applyFilter(filters[i], from, where);\n return new SemanticFilter(from, where);\n };\n SemanticFilter.isDefaultFilter = function (filter) {\n if (!filter || filter.where().length !== 1)\n return false;\n return data.SQExprUtils.isDefaultValue(filter.where()[0].condition);\n };\n SemanticFilter.isAnyFilter = function (filter) {\n if (!filter || filter.where().length !== 1)\n return false;\n return data.SQExprUtils.isAnyValue(filter.where()[0].condition);\n };\n SemanticFilter.isSameFilter = function (leftFilter, rightFilter) {\n if (jsCommon.JsonComparer.equals(leftFilter, rightFilter)) {\n return !((SemanticFilter.isDefaultFilter(leftFilter) && SemanticFilter.isAnyFilter(rightFilter))\n || (SemanticFilter.isAnyFilter(leftFilter) && SemanticFilter.isDefaultFilter(rightFilter)));\n }\n return false;\n };\n SemanticFilter.applyFilter = function (filter, from, where) {\n debug.assertValue(filter, 'filter');\n debug.assertValue(from, 'from');\n debug.assertValue(where, 'where');\n // Where\n var filterWhereItems = filter.whereItems;\n for (var i = 0; i < filterWhereItems.length; i++) {\n var filterWhereItem = filterWhereItems[i];\n var updatedWhereItem = {\n condition: SQExprRewriterWithSourceRenames.rewrite(filterWhereItem.condition, from),\n };\n if (filterWhereItem.target)\n updatedWhereItem.target = _.map(filterWhereItem.target, function (e) { return SQExprRewriterWithSourceRenames.rewrite(e, from); });\n where.push(updatedWhereItem);\n }\n };\n return SemanticFilter;\n }());\n data.SemanticFilter = SemanticFilter;\n /** Represents a SemanticQuery/SemanticFilter from clause. */\n var SQFrom = (function () {\n function SQFrom(items) {\n this.items = items || {};\n }\n SQFrom.prototype.keys = function () {\n return Object.keys(this.items);\n };\n SQFrom.prototype.entity = function (key) {\n return this.items[key];\n };\n SQFrom.prototype.ensureEntity = function (entity, desiredVariableName) {\n debug.assertValue(entity, 'entity');\n // 1) Reuse a reference to the entity among the already referenced\n var keys = this.keys();\n for (var i_1 = 0, len = keys.length; i_1 < len; i_1++) {\n var key = keys[i_1], item = this.items[key];\n if (item && entity.entity === item.entity && entity.schema === item.schema)\n return { name: key };\n }\n // 2) Add a reference to the entity\n var candidateName = desiredVariableName || this.candidateName(entity.entity), uniqueName = candidateName, i = 2;\n while (this.items[uniqueName]) {\n uniqueName = candidateName + i++;\n }\n this.items[uniqueName] = entity;\n return { name: uniqueName, new: true };\n };\n SQFrom.prototype.remove = function (key) {\n delete this.items[key];\n };\n /** Converts the entity name into a short reference name. Follows the Semantic Query convention of a short name. */\n SQFrom.prototype.candidateName = function (ref) {\n debug.assertValue(ref, 'ref');\n var idx = ref.lastIndexOf('.');\n if (idx >= 0 && (idx !== ref.length - 1))\n ref = ref.substr(idx + 1);\n return ref.substring(0, 1).toLowerCase();\n };\n SQFrom.prototype.clone = function () {\n // NOTE: consider deprecating this method and instead making QueryFrom be CopyOnWrite (currently we proactively clone).\n var cloned = new SQFrom();\n // NOTE: we use extend rather than prototypical inheritance on items because we use Object.keys.\n $.extend(cloned.items, this.items);\n return cloned;\n };\n return SQFrom;\n }());\n data.SQFrom = SQFrom;\n var SQExprRewriterWithSourceRenames = (function (_super) {\n __extends(SQExprRewriterWithSourceRenames, _super);\n function SQExprRewriterWithSourceRenames(renames) {\n debug.assertValue(renames, 'renames');\n _super.call(this);\n this.renames = renames;\n }\n SQExprRewriterWithSourceRenames.prototype.visitEntity = function (expr) {\n var updatedName = this.renames[expr.entity];\n if (updatedName)\n return new data.SQEntityExpr(expr.schema, expr.entity, updatedName);\n return _super.prototype.visitEntity.call(this, expr);\n };\n SQExprRewriterWithSourceRenames.prototype.rewriteFilter = function (filter) {\n debug.assertValue(filter, 'filter');\n var updatedTargets = undefined;\n if (filter.target)\n updatedTargets = this.rewriteArray(filter.target);\n var updatedCondition = filter.condition.accept(this);\n if (filter.condition === updatedCondition && filter.target === updatedTargets)\n return filter;\n var updatedFilter = {\n condition: updatedCondition,\n };\n if (updatedTargets)\n updatedFilter.target = updatedTargets;\n return updatedFilter;\n };\n SQExprRewriterWithSourceRenames.prototype.rewriteArray = function (exprs) {\n debug.assertValue(exprs, 'exprs');\n var updatedExprs;\n for (var i = 0, len = exprs.length; i < len; i++) {\n var expr = exprs[i], rewrittenExpr = expr.accept(this);\n if (expr !== rewrittenExpr && !updatedExprs)\n updatedExprs = ArrayExtensions.take(exprs, i);\n if (updatedExprs)\n updatedExprs.push(rewrittenExpr);\n }\n return updatedExprs || exprs;\n };\n SQExprRewriterWithSourceRenames.rewrite = function (expr, from) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(from, 'from');\n var renames = QuerySourceRenameDetector.run(expr, from);\n var rewriter = new SQExprRewriterWithSourceRenames(renames);\n return expr.accept(rewriter);\n };\n return SQExprRewriterWithSourceRenames;\n }(data.SQExprRewriter));\n data.SQExprRewriterWithSourceRenames = SQExprRewriterWithSourceRenames;\n /** Responsible for updating a QueryFrom based on SQExpr references. */\n var QuerySourceRenameDetector = (function (_super) {\n __extends(QuerySourceRenameDetector, _super);\n function QuerySourceRenameDetector(from) {\n debug.assertValue(from, 'from');\n _super.call(this);\n this.from = from;\n this.renames = {};\n }\n QuerySourceRenameDetector.run = function (expr, from) {\n var detector = new QuerySourceRenameDetector(from);\n expr.accept(detector);\n return detector.renames;\n };\n QuerySourceRenameDetector.prototype.visitEntity = function (expr) {\n // TODO: Renames must take the schema into account, not just entity set name.\n var existingEntity = this.from.entity(expr.variable);\n if (existingEntity && existingEntity.schema === expr.schema && existingEntity.entity === expr.entity)\n return;\n var actualEntity = this.from.ensureEntity({\n schema: expr.schema,\n entity: expr.entity,\n }, expr.variable);\n this.renames[expr.entity] = actualEntity.name;\n };\n return QuerySourceRenameDetector;\n }(data.DefaultSQExprVisitorWithTraversal));\n /** Visitor for finding unreferenced sources. */\n var UnreferencedKeyFinder = (function (_super) {\n __extends(UnreferencedKeyFinder, _super);\n function UnreferencedKeyFinder(keys) {\n debug.assertValue(keys, 'keys');\n _super.call(this);\n this.keys = keys;\n }\n UnreferencedKeyFinder.prototype.visitEntity = function (expr) {\n var index = this.keys.indexOf(expr.variable);\n if (index >= 0)\n this.keys.splice(index, 1);\n };\n UnreferencedKeyFinder.prototype.result = function () {\n return this.keys;\n };\n return UnreferencedKeyFinder;\n }(data.DefaultSQExprVisitorWithTraversal));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var DataViewTransform = powerbi.data.DataViewTransform;\n var SQExprBuilder = powerbi.data.SQExprBuilder;\n function createCategoricalDataViewBuilder() {\n return new CategoricalDataViewBuilder();\n }\n data.createCategoricalDataViewBuilder = createCategoricalDataViewBuilder;\n var CategoricalDataViewBuilder = (function () {\n function CategoricalDataViewBuilder() {\n this.categories = [];\n this.staticMeasureColumns = [];\n this.dynamicMeasureColumns = [];\n this.columnIndex = 0;\n }\n CategoricalDataViewBuilder.prototype.withCategory = function (options) {\n var categoryValues = options.values, identityFrom = options.identityFrom, type = options.source.type;\n var categoryColumn = {\n source: options.source,\n identityFields: options.identityFrom.fields,\n identity: options.identityFrom.identities || [],\n values: categoryValues,\n };\n if (!options.identityFrom.identities) {\n for (var categoryIndex = 0, categoryLength = categoryValues.length; categoryIndex < categoryLength; categoryIndex++) {\n categoryColumn.identity.push(getScopeIdentity(identityFrom, categoryIndex, categoryValues[categoryIndex], type));\n }\n }\n if (!this.categories)\n this.categories = [];\n this.categories.push(categoryColumn);\n return this;\n };\n CategoricalDataViewBuilder.prototype.withCategories = function (categories) {\n if (_.isEmpty(this.categories))\n this.categories = categories;\n else\n Array.prototype.push.apply(this.categories, categories);\n return this;\n };\n /**\n * Adds static series columns.\n *\n * Note that it is illegal to have both dynamic series and static series in a visual DataViewCategorical. It is only legal to have them both in\n * a query DataViewCategorical, where DataViewTransform is expected to split them up into separate visual DataViewCategorical objects.\n */\n CategoricalDataViewBuilder.prototype.withValues = function (options) {\n debug.assertValue(options, 'options');\n var columns = options.columns;\n debug.assertValue(columns, 'columns');\n for (var _i = 0, columns_8 = columns; _i < columns_8.length; _i++) {\n var column = columns_8[_i];\n this.staticMeasureColumns.push(column.source);\n }\n this.staticSeriesValues = columns;\n return this;\n };\n /**\n * Adds dynamic series columns.\n *\n * Note that it is illegal to have both dynamic series and static series in a visual DataViewCategorical. It is only legal to have them both in\n * a query DataViewCategorical, where DataViewTransform is expected to split them up into separate visual DataViewCategorical objects.\n */\n CategoricalDataViewBuilder.prototype.withGroupedValues = function (options) {\n debug.assertValue(options, 'options');\n var groupColumn = options.groupColumn;\n debug.assertValue(groupColumn, 'groupColumn');\n this.dynamicSeriesMetadata = {\n column: groupColumn.source,\n identityFrom: groupColumn.identityFrom,\n values: groupColumn.values,\n };\n var valueColumns = options.valueColumns;\n for (var _i = 0, valueColumns_1 = valueColumns; _i < valueColumns_1.length; _i++) {\n var valueColumn = valueColumns_1[_i];\n this.dynamicMeasureColumns.push(valueColumn.source);\n }\n this.dynamicSeriesValues = options.data;\n return this;\n };\n CategoricalDataViewBuilder.prototype.fillData = function (dataViewValues) {\n var categoryColumn = _.first(this.categories);\n var categoryLength = (categoryColumn && categoryColumn.values) ? categoryColumn.values.length : 1;\n if (this.hasDynamicSeries) {\n for (var seriesIndex = 0; seriesIndex < this.dynamicSeriesMetadata.values.length; seriesIndex++) {\n var seriesMeasures = this.dynamicSeriesValues[seriesIndex];\n debug.assert(seriesMeasures.length === this.dynamicMeasureColumns.length, 'seriesMeasures.length === this.dynamicMeasureColumns.length');\n for (var measureIndex = 0, measuresLen = this.dynamicMeasureColumns.length; measureIndex < measuresLen; measureIndex++) {\n var groupIndex = seriesIndex * measuresLen + measureIndex;\n applySeriesData(dataViewValues[groupIndex], seriesMeasures[measureIndex], categoryLength);\n }\n }\n }\n if (this.hasStaticSeries) {\n // Note: when the target categorical has both dynamic and static series, append static measures at the end of the values array.\n var staticColumnsStartingIndex = this.hasDynamicSeries ? (this.dynamicSeriesValues.length * this.dynamicMeasureColumns.length) : 0;\n for (var measureIndex = 0, measuresLen = this.staticMeasureColumns.length; measureIndex < measuresLen; measureIndex++) {\n applySeriesData(dataViewValues[staticColumnsStartingIndex + measureIndex], this.staticSeriesValues[measureIndex], categoryLength);\n }\n }\n };\n /**\n * Returns the DataView with metadata and DataViewCategorical.\n * Returns undefined if the combination of parameters is illegal, such as having both dynamic series and static series when building a visual DataView.\n */\n CategoricalDataViewBuilder.prototype.build = function () {\n var metadataColumns = [];\n var categorical = {};\n var categoryMetadata = this.categories;\n var dynamicSeriesMetadata = this.dynamicSeriesMetadata;\n // --- Build metadata columns and value groups ---\n for (var _i = 0, categoryMetadata_1 = categoryMetadata; _i < categoryMetadata_1.length; _i++) {\n var columnMetadata = categoryMetadata_1[_i];\n pushIfNotExists(metadataColumns, columnMetadata.source);\n }\n if (this.hasDynamicSeries) {\n // Dynamic series, or Dyanmic & Static series.\n pushIfNotExists(metadataColumns, dynamicSeriesMetadata.column);\n categorical.values = DataViewTransform.createValueColumns([], dynamicSeriesMetadata.identityFrom.fields, dynamicSeriesMetadata.column);\n // For each series value we will make one column per measure\n var seriesValues = dynamicSeriesMetadata.values;\n for (var seriesIndex = 0; seriesIndex < seriesValues.length; seriesIndex++) {\n var seriesValue = seriesValues[seriesIndex];\n var seriesIdentity = getScopeIdentity(dynamicSeriesMetadata.identityFrom, seriesIndex, seriesValue, dynamicSeriesMetadata.column.type);\n for (var _a = 0, _b = this.dynamicMeasureColumns; _a < _b.length; _a++) {\n var measure = _b[_a];\n var column = _.clone(measure);\n column.groupName = seriesValue;\n pushIfNotExists(metadataColumns, column);\n categorical.values.push({\n source: column,\n values: [],\n identity: seriesIdentity,\n });\n }\n }\n if (this.hasStaticSeries) {\n // IMPORTANT: In the Dyanmic & Static series case, the groups array shall not include any static group. This is to match the behavior of dsrReader.\n // Get the current return value of grouped() before adding static measure columns, an use that as the return value of this categorical.\n // Otherwise, the default behavior of DataViewValueColumns.grouped() from DataViewTransform.createValueColumns() is to create series groups from all measure columns.\n var dynamicSeriesGroups_1 = categorical.values.grouped();\n categorical.values.grouped = function () { return dynamicSeriesGroups_1; };\n this.appendStaticMeasureColumns(metadataColumns, categorical.values);\n }\n }\n else {\n // Static series only / no series\n categorical.values = DataViewTransform.createValueColumns();\n this.appendStaticMeasureColumns(metadataColumns, categorical.values);\n }\n var categories = this.categories;\n if (!_.isEmpty(categories))\n categorical.categories = categories;\n // --- Fill in data point values ---\n this.fillData(categorical.values);\n var dataView = {\n metadata: {\n columns: metadataColumns,\n },\n categorical: categorical,\n };\n if (this.isLegalDataView(dataView)) {\n return dataView;\n }\n };\n CategoricalDataViewBuilder.prototype.appendStaticMeasureColumns = function (metadataColumns, valueColumns) {\n debug.assertValue(metadataColumns, 'metadataColumns');\n debug.assertValue(valueColumns, 'valueColumns');\n if (!_.isEmpty(this.staticMeasureColumns)) {\n for (var _i = 0, _a = this.staticMeasureColumns; _i < _a.length; _i++) {\n var column = _a[_i];\n pushIfNotExists(metadataColumns, column);\n valueColumns.push({\n source: column,\n values: [],\n });\n }\n }\n };\n CategoricalDataViewBuilder.prototype.isLegalDataView = function (dataView) {\n if (this.hasDynamicSeries && this.hasStaticSeries && CategoricalDataViewBuilder.isVisualDataView(dataView.metadata.columns)) {\n // It is illegal to have both dynamic series and static series in a visual DataViewCategorical,\n // because the DataViewValueColumns interface today cannot express that 100% (see its 'source' property and return value of its 'grouped()' function).\n return false;\n }\n return true;\n };\n /**\n * This function infers that if any metdata column has 'queryName',\n * then the user of this builder is building a visual DataView (as opposed to query DataView).\n *\n * @param metadataColumns The complete collection of metadata columns in the categorical.\n */\n CategoricalDataViewBuilder.isVisualDataView = function (metadataColumns) {\n return !_.isEmpty(metadataColumns) &&\n _.any(metadataColumns, function (metadataColumn) { return !!metadataColumn.queryName; });\n };\n Object.defineProperty(CategoricalDataViewBuilder.prototype, \"hasDynamicSeries\", {\n get: function () {\n return !!this.dynamicSeriesMetadata; // In Map visual scenarios, you can have dynamic series without measure columns\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(CategoricalDataViewBuilder.prototype, \"hasStaticSeries\", {\n get: function () {\n return !!this.staticSeriesValues;\n },\n enumerable: true,\n configurable: true\n });\n return CategoricalDataViewBuilder;\n }());\n function getScopeIdentity(source, index, value, valueType) {\n var identities = source.identities;\n if (identities) {\n return identities[index];\n }\n debug.assert(source.fields && source.fields.length === 1, 'Inferring identity, expect exactly one field.');\n return data.createDataViewScopeIdentity(SQExprBuilder.equal(source.fields[0], SQExprBuilder.typedConstant(value, valueType)));\n }\n function pushIfNotExists(items, itemToAdd) {\n if (_.contains(items, itemToAdd))\n return;\n items.push(itemToAdd);\n }\n function applySeriesData(target, source, categoryLength) {\n debug.assertValue(target, 'target');\n debug.assertValue(source, 'source');\n debug.assertValue(categoryLength, 'categoryLength');\n var values = source.values;\n debug.assert(categoryLength === values.length, 'categoryLength === values.length');\n target.values = values;\n var highlights = source.highlights;\n if (highlights) {\n debug.assert(categoryLength === highlights.length, 'categoryLength === highlights.length');\n target.highlights = highlights;\n }\n var aggregates;\n if (source.minLocal !== undefined) {\n if (!aggregates)\n aggregates = {};\n aggregates.minLocal = source.minLocal;\n }\n if (source.maxLocal !== undefined) {\n if (!aggregates)\n aggregates = {};\n aggregates.maxLocal = source.maxLocal;\n }\n if (aggregates) {\n target.source.aggregates = aggregates;\n _.extend(target, aggregates);\n }\n }\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n var SQExpr = powerbi.data.SQExpr;\n function createStaticEvalContext(colorAllocatorCache, dataView, selectTransforms) {\n return new StaticEvalContext(colorAllocatorCache || data.createColorAllocatorCache(), dataView || { metadata: { columns: [] } }, selectTransforms);\n }\n data.createStaticEvalContext = createStaticEvalContext;\n /**\n * Represents an eval context over a potentially empty DataView. Only static repetition data view objects\n * are supported.\n */\n var StaticEvalContext = (function () {\n function StaticEvalContext(colorAllocatorCache, dataView, selectTransforms) {\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\n debug.assertValue(dataView, 'dataView');\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\n this.colorAllocatorCache = colorAllocatorCache;\n this.dataView = dataView;\n this.selectTransforms = selectTransforms;\n }\n StaticEvalContext.prototype.getColorAllocator = function (expr) {\n return this.colorAllocatorCache.get(expr);\n };\n StaticEvalContext.prototype.getExprValue = function (expr) {\n var dataView = this.dataView, selectTransforms = this.selectTransforms;\n if (dataView && dataView.table && selectTransforms)\n return getExprValueFromTable(expr, selectTransforms, dataView.table, /*rowIdx*/ 0);\n };\n StaticEvalContext.prototype.getRoleValue = function (roleName) {\n return;\n };\n return StaticEvalContext;\n }());\n function getExprValueFromTable(expr, selectTransforms, table, rowIdx) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(selectTransforms, 'selectTransforms');\n debug.assertValue(table, 'table');\n debug.assertValue(rowIdx, 'rowIdx');\n var rows = table.rows;\n if (_.isEmpty(rows) || rows.length <= rowIdx)\n return;\n var targetExpr = getTargetExpr(expr, selectTransforms);\n var cols = table.columns;\n for (var selectIdx = 0, selectLen = selectTransforms.length; selectIdx < selectLen; selectIdx++) {\n var selectTransform = selectTransforms[selectIdx];\n if (!SQExpr.equals(selectTransform.expr, targetExpr) || !selectTransform.queryName)\n continue;\n for (var colIdx = 0, colLen = cols.length; colIdx < colLen; colIdx++) {\n if (selectIdx !== cols[colIdx].index)\n continue;\n return rows[rowIdx][colIdx];\n }\n }\n }\n data.getExprValueFromTable = getExprValueFromTable;\n function getTargetExpr(expr, selectTransforms) {\n if (SQExpr.isSelectRef(expr)) {\n for (var _i = 0, selectTransforms_2 = selectTransforms; _i < selectTransforms_2.length; _i++) {\n var selectTransform = selectTransforms_2[_i];\n if (selectTransform.queryName === expr.expressionName) {\n return selectTransform.expr;\n }\n }\n }\n return expr;\n }\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n function createMatrixEvalContext(colorAllocatorProvider, dataViewMatrix) {\n // NOTE: Matrix context-sensitive evaluation is not yet implemented.\n return data.createStaticEvalContext(colorAllocatorProvider);\n }\n data.createMatrixEvalContext = createMatrixEvalContext;\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi_1) {\n var StringExtensions = jsCommon.StringExtensions;\n var Formatting = jsCommon.Formatting;\n var RegExpExtensions = jsCommon.RegExpExtensions;\n /** Formatting Encoder */\n var FormattingEncoder;\n (function (FormattingEncoder) {\n function preserveEscaped(format, specialChars) {\n // Unicode U+E000 - U+F8FF is a private area and so we can use the chars from the range to encode the escaped sequences\n var length = specialChars.length;\n for (var i = 0; i < length; i++) {\n var oldText = \"\\\\\" + specialChars[i];\n var newText = String.fromCharCode(0xE000 + i);\n format = StringExtensions.replaceAll(format, oldText, newText);\n }\n return format;\n }\n FormattingEncoder.preserveEscaped = preserveEscaped;\n function restoreEscaped(format, specialChars) {\n // After formatting is complete we should restore the encoded escaped chars into the unescaped chars\n var length = specialChars.length;\n for (var i = 0; i < length; i++) {\n var oldText = String.fromCharCode(0xE000 + i);\n var newText = specialChars[i];\n format = StringExtensions.replaceAll(format, oldText, newText);\n }\n return StringExtensions.replaceAll(format, \"\\\\\", \"\");\n }\n FormattingEncoder.restoreEscaped = restoreEscaped;\n function preserveLiterals(format, literals) {\n // Unicode U+E000 - U+F8FF is a private area and so we can use the chars from the range to encode the escaped sequences\n format = StringExtensions.replaceAll(format, \"\\\"\", \"'\");\n for (var i = 0;; i++) {\n var fromIndex = format.indexOf(\"'\");\n if (fromIndex < 0) {\n break;\n }\n var toIndex = format.indexOf(\"'\", fromIndex + 1);\n if (toIndex < 0) {\n break;\n }\n var literal = format.substring(fromIndex, toIndex + 1);\n literals.push(literal.substring(1, toIndex - fromIndex));\n var token = String.fromCharCode(0xE100 + i);\n format = format.replace(literal, token);\n }\n return format;\n }\n FormattingEncoder.preserveLiterals = preserveLiterals;\n function restoreLiterals(format, literals) {\n var count = literals.length;\n for (var i = 0; i < count; i++) {\n var token = String.fromCharCode(0xE100 + i);\n var literal = literals[i];\n format = format.replace(token, literal);\n }\n return format;\n }\n FormattingEncoder.restoreLiterals = restoreLiterals;\n })(FormattingEncoder || (FormattingEncoder = {}));\n var IndexedTokensRegex = /({{)|(}})|{(\\d+[^}]*)}/g;\n var ZeroPlaceholder = '0';\n var DigitPlaceholder = '#';\n var ExponentialFormatChar = 'E';\n var NumericPlaceholders = [ZeroPlaceholder, DigitPlaceholder];\n var NumericPlaceholderRegex = new RegExp(NumericPlaceholders.join('|'), 'g');\n /** Formatting Service */\n var FormattingService = (function () {\n function FormattingService() {\n }\n FormattingService.prototype.formatValue = function (value, format, culture) {\n // Handle special cases\n if (value === undefined || value === null) {\n return '';\n }\n var gculture = this.getCulture(culture);\n if (DateTimeFormat.canFormat(value)) {\n // Dates\n return DateTimeFormat.format(value, format, gculture);\n }\n else if (NumberFormat.canFormat(value)) {\n // Numbers\n return NumberFormat.format(value, format, gculture);\n }\n else {\n // Other data types - return as string\n return value.toString();\n }\n };\n FormattingService.prototype.format = function (formatWithIndexedTokens, args, culture) {\n var _this = this;\n if (!formatWithIndexedTokens) {\n return \"\";\n }\n var result = formatWithIndexedTokens.replace(IndexedTokensRegex, function (match, left, right, argToken) {\n if (left) {\n return \"{\";\n }\n else if (right) {\n return \"}\";\n }\n else {\n var parts = argToken.split(\":\");\n var argIndex = parseInt(parts[0], 10);\n var argFormat = parts[1];\n return _this.formatValue(args[argIndex], argFormat, culture);\n }\n });\n return result;\n };\n FormattingService.prototype.isStandardNumberFormat = function (format) {\n return NumberFormat.isStandardFormat(format);\n };\n FormattingService.prototype.formatNumberWithCustomOverride = function (value, format, nonScientificOverrideFormat, culture) {\n var gculture = this.getCulture(culture);\n return NumberFormat.formatWithCustomOverride(value, format, nonScientificOverrideFormat, gculture);\n };\n FormattingService.prototype.dateFormatString = function (unit) {\n if (!this._dateTimeScaleFormatInfo)\n this.initialize();\n return this._dateTimeScaleFormatInfo.getFormatString(unit);\n };\n /**\n * Sets the current localization culture\n * @param cultureSelector - name of a culture: \"en\", \"en-UK\", \"fr-FR\" etc. (See National Language Support (NLS) for full lists. Use \"default\" for invariant culture).\n */\n FormattingService.prototype.setCurrentCulture = function (cultureSelector) {\n if (this._currentCultureSelector !== cultureSelector) {\n this._currentCulture = this.getCulture(cultureSelector);\n this._currentCultureSelector = cultureSelector;\n this._dateTimeScaleFormatInfo = new DateTimeScaleFormatInfo(this._currentCulture);\n }\n };\n /**\n * Gets the culture assotiated with the specified cultureSelector (\"en\", \"en-US\", \"fr-FR\" etc).\n * @param cultureSelector - name of a culture: \"en\", \"en-UK\", \"fr-FR\" etc. (See National Language Support (NLS) for full lists. Use \"default\" for invariant culture).\n * Exposing this function for testability of unsupported cultures\n */\n FormattingService.prototype.getCulture = function (cultureSelector) {\n if (cultureSelector == null) {\n if (this._currentCulture == null) {\n this.initialize();\n }\n return this._currentCulture;\n }\n else {\n var culture = Globalize.findClosestCulture(cultureSelector);\n if (!culture)\n culture = Globalize.culture(\"en-US\");\n return culture;\n }\n };\n /** By default the Globalization module initializes to the culture/calendar provided in the language/culture URL params */\n FormattingService.prototype.initialize = function () {\n var cultureName = this.getCurrentCulture();\n this.setCurrentCulture(cultureName);\n var calendarName = this.getUrlParam(\"calendar\");\n if (calendarName) {\n var culture = this._currentCulture;\n var c = culture.calendars[calendarName];\n if (c) {\n culture.calendar = c;\n }\n }\n };\n /**\n * Exposing this function for testability\n */\n FormattingService.prototype.getCurrentCulture = function () {\n var urlParam = this.getUrlParam(\"language\");\n if (urlParam) {\n return urlParam;\n }\n if (powerbi && powerbi.common && powerbi.common.cultureInfo) {\n // Get cultureInfo set in powerbi\n return powerbi.common.cultureInfo;\n }\n return window.navigator.userLanguage || window.navigator[\"language\"] || Globalize.culture().name;\n };\n /**\n * Exposing this function for testability\n * @param name: queryString name\n */\n FormattingService.prototype.getUrlParam = function (name) {\n var param = window.location.search.match(RegExp(\"[?&]\" + name + \"=([^&]*)\"));\n return param ? param[1] : undefined;\n };\n return FormattingService;\n }());\n /**\n * DateTimeFormat module contains the static methods for formatting the DateTimes.\n * It extends the JQuery.Globalize functionality to support complete set of .NET\n * formatting expressions for dates.\n */\n var DateTimeFormat;\n (function (DateTimeFormat) {\n var _currentCachedFormat;\n var _currentCachedProcessedFormat;\n /** Evaluates if the value can be formatted using the NumberFormat */\n function canFormat(value) {\n var result = value instanceof Date;\n return result;\n }\n DateTimeFormat.canFormat = canFormat;\n /** Formats the date using provided format and culture */\n function format(value, format, culture) {\n format = format || \"G\";\n var isStandard = format.length === 1;\n try {\n if (isStandard) {\n return formatDateStandard(value, format, culture);\n }\n else {\n return formatDateCustom(value, format, culture);\n }\n }\n catch (e) {\n return formatDateStandard(value, \"G\", culture);\n }\n }\n DateTimeFormat.format = format;\n /** Formats the date using standard format expression */\n function formatDateStandard(value, format, culture) {\n // In order to provide parity with .NET we have to support additional set of DateTime patterns.\n var patterns = culture.calendar.patterns;\n // Extend supported set of patterns\n ensurePatterns(culture.calendar);\n // Handle extended set of formats\n var output = Formatting.findDateFormat(value, format, culture.name);\n if (output.format.length === 1)\n format = patterns[output.format];\n else\n format = output.format;\n //need to revisit when globalization is enabled\n culture = Globalize.culture(\"en-US\");\n return Globalize.format(output.value, format, culture);\n }\n /** Formats the date using custom format expression */\n function formatDateCustom(value, format, culture) {\n var result;\n var literals = [];\n format = FormattingEncoder.preserveEscaped(format, \"\\\\dfFghHKmstyz:/%'\\\"\");\n format = FormattingEncoder.preserveLiterals(format, literals);\n format = StringExtensions.replaceAll(format, \"\\\"\", \"'\");\n if (format.indexOf(\"F\") > -1) {\n // F is not supported so we need to replace the F with f based on the milliseconds\n // Replace all sequences of F longer than 3 with \"FFF\"\n format = StringExtensions.replaceAll(format, \"FFFF\", \"FFF\");\n // Based on milliseconds update the format to use fff\n var milliseconds = value.getMilliseconds();\n if (milliseconds % 10 >= 1) {\n format = StringExtensions.replaceAll(format, \"FFF\", \"fff\");\n }\n format = StringExtensions.replaceAll(format, \"FFF\", \"FF\");\n if ((milliseconds % 100) / 10 >= 1) {\n format = StringExtensions.replaceAll(format, \"FF\", \"ff\");\n }\n format = StringExtensions.replaceAll(format, \"FF\", \"F\");\n if ((milliseconds % 1000) / 100 >= 1) {\n format = StringExtensions.replaceAll(format, \"F\", \"f\");\n }\n format = StringExtensions.replaceAll(format, \"F\", \"\");\n if (format === \"\" || format === \"%\")\n return \"\";\n }\n format = processCustomDateTimeFormat(format);\n result = Globalize.format(value, format, culture);\n result = localize(result, culture.calendar);\n result = FormattingEncoder.restoreLiterals(result, literals);\n result = FormattingEncoder.restoreEscaped(result, \"\\\\dfFghHKmstyz:/%'\\\"\");\n return result;\n }\n /** Translates unsupported .NET custom format expressions to the custom expressions supported by JQuery.Globalize */\n function processCustomDateTimeFormat(format) {\n if (format === _currentCachedFormat) {\n return _currentCachedProcessedFormat;\n }\n _currentCachedFormat = format;\n format = Formatting.fixDateTimeFormat(format);\n _currentCachedProcessedFormat = format;\n return format;\n }\n /** Localizes the time separator symbol */\n function localize(value, dictionary) {\n var timeSeparator = dictionary[\":\"];\n if (timeSeparator === \":\") {\n return value;\n }\n var result = \"\";\n var count = value.length;\n for (var i = 0; i < count; i++) {\n var char = value.charAt(i);\n switch (char) {\n case \":\":\n result += timeSeparator;\n break;\n default:\n result += char;\n break;\n }\n }\n return result;\n }\n function ensurePatterns(calendar) {\n var patterns = calendar.patterns;\n if (patterns[\"g\"] === undefined) {\n patterns[\"g\"] = patterns[\"f\"].replace(patterns[\"D\"], patterns[\"d\"]); // Generic: Short date, short time\n patterns[\"G\"] = patterns[\"F\"].replace(patterns[\"D\"], patterns[\"d\"]); // Generic: Short date, long time\n }\n }\n })(DateTimeFormat || (DateTimeFormat = {}));\n /**\n * NumberFormat module contains the static methods for formatting the numbers.\n * It extends the JQuery.Globalize functionality to support complete set of .NET\n * formatting expressions for numeric types including custom formats.\n */\n var NumberFormat;\n (function (NumberFormat) {\n var NonScientificFormatRegex = /^\\{.+\\}.*/;\n var NumericalPlaceHolderRegex = /\\{.+\\}/;\n var ScientificFormatRegex = /e[+-]*[0#]+/i;\n var StandardFormatRegex = /^[a-z]\\d{0,2}$/i; // a letter + up to 2 digits for precision specifier\n var TrailingZerosRegex = /0+$/;\n var DecimalFormatRegex = /\\.([0#]*)/g;\n var NumericFormatRegex = /[0#,\\.]+[0,#]*/g;\n var LastNumericPlaceholderRegex = /(0|#)([^(0|#)]*)$/;\n var DecimalFormatCharacter = '.';\n NumberFormat.NumberFormatComponentsDelimeter = ';';\n function getNonScientificFormatWithPrecision(baseFormat, numericFormat) {\n if (!numericFormat || baseFormat === undefined)\n return baseFormat;\n var newFormat = \"{0:\" + numericFormat + \"}\";\n return baseFormat.replace(\"{0}\", newFormat);\n }\n function getNumericFormat(value, baseFormat) {\n if (baseFormat == null)\n return baseFormat;\n if (hasFormatComponents(baseFormat)) {\n var _a = NumberFormat.getComponents(baseFormat), positive = _a.positive, negative = _a.negative, zero = _a.zero;\n if (value > 0)\n return getNumericFormatFromComponent(value, positive);\n else if (value === 0)\n return getNumericFormatFromComponent(value, zero);\n return getNumericFormatFromComponent(value, negative);\n }\n return getNumericFormatFromComponent(value, baseFormat);\n }\n NumberFormat.getNumericFormat = getNumericFormat;\n function getNumericFormatFromComponent(value, format) {\n var match = RegExpExtensions.run(NumericFormatRegex, format);\n if (match)\n return match[0];\n return format;\n }\n function addDecimalsToFormat(baseFormat, decimals, trailingZeros) {\n if (decimals == null)\n return baseFormat;\n // Default format string\n if (baseFormat == null)\n baseFormat = ZeroPlaceholder;\n if (hasFormatComponents(baseFormat)) {\n var _a = NumberFormat.getComponents(baseFormat), positive = _a.positive, negative = _a.negative, zero = _a.zero;\n var formats = [positive, negative, zero];\n for (var i = 0; i < formats.length; i++) {\n // Update format in formats array\n formats[i] = addDecimalsToFormatComponent(formats[i], decimals, trailingZeros);\n }\n return formats.join(NumberFormat.NumberFormatComponentsDelimeter);\n }\n return addDecimalsToFormatComponent(baseFormat, decimals, trailingZeros);\n }\n NumberFormat.addDecimalsToFormat = addDecimalsToFormat;\n function addDecimalsToFormatComponent(format, decimals, trailingZeros) {\n decimals = Math.abs(decimals);\n if (decimals >= 0) {\n var placeholder = trailingZeros ? ZeroPlaceholder : DigitPlaceholder;\n var decimalPlaceholders = StringExtensions.repeat(placeholder, Math.abs(decimals));\n var match = RegExpExtensions.run(DecimalFormatRegex, format);\n if (match) {\n var beforeDecimal = format.substr(0, match.index);\n var formatDecimal = format.substr(match.index + 1, match[1].length);\n var afterDecimal = format.substr(match.index + match[0].length);\n if (trailingZeros)\n // Use explicit decimals argument as placeholders\n formatDecimal = decimalPlaceholders;\n else {\n var decimalChange = decimalPlaceholders.length - formatDecimal.length;\n if (decimalChange > 0)\n // Append decimalPlaceholders to existing decimal portion of format string\n formatDecimal = formatDecimal + decimalPlaceholders.slice(-decimalChange);\n else if (decimalChange < 0)\n // Remove decimals from formatDecimal\n formatDecimal = formatDecimal.slice(0, decimalChange);\n }\n if (formatDecimal.length > 0)\n formatDecimal = DecimalFormatCharacter + formatDecimal;\n return beforeDecimal + formatDecimal + afterDecimal;\n }\n else if (decimalPlaceholders.length > 0)\n // Replace last numeric placeholder with decimal portion\n return format.replace(LastNumericPlaceholderRegex, '$1' + DecimalFormatCharacter + decimalPlaceholders);\n }\n return format;\n }\n function hasFormatComponents(format) {\n return format.indexOf(NumberFormat.NumberFormatComponentsDelimeter) !== -1;\n }\n NumberFormat.hasFormatComponents = hasFormatComponents;\n function getComponents(format) {\n var signFormat = {\n hasNegative: false,\n positive: format,\n negative: format,\n zero: format,\n };\n var signSpecificFormats = format.split(NumberFormat.NumberFormatComponentsDelimeter);\n var formatCount = signSpecificFormats.length;\n debug.assert(!(formatCount > 3), 'format string should be of form positive[;negative;zero]');\n if (formatCount > 1) {\n signFormat.hasNegative = true;\n signFormat.positive = signFormat.zero = signSpecificFormats[0];\n signFormat.negative = signSpecificFormats[1];\n if (formatCount > 2)\n signFormat.zero = signSpecificFormats[2];\n }\n return signFormat;\n }\n NumberFormat.getComponents = getComponents;\n var _lastCustomFormatMeta;\n /** Evaluates if the value can be formatted using the NumberFormat */\n function canFormat(value) {\n var result = typeof (value) === \"number\";\n return result;\n }\n NumberFormat.canFormat = canFormat;\n function isStandardFormat(format) {\n debug.assertValue(format, 'format');\n return StandardFormatRegex.test(format);\n }\n NumberFormat.isStandardFormat = isStandardFormat;\n /** Formats the number using specified format expression and culture */\n function format(value, format, culture) {\n format = format || \"G\";\n try {\n if (isStandardFormat(format))\n return formatNumberStandard(value, format, culture);\n return formatNumberCustom(value, format, culture);\n }\n catch (e) {\n return Globalize.format(value, undefined, culture);\n }\n }\n NumberFormat.format = format;\n /** Performs a custom format with a value override. Typically used for custom formats showing scaled values. */\n function formatWithCustomOverride(value, format, nonScientificOverrideFormat, culture) {\n debug.assertValue(value, 'value');\n debug.assertValue(format, 'format');\n debug.assertValue(nonScientificOverrideFormat, 'nonScientificOverrideFormat');\n debug.assertValue(culture, 'culture');\n debug.assert(!isStandardFormat(format), 'Standard format');\n return formatNumberCustom(value, format, culture, nonScientificOverrideFormat);\n }\n NumberFormat.formatWithCustomOverride = formatWithCustomOverride;\n /** Formats the number using standard format expression */\n function formatNumberStandard(value, format, culture) {\n var result;\n var precision = (format.length > 1 ? parseInt(format.substr(1, format.length - 1), 10) : undefined);\n var numberFormatInfo = culture.numberFormat;\n var formatChar = format.charAt(0);\n switch (formatChar) {\n case \"e\":\n case \"E\":\n if (precision === undefined) {\n precision = 6;\n }\n var mantissaDecimalDigits = StringExtensions.repeat(\"0\", precision);\n format = \"0.\" + mantissaDecimalDigits + formatChar + \"+000\";\n result = formatNumberCustom(value, format, culture);\n break;\n case \"f\":\n case \"F\":\n result = precision !== undefined ? value.toFixed(precision) : value.toFixed(numberFormatInfo.decimals);\n result = localize(result, numberFormatInfo);\n break;\n case \"g\":\n case \"G\":\n var abs = Math.abs(value);\n if (abs === 0 || (1E-4 <= abs && abs < 1E15)) {\n // For the range of 0.0001 to 1,000,000,000,000,000 - use the normal form\n result = precision !== undefined ? value.toPrecision(precision) : value.toString();\n }\n else {\n // Otherwise use exponential\n // Assert that value is a number and fall back on returning value if it is not\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\n if (typeof (value) !== \"number\")\n return String(value);\n result = precision !== undefined ? value.toExponential(precision) : value.toExponential();\n result = result.replace(\"e\", \"E\");\n }\n result = localize(result, numberFormatInfo);\n break;\n case \"r\":\n case \"R\":\n result = value.toString();\n result = localize(result, numberFormatInfo);\n break;\n case \"x\":\n case \"X\":\n result = value.toString(16);\n if (formatChar === \"X\") {\n result = result.toUpperCase();\n }\n if (precision !== undefined) {\n var actualPrecision = result.length;\n var isNegative = value < 0;\n if (isNegative) {\n actualPrecision--;\n }\n var paddingZerosCount = precision - actualPrecision;\n var paddingZeros = undefined;\n if (paddingZerosCount > 0) {\n paddingZeros = StringExtensions.repeat(\"0\", paddingZerosCount);\n }\n if (isNegative) {\n result = \"-\" + paddingZeros + result.substr(1);\n }\n else {\n result = paddingZeros + result;\n }\n }\n result = localize(result, numberFormatInfo);\n break;\n default:\n result = Globalize.format(value, format, culture);\n }\n return result;\n }\n /** Formats the number using custom format expression */\n function formatNumberCustom(value, format, culture, nonScientificOverrideFormat) {\n var result;\n var numberFormatInfo = culture.numberFormat;\n if (isFinite(value)) {\n // Split format by positive[;negative;zero] pattern\n var formatComponents = getComponents(format);\n // Pick a format based on the sign of value\n if (value > 0) {\n format = formatComponents.positive;\n }\n else if (value === 0) {\n format = formatComponents.zero;\n }\n else {\n format = formatComponents.negative;\n }\n // Normalize value if we have an explicit negative format\n if (formatComponents.hasNegative)\n value = Math.abs(value);\n // Get format metadata\n var formatMeta = getCustomFormatMetadata(format, true /*calculatePrecision*/);\n // Preserve literals and escaped chars\n if (formatMeta.hasEscapes) {\n format = FormattingEncoder.preserveEscaped(format, \"\\\\0#.,%‰\");\n }\n var literals = [];\n if (formatMeta.hasQuotes) {\n format = FormattingEncoder.preserveLiterals(format, literals);\n }\n // Scientific format\n if (formatMeta.hasE && !nonScientificOverrideFormat) {\n var scientificMatch = RegExpExtensions.run(ScientificFormatRegex, format);\n if (scientificMatch) {\n // Case 2.1. Scientific custom format\n var formatM = format.substr(0, scientificMatch.index);\n var formatE = format.substr(scientificMatch.index + 2); // E(+|-)\n var precision = getCustomFormatPrecision(formatM, formatMeta);\n var scale = getCustomFormatScale(formatM, formatMeta);\n if (scale !== 1) {\n value = value * scale;\n }\n // Assert that value is a number and fall back on returning value if it is not\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\n if (typeof (value) !== \"number\")\n return String(value);\n var s = value.toExponential(precision);\n var indexOfE = s.indexOf(\"e\");\n var mantissa = s.substr(0, indexOfE);\n var exp = s.substr(indexOfE + 1);\n var resultM = fuseNumberWithCustomFormat(mantissa, formatM, numberFormatInfo);\n var resultE = fuseNumberWithCustomFormat(exp, formatE, numberFormatInfo);\n if (resultE.charAt(0) === \"+\" && scientificMatch[0].charAt(1) !== \"+\") {\n resultE = resultE.substr(1);\n }\n var e = scientificMatch[0].charAt(0);\n result = resultM + e + resultE;\n }\n }\n // Non scientific format\n if (result === undefined) {\n var valueFormatted = void 0;\n var isValueGlobalized = false;\n var precision = getCustomFormatPrecision(format, formatMeta);\n var scale = getCustomFormatScale(format, formatMeta);\n if (scale !== 1)\n value = value * scale;\n // Rounding\n value = parseFloat(toNonScientific(value, precision));\n if (nonScientificOverrideFormat) {\n // Get numeric format from format string\n var numericFormat = NumberFormat.getNumericFormat(value, format);\n // Add separators and decimalFormat to nonScientificFormat\n nonScientificOverrideFormat = getNonScientificFormatWithPrecision(nonScientificOverrideFormat, numericFormat);\n // Format the value\n valueFormatted = powerbi_1.formattingService.format(nonScientificOverrideFormat, [value], culture.name);\n isValueGlobalized = true;\n }\n else\n valueFormatted = toNonScientific(value, precision);\n result = fuseNumberWithCustomFormat(valueFormatted, format, numberFormatInfo, nonScientificOverrideFormat, isValueGlobalized);\n }\n if (formatMeta.hasQuotes) {\n result = FormattingEncoder.restoreLiterals(result, literals);\n }\n if (formatMeta.hasEscapes) {\n result = FormattingEncoder.restoreEscaped(result, \"\\\\0#.,%‰\");\n }\n _lastCustomFormatMeta = formatMeta;\n }\n else {\n return Globalize.format(value, undefined);\n }\n return result;\n }\n /** Returns string with the fixed point respresentation of the number */\n function toNonScientific(value, precision) {\n var result = \"\";\n var precisionZeros = 0;\n // Double precision numbers support actual 15-16 decimal digits of precision.\n if (precision > 16) {\n precisionZeros = precision - 16;\n precision = 16;\n }\n var digitsBeforeDecimalPoint = powerbi_1.Double.log10(Math.abs(value));\n if (digitsBeforeDecimalPoint < 16) {\n if (digitsBeforeDecimalPoint > 0) {\n var maxPrecision = 16 - digitsBeforeDecimalPoint;\n if (precision > maxPrecision) {\n precisionZeros += precision - maxPrecision;\n precision = maxPrecision;\n }\n }\n result = value.toFixed(precision);\n }\n else if (digitsBeforeDecimalPoint === 16) {\n result = value.toFixed(0);\n precisionZeros += precision;\n if (precisionZeros > 0) {\n result += \".\";\n }\n }\n else {\n // Different browsers have different implementations of the toFixed().\n // In IE it returns fixed format no matter what's the number. In FF and Chrome the method returns exponential format for numbers greater than 1E21.\n // So we need to check for range and convert the to exponential with the max precision.\n // Then we convert exponential string to fixed by removing the dot and padding with \"power\" zeros.\n // Assert that value is a number and fall back on returning value if it is not\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\n if (typeof (value) !== \"number\")\n return String(value);\n result = value.toExponential(15);\n var indexOfE = result.indexOf(\"e\");\n if (indexOfE > 0) {\n var indexOfDot = result.indexOf(\".\");\n var mantissa = result.substr(0, indexOfE);\n var exp = result.substr(indexOfE + 1);\n var powerZeros = parseInt(exp, 10) - (mantissa.length - indexOfDot - 1);\n result = mantissa.replace(\".\", \"\") + StringExtensions.repeat(\"0\", powerZeros);\n if (precision > 0) {\n result = result + \".\" + StringExtensions.repeat(\"0\", precision);\n }\n }\n }\n if (precisionZeros > 0) {\n result = result + StringExtensions.repeat(\"0\", precisionZeros);\n }\n return result;\n }\n /**\n * Returns the formatMetadata of the format\n * When calculating precision and scale, if format string of\n * positive[;negative;zero] => positive format will be used\n * @param (required) format - format string\n * @param (optional) calculatePrecision - calculate precision of positive format\n * @param (optional) calculateScale - calculate scale of positive format\n */\n function getCustomFormatMetadata(format, calculatePrecision, calculateScale) {\n if (_lastCustomFormatMeta !== undefined && format === _lastCustomFormatMeta.format) {\n return _lastCustomFormatMeta;\n }\n var result = {\n format: format,\n hasEscapes: false,\n hasQuotes: false,\n hasE: false,\n hasCommas: false,\n hasDots: false,\n hasPercent: false,\n hasPermile: false,\n precision: undefined,\n scale: undefined,\n };\n for (var i = 0, length_1 = format.length; i < length_1; i++) {\n var c = format.charAt(i);\n switch (c) {\n case \"\\\\\":\n result.hasEscapes = true;\n break;\n case \"'\":\n case \"\\\"\":\n result.hasQuotes = true;\n break;\n case \"e\":\n case \"E\":\n result.hasE = true;\n break;\n case \",\":\n result.hasCommas = true;\n break;\n case \".\":\n result.hasDots = true;\n break;\n case \"%\":\n result.hasPercent = true;\n break;\n case \"‰\":\n result.hasPermile = true;\n break;\n }\n }\n // Use positive format for calculating these values\n var formatComponents = getComponents(format);\n if (calculatePrecision)\n result.precision = getCustomFormatPrecision(formatComponents.positive, result);\n if (calculateScale)\n result.scale = getCustomFormatScale(formatComponents.positive, result);\n return result;\n }\n NumberFormat.getCustomFormatMetadata = getCustomFormatMetadata;\n /** Returns the decimal precision of format based on the number of # and 0 chars after the decimal point\n * Important: The input format string needs to be split to the appropriate pos/neg/zero portion to work correctly */\n function getCustomFormatPrecision(format, formatMeta) {\n if (formatMeta.precision > -1) {\n return formatMeta.precision;\n }\n var result = 0;\n if (formatMeta.hasDots) {\n var dotIndex = format.indexOf(\".\");\n if (dotIndex > -1) {\n var count = format.length;\n for (var i = dotIndex; i < count; i++) {\n var char = format.charAt(i);\n if (char.match(NumericPlaceholderRegex))\n result++;\n // 0.00E+0 :: Break before counting 0 in\n // exponential portion of format string\n if (char === ExponentialFormatChar)\n break;\n }\n result = Math.min(19, result);\n }\n }\n formatMeta.precision = result;\n return result;\n }\n /** Returns the scale factor of the format based on the \"%\" and scaling \",\" chars in the format */\n function getCustomFormatScale(format, formatMeta) {\n if (formatMeta.scale > -1) {\n return formatMeta.scale;\n }\n var result = 1;\n if (formatMeta.hasPercent && format.indexOf(\"%\") > -1) {\n result = result * 100;\n }\n if (formatMeta.hasPermile && format.indexOf(\"‰\") > -1) {\n result = result * 1000;\n }\n if (formatMeta.hasCommas) {\n var dotIndex = format.indexOf(\".\");\n if (dotIndex === -1) {\n dotIndex = format.length;\n }\n for (var i = dotIndex - 1; i > -1; i--) {\n var char = format.charAt(i);\n if (char === \",\") {\n result = result / 1000;\n }\n else {\n break;\n }\n }\n }\n formatMeta.scale = result;\n return result;\n }\n function fuseNumberWithCustomFormat(value, format, numberFormatInfo, nonScientificOverrideFormat, isValueGlobalized) {\n var suppressModifyValue = !!nonScientificOverrideFormat;\n var formatParts = format.split(\".\", 2);\n if (formatParts.length === 2) {\n var wholeFormat = formatParts[0];\n var fractionFormat = formatParts[1];\n var displayUnit = \"\";\n // Remove display unit from value before splitting on \".\" as localized display units sometimes end with \".\"\n if (nonScientificOverrideFormat) {\n debug.assert(NonScientificFormatRegex.test(nonScientificOverrideFormat), \"Number should always precede the display unit\");\n displayUnit = nonScientificOverrideFormat.replace(NumericalPlaceHolderRegex, \"\");\n value = value.replace(displayUnit, \"\");\n }\n var globalizedDecimalSeparator = numberFormatInfo[\".\"];\n var decimalSeparator = isValueGlobalized ? globalizedDecimalSeparator : \".\";\n var valueParts = value.split(decimalSeparator, 2);\n var wholeValue = valueParts.length === 1 ? valueParts[0] + displayUnit : valueParts[0];\n var fractionValue = valueParts.length === 2 ? valueParts[1] + displayUnit : \"\";\n fractionValue = fractionValue.replace(TrailingZerosRegex, \"\");\n var wholeFormattedValue = fuseNumberWithCustomFormatLeft(wholeValue, wholeFormat, numberFormatInfo, suppressModifyValue);\n var fractionFormattedValue = fuseNumberWithCustomFormatRight(fractionValue, fractionFormat, suppressModifyValue);\n if (fractionFormattedValue.fmtOnly || fractionFormattedValue.value === \"\")\n return wholeFormattedValue + fractionFormattedValue.value;\n return wholeFormattedValue + globalizedDecimalSeparator + fractionFormattedValue.value;\n }\n return fuseNumberWithCustomFormatLeft(value, format, numberFormatInfo, suppressModifyValue);\n }\n function fuseNumberWithCustomFormatLeft(value, format, numberFormatInfo, suppressModifyValue) {\n var groupSymbolIndex = format.indexOf(\",\");\n var enableGroups = groupSymbolIndex > -1 && groupSymbolIndex < Math.max(format.lastIndexOf(\"0\"), format.lastIndexOf(\"#\")) && numberFormatInfo[\",\"];\n var groupDigitCount = 0;\n var groupIndex = 0;\n var groupSizes = numberFormatInfo.groupSizes || [3];\n var groupSize = groupSizes[0];\n var groupSeparator = numberFormatInfo[\",\"];\n var sign = \"\";\n var firstChar = value.charAt(0);\n if (firstChar === \"+\" || firstChar === \"-\") {\n sign = numberFormatInfo[firstChar];\n value = value.substr(1);\n }\n var isZero = value === \"0\";\n var result = \"\";\n var leftBuffer = \"\";\n var vi = value.length - 1;\n var fmtOnly = true;\n // Iterate through format chars and replace 0 and # with the digits from the value string\n for (var fi = format.length - 1; fi > -1; fi--) {\n var formatChar = format.charAt(fi);\n switch (formatChar) {\n case ZeroPlaceholder:\n case DigitPlaceholder:\n fmtOnly = false;\n if (leftBuffer !== \"\") {\n result = leftBuffer + result;\n leftBuffer = \"\";\n }\n if (!suppressModifyValue) {\n if (vi > -1 || formatChar === ZeroPlaceholder) {\n if (enableGroups) {\n // If the groups are enabled we'll need to keep track of the current group index and periodically insert group separator,\n if (groupDigitCount === groupSize) {\n result = groupSeparator + result;\n groupIndex++;\n if (groupIndex < groupSizes.length) {\n groupSize = groupSizes[groupIndex];\n }\n groupDigitCount = 1;\n }\n else {\n groupDigitCount++;\n }\n }\n }\n if (vi > -1) {\n if (isZero && formatChar === DigitPlaceholder) {\n }\n else {\n result = value.charAt(vi) + result;\n }\n vi--;\n }\n else if (formatChar !== DigitPlaceholder) {\n result = formatChar + result;\n }\n }\n break;\n case \",\":\n // We should skip all the , chars\n break;\n default:\n leftBuffer = formatChar + leftBuffer;\n break;\n }\n }\n // If the value didn't fit into the number of zeros provided in the format then we should insert the missing part of the value into the result\n if (!suppressModifyValue) {\n if (vi > -1 && result !== \"\") {\n if (enableGroups) {\n while (vi > -1) {\n if (groupDigitCount === groupSize) {\n result = groupSeparator + result;\n groupIndex++;\n if (groupIndex < groupSizes.length) {\n groupSize = groupSizes[groupIndex];\n }\n groupDigitCount = 1;\n }\n else {\n groupDigitCount++;\n }\n result = value.charAt(vi) + result;\n vi--;\n }\n }\n else {\n result = value.substr(0, vi + 1) + result;\n }\n }\n // Insert sign in front of the leftBuffer and result\n return sign + leftBuffer + result;\n }\n if (fmtOnly)\n // If the format doesn't specify any digits to be displayed, then just return the format we've parsed up until now.\n return sign + leftBuffer + result;\n return sign + leftBuffer + value + result;\n }\n function fuseNumberWithCustomFormatRight(value, format, suppressModifyValue) {\n var vi = 0;\n var fCount = format.length;\n var vCount = value.length;\n if (suppressModifyValue) {\n debug.assert(fCount > 0, \"Empty formatting string\");\n var lastChar = format.charAt(fCount - 1);\n if (!lastChar.match(NumericPlaceholderRegex))\n return {\n value: value + lastChar,\n fmtOnly: value === \"\",\n };\n return {\n value: value,\n fmtOnly: value === \"\",\n };\n }\n var result = \"\", fmtOnly = true;\n for (var fi = 0; fi < fCount; fi++) {\n var formatChar = format.charAt(fi);\n if (vi < vCount) {\n switch (formatChar) {\n case ZeroPlaceholder:\n case DigitPlaceholder:\n result += value[vi++];\n fmtOnly = false;\n break;\n default:\n result += formatChar;\n }\n }\n else {\n if (formatChar !== DigitPlaceholder) {\n result += formatChar;\n fmtOnly = fmtOnly && (formatChar !== ZeroPlaceholder);\n }\n }\n }\n return {\n value: result,\n fmtOnly: fmtOnly,\n };\n }\n function localize(value, dictionary) {\n var plus = dictionary[\"+\"];\n var minus = dictionary[\"-\"];\n var dot = dictionary[\".\"];\n var comma = dictionary[\",\"];\n if (plus === \"+\" && minus === \"-\" && dot === \".\" && comma === \",\") {\n return value;\n }\n var count = value.length;\n var result = \"\";\n for (var i = 0; i < count; i++) {\n var char = value.charAt(i);\n switch (char) {\n case \"+\":\n result = result + plus;\n break;\n case \"-\":\n result = result + minus;\n break;\n case \".\":\n result = result + dot;\n break;\n case \",\":\n result = result + comma;\n break;\n default:\n result = result + char;\n break;\n }\n }\n return result;\n }\n })(NumberFormat = powerbi_1.NumberFormat || (powerbi_1.NumberFormat = {}));\n /** DateTimeScaleFormatInfo is used to calculate and keep the Date formats used for different units supported by the DateTimeScaleModel */\n var DateTimeScaleFormatInfo = (function () {\n // Constructor\n /**\n * Creates new instance of the DateTimeScaleFormatInfo class.\n * @param culture - culture which calendar info is going to be used to derive the formats.\n */\n function DateTimeScaleFormatInfo(culture) {\n var calendar = culture.calendar;\n var patterns = calendar.patterns;\n var monthAbbreviations = calendar[\"months\"][\"namesAbbr\"];\n var cultureHasMonthAbbr = monthAbbreviations && monthAbbreviations[0];\n var yearMonthPattern = patterns[\"Y\"];\n var monthDayPattern = patterns[\"M\"];\n var fullPattern = patterns[\"f\"];\n var longTimePattern = patterns[\"T\"];\n var shortTimePattern = patterns[\"t\"];\n var separator = fullPattern.indexOf(\",\") > -1 ? \", \" : \" \";\n var hasYearSymbol = yearMonthPattern.indexOf(\"yyyy'\") === 0 && yearMonthPattern.length > 6 && yearMonthPattern[6] === '\\'';\n this.YearPattern = hasYearSymbol ? yearMonthPattern.substr(0, 7) : \"yyyy\";\n var yearPos = fullPattern.indexOf(\"yy\");\n var monthPos = fullPattern.indexOf(\"MMMM\");\n this.MonthPattern = cultureHasMonthAbbr && monthPos > -1 ? (yearPos > monthPos ? \"MMM yyyy\" : \"yyyy MMM\") : yearMonthPattern;\n this.DayPattern = cultureHasMonthAbbr ? monthDayPattern.replace(\"MMMM\", \"MMM\") : monthDayPattern;\n var minutePos = fullPattern.indexOf(\"mm\");\n var pmPos = fullPattern.indexOf(\"tt\");\n var shortHourPattern = pmPos > -1 ? shortTimePattern.replace(\":mm \", \"\") : shortTimePattern;\n this.HourPattern = yearPos < minutePos ? this.DayPattern + separator + shortHourPattern : shortHourPattern + separator + this.DayPattern;\n this.MinutePattern = shortTimePattern;\n this.SecondPattern = longTimePattern;\n this.MillisecondPattern = longTimePattern.replace(\"ss\", \"ss.fff\");\n // Special cases\n switch (culture.name) {\n case \"fi-FI\":\n this.DayPattern = this.DayPattern.replace(\"'ta'\", \"\"); // Fix for finish 'ta' suffix for month names.\n this.HourPattern = this.HourPattern.replace(\"'ta'\", \"\");\n break;\n }\n }\n // Methods\n /**\n * Returns the format string of the provided DateTimeUnit.\n * @param unit - date or time unit\n */\n DateTimeScaleFormatInfo.prototype.getFormatString = function (unit) {\n switch (unit) {\n case powerbi_1.DateTimeUnit.Year:\n return this.YearPattern;\n case powerbi_1.DateTimeUnit.Month:\n return this.MonthPattern;\n case powerbi_1.DateTimeUnit.Week:\n case powerbi_1.DateTimeUnit.Day:\n return this.DayPattern;\n case powerbi_1.DateTimeUnit.Hour:\n return this.HourPattern;\n case powerbi_1.DateTimeUnit.Minute:\n return this.MinutePattern;\n case powerbi_1.DateTimeUnit.Second:\n return this.SecondPattern;\n case powerbi_1.DateTimeUnit.Millisecond:\n return this.MillisecondPattern;\n }\n debug.assertFail('Unexpected unit: ' + unit);\n };\n return DateTimeScaleFormatInfo;\n }());\n powerbi_1.formattingService = new FormattingService();\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var data;\n (function (data) {\n /** Serializes SQExpr in a form optimized in-memory comparison, but not intended for storage on disk. */\n var SQExprShortSerializer;\n (function (SQExprShortSerializer) {\n function serialize(expr) {\n return JSON.stringify(expr.accept(SQExprSerializer.instance));\n }\n SQExprShortSerializer.serialize = serialize;\n function serializeArray(exprs) {\n var str = '[';\n for (var i = 0, len = exprs.length; i < len; i++) {\n if (i > 0)\n str += ',';\n str += SQExprShortSerializer.serialize(exprs[i]);\n }\n return str + ']';\n }\n SQExprShortSerializer.serializeArray = serializeArray;\n /** Responsible for serializing an SQExpr into a comparable string. */\n var SQExprSerializer = (function (_super) {\n __extends(SQExprSerializer, _super);\n function SQExprSerializer() {\n _super.apply(this, arguments);\n }\n SQExprSerializer.prototype.visitColumnRef = function (expr) {\n return {\n col: {\n s: expr.source.accept(this),\n r: expr.ref,\n }\n };\n };\n SQExprSerializer.prototype.visitMeasureRef = function (expr) {\n return {\n measure: {\n s: expr.source.accept(this),\n r: expr.ref,\n }\n };\n };\n SQExprSerializer.prototype.visitAggr = function (expr) {\n return {\n agg: {\n a: expr.arg.accept(this),\n f: expr.func,\n }\n };\n };\n SQExprSerializer.prototype.visitEntity = function (expr) {\n debug.assertValue(expr, 'expr');\n debug.assertValue(expr.entity, 'expr.entity');\n return {\n e: expr.entity\n };\n };\n SQExprSerializer.prototype.visitHierarchyLevel = function (expr) {\n return {\n h: expr.arg.accept(this),\n l: expr.level,\n };\n };\n SQExprSerializer.prototype.visitHierarchy = function (expr) {\n return {\n e: expr.arg.accept(this),\n h: expr.hierarchy,\n };\n };\n SQExprSerializer.prototype.visitPropertyVariationSource = function (expr) {\n return {\n e: expr.arg.accept(this),\n n: expr.name,\n p: expr.property,\n };\n };\n SQExprSerializer.prototype.visitAnd = function (expr) {\n debug.assertValue(expr, 'expr');\n return {\n and: {\n l: expr.left.accept(this),\n r: expr.right.accept(this),\n }\n };\n };\n SQExprSerializer.prototype.visitCompare = function (expr) {\n debug.assertValue(expr, 'expr');\n return {\n comp: {\n k: expr.comparison,\n l: expr.left.accept(this),\n r: expr.right.accept(this),\n }\n };\n };\n SQExprSerializer.prototype.visitConstant = function (expr) {\n debug.assertValue(expr, 'expr');\n return {\n const: {\n t: expr.type.primitiveType,\n v: expr.value,\n }\n };\n };\n SQExprSerializer.prototype.visitArithmetic = function (expr) {\n debug.assertValue(expr, 'expr');\n return {\n arithmetic: {\n o: expr.operator,\n l: expr.left.accept(this),\n r: expr.right.accept(this)\n }\n };\n };\n SQExprSerializer.prototype.visitScopedEval = function (expr) {\n debug.assertValue(expr, 'expr');\n return {\n scopedEval: {\n e: expr.expression.accept(this),\n s: serializeArray(expr.scope)\n }\n };\n };\n SQExprSerializer.prototype.visitDefault = function (expr) {\n debug.assertFail('Unexpected expression type found in DataViewScopeIdentity.');\n return;\n };\n SQExprSerializer.instance = new SQExprSerializer();\n return SQExprSerializer;\n }(data.DefaultSQExprVisitor));\n })(SQExprShortSerializer = data.SQExprShortSerializer || (data.SQExprShortSerializer = {}));\n })(data = powerbi.data || (powerbi.data = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Selector = powerbi.data.Selector;\n /**\n * A combination of identifiers used to uniquely identify\n * data points and their bound geometry.\n */\n var SelectionId = (function () {\n function SelectionId(selector, highlight) {\n this.selector = selector;\n this.highlight = highlight;\n this.key = JSON.stringify({ selector: selector ? Selector.getKey(selector) : null, highlight: highlight });\n this.keyWithoutHighlight = JSON.stringify({ selector: selector ? Selector.getKey(selector) : null });\n }\n SelectionId.prototype.equals = function (other) {\n if (!this.selector || !other.selector) {\n return (!this.selector === !other.selector) && this.highlight === other.highlight;\n }\n return this.highlight === other.highlight && Selector.equals(this.selector, other.selector);\n };\n /**\n * Checks equality against other for all identifiers existing in this.\n */\n SelectionId.prototype.includes = function (other, ignoreHighlight) {\n if (ignoreHighlight === void 0) { ignoreHighlight = false; }\n var thisSelector = this.selector;\n var otherSelector = other.selector;\n if (!thisSelector || !otherSelector) {\n return false;\n }\n var thisData = thisSelector.data;\n var otherData = otherSelector.data;\n if (!thisData && (thisSelector.metadata && thisSelector.metadata !== otherSelector.metadata))\n return false;\n if (!ignoreHighlight && this.highlight !== other.highlight)\n return false;\n if (thisData) {\n if (!otherData)\n return false;\n if (thisData.length > 0) {\n for (var i = 0, ilen = thisData.length; i < ilen; i++) {\n var thisValue = thisData[i];\n if (!otherData.some(function (otherValue) { return powerbi.DataViewScopeIdentity.equals(thisValue, otherValue); }))\n return false;\n }\n }\n }\n return true;\n };\n SelectionId.prototype.getKey = function () {\n return this.key;\n };\n SelectionId.prototype.getKeyWithoutHighlight = function () {\n return this.keyWithoutHighlight;\n };\n SelectionId.prototype.hasIdentity = function () {\n return (this.selector && !!this.selector.data);\n };\n SelectionId.prototype.getSelector = function () {\n return this.selector;\n };\n SelectionId.prototype.getSelectorsByColumn = function () {\n return this.selectorsByColumn;\n };\n SelectionId.createNull = function (highlight) {\n if (highlight === void 0) { highlight = false; }\n return new SelectionId(null, highlight);\n };\n SelectionId.createWithId = function (id, highlight) {\n if (highlight === void 0) { highlight = false; }\n var selector = null;\n if (id) {\n selector = {\n data: [id]\n };\n }\n return new SelectionId(selector, highlight);\n };\n SelectionId.createWithMeasure = function (measureId, highlight) {\n if (highlight === void 0) { highlight = false; }\n debug.assertValue(measureId, 'measureId');\n var selector = {\n metadata: measureId\n };\n var selectionId = new SelectionId(selector, highlight);\n selectionId.selectorsByColumn = { metadata: measureId };\n return selectionId;\n };\n SelectionId.createWithIdAndMeasure = function (id, measureId, highlight) {\n if (highlight === void 0) { highlight = false; }\n var selector = {};\n if (id) {\n selector.data = [id];\n }\n if (measureId)\n selector.metadata = measureId;\n if (!id && !measureId)\n selector = null;\n var selectionId = new SelectionId(selector, highlight);\n return selectionId;\n };\n SelectionId.createWithIdAndMeasureAndCategory = function (id, measureId, queryName, highlight) {\n if (highlight === void 0) { highlight = false; }\n var selectionId = this.createWithIdAndMeasure(id, measureId, highlight);\n if (selectionId.selector) {\n selectionId.selectorsByColumn = {};\n if (id && queryName) {\n selectionId.selectorsByColumn.dataMap = {};\n selectionId.selectorsByColumn.dataMap[queryName] = id;\n }\n if (measureId)\n selectionId.selectorsByColumn.metadata = measureId;\n }\n return selectionId;\n };\n SelectionId.createWithIds = function (id1, id2, highlight) {\n if (highlight === void 0) { highlight = false; }\n var selector = null;\n var selectorData = SelectionId.idArray(id1, id2);\n if (selectorData)\n selector = { data: selectorData };\n return new SelectionId(selector, highlight);\n };\n SelectionId.createWithIdsAndMeasure = function (id1, id2, measureId, highlight) {\n if (highlight === void 0) { highlight = false; }\n var selector = {};\n var selectorData = SelectionId.idArray(id1, id2);\n if (selectorData)\n selector.data = selectorData;\n if (measureId)\n selector.metadata = measureId;\n if (!id1 && !id2 && !measureId)\n selector = null;\n return new SelectionId(selector, highlight);\n };\n SelectionId.createWithSelectorForColumnAndMeasure = function (dataMap, measureId, highlight) {\n if (highlight === void 0) { highlight = false; }\n var selectionId;\n var keys = Object.keys(dataMap);\n if (keys.length === 2) {\n selectionId = this.createWithIdsAndMeasure(dataMap[keys[0]], dataMap[keys[1]], measureId, highlight);\n }\n else if (keys.length === 1) {\n selectionId = this.createWithIdsAndMeasure(dataMap[keys[0]], null, measureId, highlight);\n }\n else {\n selectionId = this.createWithIdsAndMeasure(null, null, measureId, highlight);\n }\n var selectorsByColumn = {};\n if (!_.isEmpty(dataMap))\n selectorsByColumn.dataMap = dataMap;\n if (measureId)\n selectorsByColumn.metadata = measureId;\n if (!dataMap && !measureId)\n selectorsByColumn = null;\n selectionId.selectorsByColumn = selectorsByColumn;\n return selectionId;\n };\n SelectionId.createWithHighlight = function (original) {\n debug.assertValue(original, 'original');\n debug.assert(!original.highlight, '!original.highlight');\n var newId = new SelectionId(original.getSelector(), /*highlight*/ true);\n newId.selectorsByColumn = original.selectorsByColumn;\n return newId;\n };\n SelectionId.idArray = function (id1, id2) {\n if (id1 || id2) {\n var data_4 = [];\n if (id1)\n data_4.push(id1);\n if (id2 && id2 !== id1)\n data_4.push(id2);\n return data_4;\n }\n };\n return SelectionId;\n }());\n visuals.SelectionId = SelectionId;\n /**\n * This class is designed to simplify the creation of SelectionId objects\n * It allows chaining to build up an object before calling 'create' to build a SelectionId\n */\n var SelectionIdBuilder = (function () {\n function SelectionIdBuilder() {\n }\n SelectionIdBuilder.builder = function () {\n return new SelectionIdBuilder();\n };\n SelectionIdBuilder.prototype.withCategory = function (categoryColumn, index) {\n if (categoryColumn && categoryColumn.source && categoryColumn.source.queryName && categoryColumn.identity)\n this.ensureDataMap()[categoryColumn.source.queryName] = categoryColumn.identity[index];\n return this;\n };\n SelectionIdBuilder.prototype.withSeries = function (seriesColumn, valueColumn) {\n if (seriesColumn && seriesColumn.source && seriesColumn.source.queryName && valueColumn)\n this.ensureDataMap()[seriesColumn.source.queryName] = valueColumn.identity;\n return this;\n };\n SelectionIdBuilder.prototype.withMeasure = function (measureId) {\n this.measure = measureId;\n return this;\n };\n SelectionIdBuilder.prototype.createSelectionId = function () {\n return SelectionId.createWithSelectorForColumnAndMeasure(this.ensureDataMap(), this.measure);\n };\n SelectionIdBuilder.prototype.ensureDataMap = function () {\n if (!this.dataMap)\n this.dataMap = {};\n return this.dataMap;\n };\n return SelectionIdBuilder;\n }());\n visuals.SelectionIdBuilder = SelectionIdBuilder;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n\n\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n /** Allows generic traversal and type discovery for a SQExpr tree. */\r\n export interface ISQExprVisitorWithArg<T, TArg> {\r\n visitEntity(expr: SQEntityExpr, arg: TArg): T;\r\n visitColumnRef(expr: SQColumnRefExpr, arg: TArg): T;\r\n visitMeasureRef(expr: SQMeasureRefExpr, arg: TArg): T;\r\n visitAggr(expr: SQAggregationExpr, arg: TArg): T;\r\n visitPercentile(expr: SQPercentileExpr, arg: TArg): T;\r\n visitHierarchy(expr: SQHierarchyExpr, arg: TArg): T;\r\n visitHierarchyLevel(expr: SQHierarchyLevelExpr, arg: TArg): T;\r\n visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr, arg: TArg): T;\r\n visitSelectRef(expr: SQSelectRefExpr, arg: TArg): T;\r\n visitAnd(expr: SQAndExpr, arg: TArg): T;\r\n visitBetween(expr: SQBetweenExpr, arg: TArg): T;\r\n visitIn(expr: SQInExpr, arg: TArg): T;\r\n visitOr(expr: SQOrExpr, arg: TArg): T;\r\n visitCompare(expr: SQCompareExpr, arg: TArg): T;\r\n visitContains(expr: SQContainsExpr, arg: TArg): T;\r\n visitExists(expr: SQExistsExpr, arg: TArg): T;\r\n visitNot(expr: SQNotExpr, arg: TArg): T;\r\n visitStartsWith(expr: SQStartsWithExpr, arg: TArg): T;\r\n visitConstant(expr: SQConstantExpr, arg: TArg): T;\r\n visitDateSpan(expr: SQDateSpanExpr, arg: TArg): T;\r\n visitDateAdd(expr: SQDateAddExpr, arg: TArg): T;\r\n visitNow(expr: SQNowExpr, arg: TArg): T;\r\n visitDefaultValue(expr: SQDefaultValueExpr, arg: TArg): T;\r\n visitAnyValue(expr: SQAnyValueExpr, arg: TArg): T;\r\n visitArithmetic(expr: SQArithmeticExpr, arg: TArg): T;\r\n visitFillRule(expr: SQFillRuleExpr, arg: TArg): T;\r\n visitResourcePackageItem(expr: SQResourcePackageItemExpr, arg: TArg): T;\r\n visitScopedEval(expr: SQScopedEvalExpr, arg: TArg): T;\r\n }\r\n\r\n export interface ISQExprVisitor<T> extends ISQExprVisitorWithArg<T, void> {\r\n }\r\n\r\n /** Default IQueryExprVisitorWithArg implementation that others may derive from. */\r\n export class DefaultSQExprVisitorWithArg<T, TArg> implements ISQExprVisitorWithArg<T, TArg> {\r\n public visitEntity(expr: SQEntityExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitPercentile(expr: SQPercentileExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitSelectRef(expr: SQSelectRefExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitBetween(expr: SQBetweenExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitIn(expr: SQInExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitAnd(expr: SQAndExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitOr(expr: SQOrExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitContains(expr: SQContainsExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitExists(expr: SQExistsExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitNot(expr: SQNotExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitStartsWith(expr: SQStartsWithExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitDateSpan(expr: SQDateSpanExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitDateAdd(expr: SQDateAddExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitNow(expr: SQNowExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitDefaultValue(expr: SQDefaultValueExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitAnyValue(expr: SQAnyValueExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitFillRule(expr: SQFillRuleExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitResourcePackageItem(expr: SQResourcePackageItemExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitScopedEval(expr: SQScopedEvalExpr, arg: TArg): T {\r\n return this.visitDefault(expr, arg);\r\n }\r\n\r\n public visitDefault(expr: SQExpr, arg: TArg): T {\r\n return;\r\n }\r\n }\r\n\r\n /** Default ISQExprVisitor implementation that others may derive from. */\r\n export class DefaultSQExprVisitor<T> extends DefaultSQExprVisitorWithArg<T, void> implements ISQExprVisitor<T> {\r\n }\r\n\r\n /** Default ISQExprVisitor implementation that implements default traversal and that others may derive from. */\r\n export class DefaultSQExprVisitorWithTraversal implements ISQExprVisitor<void>, IFillRuleDefinitionVisitor<void, void> {\r\n public visitEntity(expr: SQEntityExpr): void {\r\n this.visitDefault(expr);\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): void {\r\n expr.source.accept(this);\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr): void {\r\n expr.source.accept(this);\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): void {\r\n expr.arg.accept(this);\r\n } \r\n\r\n public visitPercentile(expr: SQPercentileExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitSelectRef(expr: SQSelectRefExpr): void {\r\n this.visitDefault(expr);\r\n }\r\n\r\n public visitBetween(expr: SQBetweenExpr): void {\r\n expr.arg.accept(this);\r\n expr.lower.accept(this);\r\n expr.upper.accept(this);\r\n }\r\n\r\n public visitIn(expr: SQInExpr): void {\r\n let args = expr.args;\r\n for (let i = 0, len = args.length; i < len; i++)\r\n args[i].accept(this);\r\n\r\n let values = expr.values;\r\n for (let i = 0, len = values.length; i < len; i++) {\r\n let valueTuple = values[i];\r\n for (let j = 0, jlen = valueTuple.length; j < jlen; j++)\r\n valueTuple[j].accept(this);\r\n }\r\n }\r\n\r\n public visitAnd(expr: SQAndExpr): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitOr(expr: SQOrExpr): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitContains(expr: SQContainsExpr): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitExists(expr: SQExistsExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitNot(expr: SQNotExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitStartsWith(expr: SQStartsWithExpr): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr): void {\r\n this.visitDefault(expr);\r\n }\r\n\r\n public visitDateSpan(expr: SQDateSpanExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitDateAdd(expr: SQDateAddExpr): void {\r\n expr.arg.accept(this);\r\n }\r\n\r\n public visitNow(expr: SQNowExpr): void {\r\n this.visitDefault(expr);\r\n }\r\n\r\n public visitDefaultValue(expr: SQDefaultValueExpr): void {\r\n this.visitDefault(expr);\r\n }\r\n\r\n public visitAnyValue(expr: SQAnyValueExpr): void {\r\n this.visitDefault(expr);\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitFillRule(expr: SQFillRuleExpr): void {\r\n expr.input.accept(this);\r\n\r\n let rule = expr.rule,\r\n gradient2 = rule.linearGradient2,\r\n gradient3 = rule.linearGradient3;\r\n\r\n if (gradient2) {\r\n this.visitLinearGradient2(gradient2);\r\n }\r\n\r\n if (gradient3) {\r\n this.visitLinearGradient3(gradient3);\r\n }\r\n }\r\n\r\n public visitLinearGradient2(gradient2: LinearGradient2Definition): void {\r\n debug.assertValue(gradient2, 'gradient2');\r\n\r\n this.visitFillRuleStop(gradient2.min);\r\n this.visitFillRuleStop(gradient2.max);\r\n }\r\n\r\n public visitLinearGradient3(gradient3: LinearGradient3Definition): void {\r\n debug.assertValue(gradient3, 'gradient3');\r\n\r\n this.visitFillRuleStop(gradient3.min);\r\n this.visitFillRuleStop(gradient3.mid);\r\n this.visitFillRuleStop(gradient3.max);\r\n }\r\n\r\n public visitResourcePackageItem(expr: SQResourcePackageItemExpr): void {\r\n this.visitDefault(expr);\r\n }\r\n\r\n public visitScopedEval(expr: SQScopedEvalExpr): void {\r\n expr.expression.accept(this);\r\n\r\n for (let scopeExpr of expr.scope) {\r\n scopeExpr.accept(this);\r\n }\r\n }\r\n\r\n public visitDefault(expr: SQExpr): void {\r\n return;\r\n }\r\n\r\n private visitFillRuleStop(stop: RuleColorStopDefinition): void {\r\n debug.assertValue(stop, 'stop');\r\n\r\n stop.color.accept(this);\r\n\r\n let value = stop.value;\r\n if (value)\r\n value.accept(this);\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n /** Defines a custom enumeration data type, and its values. */\r\n export interface IEnumType {\r\n /** Gets the members of the enumeration, limited to the validMembers, if appropriate. */\r\n members(validMembers?: EnumMemberValue[]): IEnumMember[];\r\n }\r\n\r\n export function createEnumType(members: IEnumMember[]): IEnumType {\r\n return new EnumType(members);\r\n }\r\n\r\n class EnumType implements IEnumType {\r\n private allMembers: IEnumMember[];\r\n\r\n constructor(allMembers: IEnumMember[]) {\r\n debug.assertValue(allMembers, 'allMembers');\r\n\r\n this.allMembers = allMembers;\r\n }\r\n\r\n public members(validMembers?: EnumMemberValue[]): IEnumMember[] {\r\n let allMembers = this.allMembers;\r\n if (!validMembers)\r\n return allMembers;\r\n\r\n let membersToReturn: IEnumMember[] = [];\r\n for (let member of allMembers) {\r\n if (_.contains(validMembers, member.value))\r\n membersToReturn.push(member);\r\n }\r\n return membersToReturn;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import SQExpr = powerbi.data.SQExpr;\r\n\r\n export interface FillDefinition {\r\n solid?: {\r\n color?: SQExpr;\r\n };\r\n gradient?: {\r\n startColor?: SQExpr;\r\n endColor?: SQExpr;\r\n };\r\n pattern?: {\r\n patternKind?: SQExpr;\r\n color?: SQExpr;\r\n };\r\n }\r\n\r\n export module FillSolidColorTypeDescriptor {\r\n /** Gets a value indicating whether the descriptor is nullable or not. */\r\n export function nullable(descriptor: FillSolidColorTypeDescriptor): boolean {\r\n debug.assertValue(descriptor, 'descriptor');\r\n\r\n if (descriptor === true)\r\n return false;\r\n\r\n let advancedDescriptor = <FillSolidColorAdvancedTypeDescriptor>descriptor;\r\n return !!advancedDescriptor.nullable;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import SQExpr = powerbi.data.SQExpr;\r\n\r\n export interface ImageTypeDescriptor {\r\n }\r\n\r\n export type ImageDefinition = ImageDefinitionGeneric<SQExpr>;\r\n\r\n export module ImageDefinition {\r\n export const urlType: ValueTypeDescriptor = { misc: { imageUrl: true } };\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import SemanticFilter = powerbi.data.SemanticFilter;\r\n\r\n export type StructuralObjectDefinition =\r\n FillDefinition |\r\n FillRuleDefinition |\r\n SemanticFilter |\r\n DefaultValueDefinition |\r\n ImageDefinition |\r\n ParagraphsDefinition;\r\n\r\n export module StructuralTypeDescriptor {\r\n export function isValid(type: StructuralTypeDescriptor): boolean {\r\n debug.assertValue(type, 'type');\r\n\r\n if (type.fill ||\r\n type.fillRule ||\r\n type.filter ||\r\n type.expression ||\r\n type.image ||\r\n type.paragraphs) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import EnumExtensions = jsCommon.EnumExtensions;\r\n\r\n export interface ValueTypeDescriptor {\r\n extendedType?: ExtendedType;\r\n }\r\n \r\n /** Describes a data value type, including a primitive type and extended type if any (derived from data category). */\r\n export class ValueType implements ValueTypeDescriptor {\r\n private static typeCache: { [id: string]: ValueType } = {};\r\n\r\n private underlyingType: ExtendedType;\r\n private category: string;\r\n\r\n private temporalType: TemporalType;\r\n private geographyType: GeographyType;\r\n private miscType: MiscellaneousType;\r\n private formattingType: FormattingType;\r\n private enumType: IEnumType;\r\n private scriptingType: ScriptType;\r\n\r\n /** Do not call the ValueType constructor directly. Use the ValueType.fromXXX methods. */\r\n constructor(type: ExtendedType, category?: string, enumType?: IEnumType) {\r\n debug.assert((!!type && ExtendedType[type] != null) || type === ExtendedType.Null, 'type');\r\n debug.assert(!!category || category === null, 'category');\r\n debug.assert(type !== ExtendedType.Enumeration || !!enumType, 'enumType');\r\n\r\n this.underlyingType = type;\r\n this.category = category;\r\n\r\n if (EnumExtensions.hasFlag(type, ExtendedType.Temporal)) {\r\n this.temporalType = new TemporalType(type);\r\n }\r\n if (EnumExtensions.hasFlag(type, ExtendedType.Geography)) {\r\n this.geographyType = new GeographyType(type);\r\n }\r\n if (EnumExtensions.hasFlag(type, ExtendedType.Miscellaneous)) {\r\n this.miscType = new MiscellaneousType(type);\r\n }\r\n if (EnumExtensions.hasFlag(type, ExtendedType.Formatting)) {\r\n this.formattingType = new FormattingType(type);\r\n }\r\n if (EnumExtensions.hasFlag(type, ExtendedType.Enumeration)) {\r\n this.enumType = enumType;\r\n }\r\n if (EnumExtensions.hasFlag(type, ExtendedType.Scripting)) {\r\n this.scriptingType = new ScriptType(type);\r\n }\r\n }\r\n\r\n /** Creates or retrieves a ValueType object based on the specified ValueTypeDescriptor. */\r\n public static fromDescriptor(descriptor: ValueTypeDescriptor): ValueType {\r\n descriptor = descriptor || {};\r\n\r\n // Simplified primitive types\r\n if (descriptor.text) return ValueType.fromExtendedType(ExtendedType.Text);\r\n if (descriptor.integer) return ValueType.fromExtendedType(ExtendedType.Integer);\r\n if (descriptor.numeric) return ValueType.fromExtendedType(ExtendedType.Double);\r\n if (descriptor.bool) return ValueType.fromExtendedType(ExtendedType.Boolean);\r\n if (descriptor.dateTime) return ValueType.fromExtendedType(ExtendedType.DateTime);\r\n if (descriptor.duration) return ValueType.fromExtendedType(ExtendedType.Duration);\r\n if (descriptor.binary) return ValueType.fromExtendedType(ExtendedType.Binary);\r\n if (descriptor.none) return ValueType.fromExtendedType(ExtendedType.None);\r\n\r\n // Extended types\r\n if (descriptor.scripting) {\r\n if (descriptor.scripting.source) return ValueType.fromExtendedType(ExtendedType.ScriptSource);\r\n }\r\n if (descriptor.enumeration) return ValueType.fromEnum(descriptor.enumeration);\r\n if (descriptor.temporal) {\r\n if (descriptor.temporal.year) return ValueType.fromExtendedType(ExtendedType.Year_Integer);\r\n if (descriptor.temporal.month) return ValueType.fromExtendedType(ExtendedType.Month_Integer);\r\n }\r\n if (descriptor.geography) {\r\n if (descriptor.geography.address) return ValueType.fromExtendedType(ExtendedType.Address);\r\n if (descriptor.geography.city) return ValueType.fromExtendedType(ExtendedType.City);\r\n if (descriptor.geography.continent) return ValueType.fromExtendedType(ExtendedType.Continent);\r\n if (descriptor.geography.country) return ValueType.fromExtendedType(ExtendedType.Country);\r\n if (descriptor.geography.county) return ValueType.fromExtendedType(ExtendedType.County);\r\n if (descriptor.geography.region) return ValueType.fromExtendedType(ExtendedType.Region);\r\n if (descriptor.geography.postalCode) return ValueType.fromExtendedType(ExtendedType.PostalCode_Text);\r\n if (descriptor.geography.stateOrProvince) return ValueType.fromExtendedType(ExtendedType.StateOrProvince);\r\n if (descriptor.geography.place) return ValueType.fromExtendedType(ExtendedType.Place);\r\n if (descriptor.geography.latitude) return ValueType.fromExtendedType(ExtendedType.Latitude_Double);\r\n if (descriptor.geography.longitude) return ValueType.fromExtendedType(ExtendedType.Longitude_Double);\r\n }\r\n if (descriptor.misc) {\r\n if (descriptor.misc.image) return ValueType.fromExtendedType(ExtendedType.Image);\r\n if (descriptor.misc.imageUrl) return ValueType.fromExtendedType(ExtendedType.ImageUrl);\r\n if (descriptor.misc.webUrl) return ValueType.fromExtendedType(ExtendedType.WebUrl);\r\n if (descriptor.misc.barcode) return ValueType.fromExtendedType(ExtendedType.Barcode_Text);\r\n }\r\n if (descriptor.formatting) {\r\n if (descriptor.formatting.color) return ValueType.fromExtendedType(ExtendedType.Color);\r\n if (descriptor.formatting.formatString) return ValueType.fromExtendedType(ExtendedType.FormatString);\r\n if (descriptor.formatting.alignment) return ValueType.fromExtendedType(ExtendedType.Alignment);\r\n if (descriptor.formatting.labelDisplayUnits) return ValueType.fromExtendedType(ExtendedType.LabelDisplayUnits);\r\n if (descriptor.formatting.fontSize) return ValueType.fromExtendedType(ExtendedType.FontSize);\r\n if (descriptor.formatting.labelDensity) return ValueType.fromExtendedType(ExtendedType.LabelDensity);\r\n }\r\n if (descriptor.extendedType) {\r\n return ValueType.fromExtendedType(descriptor.extendedType);\r\n }\r\n\r\n return ValueType.fromExtendedType(ExtendedType.Null);\r\n }\r\n\r\n /** Advanced: Generally use fromDescriptor instead. Creates or retrieves a ValueType object for the specified ExtendedType. */\r\n public static fromExtendedType(extendedType: ExtendedType): ValueType {\r\n extendedType = extendedType || ExtendedType.Null;\r\n\r\n let primitiveType = getPrimitiveType(extendedType),\r\n category = getCategoryFromExtendedType(extendedType);\r\n debug.assert(\r\n primitiveType !== PrimitiveType.Null || extendedType === ExtendedType.Null,\r\n 'Cannot create ValueType for abstract extended type. Consider using fromDescriptor instead.');\r\n return ValueType.fromPrimitiveTypeAndCategory(primitiveType, category);\r\n }\r\n\r\n /** Creates or retrieves a ValueType object for the specified PrimitiveType and data category. */\r\n public static fromPrimitiveTypeAndCategory(primitiveType: PrimitiveType, category?: string): ValueType {\r\n primitiveType = primitiveType || PrimitiveType.Null;\r\n category = category || null;\r\n\r\n let id = primitiveType.toString();\r\n if (category)\r\n id += '|' + category;\r\n\r\n return ValueType.typeCache[id] || (ValueType.typeCache[id] = new ValueType(toExtendedType(primitiveType, category), category));\r\n }\r\n\r\n /** Creates a ValueType to describe the given IEnumType. */\r\n public static fromEnum(enumType: IEnumType): ValueType {\r\n debug.assertValue(enumType, 'enumType');\r\n\r\n return new ValueType(ExtendedType.Enumeration, null, enumType);\r\n }\r\n\r\n /** Determines if the specified type is compatible from at least one of the otherTypes. */\r\n public static isCompatibleTo(type: ValueTypeDescriptor, otherTypes: ValueTypeDescriptor[]): boolean {\r\n debug.assertValue(type, 'type');\r\n debug.assertValue(otherTypes, 'otherTypes');\r\n\r\n let valueType = ValueType.fromDescriptor(type);\r\n for (let otherType of otherTypes) {\r\n let otherValueType = ValueType.fromDescriptor(otherType);\r\n\r\n if (otherValueType.isCompatibleFrom(valueType))\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /** Determines if the instance ValueType is convertable from the 'other' ValueType. */\r\n public isCompatibleFrom(other: ValueType): boolean {\r\n debug.assertValue(other, 'other');\r\n\r\n let otherPrimitiveType = other.primitiveType;\r\n if (this === other ||\r\n this.primitiveType === otherPrimitiveType ||\r\n otherPrimitiveType === PrimitiveType.Null)\r\n return true;\r\n return false;\r\n }\r\n\r\n /**\r\n * Determines if the instance ValueType is equal to the 'other' ValueType\r\n * @param {ValueType} other the other ValueType to check equality against\r\n * @returns True if the instance ValueType is equal to the 'other' ValueType\r\n */\r\n public equals(other: ValueType): boolean {\r\n return _.isEqual(this, other);\r\n }\r\n\r\n /** Gets the exact primitive type of this ValueType. */\r\n public get primitiveType(): PrimitiveType {\r\n return getPrimitiveType(this.underlyingType);\r\n }\r\n\r\n /** Gets the exact extended type of this ValueType. */\r\n public get extendedType(): ExtendedType {\r\n return this.underlyingType;\r\n }\r\n\r\n /** Gets the data category string (if any) for this ValueType. */\r\n public get categoryString(): string {\r\n return this.category;\r\n }\r\n\r\n // Simplified primitive types\r\n\r\n /** Indicates whether the type represents text values. */\r\n public get text(): boolean {\r\n return this.primitiveType === PrimitiveType.Text;\r\n }\r\n\r\n /** Indicates whether the type represents any numeric value. */\r\n public get numeric(): boolean {\r\n return EnumExtensions.hasFlag(this.underlyingType, ExtendedType.Numeric);\r\n }\r\n\r\n /** Indicates whether the type represents integer numeric values. */\r\n public get integer(): boolean {\r\n return this.primitiveType === PrimitiveType.Integer;\r\n }\r\n\r\n /** Indicates whether the type represents Boolean values. */\r\n public get bool(): boolean {\r\n return this.primitiveType === PrimitiveType.Boolean;\r\n }\r\n\r\n /** Indicates whether the type represents any date/time values. */\r\n public get dateTime(): boolean {\r\n return this.primitiveType === PrimitiveType.DateTime ||\r\n this.primitiveType === PrimitiveType.Date ||\r\n this.primitiveType === PrimitiveType.Time;\r\n }\r\n\r\n /** Indicates whether the type represents duration values. */\r\n public get duration(): boolean {\r\n return this.primitiveType === PrimitiveType.Duration;\r\n }\r\n\r\n /** Indicates whether the type represents binary values. */\r\n public get binary(): boolean {\r\n return this.primitiveType === PrimitiveType.Binary;\r\n }\r\n\r\n /** Indicates whether the type represents none values. */\r\n public get none(): boolean {\r\n return this.primitiveType === PrimitiveType.None;\r\n }\r\n\r\n // Extended types\r\n\r\n /** Returns an object describing temporal values represented by the type, if it represents a temporal type. */\r\n public get temporal(): TemporalType {\r\n return this.temporalType;\r\n }\r\n\r\n /** Returns an object describing geographic values represented by the type, if it represents a geographic type. */\r\n public get geography(): GeographyType {\r\n return this.geographyType;\r\n }\r\n\r\n /** Returns an object describing the specific values represented by the type, if it represents a miscellaneous extended type. */\r\n public get misc(): MiscellaneousType {\r\n return this.miscType;\r\n }\r\n\r\n /** Returns an object describing the formatting values represented by the type, if it represents a formatting type. */\r\n public get formatting(): FormattingType {\r\n return this.formattingType;\r\n }\r\n\r\n /** Returns an object describing the enum values represented by the type, if it represents an enumeration type. */\r\n public get enum(): IEnumType {\r\n return this.enumType;\r\n }\r\n\r\n public get scripting(): ScriptType {\r\n return this.scriptingType;\r\n }\r\n }\r\n\r\n export class ScriptType implements ScriptTypeDescriptor {\r\n private underlyingType: ExtendedType;\r\n\r\n constructor(type: ExtendedType) {\r\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Scripting), 'type');\r\n this.underlyingType = type;\r\n }\r\n\r\n public get source(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.ScriptSource);\r\n }\r\n }\r\n\r\n export class TemporalType implements TemporalTypeDescriptor {\r\n private underlyingType: ExtendedType;\r\n\r\n constructor(type: ExtendedType) {\r\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Temporal), 'type');\r\n this.underlyingType = type;\r\n }\r\n\r\n public get year(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Year);\r\n }\r\n public get month(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Month);\r\n }\r\n }\r\n\r\n export class GeographyType implements GeographyTypeDescriptor {\r\n private underlyingType: ExtendedType;\r\n\r\n constructor(type: ExtendedType) {\r\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Geography), 'type');\r\n this.underlyingType = type;\r\n }\r\n\r\n public get address(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Address);\r\n }\r\n public get city(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.City);\r\n }\r\n public get continent(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Continent);\r\n }\r\n public get country(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Country);\r\n }\r\n public get county(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.County);\r\n }\r\n public get region(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Region);\r\n }\r\n public get postalCode(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.PostalCode);\r\n }\r\n public get stateOrProvince(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.StateOrProvince);\r\n }\r\n public get place(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Place);\r\n }\r\n public get latitude(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Latitude);\r\n }\r\n public get longitude(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Longitude);\r\n }\r\n }\r\n\r\n export class MiscellaneousType implements MiscellaneousTypeDescriptor {\r\n private underlyingType: ExtendedType;\r\n\r\n constructor(type: ExtendedType) {\r\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Miscellaneous), 'type');\r\n this.underlyingType = type;\r\n }\r\n\r\n public get image(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Image);\r\n }\r\n public get imageUrl(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.ImageUrl);\r\n }\r\n public get webUrl(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.WebUrl);\r\n }\r\n public get barcode(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Barcode);\r\n }\r\n }\r\n\r\n export class FormattingType implements FormattingTypeDescriptor {\r\n private underlyingType: ExtendedType;\r\n\r\n constructor(type: ExtendedType) {\r\n debug.assert(!!type && EnumExtensions.hasFlag(type, ExtendedType.Formatting), 'type');\r\n this.underlyingType = type;\r\n }\r\n\r\n public get color(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Color);\r\n }\r\n\r\n public get formatString(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.FormatString);\r\n }\r\n\r\n public get alignment(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.Alignment);\r\n }\r\n\r\n public get labelDisplayUnits(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.LabelDisplayUnits);\r\n }\r\n\r\n public get fontSize(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.FontSize);\r\n }\r\n\r\n public get labelDensity(): boolean {\r\n return matchesExtendedTypeWithAnyPrimitive(this.underlyingType, ExtendedType.LabelDensity);\r\n }\r\n }\r\n\r\n /** Defines primitive value types. Must be consistent with types defined by server conceptual schema. */\r\n export enum PrimitiveType {\r\n Null = 0,\r\n Text = 1,\r\n Decimal = 2,\r\n Double = 3,\r\n Integer = 4,\r\n Boolean = 5,\r\n Date = 6,\r\n DateTime = 7,\r\n DateTimeZone = 8,\r\n Time = 9,\r\n Duration = 10,\r\n Binary = 11,\r\n None = 12,\r\n }\r\n\r\n /** Defines extended value types, which include primitive types and known data categories constrained to expected primitive types. */\r\n export enum ExtendedType {\r\n // Flags (1 << 8-15 range [0xFF00])\r\n // Important: Enum members must be declared before they are used in TypeScript.\r\n Numeric = 1 << 8,\r\n Temporal = 1 << 9,\r\n Geography = 1 << 10,\r\n Miscellaneous = 1 << 11,\r\n Formatting = 1 << 12,\r\n Scripting = 1 << 13, \r\n\r\n // Primitive types (0-255 range [0xFF] | flags)\r\n // The member names and base values must match those in PrimitiveType.\r\n Null = 0,\r\n Text = 1,\r\n Decimal = Numeric | 2,\r\n Double = Numeric | 3,\r\n Integer = Numeric | 4,\r\n Boolean = 5,\r\n Date = Temporal | 6,\r\n DateTime = Temporal | 7,\r\n DateTimeZone = Temporal | 8,\r\n Time = Temporal | 9,\r\n Duration = 10,\r\n Binary = 11,\r\n None = 12,\r\n\r\n // Extended types (0-32767 << 16 range [0xFFFF0000] | corresponding primitive type | flags)\r\n // Temporal\r\n Year = Temporal | (1 << 16),\r\n Year_Text = Year | Text,\r\n Year_Integer = Year | Integer,\r\n Year_Date = Year | Date,\r\n Year_DateTime = Year | DateTime,\r\n Month = Temporal | (2 << 16),\r\n Month_Text = Month | Text,\r\n Month_Integer = Month | Integer,\r\n Month_Date = Month | Date,\r\n Month_DateTime = Month | DateTime,\r\n // Geography\r\n Address = Text | Geography | (100 << 16),\r\n City = Text | Geography | (101 << 16),\r\n Continent = Text | Geography | (102 << 16),\r\n Country = Text | Geography | (103 << 16),\r\n County = Text | Geography | (104 << 16),\r\n Region = Text | Geography | (105 << 16),\r\n PostalCode = Geography | (106 << 16),\r\n PostalCode_Text = PostalCode | Text,\r\n PostalCode_Integer = PostalCode | Integer,\r\n StateOrProvince = Text | Geography | (107 << 16),\r\n Place = Text | Geography | (108 << 16),\r\n Latitude = Geography | (109 << 16),\r\n Latitude_Decimal = Latitude | Decimal,\r\n Latitude_Double = Latitude | Double,\r\n Longitude = Geography | (110 << 16),\r\n Longitude_Decimal = Longitude | Decimal,\r\n Longitude_Double = Longitude | Double,\r\n // Miscellaneous\r\n Image = Binary | Miscellaneous | (200 << 16),\r\n ImageUrl = Text | Miscellaneous | (201 << 16),\r\n WebUrl = Text | Miscellaneous | (202 << 16),\r\n Barcode = Miscellaneous | (203 << 16),\r\n Barcode_Text = Barcode | Text,\r\n Barcode_Integer = Barcode | Integer,\r\n\r\n // Formatting\r\n Color = Text | Formatting | (300 << 16),\r\n FormatString = Text | Formatting | (301 << 16),\r\n Alignment = Text | Formatting | (306 << 16),\r\n LabelDisplayUnits = Text | Formatting | (307 << 16),\r\n FontSize = Double | Formatting | (308 << 16),\r\n LabelDensity = Double | Formatting | (309 << 16),\r\n // Enumeration\r\n Enumeration = Text | 400 << 16,\r\n // Scripting\r\n ScriptSource = Text | Scripting | (500 << 16), \r\n // NOTE: To avoid confusion, underscores should be used only to delimit primitive type variants of an extended type\r\n // (e.g. Year_Integer or Latitude_Double above)\r\n }\r\n\r\n const PrimitiveTypeMask = 0xFF;\r\n const PrimitiveTypeWithFlagsMask = 0xFFFF;\r\n const PrimitiveTypeFlagsExcludedMask = 0xFFFF0000;\r\n\r\n function getPrimitiveType(extendedType: ExtendedType): PrimitiveType {\r\n return extendedType & PrimitiveTypeMask;\r\n }\r\n\r\n function isPrimitiveType(extendedType: ExtendedType): boolean {\r\n return (extendedType & PrimitiveTypeWithFlagsMask) === extendedType;\r\n }\r\n\r\n function getCategoryFromExtendedType(extendedType: ExtendedType): string {\r\n if (isPrimitiveType(extendedType))\r\n return null;\r\n\r\n let category = ExtendedType[extendedType];\r\n if (category) {\r\n // Check for ExtendedType declaration without a primitive type.\r\n // If exists, use it as category (e.g. Longitude rather than Longitude_Double)\r\n // Otherwise use the ExtendedType declaration with a primitive type (e.g. Address)\r\n let delimIdx = category.lastIndexOf('_');\r\n if (delimIdx > 0) {\r\n let baseCategory = category.slice(0, delimIdx);\r\n if (ExtendedType[baseCategory]) {\r\n debug.assert(\r\n (ExtendedType[baseCategory] & PrimitiveTypeFlagsExcludedMask) === (extendedType & PrimitiveTypeFlagsExcludedMask),\r\n 'Unexpected value for ExtendedType base member of ' + extendedType);\r\n category = baseCategory;\r\n }\r\n }\r\n }\r\n return category || null;\r\n }\r\n\r\n function toExtendedType(primitiveType: PrimitiveType, category?: string): ExtendedType {\r\n let primitiveString = PrimitiveType[primitiveType];\r\n let t = ExtendedType[primitiveString];\r\n if (t == null) {\r\n debug.assertFail('Unexpected primitiveType ' + primitiveType);\r\n t = ExtendedType.Null;\r\n }\r\n\r\n if (primitiveType && category) {\r\n let categoryType: ExtendedType = ExtendedType[category];\r\n if (categoryType) {\r\n let categoryPrimitiveType = getPrimitiveType(categoryType);\r\n if (categoryPrimitiveType === PrimitiveType.Null) {\r\n // Category supports multiple primitive types, check if requested primitive type is supported\r\n // (note: important to use t here rather than primitiveType as it may include primitive type flags)\r\n categoryType = t | categoryType;\r\n if (ExtendedType[categoryType]) {\r\n debug.assert(\r\n ExtendedType[categoryType] === (category + '_' + primitiveString),\r\n 'Unexpected name for ExtendedType member ' + categoryType);\r\n t = categoryType;\r\n }\r\n }\r\n else if (categoryPrimitiveType === primitiveType) {\r\n // Primitive type matches the single supported type for the category\r\n t = categoryType;\r\n }\r\n }\r\n }\r\n\r\n return t;\r\n }\r\n\r\n function matchesExtendedTypeWithAnyPrimitive(a: ExtendedType, b: ExtendedType): boolean {\r\n return (a & PrimitiveTypeFlagsExcludedMask) === (b & PrimitiveTypeFlagsExcludedMask);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n /**\r\n * Represents the versions of the data shape binding structure.\r\n * NOTE Keep this file in sync with the Sql\\InfoNav\\src\\Data\\Contracts\\DsqGeneration\\DataShapeBindingVersions.cs\r\n * file in the TFS Dev branch.\r\n */\r\n export const enum DataShapeBindingVersions {\r\n /** The initial version of data shape binding */\r\n Version0 = 0,\r\n /** Explicit subtotal support for axis groupings. */\r\n Version1 = 1,\r\n }\r\n\r\n export interface DataShapeBindingLimitTarget {\r\n Primary?: number;\r\n }\r\n\r\n export enum DataShapeBindingLimitType {\r\n Top = 0,\r\n First = 1,\r\n Last = 2,\r\n Sample = 3,\r\n Bottom = 4,\r\n }\r\n\r\n export interface DataShapeBindingLimit {\r\n Count?: number;\r\n Target: DataShapeBindingLimitTarget;\r\n Type: DataShapeBindingLimitType;\r\n }\r\n\r\n export interface DataShapeBinding {\r\n Version?: number;\r\n Primary: DataShapeBindingAxis;\r\n Secondary?: DataShapeBindingAxis;\r\n Aggregates?: DataShapeBindingAggregate[];\r\n Projections?: number[];\r\n Limits?: DataShapeBindingLimit[];\r\n Highlights?: FilterDefinition[];\r\n DataReduction?: DataShapeBindingDataReduction;\r\n IncludeEmptyGroups?: boolean;\r\n SuppressedJoinPredicates?: number[];\r\n }\r\n\r\n export interface DataShapeBindingDataReduction {\r\n Primary?: DataShapeBindingDataReductionAlgorithm;\r\n Secondary?: DataShapeBindingDataReductionAlgorithm;\r\n DataVolume?: number;\r\n }\r\n\r\n export interface DataShapeBindingDataReductionAlgorithm {\r\n Top?: DataShapeBindingDataReductionTopLimit;\r\n Sample?: DataShapeBindingDataReductionSampleLimit;\r\n Bottom?: DataShapeBindingDataReductionBottomLimit;\r\n Window?: DataShapeBindingDataReductionDataWindow;\r\n }\r\n\r\n export interface DataShapeBindingDataReductionTopLimit {\r\n Count?: number;\r\n }\r\n\r\n export interface DataShapeBindingDataReductionSampleLimit {\r\n Count?: number;\r\n }\r\n\r\n export interface DataShapeBindingDataReductionBottomLimit {\r\n Count?: number;\r\n }\r\n\r\n export interface DataShapeBindingDataReductionDataWindow {\r\n Count?: number;\r\n RestartTokens?: RestartToken;\r\n }\r\n\r\n export interface DataShapeBindingAxis {\r\n Groupings: DataShapeBindingAxisGrouping[];\r\n }\r\n\r\n export enum SubtotalType {\r\n None = 0,\r\n Before = 1,\r\n After = 2\r\n }\r\n\r\n export interface DataShapeBindingAxisGrouping {\r\n Projections: number[];\r\n GroupBy?: number[];\r\n SuppressedProjections?: number[];\r\n Subtotal?: SubtotalType;\r\n ShowItemsWithNoData?: number[];\r\n }\r\n\r\n export interface DataShapeBindingAggregate {\r\n Select: number;\r\n Kind: DataShapeBindingAggregateKind;\r\n }\r\n\r\n export const enum DataShapeBindingAggregateKind {\r\n None = 0,\r\n Min = 1,\r\n Max = 1 << 1,\r\n }\r\n} \r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export module DataShapeBindingDataReduction {\r\n\r\n export function createFrom(reduction: ReductionAlgorithm): DataShapeBindingDataReductionAlgorithm {\r\n if (!reduction)\r\n return;\r\n\r\n var result: DataShapeBindingDataReductionAlgorithm;\r\n if (reduction.top) {\r\n result = {\r\n Top: {}\r\n };\r\n\r\n if (reduction.top.count)\r\n result.Top.Count = reduction.top.count;\r\n }\r\n\r\n if (reduction.bottom) {\r\n result = {\r\n Bottom: {}\r\n };\r\n\r\n if (reduction.bottom.count)\r\n result.Bottom.Count = reduction.bottom.count;\r\n }\r\n\r\n if (reduction.sample) {\r\n result = {\r\n Sample: {}\r\n };\r\n\r\n if (reduction.sample.count)\r\n result.Sample.Count = reduction.sample.count;\r\n }\r\n\r\n if (reduction.window) {\r\n result = {\r\n Window: {}\r\n };\r\n\r\n if (reduction.window.count)\r\n result.Window.Count = reduction.window.count;\r\n }\r\n\r\n return result;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export interface FederatedConceptualSchemaInitOptions {\r\n schemas: { [name: string]: ConceptualSchema };\r\n links?: ConceptualSchemaLink[];\r\n }\r\n\r\n /** Represents a federated conceptual schema. */\r\n export class FederatedConceptualSchema {\r\n private schemas: { [name: string]: ConceptualSchema };\r\n private links: ConceptualSchemaLink[];\r\n\r\n constructor(options: FederatedConceptualSchemaInitOptions) {\r\n debug.assertValue(options, 'options');\r\n\r\n this.schemas = options.schemas; \r\n if (options.links)\r\n this.links = options.links;\r\n }\r\n\r\n public schema(name: string): ConceptualSchema {\r\n return this.schemas[name];\r\n }\r\n }\r\n\r\n /** Describes a semantic relationship between ConceptualSchemas. */\r\n export interface ConceptualSchemaLink {\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n export module Selector {\r\n export function filterFromSelector(selectors: Selector[], isNot?: boolean): SemanticFilter {\r\n if (_.isEmpty(selectors))\r\n return;\r\n\r\n let exprs: SQExpr[] = [];\r\n for (let i = 0, ilen = selectors.length; i < ilen; i++) {\r\n let identity = selectors[i];\r\n let data = identity.data;\r\n let exprToAdd: SQExpr = undefined;\r\n if (data && data.length) {\r\n for (let j = 0, jlen = data.length; j < jlen; j++) {\r\n exprToAdd = SQExprBuilder.and(exprToAdd, <SQExpr>(<DataViewScopeIdentity>identity.data[j]).expr);\r\n }\r\n }\r\n\r\n if (exprToAdd)\r\n exprs.push(exprToAdd);\r\n }\r\n\r\n if (!_.isEmpty(exprs))\r\n return DataViewScopeIdentity.filterFromExprs(exprs, isNot);\r\n }\r\n\r\n export function matchesData(selector: Selector, identities: DataViewScopeIdentity[]): boolean {\r\n debug.assertValue(selector, 'selector');\r\n debug.assertValue(selector.data, 'selector.data');\r\n debug.assertValue(identities, 'identities');\r\n\r\n let selectorData = selector.data;\r\n if (selectorData.length !== identities.length)\r\n return false;\r\n\r\n for (let i = 0, len = selectorData.length; i < len; i++) {\r\n let dataItem = selector.data[i];\r\n let selectorDataItem = <DataViewScopeIdentity>dataItem;\r\n if (selectorDataItem.expr) {\r\n if (!DataViewScopeIdentity.equals(selectorDataItem, identities[i]))\r\n return false;\r\n }\r\n else {\r\n if (!DataViewScopeWildcard.matches(<DataViewScopeWildcard>dataItem, identities[i]))\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n export function matchesKeys(selector: Selector, keysList: SQExpr[][]): boolean {\r\n debug.assertValue(selector, 'selector');\r\n debug.assertValue(selector.data, 'selector.data');\r\n debug.assertValue(keysList, 'keysList');\r\n\r\n let selectorData = selector.data,\r\n selectorDataLength = selectorData.length;\r\n if (selectorDataLength !== keysList.length)\r\n return false;\r\n\r\n for (let i = 0; i < selectorDataLength; i++) {\r\n let selectorDataItem = selector.data[i],\r\n selectorDataExprs: SQExpr[];\r\n\r\n if ((<DataViewScopeIdentity>selectorDataItem).expr) {\r\n selectorDataExprs = ScopeIdentityExtractor.getKeys(<SQExpr>(<DataViewScopeIdentity>selectorDataItem).expr);\r\n }\r\n else if ((<DataViewScopeWildcard>selectorDataItem).exprs) {\r\n selectorDataExprs = <SQExpr[]>(<DataViewScopeWildcard>selectorDataItem).exprs;\r\n } else { \r\n // In case DataViewRoleWildcard\r\n return false;\r\n }\r\n\r\n if (!selectorDataExprs)\r\n continue;\r\n if (!SQExprUtils.sequenceEqual(keysList[i], selectorDataExprs))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /** Determines whether two selectors are equal. */\r\n export function equals(x: Selector, y: Selector): boolean {\r\n // Normalize falsy to null\r\n x = x || null;\r\n y = y || null;\r\n\r\n if (x === y)\r\n return true;\r\n\r\n if (!x !== !y)\r\n return false;\r\n\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n\r\n if (x.id !== y.id)\r\n return false;\r\n if (x.metadata !== y.metadata)\r\n return false;\r\n if (!equalsDataArray(x.data, y.data))\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n function equalsDataArray(x: DataRepetitionSelector[], y: DataRepetitionSelector[]): boolean {\r\n // Normalize falsy to null\r\n x = x || null;\r\n y = y || null;\r\n\r\n if (x === y)\r\n return true;\r\n\r\n if (!x !== !y)\r\n return false;\r\n\r\n if (x.length !== y.length)\r\n return false;\r\n\r\n for (let i = 0, len = x.length; i < len; i++) {\r\n if (!equalsData(x[i], y[i]))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n function equalsData(x: DataRepetitionSelector, y: DataRepetitionSelector): boolean {\r\n let selector1 = <DataViewScopeIdentity & DataViewRoleWildcard & DataViewScopeWildcard>x;\r\n let selector2 = <DataViewScopeIdentity & DataViewRoleWildcard & DataViewScopeWildcard>y;\r\n if (selector1.expr && selector2.expr)\r\n return DataViewScopeIdentity.equals(selector1, selector2);\r\n\r\n if (selector1.exprs && selector2.exprs)\r\n return DataViewScopeWildcard.equals(selector1, selector2);\r\n\r\n if (selector1.roles && selector2.roles)\r\n return DataViewRoleWildcard.equals(selector1, selector2);\r\n\r\n return false;\r\n }\r\n\r\n export function getKey(selector: Selector): string {\r\n let toStringify: any = {};\r\n if (selector.data) {\r\n let data = [];\r\n for (let i = 0, ilen = selector.data.length; i < ilen; i++) {\r\n data.push(selector.data[i].key);\r\n }\r\n toStringify.data = data;\r\n }\r\n if (selector.metadata)\r\n toStringify.metadata = selector.metadata;\r\n if (selector.id)\r\n toStringify.id = selector.id;\r\n return JSON.stringify(toStringify);\r\n }\r\n\r\n export function containsWildcard(selector: Selector): boolean {\r\n debug.assertValue(selector, 'selector');\r\n\r\n let dataItems = selector.data;\r\n if (!dataItems)\r\n return false;\r\n\r\n for (let dataItem of dataItems) {\r\n let wildCard = <DataViewScopeWildcard & DataViewRoleWildcard>dataItem;\r\n if (wildCard.exprs || wildCard.roles)\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n export function hasRoleWildcard(selector: Selector): boolean {\r\n debug.assertValue(selector, 'selector');\r\n\r\n let dataItems = selector.data;\r\n if (_.isEmpty(dataItems))\r\n return false;\r\n\r\n for (let dataItem of dataItems) {\r\n if (isRoleWildcard(dataItem))\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n export function isRoleWildcard(dataItem: DataRepetitionSelector): dataItem is DataViewRoleWildcard {\r\n return !_.isEmpty((<DataViewRoleWildcard>dataItem).roles);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n export interface QueryDefinition {\r\n Version?: number;\r\n From: EntitySource[];\r\n Where?: QueryFilter[];\r\n OrderBy?: QuerySortClause[];\r\n Select: QueryExpressionContainer[];\r\n GroupBy?: QueryExpressionContainer[];\r\n }\r\n\r\n export interface FilterDefinition {\r\n Version?: number;\r\n From: EntitySource[];\r\n Where: QueryFilter[];\r\n } \r\n\r\n export enum EntitySourceType {\r\n Table = 0,\r\n Pod = 1,\r\n }\r\n\r\n export interface EntitySource {\r\n Name: string;\r\n EntitySet?: string; // TODO: Remove this when Q&A Silverlight is removed and make Entity required\r\n Entity?: string;\r\n Schema?: string;\r\n Type?: EntitySourceType;\r\n }\r\n\r\n export interface QueryFilter {\r\n Target?: QueryExpressionContainer[];\r\n Condition: QueryExpressionContainer;\r\n }\r\n\r\n export interface QuerySortClause {\r\n Expression: QueryExpressionContainer;\r\n Direction: SortDirection;\r\n }\r\n\r\n export interface QueryExpressionContainer {\r\n Name?: string;\r\n\r\n SourceRef?: QuerySourceRefExpression;\r\n Column?: QueryColumnExpression;\r\n Measure?: QueryMeasureExpression;\r\n Aggregation?: QueryAggregationExpression;\r\n Percentile?: QueryPercentileExpression;\r\n Hierarchy?: QueryHierarchyExpression;\r\n HierarchyLevel?: QueryHierarchyLevelExpression;\r\n PropertyVariationSource?: QueryPropertyVariationSourceExpression;\r\n\r\n // Logical\r\n And?: QueryBinaryExpression;\r\n Between?: QueryBetweenExpression;\r\n In?: QueryInExpression;\r\n Or?: QueryBinaryExpression;\r\n Comparison?: QueryComparisonExpression;\r\n Not?: QueryNotExpression;\r\n Contains?: QueryContainsExpression;\r\n StartsWith?: QueryStartsWithExpression;\r\n Exists?: QueryExistsExpression;\r\n\r\n // Constants\r\n Boolean?: QueryBooleanExpression;\r\n DateTime?: QueryDateTimeExpression;\r\n DateTimeSecond?: QueryDateTimeSecondExpression;\r\n Date?: QueryDateTimeExpression;\r\n Decimal?: QueryDecimalExpression;\r\n Integer?: QueryIntegerExpression;\r\n Null?: QueryNullExpression;\r\n Number?: QueryNumberExpression;\r\n String?: QueryStringExpression;\r\n Literal?: QueryLiteralExpression;\r\n\r\n DateSpan?: QueryDateSpanExpression;\r\n DateAdd?: QueryDateAddExpression;\r\n Now?: QueryNowExpression;\r\n\r\n // Default Values\r\n DefaultValue?: QueryDefaultValueExpression;\r\n AnyValue?: QueryAnyValueExpression;\r\n\r\n Arithmetic?: QueryArithmeticExpression;\r\n\r\n // Evaluation Expressions\r\n ScopedEval?: QueryScopedEvalExpression;\r\n\r\n // Client-only expressions\r\n FillRule?: QueryFillRuleExpression;\r\n ResourcePackageItem?: QueryResourcePackageItem;\r\n SelectRef?: QuerySelectRefExpression;\r\n }\r\n\r\n export interface QueryPropertyExpression {\r\n Expression: QueryExpressionContainer;\r\n Property: string;\r\n }\r\n\r\n export interface QueryColumnExpression extends QueryPropertyExpression {\r\n }\r\n\r\n export interface QueryMeasureExpression extends QueryPropertyExpression {\r\n }\r\n\r\n export interface QuerySourceRefExpression {\r\n Source: string;\r\n }\r\n\r\n export interface QuerySelectRefExpression {\r\n ExpressionName: string;\r\n }\r\n\r\n export interface QueryAggregationExpression {\r\n Function: QueryAggregateFunction;\r\n Expression: QueryExpressionContainer;\r\n }\r\n\r\n export interface QueryPercentileExpression {\r\n Expression: QueryExpressionContainer;\r\n K: number;\r\n Exclusive?: boolean;\r\n }\r\n\r\n export interface QueryHierarchyExpression {\r\n Expression: QueryExpressionContainer;\r\n Hierarchy: string;\r\n }\r\n\r\n export interface QueryHierarchyLevelExpression {\r\n Expression: QueryExpressionContainer;\r\n Level: string;\r\n }\r\n\r\n export interface QueryPropertyVariationSourceExpression {\r\n Expression: QueryExpressionContainer;\r\n Name: string;\r\n Property: string;\r\n }\r\n\r\n export interface QueryBinaryExpression {\r\n Left: QueryExpressionContainer;\r\n Right: QueryExpressionContainer;\r\n }\r\n\r\n export interface QueryBetweenExpression {\r\n Expression: QueryExpressionContainer;\r\n LowerBound: QueryExpressionContainer;\r\n UpperBound: QueryExpressionContainer;\r\n }\r\n\r\n export interface QueryInExpression {\r\n Expressions: QueryExpressionContainer[];\r\n Values: QueryExpressionContainer[][];\r\n }\r\n\r\n export interface QueryComparisonExpression extends QueryBinaryExpression {\r\n ComparisonKind: QueryComparisonKind;\r\n }\r\n\r\n export interface QueryContainsExpression extends QueryBinaryExpression { }\r\n\r\n export interface QueryNotExpression {\r\n Expression: QueryExpressionContainer;\r\n }\r\n\r\n export interface QueryStartsWithExpression extends QueryBinaryExpression { }\r\n\r\n export interface QueryExistsExpression {\r\n Expression: QueryExpressionContainer;\r\n }\r\n\r\n export interface QueryConstantExpression<T> {\r\n Value: T;\r\n }\r\n\r\n export interface QueryLiteralExpression {\r\n Value: string;\r\n }\r\n\r\n export interface QueryBooleanExpression extends QueryConstantExpression<boolean> { }\r\n export interface QueryDateTimeExpression extends QueryConstantExpression<string> { }\r\n export interface QueryDateTimeSecondExpression extends QueryConstantExpression<string> { }\r\n export interface QueryDecimalExpression extends QueryConstantExpression<number> { }\r\n export interface QueryIntegerExpression extends QueryConstantExpression<number> { }\r\n export interface QueryNumberExpression extends QueryConstantExpression<string> { }\r\n export interface QueryNullExpression { }\r\n export interface QueryStringExpression extends QueryConstantExpression<string> { }\r\n\r\n export interface QueryDateSpanExpression {\r\n TimeUnit: TimeUnit;\r\n Expression: QueryExpressionContainer;\r\n }\r\n\r\n export interface QueryDateAddExpression {\r\n Amount: number;\r\n TimeUnit: TimeUnit;\r\n Expression: QueryExpressionContainer;\r\n }\r\n\r\n export interface QueryNowExpression { }\r\n\r\n export interface QueryDefaultValueExpression { }\r\n\r\n export interface QueryAnyValueExpression { }\r\n\r\n export interface QueryArithmeticExpression {\r\n Left: QueryExpressionContainer;\r\n Right: QueryExpressionContainer;\r\n Operator: ArithmeticOperatorKind;\r\n }\r\n\r\n export const enum ArithmeticOperatorKind {\r\n Add = 0,\r\n Subtract = 1,\r\n Multiply = 2,\r\n Divide = 3,\r\n }\r\n\r\n export function getArithmeticOperatorName(arithmeticOperatorKind: ArithmeticOperatorKind): string {\r\n switch (arithmeticOperatorKind) {\r\n case ArithmeticOperatorKind.Add:\r\n return \"Add\";\r\n case ArithmeticOperatorKind.Subtract:\r\n return \"Subtract\";\r\n case ArithmeticOperatorKind.Multiply:\r\n return \"Multiply\";\r\n case ArithmeticOperatorKind.Divide:\r\n return \"Divide\";\r\n }\r\n throw new Error('Unexpected ArithmeticOperatorKind: ' + arithmeticOperatorKind);\r\n }\r\n\r\n export interface QueryFillRuleExpression {\r\n Input: QueryExpressionContainer;\r\n FillRule: FillRuleGeneric<QueryExpressionContainer, QueryExpressionContainer>;\r\n }\r\n\r\n export interface QueryResourcePackageItem {\r\n PackageName: string;\r\n PackageType: number;\r\n ItemName: string;\r\n }\r\n\r\n export interface QueryScopedEvalExpression {\r\n Expression: QueryExpressionContainer;\r\n Scope: QueryExpressionContainer[];\r\n }\r\n\r\n export enum TimeUnit {\r\n Day = 0,\r\n Week = 1,\r\n Month = 2,\r\n Year = 3,\r\n Decade = 4,\r\n Second = 5,\r\n Minute = 6,\r\n Hour = 7,\r\n }\r\n\r\n export enum QueryAggregateFunction {\r\n Sum = 0,\r\n Avg = 1,\r\n Count = 2,\r\n Min = 3,\r\n Max = 4,\r\n CountNonNull = 5,\r\n Median = 6,\r\n StandardDeviation = 7,\r\n Variance = 8,\r\n }\r\n\r\n export enum QueryComparisonKind {\r\n Equal = 0,\r\n GreaterThan = 1,\r\n GreaterThanOrEqual = 2,\r\n LessThan = 3,\r\n LessThanOrEqual = 4,\r\n }\r\n\r\n /** Defines semantic data types. */\r\n export enum SemanticType {\r\n None = 0x0,\r\n Number = 0x1,\r\n Integer = Number + 0x2,\r\n DateTime = 0x4,\r\n Time = 0x08,\r\n Date = DateTime + 0x10,\r\n Month = Integer + 0x20,\r\n Year = Integer + 0x40,\r\n YearAndMonth = 0x80,\r\n MonthAndDay = 0x100,\r\n Decade = Integer + 0x200,\r\n YearAndWeek = 0x400,\r\n String = 0x800,\r\n Boolean = 0x1000,\r\n Table = 0x2000,\r\n Range = 0x4000,\r\n }\r\n\r\n export interface QueryMetadata {\r\n Select?: SelectMetadata[];\r\n Filters?: FilterMetadata[];\r\n }\r\n\r\n // TODO: Stop using SemanticType and ConceptualDataCategory here (may need server contract changes)\r\n export interface SelectMetadata {\r\n Restatement: string;\r\n \r\n /* SemanticType or PrimitiveType. */\r\n Type?: number; \r\n\r\n Format?: string;\r\n DataCategory?: ConceptualDataCategory;\r\n\r\n /** The select projection name. */\r\n Name?: string;\r\n\r\n /* If defined, this indicates the KPI class*/\r\n kpiStatusGraphic?: string; // old version of kpi data\r\n\r\n /* If defined, this indicates the KPI metadata*/\r\n kpi?: DataViewKpiColumnMetadata;\r\n }\r\n\r\n export interface FilterMetadata {\r\n Restatement: string;\r\n Kind?: FilterKind;\r\n /** The expression being filtered. This is reflected in the filter card UI. */\r\n expression?: QueryExpressionContainer;\r\n }\r\n\r\n export enum FilterKind {\r\n Default,\r\n Period,\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n /** Represents a projection from a query result. */\r\n export interface QueryProjection {\r\n /** Name of item in the semantic query Select clause. */\r\n queryRef: string;\r\n\r\n /** Optional format string. */\r\n format?: string; // TODO: Deprecate this, and populate format string through objects instead.\r\n }\r\n\r\n /** A set of QueryProjections, grouped by visualization property, and ordered within that property. */\r\n export interface QueryProjectionsByRole {\r\n [roleName: string]: QueryProjectionCollection;\r\n }\r\n\r\n export class QueryProjectionCollection {\r\n private items: QueryProjection[];\r\n\r\n /* The activeProjectionReference is an array that contains all the items that we are grouping on in case of a drillable\r\n role. For example, if you have a drill role with [Country, State, City] and the user drilled to state, the active items\r\n will include [Country and State]. This means that the query will group on both country and state and the state \"last item\"\r\n is the item that the user drilled to.\r\n */\r\n private _activeProjectionRefs: string[];\r\n private _showAll: boolean;\r\n\r\n public constructor(items: QueryProjection[], activeProjectionRefs?: string[], showAll?: boolean) {\r\n debug.assertValue(items, 'items');\r\n\r\n this.items = items;\r\n this._activeProjectionRefs = activeProjectionRefs;\r\n this._showAll = showAll;\r\n }\r\n\r\n /** Returns all projections in a mutable array. */\r\n public all(): QueryProjection[] {\r\n return this.items;\r\n }\r\n\r\n public get activeProjectionRefs(): string[] {\r\n return this._activeProjectionRefs;\r\n }\r\n\r\n public set activeProjectionRefs(queryReferences: string[]) {\r\n if (!_.isEmpty(queryReferences)) {\r\n let queryRefs = this.items.map(val => val.queryRef);\r\n\r\n for (let queryReference of queryReferences) {\r\n if (!_.contains(queryRefs, queryReference))\r\n return;\r\n }\r\n\r\n this._activeProjectionRefs = queryReferences;\r\n }\r\n }\r\n\r\n public get showAll(): boolean {\r\n return this._showAll;\r\n }\r\n\r\n public set showAll(value: boolean) {\r\n this._showAll = value;\r\n }\r\n\r\n public addActiveQueryReference(queryRef: string): void {\r\n if (!this._activeProjectionRefs)\r\n this._activeProjectionRefs = [queryRef];\r\n else\r\n this._activeProjectionRefs.push(queryRef);\r\n }\r\n\r\n public getLastActiveQueryReference(): string {\r\n if (!_.isEmpty(this._activeProjectionRefs)) {\r\n return this._activeProjectionRefs[this._activeProjectionRefs.length - 1];\r\n }\r\n }\r\n\r\n /** Replaces the given oldQueryRef with newQueryRef in this QueryProjectionCollection. */\r\n public replaceQueryRef(oldQueryRef: string, newQueryRef: string): void {\r\n debug.assertValue(oldQueryRef, 'oldQueryRef');\r\n debug.assertValue(newQueryRef, 'newQueryRef');\r\n debug.assert(oldQueryRef !== newQueryRef, 'oldQueryRef !== newQueryRef');\r\n debug.assert(_.isEmpty(this._activeProjectionRefs), 'replaceQueryRef(...) is not supported on the QueryProjectionCollection of a drillable role');\r\n\r\n // Note: the same queryRef can get projected multiple times\r\n for (let item of this.items) {\r\n if (item.queryRef === oldQueryRef) {\r\n item.queryRef = newQueryRef;\r\n }\r\n }\r\n }\r\n\r\n public clone(): QueryProjectionCollection {\r\n return new QueryProjectionCollection(_.cloneDeep(this.items), _.clone(this._activeProjectionRefs), this._showAll);\r\n }\r\n }\r\n\r\n export module QueryProjectionsByRole {\r\n /** Clones the QueryProjectionsByRole. */\r\n export function clone(roles: QueryProjectionsByRole): QueryProjectionsByRole {\r\n if (!roles)\r\n return roles;\r\n\r\n let clonedRoles: QueryProjectionsByRole = {};\r\n\r\n for (let roleName in roles)\r\n clonedRoles[roleName] = roles[roleName].clone();\r\n\r\n return clonedRoles;\r\n }\r\n\r\n /** Returns the QueryProjectionCollection for that role. Even returns empty collections so that 'drillable' and 'activeProjection' fields are preserved. */\r\n export function getRole(roles: QueryProjectionsByRole, name: string): QueryProjectionCollection {\r\n debug.assertAnyValue(roles, 'roles');\r\n debug.assertValue(name, 'name');\r\n\r\n if (!roles)\r\n return;\r\n\r\n return roles[name];\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n export interface VisualElement {\r\n DataRoles?: DataRole[];\r\n Settings?: VisualElementSettings;\r\n }\r\n\r\n /** Defines common settings for a visual element. */\r\n export interface VisualElementSettings {\r\n DisplayUnitSystemType?: DisplayUnitSystemType;\r\n }\r\n\r\n export interface DataRole {\r\n Name: string;\r\n Projection: number;\r\n isActive?: boolean;\r\n }\r\n\r\n /** The system used to determine display units used during formatting */\r\n export enum DisplayUnitSystemType {\r\n /** Default display unit system, which saves space by using units such as K, M, bn with PowerView rules for when to pick a unit. Suitable for chart axes. */\r\n Default,\r\n\r\n /** A verbose display unit system that will only respect the formatting defined in the model. Suitable for explore mode single-value cards. */\r\n Verbose,\r\n\r\n /**\r\n * A display unit system that uses units such as K, M, bn if we have at least one of those units (e.g. 0.9M is not valid as it's less than 1 million).\r\n * Suitable for dashboard tile cards\r\n */\r\n WholeUnits,\r\n\r\n /**A display unit system that also contains Auto and None units for data labels*/\r\n DataLabels,\r\n }\r\n}\r\n\r\nmodule powerbi.data.contracts {\r\n\r\n export interface DataViewSource {\r\n data: any;\r\n type?: string;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n /** Repreasents the sequence of the dates/times */\r\n export class DateTimeSequence {\r\n // Constants\r\n private static MIN_COUNT: number = 1;\r\n private static MAX_COUNT: number = 1000; \r\n\r\n // Fields\r\n public min: Date;\r\n public max: Date;\r\n public unit: DateTimeUnit;\r\n public sequence: Date[];\r\n public interval: number;\r\n public intervalOffset: number;\r\n\r\n // Constructors\r\n /** Creates new instance of the DateTimeSequence */\r\n constructor(unit: DateTimeUnit) { \r\n this.unit = unit;\r\n this.sequence = [];\r\n this.min = new Date(\"9999-12-31T23:59:59.999\");\r\n this.max = new Date(\"0001-01-01T00:00:00.000\");\r\n }\r\n\r\n // Methods\r\n /** \r\n * Add a new Date to a sequence.\r\n * @param date - date to add\r\n */\r\n public add(date: Date) { \r\n if (date < this.min) { \r\n this.min = date;\r\n }\r\n if (date > this.max) { \r\n this.max = date;\r\n }\r\n this.sequence.push(date);\r\n }\r\n\r\n // Methods\r\n /** \r\n * Extends the sequence to cover new date range\r\n * @param min - new min to be covered by sequence\r\n * @param max - new max to be covered by sequence\r\n */\r\n public extendToCover(min: Date, max: Date): void {\r\n let x: Date = this.min;\r\n while (min < x) {\r\n x = DateTimeSequence.addInterval(x, -this.interval, this.unit);\r\n this.sequence.splice(0, 0, x);\r\n }\r\n this.min = x;\r\n\r\n x = this.max;\r\n while (x < max) {\r\n x = DateTimeSequence.addInterval(x, this.interval, this.unit);\r\n this.sequence.push(x);\r\n }\r\n this.max = x;\r\n }\r\n\r\n /** \r\n * Move the sequence to cover new date range\r\n * @param min - new min to be covered by sequence\r\n * @param max - new max to be covered by sequence\r\n */\r\n public moveToCover(min: Date, max: Date): void { \r\n let delta: number = DateTimeSequence.getDelta(min, max, this.unit);\r\n let count = Math.floor(delta / this.interval);\r\n this.min = DateTimeSequence.addInterval(this.min, count * this.interval, this.unit);\r\n\r\n this.sequence = []; \r\n this.sequence.push(this.min);\r\n this.max = this.min;\r\n while (this.max < max) {\r\n this.max = DateTimeSequence.addInterval(this.max, this.interval, this.unit);\r\n this.sequence.push(this.max);\r\n }\r\n }\r\n\r\n // Static\r\n /**\r\n * Calculate a new DateTimeSequence\r\n * @param dataMin - Date representing min of the data range\r\n * @param dataMax - Date representing max of the data range\r\n * @param expectedCount - expected number of intervals in the sequence\r\n * @param unit - of the intervals in the sequence\r\n */\r\n public static calculate(dataMin: Date, dataMax: Date, expectedCount: number, unit?: DateTimeUnit): DateTimeSequence {\r\n if (!unit) { \r\n unit = DateTimeSequence.getIntervalUnit(dataMin, dataMax, expectedCount);\r\n }\r\n switch (unit) {\r\n case DateTimeUnit.Year:\r\n return DateTimeSequence.calculateYears(dataMin, dataMax, expectedCount);\r\n case DateTimeUnit.Month:\r\n return DateTimeSequence.calculateMonths(dataMin, dataMax, expectedCount);\r\n case DateTimeUnit.Week:\r\n return DateTimeSequence.calculateWeeks(dataMin, dataMax, expectedCount);\r\n case DateTimeUnit.Day:\r\n return DateTimeSequence.calculateDays(dataMin, dataMax, expectedCount);\r\n case DateTimeUnit.Hour:\r\n return DateTimeSequence.calculateHours(dataMin, dataMax, expectedCount);\r\n case DateTimeUnit.Minute:\r\n return DateTimeSequence.calculateMinutes(dataMin, dataMax, expectedCount);\r\n case DateTimeUnit.Second:\r\n return DateTimeSequence.calculateSeconds(dataMin, dataMax, expectedCount);\r\n case DateTimeUnit.Millisecond:\r\n return DateTimeSequence.calculateMilliseconds(dataMin, dataMax, expectedCount);\r\n default:\r\n debug.assertFail(\"Unsupported DateTimeUnit\");\r\n }\r\n }\r\n\r\n public static calculateYears(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(!expectedCount || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"Expected count is out of range\");\r\n\r\n // Calculate range and sequence\r\n let yearsRange = NumericSequenceRange.calculateDataRange(dataMin.getFullYear(), dataMax.getFullYear(), false);\r\n\r\n // Calculate year sequence\r\n let sequence = NumericSequence.calculate(NumericSequenceRange.calculate(0, yearsRange.max - yearsRange.min), expectedCount, 0, null, null, [1, 2, 5]);\r\n let newMinYear = Math.floor(yearsRange.min / sequence.interval) * sequence.interval; \r\n let date = new Date(newMinYear, 0, 1);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Year);\r\n return result;\r\n }\r\n\r\n public static calculateMonths(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\r\n\r\n // Calculate range\r\n let minYear = dataMin.getFullYear();\r\n let maxYear = dataMax.getFullYear();\r\n let minMonth = dataMin.getMonth();\r\n let maxMonth = (maxYear - minYear) * 12 + dataMax.getMonth();\r\n let date = new Date(minYear, 0, 1);\r\n \r\n // Calculate month sequence\r\n let sequence = NumericSequence.calculateUnits(minMonth, maxMonth, expectedCount, [1, 2, 3, 6, 12]);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Month);\r\n return result;\r\n }\r\n\r\n public static calculateWeeks(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\r\n\r\n let firstDayOfWeek = 0;\r\n let minDayOfWeek = dataMin.getDay();\r\n let dayOffset = (minDayOfWeek - firstDayOfWeek + 7) % 7;\r\n let minDay = dataMin.getDate() - dayOffset;\r\n\r\n // Calculate range\r\n let date = new Date(dataMin.getFullYear(), dataMin.getMonth(), minDay);\r\n let min = 0;\r\n let max = Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, DateTimeUnit.Week));\r\n\r\n // Calculate week sequence\r\n let sequence = NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 4, 8]);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Week);\r\n return result;\r\n }\r\n\r\n public static calculateDays(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\r\n\r\n // Calculate range\r\n let date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate());\r\n let min = 0;\r\n let max = Double.ceilWithPrecision(DateTimeSequence.getDelta(dataMin, dataMax, DateTimeUnit.Day));\r\n \r\n // Calculate day sequence\r\n let sequence = NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 7, 14]);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Day);\r\n return result;\r\n }\r\n\r\n public static calculateHours(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\r\n\r\n // Calculate range\r\n let date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate());\r\n let min = Double.floorWithPrecision(DateTimeSequence.getDelta(date, dataMin, DateTimeUnit.Hour));\r\n let max = Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, DateTimeUnit.Hour));\r\n \r\n // Calculate hour sequence\r\n let sequence = NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 3, 6, 12, 24]);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Hour);\r\n return result;\r\n }\r\n\r\n public static calculateMinutes(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\r\n\r\n // Calculate range\r\n let date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate(), dataMin.getHours());\r\n let min = Double.floorWithPrecision(DateTimeSequence.getDelta(date, dataMin, DateTimeUnit.Minute));\r\n let max = Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, DateTimeUnit.Minute));\r\n\r\n // Calculate minutes numeric sequence\r\n let sequence = NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 5, 10, 15, 30, 60, 60 * 2, 60 * 3, 60 * 6, 60 * 12, 60 * 24]);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Minute);\r\n return result;\r\n }\r\n\r\n public static calculateSeconds(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\r\n\r\n // Calculate range\r\n let date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate(), dataMin.getHours(), dataMin.getMinutes());\r\n let min = Double.floorWithPrecision(DateTimeSequence.getDelta(date, dataMin, DateTimeUnit.Second));\r\n let max = Double.ceilWithPrecision(DateTimeSequence.getDelta(date, dataMax, DateTimeUnit.Second));\r\n\r\n // Calculate minutes numeric sequence\r\n let sequence = NumericSequence.calculateUnits(min, max, expectedCount, [1, 2, 5, 10, 15, 30, 60, 60 * 2, 60 * 5, 60 * 10, 60 * 15, 60 * 30, 60 * 60]);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Second);\r\n return result;\r\n }\r\n\r\n public static calculateMilliseconds(dataMin: Date, dataMax: Date, expectedCount: number): DateTimeSequence {\r\n debug.assertValue(dataMin, \"dataMin\");\r\n debug.assertValue(dataMax, \"dataMax\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= DateTimeSequence.MIN_COUNT && expectedCount <= DateTimeSequence.MAX_COUNT), \"expected count is out of range\");\r\n\r\n // Calculate range\r\n let date = new Date(dataMin.getFullYear(), dataMin.getMonth(), dataMin.getDate(), dataMin.getHours(), dataMin.getMinutes(), dataMin.getSeconds());\r\n let min = DateTimeSequence.getDelta(date, dataMin, DateTimeUnit.Millisecond);\r\n let max = DateTimeSequence.getDelta(date, dataMax, DateTimeUnit.Millisecond);\r\n \r\n // Calculate milliseconds numeric sequence\r\n let sequence = NumericSequence.calculate(NumericSequenceRange.calculate(min, max), expectedCount, 0);\r\n\r\n // Convert to date sequence\r\n let result = DateTimeSequence.fromNumericSequence(date, sequence, DateTimeUnit.Millisecond);\r\n return result;\r\n }\r\n\r\n public static addInterval(value: Date, interval: number, unit: DateTimeUnit): Date {\r\n interval = Math.round(interval);\r\n switch (unit) {\r\n case DateTimeUnit.Year:\r\n return DateUtils.addYears(value, interval);\r\n case DateTimeUnit.Month:\r\n return DateUtils.addMonths(value, interval);\r\n case DateTimeUnit.Week:\r\n return DateUtils.addWeeks(value, interval);\r\n case DateTimeUnit.Day:\r\n return DateUtils.addDays(value, interval);\r\n case DateTimeUnit.Hour:\r\n return DateUtils.addHours(value, interval);\r\n case DateTimeUnit.Minute:\r\n return DateUtils.addMinutes(value, interval);\r\n case DateTimeUnit.Second:\r\n return DateUtils.addSeconds(value, interval);\r\n case DateTimeUnit.Millisecond:\r\n return DateUtils.addMilliseconds(value, interval);\r\n }\r\n }\r\n\r\n private static fromNumericSequence(date: Date, sequence: NumericSequence, unit: DateTimeUnit) { \r\n let result = new DateTimeSequence(unit);\r\n for (let i = 0; i < sequence.sequence.length; i++) { \r\n let x: number = sequence.sequence[i];\r\n let d: Date = DateTimeSequence.addInterval(date, x, unit);\r\n result.add(d);\r\n }\r\n result.interval = sequence.interval;\r\n result.intervalOffset = sequence.intervalOffset;\r\n return result;\r\n }\r\n\r\n private static getDelta(min: Date, max: Date, unit: DateTimeUnit): number {\r\n let delta: number = 0;\r\n switch (unit) {\r\n case DateTimeUnit.Year:\r\n delta = max.getFullYear() - min.getFullYear();\r\n break;\r\n case DateTimeUnit.Month:\r\n delta = (max.getFullYear() - min.getFullYear()) * 12 + max.getMonth() - min.getMonth();\r\n break;\r\n case DateTimeUnit.Week:\r\n delta = (max.getTime() - min.getTime()) / (7 * 24 * 3600000);\r\n break;\r\n case DateTimeUnit.Day:\r\n delta = (max.getTime() - min.getTime()) / (24 * 3600000);\r\n break;\r\n case DateTimeUnit.Hour:\r\n delta = (max.getTime() - min.getTime()) / 3600000;\r\n break;\r\n case DateTimeUnit.Minute:\r\n delta = (max.getTime() - min.getTime()) / 60000;\r\n break;\r\n case DateTimeUnit.Second:\r\n delta = (max.getTime() - min.getTime()) / 1000;\r\n break;\r\n case DateTimeUnit.Millisecond:\r\n delta = max.getTime() - min.getTime();\r\n break;\r\n }\r\n return delta;\r\n }\r\n\r\n public static getIntervalUnit(min:Date, max:Date, maxCount: number): DateTimeUnit {\r\n maxCount = Math.max(maxCount, 2);\r\n let totalDays = DateTimeSequence.getDelta(min, max, DateTimeUnit.Day);\r\n if (totalDays > 356 && totalDays >= 30 * 6 * maxCount)\r\n return DateTimeUnit.Year;\r\n if (totalDays > 60 && totalDays > 7 * maxCount)\r\n return DateTimeUnit.Month;\r\n if (totalDays > 14 && totalDays > 2 * maxCount)\r\n return DateTimeUnit.Week;\r\n let totalHours = DateTimeSequence.getDelta(min, max, DateTimeUnit.Hour);\r\n if (totalDays > 2 && totalHours > 12 * maxCount)\r\n return DateTimeUnit.Day;\r\n if (totalHours >= 24 && totalHours >= maxCount)\r\n return DateTimeUnit.Hour;\r\n let totalMinutes = DateTimeSequence.getDelta(min, max, DateTimeUnit.Minute);\r\n if (totalMinutes > 2 && totalMinutes >= maxCount)\r\n return DateTimeUnit.Minute;\r\n let totalSeconds = DateTimeSequence.getDelta(min, max, DateTimeUnit.Second);\r\n if (totalSeconds > 2 && totalSeconds >= 0.8 * maxCount)\r\n return DateTimeUnit.Second;\r\n let totalMilliseconds = DateTimeSequence.getDelta(min, max, DateTimeUnit.Millisecond);\r\n if (totalMilliseconds > 0)\r\n return DateTimeUnit.Millisecond;\r\n \r\n // If the size of the range is 0 we need to guess the unit based on the date's non-zero values starting with milliseconds\r\n let date = min;\r\n if (date.getMilliseconds() !== 0)\r\n return DateTimeUnit.Millisecond;\r\n if (date.getSeconds() !== 0)\r\n return DateTimeUnit.Second;\r\n if (date.getMinutes() !== 0)\r\n return DateTimeUnit.Minute;\r\n if (date.getHours() !== 0)\r\n return DateTimeUnit.Hour;\r\n if (date.getDate() !== 1)\r\n return DateTimeUnit.Day;\r\n if (date.getMonth() !== 0)\r\n return DateTimeUnit.Month;\r\n \r\n return DateTimeUnit.Year;\r\n }\r\n }\r\n\r\n /** DateUtils module provides DateTimeSequence with set of additional date manipulation routines */\r\n export module DateUtils { \r\n let MonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\r\n let MonthDaysLeap = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\r\n\r\n /**\r\n * Returns bool indicating weither the provided year is a leap year.\r\n * @param year - year value\r\n */\r\n function isLeap(year: number): boolean { \r\n return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);\r\n }\r\n\r\n /** \r\n * Returns number of days in the provided year/month.\r\n * @param year - year value\r\n * @param month - month value\r\n */\r\n function getMonthDays(year: number, month: number) { \r\n return isLeap(year) ? MonthDaysLeap[month] : MonthDays[month];\r\n }\r\n\r\n /**\r\n * Adds a specified number of years to the provided date.\r\n * @param date - date value\r\n * @param yearDelta - number of years to add\r\n */\r\n export function addYears(date: Date, yearDelta: number): Date { \r\n let year = date.getFullYear();\r\n let month = date.getMonth();\r\n let day = date.getDate();\r\n let isLeapDay = month === 2 && day === 29;\r\n\r\n let result = new Date(date.getTime());\r\n year = year + yearDelta;\r\n if (isLeapDay && !isLeap(year)) {\r\n day = 28;\r\n } \r\n result.setFullYear(year, month, day);\r\n return result;\r\n }\r\n\r\n /** \r\n * Adds a specified number of months to the provided date.\r\n * @param date - date value\r\n * @param monthDelta - number of months to add\r\n */\r\n export function addMonths(date: Date, monthDelta: number): Date { \r\n let year = date.getFullYear();\r\n let month = date.getMonth();\r\n let day = date.getDate();\r\n \r\n let result = new Date(date.getTime());\r\n year += (monthDelta - (monthDelta % 12)) / 12;\r\n month += monthDelta % 12;\r\n\r\n // VSTS 1325771: Certain column charts don't display any data\r\n // Wrap arround the month if is after december (value 11)\r\n if (month > 11) {\r\n month = month % 12;\r\n year++;\r\n }\r\n\r\n day = Math.min(day, getMonthDays(year, month));\r\n result.setFullYear(year, month, day);\r\n return result;\r\n }\r\n\r\n /** \r\n * Adds a specified number of weeks to the provided date.\r\n * @param date - date value\r\n * @param weeks - number of weeks to add\r\n */\r\n export function addWeeks(date: Date, weeks: number): Date { \r\n return addDays(date, weeks * 7);\r\n }\r\n\r\n /** \r\n * Adds a specified number of days to the provided date.\r\n * @param date - date value\r\n * @param days - number of days to add\r\n */\r\n export function addDays(date: Date, days: number): Date { \r\n let year = date.getFullYear();\r\n let month = date.getMonth();\r\n let day = date.getDate(); \r\n let result = new Date(date.getTime());\r\n result.setFullYear(year, month, day + days);\r\n return result;\r\n }\r\n\r\n /**\r\n * Adds a specified number of hours to the provided date.\r\n * @param date - date value\r\n * @param hours - number of hours to add\r\n */\r\n export function addHours(date: Date, hours: number): Date { \r\n return new Date(date.getTime() + hours * 3600000);\r\n }\r\n\r\n /**\r\n * Adds a specified number of minutes to the provided date.\r\n * @param date - date value\r\n * @param minutes - number of minutes to add\r\n */\r\n export function addMinutes(date: Date, minutes: number): Date { \r\n return new Date(date.getTime() + minutes * 60000);\r\n }\r\n\r\n /** \r\n * Adds a specified number of seconds to the provided date.\r\n * @param date - date value\r\n * @param seconds - number of seconds to add\r\n */\r\n export function addSeconds(date: Date, seconds: number): Date { \r\n return new Date(date.getTime() + seconds * 1000);\r\n }\r\n\r\n /** \r\n * Adds a specified number of milliseconds to the provided date.\r\n * @param date - date value\r\n * @param milliseconds - number of milliseconds to add\r\n */\r\n export function addMilliseconds(date: Date, milliseconds: number): Date { \r\n return new Date(date.getTime() + milliseconds);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n // Constants\r\n const maxExponent = 24;\r\n const defaultScientificBigNumbersBoundary = 1E15;\r\n const scientificSmallNumbersBoundary = 1E-4;\r\n const PERCENTAGE_FORMAT = '%';\r\n const SCIENTIFIC_FORMAT = 'E+0';\r\n const DEFAULT_SCIENTIFIC_FORMAT = '0.##' + SCIENTIFIC_FORMAT;\r\n\r\n // Regular expressions\r\n /**\r\n * This regex looks for strings that match one of the following conditions:\r\n * - Optionally contain \"0\", \"#\", followed by a period, followed by at least one \"0\" or \"#\" (Ex. ###,000.###)\r\n * - Contains at least one of \"0\", \"#\", or \",\" (Ex. ###,000)\r\n * - Contain a \"g\" (indicates to use the general .NET numeric format string)\r\n * The entire string (start to end) must match, and the match is not case-sensitive.\r\n */\r\n const SUPPORTED_SCIENTIFIC_FORMATS = /^([0\\#,]*\\.[0\\#]+|[0\\#,]+|g)$/i;\r\n\r\n export class DisplayUnit {\r\n // Fields\r\n public value: number;\r\n public title: string;\r\n public labelFormat: string;\r\n public applicableRangeMin: number;\r\n public applicableRangeMax: number;\r\n\r\n // Methods\r\n public project(value: number): number {\r\n if (this.value) {\r\n return Double.removeDecimalNoise(value / this.value);\r\n } else {\r\n return value;\r\n }\r\n }\r\n\r\n public reverseProject(value: number): number {\r\n if (this.value) {\r\n return value * this.value;\r\n } else {\r\n return value;\r\n }\r\n }\r\n\r\n public isApplicableTo(value: number): boolean {\r\n value = Math.abs(value);\r\n let precision = Double.getPrecision(value, 3);\r\n return Double.greaterOrEqualWithPrecision(value, this.applicableRangeMin, precision) && Double.lessWithPrecision(value, this.applicableRangeMax, precision);\r\n }\r\n\r\n public isScaling(): boolean {\r\n return this.value > 1;\r\n }\r\n }\r\n\r\n export class DisplayUnitSystem {\r\n // Fields\r\n public units: DisplayUnit[];\r\n public displayUnit: DisplayUnit;\r\n private unitBaseValue: number;\r\n protected static UNSUPPORTED_FORMATS = /^(p\\d*)|(.*\\%)|(e\\d*)$/i;\r\n\r\n // Constructor\r\n constructor(units?: DisplayUnit[]) {\r\n this.units = units ? units : [];\r\n }\r\n\r\n // Properties\r\n public get title(): string {\r\n return this.displayUnit ? this.displayUnit.title : undefined;\r\n }\r\n\r\n // Methods\r\n public update(value: number): void {\r\n if (value === undefined)\r\n return;\r\n\r\n this.unitBaseValue = value;\r\n this.displayUnit = this.findApplicableDisplayUnit(value);\r\n }\r\n\r\n private findApplicableDisplayUnit(value: number): DisplayUnit {\r\n for (let unit of this.units) {\r\n if (unit.isApplicableTo(value))\r\n return unit;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n public format(value: number, format: string, decimals?: number, trailingZeros?: boolean): string {\r\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\r\n if (this.isFormatSupported(format)) {\r\n decimals = this.getNumberOfDecimalsForFormatting(format, decimals);\r\n\r\n if (this.hasScientitifcFormat(format)) {\r\n return this.formatHelper(value, '', format, decimals, trailingZeros);\r\n }\r\n if (this.isScalingUnit() && this.shouldRespectScalingUnit(format)) {\r\n return this.formatHelper(this.displayUnit.project(value), this.displayUnit.labelFormat, format, decimals, trailingZeros);\r\n }\r\n if (decimals != null) {\r\n return this.formatHelper(value, '', format, decimals, trailingZeros);\r\n }\r\n }\r\n \r\n return formattingService.formatValue(value, format);\r\n }\r\n\r\n public isFormatSupported(format: string): boolean {\r\n return !DisplayUnitSystem.UNSUPPORTED_FORMATS.test(format);\r\n }\r\n\r\n public isPercentageFormat(format: string): boolean {\r\n return format && format.indexOf(PERCENTAGE_FORMAT) >= 0;\r\n }\r\n\r\n public shouldRespectScalingUnit(format: string): boolean {\r\n return !this.isPercentageFormat(format);\r\n }\r\n\r\n public getNumberOfDecimalsForFormatting(format: string, decimals?: number) {\r\n return decimals;\r\n }\r\n\r\n public isScalingUnit(): boolean {\r\n return this.displayUnit && this.displayUnit.isScaling();\r\n }\r\n\r\n private formatHelper(value: number, nonScientificFormat: string, format: string, decimals?: number, trailingZeros?: boolean) {\r\n // If the format is \"general\" and we want to override the number of decimal places then use the default numeric format string.\r\n if ((format === 'g' || format === 'G') && decimals != null)\r\n format = visuals.valueFormatter.DefaultNumericFormat;\r\n\r\n format = NumberFormat.addDecimalsToFormat(format, decimals, trailingZeros);\r\n\r\n if (format && !formattingService.isStandardNumberFormat(format))\r\n return formattingService.formatNumberWithCustomOverride(value, format, nonScientificFormat);\r\n\r\n if (!format)\r\n format = 'G';\r\n if (!nonScientificFormat)\r\n nonScientificFormat = '{0}';\r\n\r\n let text = formattingService.formatValue(value, format);\r\n return formattingService.format(nonScientificFormat, [text]);\r\n }\r\n\r\n /** Formats a single value by choosing an appropriate base for the DisplayUnitSystem before formatting. */\r\n public formatSingleValue(value: number, format: string, decimals?: number, trailingZeros?: boolean): string {\r\n // Change unit base to a value appropriate for this value\r\n this.update(this.shouldUseValuePrecision(value) ? Double.getPrecision(value, 8) : value);\r\n\r\n return this.format(value, format, decimals, trailingZeros);\r\n }\r\n\r\n private shouldUseValuePrecision(value: number): boolean {\r\n if (this.units.length === 0)\r\n return true;\r\n\r\n // Check if the value is big enough to have a valid unit by checking against the smallest unit (that it's value bigger than 1).\r\n let applicableRangeMin: number = 0;\r\n for (let i = 0; i < this.units.length; i++) {\r\n if (this.units[i].isScaling()) {\r\n applicableRangeMin = this.units[i].applicableRangeMin;\r\n break;\r\n }\r\n }\r\n\r\n return Math.abs(value) < applicableRangeMin;\r\n }\r\n\r\n protected isScientific(value: number): boolean {\r\n return value < - defaultScientificBigNumbersBoundary || value > defaultScientificBigNumbersBoundary ||\r\n (-scientificSmallNumbersBoundary < value && value < scientificSmallNumbersBoundary && value !== 0);\r\n }\r\n\r\n protected hasScientitifcFormat(format: string): boolean {\r\n return format && format.toUpperCase().indexOf(\"E\") !== -1;\r\n }\r\n\r\n protected supportsScientificFormat(format: string): boolean {\r\n if (format)\r\n return SUPPORTED_SCIENTIFIC_FORMATS.test(format);\r\n\r\n return true;\r\n }\r\n\r\n protected shouldFallbackToScientific(value: number, format: string): boolean {\r\n return !this.hasScientitifcFormat(format)\r\n && this.supportsScientificFormat(format)\r\n && this.isScientific(value);\r\n }\r\n\r\n protected getScientificFormat(data: number, format: string, decimals: number, trailingZeros: boolean): string {\r\n // Use scientific format outside of the range\r\n if (this.isFormatSupported(format) && this.shouldFallbackToScientific(data, format)) {\r\n let numericFormat = NumberFormat.getNumericFormat(data, format);\r\n if (decimals)\r\n numericFormat = NumberFormat.addDecimalsToFormat(numericFormat ? numericFormat : '0', Math.abs(decimals), trailingZeros);\r\n\r\n if (numericFormat)\r\n return numericFormat + SCIENTIFIC_FORMAT;\r\n else\r\n return DEFAULT_SCIENTIFIC_FORMAT;\r\n }\r\n\r\n return format;\r\n }\r\n }\r\n\r\n /** Provides a unit system that is defined by formatting in the model, and is suitable for visualizations shown in single number visuals in explore mode. */\r\n export class NoDisplayUnitSystem extends DisplayUnitSystem {\r\n // Constructor\r\n constructor() {\r\n super([]);\r\n }\r\n }\r\n\r\n /** Provides a unit system that creates a more concise format for displaying values. This is suitable for most of the cases where\r\n we are showing values (chart axes) and as such it is the default unit system. */\r\n export class DefaultDisplayUnitSystem extends DisplayUnitSystem {\r\n private static units: DisplayUnit[];\r\n\r\n // Constructor\r\n constructor(unitLookup: (exponent: number) => DisplayUnitSystemNames) {\r\n super(DefaultDisplayUnitSystem.getUnits(unitLookup));\r\n }\r\n\r\n // Methods\r\n public format(data: number, format: string, decimals?: number, trailingZeros?: boolean): string {\r\n format = this.getScientificFormat(data, format, decimals, trailingZeros);\r\n\r\n return super.format(data, format, decimals, trailingZeros);\r\n }\r\n\r\n public static reset(): void {\r\n DefaultDisplayUnitSystem.units = null;\r\n }\r\n\r\n private static getUnits(unitLookup: (exponent: number) => DisplayUnitSystemNames): DisplayUnit[] {\r\n if (!DefaultDisplayUnitSystem.units) {\r\n DefaultDisplayUnitSystem.units = createDisplayUnits(unitLookup, (value: number, previousUnitValue: number, min: number) => {\r\n // When dealing with millions/billions/trillions we need to switch to millions earlier: for example instead of showing 100K 200K 300K we should show 0.1M 0.2M 0.3M etc\r\n if (value - previousUnitValue >= 1000) {\r\n return value / 10;\r\n }\r\n\r\n return min;\r\n });\r\n\r\n // Ensure last unit has max of infinity\r\n DefaultDisplayUnitSystem.units[DefaultDisplayUnitSystem.units.length - 1].applicableRangeMax = Infinity;\r\n }\r\n return DefaultDisplayUnitSystem.units;\r\n }\r\n }\r\n\r\n /** Provides a unit system that creates a more concise format for displaying values, but only allows showing a unit if we have at least\r\n one of those units (e.g. 0.9M is not allowed since it's less than 1 million). This is suitable for cases such as dashboard tiles\r\n where we have restricted space but do not want to show partial units. */\r\n export class WholeUnitsDisplayUnitSystem extends DisplayUnitSystem {\r\n private static units: DisplayUnit[];\r\n\r\n // Constructor\r\n constructor(unitLookup: (exponent: number) => DisplayUnitSystemNames) {\r\n super(WholeUnitsDisplayUnitSystem.getUnits(unitLookup));\r\n }\r\n\r\n public static reset(): void {\r\n WholeUnitsDisplayUnitSystem.units = null;\r\n }\r\n\r\n private static getUnits(unitLookup: (exponent: number) => DisplayUnitSystemNames): DisplayUnit[] {\r\n if (!WholeUnitsDisplayUnitSystem.units) {\r\n WholeUnitsDisplayUnitSystem.units = createDisplayUnits(unitLookup);\r\n\r\n // Ensure last unit has max of infinity\r\n WholeUnitsDisplayUnitSystem.units[WholeUnitsDisplayUnitSystem.units.length - 1].applicableRangeMax = Infinity;\r\n }\r\n\r\n return WholeUnitsDisplayUnitSystem.units;\r\n }\r\n\r\n public format(data: number, format: string, decimals?: number, trailingZeros?: boolean): string {\r\n format = this.getScientificFormat(data, format, decimals, trailingZeros);\r\n\r\n return super.format(data, format, decimals, trailingZeros);\r\n }\r\n }\r\n\r\n export class DataLabelsDisplayUnitSystem extends DisplayUnitSystem {\r\n\r\n // Constants\r\n private static AUTO_DISPLAYUNIT_VALUE = 0;\r\n private static NONE_DISPLAYUNIT_VALUE = 1;\r\n protected static UNSUPPORTED_FORMATS = /^(e\\d*)$/i;\r\n\r\n private static units: DisplayUnit[];\r\n\r\n constructor(unitLookup: (exponent: number) => DisplayUnitSystemNames) {\r\n super(DataLabelsDisplayUnitSystem.getUnits(unitLookup));\r\n }\r\n\r\n public isFormatSupported(format: string): boolean {\r\n return !DataLabelsDisplayUnitSystem.UNSUPPORTED_FORMATS.test(format);\r\n }\r\n\r\n private static getUnits(unitLookup: (exponent: number) => DisplayUnitSystemNames): DisplayUnit[] {\r\n if (!DataLabelsDisplayUnitSystem.units) {\r\n let units = [];\r\n let adjustMinBasedOnPreviousUnit = (value: number, previousUnitValue: number, min: number): number => {\r\n // Never returns true, we are always ignoring\r\n // We do not early switch (e.g. 100K instead of 0.1M)\r\n // Intended? If so, remove this function, otherwise, remove if statement\r\n if (value === -1)\r\n if (value - previousUnitValue >= 1000) {\r\n return value / 10;\r\n }\r\n return min;\r\n };\r\n\r\n // Add Auto & None\r\n let names = unitLookup(-1);\r\n addUnitIfNonEmpty(units, DataLabelsDisplayUnitSystem.AUTO_DISPLAYUNIT_VALUE, names.title, names.format, adjustMinBasedOnPreviousUnit);\r\n\r\n names = unitLookup(0);\r\n addUnitIfNonEmpty(units, DataLabelsDisplayUnitSystem.NONE_DISPLAYUNIT_VALUE, names.title, names.format, adjustMinBasedOnPreviousUnit);\r\n\r\n // Add normal units\r\n DataLabelsDisplayUnitSystem.units = units.concat(createDisplayUnits(unitLookup, adjustMinBasedOnPreviousUnit));\r\n\r\n // Ensure last unit has max of infinity\r\n DataLabelsDisplayUnitSystem.units[DataLabelsDisplayUnitSystem.units.length - 1].applicableRangeMax = Infinity;\r\n }\r\n return DataLabelsDisplayUnitSystem.units;\r\n }\r\n\r\n public format(data: number, format: string, decimals?: number, trailingZeros?: boolean): string {\r\n format = this.getScientificFormat(data, format, decimals, trailingZeros);\r\n\r\n return super.format(data, format, decimals, trailingZeros);\r\n }\r\n }\r\n\r\n export interface DisplayUnitSystemNames {\r\n title: string;\r\n format: string;\r\n }\r\n\r\n function createDisplayUnits(unitLookup: (exponent: number) => DisplayUnitSystemNames, adjustMinBasedOnPreviousUnit?: (value: number, previousUnitValue: number, min: number) => number) {\r\n let units = [];\r\n for (let i = 3; i < maxExponent; i++) {\r\n let names = unitLookup(i);\r\n if (names)\r\n addUnitIfNonEmpty(units, Double.pow10(i), names.title, names.format, adjustMinBasedOnPreviousUnit);\r\n }\r\n\r\n return units;\r\n }\r\n\r\n function addUnitIfNonEmpty(\r\n units: DisplayUnit[],\r\n value: number,\r\n title: string,\r\n labelFormat: string,\r\n adjustMinBasedOnPreviousUnit?: (value: number, previousUnitValue: number, min: number) => number): void {\r\n if (title || labelFormat) {\r\n let min = value;\r\n\r\n if (units.length > 0) {\r\n let previousUnit = units[units.length - 1];\r\n\r\n if (adjustMinBasedOnPreviousUnit)\r\n min = adjustMinBasedOnPreviousUnit(value, previousUnit.value, min);\r\n\r\n previousUnit.applicableRangeMax = min;\r\n }\r\n let unit = new DisplayUnit();\r\n unit.value = value;\r\n unit.applicableRangeMin = min;\r\n unit.applicableRangeMax = min * 1000;\r\n unit.title = title;\r\n unit.labelFormat = labelFormat;\r\n units.push(unit);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export class NumericSequence {\r\n private static MIN_COUNT: number = 1;\r\n private static MAX_COUNT: number = 1000;\r\n\r\n private maxAllowedMargin: number;\r\n private canExtendMin: boolean;\r\n private canExtendMax: boolean;\r\n\r\n public interval: number;\r\n public intervalOffset: number;\r\n public min: number;\r\n public max: number;\r\n public precision: number;\r\n public sequence: number[];\r\n\r\n public static calculate (range: NumericSequenceRange, expectedCount: number, maxAllowedMargin?: number, minPower?: number, useZeroRefPoint?: boolean, steps?: number[]): NumericSequence {\r\n debug.assertValue(range, \"range\");\r\n debug.assert(expectedCount === undefined || (expectedCount >= NumericSequence.MIN_COUNT && expectedCount <= NumericSequence.MAX_COUNT), \"expectedCount\");\r\n debug.assert(minPower === undefined|| (minPower >= Double.MIN_EXP && minPower <= Double.MAX_EXP), \"minPower\");\r\n debug.assert(maxAllowedMargin === undefined|| (maxAllowedMargin >= 0), \"maxAllowedMargin\");\r\n\r\n let result = new NumericSequence();\r\n\r\n if (expectedCount === undefined)\r\n expectedCount = 10;\r\n else\r\n expectedCount = Double.ensureInRange(expectedCount, NumericSequence.MIN_COUNT, NumericSequence.MAX_COUNT);\r\n if (minPower === undefined)\r\n minPower = Double.MIN_EXP;\r\n if (useZeroRefPoint === undefined)\r\n useZeroRefPoint = false;\r\n if (maxAllowedMargin === undefined)\r\n maxAllowedMargin = 1;\r\n if (steps === undefined)\r\n steps = [1, 2, 5];\r\n\r\n // Handle single stop case\r\n if (range.forcedSingleStop) {\r\n result.interval = range.getSize();\r\n result.intervalOffset = result.interval - (range.forcedSingleStop - range.min);\r\n result.min = range.min;\r\n result.max = range.max;\r\n result.sequence = [range.forcedSingleStop];\r\n return result;\r\n }\r\n\r\n let interval = 0;\r\n let min = 0;\r\n let max = 9;\r\n let canExtendMin = maxAllowedMargin > 0 && !range.hasFixedMin;\r\n let canExtendMax = maxAllowedMargin > 0 && !range.hasFixedMax;\r\n\r\n let size = range.getSize();\r\n let exp = Double.log10(size);\r\n\r\n // Account for Exp of steps\r\n let stepExp = Double.log10(steps[0]);\r\n exp = exp - stepExp;\r\n\r\n // Account for MaxCount\r\n let expectedCountExp = Double.log10(expectedCount);\r\n exp = exp - expectedCountExp;\r\n\r\n // Account for MinPower\r\n exp = Math.max(exp, minPower - stepExp + 1);\r\n let count = undefined;\r\n // Create array of \"good looking\" numbers\r\n if (interval !== 0) {\r\n // If explicit interval is defined - use it instead of the steps array.\r\n let power = Double.pow10(exp);\r\n let roundMin = Double.floorToPrecision(range.min, power);\r\n let roundMax = Double.ceilToPrecision(range.max, power);\r\n let roundRange = NumericSequenceRange.calculateFixedRange(roundMin, roundMax);\r\n\r\n roundRange.shrinkByStep(range, interval);\r\n min = roundRange.min;\r\n max = roundRange.max;\r\n count = Math.floor(roundRange.getSize() / interval);\r\n }\r\n else {\r\n // No interval defined -> find optimal interval\r\n let dexp;\r\n for (dexp = 0; dexp < 3; dexp++) {\r\n let e = exp + dexp;\r\n let power = Double.pow10(e);\r\n\r\n let roundMin = Double.floorToPrecision(range.min, power);\r\n let roundMax = Double.ceilToPrecision(range.max, power);\r\n\r\n // Go throught the steps array looking for the smallest step that produces the right interval count.\r\n let stepsCount = steps.length;\r\n let stepPower = Double.pow10(e - 1);\r\n for (let i = 0; i < stepsCount; i++) {\r\n let step = steps[i] * stepPower;\r\n let roundRange = NumericSequenceRange.calculateFixedRange(roundMin, roundMax, useZeroRefPoint);\r\n roundRange.shrinkByStep(range, step);\r\n\r\n // If the range is based on Data we might need to extend it to provide nice data margins.\r\n if (canExtendMin && range.min === roundRange.min && maxAllowedMargin >= 1)\r\n roundRange.min -= step;\r\n if (canExtendMax && range.max === roundRange.max && maxAllowedMargin >= 1)\r\n roundRange.max += step;\r\n\r\n // Count the intervals\r\n count = Double.ceilWithPrecision(roundRange.getSize() / step);\r\n\r\n if (count <= expectedCount || (dexp === 2 && i === stepsCount - 1) || (expectedCount === 1 && count === 2 && (step > range.getSize() || (range.min < 0 && range.max > 0 && step * 2 >= range.getSize())))) {\r\n interval = step;\r\n min = roundRange.min;\r\n max = roundRange.max;\r\n break;\r\n }\r\n }\r\n\r\n // Increase the scale power until the interval is found\r\n if (interval !== 0)\r\n break;\r\n }\r\n }\r\n\r\n // Avoid extreme count cases (>1000 ticks)\r\n if (count > expectedCount * 32 || count > NumericSequence.MAX_COUNT) {\r\n count = Math.min(expectedCount * 32, NumericSequence.MAX_COUNT);\r\n interval = (max - min) / count;\r\n }\r\n\r\n result.min = min;\r\n result.max = max;\r\n result.interval = interval;\r\n result.intervalOffset = min - range.min;\r\n result.maxAllowedMargin = maxAllowedMargin;\r\n result.canExtendMin = canExtendMin;\r\n result.canExtendMax = canExtendMax;\r\n\r\n // Fill in the Sequence\r\n let precision = Double.getPrecision(interval, 0);\r\n result.precision = precision;\r\n\r\n let sequence = [];\r\n\r\n let x = Double.roundToPrecision(min, precision);\r\n sequence.push(x);\r\n for (let i = 0; i < count; i++) {\r\n x = Double.roundToPrecision(x + interval, precision);\r\n sequence.push(x);\r\n }\r\n \r\n result.sequence = sequence;\r\n\r\n result.trimMinMax(range.min, range.max);\r\n\r\n return result;\r\n }\r\n\r\n /** \r\n * Calculates the sequence of int numbers which are mapped to the multiples of the units grid. \r\n * @min - The minimum of the range.\r\n * @max - The maximum of the range.\r\n * @maxCount - The max count of intervals.\r\n * @steps - array of intervals.\r\n */\r\n public static calculateUnits(min: number, max: number, maxCount: number, steps: number[]): NumericSequence {\r\n // Initialization actions\r\n maxCount = Double.ensureInRange(maxCount, NumericSequence.MIN_COUNT, NumericSequence.MAX_COUNT);\r\n if (min === max) {\r\n max = min + 1;\r\n }\r\n let stepCount = 0;\r\n let step = 0;\r\n\r\n // Calculate step\r\n for (let i = 0; i < steps.length; i++)\r\n {\r\n step = steps[i];\r\n let maxStepCount = Double.ceilWithPrecision(max / step);\r\n let minStepCount = Double.floorWithPrecision(min / step);\r\n stepCount = maxStepCount - minStepCount;\r\n \r\n if (stepCount <= maxCount) {\r\n break;\r\n }\r\n }\r\n\r\n // Calculate the offset\r\n let offset = -min;\r\n offset = offset % step;\r\n\r\n // Create sequence\r\n let result = new NumericSequence();\r\n result.sequence = [];\r\n for (let x = min + offset; ; x += step)\r\n {\r\n result.sequence.push(x);\r\n if (x >= max)\r\n break;\r\n }\r\n result.interval = step;\r\n result.intervalOffset = offset;\r\n result.min = result.sequence[0];\r\n result.max = result.sequence[result.sequence.length - 1];\r\n return result;\r\n }\r\n\r\n public trimMinMax(min: number, max: number): void { \r\n let minMargin = (min - this.min) / this.interval;\r\n let maxMargin = (this.max - max) / this.interval;\r\n let marginPrecision = 0.001;\r\n\r\n if (!this.canExtendMin || (minMargin > this.maxAllowedMargin && minMargin > marginPrecision)) {\r\n this.min = min;\r\n }\r\n\r\n if (!this.canExtendMax || (maxMargin > this.maxAllowedMargin && maxMargin > marginPrecision)) {\r\n this.max = max;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export class NumericSequenceRange {\r\n private static DEFAULT_MAX: number = 10;\r\n private static MIN_SUPPORTED_DOUBLE = -1E307;\r\n private static MAX_SUPPORTED_DOUBLE = 1E307;\r\n\r\n public min: number;\r\n public max: number;\r\n public includeZero: boolean;\r\n public forcedSingleStop: number;\r\n public hasDataRange: boolean;\r\n public hasFixedMin: boolean;\r\n public hasFixedMax: boolean;\r\n\r\n private _ensureIncludeZero(): void { \r\n if (this.includeZero) {\r\n // fixed min and max has higher priority than includeZero\r\n if (this.min > 0 && !this.hasFixedMin) {\r\n this.min = 0;\r\n }\r\n if (this.max < 0 && !this.hasFixedMax) {\r\n this.max = 0;\r\n }\r\n }\r\n }\r\n\r\n private _ensureNotEmpty(): void { \r\n if (this.min === this.max) {\r\n if (!this.min) {\r\n this.min = 0;\r\n this.max = NumericSequenceRange.DEFAULT_MAX;\r\n this.hasFixedMin = true;\r\n this.hasFixedMax = true;\r\n } else {\r\n // We are dealing with a single data value (includeZero is not set)\r\n // In order to fix the range we need to extend it in both directions by half of the interval.\r\n // Interval is calculated based on the number:\r\n // 1. Integers below 10,000 are extended by 0.5: so the [2006-2006] empty range is extended to [2005.5-2006.5] range and the ForsedSingleStop=2006\r\n // 2. Other numbers are extended by half of their power: [700,001-700,001] => [650,001-750,001] and the ForsedSingleStop=null as we want the intervals to be calculated to cover the range.\r\n let value = this.min;\r\n let exp = Double.log10(Math.abs(value));\r\n let step: number;\r\n if (exp >= 0 && exp < 4) {\r\n step = 0.5;\r\n this.forcedSingleStop = value;\r\n } else {\r\n step = Double.pow10(exp) / 2;\r\n this.forcedSingleStop = null;\r\n }\r\n this.min = value - step;\r\n this.max = value + step;\r\n }\r\n }\r\n }\r\n\r\n private _ensureDirection() { \r\n if (this.min > this.max) { \r\n let temp = this.min;\r\n this.min = this.max;\r\n this.max = temp;\r\n }\r\n }\r\n\r\n public getSize(): number {\r\n return this.max - this.min;\r\n }\r\n\r\n public shrinkByStep(range: NumericSequenceRange, step: number) {\r\n debug.assertValue(range, \"range\");\r\n debug.assert(step > 0, \"step\");\r\n\r\n let oldCount = this.min / step;\r\n let newCount = range.min / step;\r\n let deltaCount = Math.floor(newCount - oldCount);\r\n this.min += deltaCount * step;\r\n\r\n oldCount = this.max / step;\r\n newCount = range.max / step;\r\n deltaCount = Math.ceil(newCount - oldCount);\r\n this.max += deltaCount * step;\r\n }\r\n\r\n public static calculate(dataMin: number, dataMax: number, fixedMin?:number, fixedMax?:number, includeZero?: boolean): NumericSequenceRange { \r\n debug.assert(dataMin <= dataMax, \"dataMin should be less or equal to dataMax.\");\r\n debug.assert(!fixedMin || !fixedMax || fixedMin <= fixedMax, \"fixedMin should be less or equal to fixedMax.\");\r\n\r\n let result = new NumericSequenceRange(); \r\n result.includeZero = includeZero ? true : false;\r\n result.hasDataRange = ValueUtil.hasValue(dataMin) && ValueUtil.hasValue(dataMax);\r\n result.hasFixedMin = ValueUtil.hasValue(fixedMin);\r\n result.hasFixedMax = ValueUtil.hasValue(fixedMax);\r\n\r\n dataMin = Double.ensureInRange(dataMin, NumericSequenceRange.MIN_SUPPORTED_DOUBLE, NumericSequenceRange.MAX_SUPPORTED_DOUBLE);\r\n dataMax = Double.ensureInRange(dataMax, NumericSequenceRange.MIN_SUPPORTED_DOUBLE, NumericSequenceRange.MAX_SUPPORTED_DOUBLE);\r\n\r\n // Calculate the range using the min, max, dataRange\r\n if (result.hasFixedMin && result.hasFixedMax) {\r\n result.min = fixedMin;\r\n result.max = fixedMax;\r\n } else if (result.hasFixedMin) {\r\n result.min = fixedMin;\r\n result.max = dataMax > fixedMin ? dataMax : fixedMin;\r\n } else if (result.hasFixedMax) {\r\n result.min = dataMin < fixedMax ? dataMin : fixedMax;\r\n result.max = fixedMax;\r\n } else if (result.hasDataRange) {\r\n result.min = dataMin;\r\n result.max = dataMax;\r\n } else {\r\n result.min = 0;\r\n result.max = 0;\r\n }\r\n\r\n result._ensureIncludeZero();\r\n result._ensureNotEmpty();\r\n result._ensureDirection();\r\n \r\n if (result.min === 0) {\r\n result.hasFixedMin = true; // If the range starts from zero we should prevent extending the intervals into the negative range\r\n } else if (result.max === 0) {\r\n result.hasFixedMax = true; // If the range ends at zero we should prevent extending the intervals into the positive range\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public static calculateDataRange(dataMin: number, dataMax: number, includeZero?: boolean): NumericSequenceRange { \r\n if (!ValueUtil.hasValue(dataMin) || !ValueUtil.hasValue(dataMax)) {\r\n return NumericSequenceRange.calculateFixedRange(0, NumericSequenceRange.DEFAULT_MAX);\r\n } else {\r\n return NumericSequenceRange.calculate(dataMin, dataMax, null, null, includeZero);\r\n }\r\n }\r\n\r\n public static calculateFixedRange(fixedMin: number, fixedMax: number, includeZero?: boolean): NumericSequenceRange { \r\n debug.assertValue(fixedMin, \"fixedMin\");\r\n debug.assertValue(fixedMax, \"fixedMax\");\r\n\r\n let result = new NumericSequenceRange(); \r\n result.hasDataRange = false;\r\n result.includeZero = includeZero;\r\n result.min = fixedMin;\r\n result.max = fixedMax;\r\n result._ensureIncludeZero();\r\n result._ensureNotEmpty();\r\n result._ensureDirection();\r\n result.hasFixedMin = true;\r\n result.hasFixedMax = true;\r\n\r\n return result;\r\n }\r\n }\r\n\r\n /** Note: Exported for testability */\r\n export module ValueUtil {\r\n export function hasValue(value: any): boolean {\r\n return value !== undefined && value !== null;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n /**\r\n * Formats the value using provided format expression\r\n * @param value - value to be formatted and converted to string.\r\n * @param format - format to be applied if the number shouldn't be abbreviated.\r\n * If the number should be abbreviated this string is checked for special characters like $ or % if any\r\n */\r\n export interface ICustomValueFormatter {\r\n (value: any, format?: string): string;\r\n }\r\n\r\n export interface ICustomValueColumnFormatter {\r\n (value: any, column: DataViewMetadataColumn, formatStringProp: DataViewObjectPropertyIdentifier): string;\r\n }\r\n\r\n export interface ValueFormatterOptions {\r\n /** The format string to use. */\r\n format?: string;\r\n\r\n /** The data value. */\r\n value?: any;\r\n\r\n /** The data value. */\r\n value2?: any;\r\n\r\n /** The number of ticks. */\r\n tickCount?: any;\r\n\r\n /** The display unit system to use */\r\n displayUnitSystemType?: DisplayUnitSystemType;\r\n\r\n /** True if we are formatting single values in isolation (e.g. card), as opposed to multiple values with a common base (e.g. chart axes) */\r\n formatSingleValues?: boolean;\r\n\r\n /** True if we want to trim off unnecessary zeroes after the decimal and remove a space before the % symbol */\r\n allowFormatBeautification?: boolean;\r\n\r\n /** Specifies the maximum number of decimal places to show*/\r\n precision?: number;\r\n\r\n /** Detect axis precision based on value */\r\n detectAxisPrecision?: boolean;\r\n\r\n /** Specifies the column type of the data value */\r\n columnType?: ValueTypeDescriptor;\r\n }\r\n\r\n export interface IValueFormatter {\r\n format(value: any): string;\r\n displayUnit?: DisplayUnit;\r\n options?: ValueFormatterOptions;\r\n }\r\n\r\n /** Captures all locale-specific options used by the valueFormatter. */\r\n export interface ValueFormatterLocalizationOptions {\r\n null: string;\r\n true: string;\r\n false: string;\r\n NaN: string;\r\n infinity: string;\r\n negativeInfinity: string;\r\n\r\n /** Returns a beautified form the given format string. */\r\n beautify(format: string): string;\r\n\r\n /** Returns an object describing the given exponent in the current language. */\r\n describe(exponent: number): DisplayUnitSystemNames;\r\n restatementComma: string;\r\n restatementCompoundAnd: string;\r\n restatementCompoundOr: string;\r\n }\r\n\r\n export module valueFormatter {\r\n import StringExtensions = jsCommon.StringExtensions;\r\n const BeautifiedFormat: { [x: string]: string } = {\r\n '0.00 %;-0.00 %;0.00 %': 'Percentage',\r\n '0.0 %;-0.0 %;0.0 %': 'Percentage1',\r\n };\r\n\r\n export const DefaultIntegerFormat = 'g';\r\n export const DefaultNumericFormat = '#,0.00';\r\n export const DefaultDateFormat = 'd';\r\n\r\n const defaultLocalizedStrings = {\r\n 'NullValue': '(Blank)',\r\n 'BooleanTrue': 'True',\r\n 'BooleanFalse': 'False',\r\n 'NaNValue': 'NaN',\r\n 'InfinityValue': '+Infinity',\r\n 'NegativeInfinityValue': '-Infinity',\r\n 'RestatementComma': '{0}, {1}',\r\n 'RestatementCompoundAnd': '{0} and {1}',\r\n 'RestatementCompoundOr': '{0} or {1}',\r\n 'DisplayUnitSystem_EAuto_Title': 'Auto',\r\n 'DisplayUnitSystem_E0_Title': 'None',\r\n 'DisplayUnitSystem_E3_LabelFormat': '{0}K',\r\n 'DisplayUnitSystem_E3_Title': 'Thousands',\r\n 'DisplayUnitSystem_E6_LabelFormat': '{0}M',\r\n 'DisplayUnitSystem_E6_Title': 'Millions',\r\n 'DisplayUnitSystem_E9_LabelFormat': '{0}bn',\r\n 'DisplayUnitSystem_E9_Title': 'Billions',\r\n 'DisplayUnitSystem_E12_LabelFormat': '{0}T',\r\n 'DisplayUnitSystem_E12_Title': 'Trillions',\r\n 'Percentage': '#,0.##%',\r\n 'Percentage1': '#,0.#%',\r\n 'TableTotalLabel': 'Total',\r\n 'Tooltip_HighlightedValueDisplayName': 'Highlighted',\r\n 'Funnel_PercentOfFirst': 'Percent of first',\r\n 'Funnel_PercentOfPrevious': 'Percent of previous',\r\n 'Funnel_PercentOfFirst_Highlight': 'Percent of first (highlighted)',\r\n 'Funnel_PercentOfPrevious_Highlight': 'Percent of previous (highlighted)',\r\n // Geotagging strings\r\n 'GeotaggingString_Continent': 'continent',\r\n 'GeotaggingString_Continents': 'continents',\r\n 'GeotaggingString_Country': 'country',\r\n 'GeotaggingString_Countries': 'countries',\r\n 'GeotaggingString_State': 'state',\r\n 'GeotaggingString_States': 'states',\r\n 'GeotaggingString_City': 'city',\r\n 'GeotaggingString_Cities': 'cities',\r\n 'GeotaggingString_Town': 'town',\r\n 'GeotaggingString_Towns': 'towns',\r\n 'GeotaggingString_Province': 'province',\r\n 'GeotaggingString_Provinces': 'provinces',\r\n 'GeotaggingString_County': 'county',\r\n 'GeotaggingString_Counties': 'counties',\r\n 'GeotaggingString_Village': 'village',\r\n 'GeotaggingString_Villages': 'villages',\r\n 'GeotaggingString_Post': 'post',\r\n 'GeotaggingString_Zip': 'zip',\r\n 'GeotaggingString_Code': 'code',\r\n 'GeotaggingString_Place': 'place',\r\n 'GeotaggingString_Places': 'places',\r\n 'GeotaggingString_Address': 'address',\r\n 'GeotaggingString_Addresses': 'addresses',\r\n 'GeotaggingString_Street': 'street',\r\n 'GeotaggingString_Streets': 'streets',\r\n 'GeotaggingString_Longitude': 'longitude',\r\n 'GeotaggingString_Longitude_Short': 'lon',\r\n 'GeotaggingString_Latitude': 'latitude',\r\n 'GeotaggingString_Latitude_Short': 'lat',\r\n 'GeotaggingString_PostalCode': 'postal code',\r\n 'GeotaggingString_PostalCodes': 'postal codes',\r\n 'GeotaggingString_ZipCode': 'zip code',\r\n 'GeotaggingString_ZipCodes': 'zip codes',\r\n 'GeotaggingString_Territory': 'territory',\r\n 'GeotaggingString_Territories': 'territories',\r\n };\r\n\r\n function beautify(format: string): string {\r\n let key = BeautifiedFormat[format];\r\n if (key)\r\n return defaultLocalizedStrings[key] || format;\r\n return format;\r\n }\r\n\r\n function describeUnit(exponent: number): DisplayUnitSystemNames {\r\n let exponentLookup = (exponent === -1) ? 'Auto' : exponent.toString();\r\n\r\n let title: string = defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_Title\"];\r\n let format: string = (exponent <= 0) ? '{0}' : defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_LabelFormat\"];\r\n\r\n if (title || format)\r\n return { title: title, format: format };\r\n }\r\n\r\n export function getLocalizedString(stringId: string): string {\r\n return defaultLocalizedStrings[stringId];\r\n }\r\n\r\n // NOTE: Define default locale options, but these can be overriden by setLocaleOptions.\r\n let locale: ValueFormatterLocalizationOptions = {\r\n null: defaultLocalizedStrings['NullValue'],\r\n true: defaultLocalizedStrings['BooleanTrue'],\r\n false: defaultLocalizedStrings['BooleanFalse'],\r\n NaN: defaultLocalizedStrings['NaNValue'],\r\n infinity: defaultLocalizedStrings['InfinityValue'],\r\n negativeInfinity: defaultLocalizedStrings['NegativeInfinityValue'],\r\n beautify: format => beautify(format),\r\n describe: exponent => describeUnit(exponent),\r\n restatementComma: defaultLocalizedStrings['RestatementComma'],\r\n restatementCompoundAnd: defaultLocalizedStrings['RestatementCompoundAnd'],\r\n restatementCompoundOr: defaultLocalizedStrings['RestatementCompoundOr'],\r\n };\r\n\r\n const MaxScaledDecimalPlaces = 2;\r\n const MaxValueForDisplayUnitRounding = 1000;\r\n const MinIntegerValueForDisplayUnits = 10000;\r\n const MinPrecisionForDisplayUnits = 2;\r\n\r\n const DateTimeMetadataColumn: DataViewMetadataColumn = {\r\n displayName: '',\r\n type: ValueType.fromPrimitiveTypeAndCategory(PrimitiveType.DateTime),\r\n };\r\n\r\n export function getFormatMetadata(format: string): powerbi.NumberFormat.NumericFormatMetadata {\r\n return powerbi.NumberFormat.getCustomFormatMetadata(format);\r\n }\r\n\r\n export function setLocaleOptions(options: ValueFormatterLocalizationOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n locale = options;\r\n\r\n DefaultDisplayUnitSystem.reset();\r\n WholeUnitsDisplayUnitSystem.reset();\r\n }\r\n\r\n export function createDefaultFormatter(formatString: string, allowFormatBeautification: boolean = false): IValueFormatter {\r\n let formatBeaut: string = allowFormatBeautification ? locale.beautify(formatString) : formatString;\r\n return {\r\n format: function (value: any): string {\r\n if (value == null)\r\n return locale.null;\r\n\r\n return formatCore(value, formatBeaut);\r\n }\r\n };\r\n }\r\n\r\n /** Creates an IValueFormatter to be used for a range of values. */\r\n export function create(options: ValueFormatterOptions): IValueFormatter {\r\n debug.assertValue(options, 'options');\r\n\r\n let format = !!options.allowFormatBeautification ? locale.beautify(options.format) : options.format;\r\n\r\n if (shouldUseNumericDisplayUnits(options)) {\r\n let displayUnitSystem = createDisplayUnitSystem(options.displayUnitSystemType);\r\n\r\n let singleValueFormattingMode = !!options.formatSingleValues;\r\n\r\n displayUnitSystem.update(Math.max(Math.abs(options.value || 0), Math.abs(options.value2 || 0)));\r\n\r\n let forcePrecision = options.precision != null;\r\n\r\n let decimals: number;\r\n\r\n if (forcePrecision)\r\n decimals = -options.precision;\r\n else if (displayUnitSystem.displayUnit && displayUnitSystem.displayUnit.value > 1)\r\n decimals = -MaxScaledDecimalPlaces;\r\n\r\n // Detect axis precision\r\n if (options.detectAxisPrecision) {\r\n // Trailing zeroes\r\n forcePrecision = true;\r\n\r\n let axisValue = options.value;\r\n if (displayUnitSystem.displayUnit && displayUnitSystem.displayUnit.value > 0)\r\n axisValue = axisValue / displayUnitSystem.displayUnit.value;\r\n\r\n if (Double.isInteger(axisValue))\r\n decimals = 0;\r\n else\r\n decimals = Double.log10(axisValue);\r\n }\r\n\r\n return {\r\n format: function (value: any): string {\r\n let formattedValue: string = getStringFormat(value, true /*nullsAreBlank*/);\r\n if (!StringExtensions.isNullOrUndefinedOrWhiteSpaceString(formattedValue))\r\n return formattedValue;\r\n\r\n // Round to Double.DEFAULT_PRECISION\r\n if (value && !displayUnitSystem.isScalingUnit() && Math.abs(value) < MaxValueForDisplayUnitRounding && !forcePrecision)\r\n value = Double.roundToPrecision(value);\r\n\r\n return singleValueFormattingMode ?\r\n displayUnitSystem.formatSingleValue(value, format, decimals, forcePrecision) :\r\n displayUnitSystem.format(value, format, decimals, forcePrecision);\r\n },\r\n displayUnit: displayUnitSystem.displayUnit,\r\n options: options\r\n };\r\n }\r\n\r\n if (shouldUseDateUnits(options.value, options.value2, options.tickCount)) {\r\n let unit = DateTimeSequence.getIntervalUnit(options.value /* minDate */, options.value2 /* maxDate */, options.tickCount);\r\n\r\n return {\r\n format: function (value: any): string {\r\n if (value == null)\r\n return locale.null;\r\n\r\n let formatString = formattingService.dateFormatString(unit);\r\n return formatCore(value, formatString);\r\n },\r\n options: options\r\n };\r\n }\r\n\r\n return createDefaultFormatter(format);\r\n }\r\n\r\n export function format(value: any, format?: string, allowFormatBeautification?: boolean): string {\r\n if (value == null)\r\n return locale.null;\r\n\r\n return formatCore(\r\n value,\r\n !!allowFormatBeautification ? locale.beautify(format) : format);\r\n }\r\n\r\n function getValueFormat(value: any, columnType: ValueTypeDescriptor): string {\r\n // If column type not defined or is not datetime\r\n // ...and the value is of time datetime,\r\n // then use the default date format string\r\n if ((!columnType || !columnType.dateTime) && value instanceof Date)\r\n return getFormatString(DateTimeMetadataColumn, null, false);\r\n }\r\n\r\n export function formatValueColumn(value: any, column: DataViewMetadataColumn, formatStringProp: DataViewObjectPropertyIdentifier): string {\r\n let valueFormat = getValueFormat(value, column.type);\r\n if (valueFormat)\r\n return formatCore(value, valueFormat);\r\n else\r\n return formatCore(value, getFormatString(column, formatStringProp));\r\n }\r\n\r\n function createDisplayUnitSystem(displayUnitSystemType?: DisplayUnitSystemType): DisplayUnitSystem {\r\n if (displayUnitSystemType == null)\r\n return new DefaultDisplayUnitSystem(locale.describe);\r\n\r\n switch (displayUnitSystemType) {\r\n case DisplayUnitSystemType.Default:\r\n return new DefaultDisplayUnitSystem(locale.describe);\r\n case DisplayUnitSystemType.WholeUnits:\r\n return new WholeUnitsDisplayUnitSystem(locale.describe);\r\n case DisplayUnitSystemType.Verbose:\r\n return new NoDisplayUnitSystem();\r\n case DisplayUnitSystemType.DataLabels:\r\n return new DataLabelsDisplayUnitSystem(locale.describe);\r\n default:\r\n debug.assertFail('Unknown display unit system type');\r\n return new DefaultDisplayUnitSystem(locale.describe);\r\n }\r\n }\r\n\r\n function shouldUseNumericDisplayUnits(options: ValueFormatterOptions): boolean {\r\n let value = options.value;\r\n let value2 = options.value2;\r\n let format = options.format;\r\n // For singleValue visuals like card, gauge we don't want to roundoff data to the nearest thousands so format the whole number / integers below 10K to not use display units\r\n if (options.formatSingleValues && format) {\r\n\r\n if (Math.abs(value) < MinIntegerValueForDisplayUnits) {\r\n\r\n let isCustomFormat = !powerbi.NumberFormat.isStandardFormat(format);\r\n\r\n if (isCustomFormat) {\r\n let precision = powerbi.NumberFormat.getCustomFormatMetadata(format, true /*calculatePrecision*/).precision;\r\n\r\n if (precision < MinPrecisionForDisplayUnits)\r\n return false;\r\n }\r\n else if (Double.isInteger(value))\r\n return false;\r\n }\r\n }\r\n\r\n if ((typeof value === 'number') || (typeof value2 === 'number')) {\r\n return true;\r\n }\r\n }\r\n\r\n function shouldUseDateUnits(value: any, value2?: any, tickCount?: number): boolean {\r\n // must check both value and value2 because we'll need to get an interval for date units\r\n return (value instanceof Date) && (value2 instanceof Date) && (tickCount !== undefined && tickCount !== null);\r\n }\r\n\r\n /*\r\n * Get the column format. Order of precendence is:\r\n * 1. Column format\r\n * 2. Default PowerView policy for column type\r\n */\r\n export function getFormatString(column: DataViewMetadataColumn, formatStringProperty: DataViewObjectPropertyIdentifier, suppressTypeFallback?: boolean): string {\r\n if (column) {\r\n if (formatStringProperty) {\r\n let propertyValue = DataViewObjects.getValue<string>(column.objects, formatStringProperty);\r\n if (propertyValue)\r\n return propertyValue;\r\n }\r\n\r\n if (!suppressTypeFallback) {\r\n let columnType = column.type;\r\n if (columnType) {\r\n if (columnType.dateTime)\r\n return DefaultDateFormat;\r\n if (columnType.integer)\r\n return DefaultIntegerFormat;\r\n if (columnType.numeric)\r\n return DefaultNumericFormat;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function formatListCompound(strings: string[], conjunction: string): string {\r\n let result: string;\r\n\r\n if (!strings) {\r\n return null;\r\n }\r\n\r\n let length = strings.length;\r\n if (length > 0) {\r\n result = strings[0];\r\n let lastIndex = length - 1;\r\n for (let i = 1, len = lastIndex; i < len; i++) {\r\n let value = strings[i];\r\n result = StringExtensions.format(locale.restatementComma, result, value);\r\n }\r\n\r\n if (length > 1) {\r\n let value = strings[lastIndex];\r\n result = StringExtensions.format(conjunction, result, value);\r\n }\r\n }\r\n else {\r\n result = null;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /** The returned string will look like 'A, B, ..., and C' */\r\n export function formatListAnd(strings: string[]): string {\r\n return formatListCompound(strings, locale.restatementCompoundAnd);\r\n }\r\n\r\n /** The returned string will look like 'A, B, ..., or C' */\r\n export function formatListOr(strings: string[]): string {\r\n return formatListCompound(strings, locale.restatementCompoundOr);\r\n }\r\n\r\n function formatCore(value: any, format: string): string {\r\n let formattedValue = getStringFormat(value, false /*nullsAreBlank*/);\r\n\r\n if (!StringExtensions.isNullOrUndefinedOrWhiteSpaceString(formattedValue))\r\n return formattedValue;\r\n\r\n return formattingService.formatValue(value, format);\r\n }\r\n\r\n function getStringFormat(value: any, nullsAreBlank: boolean): string {\r\n if (value == null && nullsAreBlank)\r\n return locale.null;\r\n\r\n if (value === true)\r\n return locale.true;\r\n\r\n if (value === false)\r\n return locale.false;\r\n\r\n if (typeof value === 'number' && isNaN(value))\r\n return locale.NaN;\r\n\r\n if (value === Number.NEGATIVE_INFINITY)\r\n return locale.negativeInfinity;\r\n\r\n if (value === Number.POSITIVE_INFINITY)\r\n return locale.infinity;\r\n\r\n return '';\r\n }\r\n\r\n export function getDisplayUnits(displayUnitSystemType: DisplayUnitSystemType): DisplayUnit[] {\r\n let displayUnitSystem = createDisplayUnitSystem(displayUnitSystemType);\r\n return displayUnitSystem.units;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export module DataRoleHelper {\r\n export function getMeasureIndexOfRole(grouped: DataViewValueColumnGroup[], roleName: string): number {\r\n if (!_.isEmpty(grouped)) {\r\n let firstGroup = grouped[0];\r\n if (firstGroup.values && firstGroup.values.length > 0) {\r\n for (let i = 0, len = firstGroup.values.length; i < len; ++i) {\r\n let value = firstGroup.values[i];\r\n if (value && value.source) {\r\n if (hasRole(value.source, roleName))\r\n return i;\r\n }\r\n }\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n export function getCategoryIndexOfRole(categories: DataViewCategoryColumn[], roleName: string): number {\r\n if (!_.isEmpty(categories)) {\r\n for (let i = 0, ilen = categories.length; i < ilen; i++) {\r\n if (hasRole(categories[i].source, roleName))\r\n return i;\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n export function hasRole(column: DataViewMetadataColumn, name: string): boolean {\r\n let roles = column.roles;\r\n return roles && roles[name];\r\n }\r\n\r\n export function hasRoleInDataView(dataView: DataView, name: string): boolean {\r\n return dataView != null\r\n && dataView.metadata != null\r\n && dataView.metadata.columns\r\n && _.any(dataView.metadata.columns, c => c.roles && c.roles[name] !== undefined);\r\n }\r\n \r\n export function hasRoleInValueColumn(valueColumn: DataViewValueColumn, name: string): boolean {\r\n return valueColumn && valueColumn.source && valueColumn.source.roles && (valueColumn.source.roles[name] === true);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export function createIDataViewCategoricalReader(dataView: DataView): IDataViewCategoricalReader {\r\n return new DataViewCategoricalReader(dataView);\r\n }\r\n\r\n export interface IDataViewCategoricalReader {\r\n // Category functions\r\n hasCategories(): boolean;\r\n getCategoryCount(): number;\r\n getCategoryValues(roleName: string): any;\r\n getCategoryValue(roleName: string, categoryIndex: number): any;\r\n getCategoryColumn(roleName: string): DataViewCategoryColumn;\r\n getCategoryMetadataColumn(roleName: string): DataViewMetadataColumn;\r\n getCategoryColumnIdentityFields(roleName: string): powerbi.data.ISQExpr[];\r\n getCategoryDisplayName(roleName: string): string;\r\n hasCompositeCategories(): boolean;\r\n hasCategoryWithRole(roleName: string): boolean;\r\n getCategoryObjects(roleName: string, categoryIndex: number): DataViewObjects;\r\n // Value functions\r\n hasValues(roleName: string): boolean;\r\n /**\r\n * Obtains the value for the given role name, category index, and series index.\r\n *\r\n * Note: in cases where have multiple values in a role where the multiple values\r\n * are not being used to create a static series, the first is obtained. (this is\r\n * a rare case)\r\n */\r\n getValue(roleName: string, categoryIndex: number, seriesIndex?: number): any;\r\n /**\r\n * Obtains the highlighted value for the given role name, category index, and series index.\r\n *\r\n * Note: in cases where have multiple values in a role where the multiple values\r\n * are not being used to create a static series, the first is obtained. (this is\r\n * a rare case)\r\n */\r\n getHighlight(roleName: string, categoryIndex: number, seriesIndex?: number): any;\r\n /**\r\n * Obtains all the values for the given role name, category index, and series index, drawing\r\n * from each of the value columns at that intersection. Used when you have multiple\r\n * values in a role that are not conceptually a static series.\r\n */\r\n getAllValuesForRole(roleName: string, categoryIndex: number, seriesIndex?: number): any[];\r\n /**\r\n * Obtains all the highlight values for the given role name, category index, and series index, drawing\r\n * from each of the value columns at that intersection. Used when you have multiple\r\n * values in a role that are not conceptually a static series.\r\n */\r\n getAllHighlightsForRole(roleName: string, categoryIndex: number, seriesIndex?: number): any[];\r\n /**\r\n * Obtains the first non-null value for the given role name and category index.\r\n * It should mainly be used for values that are expected to be the same across\r\n * series, but avoids false nulls when the data is sparse.\r\n */\r\n getFirstNonNullValueForCategory(roleName: string, categoryIndex: number): any;\r\n getMeasureQueryName(roleName: string): string;\r\n getValueColumn(roleName: string, seriesIndex?: number): DataViewValueColumn;\r\n getValueMetadataColumn(roleName: string, seriesIndex?: number): DataViewMetadataColumn;\r\n getValueDisplayName(roleName: string, seriesIndex?: number): string;\r\n // Series Methods\r\n hasDynamicSeries(): boolean;\r\n /**\r\n * Get the series count. This requires a value role name for cases where you may\r\n * have a static series, but is not required if the only series you expect are dynamic\r\n * or single series. \r\n * \r\n * @param valueRoleName The role of the value for which a static series may exist\r\n */\r\n getSeriesCount(valueRoleName?: string): number;\r\n getSeriesObjects(seriesIndex: number): DataViewObjects;\r\n getSeriesValueColumns(): DataViewValueColumns;\r\n getSeriesValueColumnGroup(seriesIndex: number): DataViewValueColumnGroup;\r\n getSeriesMetadataColumn(): DataViewMetadataColumn;\r\n getSeriesColumnIdentityFields(): powerbi.data.ISQExpr[];\r\n getSeriesName(seriesIndex: number): PrimitiveValue;\r\n getSeriesDisplayName(): string;\r\n }\r\n\r\n /**\r\n * A mapping used to map indeces within a specific roleName to an index into the values\r\n * of a grouped. This is used so that you can iterate over values within a role without\r\n * expensive filtering or extra traversal.\r\n */ \r\n interface RoleIndexMapping {\r\n [roleName: string]: number[];\r\n }\r\n\r\n class DataViewCategoricalReader implements IDataViewCategoricalReader {\r\n private dataView: DataView;\r\n private categories: DataViewCategoryColumn[];\r\n private grouped: DataViewValueColumnGroup[];\r\n private dataHasDynamicSeries: boolean;\r\n private valueRoleIndexMapping: RoleIndexMapping;\r\n \r\n // Validation variables\r\n private hasValidCategories: boolean;\r\n private hasAnyValidValues: boolean;\r\n\r\n constructor(dataView: DataView) {\r\n debug.assertValue(dataView, 'dataView');\r\n this.dataView = dataView;\r\n // Validate categories\r\n let categorical: DataViewCategorical;\r\n if (dataView)\r\n categorical = dataView.categorical;\r\n let categories: DataViewCategoryColumn[];\r\n if (categorical)\r\n categories = this.categories = categorical.categories;\r\n this.hasValidCategories = !_.isEmpty(categories);\r\n\r\n // Validate values\r\n let values: DataViewValueColumns;\r\n if (categorical)\r\n values = categorical.values;\r\n // We need to access grouped as long as values is non-null; if it's an empty array (meaning there is a category + series), we'll use grouped for non-value stuff\r\n // TODO: think a bit more about how to represent this internally; Maybe split this up between hasGroup and hasValidValues or something\r\n this.hasAnyValidValues = false;\r\n if (values != null) {\r\n let grouped = dataView.categorical.values.grouped();\r\n\r\n if (grouped.length > 0) {\r\n this.hasAnyValidValues = true;\r\n this.grouped = grouped;\r\n\r\n // Iterate through the first group's values to populate the valueRoleIndexMapping\r\n let valueRoleIndexMapping: RoleIndexMapping = {};\r\n let firstGroupValues = grouped[0].values;\r\n for (let valueIndex = 0, valueCount = firstGroupValues.length; valueIndex < valueCount; valueIndex++) {\r\n let valueRoles = firstGroupValues[valueIndex].source.roles;\r\n for (let role in valueRoles) {\r\n if (valueRoles[role]) {\r\n if (!valueRoleIndexMapping[role])\r\n valueRoleIndexMapping[role] = [];\r\n valueRoleIndexMapping[role].push(valueIndex);\r\n }\r\n }\r\n }\r\n this.valueRoleIndexMapping = valueRoleIndexMapping;\r\n }\r\n }\r\n\r\n if (this.hasAnyValidValues)\r\n this.dataHasDynamicSeries = !!this.dataView.categorical.values.source;\r\n }\r\n\r\n // Category methods\r\n \r\n public hasCategories(): boolean {\r\n return this.hasValidCategories;\r\n }\r\n\r\n public getCategoryCount(): number {\r\n if (this.hasValidCategories)\r\n return this.categories[0].values.length;\r\n else\r\n return 0;\r\n }\r\n\r\n public getCategoryValues(roleName: string): any {\r\n if (this.hasValidCategories) {\r\n let categories = this.getCategoryFromRole(roleName);\r\n return categories ? categories.values : undefined;\r\n }\r\n }\r\n\r\n public getCategoryValue(roleName: string, categoryIndex: number): any {\r\n if (this.hasValidCategories) {\r\n let categories = this.getCategoryFromRole(roleName);\r\n return categories ? categories.values[categoryIndex] : undefined;\r\n }\r\n }\r\n\r\n public getCategoryColumn(roleName: string): DataViewCategoryColumn {\r\n if (this.hasValidCategories)\r\n return this.getCategoryFromRole(roleName);\r\n }\r\n\r\n public getCategoryMetadataColumn(roleName: string): DataViewMetadataColumn {\r\n if (this.hasValidCategories) {\r\n let categories = this.getCategoryFromRole(roleName);\r\n return categories ? categories.source : undefined;\r\n }\r\n }\r\n\r\n public getCategoryColumnIdentityFields(roleName: string): powerbi.data.ISQExpr[] {\r\n if (this.hasValidCategories) {\r\n let categories = this.getCategoryFromRole(roleName);\r\n return categories ? categories.identityFields : undefined;\r\n }\r\n }\r\n\r\n public getCategoryDisplayName(roleName: string): string {\r\n if (this.hasValidCategories) {\r\n let targetColumn = this.getCategoryColumn(roleName);\r\n if (targetColumn && targetColumn.source) {\r\n return targetColumn.source.displayName;\r\n }\r\n }\r\n }\r\n\r\n public hasCompositeCategories(): boolean {\r\n if (this.hasValidCategories)\r\n return this.categories.length > 1;\r\n }\r\n\r\n public hasCategoryWithRole(roleName: string): boolean {\r\n return DataRoleHelper.getCategoryIndexOfRole(this.categories, roleName) !== -1;\r\n }\r\n\r\n public getCategoryObjects(roleName: string, categoryIndex: number): DataViewObjects {\r\n if (this.hasValidCategories) {\r\n let category = this.getCategoryFromRole(roleName);\r\n if (category && category.objects) {\r\n return category.objects[categoryIndex];\r\n }\r\n }\r\n }\r\n\r\n private getCategoryFromRole(roleName: string): DataViewCategoryColumn {\r\n let categories = this.categories;\r\n return categories[DataRoleHelper.getCategoryIndexOfRole(categories, roleName)];\r\n }\r\n\r\n // Value and measure methods\r\n\r\n public hasValues(roleName: string): boolean {\r\n return this.valueRoleIndexMapping && !_.isEmpty(this.valueRoleIndexMapping[roleName]);\r\n }\r\n\r\n public getValue(roleName: string, categoryIndex: number, seriesIndex: number = 0): any {\r\n if (this.hasValues(roleName)) {\r\n if (this.dataHasDynamicSeries) {\r\n // For dynamic series, we only ever obtain the first value column from a role\r\n return this.getValueInternal(roleName, categoryIndex, seriesIndex, 0, false /* getHighlight */);\r\n }\r\n else {\r\n // For static series or single series, we obtain value columns from the first series\r\n // and use the seriesIndex to index into the value columns within the role\r\n return this.getValueInternal(roleName, categoryIndex, 0, seriesIndex, false /* getHighlight */);\r\n }\r\n }\r\n }\r\n\r\n public getHighlight(roleName: string, categoryIndex: number, seriesIndex: number = 0): any {\r\n if (this.hasValues(roleName)) {\r\n if (this.dataHasDynamicSeries) {\r\n // For dynamic series, we only ever obtain the first value column from a role\r\n return this.getValueInternal(roleName, categoryIndex, seriesIndex, 0, true /* getHighlight */);\r\n }\r\n else {\r\n // For static series or single series, we obtain value columns from the first series\r\n // and use the seriesIndex to index into the value columns within the role\r\n return this.getValueInternal(roleName, categoryIndex, 0, seriesIndex, true /* getHighlight */);\r\n }\r\n }\r\n }\r\n\r\n public getAllValuesForRole(roleName: string, categoryIndex: number, seriesIndex: number = 0): any[] {\r\n if (this.hasValues(roleName)) {\r\n let valuesInRole = [];\r\n for (let roleValueIndex, roleValueCount = this.valueRoleIndexMapping[roleName].length; roleValueIndex < roleValueCount; roleValueIndex++) {\r\n valuesInRole.push(this.getValueInternal(roleName, categoryIndex, seriesIndex, roleValueIndex, false /* getHighlight */));\r\n }\r\n return valuesInRole;\r\n }\r\n }\r\n\r\n public getAllHighlightsForRole(roleName: string, categoryIndex: number, seriesIndex: number = 0): any[] {\r\n if (this.hasValues(roleName)) {\r\n let valuesInRole = [];\r\n for (let roleValueIndex, roleValueCount = this.valueRoleIndexMapping[roleName].length; roleValueIndex < roleValueCount; roleValueIndex++) {\r\n valuesInRole.push(this.getValueInternal(roleName, categoryIndex, seriesIndex, roleValueIndex, true /* getHighlight */));\r\n }\r\n return valuesInRole;\r\n }\r\n }\r\n\r\n /**\r\n * Obtains the value from grouped.\r\n *\r\n * Grouped: [0] [1] [2] [3] (seriesIndex)\r\n * / \\\r\n * .values: [T0] [V0] [V1] [T1] [V2] (valueColumnIndex)\r\n * / \\ \\ \\ \r\n * v.values: [0, 1, 2, 3, 4] [5, 6, 7, 8, 9] (categoryIndex)\r\n * \r\n *--------------------------------|\r\n * |Category |\r\n * Series|Value Columns |A B C D E|\r\n *--------------------------------|\r\n * 0|col0 (tooltip)| |\r\n * |col1 (value) | |\r\n * |col2 (value) | |\r\n * |col3 (tooltip)| |\r\n * |col4 (value) | |\r\n *--------------------------------|\r\n * 1|col0 (tooltip)| |\r\n * |col1 (value) |0 1 2 3 4|\r\n * |col2 (value) |5 6 7 8 9|\r\n * |col3 (tooltip)| |\r\n * |col4 (value) | |\r\n *--------------------------------|\r\n * 2|col0 (tooltip)|... |\r\n * \r\n * valueColumnIndexInRole is for indexing into the values for a single role\r\n * valueColumnIndex is for indexing into the entire value array including\r\n * all roles\r\n * \r\n * The valueRoleIndexMapping converts roleValueIndex and role (value role\r\n * with an index of 1) into groupedValueIndex (2)\r\n *\r\n * Example: getValueInternal(V, 3, 1, 1) returns 8: The second group,\r\n * the second value column with role \"value\" (which is converted to a\r\n * groupedValueIndex of 2) and the fourth value within that value column.\r\n */\r\n private getValueInternal(roleName: string, categoryIndex: number, groupIndex: number, valueColumnIndexInRole: number, getHighlight: boolean): any {\r\n if (this.hasValues(roleName)) {\r\n let valueColumnIndex = this.valueRoleIndexMapping[roleName][valueColumnIndexInRole];\r\n let groupedValues = this.grouped[groupIndex].values[valueColumnIndex];\r\n return getHighlight ? groupedValues.highlights[categoryIndex] : groupedValues.values[categoryIndex];\r\n }\r\n }\r\n\r\n public getFirstNonNullValueForCategory(roleName: string, categoryIndex: number): any {\r\n if (this.hasValues(roleName)) {\r\n if (!this.dataHasDynamicSeries) {\r\n debug.assert(this.grouped.length === 1, \"getFirstNonNullValueForCategory shouldn't be called if you have a static series\");\r\n return this.getValue(roleName, categoryIndex);\r\n }\r\n for (let seriesIndex = 0, seriesCount = this.grouped.length; seriesIndex < seriesCount; seriesIndex++) {\r\n let value = this.getValue(roleName, categoryIndex, seriesIndex);\r\n if (value != null) {\r\n return value;\r\n }\r\n }\r\n }\r\n }\r\n\r\n public getMeasureQueryName(roleName: string): string {\r\n if (this.hasValues(roleName))\r\n return this.grouped[0].values[this.valueRoleIndexMapping[roleName][0]].source.queryName;\r\n }\r\n\r\n public getValueColumn(roleName: string, seriesIndex: number = 0): DataViewValueColumn {\r\n if (this.hasValues(roleName)) {\r\n if (this.dataHasDynamicSeries) {\r\n return this.grouped[seriesIndex].values[this.valueRoleIndexMapping[roleName][0]];\r\n }\r\n else {\r\n return this.grouped[0].values[this.valueRoleIndexMapping[roleName][seriesIndex]];\r\n }\r\n }\r\n }\r\n\r\n public getValueMetadataColumn(roleName: string, seriesIndex: number = 0): DataViewMetadataColumn {\r\n let valueColumn = this.getValueColumn(roleName, seriesIndex);\r\n if (valueColumn) {\r\n return valueColumn.source;\r\n }\r\n }\r\n\r\n public getValueDisplayName(roleName: string, seriesIndex?: number): string {\r\n if (this.hasValues(roleName)) {\r\n let targetColumn = this.getValueColumn(roleName, seriesIndex);\r\n if (targetColumn && targetColumn.source) {\r\n return targetColumn.source.displayName;\r\n }\r\n }\r\n }\r\n\r\n // Series methods\r\n\r\n public hasDynamicSeries(): boolean {\r\n return this.dataHasDynamicSeries;\r\n }\r\n\r\n public getSeriesCount(valueRoleName?: string): number {\r\n if (this.hasAnyValidValues) {\r\n if (this.dataHasDynamicSeries) {\r\n return this.grouped.length;\r\n }\r\n else if (valueRoleName) {\r\n return this.valueRoleIndexMapping[valueRoleName].length;\r\n }\r\n else {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n public getSeriesObjects(seriesIndex: number): DataViewObjects {\r\n if (this.hasAnyValidValues)\r\n return this.grouped[seriesIndex].objects;\r\n }\r\n\r\n public getSeriesValueColumns(): DataViewValueColumns {\r\n if (this.hasAnyValidValues)\r\n return this.dataView.categorical.values;\r\n }\r\n\r\n public getSeriesValueColumnGroup(seriesIndex: number): DataViewValueColumnGroup {\r\n if (this.hasAnyValidValues)\r\n return this.grouped[seriesIndex];\r\n }\r\n\r\n public getSeriesMetadataColumn(): DataViewMetadataColumn {\r\n if (this.hasAnyValidValues)\r\n return this.dataView.categorical.values.source;\r\n }\r\n\r\n public getSeriesColumnIdentityFields(): powerbi.data.ISQExpr[] {\r\n if (this.hasAnyValidValues)\r\n return this.dataView.categorical.values.identityFields;\r\n }\r\n\r\n public getSeriesName(seriesIndex: number): PrimitiveValue {\r\n if (this.hasAnyValidValues)\r\n return this.grouped[seriesIndex].name;\r\n }\r\n\r\n public getSeriesDisplayName(): string {\r\n if (this.hasAnyValidValues && this.dataHasDynamicSeries)\r\n return this.dataView.categorical.values.source.displayName;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import inherit = Prototype.inherit;\r\n import inheritSingle = Prototype.inheritSingle;\r\n import RoleKindByQueryRef = DataViewAnalysis.RoleKindByQueryRef;\r\n import valueFormatter = powerbi.visuals.valueFormatter;\r\n\r\n export module DataViewConcatenateCategoricalColumns {\r\n\r\n /* Represents a collection of DataViewCategoryColumn that are tied to the same role. */\r\n interface CategoryColumnsByRole {\r\n /* The name of the role shared by all the objects in the categories property. */\r\n roleName: string;\r\n\r\n /**\r\n * The list of columns that are tied to roleName, in the same order as they appear\r\n * in the categories property of their owner DataViewCategorical object.\r\n */\r\n categories: DataViewCategoryColumn[];\r\n }\r\n\r\n export function detectAndApply(\r\n dataView: DataView,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n roleMappings: DataViewMapping[],\r\n projectionOrdering: DataViewProjectionOrdering,\r\n selects: DataViewSelectTransform[],\r\n projectionActiveItems: DataViewProjectionActiveItems): DataView {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertAnyValue(roleMappings, 'roleMappings');\r\n debug.assertAnyValue(projectionOrdering, 'projectionOrdering');\r\n\r\n let result = dataView;\r\n let dataViewCategorical: DataViewCategorical = dataView.categorical;\r\n\r\n if (dataViewCategorical) {\r\n let concatenationSource: CategoryColumnsByRole = detectCategoricalRoleForHierarchicalGroup(dataViewCategorical, dataView.metadata, roleMappings, selects, projectionActiveItems);\r\n\r\n if (concatenationSource) {\r\n // Consider: Perhaps the re-ordering of categorical columns should happen in the function transformSelects(...) of dataViewTransform?\r\n let columnsSortedByProjectionOrdering = sortColumnsByProjectionOrdering(projectionOrdering, concatenationSource.roleName, concatenationSource.categories);\r\n if (columnsSortedByProjectionOrdering.length >= 2) {\r\n let activeItemsToIgnoreInConcatenation =\r\n _.chain(projectionActiveItems[concatenationSource.roleName])\r\n .filter((activeItemInfo: DataViewProjectionActiveItemInfo) => activeItemInfo.suppressConcat)\r\n .map((activeItemInfo: DataViewProjectionActiveItemInfo) => activeItemInfo.queryRef)\r\n .value();\r\n\r\n result = applyConcatenation(dataView, objectDescriptors, concatenationSource.roleName, columnsSortedByProjectionOrdering, activeItemsToIgnoreInConcatenation);\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /** For applying concatenation to the DataViewCategorical that is the data for one of the frames in a play chart. */\r\n export function applyToPlayChartCategorical(\r\n metadata: DataViewMetadata,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n categoryRoleName: string,\r\n categorical: DataViewCategorical): DataView {\r\n debug.assertValue(metadata, 'metadata');\r\n debug.assertAnyValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(categorical, 'categorical');\r\n\r\n let result: DataView;\r\n if (!_.isEmpty(categorical.categories) && categorical.categories.length >= 2) {\r\n // In PlayChart, the code converts the Visual DataView with a matrix into multiple Visual DataViews, each with a categorical.\r\n // metadata and metadata.columns could already be inherited objects as they come from the Visual DataView with a matrix.\r\n // To guarantee that this method does not have any side effect on prototypeMetadata (which might already be an inherited obj),\r\n // use inherit() rather than inheritSingle() here.\r\n let transformingColumns = inherit(metadata.columns);\r\n let transformingMetadata = inherit(metadata, m => { m.columns = transformingColumns; });\r\n\r\n let transformingDataView = { metadata: transformingMetadata, categorical: categorical };\r\n result = applyConcatenation(transformingDataView, objectDescriptors, categoryRoleName, categorical.categories, []);\r\n }\r\n else {\r\n result = { metadata: metadata, categorical: categorical };\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Returns the role and its assocated category columns (from dataViewCategorical.categories)\r\n * that should be concatenated for the case of hierarchical group.\r\n *\r\n * Note: In the future if we support sibling hierarchical groups in categorical,\r\n * change the return type to CategoryColumnsByRole[] and update detection logic.\r\n */\r\n function detectCategoricalRoleForHierarchicalGroup(dataViewCategorical: DataViewCategorical, metadata: DataViewMetadata, dataViewMappings: DataViewMapping[], selects: DataViewSelectTransform[], projectionActiveItems: DataViewProjectionActiveItems): CategoryColumnsByRole {\r\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\r\n debug.assertAnyValue(dataViewMappings, 'dataViewMappings');\r\n\r\n let result: CategoryColumnsByRole;\r\n\r\n let roleKinds: RoleKindByQueryRef = DataViewSelectTransform.createRoleKindFromMetadata(selects, metadata);\r\n let projections = DataViewSelectTransform.projectionsFromSelects(selects, projectionActiveItems);\r\n let supportedRoleMappings = DataViewAnalysis.chooseDataViewMappings(projections, dataViewMappings, roleKinds).supportedMappings;\r\n\r\n // The following code will choose a role name only if all supportedRoleMappings share the same role for Categorical Category.\r\n // Handling multiple supportedRoleMappings is necessary for TransformActions with splits, which can happen in scenarios such as:\r\n // 1. combo chart with a field for both Line and Column values, and\r\n // 2. chart with regression line enabled.\r\n // In case 1, you can pretty much get exactly the one from supportedRoleMappings for which this code is currently processing for,\r\n // by looking at the index of the current split in DataViewTransformActions.splits.\r\n // In case 2, however, supportedRoleMappings.length will be different than DataViewTransformActions.splits.length, hence it is\r\n // not straight forward to figure out for which one in supportedRoleMappings is this code currently processing.\r\n // SO... This code will just choose the category role name if it is consistent across all supportedRoleMappings.\r\n\r\n let isEveryRoleMappingForCategorical = !_.isEmpty(supportedRoleMappings) &&\r\n _.every(supportedRoleMappings, (roleMapping) => !!roleMapping.categorical);\r\n\r\n if (isEveryRoleMappingForCategorical) {\r\n let targetRoleName = getSingleCategoryRoleNameInEveryRoleMapping(supportedRoleMappings);\r\n if (targetRoleName &&\r\n isVisualExpectingMaxOneCategoryColumn(targetRoleName, supportedRoleMappings)) {\r\n\r\n let categoryColumnsForTargetRole: DataViewCategoryColumn[] = _.filter(\r\n dataViewCategorical.categories,\r\n (categoryColumn: DataViewCategoryColumn) => categoryColumn.source.roles && !!categoryColumn.source.roles[targetRoleName]);\r\n\r\n // There is no need to concatenate columns unless there is actually more than one column\r\n if (categoryColumnsForTargetRole.length >= 2) {\r\n // At least for now, we expect all category columns for the same role to have the same number of value entries.\r\n // If that's not the case, we won't run the concatenate logic for that role at all...\r\n let areValuesCountsEqual: boolean = _.every(\r\n categoryColumnsForTargetRole,\r\n (categoryColumn: DataViewCategoryColumn) => categoryColumn.values.length === categoryColumnsForTargetRole[0].values.length);\r\n \r\n if (areValuesCountsEqual) {\r\n result = {\r\n roleName: targetRoleName,\r\n categories: categoryColumnsForTargetRole,\r\n };\r\n }\r\n }\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n /** If all mappings in the specified roleMappings have the same single role name for their categorical category roles, return that role name, else returns undefined. */\r\n function getSingleCategoryRoleNameInEveryRoleMapping(categoricalRoleMappings: DataViewMapping[]): string {\r\n debug.assertNonEmpty(categoricalRoleMappings, 'categoricalRoleMappings');\r\n debug.assert(_.every(categoricalRoleMappings, (roleMapping) => !!roleMapping.categorical), 'All mappings in categoricalRoleMappings must contain a DataViewCategoricalMapping');\r\n\r\n let result: string;\r\n\r\n // With \"list\" in role mapping, it is possible to have multiple role names for category.\r\n // For now, proceed to concatenate category columns only when categories are bound to 1 Role.\r\n // We can change this if we want to support independent (sibling) group hierarchies in categorical.\r\n let uniqueCategoryRoles: string[] = _.chain(categoricalRoleMappings)\r\n .map((roleMapping) => {\r\n let categoryRoles = getAllRolesInCategories(roleMapping.categorical);\r\n return categoryRoles.length === 1 ? categoryRoles[0] : undefined;\r\n })\r\n .uniq() // Note: _.uniq() does not treat two arrays with same elements as equal\r\n .value();\r\n \r\n\r\n let isSameCategoryRoleNameInAllRoleMappings = uniqueCategoryRoles.length === 1 && !_.isUndefined(uniqueCategoryRoles[0]);\r\n if (isSameCategoryRoleNameInAllRoleMappings) {\r\n result = uniqueCategoryRoles[0];\r\n }\r\n\r\n return result;\r\n }\r\n\r\n function isVisualExpectingMaxOneCategoryColumn(categoricalRoleName: string, roleMappings: DataViewMapping[]): boolean {\r\n debug.assertValue(categoricalRoleName, 'categoricalRoleName');\r\n debug.assertNonEmpty(roleMappings, 'roleMappings');\r\n\r\n let isVisualExpectingMaxOneCategoryColumn = _.every(\r\n roleMappings,\r\n (roleMapping) => {\r\n return !_.isEmpty(roleMapping.conditions) &&\r\n _.every(roleMapping.conditions, condition => condition[categoricalRoleName] && condition[categoricalRoleName].max === 1);\r\n });\r\n\r\n return isVisualExpectingMaxOneCategoryColumn;\r\n }\r\n\r\n /**\r\n * Returns the array of role names that are mapped to categorical categories.\r\n * Returns an empty array if none exists.\r\n */\r\n function getAllRolesInCategories(categoricalRoleMapping: DataViewCategoricalMapping): string[] {\r\n debug.assertValue(categoricalRoleMapping, 'categoricalRoleMapping');\r\n\r\n let roleNames: string[] = [];\r\n DataViewMapping.visitCategoricalCategories(\r\n categoricalRoleMapping.categories,\r\n {\r\n visitRole: (roleName: string) => {\r\n roleNames.push(roleName);\r\n }\r\n });\r\n\r\n return roleNames;\r\n }\r\n\r\n function applyConcatenation(dataView: DataView, objectDescriptors: DataViewObjectDescriptors, roleName: string, columnsSortedByProjectionOrdering: DataViewCategoryColumn[], queryRefsToIgnore: string[]): DataView {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertAnyValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(roleName, 'roleName');\r\n debug.assert(columnsSortedByProjectionOrdering && columnsSortedByProjectionOrdering.length >= 2, 'columnsSortedByProjectionOrdering && columnsSortedByProjectionOrdering.length >= 2');\r\n\r\n let formatStringPropId: DataViewObjectPropertyIdentifier = DataViewObjectDescriptors.findFormatString(objectDescriptors);\r\n let concatenatedValues: string[] = concatenateValues(columnsSortedByProjectionOrdering, queryRefsToIgnore, formatStringPropId);\r\n\r\n let columnsSourceSortedByProjectionOrdering = _.map(columnsSortedByProjectionOrdering, categoryColumn => categoryColumn.source);\r\n let concatenatedColumnMetadata: DataViewMetadataColumn = createConcatenatedColumnMetadata(roleName, columnsSourceSortedByProjectionOrdering, queryRefsToIgnore);\r\n let transformedDataView = inheritSingle(dataView);\r\n addToMetadata(transformedDataView, concatenatedColumnMetadata);\r\n\r\n let concatenatedCategoryColumn: DataViewCategoryColumn = createConcatenatedCategoryColumn(\r\n columnsSortedByProjectionOrdering,\r\n concatenatedColumnMetadata,\r\n concatenatedValues);\r\n\r\n let dataViewCategorical: DataViewCategorical = dataView.categorical;\r\n\r\n let transformedCategoricalCategories: DataViewCategoryColumn[] = _.difference(dataViewCategorical.categories, columnsSortedByProjectionOrdering);\r\n transformedCategoricalCategories.push(concatenatedCategoryColumn);\r\n\r\n let transformedCategorical: DataViewCategorical = inheritSingle(dataViewCategorical);\r\n transformedCategorical.categories = transformedCategoricalCategories;\r\n transformedDataView.categorical = transformedCategorical;\r\n\r\n return transformedDataView;\r\n }\r\n\r\n function concatenateValues(columnsSortedByProjectionOrdering: DataViewCategoryColumn[], queryRefsToIgnore: string[], formatStringPropId: DataViewObjectPropertyIdentifier): string[] {\r\n debug.assertValue(columnsSortedByProjectionOrdering, 'columnsSortedByProjectionOrdering');\r\n debug.assertAnyValue(queryRefsToIgnore, 'queryRefsToIgnore');\r\n debug.assertAnyValue(formatStringPropId, 'formatStringPropId');\r\n\r\n let concatenatedValues: string[] = [];\r\n\r\n // concatenate the values in dataViewCategorical.categories[0..length-1].values[j], and store it in combinedValues[j]\r\n for (let categoryColumn of columnsSortedByProjectionOrdering) {\r\n let formatString = valueFormatter.getFormatString(categoryColumn.source, formatStringPropId);\r\n\r\n for (let i = 0, len = categoryColumn.values.length; i < len; i++) {\r\n if (!_.contains(queryRefsToIgnore, categoryColumn.source.queryName)) {\r\n let value = categoryColumn.values && categoryColumn.values[i];\r\n let formattedValue = valueFormatter.format(value, formatString);\r\n concatenatedValues[i] = (concatenatedValues[i] === undefined) ? formattedValue : (formattedValue + ' ' + concatenatedValues[i]);\r\n }\r\n }\r\n }\r\n\r\n return concatenatedValues;\r\n }\r\n\r\n /**\r\n * Returns a new array of elements from columns as they are ordered for the specified roleName in the specified projectionOrdering.\r\n */\r\n function sortColumnsByProjectionOrdering(projectionOrdering: DataViewProjectionOrdering, roleName: string, columns: DataViewCategoryColumn[]): DataViewCategoryColumn[] {\r\n debug.assertAnyValue(projectionOrdering, 'projectionOrdering');\r\n debug.assertValue(roleName, 'roleName');\r\n debug.assertValue(columns, 'columns');\r\n\r\n let columnsInProjectionOrdering: DataViewCategoryColumn[];\r\n\r\n if (projectionOrdering) {\r\n // the numeric values in projectionOrdering correspond to the index property of DataViewMetadataColumn\r\n let columnsByIndex: { [index: number]: DataViewCategoricalColumn } = {};\r\n for (let column of columns) {\r\n if (column.source.roles[roleName]) {\r\n debug.assert(!columnsByIndex[column.source.index], 'The specified columns should not contain multiple columns with same index: ' + column.source.index);\r\n columnsByIndex[column.source.index] = column;\r\n }\r\n }\r\n\r\n let columnIndicesInProjectionOrdering: number[] = projectionOrdering[roleName];\r\n\r\n columnsInProjectionOrdering = _.chain(columnIndicesInProjectionOrdering)\r\n .map(columnIndex => columnsByIndex[columnIndex])\r\n .filter((column: DataViewCategoricalColumn) => !!column)\r\n .value();\r\n }\r\n else {\r\n // If projectionOrder is unspecified, just return the columns for the specified role in their current order\r\n columnsInProjectionOrdering = _.filter(columns, column => column.source.roles[roleName]);\r\n }\r\n\r\n return columnsInProjectionOrdering;\r\n }\r\n\r\n /**\r\n * Creates the column metadata that will back the column with the concatenated values. \r\n */\r\n function createConcatenatedColumnMetadata(roleName: string, sourceColumnsSortedByProjectionOrdering: DataViewMetadataColumn[], queryRefsToIgnore?: string[]): DataViewMetadataColumn {\r\n debug.assertValue(roleName, 'roleName');\r\n debug.assertNonEmpty(sourceColumnsSortedByProjectionOrdering, 'sourceColumnsSortedByProjectionOrdering');\r\n debug.assert(_.chain(sourceColumnsSortedByProjectionOrdering).map(c => c.isMeasure).uniq().value().length === 1, 'pre-condition: caller code should not attempt to combine a mix of measure columns and non-measure columns');\r\n\r\n let concatenatedDisplayName: string;\r\n\r\n for (let columnSource of sourceColumnsSortedByProjectionOrdering) {\r\n if (!_.contains(queryRefsToIgnore, columnSource.queryName)) {\r\n concatenatedDisplayName = (concatenatedDisplayName == null) ? columnSource.displayName : (columnSource.displayName + ' ' + concatenatedDisplayName);\r\n }\r\n }\r\n\r\n let newRoles: { [name: string]: boolean } = {};\r\n newRoles[roleName] = true;\r\n\r\n let newColumnMetadata: DataViewMetadataColumn = {\r\n displayName: concatenatedDisplayName,\r\n roles: newRoles,\r\n type: ValueType.fromPrimitiveTypeAndCategory(PrimitiveType.Text)\r\n };\r\n\r\n let columnSourceForCurrentDrillLevel = _.last(sourceColumnsSortedByProjectionOrdering);\r\n if (columnSourceForCurrentDrillLevel.isMeasure !== undefined) {\r\n newColumnMetadata.isMeasure = columnSourceForCurrentDrillLevel.isMeasure;\r\n }\r\n\r\n // TODO VSTS 6842046: Investigate whether we should change that property to mandatory or change the Chart visual code.\r\n // If queryName is not set at all, the column chart visual will only render column for the first group instance.\r\n // If queryName is set to any string other than columnForCurrentDrillLevel.source.queryName, then drilldown by group instance is broken (VSTS 6847879).\r\n newColumnMetadata.queryName = columnSourceForCurrentDrillLevel.queryName;\r\n\r\n return newColumnMetadata;\r\n }\r\n\r\n function addToMetadata(transformedDataView: DataView, newColumn: DataViewMetadataColumn): void {\r\n debug.assertValue(transformedDataView, 'transformedDataView');\r\n debug.assertValue(newColumn, 'newColumn');\r\n\r\n let transformedColumns = inheritSingle(transformedDataView.metadata.columns);\r\n transformedColumns.push(newColumn);\r\n\r\n let transformedMetadata = inheritSingle(transformedDataView.metadata);\r\n transformedMetadata.columns = transformedColumns;\r\n\r\n transformedDataView.metadata = transformedMetadata;\r\n }\r\n\r\n function createConcatenatedCategoryColumn(\r\n sourceColumnsSortedByProjectionOrdering: DataViewCategoryColumn[],\r\n columnMetadata: DataViewMetadataColumn,\r\n concatenatedValues: string[]): DataViewCategoryColumn {\r\n debug.assert(sourceColumnsSortedByProjectionOrdering && sourceColumnsSortedByProjectionOrdering.length >= 2, 'sourceColumnsSortedByProjectionOrdering && sourceColumnsSortedByProjectionOrdering.length >= 2');\r\n\r\n let newCategoryColumn: DataViewCategoryColumn = {\r\n source: columnMetadata,\r\n values: concatenatedValues\r\n };\r\n\r\n // We expect every DataViewCategoryColumn in concatenationSourceColumns to have the same set of identities, always.\r\n // So, we'll just take the identities and identityFields from the first column\r\n let firstColumn = sourceColumnsSortedByProjectionOrdering[0];\r\n\r\n if (firstColumn.identity) {\r\n newCategoryColumn.identity = firstColumn.identity;\r\n }\r\n\r\n if (firstColumn.identityFields) {\r\n newCategoryColumn.identityFields = firstColumn.identityFields;\r\n }\r\n\r\n // It is safe to look at the first column as it is the one that is being set by findSelectedCategoricalColumn\r\n if (firstColumn.objects) {\r\n newCategoryColumn.objects = firstColumn.objects;\r\n }\r\n\r\n return newCategoryColumn;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export const enum RoleItemContext {\r\n CategoricalValue,\r\n CategoricalValueGroup,\r\n }\r\n\r\n export interface IDataViewMappingVisitor {\r\n visitRole(role: string, context?: RoleItemContext): void;\r\n visitReduction?(reductionAlgorithm?: ReductionAlgorithm): void;\r\n }\r\n\r\n export module DataViewMapping {\r\n export function visitMapping(mapping: DataViewMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n let categorical = mapping.categorical;\r\n if (categorical)\r\n visitCategorical(categorical, visitor);\r\n\r\n let table = mapping.table;\r\n if (table)\r\n visitTable(table, visitor);\r\n\r\n let matrix = mapping.matrix;\r\n if (matrix)\r\n visitMatrix(matrix, visitor);\r\n\r\n let tree = mapping.tree;\r\n if (tree)\r\n visitTree(tree, visitor);\r\n \r\n let single = mapping.single;\r\n if (single)\r\n visitSingle(single, visitor);\r\n }\r\n\r\n export function visitCategorical(mapping: DataViewCategoricalMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n visitCategoricalCategories(mapping.categories, visitor);\r\n\r\n visitCategoricalValues(mapping.values, visitor);\r\n }\r\n\r\n export function visitCategoricalCategories(mapping: DataViewRoleMappingWithReduction | DataViewListRoleMappingWithReduction, visitor: IDataViewMappingVisitor): void {\r\n debug.assertAnyValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n if (mapping) {\r\n visitBind(<DataViewRoleBindMapping>mapping, visitor);\r\n visitFor(<DataViewRoleForMapping>mapping, visitor);\r\n visitList(<DataViewListRoleMapping>mapping, visitor);\r\n\r\n visitReduction(mapping, visitor);\r\n }\r\n }\r\n\r\n export function visitCategoricalValues(mapping: DataViewRoleMapping | DataViewGroupedRoleMapping | DataViewListRoleMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertAnyValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n if (mapping) {\r\n visitBind(<DataViewRoleBindMapping>mapping, visitor, RoleItemContext.CategoricalValue);\r\n visitFor(<DataViewRoleForMapping>mapping, visitor, RoleItemContext.CategoricalValue);\r\n visitList(<DataViewListRoleMapping>mapping, visitor, RoleItemContext.CategoricalValue);\r\n\r\n let groupedRoleMapping = <DataViewGroupedRoleMapping>mapping;\r\n visitGrouped(groupedRoleMapping, visitor);\r\n\r\n let group = groupedRoleMapping.group;\r\n if (group) {\r\n for (let item of group.select) {\r\n visitBind(<DataViewRoleBindMapping>item, visitor, RoleItemContext.CategoricalValueGroup);\r\n visitFor(<DataViewRoleForMapping>item, visitor, RoleItemContext.CategoricalValueGroup);\r\n }\r\n }\r\n }\r\n }\r\n\r\n export function visitTable(mapping: DataViewTableMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n let rows = mapping.rows;\r\n visitBind(<DataViewRoleBindMapping>rows, visitor);\r\n visitFor(<DataViewRoleForMapping>rows, visitor);\r\n visitList(<DataViewListRoleMapping>rows, visitor);\r\n\r\n visitReduction(rows, visitor);\r\n }\r\n\r\n function visitMatrix(mapping: DataViewMatrixMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n visitMatrixItems(mapping.rows, visitor);\r\n visitMatrixItems(mapping.columns, visitor);\r\n visitMatrixItems(mapping.values, visitor);\r\n }\r\n\r\n /**\r\n * For visiting DataViewMatrixMapping.rows, DataViewMatrixMapping.columns, or DataViewMatrixMapping.values.\r\n *\r\n * @param mapping Can be one of DataViewMatrixMapping.rows, DataViewMatrixMapping.columns, or DataViewMatrixMapping.values.\r\n * @param visitor The visitor.\r\n */\r\n export function visitMatrixItems(mapping: DataViewRoleForMappingWithReduction | DataViewListRoleMappingWithReduction, visitor: IDataViewMappingVisitor): void {\r\n debug.assertAnyValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n if (mapping) {\r\n visitFor(<DataViewRoleForMapping>mapping, visitor);\r\n visitList(<DataViewListRoleMapping>mapping, visitor);\r\n\r\n visitReduction(mapping, visitor);\r\n }\r\n }\r\n\r\n function visitTree(mapping: DataViewTreeMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n visitTreeNodes(mapping.nodes, visitor);\r\n visitTreeValues(mapping.values, visitor);\r\n }\r\n\r\n export function visitTreeNodes(mapping: DataViewRoleForMappingWithReduction, visitor: IDataViewMappingVisitor): void {\r\n debug.assertAnyValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n if (mapping) {\r\n visitFor(mapping, visitor);\r\n\r\n visitReduction(mapping, visitor);\r\n }\r\n }\r\n\r\n export function visitTreeValues(mapping: DataViewRoleForMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertAnyValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n if (mapping) {\r\n visitFor(mapping, visitor);\r\n }\r\n }\r\n\r\n function visitBind(mapping: DataViewRoleBindMapping, visitor: IDataViewMappingVisitor, context?: RoleItemContext): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n let bind = mapping.bind;\r\n if (bind) {\r\n if (context != null)\r\n visitor.visitRole(bind.to, context);\r\n else\r\n visitor.visitRole(bind.to);\r\n }\r\n }\r\n\r\n function visitFor(mapping: DataViewRoleForMapping, visitor: IDataViewMappingVisitor, context?: RoleItemContext): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n let forValue = mapping.for;\r\n if (forValue) {\r\n if (context != null)\r\n visitor.visitRole(forValue.in, context);\r\n else\r\n visitor.visitRole(forValue.in);\r\n }\r\n }\r\n\r\n function visitList(mapping: DataViewListRoleMapping, visitor: IDataViewMappingVisitor, context?: RoleItemContext): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n let select = mapping.select;\r\n if (select) {\r\n for (let item of select) {\r\n visitBind(<DataViewRoleBindMapping>item, visitor, context);\r\n visitFor(<DataViewRoleForMapping>item, visitor, context);\r\n }\r\n }\r\n }\r\n\r\n export function visitGrouped(mapping: DataViewGroupedRoleMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertAnyValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n if (!mapping)\r\n return;\r\n\r\n let group = mapping.group;\r\n if (group) {\r\n visitor.visitRole(group.by);\r\n\r\n visitReduction(group, visitor);\r\n }\r\n }\r\n\r\n function visitReduction(mapping: HasReductionAlgorithm, visitor: IDataViewMappingVisitor): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n if (visitor.visitReduction) {\r\n let reductionAlgorithm = mapping.dataReductionAlgorithm;\r\n if (reductionAlgorithm) {\r\n visitor.visitReduction(reductionAlgorithm);\r\n }\r\n }\r\n }\r\n\r\n function visitSingle(mapping: DataViewSingleMapping, visitor: IDataViewMappingVisitor): void {\r\n debug.assertValue(mapping, 'mapping');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n visitor.visitRole(mapping.role);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import inheritSingle = Prototype.inheritSingle;\r\n\r\n export interface DataViewNormalizeValuesApplyOptions {\r\n dataview: DataView;\r\n dataViewMappings: DataViewMapping[];\r\n dataRoles: VisualDataRole[];\r\n }\r\n\r\n /**\r\n * Interface of a function for deciding whether a column is tied to any role that has required type(s).\r\n *\r\n * @param columnIndex the position of the column in the select statement, i.e. the same semantic as the index property on the DataViewMetadataColumn interface.\r\n * @returns true iff the column in the specified columnIndex is tied to any role that has required type(s), i.e. if the value in that column potentially needs to get normalized.\r\n */\r\n export interface IMetadataColumnFilter {\r\n (columnIndex: number): boolean;\r\n }\r\n\r\n /**\r\n * Returns true iff the specified value is of matching type as required by the role assigned to the column associated with this filter object.\r\n */\r\n export interface IColumnValueFilter {\r\n (value: any): boolean;\r\n }\r\n\r\n /**\r\n * Interface of a function for deciding whether a value needs to be normalized due to not having a matching type as required by a role tied to the column associated with the specified columnIndex.\r\n *\r\n * @param columnIndex the position of the column in the select statement, i.e. the same semantic as the index property on the DataViewMetadataColumn interface.\r\n * @returns false iff the specified value needs to be normalized due to not having a matching type as required by a role tied to the column associated with the specified columnIndex.\r\n */\r\n export interface IValueFilter {\r\n (columnIndex: number, value: any): boolean;\r\n }\r\n\r\n export module DataViewNormalizeValues {\r\n export function apply(options: DataViewNormalizeValuesApplyOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n let rolesToNormalize = _.filter(options.dataRoles, role => !_.isEmpty(role.requiredTypes));\r\n\r\n filterVariantMeasures(options.dataview, options.dataViewMappings, rolesToNormalize);\r\n }\r\n\r\n export function filterVariantMeasures(dataview: DataView, dataViewMappings: DataViewMapping[], rolesToNormalize: VisualDataRole[]): void {\r\n debug.assertValue(dataview, 'dataview');\r\n\r\n // Don't perform this unless we actually have dataViewMappings and variant measures to suppress\r\n // When we switch to lazy per-visual DataView creation, we'll be able to remove this check.\r\n if (_.isEmpty(dataViewMappings) || _.isEmpty(rolesToNormalize))\r\n return;\r\n\r\n let columnFilter = generateMetadataColumnFilter(dataview.metadata.columns, rolesToNormalize);\r\n let valueFilter = generateValueFilter(dataview.metadata.columns, rolesToNormalize);\r\n\r\n let usedMappings = {};\r\n for (let dataViewMapping of dataViewMappings) {\r\n // Get dataview specified in mappings which are also in dataview\r\n for (let dataViewMappingProp in dataViewMapping) {\r\n if (dataview[dataViewMappingProp] != null)\r\n usedMappings[dataViewMappingProp] = true;\r\n }\r\n }\r\n\r\n if (usedMappings['categorical'])\r\n filterVariantMeasuresCategorical(dataview.categorical, columnFilter, valueFilter);\r\n if (usedMappings['table'])\r\n filterVariantMeasuresTable(dataview.table, columnFilter, valueFilter);\r\n if (usedMappings['tree'])\r\n filterVariantMeasuresTreeNode(dataview.tree.root, columnFilter, valueFilter);\r\n if (usedMappings['matrix'])\r\n filterVariantMeasuresMatrix(dataview.matrix, columnFilter, valueFilter);\r\n if (usedMappings['single'])\r\n filterVariantMeasuresSingle(dataview, dataViewMappings, rolesToNormalize, valueFilter);\r\n }\r\n\r\n export function generateMetadataColumnFilter(columns: DataViewMetadataColumn[], rolesToNormalize: VisualDataRole[]): IMetadataColumnFilter {\r\n if (!columns || !rolesToNormalize)\r\n return () => false;\r\n\r\n let columnsToNormalize = {};\r\n for (let column of columns) {\r\n let roles = column.roles;\r\n if (!roles)\r\n continue;\r\n for (let role of rolesToNormalize) {\r\n if (!roles[role.name])\r\n continue;\r\n columnsToNormalize[column.index] = true;\r\n break;\r\n }\r\n }\r\n\r\n return (columnIndex: number) => {\r\n if (isNaN(columnIndex))\r\n return false;\r\n\r\n return !!columnsToNormalize[columnIndex];\r\n };\r\n }\r\n\r\n export function generateValueFilter(columns: DataViewMetadataColumn[], rolesToNormalize: VisualDataRole[]): IValueFilter {\r\n if (!columns || !rolesToNormalize)\r\n return () => true;\r\n\r\n let columnValueFilters: IColumnValueFilter[] = [];\r\n\r\n // Build columnValueFilters based on role requiredTypes\r\n for (let column of columns) {\r\n let columnValueFilter = generateColumnValueFilter(column, rolesToNormalize);\r\n\r\n if (columnValueFilter)\r\n columnValueFilters[column.index] = columnValueFilter;\r\n }\r\n\r\n return <IValueFilter>(columnIndex: number, value: any) => {\r\n if (columnValueFilters[columnIndex])\r\n return columnValueFilters[columnIndex](value);\r\n\r\n return true;\r\n };\r\n }\r\n\r\n function generateColumnValueFilter(column: DataViewMetadataColumn, rolesToNormalize: VisualDataRole[]): IColumnValueFilter {\r\n let requiredTypes = getColumnRequiredTypes(column, rolesToNormalize);\r\n\r\n if (_.isEmpty(requiredTypes))\r\n return;\r\n\r\n return (value: any): boolean => {\r\n return doesValueMatchTypes(value, requiredTypes);\r\n };\r\n }\r\n\r\n export function getColumnRequiredTypes(column: DataViewMetadataColumn, rolesToNormalize: VisualDataRole[]): ValueType[] {\r\n let requiredTypes = [];\r\n let columnRoles = column && column.roles;\r\n\r\n if (!columnRoles)\r\n return requiredTypes;\r\n\r\n for (let role of rolesToNormalize) {\r\n if (!columnRoles[role.name])\r\n continue;\r\n for (let typeDescriptor of role.requiredTypes) {\r\n let type = ValueType.fromDescriptor(typeDescriptor);\r\n requiredTypes.push(type);\r\n }\r\n }\r\n\r\n return requiredTypes;\r\n }\r\n\r\n function filterVariantMeasuresCategorical(dataview: DataViewCategorical, columnFilter: IMetadataColumnFilter, valueFilter: IValueFilter): void {\r\n let values = dataview && dataview.values;\r\n if (!values)\r\n return;\r\n\r\n let valuesGrouped = values.grouped();\r\n if (!valuesGrouped)\r\n return;\r\n\r\n for (let valueGroup of valuesGrouped) {\r\n let valuesInGroup = valueGroup.values;\r\n for (let valueColumn of valuesInGroup) {\r\n let columnIndex = valueColumn.source.index;\r\n if (!columnFilter(columnIndex))\r\n continue;\r\n\r\n for (let i = 0, ilen = valueColumn.values.length; i < ilen; i++) {\r\n valueColumn.values = normalizeVariant(valueColumn.values, i, columnIndex, valueFilter);\r\n }\r\n }\r\n }\r\n }\r\n\r\n function filterVariantMeasuresTable(dataview: DataViewTable, columnFilter: IMetadataColumnFilter, valueFilter: IValueFilter): void {\r\n let columns = dataview && dataview.columns;\r\n\r\n if (!columns)\r\n return;\r\n\r\n let filteredColumns = [];\r\n for (let column of columns) {\r\n if (columnFilter(column.index))\r\n filteredColumns.push(column.index);\r\n }\r\n\r\n let rows = dataview.rows;\r\n for (let i = 0, ilen = rows.length; i < ilen; i++) {\r\n for (let index of filteredColumns) {\r\n rows[i] = normalizeVariant(rows[i], index, index, valueFilter);\r\n }\r\n }\r\n }\r\n\r\n function filterVariantMeasuresTreeNode(node: DataViewTreeNode, columnFilter: IMetadataColumnFilter, valueFilter: IValueFilter): void {\r\n if (node.values) {\r\n for (let columnIndex in node.values) {\r\n // In dataView.tree, the keys in node.values correspond to columnIndex of the node value\r\n if (columnFilter(<any>columnIndex)) {\r\n // According to nojorgen, it is possible to have primitive values as values in the node.values dictionary.\r\n if (typeof (node.values[columnIndex]) === 'object' && ('value' in node.values[columnIndex]))\r\n node.values[columnIndex] = normalizeVariant(node.values[columnIndex], 'value', <any>columnIndex, valueFilter);\r\n else // if node.values[columnIndex] is a primitive value\r\n node.values = normalizeVariant(node.values, columnIndex, <any>columnIndex, valueFilter);\r\n }\r\n }\r\n }\r\n else if (node.children) {\r\n for (let child of node.children) {\r\n filterVariantMeasuresTreeNode(child, columnFilter, valueFilter);\r\n }\r\n }\r\n }\r\n\r\n function filterVariantMeasuresMatrix(dataview: DataViewMatrix, columnFilter: IMetadataColumnFilter, valueFilter: IValueFilter): void {\r\n let root = dataview && dataview.rows && dataview.rows.root;\r\n\r\n if (!root)\r\n return;\r\n\r\n // Recurse into rows.children\r\n // e.g. rows.children -> .children -> .children.values\r\n filterVariantMeasuresMatrixRecursive(dataview, root, columnFilter, valueFilter);\r\n }\r\n\r\n function filterVariantMeasuresMatrixRecursive(dataviewMatrix: DataViewMatrix, node: DataViewTreeNode, columnFilter: IMetadataColumnFilter, valueFilter: IValueFilter): void {\r\n if (node.values) {\r\n for (let id in node.values) {\r\n // Note related to VSTS 6547124: In dataView.matrix, the keys in node.values are NOT equivalent to value.valueSourceIndex.\r\n let nodeValue: DataViewMatrixNodeValue = node.values[id];\r\n\r\n // the property DataViewMatrixNodeValue.valueSourceIndex will not exist if valueSourceIndex is 0 for that value\r\n let valueSourceIndex: number = nodeValue.valueSourceIndex || 0;\r\n\r\n // index is an optional property on DataViewMetadataColumn, but I am not sure when it will ever be undefined in a matrix' column metadata\r\n let columnIndex = dataviewMatrix.valueSources[valueSourceIndex].index;\r\n\r\n if (_.isNumber(columnIndex) && columnFilter(columnIndex)) {\r\n node.values[id] = normalizeVariant(nodeValue, 'value', columnIndex, valueFilter);\r\n }\r\n }\r\n }\r\n else if (node.children) {\r\n for (let child of node.children) {\r\n filterVariantMeasuresMatrixRecursive(dataviewMatrix, child, columnFilter, valueFilter);\r\n }\r\n }\r\n }\r\n\r\n function filterVariantMeasuresSingle(dataview: DataView, dataViewMappings: DataViewMapping[], rolesToNormalize: VisualDataRole[], valueFilter: IValueFilter): void {\r\n if (!dataview.single)\r\n return;\r\n\r\n let roleNames: string[] = [];\r\n for (let role of rolesToNormalize) {\r\n if (role.name)\r\n roleNames.push(role.name);\r\n }\r\n\r\n let columns = dataview.metadata.columns;\r\n for (let dataViewMapping of dataViewMappings) {\r\n let roleName = dataViewMapping.single.role;\r\n if (roleNames.indexOf(roleName) !== -1) {\r\n let column = firstColumnByRoleName(columns, roleName);\r\n if (column)\r\n dataview.single = normalizeVariant(dataview.single, 'value', column.index, valueFilter);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n export function normalizeVariant<T>(object: T, key: string|number, columnIndex: number, valueFilter: IValueFilter): T {\r\n if (!object)\r\n return;\r\n\r\n let value = object[key];\r\n if (value !== null && !valueFilter(columnIndex, value)) {\r\n object = inheritSingle(object);\r\n object[key] = null;\r\n }\r\n\r\n return object;\r\n }\r\n\r\n function doesValueMatchTypes<T>(value: T, types: ValueType[]): boolean {\r\n for (let type of types) {\r\n if (type.numeric || type.integer)\r\n return typeof (value) === 'number';\r\n }\r\n\r\n return false;\r\n }\r\n\r\n function firstColumnByRoleName(columns: DataViewMetadataColumn[], roleName: string): DataViewMetadataColumn {\r\n for (let column of columns) {\r\n let columnRoles = column && column.roles;\r\n if (columnRoles && columnRoles[roleName])\r\n return column;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n export module DataViewObjects {\r\n /** Gets the value of the given object/property pair. */\r\n export function getValue<T>(objects: DataViewObjects, propertyId: DataViewObjectPropertyIdentifier, defaultValue?: T): T {\r\n debug.assertAnyValue(objects, 'objects');\r\n debug.assertValue(propertyId, 'propertyId');\r\n\r\n if (!objects)\r\n return defaultValue;\r\n\r\n let objectOrMap = objects[propertyId.objectName];\r\n debug.assert(!isUserDefined(objectOrMap), 'expected DataViewObject');\r\n\r\n let object = <DataViewObject>objectOrMap;\r\n return DataViewObject.getValue(object, propertyId.propertyName, defaultValue);\r\n }\r\n\r\n /** Gets an object from objects. */\r\n export function getObject(objects: DataViewObjects, objectName: string, defaultValue?: DataViewObject): DataViewObject {\r\n if (objects && objects[objectName]) {\r\n let object = <DataViewObject>objects[objectName];\r\n debug.assert(!isUserDefined(object), 'expected DataViewObject');\r\n return object;\r\n }\r\n else {\r\n return defaultValue;\r\n }\r\n }\r\n\r\n /** Gets a map of user-defined objects. */\r\n export function getUserDefinedObjects(objects: DataViewObjects, objectName: string): DataViewObjectMap {\r\n if (objects && objects[objectName]) {\r\n let map = <DataViewObjectMap>objects[objectName];\r\n debug.assert(isUserDefined(map), 'expected DataViewObjectMap');\r\n return map;\r\n }\r\n }\r\n\r\n /** Gets the solid color from a fill property. */\r\n export function getFillColor(objects: DataViewObjects, propertyId: DataViewObjectPropertyIdentifier, defaultColor?: string): string {\r\n let value: Fill = getValue(objects, propertyId);\r\n if (!value || !value.solid)\r\n return defaultColor;\r\n\r\n return value.solid.color;\r\n }\r\n\r\n /** Returns true if the given object represents a collection of user-defined objects */\r\n export function isUserDefined(objectOrMap: DataViewObject | DataViewObjectMap): boolean {\r\n return _.isArray(objectOrMap);\r\n }\r\n }\r\n\r\n export module DataViewObject {\r\n export function getValue<T>(object: DataViewObject, propertyName: string, defaultValue?: T): T {\r\n debug.assertAnyValue(object, 'object');\r\n debug.assertValue(propertyName, 'propertyName');\r\n\r\n if (!object)\r\n return defaultValue;\r\n\r\n let propertyValue = <T>object[propertyName];\r\n if (propertyValue === undefined)\r\n return defaultValue;\r\n\r\n return propertyValue;\r\n }\r\n\r\n /** Gets the solid color from a fill property using only a propertyName */\r\n export function getFillColorByPropertyName(objects: DataViewObjects, propertyName: string, defaultColor?: string): string {\r\n let value: Fill = DataViewObject.getValue(objects, propertyName);\r\n if (!value || !value.solid)\r\n return defaultColor;\r\n\r\n return value.solid.color;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import JsonComparer = jsCommon.JsonComparer;\r\n\r\n /** Defines the values for particular objects. */\r\n export interface DataViewObjectDefinitions {\r\n [objectName: string]: DataViewObjectDefinition[];\r\n }\r\n\r\n export interface DataViewObjectDefinition {\r\n selector?: Selector;\r\n properties: DataViewObjectPropertyDefinitions;\r\n }\r\n\r\n export interface DataViewObjectPropertyDefinitions {\r\n [name: string]: DataViewObjectPropertyDefinition;\r\n }\r\n\r\n export type DataViewObjectPropertyDefinition = SQExpr | StructuralObjectDefinition;\r\n\r\n export module DataViewObjectDefinitions {\r\n\r\n /** Creates or reuses a DataViewObjectDefinition for matching the given objectName and selector within the defns. */\r\n export function ensure(\r\n defns: DataViewObjectDefinitions,\r\n objectName: string,\r\n selector: Selector): DataViewObjectDefinition {\r\n debug.assertValue(defns, 'defns');\r\n\r\n let defnsForObject = defns[objectName];\r\n if (!defnsForObject)\r\n defns[objectName] = defnsForObject = [];\r\n\r\n for (let i = 0, len = defnsForObject.length; i < len; i++) {\r\n let defn = defnsForObject[i];\r\n if (Selector.equals(defn.selector, selector))\r\n return defn;\r\n }\r\n\r\n let newDefn: DataViewObjectDefinition = {\r\n selector: selector,\r\n properties: {},\r\n };\r\n defnsForObject.push(newDefn);\r\n\r\n return newDefn;\r\n }\r\n\r\n export function deleteProperty(\r\n defns: DataViewObjectDefinitions,\r\n objectName: string,\r\n selector: Selector,\r\n propertyName: string): void {\r\n debug.assertValue(defns, 'defns');\r\n\r\n let defn = getObjectDefinition(defns, objectName, selector);\r\n if (!defn)\r\n return;\r\n\r\n DataViewObjectDefinition.deleteSingleProperty(defn, propertyName);\r\n }\r\n \r\n export function setValue(\r\n defns: DataViewObjectDefinitions,\r\n propertyId: DataViewObjectPropertyIdentifier,\r\n selector: Selector,\r\n value: DataViewObjectPropertyDefinition): void {\r\n debug.assertValue(defns, 'defns');\r\n debug.assertValue(propertyId, 'propertyId');\r\n\r\n ensure(defns, propertyId.objectName, selector).properties[propertyId.propertyName] = value;\r\n }\r\n\r\n export function getValue(\r\n defns: DataViewObjectDefinitions,\r\n propertyId: DataViewObjectPropertyIdentifier,\r\n selector: Selector): DataViewObjectPropertyDefinition {\r\n\r\n let properties = getPropertyContainer(defns, propertyId, selector);\r\n if (!properties)\r\n return;\r\n\r\n return properties[propertyId.propertyName];\r\n }\r\n\r\n export function getPropertyContainer(\r\n defns: DataViewObjectDefinitions,\r\n propertyId: DataViewObjectPropertyIdentifier,\r\n selector: Selector): DataViewObjectPropertyDefinitions {\r\n\r\n let defn = getObjectDefinition(defns, propertyId.objectName, selector);\r\n if (!defn)\r\n return;\r\n\r\n return defn.properties;\r\n }\r\n\r\n export function getObjectDefinition(\r\n defns: DataViewObjectDefinitions,\r\n objectName: string,\r\n selector: Selector): DataViewObjectDefinition {\r\n debug.assertAnyValue(defns, 'defns');\r\n debug.assertValue(objectName, 'objectName');\r\n debug.assertAnyValue(selector, 'selector');\r\n\r\n if (!defns)\r\n return;\r\n\r\n let defnsForObject = defns[objectName];\r\n if (!defnsForObject)\r\n return;\r\n\r\n for (let i = 0, len = defnsForObject.length; i < len; i++) {\r\n let defn = defnsForObject[i];\r\n if (Selector.equals(defn.selector, selector))\r\n return defn;\r\n }\r\n }\r\n\r\n export function propertiesAreEqual(a: DataViewObjectPropertyDefinition, b: DataViewObjectPropertyDefinition): boolean {\r\n if (a instanceof SemanticFilter && b instanceof SemanticFilter) {\r\n return SemanticFilter.isSameFilter(<SemanticFilter>a, <SemanticFilter>b);\r\n }\r\n\r\n return JsonComparer.equals(a, b);\r\n }\r\n\r\n export function allPropertiesAreEqual(a: DataViewObjectPropertyDefinitions, b: DataViewObjectPropertyDefinitions): boolean {\r\n debug.assertValue(a, 'a');\r\n debug.assertValue(b, 'b');\r\n\r\n if (Object.keys(a).length !== Object.keys(b).length)\r\n return false;\r\n\r\n for (let property in a) {\r\n if (!propertiesAreEqual(a[property], b[property]))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n export function encodePropertyValue(value: DataViewPropertyValue, valueTypeDescriptor: ValueTypeDescriptor): DataViewObjectPropertyDefinition {\r\n debug.assertAnyValue(value, 'value');\r\n debug.assertValue(valueTypeDescriptor, 'valueTypeDescriptor');\r\n\r\n if (valueTypeDescriptor.bool) {\r\n if (typeof (value) !== 'boolean')\r\n value = false; // This is fallback, which doesn't really belong here.\r\n\r\n return SQExprBuilder.boolean(<boolean>value);\r\n }\r\n else if (valueTypeDescriptor.text || (valueTypeDescriptor.scripting && valueTypeDescriptor.scripting.source)) {\r\n return SQExprBuilder.text(<string>value);\r\n }\r\n else if (valueTypeDescriptor.numeric) {\r\n if ($.isNumeric(value))\r\n return SQExprBuilder.double(+value);\r\n }\r\n else if ((<StructuralTypeDescriptor>valueTypeDescriptor).fill) {\r\n if (value) {\r\n return {\r\n solid: { color: SQExprBuilder.text(<string>value) }\r\n };\r\n }\r\n }\r\n else if (valueTypeDescriptor.formatting) {\r\n if (valueTypeDescriptor.formatting.labelDisplayUnits) {\r\n return SQExprBuilder.double(+value);\r\n }\r\n else {\r\n return SQExprBuilder.text(<string>value);\r\n }\r\n }\r\n else if (valueTypeDescriptor.enumeration) {\r\n if ($.isNumeric(value))\r\n return SQExprBuilder.double(+value);\r\n else\r\n return SQExprBuilder.text(<string>value);\r\n }\r\n else if (valueTypeDescriptor.misc) {\r\n if (value) {\r\n value = SQExprBuilder.text(<string>value);\r\n } else {\r\n value = null;\r\n }\r\n }\r\n else if ((<StructuralTypeDescriptor>valueTypeDescriptor).image) {\r\n if (value) {\r\n let imageValue = <ImageValue>value;\r\n let imageDefinition: ImageDefinition = {\r\n name: SQExprBuilder.text(imageValue.name),\r\n url: SQExprBuilder.text(imageValue.url),\r\n };\r\n\r\n if (imageValue.scaling)\r\n imageDefinition.scaling = SQExprBuilder.text(imageValue.scaling);\r\n\r\n return imageDefinition;\r\n }\r\n }\r\n\r\n return value;\r\n }\r\n\r\n export function clone(original: DataViewObjectDefinitions): DataViewObjectDefinitions {\r\n debug.assertValue(original, 'original');\r\n\r\n let cloned: DataViewObjectDefinitions = {};\r\n\r\n for (let objectName in original) {\r\n let originalDefns = original[objectName];\r\n if (_.isEmpty(originalDefns))\r\n continue;\r\n\r\n let clonedDefns: DataViewObjectDefinition[] = [];\r\n for (let originalDefn of originalDefns) {\r\n clonedDefns.push({\r\n properties: cloneProperties(originalDefn.properties),\r\n selector: originalDefn.selector,\r\n });\r\n }\r\n cloned[objectName] = clonedDefns;\r\n }\r\n\r\n return cloned;\r\n }\r\n\r\n function cloneProperties(original: DataViewObjectPropertyDefinitions): DataViewObjectPropertyDefinitions {\r\n debug.assertValue(original, 'original');\r\n\r\n // NOTE: properties are considered atomic, so a shallow clone is appropriate here.\r\n return _.clone(original);\r\n }\r\n }\r\n\r\n export module DataViewObjectDefinition {\r\n\r\n export function deleteSingleProperty(\r\n defn: DataViewObjectDefinition,\r\n propertyName: string): void {\r\n\r\n //note: We decided that delete is acceptable here and that we don't need optimization here\r\n delete defn.properties[propertyName];\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n export module DataViewObjectDescriptors {\r\n /** Attempts to find the format string property. This can be useful for upgrade and conversion. */\r\n export function findFormatString(descriptors: DataViewObjectDescriptors): DataViewObjectPropertyIdentifier {\r\n return findProperty(\r\n descriptors,\r\n (propDesc: DataViewObjectPropertyDescriptor) => {\r\n let formattingTypeDesc = ValueType.fromDescriptor(propDesc.type).formatting;\r\n return formattingTypeDesc && formattingTypeDesc.formatString;\r\n });\r\n }\r\n\r\n /** Attempts to find the filter property. This can be useful for propagating filters from one visual to others. */\r\n export function findFilterOutput(descriptors: DataViewObjectDescriptors): DataViewObjectPropertyIdentifier {\r\n return findProperty(\r\n descriptors,\r\n (propDesc: DataViewObjectPropertyDescriptor) => {\r\n let propType: StructuralTypeDescriptor = propDesc.type;\r\n return propType && !!propType.filter;\r\n });\r\n }\r\n\r\n /** Attempts to find the default value property. This can be useful for propagating schema default value. */\r\n export function findDefaultValue(descriptors: DataViewObjectDescriptors): DataViewObjectPropertyIdentifier {\r\n return findProperty(\r\n descriptors,\r\n (propDesc: DataViewObjectPropertyDescriptor) => {\r\n let propType: StructuralTypeDescriptor = propDesc.type;\r\n return propType && !!propType.expression && propType.expression.defaultValue;\r\n });\r\n }\r\n\r\n function findProperty(descriptors: DataViewObjectDescriptors, propPredicate: (propDesc: DataViewObjectPropertyDescriptor) => boolean): DataViewObjectPropertyIdentifier {\r\n debug.assertAnyValue(descriptors, 'descriptors');\r\n debug.assertAnyValue(propPredicate, 'propPredicate');\r\n\r\n if (!descriptors)\r\n return;\r\n\r\n for (let objectName in descriptors) {\r\n let objPropDescs = descriptors[objectName].properties;\r\n\r\n for (let propertyName in objPropDescs) {\r\n if (propPredicate(objPropDescs[propertyName])) {\r\n return {\r\n objectName: objectName,\r\n propertyName: propertyName,\r\n };\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n * MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n* \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.data {\r\n export interface DataViewObjectDefinitionsByRepetition {\r\n metadataOnce?: DataViewObjectDefinitionsForSelector;\r\n userDefined?: DataViewObjectDefinitionsForSelector[];\r\n metadata?: DataViewObjectDefinitionsForSelector[];\r\n data: DataViewObjectDefinitionsForSelectorWithRule[];\r\n }\r\n\r\n export interface DataViewObjectDefinitionsForSelector {\r\n selector?: Selector;\r\n objects: DataViewNamedObjectDefinition[];\r\n }\r\n\r\n export interface DataViewObjectDefinitionsForSelectorWithRule extends DataViewObjectDefinitionsForSelector {\r\n rules?: RuleEvaluation[];\r\n }\r\n\r\n export interface DataViewNamedObjectDefinition {\r\n name: string;\r\n properties: DataViewObjectPropertyDefinitions;\r\n }\r\n\r\n export module DataViewObjectEvaluationUtils {\r\n export function evaluateDataViewObjects(\r\n evalContext: IEvalContext,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n objectDefns: DataViewNamedObjectDefinition[]): DataViewObjects {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n\r\n let objects: DataViewObjects;\r\n\r\n for (let j = 0, jlen = objectDefns.length; j < jlen; j++) {\r\n let objectDefinition = objectDefns[j],\r\n objectName = objectDefinition.name;\r\n\r\n let evaluatedObject: DataViewObject = DataViewObjectEvaluator.run(\r\n evalContext,\r\n objectDescriptors[objectName],\r\n objectDefinition.properties);\r\n\r\n if (!evaluatedObject)\r\n continue;\r\n\r\n if (!objects)\r\n objects = {};\r\n\r\n // NOTE: this currently has last-object-wins semantics.\r\n objects[objectName] = evaluatedObject;\r\n }\r\n\r\n return objects;\r\n }\r\n\r\n export function groupObjectsBySelector(objectDefinitions: DataViewObjectDefinitions): DataViewObjectDefinitionsByRepetition {\r\n debug.assertAnyValue(objectDefinitions, 'objectDefinitions');\r\n\r\n let grouped: DataViewObjectDefinitionsByRepetition = {\r\n data: [],\r\n };\r\n\r\n if (objectDefinitions) {\r\n for (let objectName in objectDefinitions) {\r\n let objectDefnList = objectDefinitions[objectName];\r\n\r\n for (let i = 0, len = objectDefnList.length; i < len; i++) {\r\n let objectDefn = objectDefnList[i];\r\n\r\n ensureDefinitionListForSelector(grouped, objectDefn.selector).objects.push({\r\n name: objectName,\r\n properties: objectDefn.properties,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return grouped;\r\n }\r\n\r\n function ensureDefinitionListForSelector(grouped: DataViewObjectDefinitionsByRepetition, selector: Selector): DataViewObjectDefinitionsForSelector {\r\n debug.assertValue(grouped, 'grouped');\r\n debug.assertAnyValue(selector, 'selector');\r\n\r\n if (!selector) {\r\n if (!grouped.metadataOnce)\r\n grouped.metadataOnce = { objects: [] };\r\n return grouped.metadataOnce;\r\n }\r\n\r\n let groupedObjects: DataViewObjectDefinitionsForSelector[];\r\n if (selector.data) {\r\n groupedObjects = grouped.data;\r\n }\r\n else if (selector.metadata) {\r\n if (!grouped.metadata)\r\n grouped.metadata = [];\r\n groupedObjects = grouped.metadata;\r\n }\r\n else if (selector.id) {\r\n if (!grouped.userDefined)\r\n grouped.userDefined = [];\r\n groupedObjects = grouped.userDefined;\r\n }\r\n\r\n debug.assert(!!groupedObjects, 'GroupedObjects is not defined. Indicates malformed selector.');\r\n\r\n for (let item of groupedObjects) {\r\n if (Selector.equals(selector, item.selector))\r\n return item;\r\n }\r\n\r\n let item: DataViewObjectDefinitionsForSelector = {\r\n selector: selector,\r\n objects: [],\r\n };\r\n groupedObjects.push(item);\r\n\r\n return item;\r\n }\r\n\r\n export function addImplicitObjects(\r\n objectsForAllSelectors: DataViewObjectDefinitionsByRepetition,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n columns: DataViewMetadataColumn[],\r\n selectTransforms: DataViewSelectTransform[]): void {\r\n debug.assertValue(objectsForAllSelectors, 'objectsForAllSelectors');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(columns, 'columns');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n\r\n if (selectTransforms) {\r\n addDefaultFormatString(objectsForAllSelectors, objectDescriptors, columns, selectTransforms);\r\n addDefaultValue(objectsForAllSelectors, objectDescriptors, columns, selectTransforms);\r\n }\r\n }\r\n\r\n function addDefaultFormatString(\r\n objectsForAllSelectors: DataViewObjectDefinitionsByRepetition,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n columns: DataViewMetadataColumn[],\r\n selectTransforms: DataViewSelectTransform[]): void {\r\n debug.assertValue(objectsForAllSelectors, 'objectsForAllSelectors');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(columns, 'columns');\r\n debug.assertValue(selectTransforms, 'selectTransforms');\r\n\r\n let formatStringProp = DataViewObjectDescriptors.findFormatString(objectDescriptors);\r\n if (!formatStringProp)\r\n return;\r\n\r\n for (let selectIdx = 0, selectLen = selectTransforms.length; selectIdx < selectLen; selectIdx++) {\r\n let selectTransform = selectTransforms[selectIdx];\r\n if (!selectTransform)\r\n continue;\r\n debug.assertValue(selectTransform.queryName, 'selectTransform.queryName');\r\n\r\n applyFormatString(\r\n objectsForAllSelectors,\r\n formatStringProp,\r\n selectTransform.queryName,\r\n selectTransform.format || getColumnFormatForIndex(columns, selectIdx));\r\n }\r\n }\r\n\r\n /** Registers properties for default value, if the properties are not explicitly provided. */\r\n function addDefaultValue (\r\n objectsForAllSelectors: DataViewObjectDefinitionsByRepetition,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n columns: DataViewMetadataColumn[],\r\n selectTransforms: DataViewSelectTransform[]): void {\r\n debug.assertValue(objectsForAllSelectors, 'objectsForAllSelectors');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(columns, 'columns');\r\n debug.assertValue(selectTransforms, 'selectTransforms');\r\n\r\n let defaultValueProp = DataViewObjectDescriptors.findDefaultValue(objectDescriptors);\r\n if (!defaultValueProp)\r\n return;\r\n\r\n for (let selectTransform of selectTransforms) {\r\n if (!selectTransform)\r\n continue;\r\n debug.assertValue(selectTransform.queryName, 'selectTransform.queryName');\r\n\r\n applyDefaultValue(\r\n objectsForAllSelectors,\r\n defaultValueProp,\r\n selectTransform.queryName,\r\n selectTransform.defaultValue);\r\n }\r\n }\r\n\r\n function getColumnFormatForIndex(columns: DataViewMetadataColumn[], selectIdx: number): string {\r\n for (let columnIdx = 0, columnLen = columns.length; columnIdx < columnLen; columnIdx++) {\r\n let column = columns[columnIdx];\r\n if (!column || column.index !== selectIdx)\r\n continue;\r\n\r\n return column.format;\r\n }\r\n }\r\n\r\n function applyFormatString(\r\n objectsForAllSelectors: DataViewObjectDefinitionsByRepetition,\r\n formatStringProp: DataViewObjectPropertyIdentifier,\r\n queryName: string,\r\n formatStringValue: string): void {\r\n if (!formatStringValue)\r\n return;\r\n\r\n // There is a format string specified -- apply it as an object property, if there is not already one specified.\r\n applyMetadataProperty(\r\n objectsForAllSelectors,\r\n formatStringProp,\r\n { metadata: queryName },\r\n SQExprBuilder.text(formatStringValue));\r\n }\r\n\r\n function applyDefaultValue(\r\n objectsForAllSelectors: DataViewObjectDefinitionsByRepetition,\r\n defaultValueProp: DataViewObjectPropertyIdentifier,\r\n queryName: string,\r\n defaultValue: DefaultValueDefinition): void {\r\n if (!defaultValue)\r\n return;\r\n\r\n // There is a default value specified -- apply it as an object property, if there is not already one specified.\r\n applyMetadataProperty(\r\n objectsForAllSelectors,\r\n defaultValueProp,\r\n { metadata: queryName },\r\n defaultValue);\r\n }\r\n\r\n function applyMetadataProperty(\r\n objectsForAllSelectors: DataViewObjectDefinitionsByRepetition,\r\n propertyId: DataViewObjectPropertyIdentifier,\r\n selector: Selector,\r\n value: DataViewObjectPropertyDefinition): void {\r\n\r\n let objectDefns: DataViewObjectDefinitionsForSelector[];\r\n if (selector) {\r\n let metadataObjects = objectsForAllSelectors.metadata;\r\n if (!metadataObjects)\r\n metadataObjects = objectsForAllSelectors.metadata = [];\r\n objectDefns = metadataObjects;\r\n }\r\n else {\r\n let metadataOnce = objectsForAllSelectors.metadataOnce;\r\n if (!metadataOnce)\r\n metadataOnce = objectsForAllSelectors.metadataOnce = { selector: selector, objects: [] };\r\n objectDefns = [metadataOnce];\r\n }\r\n\r\n let targetMetadataObject = findWithMatchingSelector(objectDefns, selector);\r\n let targetObjectDefn: DataViewNamedObjectDefinition;\r\n if (targetMetadataObject) {\r\n let targetObjectDefns = targetMetadataObject.objects;\r\n targetObjectDefn = findExistingObject(targetObjectDefns, propertyId.objectName);\r\n if (targetObjectDefn) {\r\n if (targetObjectDefn.properties[propertyId.propertyName])\r\n return;\r\n }\r\n else {\r\n targetObjectDefn = {\r\n name: propertyId.objectName,\r\n properties: {},\r\n };\r\n targetObjectDefns.push(targetObjectDefn);\r\n }\r\n }\r\n else {\r\n targetObjectDefn = {\r\n name: propertyId.objectName,\r\n properties: {}\r\n };\r\n\r\n objectDefns.push({\r\n selector: selector,\r\n objects: [targetObjectDefn],\r\n });\r\n }\r\n\r\n targetObjectDefn.properties[propertyId.propertyName] = value;\r\n }\r\n\r\n function findWithMatchingSelector(objects: DataViewObjectDefinitionsForSelector[], selector: Selector): DataViewObjectDefinitionsForSelector {\r\n debug.assertValue(objects, 'objects');\r\n debug.assertAnyValue(selector, 'selector');\r\n\r\n for (let i = 0, len = objects.length; i < len; i++) {\r\n let object = objects[i];\r\n if (Selector.equals(object.selector, selector))\r\n return object;\r\n }\r\n }\r\n\r\n function findExistingObject(objectDefns: DataViewNamedObjectDefinition[], objectName: string): DataViewNamedObjectDefinition {\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(objectName, 'objectName');\r\n\r\n for (let i = 0, len = objectDefns.length; i < len; i++) {\r\n let objectDefn = objectDefns[i];\r\n\r\n if (objectDefn.name === objectName)\r\n return objectDefn;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n \r\n\r\nmodule powerbi.data {\r\n /** Responsible for evaluating object property expressions to be applied at various scopes in a DataView. */\r\n export module DataViewObjectEvaluator {\r\n const colorValueType: ValueType = ValueType.fromDescriptor({ formatting: { color: true } });\r\n const numericType: ValueType = ValueType.fromDescriptor({ numeric: true });\r\n const textType: ValueType = ValueType.fromDescriptor({ text: true });\r\n\r\n export function run(\r\n evalContext: IEvalContext,\r\n objectDescriptor: DataViewObjectDescriptor,\r\n propertyDefinitions: DataViewObjectPropertyDefinitions): DataViewObject {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertAnyValue(objectDescriptor, 'objectDescriptor');\r\n debug.assertValue(propertyDefinitions, 'propertyDefinitions');\r\n\r\n if (!objectDescriptor)\r\n return;\r\n\r\n let object: DataViewObject,\r\n propertyDescriptors = objectDescriptor.properties;\r\n for (let propertyName in propertyDefinitions) {\r\n let propertyDefinition = propertyDefinitions[propertyName],\r\n propertyDescriptor = propertyDescriptors[propertyName];\r\n\r\n if (!propertyDescriptor)\r\n continue;\r\n\r\n let propertyValue = evaluateProperty(evalContext, propertyDescriptor, propertyDefinition);\r\n if (propertyValue === undefined)\r\n continue;\r\n\r\n if (!object)\r\n object = {};\r\n object[propertyName] = propertyValue;\r\n }\r\n\r\n return object;\r\n }\r\n\r\n /** Note: Exported for testability */\r\n export function evaluateProperty(\r\n evalContext: IEvalContext,\r\n propertyDescriptor: DataViewObjectPropertyDescriptor,\r\n propertyDefinition: DataViewObjectPropertyDefinition): any {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(propertyDescriptor, 'propertyDescriptor');\r\n debug.assertValue(propertyDefinition, 'propertyDefinition');\r\n\r\n let structuralType = <StructuralTypeDescriptor>propertyDescriptor.type;\r\n if (structuralType && structuralType.expression)\r\n return propertyDefinition;\r\n\r\n let value = evaluateValue(evalContext, <any>propertyDefinition, ValueType.fromDescriptor(propertyDescriptor.type));\r\n if (value !== undefined || (propertyDefinition instanceof RuleEvaluation))\r\n return value;\r\n\r\n return evaluateFill(evalContext, <FillDefinition>propertyDefinition, structuralType)\r\n || evaluateFillRule(evalContext, <FillRuleDefinition>propertyDefinition, structuralType)\r\n || evaluateImage(evalContext, <ImageDefinition>propertyDefinition, structuralType)\r\n || evaluateParagraphs(evalContext, <ParagraphsDefinition>propertyDefinition, structuralType)\r\n || propertyDefinition;\r\n }\r\n\r\n function evaluateFill(evalContext: IEvalContext, fillDefn: FillDefinition, type: StructuralTypeDescriptor): Fill {\r\n let fillType = type.fill;\r\n if (!fillType)\r\n return;\r\n\r\n if (fillType && fillType.solid && fillType.solid.color && fillDefn.solid) {\r\n return {\r\n solid: {\r\n color: evaluateValue(evalContext, fillDefn.solid.color, ValueType.fromExtendedType(ExtendedType.Color)),\r\n }\r\n };\r\n }\r\n }\r\n\r\n function evaluateFillRule(evalContext: IEvalContext, fillRuleDefn: FillRuleDefinition, type: StructuralTypeDescriptor): FillRule {\r\n if (!type.fillRule)\r\n return;\r\n\r\n if (fillRuleDefn.linearGradient2) {\r\n let linearGradient2 = fillRuleDefn.linearGradient2;\r\n return {\r\n linearGradient2: {\r\n min: evaluateColorStop(evalContext, linearGradient2.min),\r\n max: evaluateColorStop(evalContext, linearGradient2.max),\r\n }\r\n };\r\n }\r\n\r\n if (fillRuleDefn.linearGradient3) {\r\n let linearGradient3 = fillRuleDefn.linearGradient3;\r\n return {\r\n linearGradient3: {\r\n min: evaluateColorStop(evalContext, linearGradient3.min),\r\n mid: evaluateColorStop(evalContext, linearGradient3.mid),\r\n max: evaluateColorStop(evalContext, linearGradient3.max),\r\n }\r\n };\r\n }\r\n }\r\n\r\n function evaluateColorStop(evalContext: IEvalContext, colorStop: RuleColorStopDefinition): RuleColorStop {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(colorStop, 'colorStop');\r\n\r\n let step: RuleColorStop = {\r\n color: evaluateValue(evalContext, colorStop.color, colorValueType),\r\n };\r\n\r\n let value = evaluateValue(evalContext, colorStop.value, numericType);\r\n if (value != null)\r\n step.value = value;\r\n\r\n return step;\r\n }\r\n\r\n function evaluateImage(evalContext: IEvalContext, definition: ImageDefinition, type: StructuralTypeDescriptor): ImageValue {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertAnyValue(definition, 'definition');\r\n debug.assertValue(type, 'type');\r\n\r\n if (!type.image || !definition)\r\n return;\r\n\r\n let value: ImageValue = {\r\n name: evaluateValue(evalContext, definition.name, textType),\r\n url: evaluateValue(evalContext, definition.url, ValueType.fromDescriptor(ImageDefinition.urlType)),\r\n };\r\n\r\n if (definition.scaling)\r\n value.scaling = evaluateValue(evalContext, definition.scaling, textType);\r\n\r\n return value;\r\n }\r\n\r\n function evaluateParagraphs(evalContext: IEvalContext, definition: ParagraphsDefinition, type: StructuralTypeDescriptor): Paragraphs {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertAnyValue(definition, 'definition');\r\n debug.assertValue(type, 'type');\r\n\r\n if (!type.paragraphs || !definition)\r\n return;\r\n\r\n return evaluateArrayCopyOnChange(evalContext, definition, evaluateParagraph);\r\n }\r\n\r\n function evaluateParagraph(evalContext: IEvalContext, definition: ParagraphDefinition): Paragraph {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(definition, 'definition');\r\n\r\n let evaluated: Paragraph;\r\n\r\n let definitionTextRuns = definition.textRuns;\r\n let evaluatedTextRuns: TextRun[] = evaluateArrayCopyOnChange(evalContext, definitionTextRuns, evaluateTextRun);\r\n if (definitionTextRuns !== evaluatedTextRuns) {\r\n evaluated = _.clone(<any>definition);\r\n evaluated.textRuns = evaluatedTextRuns;\r\n }\r\n\r\n return evaluated || <Paragraph>definition;\r\n }\r\n\r\n function evaluateTextRun(evalContext: IEvalContext, definition: TextRunDefinition): TextRun {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(definition, 'definition');\r\n\r\n let evaluated: TextRun;\r\n\r\n let definitionValue = definition.value;\r\n let evaluatedValue = evaluateValue(evalContext, <any> definitionValue, textType);\r\n if (evaluatedValue !== undefined) {\r\n evaluated = _.clone(<any>definition);\r\n evaluated.value = evaluatedValue;\r\n }\r\n\r\n return evaluated || <TextRun>definition;\r\n }\r\n\r\n /**\r\n * Evaluates an array, and lazily copies on write whenever the evaluator function returns something\r\n * other than the input to it.\r\n */\r\n function evaluateArrayCopyOnChange<TDefinition, TEvaluated>(\r\n evalContext: IEvalContext,\r\n definitions: TDefinition[],\r\n evaluator: (ctx: IEvalContext, defn: TDefinition) => TEvaluated): TEvaluated[] {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(definitions, 'definitions');\r\n debug.assertValue(evaluator, 'evaluator');\r\n\r\n let evaluatedValues: TEvaluated[];\r\n\r\n for (let i = 0, len = definitions.length; i < len; i++) {\r\n let definition = definitions[i];\r\n let evaluated: TEvaluated = evaluator(evalContext, definition);\r\n\r\n // NOTE: the any casts here are necessary due to the compiler not knowing the relationship\r\n // between TEvaluated & TDefinition\r\n if (!evaluatedValues && <any>definition !== evaluated) {\r\n evaluatedValues = _.take(<TEvaluated[]><any>definitions, i);\r\n }\r\n\r\n if (evaluatedValues) {\r\n evaluatedValues.push(evaluated);\r\n }\r\n }\r\n\r\n return evaluatedValues || <TEvaluated[]><any>definitions;\r\n }\r\n\r\n function evaluateValue(evalContext: IEvalContext, definition: SQExpr | RuleEvaluation, valueType: ValueType): any {\r\n if (definition instanceof SQExpr)\r\n return ExpressionEvaluator.evaluate(<SQExpr>definition, evalContext);\r\n\r\n if (definition instanceof RuleEvaluation)\r\n return (<RuleEvaluation>definition).evaluate(evalContext);\r\n }\r\n\r\n /** Responsible for evaluating SQExprs into values. */\r\n class ExpressionEvaluator extends DefaultSQExprVisitorWithArg<PrimitiveValue, IEvalContext> {\r\n private static instance: ExpressionEvaluator = new ExpressionEvaluator();\r\n\r\n public static evaluate(expr: SQExpr, evalContext: IEvalContext): PrimitiveValue {\r\n if (expr == null)\r\n return;\r\n\r\n return expr.accept(ExpressionEvaluator.instance, evalContext);\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr, evalContext: IEvalContext): PrimitiveValue {\r\n return evalContext.getExprValue(expr);\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr, evalContext: IEvalContext): PrimitiveValue {\r\n return expr.value;\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr, evalContext: IEvalContext): PrimitiveValue {\r\n return evalContext.getExprValue(expr);\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr, evalContext: IEvalContext): PrimitiveValue {\r\n return evalContext.getExprValue(expr);\r\n }\r\n\r\n public visitFillRule(expr: SQFillRuleExpr, evalContext: IEvalContext): PrimitiveValue {\r\n let inputValue = expr.input.accept(this, evalContext);\r\n if (inputValue !== undefined) {\r\n let colorAllocator = evalContext.getColorAllocator(expr);\r\n if (colorAllocator) {\r\n return colorAllocator.color(inputValue);\r\n }\r\n }\r\n }\r\n\r\n public visitSelectRef(expr: SQSelectRefExpr, evalContext: IEvalContext): PrimitiveValue {\r\n return evalContext.getExprValue(expr);\r\n }\r\n }\r\n }\r\n} \r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import inherit = Prototype.inherit;\r\n\r\n export module DataViewPivotCategorical {\r\n /**\r\n * Pivots categories in a categorical DataView into valueGroupings.\r\n * This is akin to a mathematical matrix transpose.\r\n */\r\n export function apply(dataView: DataView): DataView {\r\n debug.assertValue(dataView, 'dataView');\r\n\r\n let categorical = dataView.categorical;\r\n if (!categorical)\r\n return null;\r\n\r\n let categories = categorical.categories;\r\n if (!categories || categories.length !== 1)\r\n return null;\r\n\r\n let values = categorical.values;\r\n if (_.isEmpty(values) || values.source)\r\n return null;\r\n\r\n let category = categories[0],\r\n categoryIdentities = category.identity,\r\n categoryValues = category.values,\r\n pivotedColumns: DataViewMetadataColumn[] = [],\r\n pivotedValues: DataViewValueColumn[] = [];\r\n for (let rowIdx = 0, rowCount = categoryValues.length; rowIdx < rowCount; rowIdx++) {\r\n let categoryValue = categoryValues[rowIdx],\r\n categoryIdentity = categoryIdentities[rowIdx];\r\n for (let colIdx = 0, colCount = values.length; colIdx < colCount; colIdx++) {\r\n let value = values[colIdx],\r\n pivotedColumn = inherit(value.source);\r\n\r\n // A value has a series group, which is not implemented for pivoting -- just give up.\r\n if (value.identity)\r\n return null;\r\n\r\n pivotedColumn.groupName = categoryValue;\r\n let pivotedValue: DataViewValueColumn = {\r\n source: pivotedColumn,\r\n values: [value.values[rowIdx]],\r\n identity: categoryIdentity,\r\n min: value.min,\r\n max: value.max,\r\n subtotal: value.subtotal\r\n };\r\n\r\n let highlights = value.highlights;\r\n if (highlights) {\r\n pivotedValue.highlights = [highlights[rowIdx]];\r\n }\r\n\r\n pivotedColumns.push(pivotedColumn);\r\n pivotedValues.push(pivotedValue);\r\n }\r\n }\r\n\r\n let pivotedMetadata = inherit(dataView.metadata);\r\n pivotedMetadata.columns = pivotedColumns;\r\n\r\n values = DataViewTransform.createValueColumns(pivotedValues, <SQExpr[]>category.identityFields, category.source);\r\n return {\r\n metadata: pivotedMetadata,\r\n categorical: {\r\n values: values,\r\n },\r\n matrix: dataView.matrix\r\n };\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export module DataViewPivotMatrix {\r\n /** Pivots row hierarchy members in a matrix DataView into column hierarchy. */\r\n export function apply(dataViewMatrix: DataViewMatrix, context: MatrixTransformationContext): void {\r\n debug.assertValue(dataViewMatrix, 'dataViewMatrix');\r\n\r\n if (!context.columnHierarchyRewritten)\r\n dataViewMatrix.columns = Prototype.inherit(dataViewMatrix.columns);\r\n let columns = dataViewMatrix.columns;\r\n\r\n if (!context.rowHierarchyRewritten)\r\n dataViewMatrix.rows = Prototype.inherit(dataViewMatrix.rows);\r\n let rows = dataViewMatrix.rows;\r\n\r\n if (columns.levels.length > 1)\r\n return;\r\n\r\n let pivotedRowNode: DataViewMatrixNode = {\r\n level: 0\r\n };\r\n\r\n let columnLeafNodes: DataViewMatrixNode[] = columns.root.children;\r\n let measureCount = columnLeafNodes.length;\r\n\r\n // Notes related to VSTS 6999369: The level value of Measure Header nodes is not necessarily its parent node's level + 1.\r\n // In particular, the Measure Header column nodes directly under the Grand Total node at level 0 (i.e. _.last(pivotResultMatrix.columns.root.children))\r\n // will have level === (pivotResultMatrix.columns.levels.length - 1), which will be greater than the Grand Total node's 'level + 1' \r\n // in a matrix with 2+ column fields and 2+ measure fields.\r\n // In this code, all row levels will get pivoted over to the columns hierarchy, hence the level of any Measure Header nodes in the pivot result\r\n // is just (1 + the level of the deepest row node's level), which === rows.levels.length.\r\n let pivotResultMeasureHeaderLevel = rows.levels.length;\r\n\r\n if (measureCount > 0) {\r\n let index = 0;\r\n let callback = function (node: DataViewMatrixNode) {\r\n // Collect values and remove them from row leaves\r\n if (node.values) {\r\n if (!pivotedRowNode.values)\r\n pivotedRowNode.values = {};\r\n\r\n for (let i = 0; i < measureCount; i++)\r\n pivotedRowNode.values[index++] = node.values[i];\r\n\r\n delete node.values;\r\n }\r\n\r\n // Create measure headers if there are more than one measures\r\n if (measureCount > 1) {\r\n if (!node.children)\r\n node.children = [];\r\n\r\n for (let j = 0; j < measureCount; j++) {\r\n let measureHeaderLeaf: DataViewMatrixNode = { level: pivotResultMeasureHeaderLevel };\r\n\r\n // Copy levelSourceIndex from columnLeafNodes (as they might have been reordered)\r\n let columnLeafNode = columnLeafNodes[j];\r\n measureHeaderLeaf.levelSourceIndex = columnLeafNode.levelSourceIndex;\r\n\r\n if (node.isSubtotal)\r\n measureHeaderLeaf.isSubtotal = true;\r\n\r\n node.children.push(measureHeaderLeaf);\r\n }\r\n }\r\n };\r\n\r\n if (context.hierarchyTreesRewritten) {\r\n forEachLeaf(rows.root, callback);\r\n }\r\n else {\r\n dataViewMatrix.columns.root = cloneTreeExecuteOnLeaf(rows.root, callback);\r\n }\r\n }\r\n else {\r\n if (!context.hierarchyTreesRewritten) {\r\n dataViewMatrix.columns.root = cloneTree(rows.root);\r\n }\r\n }\r\n\r\n if (measureCount > 1) {\r\n // Keep measure headers, but move them to the innermost level\r\n let level: DataViewHierarchyLevel = { sources: columns.levels[0].sources };\r\n rows.levels.push(level);\r\n\r\n columns.levels.length = 0;\r\n }\r\n\r\n if (context.hierarchyTreesRewritten) {\r\n dataViewMatrix.columns.root = rows.root;\r\n dataViewMatrix.rows.root = {\r\n children: [pivotedRowNode]\r\n };\r\n }\r\n else {\r\n let updatedRowRoot = Prototype.inherit(dataViewMatrix.rows.root);\r\n updatedRowRoot.children = [pivotedRowNode];\r\n dataViewMatrix.rows.root = updatedRowRoot;\r\n }\r\n\r\n dataViewMatrix.columns.levels = rows.levels;\r\n dataViewMatrix.rows.levels = [];\r\n }\r\n\r\n function forEachLeaf(root: DataViewMatrixNode, callback: (node: DataViewMatrixNode) => void): void {\r\n let children = root.children;\r\n if (children && children.length > 0) {\r\n for (let i = 0, ilen = children.length; i < ilen; i++)\r\n forEachLeaf(children[i], callback);\r\n\r\n return;\r\n }\r\n\r\n callback(root);\r\n }\r\n\r\n export function cloneTree(node: DataViewMatrixNode): DataViewMatrixNode {\r\n return cloneTreeExecuteOnLeaf(node);\r\n }\r\n\r\n export function cloneTreeExecuteOnLeaf(node: DataViewMatrixNode, callback?: (node: DataViewMatrixNode) => void): DataViewMatrixNode {\r\n let updatedNode = Prototype.inherit(node);\r\n\r\n let children = node.children;\r\n if (children && children.length > 0) {\r\n let newChildren: DataViewTreeNode[] = [];\r\n\r\n for (let i = 0, ilen = children.length; i < ilen; i++) {\r\n let updatedChild = cloneTreeExecuteOnLeaf(children[i], callback);\r\n newChildren.push(updatedChild);\r\n }\r\n updatedNode.children = newChildren;\r\n }\r\n else {\r\n if (callback)\r\n callback(updatedNode);\r\n }\r\n\r\n return updatedNode;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export module DataViewSelfCrossJoin {\r\n /**\r\n * Returns a new DataView based on the original, with a single DataViewCategorical category that is \"cross joined\"\r\n * to itself as a value grouping.\r\n * This is the mathematical equivalent of taking an array and turning it into an identity matrix.\r\n */\r\n export function apply(dataView: DataView): DataView {\r\n debug.assertValue(dataView, 'dataView');\r\n\r\n if (!dataView.categorical)\r\n return;\r\n let dataViewCategorical = dataView.categorical;\r\n if (!dataViewCategorical.categories || dataViewCategorical.categories.length !== 1)\r\n return;\r\n if (dataViewCategorical.values && dataViewCategorical.values.source)\r\n return;\r\n\r\n return applyCategorical(dataView.metadata, dataViewCategorical);\r\n }\r\n\r\n function applyCategorical(dataViewMetadata: DataViewMetadata, dataViewCategorical: DataViewCategorical): DataView {\r\n debug.assertValue(dataViewMetadata, 'dataViewMetadata');\r\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\r\n debug.assertValue(dataViewCategorical.categories, 'dataViewCategorical.categories');\r\n\r\n let category = dataViewCategorical.categories[0],\r\n categoryValues = category.values,\r\n categoryLength = categoryValues.length;\r\n\r\n if (categoryLength === 0)\r\n return;\r\n\r\n let valuesArray: DataViewValueColumn[] = dataViewCategorical.values\r\n ? dataViewCategorical.values.grouped()[0].values\r\n : [];\r\n let transformedDataView = createCategoricalDataViewBuilder()\r\n .withCategories(dataViewCategorical.categories)\r\n .withGroupedValues(createGroupedValues(category, categoryValues, categoryLength, valuesArray))\r\n .build();\r\n\r\n dataViewMetadata = Prototype.inherit(dataViewMetadata);\r\n dataViewMetadata.columns = transformedDataView.metadata.columns;\r\n\r\n return {\r\n metadata: dataViewMetadata,\r\n categorical: transformedDataView.categorical,\r\n };\r\n }\r\n\r\n function createGroupedValues(\r\n category: DataViewCategoryColumn,\r\n categoryValues: any[],\r\n categoryLength: number,\r\n valuesArray: DataViewValueColumn[]): DataViewBuilderGroupedValuesOptions {\r\n debug.assertValue(category, 'category');\r\n debug.assertValue(categoryValues, 'categoryValues');\r\n debug.assertValue(categoryLength, 'categoryLength');\r\n debug.assertValue(valuesArray, 'valuesArray');\r\n\r\n let nullValuesArray: any[] = createNullValues(categoryLength),\r\n valuesArrayLen = valuesArray.length,\r\n seriesData: DataViewBuilderSeriesData[][] = [];\r\n\r\n for (let i = 0; i < categoryLength; i++) {\r\n let seriesDataItem: DataViewBuilderSeriesData[] = [];\r\n\r\n for (let j = 0; j < valuesArrayLen; j++) {\r\n let originalValueColumn = valuesArray[j],\r\n originalHighlightValues = originalValueColumn.highlights;\r\n\r\n let seriesDataItemCategory: DataViewBuilderSeriesData = {\r\n values: inheritArrayWithValue(nullValuesArray, originalValueColumn.values, i),\r\n };\r\n if (originalHighlightValues)\r\n seriesDataItemCategory.highlights = inheritArrayWithValue(nullValuesArray, originalHighlightValues, i);\r\n\r\n seriesDataItem.push(seriesDataItemCategory);\r\n }\r\n\r\n seriesData.push(seriesDataItem);\r\n }\r\n\r\n return {\r\n groupColumn: {\r\n source: category.source,\r\n identityFrom: { fields: <SQExpr[]>category.identityFields, identities: category.identity },\r\n values: category.values,\r\n },\r\n valueColumns: _.map(valuesArray, v => <DataViewBuilderColumnOptions>{ source: v.source }),\r\n data: seriesData,\r\n };\r\n }\r\n }\r\n\r\n function createNullValues(length: number): any[] {\r\n debug.assertValue(length, 'length');\r\n\r\n let array = new Array(length);\r\n for (let i = 0; i < length; i++)\r\n array[i] = null;\r\n return array;\r\n }\r\n\r\n function inheritArrayWithValue(nullValues: any[], original: any[], index: number): any[] {\r\n let inherited = Prototype.inherit(nullValues);\r\n inherited[index] = original[index];\r\n\r\n return inherited;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n import DataShapeBindingDataReduction = powerbi.data.DataShapeBindingDataReduction;\r\n import inheritSingle = powerbi.Prototype.inheritSingle;\r\n import RoleKindByQueryRef = DataViewAnalysis.RoleKindByQueryRef;\r\n\r\n export module DataViewPivotCategoricalToPrimaryGroups {\r\n\r\n /**\r\n * If mapping requests cross axis data reduction and the binding has secondary grouping, mutates the binding to\r\n * pivot the secondary before the primary.\r\n */\r\n export function pivotBinding(binding: DataShapeBinding, allMappings: CompiledDataViewMapping[], finalMapping: CompiledDataViewMapping, defaultDataVolume: number): void {\r\n // unpivot is inferred from result in DataViewTransform.apply but it does not have the\r\n // compiled mappings available, let alone the merged mapping, only the original\r\n // DataViewMappings. to keep that inference easy, only apply pivot when there's\r\n // only one matching mapping\r\n if (!allMappings || allMappings.length !== 1)\r\n return;\r\n\r\n if (!finalMapping.categorical || !finalMapping.categorical.dataReductionAlgorithm)\r\n return;\r\n\r\n if (!binding)\r\n return;\r\n\r\n if (!canPivotCategorical(binding, finalMapping))\r\n return;\r\n\r\n // pivot secondary onto front of primary\r\n binding.Primary.Groupings = [binding.Secondary.Groupings[0], binding.Primary.Groupings[0]];\r\n\r\n binding.Secondary = undefined;\r\n \r\n // set primary to pivot reduction\r\n binding.DataReduction = {\r\n Primary: DataShapeBindingDataReduction.createFrom(finalMapping.categorical.dataReductionAlgorithm),\r\n DataVolume: finalMapping.categorical.dataVolume || defaultDataVolume,\r\n };\r\n }\r\n\r\n /** narrowly targets scatter chart scenario for now to keep code simple */\r\n function isPivotableAxis(axis: powerbi.data.DataShapeBindingAxis): boolean {\r\n return axis\r\n && axis.Groupings\r\n && axis.Groupings.length === 1\r\n && !_.isEmpty(axis.Groupings[0].Projections)\r\n && !axis.Groupings[0].Subtotal\r\n && _.isEmpty(axis.Groupings[0].SuppressedProjections);\r\n }\r\n\r\n function canPivotCategorical(binding: DataShapeBinding, mapping: CompiledDataViewMapping): boolean {\r\n if (!isPivotableAxis(binding.Primary))\r\n return false;\r\n if (!isPivotableAxis(binding.Secondary) || binding.Secondary.Groupings[0].Projections.length !== 1)\r\n return false;\r\n\r\n // don't pivot if either axis has a data reduction\r\n if (binding.DataReduction && (binding.DataReduction.Primary || binding.DataReduction.Secondary))\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n export function unpivotResult(oldDataView: DataView, selects: DataViewSelectTransform[], dataViewMappings: DataViewMapping[], projectionActiveItems: DataViewProjectionActiveItems): DataView {\r\n if (!inferUnpivotTransform(selects, dataViewMappings, oldDataView, projectionActiveItems))\r\n return oldDataView;\r\n\r\n // This returns a subsetted version of the DataView rather than using prototypal inheritance because\r\n // any dataviews in the old one (including ones invented after this code is written) will correspond\r\n // to a pivoted query result and therefore will be in the wrong shape for the unpivoted query the\r\n // querying code made.\r\n let newDataView: DataView = {\r\n metadata: {\r\n columns: ArrayExtensions.copy(oldDataView.metadata.columns),\r\n },\r\n };\r\n \r\n // preserve view types that aren't affected by pivoting\r\n if (oldDataView.single)\r\n newDataView.single = oldDataView.single;\r\n if (oldDataView.table)\r\n newDataView.table = oldDataView.table;\r\n\r\n // other views are derived from matrix\r\n if (oldDataView.matrix) {\r\n let newDataViewMatrix = unpivotMatrix(oldDataView.matrix);\r\n\r\n // categorical only if there's data\r\n if (!_.isEmpty(newDataViewMatrix.valueSources)) {\r\n // Guard against a DataViewMatrix with composite grouping in columns, because composite group in Series is \r\n // not yet expressible in the current version of DataViewValueColumns and DataViewValueColumnGroup interfaces.\r\n // this.canPivotCategorical() would have returned false in the first place for this query.\r\n let hasCompositeGroupInSeries = utils.DataViewMatrixUtils.containsCompositeGroup(newDataViewMatrix.columns);\r\n if (!hasCompositeGroupInSeries) {\r\n newDataView.categorical = categoricalFromUnpivotedMatrix(newDataViewMatrix, newDataView.metadata.columns);\r\n }\r\n }\r\n }\r\n\r\n return newDataView;\r\n }\r\n\r\n /**\r\n * Infer from the query result and the visual mappings whether the query was pivoted.\r\n * Narrowly targets scatter chart scenario for now to keep code simple\r\n */\r\n function inferUnpivotTransform(selects: DataViewSelectTransform[], dataViewMappings: DataViewMapping[], dataView: DataView, projectionActiveItems: DataViewProjectionActiveItems): boolean {\r\n if (_.isEmpty(selects) || _.isEmpty(dataViewMappings) || !dataView)\r\n return false;\r\n\r\n // select applicable mappings based on select roles\r\n let roleKinds: RoleKindByQueryRef = DataViewSelectTransform.createRoleKindFromMetadata(selects, dataView.metadata);\r\n let projections: QueryProjectionsByRole = DataViewSelectTransform.projectionsFromSelects(selects, projectionActiveItems);\r\n let supportedDataViewMappings = DataViewAnalysis.chooseDataViewMappings(projections, dataViewMappings, roleKinds).supportedMappings;\r\n\r\n // NOTE: limiting to simple situation that handles scatter for now - see the other side in canPivotCategorical\r\n if (!supportedDataViewMappings || supportedDataViewMappings.length !== 1)\r\n return false;\r\n\r\n let categoricalMapping = supportedDataViewMappings[0].categorical;\r\n if (!categoricalMapping)\r\n return false;\r\n\r\n // pivoted query will have produced a matrix\r\n let matrixDataview = dataView.matrix;\r\n if (!matrixDataview)\r\n return false;\r\n\r\n // matrix must have two levels of grouping\r\n if (!matrixDataview.rows || !matrixDataview.rows.levels || matrixDataview.rows.levels.length !== 2)\r\n return false;\r\n \r\n // get category and value grouping roles\r\n let categoryGroups: string[] = [];\r\n let valueGroups: string[] = [];\r\n\r\n let addGroupingRole = (roleName: string, groups: string[]) => {\r\n let roleProjections: QueryProjectionCollection = projections[roleName];\r\n if (!roleProjections)\r\n return;\r\n\r\n for (let roleProjection of roleProjections.all()) {\r\n if (roleKinds[roleProjection.queryRef] === VisualDataRoleKind.Grouping)\r\n groups.push(roleProjection.queryRef);\r\n }\r\n };\r\n\r\n DataViewMapping.visitCategoricalCategories(categoricalMapping.categories, {\r\n visitRole: (roleName: string) => { addGroupingRole(roleName, categoryGroups); }\r\n });\r\n\r\n DataViewMapping.visitCategoricalValues(categoricalMapping.values, {\r\n visitRole: (roleName: string) => { addGroupingRole(roleName, valueGroups); }\r\n });\r\n\r\n // need both for pivot to have been done\r\n if (_.isEmpty(categoryGroups) || _.isEmpty(valueGroups))\r\n return false;\r\n\r\n // if there was a pivot, there won't be any measures left in the columns\r\n for (let level of matrixDataview.columns.levels) {\r\n for (let source of level.sources) {\r\n if (!source.isMeasure)\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n interface DataViewMatrixNodeValues {\r\n [id: number]: DataViewMatrixNodeValue;\r\n }\r\n\r\n /**\r\n * matrix will have two groupings in the rows, outer (series) and inner (categories), and none in the columns.\r\n * this function changes that so that the categories become the rows and the series the columns.\r\n */\r\n function unpivotMatrix(oldMatrix: DataViewMatrix): DataViewMatrix {\r\n let oldRows = oldMatrix.rows;\r\n let oldRoot = oldRows.root;\r\n let oldChildren = <DataViewMatrixNode[]>oldRoot.children;\r\n\r\n // series are the outer grouping\r\n let series: DataViewMatrixNode[] = [];\r\n let seriesIdLevel = oldRows.levels[0];\r\n let seriesIdFields = oldRoot.childIdentityFields;\r\n\r\n // categories are the inner grouping. \r\n let categoryIndex: _.Dictionary<number> = {};\r\n let categories: DataViewMatrixNode[] = [];\r\n let categoryIdLevel = oldRows.levels[1];\r\n let categoryIdFields = _.isEmpty(oldChildren) ? undefined : oldChildren[0].childIdentityFields;\r\n\r\n let measureCount = oldMatrix.valueSources.length;\r\n\r\n // within each series value, the category list may not be complete so cannot simply use the inner loop index\r\n // to reference it.\r\n let findCategory = (identity: DataViewScopeIdentity) => {\r\n let index = categoryIndex[identity.key];\r\n\r\n debug.assert(index !== undefined, \"findcat() !== undefined\");\r\n\r\n return index;\r\n };\r\n\r\n // collect series and categories from the row hierarchy\r\n if (oldChildren) {\r\n let addCategory = (categoryNode: DataViewMatrixNode) => {\r\n let key = categoryNode.identity.key;\r\n let index = categoryIndex[key];\r\n if (index === undefined) {\r\n index = categories.length;\r\n categoryIndex[key] = index;\r\n categories.push(categoryNode);\r\n }\r\n };\r\n\r\n for (let seriesNode of oldChildren) {\r\n series.push(seriesNode);\r\n\r\n for (let categoryNode of <DataViewMatrixNode[]>seriesNode.children) {\r\n addCategory(categoryNode);\r\n }\r\n }\r\n }\r\n \r\n // extract intersection values from pivoted matrix\r\n // values will be indexed by categories then series\r\n let matrixValues: DataViewMatrixNodeValues[][] = new Array<DataViewMatrixNodeValues[]>(categories.length);\r\n for (let j = 0; j < series.length; ++j) { // outer is series\r\n let seriesNode = oldChildren[j];\r\n for (let categoryNode of seriesNode.children) { // inner is categories but maybe a subset\r\n let i = findCategory(categoryNode.identity); // must lookup actual category index\r\n\r\n if (!matrixValues[i])\r\n matrixValues[i] = new Array<DataViewMatrixNodeValues>(series.length);\r\n\r\n matrixValues[i][j] = categoryNode.values;\r\n }\r\n }\r\n\r\n // columns of the unpivoted matrix are the series\r\n let newColumns: DataViewHierarchy = {\r\n root: {\r\n children: _.map(series, s => {\r\n let inheritedNode = inheritSingle(s);\r\n inheritedNode.level = 0; // s.level should already be 0, but just in case...\r\n inheritedNode.children = undefined; // if Measure Headers exist in oldMatrix.columns, newColumns.root.children will get populated later in this function\r\n inheritedNode.childIdentityFields = undefined;\r\n return inheritedNode;\r\n }),\r\n childIdentityFields: seriesIdFields,\r\n },\r\n levels: [\r\n seriesIdLevel,\r\n \r\n ],\r\n };\r\n\r\n // Re-add any Measure Headers from oldMatrix.columns as leaf nodes under newColumns\r\n if (measureCount > 0) {\r\n let newColChildren: DataViewMatrixNode[] = _.map(oldMatrix.columns.root.children, (srcnode: DataViewMatrixNode) => {\r\n let dstnode: DataViewMatrixNode = { level: 1 };\r\n if (srcnode.levelSourceIndex)\r\n dstnode.levelSourceIndex = srcnode.levelSourceIndex;\r\n return dstnode;\r\n });\r\n\r\n for (let i = 0; i < newColumns.root.children.length; ++i)\r\n newColumns.root.children[i].children = newColChildren;\r\n\r\n newColumns.levels.push(oldMatrix.columns.levels[0]);\r\n }\r\n\r\n // rows of the unpivoted matrix are the categories\r\n let newRows: DataViewHierarchy = {\r\n root: {\r\n children: _.map(categories, c => {\r\n let inheritedNode = inheritSingle(c);\r\n inheritedNode.level = 0;\r\n inheritedNode.children = undefined; // c.children should already be undefined, but just in case...\r\n inheritedNode.childIdentityFields = undefined; // c.children should already be undefined, but just in case...\r\n return inheritedNode;\r\n }),\r\n childIdentityFields: categoryIdFields,\r\n },\r\n levels: [\r\n categoryIdLevel,\r\n ],\r\n };\r\n\r\n // put values into rows\r\n if (measureCount > 0) {\r\n for (let i = 0; i < categories.length; ++i) {\r\n let row = newRows.root.children[i];\r\n let rowValues: DataViewMatrixNodeValues = {};\r\n\r\n for (let j = 0; j < series.length; ++j) {\r\n let mvalues = matrixValues[i] && matrixValues[i][j];\r\n for (let k = 0; k < measureCount; ++k) {\r\n let l = j * measureCount + k;\r\n rowValues[l] = !mvalues\r\n ? ( k === 0 ? { value: null } : { value: null, valueSourceIndex: k } )\r\n : mvalues[k];\r\n }\r\n }\r\n\r\n row.values = rowValues;\r\n }\r\n }\r\n\r\n let newMatrix: DataViewMatrix = {\r\n rows: newRows,\r\n columns: newColumns,\r\n valueSources: oldMatrix.valueSources,\r\n };\r\n\r\n return newMatrix;\r\n }\r\n\r\n /** build a categorical data view from an unpivoted matrix. */\r\n function categoricalFromUnpivotedMatrix(matrix: DataViewMatrix, columnMetadata: DataViewMetadataColumn[]): DataViewCategorical {\r\n let seriesCount = matrix.columns.root.children.length;\r\n let measureMetadata = matrix.valueSources;\r\n let measureCount = measureMetadata.length;\r\n\r\n let categories: DataViewCategoryColumn[] = createCategoryColumnsFromUnpivotedMatrix(matrix);\r\n\r\n // create grouped values\r\n let groups: DataViewValueColumnGroup[] = [];\r\n for (let j = 0; j < seriesCount; ++j) {\r\n let seriesColumn = matrix.columns.root.children[j];\r\n let group: DataViewValueColumnGroup = {\r\n values: [],\r\n identity: seriesColumn.identity,\r\n name: seriesColumn.value || null,\r\n };\r\n\r\n groups.push(group);\r\n\r\n for (let k = 0; k < measureCount; ++k) {\r\n let valueColumnMetadataSrc = measureMetadata[k];\r\n let valueColumnMetadataDst: DataViewMetadataColumn = <DataViewMetadataColumn>{};\r\n for (let key in valueColumnMetadataSrc)\r\n valueColumnMetadataDst[key] = valueColumnMetadataSrc[key];\r\n valueColumnMetadataDst.groupName = group.name;\r\n\r\n columnMetadata.push(valueColumnMetadataDst);\r\n\r\n let valueColumn: DataViewValueColumn = {\r\n source: valueColumnMetadataDst,\r\n values: [],\r\n identity: group.identity,\r\n };\r\n\r\n group.values.push(valueColumn);\r\n\r\n // grab measure values in the group from across rows of matrix\r\n let index = k + j * measureCount;\r\n\r\n for (let categoryNode of matrix.rows.root.children) {\r\n let value = categoryNode.values[index].value;\r\n\r\n valueColumn.values.push(value);\r\n }\r\n }\r\n }\r\n\r\n // and now ungrouped\r\n let values: DataViewValueColumns = <DataViewValueColumns>[];\r\n for (let group of groups) {\r\n for (let k = 0; k < measureCount; ++k) {\r\n values.push(group.values[k]);\r\n }\r\n }\r\n\r\n values.grouped = () => groups;\r\n values.identityFields = matrix.columns.root.childIdentityFields;\r\n values.source = matrix.columns.levels[0].sources[0];\r\n\r\n // final assembly\r\n let categorical: DataViewCategorical = {\r\n categories: categories,\r\n values: values,\r\n };\r\n\r\n return categorical;\r\n }\r\n\r\n function createCategoryColumnsFromUnpivotedMatrix(unpivotedMatrix: DataViewMatrix): DataViewCategoryColumn[] {\r\n debug.assertValue(unpivotedMatrix, 'unpivotedMatrix');\r\n debug.assert(unpivotedMatrix && unpivotedMatrix.rows && unpivotedMatrix.rows.levels && (unpivotedMatrix.rows.levels.length === 1),\r\n 'pre-condition: unpivotedMatrix should have exactly one level in row hierarchy');\r\n\r\n // Create categories from rows. If matrix.rows.levels[0].sources represents a composite group, expand each column in the \r\n // composite group into a separate DataViewCategoryColumn. The identity and childIdentityFields properties will be the \r\n // same amongst the resulting DataViewCategoryColumns.\r\n let categoryIdentity = _.map(unpivotedMatrix.rows.root.children, x => x.identity);\r\n let categoryIdentityFields = unpivotedMatrix.rows.root.childIdentityFields;\r\n let categorySourceColumns = unpivotedMatrix.rows.levels[0].sources;\r\n\r\n let categories: DataViewCategoryColumn[] = [];\r\n for (var i = 0, ilen = categorySourceColumns.length; i < ilen; i++) {\r\n let groupLevelValues = _.map(unpivotedMatrix.rows.root.children, (categoryNode: DataViewMatrixNode) => {\r\n let levelValues: DataViewMatrixGroupValue[] = categoryNode.levelValues;\r\n\r\n // Please refer to the interface comments on when this is undefined... But in today's code\r\n // I believe we will not see undefined levelValues in the rows of any unpivotedMatrix. \r\n if (levelValues !== undefined) {\r\n debug.assert(levelValues[i] && (levelValues[i].levelSourceIndex === i),\r\n 'pre-condition: DataViewMatrixNode.levelValues is expected to have one DataViewMatrixGroupValue node per level source column, sorted by levelSourceIndex.');\r\n return levelValues[i].value;\r\n }\r\n });\r\n\r\n categories.push({\r\n source: categorySourceColumns[i],\r\n values: groupLevelValues,\r\n identity: categoryIdentity,\r\n identityFields: categoryIdentityFields,\r\n });\r\n }\r\n\r\n return categories;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import inherit = Prototype.inherit;\r\n import inheritSingle = Prototype.inheritSingle;\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n import EnumExtensions = jsCommon.EnumExtensions;\r\n import INumberDictionary = jsCommon.INumberDictionary;\r\n\r\n export interface DataViewTransformApplyOptions {\r\n prototype: DataView;\r\n objectDescriptors: DataViewObjectDescriptors;\r\n dataViewMappings?: DataViewMapping[];\r\n transforms: DataViewTransformActions;\r\n colorAllocatorFactory: IColorAllocatorFactory;\r\n dataRoles: VisualDataRole[];\r\n }\r\n\r\n /** Describes the Transform actions to be done to a prototype DataView. */\r\n export interface DataViewTransformActions {\r\n /** Describes transform metadata for each semantic query select item, as the arrays align, by index. */\r\n selects?: DataViewSelectTransform[];\r\n\r\n /** Describes the DataViewObject definitions. */\r\n objects?: DataViewObjectDefinitions;\r\n\r\n /** Describes the splitting of a single input DataView into multiple DataViews. */\r\n splits?: DataViewSplitTransform[];\r\n\r\n /** Describes the projection metadata which includes projection ordering and active items. */\r\n roles?: DataViewRoleTransformMetadata;\r\n }\r\n\r\n export interface DataViewSplitTransform {\r\n selects: INumberDictionary<boolean>;\r\n }\r\n\r\n export interface DataViewProjectionOrdering {\r\n [roleName: string]: number[];\r\n }\r\n\r\n export interface DataViewProjectionActiveItemInfo {\r\n queryRef: string;\r\n\r\n /** Describes if the active item should be ignored in concatenation.\r\n If the active item has a drill filter, it will not be used in concatenation.\r\n If the value of suppressConcat is true, the activeItem will be ommitted from concatenation. */\r\n suppressConcat?: boolean;\r\n }\r\n\r\n export interface DataViewProjectionActiveItems {\r\n [roleName: string]: DataViewProjectionActiveItemInfo[];\r\n }\r\n\r\n export interface DataViewRoleTransformMetadata {\r\n /** Describes the order of selects (referenced by query index) in each role. */\r\n ordering?: DataViewProjectionOrdering;\r\n\r\n /** Describes the active items in each role. */\r\n activeItems?: DataViewProjectionActiveItems;\r\n }\r\n\r\n export interface MatrixTransformationContext {\r\n rowHierarchyRewritten: boolean;\r\n columnHierarchyRewritten: boolean;\r\n hierarchyTreesRewritten: boolean;\r\n }\r\n\r\n interface ValueRewrite<T> {\r\n from: T;\r\n to: T;\r\n }\r\n\r\n interface NumberToNumberMapping {\r\n [position: number]: number;\r\n }\r\n\r\n const enum CategoricalDataViewTransformation {\r\n None,\r\n Pivot,\r\n SelfCrossJoin,\r\n }\r\n\r\n export const enum StandardDataViewKinds {\r\n None = 0,\r\n Categorical = 1,\r\n Matrix = 1 << 1,\r\n Single = 1 << 2,\r\n Table = 1 << 3,\r\n Tree = 1 << 4,\r\n }\r\n\r\n // TODO: refactor & focus DataViewTransform into a service with well-defined dependencies.\r\n export module DataViewTransform {\r\n const fillRulePropertyDescriptor: DataViewObjectPropertyDescriptor = { type: { fillRule: {} } };\r\n\r\n const enum ColumnIdentifierKind {\r\n QueryName,\r\n Role,\r\n }\r\n\r\n export function apply(options: DataViewTransformApplyOptions): DataView[] {\r\n debug.assertValue(options, 'options');\r\n\r\n // TODO: Flow a context object through to capture errors/warnings about what happens here for better diagnosability.\r\n\r\n let prototype = options.prototype,\r\n objectDescriptors = options.objectDescriptors,\r\n dataViewMappings = options.dataViewMappings,\r\n transforms = options.transforms,\r\n projectionActiveItems = transforms && transforms.roles && transforms.roles.activeItems,\r\n colorAllocatorFactory = options.colorAllocatorFactory,\r\n dataRoles = options.dataRoles;\r\n\r\n if (!prototype)\r\n return transformEmptyDataView(objectDescriptors, transforms, colorAllocatorFactory);\r\n\r\n if (!transforms)\r\n return [prototype];\r\n\r\n // Transform Query DataView\r\n prototype = DataViewPivotCategoricalToPrimaryGroups.unpivotResult(prototype, transforms.selects, dataViewMappings, projectionActiveItems);\r\n let visualDataViews: DataView[] = transformQueryToVisualDataView(prototype, transforms, objectDescriptors, dataViewMappings, colorAllocatorFactory, dataRoles);\r\n\r\n // Transform and generate derived visual DataViews\r\n visualDataViews = DataViewRegression.run({\r\n dataViewMappings: dataViewMappings,\r\n visualDataViews: visualDataViews,\r\n dataRoles: dataRoles,\r\n objectDescriptors: objectDescriptors,\r\n objectDefinitions: transforms.objects,\r\n colorAllocatorFactory: colorAllocatorFactory,\r\n transformSelects: transforms.selects,\r\n metadata: prototype.metadata,\r\n projectionActiveItems: projectionActiveItems,\r\n });\r\n\r\n return visualDataViews;\r\n }\r\n\r\n function transformQueryToVisualDataView(\r\n prototype: DataView,\r\n transforms: DataViewTransformActions,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n dataViewMappings: DataViewMapping[],\r\n colorAllocatorFactory: IColorAllocatorFactory,\r\n dataRoles: VisualDataRole[]): DataView[] {\r\n let transformedDataViews: DataView[] = [];\r\n let splits = transforms.splits;\r\n if (_.isEmpty(splits)) {\r\n transformedDataViews.push(transformDataView(prototype, objectDescriptors, dataViewMappings, transforms, colorAllocatorFactory, dataRoles));\r\n } else {\r\n for (let split of splits) {\r\n let transformed = transformDataView(prototype, objectDescriptors, dataViewMappings, transforms, colorAllocatorFactory, dataRoles, split.selects);\r\n transformedDataViews.push(transformed);\r\n }\r\n }\r\n return transformedDataViews;\r\n }\r\n\r\n function transformEmptyDataView(objectDescriptors: DataViewObjectDescriptors, transforms: DataViewTransformActions, colorAllocatorFactory: IColorAllocatorFactory): DataView[] {\r\n if (transforms && transforms.objects) {\r\n let emptyDataView: DataView = {\r\n metadata: {\r\n columns: [],\r\n }\r\n };\r\n\r\n transformObjects(\r\n emptyDataView,\r\n StandardDataViewKinds.None,\r\n objectDescriptors,\r\n transforms.objects,\r\n transforms.selects,\r\n colorAllocatorFactory);\r\n\r\n return [emptyDataView];\r\n }\r\n\r\n return [];\r\n }\r\n\r\n function transformDataView(\r\n prototype: DataView,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n roleMappings: DataViewMapping[],\r\n transforms: DataViewTransformActions,\r\n colorAllocatorFactory: IColorAllocatorFactory,\r\n dataRoles: VisualDataRole[],\r\n selectsToInclude?: INumberDictionary<boolean>): DataView {\r\n debug.assertValue(prototype, 'prototype');\r\n debug.assertValue(transforms, 'transforms');\r\n debug.assert(!selectsToInclude ||\r\n _.filter(\r\n Object.keys(selectsToInclude),\r\n (selectIndex) => selectsToInclude[selectIndex] && (!transforms.selects || !transforms.selects[selectIndex]))\r\n .length === 0, // asserts that the number of select indices in selectsToInclude without a corresponding Select Transform === 0\r\n 'If selectsToInclude is specified, every Select Index in it must have a corresponding Select Transform.');\r\n\r\n let targetKinds = getTargetKinds(roleMappings);\r\n let transformed = inherit(prototype);\r\n transformed.metadata = inherit(prototype.metadata);\r\n\r\n let projectionOrdering = transforms.roles && transforms.roles.ordering;\r\n let projectionActiveItems = transforms.roles && transforms.roles.activeItems;\r\n transformed = transformSelects(transformed, targetKinds, roleMappings, transforms.selects, projectionOrdering, selectsToInclude);\r\n transformObjects(transformed, targetKinds, objectDescriptors, transforms.objects, transforms.selects, colorAllocatorFactory);\r\n\r\n // Note: Do this step after transformObjects() so that metadata columns in 'transformed' have roles and objects.general.formatString populated\r\n transformed = DataViewConcatenateCategoricalColumns.detectAndApply(transformed, objectDescriptors, roleMappings, projectionOrdering, transforms.selects, projectionActiveItems);\r\n\r\n DataViewNormalizeValues.apply({\r\n dataview: transformed,\r\n dataViewMappings: roleMappings,\r\n dataRoles: dataRoles,\r\n });\r\n\r\n return transformed;\r\n }\r\n\r\n function getTargetKinds(roleMappings: DataViewMapping[]): StandardDataViewKinds {\r\n debug.assertAnyValue(roleMappings, 'roleMappings');\r\n\r\n if (!roleMappings)\r\n return StandardDataViewKinds.None;\r\n\r\n let result = StandardDataViewKinds.None;\r\n for (let roleMapping of roleMappings) {\r\n if (roleMapping.categorical)\r\n result |= StandardDataViewKinds.Categorical;\r\n if (roleMapping.matrix)\r\n result |= StandardDataViewKinds.Matrix;\r\n if (roleMapping.single)\r\n result |= StandardDataViewKinds.Single;\r\n if (roleMapping.table)\r\n result |= StandardDataViewKinds.Table;\r\n if (roleMapping.tree)\r\n result |= StandardDataViewKinds.Tree;\r\n }\r\n return result;\r\n }\r\n\r\n function transformSelects(\r\n dataView: DataView,\r\n targetDataViewKinds: StandardDataViewKinds,\r\n roleMappings: DataViewMapping[],\r\n selectTransforms: DataViewSelectTransform[],\r\n projectionOrdering?: DataViewProjectionOrdering,\r\n selectsToInclude?: INumberDictionary<boolean>): DataView {\r\n\r\n let columnRewrites: ValueRewrite<DataViewMetadataColumn>[] = [];\r\n if (selectTransforms) {\r\n dataView.metadata.columns = applyTransformsToColumns(\r\n dataView.metadata.columns,\r\n selectTransforms,\r\n columnRewrites);\r\n }\r\n\r\n // NOTE: no rewrites necessary for Tree (it doesn't reference the columns)\r\n\r\n if (dataView.categorical && EnumExtensions.hasFlag(targetDataViewKinds, StandardDataViewKinds.Categorical)) {\r\n dataView.categorical = applyRewritesToCategorical(dataView.categorical, columnRewrites, selectsToInclude);\r\n\r\n // TODO VSTS 7024199: separate out structural transformations from dataViewTransform.transformSelects(...)\r\n // NOTE: This is slightly DSR-specific.\r\n dataView = pivotIfNecessary(dataView, roleMappings);\r\n }\r\n\r\n // Don't perform this potentially expensive transform unless we actually have a matrix.\r\n // When we switch to lazy per-visual DataView creation, we'll be able to remove this check.\r\n if (dataView.matrix && EnumExtensions.hasFlag(targetDataViewKinds, StandardDataViewKinds.Matrix)) {\r\n let matrixTransformationContext: MatrixTransformationContext = {\r\n rowHierarchyRewritten: false,\r\n columnHierarchyRewritten: false,\r\n hierarchyTreesRewritten: false\r\n };\r\n dataView.matrix = applyRewritesToMatrix(dataView.matrix, columnRewrites, roleMappings, projectionOrdering, matrixTransformationContext);\r\n\r\n // TODO VSTS 7024199: separate out structural transformations from dataViewTransform.transformSelects(...)\r\n if (shouldPivotMatrix(dataView.matrix, roleMappings))\r\n DataViewPivotMatrix.apply(dataView.matrix, matrixTransformationContext);\r\n }\r\n\r\n // Don't perform this potentially expensive transform unless we actually have a table.\r\n // When we switch to lazy per-visual DataView creation, we'll be able to remove this check.\r\n if (dataView.table && EnumExtensions.hasFlag(targetDataViewKinds, StandardDataViewKinds.Table)) {\r\n dataView.table = applyRewritesToTable(dataView.table, columnRewrites, projectionOrdering);\r\n }\r\n\r\n return dataView;\r\n }\r\n\r\n function applyTransformsToColumns(\r\n prototypeColumns: DataViewMetadataColumn[],\r\n selects: DataViewSelectTransform[],\r\n rewrites: ValueRewrite<DataViewMetadataColumn>[]): DataViewMetadataColumn[] {\r\n debug.assertValue(prototypeColumns, 'columns');\r\n\r\n if (!selects)\r\n return prototypeColumns;\r\n\r\n //column may contain undefined entries\r\n let columns = inherit(prototypeColumns);\r\n\r\n for (let i = 0, len = prototypeColumns.length; i < len; i++) {\r\n let prototypeColumn = prototypeColumns[i];\r\n let select = selects[prototypeColumn.index];\r\n if (!select)\r\n continue;\r\n\r\n let column: DataViewMetadataColumn = columns[i] = inherit(prototypeColumn);\r\n\r\n if (select.roles)\r\n column.roles = select.roles;\r\n if (select.type)\r\n column.type = select.type;\r\n column.format = getFormatForColumn(select, column);\r\n\r\n if (select.displayName)\r\n column.displayName = select.displayName;\r\n if (select.queryName)\r\n column.queryName = select.queryName;\r\n if (select.kpi)\r\n column.kpi = select.kpi;\r\n if (select.sort)\r\n column.sort = select.sort;\r\n if (select.discourageAggregationAcrossGroups)\r\n column.discourageAggregationAcrossGroups = select.discourageAggregationAcrossGroups;\r\n\r\n rewrites.push({\r\n from: prototypeColumn,\r\n to: column,\r\n });\r\n }\r\n\r\n return columns;\r\n }\r\n\r\n /**\r\n * Get the column format. Order of precendence is:\r\n * 1. Select format\r\n * 2. Column format\r\n */\r\n function getFormatForColumn(select: DataViewSelectTransform, column: DataViewMetadataColumn): string {\r\n // TODO: we already copied the select.Format to column.format, we probably don't need this check\r\n return select.format || column.format;\r\n }\r\n\r\n function applyRewritesToCategorical(prototype: DataViewCategorical, columnRewrites: ValueRewrite<DataViewMetadataColumn>[], selectsToInclude?: INumberDictionary<boolean>): DataViewCategorical {\r\n debug.assertValue(prototype, 'prototype');\r\n debug.assertValue(columnRewrites, 'columnRewrites');\r\n\r\n let categorical = inherit(prototype);\r\n\r\n function override(value: { source?: DataViewMetadataColumn }) {\r\n let rewrittenSource = findOverride(value.source, columnRewrites);\r\n if (rewrittenSource) {\r\n let rewritten = inherit(value);\r\n rewritten.source = rewrittenSource;\r\n return rewritten;\r\n }\r\n }\r\n\r\n let categories = Prototype.overrideArray(prototype.categories, override);\r\n if (categories)\r\n categorical.categories = categories;\r\n\r\n let valuesOverride = Prototype.overrideArray(prototype.values, override);\r\n let valueColumns = valuesOverride || prototype.values;\r\n\r\n if (valueColumns) {\r\n if (valueColumns.source) {\r\n if (selectsToInclude && !selectsToInclude[valueColumns.source.index]) {\r\n // if processing a split and this is the split without series...\r\n valueColumns.source = undefined;\r\n }\r\n else {\r\n let rewrittenValuesSource = findOverride(valueColumns.source, columnRewrites);\r\n if (rewrittenValuesSource)\r\n valueColumns.source = rewrittenValuesSource;\r\n }\r\n }\r\n\r\n if (selectsToInclude) {\r\n // Apply selectsToInclude to values by removing value columns not included\r\n for (let i = valueColumns.length - 1; i >= 0; i--) {\r\n if (!selectsToInclude[valueColumns[i].source.index]) {\r\n valueColumns.splice(i, 1);\r\n }\r\n }\r\n }\r\n\r\n let isDynamicSeries = !!valueColumns.source;\r\n\r\n debug.assert(_.every(valueColumns, (valueColumn) => isDynamicSeries === !!valueColumn.identity),\r\n 'After applying selectsToInclude, all remaining DataViewValueColumn objects should have a consistent scope type (static vs. dynamic) with the parent DataViewValueColumns object.');\r\n \r\n // Dynamic or not, always update the return values of grouped() to have the rewritten 'source' property\r\n let seriesGroups: DataViewValueColumnGroup[];\r\n if (isDynamicSeries) {\r\n // We have a dynamic series, so update the return value of grouped() to have the DataViewValueColumn objects with rewritten 'source'.\r\n // Also, exclude any column that belongs to a static series.\r\n seriesGroups = inherit(valueColumns.grouped());\r\n\r\n // The following assert is not a rule that's set in stone. If it becomes false someday, update the code below to remove static series from seriesGroups.\r\n debug.assert(_.every(seriesGroups, (group) => !!group.identity), 'If the categorical has a dynamic series, query DataView is expected to have a grouped() function that returns only dynamic series groups, even when there is any column that belongs to a static group (in the case of combo chart and splits). If this assertion becomes false someday, update the code below to remove static series from seriesGroups.');\r\n\r\n let nextSeriesGroupIndex = 0;\r\n let currentSeriesGroup: DataViewValueColumnGroup;\r\n for (let i = 0, ilen = valueColumns.length; i < ilen; i++) {\r\n let currentValueColumn = valueColumns[i];\r\n if (!currentSeriesGroup || (currentValueColumn.identity !== currentSeriesGroup.identity)) {\r\n currentSeriesGroup = inherit(seriesGroups[nextSeriesGroupIndex]);\r\n seriesGroups[nextSeriesGroupIndex] = currentSeriesGroup;\r\n currentSeriesGroup.values = [];\r\n nextSeriesGroupIndex++;\r\n debug.assert(currentValueColumn.identity === currentSeriesGroup.identity, 'expecting the value columns are sequenced by series groups');\r\n }\r\n currentSeriesGroup.values.push(currentValueColumn);\r\n }\r\n }\r\n else {\r\n // We are in a static series, so we should throw away the grouped and recreate it using the static values\r\n // which have already been filtered\r\n seriesGroups = [{ values: valueColumns }];\r\n }\r\n\r\n valueColumns.grouped = () => seriesGroups;\r\n categorical.values = valueColumns;\r\n }\r\n\r\n return categorical;\r\n }\r\n\r\n function applyRewritesToTable(\r\n prototype: DataViewTable,\r\n columnRewrites: ValueRewrite<DataViewMetadataColumn>[],\r\n projectionOrdering: DataViewProjectionOrdering): DataViewTable {\r\n debug.assertValue(prototype, 'prototype');\r\n debug.assertValue(columnRewrites, 'columnRewrites');\r\n\r\n let table = inherit(prototype);\r\n\r\n // Copy the rewritten columns into the table view\r\n let override = (metadata: DataViewMetadataColumn) => findOverride(metadata, columnRewrites);\r\n let columns = Prototype.overrideArray(prototype.columns, override);\r\n if (columns)\r\n table.columns = columns;\r\n\r\n if (!projectionOrdering)\r\n return table;\r\n\r\n let newToOldPositions = createTableColumnPositionMapping(projectionOrdering, columnRewrites);\r\n if (!newToOldPositions)\r\n return table;\r\n\r\n // Reorder the columns\r\n let columnsClone = columns.slice(0);\r\n let keys = Object.keys(newToOldPositions);\r\n for (let i = 0, len = keys.length; i < len; i++) {\r\n let sourceColumn = columnsClone[newToOldPositions[keys[i]]];\r\n\r\n // In the case we've hit the end of our columns array, but still have position reordering keys,\r\n // there is a duplicate column so we will need to add a new column for the duplicate data\r\n if (i === columns.length)\r\n columns.push(sourceColumn);\r\n else {\r\n debug.assert(i < columns.length, 'The column index is out of range for reordering.');\r\n columns[i] = sourceColumn;\r\n }\r\n }\r\n\r\n // Reorder the rows\r\n let rows = Prototype.overrideArray(table.rows,\r\n (row: any[]) => {\r\n let newRow: any[] = [];\r\n for (let i = 0, len = keys.length; i < len; ++i)\r\n newRow[i] = row[newToOldPositions[keys[i]]];\r\n\r\n return newRow;\r\n });\r\n\r\n if (rows)\r\n table.rows = rows;\r\n\r\n return table;\r\n }\r\n\r\n /** Creates a mapping of new position to original position. */\r\n function createTableColumnPositionMapping(\r\n projectionOrdering: DataViewProjectionOrdering,\r\n columnRewrites: ValueRewrite<DataViewMetadataColumn>[]): NumberToNumberMapping {\r\n let roles = Object.keys(projectionOrdering);\r\n\r\n // If we have more than one role then the ordering of columns between roles is ambiguous, so don't reorder anything.\r\n if (roles.length !== 1)\r\n return;\r\n\r\n let role = roles[0],\r\n originalOrder = _.map(columnRewrites, (rewrite: ValueRewrite<DataViewMetadataColumn>) => rewrite.from.index),\r\n newOrder = projectionOrdering[role];\r\n\r\n return createOrderMapping(originalOrder, newOrder);\r\n }\r\n\r\n function applyRewritesToMatrix(\r\n prototype: DataViewMatrix,\r\n columnRewrites: ValueRewrite<DataViewMetadataColumn>[],\r\n roleMappings: DataViewMapping[],\r\n projectionOrdering: DataViewProjectionOrdering,\r\n context: MatrixTransformationContext): DataViewMatrix {\r\n debug.assertValue(prototype, 'prototype');\r\n debug.assertValue(columnRewrites, 'columnRewrites');\r\n debug.assertValue(roleMappings, 'roleMappings');\r\n \r\n let firstRoleMappingWithMatrix = _.find(roleMappings, (roleMapping) => !!roleMapping.matrix);\r\n debug.assertValue(firstRoleMappingWithMatrix, 'roleMappings - at least one role mapping is expected to target DataViewMatrix');\r\n\r\n let matrixMapping = firstRoleMappingWithMatrix.matrix;\r\n let matrix = inherit(prototype);\r\n\r\n function override(metadata: DataViewMetadataColumn) {\r\n return findOverride(metadata, columnRewrites);\r\n }\r\n\r\n function overrideHierarchy(hierarchy: DataViewHierarchy): DataViewHierarchy {\r\n let rewrittenHierarchy: DataViewHierarchy = null;\r\n\r\n let newLevels = Prototype.overrideArray(\r\n hierarchy.levels,\r\n (level: DataViewHierarchyLevel) => {\r\n let newLevel: DataViewHierarchyLevel = null;\r\n let levelSources = Prototype.overrideArray(level.sources, override);\r\n if (levelSources)\r\n newLevel = ensureRewritten<DataViewHierarchyLevel>(newLevel, level, h => h.sources = levelSources);\r\n\r\n return newLevel;\r\n });\r\n if (newLevels)\r\n rewrittenHierarchy = ensureRewritten<DataViewHierarchy>(rewrittenHierarchy, hierarchy, r => r.levels = newLevels);\r\n\r\n return rewrittenHierarchy;\r\n }\r\n\r\n let rows = overrideHierarchy(matrix.rows);\r\n if (rows) {\r\n matrix.rows = rows;\r\n context.rowHierarchyRewritten = true;\r\n }\r\n\r\n let columns = overrideHierarchy(matrix.columns);\r\n if (columns) {\r\n matrix.columns = columns;\r\n context.columnHierarchyRewritten = true;\r\n }\r\n\r\n let valueSources = Prototype.overrideArray(matrix.valueSources, override);\r\n if (valueSources) {\r\n matrix.valueSources = valueSources;\r\n\r\n // Only need to reorder if we have more than one value source, and they are all bound to the same role\r\n let matrixValues = <DataViewRoleForMapping>matrixMapping.values;\r\n if (projectionOrdering && valueSources.length > 1 && matrixValues && matrixValues.for) {\r\n let columnLevels = columns.levels.length;\r\n if (columnLevels > 0) {\r\n let newToOldPositions = createMatrixValuesPositionMapping(matrixValues, projectionOrdering, valueSources, columnRewrites);\r\n if (newToOldPositions) {\r\n let keys = Object.keys(newToOldPositions);\r\n let numKeys = keys.length;\r\n\r\n // Reorder the value columns\r\n columns.root = DataViewPivotMatrix.cloneTree(columns.root);\r\n if (columnLevels === 1)\r\n reorderChildNodes(columns.root, newToOldPositions);\r\n else\r\n forEachNodeAtLevel(columns.root, columnLevels - 2, (node: DataViewMatrixNode) => reorderChildNodes(node, newToOldPositions));\r\n\r\n // Reorder the value rows\r\n matrix.rows.root = DataViewPivotMatrix.cloneTreeExecuteOnLeaf(matrix.rows.root, (node: DataViewMatrixNode) => {\r\n\r\n if (!node.values)\r\n return;\r\n\r\n let newValues: { [id: number]: DataViewTreeNodeValue } = {};\r\n\r\n let iterations = Object.keys(node.values).length / numKeys;\r\n for (let i = 0, len = iterations; i < len; i++) {\r\n let offset = i * numKeys;\r\n for (let keysIndex = 0; keysIndex < numKeys; keysIndex++)\r\n newValues[offset + keysIndex] = node.values[offset + newToOldPositions[keys[keysIndex]]];\r\n }\r\n\r\n node.values = newValues;\r\n });\r\n\r\n context.hierarchyTreesRewritten = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n reorderMatrixCompositeGroups(matrix, matrixMapping, projectionOrdering);\r\n\r\n return matrix;\r\n }\r\n\r\n function reorderChildNodes(node: DataViewMatrixNode, newToOldPositions: NumberToNumberMapping): void {\r\n let keys = Object.keys(newToOldPositions);\r\n let numKeys = keys.length;\r\n let children = node.children;\r\n\r\n let childrenClone = children.slice(0);\r\n for (let i = 0, len = numKeys; i < len; i++) {\r\n let sourceColumn = childrenClone[newToOldPositions[keys[i]]];\r\n\r\n // In the case we've hit the end of our columns array, but still have position reordering keys,\r\n // there is a duplicate column so we will need to add a new column for the duplicate data\r\n if (i === children.length)\r\n children.push(sourceColumn);\r\n else {\r\n debug.assert(i < children.length, 'The column index is out of range for reordering.');\r\n children[i] = sourceColumn;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns a inheritSingle() version of the specified prototype DataViewMatrix with any composite group levels\r\n * and values re-ordered by projection ordering.\r\n * Returns undefined if no re-ordering under the specified prototype is necessary.\r\n */\r\n function reorderMatrixCompositeGroups(\r\n prototype: DataViewMatrix,\r\n supportedDataViewMapping: DataViewMatrixMapping,\r\n projection: DataViewProjectionOrdering): DataViewMatrix {\r\n\r\n let transformedDataView: DataViewMatrix;\r\n\r\n if (prototype && supportedDataViewMapping && projection) {\r\n\r\n // reorder levelValues in any composite groups in rows hierarchy\r\n let transformedRowsHierarchy: DataViewHierarchy;\r\n DataViewMapping.visitMatrixItems(supportedDataViewMapping.rows, {\r\n visitRole: (role: string, context?: RoleItemContext): void => {\r\n transformedRowsHierarchy = reorderMatrixHierarchyCompositeGroups(\r\n transformedRowsHierarchy || prototype.rows,\r\n role,\r\n projection);\r\n }\r\n });\r\n\r\n // reorder levelValues in any composite groups in columns hierarchy\r\n let transformedColumnsHierarchy: DataViewHierarchy;\r\n DataViewMapping.visitMatrixItems(supportedDataViewMapping.columns, {\r\n visitRole: (role: string, context?: RoleItemContext): void => {\r\n transformedColumnsHierarchy = reorderMatrixHierarchyCompositeGroups(\r\n transformedColumnsHierarchy || prototype.columns,\r\n role,\r\n projection);\r\n }\r\n });\r\n\r\n if (transformedRowsHierarchy || transformedColumnsHierarchy) {\r\n transformedDataView = inheritSingle(prototype);\r\n transformedDataView.rows = transformedRowsHierarchy || transformedDataView.rows;\r\n transformedDataView.columns = transformedColumnsHierarchy || transformedDataView.columns;\r\n }\r\n }\r\n\r\n return transformedDataView;\r\n }\r\n\r\n /**\r\n * Returns a inheritSingle() version of the specified matrixHierarchy with any composite group levels and\r\n * values re-ordered by projection ordering.\r\n * Returns undefined if no re-ordering under the specified matrixHierarchy is necessary.\r\n */\r\n function reorderMatrixHierarchyCompositeGroups(\r\n matrixHierarchy: DataViewHierarchy,\r\n hierarchyRole: string,\r\n projection: DataViewProjectionOrdering): DataViewHierarchy {\r\n debug.assertValue(matrixHierarchy, 'matrixHierarchy');\r\n debug.assertValue(hierarchyRole, 'hierarchyRole');\r\n debug.assertValue(projection, 'projection');\r\n\r\n let transformedHierarchy: DataViewHierarchy;\r\n let selectIndicesInProjectionOrder: number[] = projection[hierarchyRole];\r\n\r\n // reordering needs to happen only if there are multiple columns for the hierarchy's role in the projection\r\n let hasMultipleColumnsInProjection = selectIndicesInProjectionOrder && selectIndicesInProjectionOrder.length >= 2;\r\n if (hasMultipleColumnsInProjection && !_.isEmpty(matrixHierarchy.levels)) {\r\n for (let i = matrixHierarchy.levels.length - 1; i >= 0; i--) {\r\n var hierarchyLevel: DataViewHierarchyLevel = matrixHierarchy.levels[i];\r\n\r\n // compute a mapping for any necessary reordering of columns at this given level, based on projection ordering\r\n let newToOldLevelSourceIndicesMapping: NumberToNumberMapping =\r\n createMatrixHierarchyLevelSourcesPositionMapping(hierarchyLevel, hierarchyRole, projection);\r\n\r\n if (newToOldLevelSourceIndicesMapping) {\r\n if (_.isUndefined(transformedHierarchy)) {\r\n // Because we start inspecting the hierarchy from the deepest level and work backwards to the root,\r\n // the current hierarchyLevel is therefore the inner-most level that needs re-ordering of composite group values...\r\n transformedHierarchy = inheritSingle(matrixHierarchy);\r\n transformedHierarchy.levels = inheritSingle(matrixHierarchy.levels);\r\n\r\n // Because the current hierarchyLevel is the inner-most level that needs re-ordering of composite group values,\r\n // inheriting all nodes from root down to this level will also prepare the nodes for any transform that needs to\r\n // happen in other hierarchy levels in the later iterations of this for-loop.\r\n transformedHierarchy.root = utils.DataViewMatrixUtils.inheritMatrixNodeHierarchy(matrixHierarchy.root, i, true);\r\n }\r\n\r\n // reorder the metadata columns in the sources array at that level\r\n let transformingHierarchyLevel = inheritSingle(matrixHierarchy.levels[i]); // inherit at most once during the whole dataViewTransform for this obj...\r\n transformedHierarchy.levels[i] = reorderMatrixHierarchyLevelColumnSources(transformingHierarchyLevel, newToOldLevelSourceIndicesMapping);\r\n\r\n // reorder the level values in the composite group nodes at the current hierarchy level\r\n reorderMatrixHierarchyLevelValues(transformedHierarchy.root, i, newToOldLevelSourceIndicesMapping);\r\n }\r\n }\r\n }\r\n\r\n return transformedHierarchy;\r\n }\r\n\r\n /**\r\n * If reordering is needed on the level's metadata column sources (i.e. hierarchyLevel.sources),\r\n * returns the mapping from the target LevelSourceIndex (based on projection order) to original LevelSourceIndex.\r\n *\r\n * The returned value maps level source indices from the new target order (calculated from projection order)\r\n * back to the original order as they appear in the specified hierarchyLevel's sources.\r\n * Please refer to comments on the createOrderMapping() function for more explanation on the mappings in the return value.\r\n *\r\n * Note: The return value is the mapping from new index to old index, for consistency with existing and similar functions in this module.\r\n *\r\n * @param hierarchyLevel The hierarchy level that contains the metadata column sources.\r\n * @param hierarchyRoleName The role name for the hierarchy where the specified hierarchyLevel belongs.\r\n * @param projection The projection ordering that includes an ordering for the specified hierarchyRoleName.\r\n */\r\n function createMatrixHierarchyLevelSourcesPositionMapping(\r\n hierarchyLevel: DataViewHierarchyLevel,\r\n hierarchyRole: string,\r\n projection: DataViewProjectionOrdering): NumberToNumberMapping {\r\n debug.assertValue(hierarchyLevel, 'hierarchyLevel');\r\n debug.assertValue(hierarchyRole, 'hierarchyRole');\r\n debug.assertValue(projection, 'projection');\r\n debug.assertValue(projection[hierarchyRole], 'pre-condition: The specified projection must contain an ordering for the specified hierarchyRoleName.');\r\n\r\n let newToOldLevelSourceIndicesMapping: NumberToNumberMapping;\r\n let levelSourceColumns = hierarchyLevel.sources;\r\n\r\n if (levelSourceColumns && levelSourceColumns.length >= 2) {\r\n // The hierarchy level has multiple columns, so it is possible to have composite group, go on to check other conditions...\r\n\r\n let columnsForHierarchyRoleOrderedByLevelSourceIndex = utils.DataViewMetadataColumnUtils.joinMetadataColumnsAndProjectionOrder(\r\n levelSourceColumns,\r\n projection,\r\n hierarchyRole);\r\n\r\n if (columnsForHierarchyRoleOrderedByLevelSourceIndex && columnsForHierarchyRoleOrderedByLevelSourceIndex.length >= 2) {\r\n // The hierarchy level has multiple columns for the hierarchy's role, go on to calculate newToOldLevelSourceIndicesMapping...\r\n let columnsForHierarchyRoleOrderedByProjection = _.sortBy(\r\n columnsForHierarchyRoleOrderedByLevelSourceIndex,\r\n columnInfo => columnInfo.projectionOrderIndex);\r\n\r\n newToOldLevelSourceIndicesMapping = createOrderMapping(\r\n _.map(columnsForHierarchyRoleOrderedByLevelSourceIndex, columnInfo => columnInfo.sourceIndex),\r\n _.map(columnsForHierarchyRoleOrderedByProjection, columnInfo => columnInfo.sourceIndex));\r\n }\r\n }\r\n\r\n return newToOldLevelSourceIndicesMapping;\r\n }\r\n\r\n /**\r\n * Applies re-ordering on the specified transformingHierarchyLevel's sources.\r\n * Returns the same object as the specified transformingHierarchyLevel.\r\n */\r\n function reorderMatrixHierarchyLevelColumnSources(transformingHierarchyLevel: DataViewHierarchyLevel, newToOldLevelSourceIndicesMapping: NumberToNumberMapping): DataViewHierarchyLevel {\r\n debug.assertValue(transformingHierarchyLevel, 'transformingHierarchyLevel');\r\n debug.assertValue(newToOldLevelSourceIndicesMapping, 'newToOldLevelSourceIndicesMapping');\r\n\r\n let originalLevelSources = transformingHierarchyLevel.sources;\r\n\r\n transformingHierarchyLevel.sources = originalLevelSources.slice(0); // make a clone of the array before modifying it, because the for-loop depends on the origin array.\r\n\r\n let newLevelSourceIndices = Object.keys(newToOldLevelSourceIndicesMapping);\r\n for (let i = 0, ilen = newLevelSourceIndices.length; i < ilen; i++) {\r\n let newLevelSourceIndex = newLevelSourceIndices[i];\r\n let oldLevelSourceIndex = newToOldLevelSourceIndicesMapping[newLevelSourceIndex];\r\n\r\n debug.assert(oldLevelSourceIndex < originalLevelSources.length,\r\n 'pre-condition: The value in every mapping in the specified levelSourceIndicesReorderingMap must be a valid index to the specified hierarchyLevel.sources array property');\r\n\r\n transformingHierarchyLevel.sources[newLevelSourceIndex] = originalLevelSources[oldLevelSourceIndex];\r\n }\r\n\r\n return transformingHierarchyLevel;\r\n }\r\n\r\n /**\r\n * Reorders the elements in levelValues in each node under transformingHierarchyRootNode at the specified hierarchyLevel,\r\n * and updates their DataViewMatrixGroupValue.levelSourceIndex property.\r\n *\r\n * Returns the same object as the specified transformingHierarchyRootNode.\r\n */\r\n function reorderMatrixHierarchyLevelValues(\r\n transformingHierarchyRootNode: DataViewMatrixNode,\r\n transformingHierarchyLevelIndex: number,\r\n newToOldLevelSourceIndicesMapping: NumberToNumberMapping): DataViewMatrixNode {\r\n debug.assertValue(transformingHierarchyRootNode, 'transformingHierarchyRootNode');\r\n debug.assertValue(newToOldLevelSourceIndicesMapping, 'newToOldLevelSourceIndicesMapping');\r\n\r\n let oldToNewLevelSourceIndicesMapping: NumberToNumberMapping = createReversedMapping(newToOldLevelSourceIndicesMapping);\r\n\r\n forEachNodeAtLevel(transformingHierarchyRootNode, transformingHierarchyLevelIndex, (transformingMatrixNode: DataViewMatrixNode) => {\r\n let originalLevelValues = transformingMatrixNode.levelValues;\r\n\r\n // Note: Technically this function is incorrect, because the driving source of the new LevelValues is really\r\n // the \"projection for this composite group\", a concept that isn't yet implemented in DataViewProjectionOrdering.\r\n // The following code isn't correct in the special case where a column is projected twice in this composite group,\r\n // in which case the DSR will not have the duplicate columns; DataViewTransform is supposed to expand the duplicates.\r\n // Until we fully implement composite group projection, though, we'll just sort what we have in transformingMatrixNode.levelValues.\r\n\r\n if (!_.isEmpty(originalLevelValues)) {\r\n // First, re-order the elements in transformingMatrixNode.levelValues by the new levelSourceIndex order.\r\n // _.sortBy() also creates a new array, which we want to do for all nodes (including when levelValues.length === 1)\r\n // because we don't want to accidentally modify the array AND its value references in Query DataView\r\n let newlyOrderedLevelValues = _.sortBy(originalLevelValues, levelValue => oldToNewLevelSourceIndicesMapping[levelValue.levelSourceIndex]);\r\n\r\n for (let i = 0, ilen = newlyOrderedLevelValues.length; i < ilen; i++) {\r\n let transformingLevelValue = inheritSingle(newlyOrderedLevelValues[i]);\r\n transformingLevelValue.levelSourceIndex = oldToNewLevelSourceIndicesMapping[transformingLevelValue.levelSourceIndex];\r\n newlyOrderedLevelValues[i] = transformingLevelValue;\r\n }\r\n\r\n transformingMatrixNode.levelValues = newlyOrderedLevelValues;\r\n\r\n // For consistency with how DataViewTreeNode.value works, and for a bit of backward compatibility,\r\n // copy the last value from DataViewMatrixNode.levelValues to DataViewMatrixNode.value.\r\n let newlyOrderedLastLevelValue = _.last(newlyOrderedLevelValues);\r\n if (transformingMatrixNode.value !== newlyOrderedLastLevelValue.value) {\r\n transformingMatrixNode.value = newlyOrderedLastLevelValue.value;\r\n }\r\n if ((transformingMatrixNode.levelSourceIndex || 0) !== newlyOrderedLastLevelValue.levelSourceIndex) {\r\n transformingMatrixNode.levelSourceIndex = newlyOrderedLastLevelValue.levelSourceIndex;\r\n }\r\n }\r\n });\r\n\r\n return transformingHierarchyRootNode;\r\n }\r\n\r\n /**\r\n * Creates a mapping of new position to original position.\r\n *\r\n * The return value is a mapping where each key-value pair represent the order mapping of a particular column:\r\n * - the key in the key-value pair is the index of the particular column in the new order (e.g. projection order)\r\n * - the value in the key-value pair is the index of the particular column in the original order\r\n */\r\n function createMatrixValuesPositionMapping(\r\n matrixValues: DataViewRoleForMapping,\r\n projectionOrdering: DataViewProjectionOrdering,\r\n valueSources: DataViewMetadataColumn[],\r\n columnRewrites: ValueRewrite<DataViewMetadataColumn>[]): NumberToNumberMapping {\r\n\r\n let role = matrixValues.for.in;\r\n let newOrder = projectionOrdering[role];\r\n\r\n let originalOrder = _.chain(columnRewrites)\r\n .filter(rewrite => _.contains(valueSources, rewrite.to))\r\n .map(rewrite => rewrite.from.index)\r\n .value();\r\n\r\n return createOrderMapping(originalOrder, newOrder);\r\n }\r\n\r\n /**\r\n * Creates a mapping of indices, from indices to the specified newOrder array, back to indices to the specified\r\n * originalOrder array.\r\n * Each of the number value in originalOrder and newOrder is actually the unique key of a column (unqiue\r\n * under the context of the caller code), e.g. the Select Index in projection ordering array.\r\n * Also, the specified originalOrder must contain every value that exists in newOrder.\r\n *\r\n * If the specified originalOrder and newOrder are different in sequence order, then this function returns a collection of\r\n * key-value pair, each of which represents the new and old indices of a particular column:\r\n * - the key in each key-value pair is the index of the particular column key as it exists in the specified newOrder array\r\n * - the value in each key-value pair is the index of the particular column key as it exists in the specified originalOrder array\r\n *\r\n * For example on how the return value is consumed, see functions such as reorderMatrixHierarchyLevelColumnSources(...).\r\n *\r\n * If the specified originalOrder and newOrder are same, then this function returns undefined.\r\n *\r\n * @param originalOrder E.g. an array of metadata column \"select indices\", in the original order as they exist in Query DataView.\r\n * @param newOrder E.g. an array of metadata column \"select indices\", in rojection ordering.\r\n */\r\n function createOrderMapping(originalOrder: number[], newOrder: number[]): NumberToNumberMapping {\r\n // Optimization: avoid rewriting if the current order is correct\r\n if (ArrayExtensions.sequenceEqual(originalOrder, newOrder, (x: number, y: number) => x === y))\r\n return;\r\n\r\n let mapping: NumberToNumberMapping = {};\r\n for (let i = 0, len = newOrder.length; i < len; ++i) {\r\n let newPosition = newOrder[i];\r\n mapping[i] = originalOrder.indexOf(newPosition);\r\n }\r\n\r\n return mapping;\r\n }\r\n\r\n function createReversedMapping(mapping: NumberToNumberMapping): NumberToNumberMapping {\r\n debug.assertValue(mapping, 'mapping');\r\n\r\n let reversed: NumberToNumberMapping = {};\r\n\r\n for (let key in mapping) {\r\n // Note: key is a string after we get it out from mapping, thus we need to parse it\r\n // back into a number before putting it as the value in the reversed mapping\r\n let value = mapping[key];\r\n let keyAsNumber = parseInt(key, 10);\r\n reversed[value] = keyAsNumber;\r\n }\r\n\r\n debug.assertValue(Object.keys(mapping).length === Object.keys(reversed).length,\r\n 'pre-condition: The specified mapping must not contain any duplicate value because duplicate values are obmitted from the reversed mapping.');\r\n\r\n return reversed;\r\n }\r\n\r\n export function forEachNodeAtLevel(node: DataViewMatrixNode, targetLevel: number, callback: (node: DataViewMatrixNode) => void): void {\r\n debug.assertValue(node, 'node');\r\n debug.assert(targetLevel >= 0, 'argetLevel >= 0');\r\n debug.assertValue(callback, 'callback');\r\n\r\n if (node.level === targetLevel) {\r\n callback(node);\r\n return;\r\n }\r\n\r\n let children = node.children;\r\n if (children && children.length > 0) {\r\n for (let i = 0, ilen = children.length; i < ilen; i++)\r\n forEachNodeAtLevel(children[i], targetLevel, callback);\r\n }\r\n }\r\n\r\n function findOverride(source: DataViewMetadataColumn, columnRewrites: ValueRewrite<DataViewMetadataColumn>[]): DataViewMetadataColumn {\r\n for (let i = 0, len = columnRewrites.length; i < len; i++) {\r\n let columnRewrite = columnRewrites[i];\r\n if (columnRewrite.from === source)\r\n return columnRewrite.to;\r\n }\r\n }\r\n\r\n function ensureRewritten<T>(rewritten: T, prototype: T, callback?: (rewritten: T) => void): T {\r\n if (!rewritten)\r\n rewritten = inherit(prototype);\r\n\r\n if (callback)\r\n callback(rewritten);\r\n\r\n return rewritten;\r\n }\r\n\r\n export function transformObjects(\r\n dataView: DataView,\r\n targetDataViewKinds: StandardDataViewKinds,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n objectDefinitions: DataViewObjectDefinitions,\r\n selectTransforms: DataViewSelectTransform[],\r\n colorAllocatorFactory: IColorAllocatorFactory): void {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(targetDataViewKinds, 'targetDataViewKinds');\r\n debug.assertAnyValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertAnyValue(objectDefinitions, 'objectDefinitions');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n\r\n if (!objectDescriptors)\r\n return;\r\n\r\n let objectsForAllSelectors = DataViewObjectEvaluationUtils.groupObjectsBySelector(objectDefinitions);\r\n DataViewObjectEvaluationUtils.addImplicitObjects(objectsForAllSelectors, objectDescriptors, dataView.metadata.columns, selectTransforms);\r\n\r\n let metadataOnce = objectsForAllSelectors.metadataOnce;\r\n let dataObjects = objectsForAllSelectors.data;\r\n if (metadataOnce)\r\n evaluateMetadataObjects(dataView, selectTransforms, objectDescriptors, metadataOnce.objects, dataObjects, colorAllocatorFactory);\r\n\r\n let metadataObjects = objectsForAllSelectors.metadata;\r\n if (metadataObjects) {\r\n for (let i = 0, len = metadataObjects.length; i < len; i++) {\r\n let metadataObject = metadataObjects[i];\r\n let objectDefns = metadataObject.objects;\r\n let colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefns, colorAllocatorFactory);\r\n evaluateMetadataRepetition(dataView, selectTransforms, objectDescriptors, metadataObject.selector, objectDefns, colorAllocatorCache);\r\n }\r\n }\r\n\r\n for (let i = 0, len = dataObjects.length; i < len; i++) {\r\n let dataObject = dataObjects[i];\r\n let objectDefns = dataObject.objects;\r\n let colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefns, colorAllocatorFactory);\r\n evaluateDataRepetition(dataView, targetDataViewKinds, selectTransforms, objectDescriptors, dataObject.selector, dataObject.rules, objectDefns, colorAllocatorCache);\r\n }\r\n\r\n let userDefined = objectsForAllSelectors.userDefined;\r\n if (userDefined) {\r\n // TODO: We only handle user defined objects at the metadata level, but should be able to support them with arbitrary repetition.\r\n evaluateUserDefinedObjects(dataView, selectTransforms, objectDescriptors, userDefined, colorAllocatorFactory);\r\n }\r\n }\r\n\r\n function evaluateUserDefinedObjects(\r\n dataView: DataView,\r\n selectTransforms: DataViewSelectTransform[],\r\n objectDescriptors: DataViewObjectDescriptors,\r\n objectDefns: DataViewObjectDefinitionsForSelector[],\r\n colorAllocatorFactory: IColorAllocatorFactory): void {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n\r\n let dataViewObjects: DataViewObjects = dataView.metadata.objects;\r\n if (!dataViewObjects) {\r\n dataViewObjects = dataView.metadata.objects = {};\r\n }\r\n\r\n for (let objectDefn of objectDefns) {\r\n let id = objectDefn.selector.id;\r\n\r\n let colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefn.objects, colorAllocatorFactory);\r\n let evalContext = createStaticEvalContext(colorAllocatorCache, dataView, selectTransforms);\r\n let objects = DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefn.objects);\r\n\r\n for (let objectName in objects) {\r\n let object = <DataViewObject>objects[objectName];\r\n\r\n let map = <DataViewObjectMap>dataViewObjects[objectName];\r\n if (!map)\r\n map = dataViewObjects[objectName] = [];\r\n debug.assert(DataViewObjects.isUserDefined(map), 'expected DataViewObjectMap');\r\n\r\n // NOTE: We do not check for duplicate ids.\r\n map.push({ id: id, object: object });\r\n }\r\n }\r\n }\r\n\r\n /** Evaluates and sets properties on the DataView metadata. */\r\n function evaluateMetadataObjects(\r\n dataView: DataView,\r\n selectTransforms: DataViewSelectTransform[],\r\n objectDescriptors: DataViewObjectDescriptors,\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n dataObjects: DataViewObjectDefinitionsForSelectorWithRule[],\r\n colorAllocatorFactory: IColorAllocatorFactory): void {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(dataObjects, 'dataObjects');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n\r\n let colorAllocatorCache = populateColorAllocatorCache(dataView, selectTransforms, objectDefns, colorAllocatorFactory);\r\n let evalContext = createStaticEvalContext(colorAllocatorCache, dataView, selectTransforms);\r\n let objects = DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\r\n if (objects) {\r\n dataView.metadata.objects = objects;\r\n\r\n for (let objectName in objects) {\r\n let object = <DataViewObject>objects[objectName],\r\n objectDesc = objectDescriptors[objectName];\r\n\r\n for (let propertyName in object) {\r\n let propertyDesc = objectDesc.properties[propertyName],\r\n ruleDesc = propertyDesc.rule;\r\n if (!ruleDesc)\r\n continue;\r\n\r\n let definition = createRuleEvaluationInstance(\r\n dataView,\r\n colorAllocatorFactory,\r\n ruleDesc,\r\n objectName,\r\n object[propertyName],\r\n propertyDesc.type);\r\n if (!definition)\r\n continue;\r\n\r\n dataObjects.push(definition);\r\n }\r\n }\r\n }\r\n }\r\n\r\n function createRuleEvaluationInstance(\r\n dataView: DataView,\r\n colorAllocatorFactory: IColorAllocatorFactory,\r\n ruleDesc: DataViewObjectPropertyRuleDescriptor,\r\n objectName: string,\r\n propertyValue: DataViewPropertyValue,\r\n ruleType: StructuralTypeDescriptor): DataViewObjectDefinitionsForSelectorWithRule {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n debug.assertValue(ruleDesc, 'ruleDesc');\r\n debug.assertValue(propertyValue, 'propertyValue');\r\n debug.assertValue(ruleType, 'ruleType');\r\n\r\n let ruleOutput = ruleDesc.output;\r\n if (!ruleOutput)\r\n return;\r\n\r\n let selectorToCreate = findSelectorForRuleInput(dataView, ruleOutput.selector);\r\n if (!selectorToCreate)\r\n return;\r\n\r\n if (ruleType.fillRule) {\r\n return createRuleEvaluationInstanceFillRule(dataView, colorAllocatorFactory, ruleDesc, selectorToCreate, objectName, <FillRule>propertyValue);\r\n }\r\n }\r\n\r\n function createRuleEvaluationInstanceFillRule(\r\n dataView: DataView,\r\n colorAllocatorFactory: IColorAllocatorFactory,\r\n ruleDesc: DataViewObjectPropertyRuleDescriptor,\r\n selectorToCreate: Selector,\r\n objectName: string,\r\n propertyValue: FillRule): DataViewObjectDefinitionsForSelectorWithRule {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n debug.assertValue(ruleDesc, 'ruleDesc');\r\n debug.assertValue(selectorToCreate, 'selectorToCreate');\r\n debug.assertValue(propertyValue, 'propertyValue');\r\n\r\n let colorAllocator = tryCreateColorAllocatorForFillRule(dataView, colorAllocatorFactory, ruleDesc.inputRole, ColumnIdentifierKind.Role, propertyValue);\r\n\r\n if (!colorAllocator)\r\n return;\r\n\r\n let rule = new ColorRuleEvaluation(ruleDesc.inputRole, colorAllocator);\r\n let fillRuleProperties: DataViewObjectPropertyDefinitions = {};\r\n fillRuleProperties[ruleDesc.output.property] = {\r\n solid: { color: rule }\r\n };\r\n\r\n return {\r\n selector: selectorToCreate,\r\n rules: [rule],\r\n objects: [{\r\n name: objectName,\r\n properties: fillRuleProperties,\r\n }]\r\n };\r\n }\r\n\r\n function tryCreateColorAllocatorForFillRule(\r\n dataView: DataView,\r\n colorAllocatorFactory: IColorAllocatorFactory,\r\n identifier: string,\r\n identifierKind: ColumnIdentifierKind,\r\n propertyValue: FillRule): IColorAllocator {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n debug.assertValue(identifier, 'identifier');\r\n debug.assertValue(identifierKind, 'identifierKind');\r\n debug.assertValue(propertyValue, 'propertyValue');\r\n\r\n if (propertyValue.linearGradient2)\r\n return createColorAllocatorLinearGradient2(dataView, colorAllocatorFactory, identifier, identifierKind, propertyValue, propertyValue.linearGradient2);\r\n\r\n if (propertyValue.linearGradient3)\r\n return createColorAllocatorLinearGradient3(dataView, colorAllocatorFactory, identifier, identifierKind, propertyValue, propertyValue.linearGradient3);\r\n }\r\n\r\n function createColorAllocatorLinearGradient2(\r\n dataView: DataView,\r\n colorAllocatorFactory: IColorAllocatorFactory,\r\n identifier: string,\r\n identifierKind: ColumnIdentifierKind,\r\n propertyValueFillRule: FillRule,\r\n linearGradient2: LinearGradient2): IColorAllocator {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n debug.assertValue(identifier, 'identifier');\r\n debug.assertValue(identifierKind, 'identifierKind');\r\n debug.assertValue(linearGradient2, 'linearGradient2');\r\n\r\n linearGradient2 = propertyValueFillRule.linearGradient2;\r\n if (linearGradient2.min.value === undefined ||\r\n linearGradient2.max.value === undefined) {\r\n let inputRange = findRuleInputColumnNumberRange(dataView, identifier, identifierKind);\r\n if (!inputRange)\r\n return;\r\n\r\n if (linearGradient2.min.value === undefined)\r\n linearGradient2.min.value = inputRange.min;\r\n if (linearGradient2.max.value === undefined)\r\n linearGradient2.max.value = inputRange.max;\r\n }\r\n\r\n return colorAllocatorFactory.linearGradient2(propertyValueFillRule.linearGradient2);\r\n }\r\n\r\n function createColorAllocatorLinearGradient3(\r\n dataView: DataView,\r\n colorAllocatorFactory: IColorAllocatorFactory,\r\n identifier: string,\r\n identifierKind: ColumnIdentifierKind,\r\n propertyValueFillRule: FillRule,\r\n linearGradient3: LinearGradient3): IColorAllocator {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n debug.assertValue(identifier, 'identifier');\r\n debug.assertValue(identifierKind, 'identifierKind');\r\n debug.assertValue(linearGradient3, 'linearGradient3');\r\n\r\n let splitScales: boolean;\r\n linearGradient3 = propertyValueFillRule.linearGradient3;\r\n if (linearGradient3.min.value === undefined ||\r\n linearGradient3.mid.value === undefined ||\r\n linearGradient3.max.value === undefined) {\r\n let inputRange = findRuleInputColumnNumberRange(dataView, identifier, identifierKind);\r\n if (!inputRange)\r\n return;\r\n\r\n splitScales =\r\n linearGradient3.min.value === undefined &&\r\n linearGradient3.max.value === undefined &&\r\n linearGradient3.mid.value !== undefined;\r\n\r\n if (linearGradient3.min.value === undefined) {\r\n linearGradient3.min.value = inputRange.min;\r\n }\r\n if (linearGradient3.max.value === undefined) {\r\n linearGradient3.max.value = inputRange.max;\r\n }\r\n if (linearGradient3.mid.value === undefined) {\r\n let midValue: number = (linearGradient3.max.value + linearGradient3.min.value) / 2;\r\n linearGradient3.mid.value = midValue;\r\n }\r\n }\r\n\r\n return colorAllocatorFactory.linearGradient3(propertyValueFillRule.linearGradient3, splitScales);\r\n }\r\n\r\n function populateColorAllocatorCache(\r\n dataView: DataView,\r\n selectTransforms: DataViewSelectTransform[],\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n colorAllocatorFactory: IColorAllocatorFactory): IColorAllocatorCache {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n\r\n let cache = createColorAllocatorCache();\r\n let staticEvalContext = createStaticEvalContext();\r\n\r\n for (let i = 0, len = objectDefns.length; i < len; i++) {\r\n let objectDefnProperties = objectDefns[i].properties;\r\n\r\n for (let propertyName in objectDefnProperties) {\r\n let fillProperty = <FillDefinition>objectDefnProperties[propertyName];\r\n if (fillProperty &&\r\n fillProperty.solid &&\r\n fillProperty.solid.color &&\r\n fillProperty.solid.color.kind === SQExprKind.FillRule) {\r\n\r\n let fillRuleExpr = <SQFillRuleExpr>fillProperty.solid.color;\r\n\r\n let inputExprQueryName = findFirstQueryNameForExpr(selectTransforms, fillRuleExpr.input);\r\n if (!inputExprQueryName)\r\n continue;\r\n\r\n let fillRule = DataViewObjectEvaluator.evaluateProperty(\r\n staticEvalContext,\r\n fillRulePropertyDescriptor,\r\n fillRuleExpr.rule);\r\n\r\n let colorAllocator = tryCreateColorAllocatorForFillRule(dataView, colorAllocatorFactory, inputExprQueryName, ColumnIdentifierKind.QueryName, fillRule);\r\n if (colorAllocator)\r\n cache.register(fillRuleExpr, colorAllocator);\r\n }\r\n }\r\n }\r\n\r\n return cache;\r\n }\r\n\r\n function evaluateDataRepetition(\r\n dataView: DataView,\r\n targetDataViewKinds: StandardDataViewKinds,\r\n selectTransforms: DataViewSelectTransform[],\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n colorAllocatorCache: IColorAllocatorCache): void {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(targetDataViewKinds, 'targetDataViewKinds');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertAnyValue(rules, 'rules');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(colorAllocatorCache, 'colorAllocatorFactory');\r\n\r\n let containsWildcard = Selector.containsWildcard(selector);\r\n\r\n let dataViewCategorical = dataView.categorical;\r\n if (dataViewCategorical && EnumExtensions.hasFlag(targetDataViewKinds, StandardDataViewKinds.Categorical)) {\r\n // 1) Match against categories\r\n evaluateDataRepetitionCategoricalCategory(dataViewCategorical, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache);\r\n\r\n // 2) Match against valueGrouping\r\n evaluateDataRepetitionCategoricalValueGrouping(dataViewCategorical, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache);\r\n\r\n // Consider capturing diagnostics for unmatched selectors to help debugging.\r\n }\r\n\r\n let dataViewMatrix = dataView.matrix;\r\n if (dataViewMatrix && EnumExtensions.hasFlag(targetDataViewKinds, StandardDataViewKinds.Matrix)) {\r\n let rewrittenMatrix = evaluateDataRepetitionMatrix(dataViewMatrix, objectDescriptors, selector, rules, containsWildcard, objectDefns, colorAllocatorCache);\r\n if (rewrittenMatrix) {\r\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\r\n // revisit this, likely when we do lazy evaluation of DataView.\r\n dataView.matrix = rewrittenMatrix;\r\n }\r\n\r\n // Consider capturing diagnostics for unmatched selectors to help debugging.\r\n }\r\n\r\n let dataViewTable = dataView.table;\r\n if (dataViewTable && EnumExtensions.hasFlag(targetDataViewKinds, StandardDataViewKinds.Table)) {\r\n let rewrittenSelector = rewriteTableRoleSelector(dataViewTable, selector);\r\n let rewrittenTable = evaluateDataRepetitionTable(dataViewTable, selectTransforms, objectDescriptors, rewrittenSelector, rules, containsWildcard, objectDefns, colorAllocatorCache);\r\n if (rewrittenTable) {\r\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\r\n // revisit this, likely when we do lazy evaluation of DataView.\r\n dataView.table = rewrittenTable;\r\n }\r\n\r\n // Consider capturing diagnostics for unmatched selectors to help debugging.\r\n }\r\n }\r\n\r\n function rewriteTableRoleSelector(dataViewTable: DataViewTable, selector: Selector): Selector {\r\n if (Selector.hasRoleWildcard(selector)) {\r\n selector = findSelectorForRoleWildcard(dataViewTable, selector);\r\n }\r\n\r\n return selector;\r\n }\r\n\r\n function findSelectorForRoleWildcard(dataViewTable: DataViewTable, selector: Selector): Selector {\r\n let resultingSelector: Selector = {\r\n data: [],\r\n id: selector.id,\r\n metadata: selector.metadata\r\n };\r\n\r\n for (let dataSelector of selector.data) {\r\n if (Selector.isRoleWildcard(dataSelector)) {\r\n let selectorRoles = dataSelector.roles;\r\n let allColumnsBelongToSelectorRole: boolean = allColumnsBelongToRole(dataViewTable.columns, selectorRoles);\r\n let exprs = dataViewTable.identityFields;\r\n if (allColumnsBelongToSelectorRole && exprs) {\r\n resultingSelector.data.push(DataViewScopeWildcard.fromExprs(<SQExpr[]>exprs));\r\n continue;\r\n }\r\n }\r\n\r\n if (isUniqueDataSelector(resultingSelector.data, dataSelector)) {\r\n resultingSelector.data.push(dataSelector);\r\n }\r\n }\r\n\r\n return resultingSelector;\r\n }\r\n\r\n function isUniqueDataSelector(dataSelectors: DataRepetitionSelector[], newSelector: DataRepetitionSelector): boolean {\r\n if (_.isEmpty(dataSelectors))\r\n return true;\r\n\r\n return !_.any(dataSelectors, (dataSelector: DataRepetitionSelector) => dataSelector.key === newSelector.key);\r\n }\r\n\r\n function allColumnsBelongToRole(columns: DataViewMetadataColumn[], selectorRoles: string[]): boolean {\r\n for (let column of columns) {\r\n var roles = column.roles;\r\n if (!roles || !_.any(selectorRoles, (selectorRole) => roles[selectorRole]))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n function evaluateDataRepetitionCategoricalCategory(\r\n dataViewCategorical: DataViewCategorical,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n containsWildcard: boolean,\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n colorAllocatorCache: IColorAllocatorCache): boolean {\r\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertAnyValue(rules, 'rules');\r\n debug.assertValue(containsWildcard, 'containsWildcard');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\r\n\r\n if (!dataViewCategorical.categories || dataViewCategorical.categories.length === 0)\r\n return;\r\n\r\n let targetColumn = findSelectedCategoricalColumn(dataViewCategorical, selector);\r\n if (!targetColumn)\r\n return;\r\n\r\n let identities = targetColumn.identities,\r\n foundMatch: boolean,\r\n evalContext = createCategoricalEvalContext(colorAllocatorCache, dataViewCategorical);\r\n\r\n if (!identities)\r\n return;\r\n\r\n debug.assert(targetColumn.column.values.length === identities.length, 'Column length mismatch');\r\n\r\n for (let i = 0, len = identities.length; i < len; i++) {\r\n let identity = identities[i];\r\n\r\n if (containsWildcard || Selector.matchesData(selector, [identity])) {\r\n evalContext.setCurrentRowIndex(i);\r\n\r\n let objects = DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\r\n if (objects) {\r\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\r\n // revisit this, likely when we do lazy evaluation of DataView.\r\n if (!targetColumn.column.objects) {\r\n targetColumn.column.objects = [];\r\n targetColumn.column.objects.length = len;\r\n }\r\n targetColumn.column.objects[i] = objects;\r\n }\r\n\r\n if (!containsWildcard)\r\n return true;\r\n\r\n foundMatch = true;\r\n }\r\n }\r\n\r\n return foundMatch;\r\n }\r\n\r\n function evaluateDataRepetitionCategoricalValueGrouping(\r\n dataViewCategorical: DataViewCategorical,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n containsWildcard: boolean,\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n colorAllocatorCache: IColorAllocatorCache): boolean {\r\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertAnyValue(rules, 'rules');\r\n debug.assertValue(containsWildcard, 'containsWildcard');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\r\n\r\n let dataViewCategoricalValues = dataViewCategorical.values;\r\n if (!dataViewCategoricalValues || !dataViewCategoricalValues.identityFields)\r\n return;\r\n\r\n if (!Selector.matchesKeys(selector, <SQExpr[][]>[dataViewCategoricalValues.identityFields]))\r\n return;\r\n\r\n let valuesGrouped = dataViewCategoricalValues.grouped();\r\n if (!valuesGrouped)\r\n return;\r\n\r\n // NOTE: We do not set the evalContext row index below because iteration is over value groups (i.e., columns, no rows).\r\n // This should be enhanced in the future.\r\n let evalContext = createCategoricalEvalContext(colorAllocatorCache, dataViewCategorical);\r\n\r\n let foundMatch: boolean;\r\n for (let i = 0, len = valuesGrouped.length; i < len; i++) {\r\n let valueGroup = valuesGrouped[i];\r\n let selectorMetadata = selector.metadata;\r\n let valuesInGroup = valueGroup.values;\r\n if (containsWildcard || Selector.matchesData(selector, [valueGroup.identity])) {\r\n let objects = DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\r\n if (objects) {\r\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\r\n // revisit this, likely when we do lazy evaluation of DataView.\r\n\r\n if (selectorMetadata) {\r\n for (let j = 0, jlen = valuesInGroup.length; j < jlen; j++) {\r\n let valueColumn = valuesInGroup[j],\r\n valueSource = valueColumn.source;\r\n if (valueSource.queryName === selectorMetadata) {\r\n let valueSourceOverwrite = Prototype.inherit(valueSource);\r\n valueSourceOverwrite.objects = objects;\r\n valueColumn.source = valueSourceOverwrite;\r\n\r\n foundMatch = true;\r\n break;\r\n }\r\n }\r\n }\r\n else {\r\n valueGroup.objects = objects;\r\n setGrouped(dataViewCategoricalValues, valuesGrouped);\r\n\r\n foundMatch = true;\r\n }\r\n }\r\n\r\n if (!containsWildcard)\r\n return true;\r\n }\r\n }\r\n\r\n return foundMatch;\r\n }\r\n\r\n function evaluateDataRepetitionMatrix(\r\n dataViewMatrix: DataViewMatrix,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n containsWildcard: boolean,\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n colorAllocatorCache: IColorAllocatorCache): DataViewMatrix {\r\n\r\n let evalContext = createMatrixEvalContext(colorAllocatorCache, dataViewMatrix);\r\n let rewrittenRows = evaluateDataRepetitionMatrixHierarchy(evalContext, dataViewMatrix.rows, objectDescriptors, selector, rules, containsWildcard, objectDefns);\r\n let rewrittenCols = evaluateDataRepetitionMatrixHierarchy(evalContext, dataViewMatrix.columns, objectDescriptors, selector, rules, containsWildcard, objectDefns);\r\n\r\n if (rewrittenRows || rewrittenCols) {\r\n let rewrittenMatrix = inheritSingle(dataViewMatrix);\r\n\r\n if (rewrittenRows)\r\n rewrittenMatrix.rows = rewrittenRows;\r\n if (rewrittenCols)\r\n rewrittenMatrix.columns = rewrittenCols;\r\n\r\n return rewrittenMatrix;\r\n }\r\n }\r\n\r\n function evaluateDataRepetitionMatrixHierarchy(\r\n evalContext: IEvalContext,\r\n dataViewMatrixHierarchy: DataViewHierarchy,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n containsWildcard: boolean,\r\n objectDefns: DataViewNamedObjectDefinition[]): DataViewHierarchy {\r\n debug.assertAnyValue(dataViewMatrixHierarchy, 'dataViewMatrixHierarchy');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertAnyValue(rules, 'rules');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n\r\n if (!dataViewMatrixHierarchy)\r\n return;\r\n\r\n let root = dataViewMatrixHierarchy.root;\r\n if (!root)\r\n return;\r\n\r\n let rewrittenRoot = evaluateDataRepetitionMatrixNode(evalContext, root, objectDescriptors, selector, rules, containsWildcard, objectDefns);\r\n if (rewrittenRoot) {\r\n let rewrittenHierarchy = inheritSingle(dataViewMatrixHierarchy);\r\n rewrittenHierarchy.root = rewrittenRoot;\r\n\r\n return rewrittenHierarchy;\r\n }\r\n }\r\n\r\n function evaluateDataRepetitionMatrixNode(\r\n evalContext: IEvalContext,\r\n dataViewNode: DataViewMatrixNode,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n containsWildcard: boolean,\r\n objectDefns: DataViewNamedObjectDefinition[]): DataViewMatrixNode {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(dataViewNode, 'dataViewNode');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertAnyValue(rules, 'rules');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n\r\n let childNodes = dataViewNode.children;\r\n if (!childNodes)\r\n return;\r\n\r\n let rewrittenNode: DataViewMatrixNode;\r\n let shouldSearchChildren: boolean;\r\n let childIdentityFields = dataViewNode.childIdentityFields;\r\n if (childIdentityFields) {\r\n // NOTE: selector matching in matrix currently only considers the current node, and does not consider parents as part of the match.\r\n shouldSearchChildren = Selector.matchesKeys(selector, <SQExpr[][]>[childIdentityFields]);\r\n }\r\n\r\n for (let i = 0, len = childNodes.length; i < len; i++) {\r\n let childNode = childNodes[i],\r\n identity = childNode.identity,\r\n rewrittenChildNode: DataViewMatrixNode = null;\r\n\r\n if (shouldSearchChildren) {\r\n if (containsWildcard || Selector.matchesData(selector, [identity])) {\r\n // TODO: Need to initialize context for rule-based properties. Rule-based properties\r\n // (such as fillRule/gradients) are not currently implemented.\r\n\r\n let objects = DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\r\n if (objects) {\r\n rewrittenChildNode = inheritSingle(childNode);\r\n rewrittenChildNode.objects = objects;\r\n }\r\n }\r\n }\r\n else {\r\n rewrittenChildNode = evaluateDataRepetitionMatrixNode(\r\n evalContext,\r\n childNode,\r\n objectDescriptors,\r\n selector,\r\n rules,\r\n containsWildcard,\r\n objectDefns);\r\n }\r\n\r\n if (rewrittenChildNode) {\r\n if (!rewrittenNode)\r\n rewrittenNode = inheritNodeAndChildren(dataViewNode);\r\n rewrittenNode.children[i] = rewrittenChildNode;\r\n\r\n if (!containsWildcard) {\r\n // NOTE: once we find a match for a non-wildcard selector, stop looking.\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return rewrittenNode;\r\n }\r\n\r\n function inheritNodeAndChildren(node: DataViewMatrixNode): DataViewMatrixNode {\r\n if (Object.getPrototypeOf(node) !== Object.prototype) {\r\n return node;\r\n }\r\n\r\n let inherited = inheritSingle(node);\r\n inherited.children = inherit(node.children);\r\n return inherited;\r\n }\r\n\r\n function evaluateDataRepetitionTable(\r\n dataViewTable: DataViewTable,\r\n selectTransforms: DataViewSelectTransform[],\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n containsWildcard: boolean,\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n colorAllocatorCache: IColorAllocatorCache): DataViewTable {\r\n debug.assertValue(dataViewTable, 'dataViewTable');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertAnyValue(rules, 'rules');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\r\n\r\n let evalContext = createTableEvalContext(colorAllocatorCache, dataViewTable, selectTransforms);\r\n let rewrittenRows = evaluateDataRepetitionTableRows(\r\n evalContext,\r\n dataViewTable.columns,\r\n dataViewTable.rows,\r\n dataViewTable.identity,\r\n dataViewTable.identityFields,\r\n objectDescriptors,\r\n selector,\r\n rules,\r\n containsWildcard,\r\n objectDefns);\r\n\r\n if (rewrittenRows) {\r\n let rewrittenTable = inheritSingle(dataViewTable);\r\n rewrittenTable.rows = rewrittenRows;\r\n\r\n return rewrittenTable;\r\n }\r\n }\r\n\r\n function evaluateDataRepetitionTableRows(\r\n evalContext: ITableEvalContext,\r\n columns: DataViewMetadataColumn[],\r\n rows: DataViewTableRow[],\r\n identities: DataViewScopeIdentity[],\r\n identityFields: ISQExpr[],\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n rules: RuleEvaluation[],\r\n containsWildcard: boolean,\r\n objectDefns: DataViewNamedObjectDefinition[]): DataViewTableRow[] {\r\n debug.assertValue(evalContext, 'evalContext');\r\n debug.assertValue(columns, 'columns');\r\n debug.assertValue(rows, 'rows');\r\n debug.assertAnyValue(identities, 'identities');\r\n debug.assertAnyValue(identityFields, 'identityFields');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertAnyValue(rules, 'rules');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n\r\n if (_.isEmpty(identities) || _.isEmpty(identityFields))\r\n return;\r\n\r\n if (!selector.metadata ||\r\n !Selector.matchesKeys(selector, <SQExpr[][]>[identityFields]))\r\n return;\r\n\r\n let colIdx = _.findIndex(columns, col => col.queryName === selector.metadata);\r\n if (colIdx < 0)\r\n return;\r\n\r\n debug.assert(rows.length === identities.length, 'row length mismatch');\r\n let colLen = columns.length;\r\n let inheritedRows: DataViewTableRow[];\r\n\r\n for (let rowIdx = 0, rowLen = identities.length; rowIdx < rowLen; rowIdx++) {\r\n let identity = identities[rowIdx];\r\n\r\n if (containsWildcard || Selector.matchesData(selector, [identity])) {\r\n evalContext.setCurrentRowIndex(rowIdx);\r\n\r\n let objects = DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\r\n if (objects) {\r\n if (!inheritedRows)\r\n inheritedRows = inheritSingle(rows);\r\n\r\n let inheritedRow = inheritedRows[rowIdx] = inheritSingle(inheritedRows[rowIdx]);\r\n let objectsForColumns = inheritedRow.objects;\r\n if (!objectsForColumns)\r\n inheritedRow.objects = objectsForColumns = new Array(colLen);\r\n\r\n objectsForColumns[colIdx] = objects;\r\n }\r\n\r\n if (!containsWildcard)\r\n break;\r\n }\r\n }\r\n\r\n return inheritedRows;\r\n }\r\n\r\n function evaluateMetadataRepetition(\r\n dataView: DataView,\r\n selectTransforms: DataViewSelectTransform[],\r\n objectDescriptors: DataViewObjectDescriptors,\r\n selector: Selector,\r\n objectDefns: DataViewNamedObjectDefinition[],\r\n colorAllocatorCache: IColorAllocatorCache): void {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(selector, 'selector');\r\n debug.assertValue(objectDefns, 'objectDefns');\r\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\r\n\r\n // TODO: This mutates the DataView -- the assumption is that prototypal inheritance has already occurred. We should\r\n // revisit this, likely when we do lazy evaluation of DataView.\r\n let columns = dataView.metadata.columns,\r\n metadataId = selector.metadata,\r\n evalContext = createStaticEvalContext(colorAllocatorCache, dataView, selectTransforms);\r\n for (let i = 0, len = columns.length; i < len; i++) {\r\n let column = columns[i];\r\n if (column.queryName === metadataId) {\r\n let objects = DataViewObjectEvaluationUtils.evaluateDataViewObjects(evalContext, objectDescriptors, objectDefns);\r\n if (objects)\r\n column.objects = objects;\r\n }\r\n }\r\n }\r\n\r\n /** Attempts to find a column that can possibly match the selector. */\r\n function findSelectedCategoricalColumn(dataViewCategorical: DataViewCategorical, selector: Selector) {\r\n debug.assertValue(dataViewCategorical.categories[0], 'dataViewCategorical.categories[0]');\r\n\r\n let categoricalColumn = dataViewCategorical.categories[0];\r\n if (!categoricalColumn.identityFields)\r\n return;\r\n if (!Selector.matchesKeys(selector, <SQExpr[][]>[categoricalColumn.identityFields]))\r\n return;\r\n\r\n let identities = categoricalColumn.identity,\r\n targetColumn: DataViewCategoricalColumn = categoricalColumn;\r\n\r\n let selectedMetadataId = selector.metadata;\r\n if (selectedMetadataId) {\r\n let valueColumns = dataViewCategorical.values;\r\n if (valueColumns) {\r\n for (let i = 0, len = valueColumns.length; i < len; i++) {\r\n let valueColumn = valueColumns[i];\r\n if (valueColumn.source.queryName === selectedMetadataId) {\r\n targetColumn = valueColumn;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n column: targetColumn,\r\n identities: identities,\r\n };\r\n }\r\n\r\n function findSelectorForRuleInput(dataView: DataView, selectorRoles: string[]): Selector {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(selectorRoles, 'selectorRoles');\r\n\r\n if (selectorRoles.length !== 1)\r\n return;\r\n\r\n let dataViewCategorical = dataView.categorical;\r\n if (!dataViewCategorical)\r\n return;\r\n\r\n let categories = dataViewCategorical.categories;\r\n if (!categories || categories.length !== 1)\r\n return;\r\n\r\n let categoryColumn = categories[0],\r\n categoryRoles = categoryColumn.source.roles,\r\n categoryIdentityFields = categoryColumn.identityFields;\r\n if (!categoryRoles || !categoryIdentityFields || !categoryRoles[selectorRoles[0]])\r\n return;\r\n\r\n return { data: [DataViewScopeWildcard.fromExprs(<SQExpr[]>categoryIdentityFields)] };\r\n }\r\n\r\n function findFirstQueryNameForExpr(selectTransforms: DataViewSelectTransform[], expr: SQExpr): string {\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(expr, 'expr');\r\n\r\n if (SQExpr.isSelectRef(expr))\r\n return expr.expressionName;\r\n\r\n if (!selectTransforms)\r\n return;\r\n\r\n for (let i = 0, len = selectTransforms.length; i < len; i++) {\r\n let select = selectTransforms[i],\r\n columnExpr = select.expr;\r\n\r\n if (!columnExpr || !SQExpr.equals(expr, select.expr))\r\n continue;\r\n\r\n return select.queryName;\r\n }\r\n }\r\n\r\n /** Attempts to find the value range for the single column with the given identifier/identifierKind. */\r\n function findRuleInputColumnNumberRange(dataView: DataView, identifier: string, identifierKind: ColumnIdentifierKind): NumberRange {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(identifier, 'identifier');\r\n debug.assertValue(identifierKind, 'identifierKind');\r\n\r\n let columns = dataView.metadata.columns;\r\n\r\n for (let i = 0, len = columns.length; i < len; i++) {\r\n let column = columns[i];\r\n\r\n if (identifierKind === ColumnIdentifierKind.Role) {\r\n let valueColRoles = column.roles;\r\n\r\n if (!valueColRoles || !valueColRoles[identifier])\r\n continue;\r\n }\r\n else {\r\n debug.assert(identifierKind === ColumnIdentifierKind.QueryName, 'identifierKind === ColumnIdentifierKind.QueryName');\r\n\r\n if (column.queryName !== identifier)\r\n continue;\r\n }\r\n\r\n let aggregates = column.aggregates;\r\n if (!aggregates)\r\n continue;\r\n\r\n let min = <number>aggregates.min;\r\n if (min === undefined)\r\n min = <number>aggregates.minLocal;\r\n if (min === undefined)\r\n continue;\r\n\r\n let max = <number>aggregates.max;\r\n if (max === undefined)\r\n max = <number>aggregates.maxLocal;\r\n if (max === undefined)\r\n continue;\r\n\r\n return { min: min, max: max };\r\n }\r\n }\r\n\r\n // TODO: refactor this, setGrouped, and groupValues to a test helper to stop using it in the product\r\n export function createValueColumns(\r\n values: DataViewValueColumn[] = [],\r\n valueIdentityFields?: SQExpr[],\r\n source?: DataViewMetadataColumn): DataViewValueColumns {\r\n let result = <DataViewValueColumns>values;\r\n setGrouped(<DataViewValueColumns>values);\r\n\r\n if (valueIdentityFields)\r\n result.identityFields = valueIdentityFields;\r\n\r\n if (source)\r\n result.source = source;\r\n\r\n return result;\r\n }\r\n\r\n export function setGrouped(values: DataViewValueColumns, groupedResult?: DataViewValueColumnGroup[]): void {\r\n values.grouped = groupedResult\r\n ? () => groupedResult\r\n : () => groupValues(values);\r\n }\r\n\r\n /** Group together the values with a common identity. */\r\n function groupValues(values: DataViewValueColumn[]): DataViewValueColumnGroup[] {\r\n debug.assertValue(values, 'values');\r\n\r\n let groups: DataViewValueColumnGroup[] = [],\r\n currentGroup: DataViewValueColumnGroup;\r\n\r\n for (let i = 0, len = values.length; i < len; i++) {\r\n let value = values[i];\r\n\r\n if (!currentGroup || currentGroup.identity !== value.identity) {\r\n currentGroup = {\r\n values: []\r\n };\r\n\r\n if (value.identity) {\r\n currentGroup.identity = value.identity;\r\n\r\n let source = value.source;\r\n\r\n // allow null, which will be formatted as (Blank).\r\n if (source.groupName !== undefined)\r\n currentGroup.name = source.groupName;\r\n else if (source.displayName)\r\n currentGroup.name = source.displayName;\r\n }\r\n\r\n groups.push(currentGroup);\r\n }\r\n\r\n currentGroup.values.push(value);\r\n }\r\n\r\n return groups;\r\n }\r\n\r\n function pivotIfNecessary(dataView: DataView, dataViewMappings: DataViewMapping[]): DataView {\r\n debug.assertValue(dataView, 'dataView');\r\n\r\n let transformedDataView: DataView;\r\n switch (determineCategoricalTransformation(dataView.categorical, dataViewMappings)) {\r\n case CategoricalDataViewTransformation.Pivot:\r\n transformedDataView = DataViewPivotCategorical.apply(dataView);\r\n break;\r\n\r\n case CategoricalDataViewTransformation.SelfCrossJoin:\r\n transformedDataView = DataViewSelfCrossJoin.apply(dataView);\r\n break;\r\n }\r\n\r\n return transformedDataView || dataView;\r\n }\r\n\r\n function determineCategoricalTransformation(categorical: DataViewCategorical, dataViewMappings: DataViewMapping[]): CategoricalDataViewTransformation {\r\n if (!categorical || _.isEmpty(dataViewMappings))\r\n return;\r\n\r\n let categories = categorical.categories;\r\n if (!categories || categories.length !== 1)\r\n return;\r\n\r\n let values = categorical.values;\r\n if (_.isEmpty(values))\r\n return;\r\n\r\n if (values.grouped().some(vg => !!vg.identity))\r\n return;\r\n\r\n // If we made it here, the DataView has a single category and no valueGrouping.\r\n let categoryRoles = categories[0].source.roles;\r\n\r\n for (let i = 0, len = dataViewMappings.length; i < len; i++) {\r\n let roleMappingCategorical = dataViewMappings[i].categorical;\r\n if (!roleMappingCategorical)\r\n continue;\r\n\r\n if (!hasRolesGrouped(categoryRoles, <DataViewGroupedRoleMapping>roleMappingCategorical.values))\r\n continue;\r\n\r\n // If we made it here, the DataView's single category has the value grouping role.\r\n let categoriesMapping = roleMappingCategorical.categories;\r\n let hasCategoryRole =\r\n hasRolesBind(categoryRoles, <DataViewRoleBindMappingWithReduction>categoriesMapping) ||\r\n hasRolesFor(categoryRoles, <DataViewRoleForMappingWithReduction>categoriesMapping);\r\n\r\n if (hasCategoryRole)\r\n return CategoricalDataViewTransformation.SelfCrossJoin;\r\n\r\n return CategoricalDataViewTransformation.Pivot;\r\n }\r\n }\r\n\r\n function shouldPivotMatrix(matrix: DataViewMatrix, dataViewMappings: DataViewMapping[]): boolean {\r\n if (!matrix || _.isEmpty(dataViewMappings))\r\n return;\r\n\r\n let rowLevels = matrix.rows.levels;\r\n if (rowLevels.length < 1)\r\n return;\r\n\r\n let rows = matrix.rows.root.children;\r\n if (!rows || rows.length === 0)\r\n return;\r\n\r\n let rowRoles = rowLevels[0].sources[0].roles;\r\n\r\n for (let i = 0, len = dataViewMappings.length; i < len; i++) {\r\n let roleMappingMatrix = dataViewMappings[i].matrix;\r\n if (!roleMappingMatrix)\r\n continue;\r\n\r\n if (!hasRolesFor(rowRoles, <DataViewRoleForMappingWithReduction>roleMappingMatrix.rows) &&\r\n hasRolesFor(rowRoles, <DataViewRoleForMappingWithReduction>roleMappingMatrix.columns)) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n function hasRolesBind(roles: { [name: string]: boolean }, roleMapping: DataViewRoleBindMappingWithReduction): boolean {\r\n if (roles && roleMapping && roleMapping.bind)\r\n return roles[roleMapping.bind.to];\r\n }\r\n\r\n function hasRolesFor(roles: { [name: string]: boolean }, roleMapping: DataViewRoleForMappingWithReduction): boolean {\r\n if (roles && roleMapping && roleMapping.for)\r\n return roles[roleMapping.for.in];\r\n }\r\n\r\n function hasRolesGrouped(roles: { [name: string]: boolean }, roleMapping: DataViewGroupedRoleMapping): boolean {\r\n if (roles && roleMapping && roleMapping.group)\r\n return roles[roleMapping.group.by];\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import IStringResourceProvider = jsCommon.IStringResourceProvider;\r\n\r\n export function createDisplayNameGetter(displayNameKey: string): (IStringResourceProvider) => string {\r\n return (resourceProvider: IStringResourceProvider) => resourceProvider.get(displayNameKey);\r\n }\r\n\r\n export function getDisplayName(displayNameGetter: data.DisplayNameGetter, resourceProvider: jsCommon.IStringResourceProvider): string {\r\n if (typeof displayNameGetter === 'function')\r\n return displayNameGetter(resourceProvider);\r\n\r\n if (typeof displayNameGetter === 'string')\r\n return displayNameGetter;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n /** Enumeration of DateTimeUnits */\r\n export enum DateTimeUnit {\r\n Year,\r\n Month,\r\n Week,\r\n Day,\r\n Hour,\r\n Minute,\r\n Second,\r\n Millisecond,\r\n }\r\n\r\n export interface IFormattingService {\r\n /** \r\n * Formats the value using provided format expression and culture\r\n * @param value - value to be formatted and converted to string.\r\n * @param format - format to be applied. If undefined or empty then generic format is used. \r\n */\r\n formatValue(value: any, format?: string): string;\r\n\r\n /** \r\n * Replaces the indexed format tokens (for example {0:c2}) in the format string with the localized formatted arguments.\r\n * @param formatWithIndexedTokens - format string with a set of indexed format tokens.\r\n * @param args - array of values which should replace the tokens in the format string.\r\n * @param culture - localization culture. If undefined then the current culture is used.\r\n */\r\n format(formatWithIndexedTokens: string, args: any[], culture?: string): string;\r\n\r\n /** Gets a value indicating whether the specified format a standard numeric format specifier. */\r\n isStandardNumberFormat(format: string): boolean;\r\n\r\n /** Performs a custom format with a value override. Typically used for custom formats showing scaled values. */\r\n formatNumberWithCustomOverride(value: number, format: string, nonScientificOverrideFormat: string): string;\r\n\r\n /** Gets the format string to use for dates in particular units. */\r\n dateFormatString(unit: DateTimeUnit): string;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n /** Represents common expression patterns for 'field' expressions such as columns, column aggregates, measures, etc. */\r\n export interface FieldExprPattern {\r\n column?: FieldExprColumnPattern;\r\n columnAggr?: FieldExprColumnAggrPattern;\r\n columnHierarchyLevelVariation?: FieldExprColumnHierarchyLevelVariationPattern;\r\n entity?: FieldExprEntityPattern;\r\n entityAggr?: FieldExprEntityAggrPattern;\r\n hierarchy?: FieldExprHierarchyPattern;\r\n hierarchyLevel?: FieldExprHierarchyLevelPattern;\r\n hierarchyLevelAggr?: FieldExprHierarchyLevelAggrPattern;\r\n measure?: FieldExprMeasurePattern;\r\n percentile?: FieldExprPercentilePattern;\r\n percentOfGrandTotal?: FieldExprPercentOfGrandTotalPattern;\r\n selectRef?: FieldExprSelectRefPattern;\r\n }\r\n\r\n /** By design there is no default, no-op visitor. Components concerned with patterns need to be aware of all patterns as they are added. */\r\n export interface IFieldExprPatternVisitor<T> {\r\n visitColumn(column: FieldExprColumnPattern): T;\r\n visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): T;\r\n visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): T;\r\n visitEntity(entity: FieldExprEntityPattern): T;\r\n visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): T;\r\n visitHierarchy(hierarchy: FieldExprHierarchyPattern): T;\r\n visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): T;\r\n visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): T;\r\n visitMeasure(measure: FieldExprMeasurePattern): T;\r\n visitPercentile(percentile: FieldExprPercentilePattern): T;\r\n visitPercentOfGrandTotal(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern): T;\r\n visitSelectRef(selectRef: FieldExprSelectRefPattern): T;\r\n }\r\n\r\n export interface FieldExprEntityPattern {\r\n schema: string;\r\n entity: string;\r\n entityVar?: string;\r\n }\r\n\r\n export interface FieldExprEntityItemPattern extends FieldExprEntityPattern {\r\n }\r\n\r\n export interface FieldExprEntityPropertyPattern extends FieldExprEntityItemPattern {\r\n name: string;\r\n }\r\n\r\n export type FieldExprColumnPattern = FieldExprEntityPropertyPattern;\r\n export type FieldExprMeasurePattern = FieldExprEntityPropertyPattern;\r\n export type FieldExprHierarchyPattern = FieldExprEntityPropertyPattern;\r\n\r\n export type FieldExprPropertyPattern = FieldExprColumnPattern | FieldExprMeasurePattern | FieldExprHierarchyPattern;\r\n\r\n export interface FieldExprEntityAggrPattern extends FieldExprEntityPattern {\r\n aggregate: QueryAggregateFunction;\r\n }\r\n\r\n export interface FieldExprColumnAggrPattern extends FieldExprColumnPattern {\r\n aggregate: QueryAggregateFunction;\r\n }\r\n\r\n export interface FieldExprHierarchyLevelPattern extends FieldExprEntityItemPattern {\r\n name: string;\r\n level: string;\r\n }\r\n\r\n export interface FieldExprHierarchyLevelAggrPattern extends FieldExprHierarchyLevelPattern {\r\n aggregate: QueryAggregateFunction;\r\n }\r\n\r\n export interface FieldExprColumnHierarchyLevelVariationPattern {\r\n source: FieldExprColumnPattern;\r\n level: FieldExprHierarchyLevelPattern;\r\n variationName: string;\r\n }\r\n\r\n export interface FieldExprPercentilePattern {\r\n arg: FieldExprPattern;\r\n k: number;\r\n exclusive: boolean;\r\n }\r\n\r\n export interface FieldExprPercentOfGrandTotalPattern {\r\n baseExpr: FieldExprPattern;\r\n }\r\n\r\n export interface FieldExprSelectRefPattern {\r\n expressionName: string;\r\n }\r\n\r\n export module SQExprBuilder {\r\n export function fieldExpr(fieldExpr: FieldExprPattern): SQExpr {\r\n let sqExpr = FieldExprPattern.visit<SQExpr>(fieldExpr, FieldExprToSQExprVisitor.instance);\r\n debug.assertValue(sqExpr, 'Failed to convert FieldExprPattern into SQExpr');\r\n return sqExpr;\r\n }\r\n\r\n export function fromColumnAggr(columnAggr: FieldExprColumnAggrPattern): SQAggregationExpr {\r\n return aggregate(fromColumn(columnAggr), columnAggr.aggregate);\r\n }\r\n\r\n export function fromColumn(column: FieldExprColumnPattern): SQColumnRefExpr {\r\n return columnRef(fromEntity(column), column.name);\r\n }\r\n\r\n export function fromEntity(entityPattern: FieldExprEntityPattern): SQEntityExpr {\r\n return entity(entityPattern.schema, entityPattern.entity, entityPattern.entityVar);\r\n }\r\n\r\n export function fromEntityAggr(entityAggr: FieldExprEntityAggrPattern): SQAggregationExpr {\r\n return aggregate(fromEntity(entityAggr), entityAggr.aggregate);\r\n }\r\n\r\n export function fromHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): SQAggregationExpr {\r\n return aggregate(fromHierarchyLevel(hierarchyLevelAggr), hierarchyLevelAggr.aggregate);\r\n }\r\n\r\n export function fromHierarchyLevel(hierarchyLevelPattern: FieldExprHierarchyLevelPattern): SQHierarchyLevelExpr {\r\n return hierarchyLevel(fromHierarchy(hierarchyLevelPattern), hierarchyLevelPattern.level);\r\n }\r\n\r\n export function fromHierarchy(hierarchyPattern: FieldExprHierarchyPattern): SQHierarchyExpr {\r\n return hierarchy(fromEntity(hierarchyPattern), hierarchyPattern.name);\r\n }\r\n\r\n class FieldExprToSQExprVisitor implements IFieldExprPatternVisitor<SQExpr> {\r\n public static instance: FieldExprToSQExprVisitor = new FieldExprToSQExprVisitor();\r\n\r\n public visitColumn(column: FieldExprColumnPattern): SQColumnRefExpr {\r\n return fromColumn(column);\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): SQAggregationExpr {\r\n return fromColumnAggr(columnAggr);\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariationPattern: FieldExprColumnHierarchyLevelVariationPattern): SQPropertyVariationSourceExpr {\r\n return propertyVariationSource(\r\n this.visitEntity(columnHierarchyLevelVariationPattern.source),\r\n columnHierarchyLevelVariationPattern.source.name,\r\n columnHierarchyLevelVariationPattern.level.name);\r\n }\r\n\r\n public visitEntity(entityPattern: FieldExprEntityPattern): SQEntityExpr {\r\n return fromEntity(entityPattern);\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): SQAggregationExpr {\r\n return fromEntityAggr(entityAggr);\r\n }\r\n\r\n public visitHierarchy(hierarchyPattern: FieldExprHierarchyPattern): SQHierarchyExpr {\r\n return fromHierarchy(hierarchyPattern);\r\n }\r\n\r\n public visitHierarchyLevel(level: FieldExprHierarchyLevelPattern): SQHierarchyLevelExpr {\r\n return fromHierarchyLevel(level);\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): SQAggregationExpr {\r\n return fromHierarchyLevelAggr(hierarchyLevelAggr);\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): SQMeasureRefExpr {\r\n return measureRef(this.visitEntity(measure), measure.name);\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): SQPercentileExpr {\r\n let arg = SQExprBuilder.fieldExpr(percentile.arg);\r\n return SQExprBuilder.percentile(arg, percentile.k, percentile.exclusive);\r\n }\r\n\r\n public visitPercentOfGrandTotal(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern): SQArithmeticExpr {\r\n let baseSQExpr = SQExprBuilder.fieldExpr(percentOfGrandTotal.baseExpr);\r\n return arithmetic(\r\n baseSQExpr,\r\n SQExprBuilder.scopedEval(baseSQExpr, []),\r\n ArithmeticOperatorKind.Divide);\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): SQSelectRefExpr {\r\n return SQExprBuilder.selectRef(selectRef.expressionName);\r\n }\r\n }\r\n }\r\n\r\n export module SQExprConverter {\r\n export function asFieldPattern(sqExpr: SQExpr): FieldExprPattern {\r\n return sqExpr.accept(FieldExprPatternBuilder.instance);\r\n }\r\n }\r\n\r\n interface FieldExprSourceVariationPattern {\r\n column: FieldExprColumnPattern;\r\n variationName: string;\r\n }\r\n\r\n interface SourceExprPattern {\r\n entity?: FieldExprEntityPattern;\r\n\r\n // TODO: Change FieldExprHierarchyPattern to FieldExprHierarchyLevelPattern\r\n hierarchy?: FieldExprHierarchyPattern;\r\n variation?: FieldExprSourceVariationPattern;\r\n }\r\n\r\n interface HierarchySourceExprPattern {\r\n hierarchy: FieldExprHierarchyPattern;\r\n variation?: FieldExprSourceVariationPattern;\r\n }\r\n\r\n class FieldExprPatternBuilder extends DefaultSQExprVisitor<FieldExprPattern> {\r\n public static instance: FieldExprPatternBuilder = new FieldExprPatternBuilder();\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): FieldExprPattern {\r\n let sourceRef = expr.source.accept(SourceExprPatternBuilder.instance);\r\n if (!sourceRef)\r\n return;\r\n\r\n if (sourceRef.entity) {\r\n let columnRef = <FieldExprColumnPattern>sourceRef.entity;\r\n columnRef.name = expr.ref;\r\n\r\n return { column: columnRef };\r\n }\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr): FieldExprPattern {\r\n let sourceRef = expr.source.accept(SourceExprPatternBuilder.instance);\r\n if (!sourceRef)\r\n return;\r\n\r\n if (sourceRef.entity) {\r\n let measureRef = <FieldExprMeasurePattern>sourceRef.entity;\r\n measureRef.name = expr.ref;\r\n\r\n return { measure: measureRef };\r\n }\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): FieldExprPattern {\r\n let entityRef: FieldExprEntityPattern = {\r\n schema: expr.schema,\r\n entity: expr.entity\r\n };\r\n if (expr.variable)\r\n entityRef.entityVar = expr.variable;\r\n\r\n return { entity: entityRef };\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): FieldExprPattern {\r\n let fieldPattern: FieldExprPattern = expr.arg.accept(this);\r\n if (fieldPattern && fieldPattern.column) {\r\n let argAggr = <FieldExprColumnAggrPattern>fieldPattern.column;\r\n argAggr.aggregate = expr.func;\r\n return { columnAggr: argAggr };\r\n } else if (fieldPattern && fieldPattern.columnAggr) {\r\n let argAggr = <FieldExprColumnAggrPattern>fieldPattern.columnAggr;\r\n argAggr.aggregate = expr.func;\r\n return { columnAggr: argAggr };\r\n } else if (fieldPattern && fieldPattern.hierarchyLevel) {\r\n let argAggr = <FieldExprHierarchyLevelAggrPattern>fieldPattern.hierarchyLevel;\r\n argAggr.aggregate = expr.func;\r\n return { hierarchyLevelAggr: argAggr };\r\n }\r\n\r\n let sourcePattern = expr.arg.accept(SourceExprPatternBuilder.instance);\r\n if (sourcePattern && sourcePattern.entity) {\r\n let argAggr = <FieldExprEntityAggrPattern>sourcePattern.entity;\r\n argAggr.aggregate = expr.func;\r\n\r\n return { entityAggr: argAggr };\r\n }\r\n }\r\n\r\n public visitPercentile(expr: SQPercentileExpr): FieldExprPattern {\r\n return {\r\n percentile: {\r\n arg: expr.arg.accept(this),\r\n k: expr.k,\r\n exclusive: expr.exclusive,\r\n }\r\n };\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): FieldExprPattern {\r\n let sourcePattern = expr.arg.accept(SourceExprPatternBuilder.instance);\r\n\r\n if (sourcePattern && sourcePattern.entity) {\r\n let hierarchyRef = <FieldExprHierarchyPattern>(sourcePattern.entity);\r\n hierarchyRef.name = expr.hierarchy;\r\n return { hierarchy: hierarchyRef };\r\n }\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): FieldExprPattern {\r\n let hierarchySourceExprPattern: HierarchySourceExprPattern = expr.arg.accept(HierarchyExprPatternBuiler.instance);\r\n if (!hierarchySourceExprPattern)\r\n return;\r\n\r\n let hierarchyLevel: FieldExprHierarchyLevelPattern;\r\n if (hierarchySourceExprPattern.hierarchy) {\r\n hierarchyLevel = {\r\n entity: hierarchySourceExprPattern.hierarchy.entity,\r\n schema: hierarchySourceExprPattern.hierarchy.schema,\r\n name: hierarchySourceExprPattern.hierarchy.name,\r\n level: expr.level,\r\n };\r\n }\r\n\r\n if (hierarchySourceExprPattern.variation) {\r\n return {\r\n columnHierarchyLevelVariation: {\r\n source: {\r\n entity: hierarchySourceExprPattern.variation.column.entity,\r\n schema: hierarchySourceExprPattern.variation.column.schema,\r\n name: hierarchySourceExprPattern.variation.column.name,\r\n },\r\n level: hierarchyLevel,\r\n variationName: hierarchySourceExprPattern.variation.variationName,\r\n }\r\n };\r\n }\r\n\r\n return { hierarchyLevel: hierarchyLevel };\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr): FieldExprPattern {\r\n let percentOfGrandTotalPattern: FieldExprPattern = {\r\n percentOfGrandTotal: {\r\n baseExpr: expr.left.accept(this)\r\n }\r\n };\r\n\r\n if (SQExpr.equals(expr, SQExprBuilder.fieldExpr(percentOfGrandTotalPattern))) {\r\n return percentOfGrandTotalPattern;\r\n }\r\n }\r\n\r\n public visitSelectRef(expr: SQSelectRefExpr): FieldExprPattern {\r\n return {\r\n selectRef: {\r\n expressionName: expr.expressionName,\r\n }\r\n };\r\n }\r\n }\r\n\r\n class SourceExprPatternBuilder extends DefaultSQExprVisitor<SourceExprPattern> {\r\n public static instance: SourceExprPatternBuilder = new SourceExprPatternBuilder();\r\n\r\n public visitEntity(expr: SQEntityExpr): SourceExprPattern {\r\n let entityRef: FieldExprEntityPattern = {\r\n schema: expr.schema,\r\n entity: expr.entity\r\n };\r\n if (expr.variable)\r\n entityRef.entityVar = expr.variable;\r\n\r\n return { entity: entityRef };\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr): SourceExprPattern {\r\n let entityExpr = <SQEntityExpr>expr.arg;\r\n\r\n if (entityExpr instanceof SQEntityExpr) {\r\n let propertyVariationSource: FieldExprColumnPattern = {\r\n schema: entityExpr.schema,\r\n entity: entityExpr.entity,\r\n name: expr.property,\r\n };\r\n\r\n if (entityExpr.variable)\r\n propertyVariationSource.entityVar = entityExpr.variable;\r\n\r\n return {\r\n variation: {\r\n column: propertyVariationSource,\r\n variationName: expr.name,\r\n }\r\n };\r\n }\r\n }\r\n }\r\n\r\n class HierarchyExprPatternBuiler extends DefaultSQExprVisitor<HierarchySourceExprPattern> {\r\n public static instance: HierarchyExprPatternBuiler = new HierarchyExprPatternBuiler();\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): HierarchySourceExprPattern {\r\n let exprPattern = expr.arg.accept(SourceExprPatternBuilder.instance);\r\n let hierarchyRef: FieldExprHierarchyPattern;\r\n let variationRef: FieldExprSourceVariationPattern;\r\n\r\n if (exprPattern.variation) {\r\n hierarchyRef = {\r\n name: expr.hierarchy,\r\n schema: exprPattern.variation.column.schema,\r\n entity: exprPattern.variation.column.entity,\r\n };\r\n variationRef = exprPattern.variation;\r\n }\r\n else\r\n hierarchyRef = {\r\n name: expr.hierarchy,\r\n schema: exprPattern.entity.schema,\r\n entity: exprPattern.entity.entity,\r\n };\r\n\r\n return {\r\n hierarchy: hierarchyRef,\r\n variation: variationRef\r\n };\r\n }\r\n }\r\n\r\n export module FieldExprPattern {\r\n\r\n export function visit<T>(expr: SQExpr | FieldExprPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n let fieldExprPattern = expr instanceof SQExpr ? SQExprConverter.asFieldPattern(expr) : expr;\r\n debug.assertValue(fieldExprPattern, 'expected sqExpr to conform to a fieldExprPattern');\r\n\r\n if (fieldExprPattern.column)\r\n return visitColumn(fieldExprPattern.column, visitor);\r\n if (fieldExprPattern.columnAggr)\r\n return visitColumnAggr(fieldExprPattern.columnAggr, visitor);\r\n if (fieldExprPattern.columnHierarchyLevelVariation)\r\n return visitColumnHierarchyLevelVariation(fieldExprPattern.columnHierarchyLevelVariation, visitor);\r\n if (fieldExprPattern.entity)\r\n return visitEntity(fieldExprPattern.entity, visitor);\r\n if (fieldExprPattern.entityAggr)\r\n return visitEntityAggr(fieldExprPattern.entityAggr, visitor);\r\n if (fieldExprPattern.hierarchy)\r\n return visitHierarchy(fieldExprPattern.hierarchy, visitor);\r\n if (fieldExprPattern.hierarchyLevel)\r\n return visitHierarchyLevel(fieldExprPattern.hierarchyLevel, visitor);\r\n if (fieldExprPattern.hierarchyLevelAggr)\r\n return visitHierarchyLevelAggr(fieldExprPattern.hierarchyLevelAggr, visitor);\r\n if (fieldExprPattern.measure)\r\n return visitMeasure(fieldExprPattern.measure, visitor);\r\n if (fieldExprPattern.percentile)\r\n return visitPercentile(fieldExprPattern.percentile, visitor);\r\n if (fieldExprPattern.percentOfGrandTotal)\r\n return visitPercentOfGrandTotal(fieldExprPattern.percentOfGrandTotal, visitor);\r\n if (fieldExprPattern.selectRef)\r\n return visitSelectRef(fieldExprPattern.selectRef, visitor);\r\n\r\n debug.assertFail('failed to visit a fieldExprPattern.');\r\n return;\r\n }\r\n\r\n function visitColumn<T>(column: FieldExprColumnPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(column, 'column');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitColumn(column);\r\n }\r\n\r\n function visitColumnAggr<T>(columnAggr: FieldExprColumnAggrPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(columnAggr, 'columnAggr');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitColumnAggr(columnAggr);\r\n }\r\n\r\n function visitColumnHierarchyLevelVariation<T>(\r\n columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern,\r\n visitor: IFieldExprPatternVisitor<T>): T {\r\n\r\n debug.assertValue(columnHierarchyLevelVariation, 'columnHierarchyLevelVariation');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation);\r\n }\r\n\r\n function visitEntity<T>(entity: FieldExprEntityPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(entity, 'entity');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitEntity(entity);\r\n }\r\n\r\n function visitEntityAggr<T>(entityAggr: FieldExprEntityAggrPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(entityAggr, 'entityAggr');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitEntityAggr(entityAggr);\r\n }\r\n\r\n function visitHierarchy<T>(hierarchy: FieldExprHierarchyPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(hierarchy, 'hierarchy');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitHierarchy(hierarchy);\r\n }\r\n\r\n function visitHierarchyLevel<T>(hierarchyLevel: FieldExprHierarchyLevelPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(hierarchyLevel, 'hierarchyLevel');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitHierarchyLevel(hierarchyLevel);\r\n }\r\n\r\n function visitHierarchyLevelAggr<T>(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(hierarchyLevelAggr, 'hierarchyLevelAggr');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitHierarchyLevelAggr(hierarchyLevelAggr);\r\n }\r\n\r\n function visitMeasure<T>(measure: FieldExprMeasurePattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(measure, 'measure');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitMeasure(measure);\r\n }\r\n\r\n function visitSelectRef<T>(selectRef: FieldExprSelectRefPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(selectRef, 'selectRef');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitSelectRef(selectRef);\r\n }\r\n\r\n function visitPercentile<T>(percentile: FieldExprPercentilePattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(percentile, 'percentile');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitPercentile(percentile);\r\n }\r\n\r\n function visitPercentOfGrandTotal<T>(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern, visitor: IFieldExprPatternVisitor<T>): T {\r\n debug.assertValue(percentOfGrandTotal, 'percentOfGrandTotal');\r\n debug.assertValue(visitor, 'visitor');\r\n\r\n return visitor.visitPercentOfGrandTotal(percentOfGrandTotal);\r\n }\r\n\r\n export function toColumnRefSQExpr(columnPattern: FieldExprColumnPattern): SQColumnRefExpr {\r\n return SQExprBuilder.columnRef(\r\n SQExprBuilder.entity(columnPattern.schema, columnPattern.entity, columnPattern.entityVar),\r\n columnPattern.name);\r\n }\r\n\r\n export function getAggregate(fieldExpr: FieldExprPattern): QueryAggregateFunction {\r\n debug.assertValue(fieldExpr, 'fieldExpr');\r\n\r\n return visit(fieldExpr, FieldExprPatternAggregateVisitor.instance);\r\n }\r\n\r\n export function isAggregation(fieldExpr: FieldExprPattern): boolean {\r\n debug.assertValue(fieldExpr, 'fieldExpr');\r\n\r\n return visit(fieldExpr, FieldExprPatternIsAggregationVisitor.instance);\r\n }\r\n\r\n export function hasFieldExprName(fieldExpr: FieldExprPattern): boolean {\r\n return (fieldExpr.column ||\r\n fieldExpr.columnAggr ||\r\n fieldExpr.measure) !== undefined;\r\n }\r\n\r\n export function getPropertyName(fieldExpr: FieldExprPattern): string {\r\n return FieldExprPattern.visit(fieldExpr, FieldExprPropertyNameVisitor.instance);\r\n }\r\n\r\n export function getHierarchyName(fieldExpr: FieldExprPattern): string {\r\n let hierarchy = fieldExpr.hierarchy;\r\n if (hierarchy)\r\n return hierarchy.name;\r\n }\r\n\r\n export function getColumnRef(fieldExpr: FieldExprPattern): FieldExprPropertyPattern {\r\n if (fieldExpr.columnHierarchyLevelVariation)\r\n return fieldExpr.columnHierarchyLevelVariation.source;\r\n\r\n return fieldExpr.column || fieldExpr.measure || fieldExpr.columnAggr;\r\n }\r\n\r\n export function getFieldExprName(fieldExpr: FieldExprPattern): string {\r\n let name = getPropertyName(fieldExpr);\r\n\r\n if (name)\r\n return name;\r\n\r\n // In case it is an entity\r\n return toFieldExprEntityPattern(fieldExpr).entity;\r\n }\r\n \r\n export function getSchema(fieldExpr: FieldExprPattern): string {\r\n debug.assertValue(fieldExpr, 'fieldExpr');\r\n \r\n let item = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n debug.assertAnyValue(item, 'expected fieldExpr to be an entity item');\r\n \r\n return item.schema;\r\n }\r\n\r\n export function toFieldExprEntityPattern(fieldExpr: FieldExprPattern): FieldExprEntityPattern {\r\n return FieldExprPattern.visit(fieldExpr, FieldExprToEntityExprPatternBuilder.instance);\r\n }\r\n\r\n export function toFieldExprEntityItemPattern(fieldExpr: FieldExprPattern): FieldExprEntityPattern {\r\n return FieldExprPattern.visit(fieldExpr, FieldExprToEntityExprPatternBuilder.instance);\r\n }\r\n\r\n class FieldExprPatternAggregateVisitor implements IFieldExprPatternVisitor<QueryAggregateFunction> {\r\n public static instance: FieldExprPatternAggregateVisitor = new FieldExprPatternAggregateVisitor();\r\n\r\n public visitColumn(column: FieldExprColumnPattern): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): QueryAggregateFunction {\r\n return columnAggr.aggregate;\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public visitEntity(entity: FieldExprEntityPattern): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): QueryAggregateFunction {\r\n return entityAggr.aggregate;\r\n }\r\n\r\n public visitHierarchy(hierarchy: FieldExprHierarchyPattern): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): QueryAggregateFunction {\r\n return hierarchyLevelAggr.aggregate;\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): QueryAggregateFunction {\r\n // NOTE: Percentile behaves like an aggregate (i.e., can be performed over numeric columns like a SUM), but\r\n // this function can't really convey that because percentile (intentionally) isn't in QueryAggregateFunction enum.\r\n // This should be revisited when we have UI support for the Percentile aggregate.\r\n return;\r\n }\r\n\r\n public visitPercentOfGrandTotal(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern): QueryAggregateFunction {\r\n return SQExprInfo.getAggregate(SQExprBuilder.fieldExpr(percentOfGrandTotal.baseExpr));\r\n }\r\n }\r\n\r\n class FieldExprPatternIsAggregationVisitor implements IFieldExprPatternVisitor<boolean> {\r\n public static instance: FieldExprPatternIsAggregationVisitor = new FieldExprPatternIsAggregationVisitor();\r\n\r\n public visitColumn(column: FieldExprColumnPattern): boolean {\r\n return false;\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): boolean {\r\n return true;\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): boolean {\r\n return false;\r\n }\r\n\r\n public visitEntity(entity: FieldExprEntityPattern): boolean {\r\n return false;\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): boolean {\r\n return true;\r\n }\r\n\r\n public visitHierarchy(hierarchy: FieldExprHierarchyPattern): boolean {\r\n return false;\r\n }\r\n\r\n public visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): boolean {\r\n return false;\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): boolean {\r\n return true;\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): boolean {\r\n return true;\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): boolean {\r\n return false;\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): boolean {\r\n return true;\r\n }\r\n\r\n public visitPercentOfGrandTotal(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern): boolean {\r\n return true;\r\n }\r\n }\r\n\r\n class FieldExprToEntityExprPatternBuilder implements IFieldExprPatternVisitor<FieldExprEntityItemPattern> {\r\n public static instance: FieldExprToEntityExprPatternBuilder = new FieldExprToEntityExprPatternBuilder();\r\n\r\n public visitColumn(column: FieldExprColumnPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(column);\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(columnAggr);\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(columnHierarchyLevelVariation.source);\r\n }\r\n\r\n public visitEntity(entity: FieldExprEntityPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(entity);\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(entityAggr);\r\n }\r\n\r\n public visitHierarchy(hierarchy: FieldExprHierarchyPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(hierarchy);\r\n }\r\n\r\n public visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(hierarchyLevel);\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(hierarchyLevelAggr);\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): FieldExprEntityItemPattern {\r\n return FieldExprToEntityExprPatternBuilder.toEntityItemExprPattern(measure);\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): FieldExprEntityItemPattern {\r\n return;\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): FieldExprEntityItemPattern {\r\n return FieldExprPattern.visit(percentile.arg, this);\r\n }\r\n\r\n public visitPercentOfGrandTotal(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern): FieldExprEntityItemPattern {\r\n return FieldExprPattern.visit(percentOfGrandTotal.baseExpr, this);\r\n }\r\n\r\n private static toEntityItemExprPattern(exprPattern: FieldExprEntityItemPattern): FieldExprEntityItemPattern {\r\n debug.assertValue(exprPattern, 'exprPattern');\r\n\r\n let pattern: FieldExprEntityItemPattern = { schema: exprPattern.schema, entity: exprPattern.entity };\r\n\r\n if (exprPattern.entityVar) {\r\n pattern.entityVar = exprPattern.entityVar;\r\n }\r\n\r\n return pattern;\r\n }\r\n }\r\n \r\n class FieldExprPropertyNameVisitor implements IFieldExprPatternVisitor<string> {\r\n public static instance: FieldExprPropertyNameVisitor = new FieldExprPropertyNameVisitor();\r\n\r\n public visitColumn(column: FieldExprColumnPattern): string {\r\n return column.name;\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): string {\r\n return columnAggr.name;\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): string {\r\n return;\r\n }\r\n\r\n public visitEntity(entity: FieldExprEntityPattern): string {\r\n return;\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): string {\r\n return;\r\n }\r\n\r\n public visitHierarchy(hierarchy: FieldExprHierarchyPattern): string {\r\n return;\r\n }\r\n\r\n public visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): string {\r\n return;\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): string {\r\n return;\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): string {\r\n return measure.name;\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): string {\r\n return;\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): string {\r\n return FieldExprPattern.visit(percentile.arg, this);\r\n }\r\n\r\n public visitPercentOfGrandTotal(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern): string {\r\n return FieldExprPattern.visit(percentOfGrandTotal.baseExpr, this);\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n export module DataViewAnalysis {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n import QueryProjectionsByRole = powerbi.data.QueryProjectionsByRole;\r\n import DataViewObjectDescriptors = powerbi.data.DataViewObjectDescriptors;\r\n import DataViewObjectDefinitions = powerbi.data.DataViewObjectDefinitions;\r\n\r\n export interface ValidateAndReshapeResult {\r\n dataView?: DataView;\r\n isValid: boolean;\r\n }\r\n\r\n export interface RoleKindByQueryRef {\r\n [queryRef: string]: VisualDataRoleKind;\r\n }\r\n\r\n export interface DataViewMappingResult {\r\n supportedMappings: DataViewMapping[];\r\n\r\n /** A set of mapping errors if there are no supported mappings */\r\n mappingErrors: DataViewMappingMatchError[];\r\n }\r\n\r\n export enum DataViewMappingMatchErrorCode {\r\n conditionRangeTooLarge,\r\n conditionRangeTooSmall,\r\n conditionKindExpectedMeasure,\r\n conditionKindExpectedGrouping,\r\n conditionKindExpectedGroupingOrMeasure,\r\n }\r\n\r\n export interface DataViewMappingMatchError {\r\n code: DataViewMappingMatchErrorCode;\r\n roleName: string;\r\n mappingIndex?: number;\r\n conditionIndex?: number;\r\n }\r\n\r\n /** Reshapes the data view to match the provided schema if possible. If not, returns null */\r\n export function validateAndReshape(dataView: DataView, dataViewMappings: DataViewMapping[]): ValidateAndReshapeResult {\r\n if (!dataViewMappings || dataViewMappings.length === 0)\r\n return { dataView: dataView, isValid: true };\r\n\r\n if (dataView) {\r\n for (let dataViewMapping of dataViewMappings) {\r\n // Keep the original when possible.\r\n if (supports(dataView, dataViewMapping))\r\n return { dataView: dataView, isValid: true };\r\n\r\n if (dataViewMapping.categorical && dataView.categorical)\r\n return reshapeCategorical(dataView, dataViewMapping);\r\n\r\n if (dataViewMapping.tree && dataView.tree)\r\n return reshapeTree(dataView, dataViewMapping.tree);\r\n\r\n if (dataViewMapping.single && dataView.single)\r\n return reshapeSingle(dataView, dataViewMapping.single);\r\n\r\n if (dataViewMapping.table && dataView.table)\r\n return reshapeTable(dataView, dataViewMapping.table);\r\n }\r\n }\r\n else if (ScriptResultUtil.findScriptResult(dataViewMappings)) {\r\n // Currently, PBI Service treats R Script Visuals as static images.\r\n // This causes validation to fail, since in PBI service no DataView is generated, but there are DataViewMappings,\r\n // to support the PBI Desktop scenario.\r\n // This code will be removed once PBI Service fully supports R Script Visuals.\r\n // VSTS: 6217994 - [R Viz] Remove temporary DataViewAnalysis validation workaround of static R Script Visual mappings\r\n return { dataView: dataView, isValid: true };\r\n }\r\n\r\n return { isValid: false };\r\n }\r\n\r\n function reshapeCategorical(dataView: DataView, dataViewMapping: DataViewMapping): ValidateAndReshapeResult {\r\n debug.assertValue(dataViewMapping, 'dataViewMapping');\r\n\r\n //The functionality that used to compare categorical.values.length to schema.values doesn't apply any more, we don't want to use the same logic for re-shaping.\r\n let categoryRoleMapping = dataViewMapping.categorical;\r\n let categorical = dataView.categorical;\r\n if (!categorical)\r\n return { isValid: false };\r\n\r\n let rowCount;\r\n if (categoryRoleMapping.rowCount) {\r\n rowCount = categoryRoleMapping.rowCount.supported;\r\n if (rowCount && rowCount.max) {\r\n let updated: DataViewCategorical;\r\n let categories = categorical.categories;\r\n let maxRowCount = rowCount.max;\r\n let originalLength = undefined;\r\n if (categories) {\r\n for (let i = 0, len = categories.length; i < len; i++) {\r\n let category = categories[i];\r\n originalLength = category.values.length;\r\n if (maxRowCount !== undefined && originalLength > maxRowCount) {\r\n\r\n // Row count too large: Trim it to fit.\r\n let updatedCategories = ArrayExtensions.range(category.values, 0, maxRowCount - 1);\r\n\r\n updated = updated || { categories: [] };\r\n updated.categories.push({\r\n source: category.source,\r\n values: updatedCategories\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (categorical.values && categorical.values.length > 0 && maxRowCount) {\r\n if (!originalLength)\r\n originalLength = categorical.values[0].values.length;\r\n\r\n if (maxRowCount !== undefined && originalLength > maxRowCount) {\r\n updated = updated || {};\r\n updated.values = data.DataViewTransform.createValueColumns();\r\n\r\n for (let i = 0, len = categorical.values.length; i < len; i++) {\r\n let column = categorical.values[i],\r\n updatedColumn: DataViewValueColumn = {\r\n source: column.source,\r\n values: ArrayExtensions.range(column.values, 0, maxRowCount - 1)\r\n };\r\n\r\n if (column.min !== undefined)\r\n updatedColumn.min = column.min;\r\n if (column.max !== undefined)\r\n updatedColumn.max = column.max;\r\n if (column.subtotal !== undefined)\r\n updatedColumn.subtotal = column.subtotal;\r\n\r\n updated.values.push(updatedColumn);\r\n }\r\n }\r\n }\r\n\r\n if (updated) {\r\n dataView = {\r\n metadata: dataView.metadata,\r\n categorical: updated,\r\n };\r\n }\r\n }\r\n }\r\n\r\n if (supportsCategorical(dataView, dataViewMapping))\r\n return { dataView: dataView, isValid: true };\r\n\r\n return null;\r\n }\r\n\r\n function reshapeSingle(dataView: DataView, singleRoleMapping: DataViewSingleMapping): ValidateAndReshapeResult {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(singleRoleMapping, 'singleRoleMapping');\r\n\r\n if (dataView.single)\r\n return { dataView: dataView, isValid: true };\r\n\r\n return { isValid: false };\r\n }\r\n\r\n function reshapeTree(dataView: DataView, treeRoleMapping: DataViewTreeMapping): ValidateAndReshapeResult {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(treeRoleMapping, 'treeRoleMapping');\r\n\r\n // TODO: Need to implement the reshaping of Tree\r\n let metadata = dataView.metadata;\r\n if (validateRange(countGroups(metadata.columns), treeRoleMapping.depth) == null /*&& conforms(countMeasures(metadata.columns), treeRoleMapping.aggregates)*/)\r\n return { dataView: dataView, isValid: true };\r\n\r\n return { isValid: false };\r\n }\r\n\r\n function reshapeTable(dataView: DataView, tableRoleMapping: DataViewTableMapping): ValidateAndReshapeResult {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(tableRoleMapping, 'tableRoleMapping');\r\n\r\n if (dataView.table)\r\n return { dataView: dataView, isValid: true };\r\n\r\n return { isValid: false };\r\n }\r\n\r\n export function countGroups(columns: DataViewMetadataColumn[]): number {\r\n let count = 0;\r\n\r\n for (let i = 0, len = columns.length; i < len; i++) {\r\n if (!columns[i].isMeasure)\r\n ++count;\r\n }\r\n\r\n return count;\r\n }\r\n\r\n export function countMeasures(columns: DataViewMetadataColumn[]): number {\r\n let count = 0;\r\n\r\n for (let i = 0, len = columns.length; i < len; i++) {\r\n if (columns[i].isMeasure)\r\n ++count;\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /** Indicates whether the dataView conforms to the specified schema. */\r\n export function supports(dataView: DataView, roleMapping: DataViewMapping, usePreferredDataViewSchema?: boolean): boolean {\r\n if (!roleMapping || !dataView)\r\n return false;\r\n\r\n if (roleMapping.scriptResult && !supportsScriptResult(dataView.scriptResult, roleMapping.scriptResult))\r\n return false;\r\n\r\n if (roleMapping.categorical && !supportsCategorical(dataView, roleMapping.categorical, usePreferredDataViewSchema))\r\n return false;\r\n\r\n if (roleMapping.tree && !supportsTree(dataView, roleMapping.tree))\r\n return false;\r\n\r\n if (roleMapping.single && !supportsSingle(dataView.single, roleMapping.single))\r\n return false;\r\n\r\n if (roleMapping.table && !supportsTable(dataView.table, roleMapping.table, usePreferredDataViewSchema))\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n function supportsCategorical(dataView: DataView, categoryRoleMapping: DataViewCategoricalMapping, usePreferredDataViewSchema?: boolean): boolean {\r\n debug.assertValue(categoryRoleMapping, 'categoryRoleMapping');\r\n\r\n let dataViewCategorical = dataView.categorical;\r\n if (!dataViewCategorical)\r\n return false;\r\n\r\n // TODO: Disabling this implementation isn't right.\r\n //if (!conforms(countMeasures(dataView.metadata.columns), categoryRoleMapping.values.roles.length))\r\n // return false;\r\n\r\n if (categoryRoleMapping.rowCount) {\r\n let rowCount = categoryRoleMapping.rowCount.supported;\r\n if (usePreferredDataViewSchema && categoryRoleMapping.rowCount.preferred)\r\n rowCount = categoryRoleMapping.rowCount.preferred;\r\n\r\n if (rowCount) {\r\n let len: number = 0;\r\n if (dataViewCategorical.values && dataViewCategorical.values.length)\r\n len = dataViewCategorical.values[0].values.length;\r\n else if (dataViewCategorical.categories && dataViewCategorical.categories.length)\r\n len = dataViewCategorical.categories[0].values.length;\r\n\r\n if (validateRange(len, rowCount) != null)\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n function supportsSingle(dataViewSingle: DataViewSingle, singleRoleMapping: DataViewSingleMapping): boolean {\r\n debug.assertValue(singleRoleMapping, 'singleRoleMapping');\r\n\r\n if (!dataViewSingle)\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n function supportsTree(dataView: DataView, treeRoleMapping: DataViewTreeMapping): boolean {\r\n debug.assertValue(treeRoleMapping, 'treeRoleMapping');\r\n\r\n let metadata = dataView.metadata;\r\n return validateRange(countGroups(metadata.columns), treeRoleMapping.depth) == null;\r\n }\r\n\r\n function supportsTable(dataViewTable: DataViewTable, tableRoleMapping: DataViewTableMapping, usePreferredDataViewSchema?: boolean): boolean {\r\n debug.assertValue(tableRoleMapping, 'tableRoleMapping');\r\n\r\n if (!dataViewTable)\r\n return false;\r\n\r\n if (tableRoleMapping.rowCount) {\r\n let rowCount = tableRoleMapping.rowCount.supported;\r\n if (usePreferredDataViewSchema && tableRoleMapping.rowCount.preferred)\r\n rowCount = tableRoleMapping.rowCount.preferred;\r\n\r\n if (rowCount) {\r\n let len: number = 0;\r\n if (dataViewTable.rows && dataViewTable.rows.length)\r\n len = dataViewTable.rows.length;\r\n\r\n if (validateRange(len, rowCount) != null)\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n function supportsScriptResult(dataView: DataViewScriptResultData, scriptResultRoleMapping: DataViewScriptResultMapping): boolean {\r\n debug.assertValue(scriptResultRoleMapping, 'scriptResultRoleMapping');\r\n\r\n if (!dataView)\r\n return false;\r\n\r\n if (!dataView.imageBase64)\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n /** \r\n * Determines whether the value conforms to the range in the role condition, returning undefined\r\n * if so or an appropriate error code if not.\r\n */\r\n export function validateRange(value: number, roleCondition: RoleCondition, ignoreMin?: boolean): DataViewMappingMatchErrorCode {\r\n debug.assertValue(value, 'value');\r\n\r\n if (!roleCondition)\r\n return;\r\n\r\n if (!ignoreMin && roleCondition.min !== undefined && roleCondition.min > value)\r\n return DataViewMappingMatchErrorCode.conditionRangeTooSmall;\r\n\r\n if (roleCondition.max !== undefined && roleCondition.max < value)\r\n return DataViewMappingMatchErrorCode.conditionRangeTooLarge;\r\n }\r\n\r\n /** \r\n * Determines whether the value conforms to the kind in the role condition, returning undefined\r\n * if so or an appropriate error code if not.\r\n */\r\n function validateKind(roleCondition: RoleCondition, roleName: string, projections: QueryProjectionsByRole, roleKindByQueryRef: RoleKindByQueryRef): DataViewMappingMatchErrorCode {\r\n if (!roleCondition || roleCondition.kind === undefined) {\r\n return;\r\n }\r\n let expectedKind = roleCondition.kind;\r\n let roleCollection = projections[roleName];\r\n if (roleCollection) {\r\n let roleProjections = roleCollection.all();\r\n for (let roleProjection of roleProjections) {\r\n if (roleKindByQueryRef[roleProjection.queryRef] !== expectedKind) {\r\n switch (expectedKind) {\r\n case VisualDataRoleKind.Measure:\r\n return DataViewMappingMatchErrorCode.conditionKindExpectedMeasure;\r\n case VisualDataRoleKind.Grouping:\r\n return DataViewMappingMatchErrorCode.conditionKindExpectedGrouping;\r\n case VisualDataRoleKind.GroupingOrMeasure:\r\n return DataViewMappingMatchErrorCode.conditionKindExpectedGroupingOrMeasure;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /** Determines the appropriate DataViewMappings for the projections. */\r\n export function chooseDataViewMappings(\r\n projections: QueryProjectionsByRole,\r\n mappings: DataViewMapping[],\r\n roleKindByQueryRef: RoleKindByQueryRef,\r\n objectDescriptors?: DataViewObjectDescriptors,\r\n objectDefinitions?: DataViewObjectDefinitions): DataViewMappingResult {\r\n debug.assertValue(projections, 'projections');\r\n debug.assertAnyValue(mappings, 'mappings');\r\n\r\n let supportedMappings: DataViewMapping[] = [];\r\n let errors: DataViewMappingMatchError[] = [];\r\n\r\n if (!_.isEmpty(mappings)) {\r\n for (let mappingIndex = 0, mappingCount = mappings.length; mappingIndex < mappingCount; mappingIndex++) {\r\n let mapping = mappings[mappingIndex],\r\n mappingConditions = mapping.conditions,\r\n requiredProperties = mapping.requiredProperties;\r\n let allPropertiesValid: boolean = areAllPropertiesValid(requiredProperties, objectDescriptors, objectDefinitions);\r\n let conditionsMet: DataViewMappingCondition[] = [];\r\n\r\n if (!_.isEmpty(mappingConditions)) {\r\n for (let conditionIndex = 0, conditionCount = mappingConditions.length; conditionIndex < conditionCount; conditionIndex++) {\r\n let condition = mappingConditions[conditionIndex];\r\n let currentConditionErrors = checkForConditionErrors(projections, condition, roleKindByQueryRef);\r\n if (!_.isEmpty(currentConditionErrors)) {\r\n for (let error of currentConditionErrors) {\r\n error.mappingIndex = mappingIndex;\r\n error.conditionIndex = conditionIndex;\r\n errors.push(error);\r\n }\r\n }\r\n else\r\n conditionsMet.push(condition);\r\n }\r\n }\r\n else {\r\n conditionsMet.push({});\r\n }\r\n\r\n if (!_.isEmpty(conditionsMet) && allPropertiesValid) {\r\n let supportedMapping = _.cloneDeep(mapping);\r\n\r\n let updatedConditions = _.filter(conditionsMet, (condition) => Object.keys(condition).length > 0);\r\n if (!_.isEmpty(updatedConditions))\r\n supportedMapping.conditions = updatedConditions;\r\n supportedMappings.push(supportedMapping);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n supportedMappings: ArrayExtensions.emptyToNull(supportedMappings),\r\n mappingErrors: ArrayExtensions.emptyToNull(errors),\r\n };\r\n }\r\n\r\n function checkForConditionErrors(projections: QueryProjectionsByRole, condition: DataViewMappingCondition, roleKindByQueryRef: RoleKindByQueryRef): DataViewMappingMatchError[] {\r\n debug.assertValue(projections, 'projections');\r\n debug.assertValue(condition, 'condition');\r\n\r\n let conditionRoles = Object.keys(condition);\r\n let errors: DataViewMappingMatchError[] = [];\r\n\r\n for (let i = 0, len = conditionRoles.length; i < len; i++) {\r\n let roleName: string = conditionRoles[i],\r\n isDrillable = projections[roleName] && !_.isEmpty(projections[roleName].activeProjectionRefs),\r\n roleCondition = condition[roleName];\r\n\r\n let roleCount = getPropertyCount(roleName, projections, isDrillable);\r\n let rangeError = validateRange(roleCount, roleCondition);\r\n if (rangeError != null) {\r\n errors.push({\r\n code: rangeError,\r\n roleName: roleName,\r\n });\r\n }\r\n let kindError = validateKind(roleCondition, roleName, projections, roleKindByQueryRef);\r\n if (kindError != null) {\r\n errors.push({\r\n code: kindError,\r\n roleName: roleName,\r\n });\r\n }\r\n }\r\n\r\n return errors;\r\n }\r\n\r\n function areAllPropertiesValid(requiredProperties: DataViewObjectPropertyIdentifier[], objectDescriptors: DataViewObjectDescriptors, objectDefinitions?: DataViewObjectDefinitions): boolean {\r\n if (_.isEmpty(requiredProperties))\r\n return true;\r\n\r\n if (!objectDescriptors || !objectDefinitions)\r\n return false;\r\n\r\n let staticEvalContext: data.IEvalContext = data.createStaticEvalContext();\r\n\r\n return _.every(requiredProperties, (requiredProperty) => {\r\n let objectDescriptorValue = null;\r\n let objectDescriptorProperty = objectDescriptors[requiredProperty.objectName];\r\n if (objectDescriptorProperty)\r\n objectDescriptorValue = objectDescriptorProperty.properties[requiredProperty.propertyName];\r\n let objectDefinitionValue = DataViewObjectDefinitions.getValue(objectDefinitions, requiredProperty, null);\r\n\r\n if (!objectDescriptorValue || !objectDefinitionValue)\r\n return false;\r\n\r\n return data.DataViewObjectEvaluator.evaluateProperty(staticEvalContext, objectDescriptorValue, objectDefinitionValue);\r\n });\r\n }\r\n\r\n export function getPropertyCount(roleName: string, projections: QueryProjectionsByRole, useActiveIfAvailable?: boolean): number {\r\n debug.assertValue(roleName, 'roleName');\r\n debug.assertValue(projections, 'projections');\r\n\r\n let projectionsForRole = projections[roleName];\r\n if (projectionsForRole) {\r\n if (useActiveIfAvailable)\r\n return 1;\r\n return projectionsForRole.all().length;\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n export function hasSameCategoryIdentity(dataView1: DataView, dataView2: DataView): boolean {\r\n if (dataView1\r\n && dataView2\r\n && dataView1.categorical\r\n && dataView2.categorical) {\r\n let dv1Categories = dataView1.categorical.categories;\r\n let dv2Categories = dataView2.categorical.categories;\r\n if (dv1Categories\r\n && dv2Categories\r\n && dv1Categories.length === dv2Categories.length) {\r\n for (let i = 0, len = dv1Categories.length; i < len; i++) {\r\n let dv1Identity = dv1Categories[i].identity;\r\n let dv2Identity = dv2Categories[i].identity;\r\n\r\n let dv1Length = getLengthOptional(dv1Identity);\r\n if (dv1Length !== getLengthOptional(dv2Identity))\r\n return false;\r\n\r\n for (let j = 0; j < dv1Length; j++) {\r\n if (!DataViewScopeIdentity.equals(dv1Identity[j], dv2Identity[j]))\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n function getLengthOptional(identity: DataViewScopeIdentity[]): number {\r\n if (identity)\r\n return identity.length;\r\n\r\n return 0;\r\n }\r\n\r\n export function areMetadataColumnsEquivalent(column1: DataViewMetadataColumn, column2: DataViewMetadataColumn): boolean {\r\n if (!column1 && !column2)\r\n return true;\r\n\r\n if (!column1 || !column2)\r\n return false;\r\n\r\n if (column1.displayName !== column2.displayName)\r\n return false;\r\n\r\n if (column1.queryName !== column2.queryName)\r\n return false;\r\n\r\n if (column1.isMeasure !== column2.isMeasure)\r\n return false;\r\n\r\n if (column1.type !== column2.type)\r\n return false;\r\n\r\n if (column1.sort !== column2.sort)\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n /* Returns true if the metadata columns at the same positions in the array are equivalent. */\r\n export function isMetadataEquivalent(metadata1: DataViewMetadata, metadata2: DataViewMetadata): boolean {\r\n if (!metadata1 && !metadata2)\r\n return true;\r\n\r\n if (!metadata1 || !metadata2)\r\n return false;\r\n\r\n let previousColumnsLength = metadata1.columns.length;\r\n let newColumnsLength = metadata2.columns.length;\r\n\r\n if (previousColumnsLength !== newColumnsLength)\r\n return false;\r\n\r\n for (let i: number = 0; i < newColumnsLength; i++) {\r\n if (!DataViewAnalysis.areMetadataColumnsEquivalent(metadata1.columns[i], metadata2.columns[i]))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n import Lazy = jsCommon.Lazy;\r\n\r\n export module DataViewRoleWildcard {\r\n export function fromRoles(roles: string[]): DataViewRoleWildcard {\r\n return new DataViewRoleWildcardImpl(roles);\r\n }\r\n\r\n export function equals(firstRoleWildcard: DataViewRoleWildcard, secondRoleWildcard: DataViewRoleWildcard): boolean {\r\n return firstRoleWildcard.key &&\r\n secondRoleWildcard.key &&\r\n firstRoleWildcard.key === secondRoleWildcard.key &&\r\n ArrayExtensions.sequenceEqual<string>(\r\n firstRoleWildcard.roles,\r\n secondRoleWildcard.roles,\r\n (role1: string, role2: string) => role1 === role2);\r\n }\r\n\r\n class DataViewRoleWildcardImpl implements DataViewRoleWildcard {\r\n private _roles: string[];\r\n private _key: Lazy<string>;\r\n\r\n public constructor(roles: string[]) {\r\n debug.assertNonEmpty(roles, 'roles');\r\n\r\n this._roles = roles;\r\n this._key = new Lazy<string>(() => JSON.stringify(this.roles));\r\n }\r\n\r\n public get roles(): string[] {\r\n return this._roles;\r\n }\r\n\r\n public get key(): string {\r\n return this._key.getValue();\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n export module DataViewScopeIdentity {\r\n /** Compares the two DataViewScopeIdentity values for equality. */\r\n export function equals(x: DataViewScopeIdentity, y: DataViewScopeIdentity, ignoreCase?: boolean): boolean {\r\n // Normalize falsy to null\r\n x = x || null;\r\n y = y || null;\r\n\r\n if (x === y)\r\n return true;\r\n\r\n if (!x !== !y)\r\n return false;\r\n\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n\r\n return data.SQExpr.equals(<data.SQExpr>x.expr, <data.SQExpr>y.expr, ignoreCase);\r\n }\r\n\r\n export function filterFromIdentity(identities: DataViewScopeIdentity[], isNot?: boolean): data.SemanticFilter {\r\n if (_.isEmpty(identities))\r\n return;\r\n \r\n let exprs: data.SQExpr[] = [];\r\n for (let identity of identities) {\r\n exprs.push(<data.SQExpr>identity.expr);\r\n }\r\n\r\n return filterFromExprs(exprs, isNot);\r\n }\r\n\r\n export function filterFromExprs(orExprs: data.SQExpr[], isNot?: boolean): data.SemanticFilter {\r\n if (_.isEmpty(orExprs))\r\n return;\r\n\r\n let resultExpr: data.SQExpr;\r\n for (let orExpr of orExprs) {\r\n let inExpr = data.ScopeIdentityExtractor.getInExpr(orExpr);\r\n if (resultExpr)\r\n resultExpr = data.SQExprBuilder.or(resultExpr, inExpr);\r\n else\r\n resultExpr = inExpr || orExpr;\r\n }\r\n \r\n if (resultExpr) {\r\n if (isNot)\r\n resultExpr = powerbi.data.SQExprBuilder.not(resultExpr);\r\n }\r\n\r\n return powerbi.data.SemanticFilter.fromSQExpr(resultExpr);\r\n }\r\n }\r\n\r\n export module data {\r\n import Lazy = jsCommon.Lazy;\r\n\r\n export function createDataViewScopeIdentity(expr: SQExpr): DataViewScopeIdentity {\r\n return new DataViewScopeIdentityImpl(expr);\r\n }\r\n\r\n class DataViewScopeIdentityImpl implements DataViewScopeIdentity {\r\n private _expr: SQExpr;\r\n private _key: Lazy<string>;\r\n\r\n public constructor(expr: SQExpr) {\r\n debug.assertValue(expr, 'expr');\r\n\r\n this._expr = expr;\r\n this._key = new Lazy(() => SQExprShortSerializer.serialize(expr));\r\n }\r\n\r\n public get expr(): SQExpr {\r\n return this._expr;\r\n }\r\n\r\n public get key(): string {\r\n return this._key.getValue();\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import Lazy = jsCommon.Lazy;\r\n\r\n export module DataViewScopeWildcard {\r\n export function matches(wildcard: DataViewScopeWildcard, instance: DataViewScopeIdentity): boolean {\r\n let instanceExprs = ScopeIdentityExtractor.getKeys(<SQExpr>instance.expr);\r\n if (!instanceExprs)\r\n return false;\r\n\r\n return SQExprUtils.sequenceEqual(<SQExpr[]>wildcard.exprs, instanceExprs);\r\n }\r\n\r\n export function equals(firstScopeWildcard: DataViewScopeWildcard, secondScopeWildcard: DataViewScopeWildcard): boolean {\r\n return firstScopeWildcard.key === secondScopeWildcard.key &&\r\n SQExprUtils.sequenceEqual(<SQExpr[]>firstScopeWildcard.exprs, <SQExpr[]>secondScopeWildcard.exprs);\r\n }\r\n\r\n export function fromExprs(exprs: SQExpr[]): DataViewScopeWildcard {\r\n return new DataViewScopeWildcardImpl(exprs);\r\n }\r\n\r\n class DataViewScopeWildcardImpl implements DataViewScopeWildcard {\r\n private _exprs: SQExpr[];\r\n private _key: Lazy<string>;\r\n\r\n public constructor(exprs: SQExpr[]) {\r\n debug.assertValue(exprs, 'exprs');\r\n\r\n this._exprs = exprs;\r\n this._key = new Lazy(() => SQExprShortSerializer.serializeArray(exprs));\r\n }\r\n\r\n public get exprs(): SQExpr[] {\r\n return this._exprs;\r\n }\r\n\r\n public get key(): string {\r\n return this._key.getValue();\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export interface IColorAllocatorCache {\r\n get(key: SQFillRuleExpr): IColorAllocator;\r\n register(key: SQFillRuleExpr, colorAllocator: IColorAllocator): this;\r\n }\r\n\r\n export function createColorAllocatorCache(): IColorAllocatorCache {\r\n return new ColorAllocatorProvider();\r\n }\r\n\r\n interface ColorAllocatorCacheEntry {\r\n key: SQFillRuleExpr;\r\n allocator: IColorAllocator;\r\n }\r\n\r\n class ColorAllocatorProvider implements IColorAllocatorCache {\r\n private cache: ColorAllocatorCacheEntry[];\r\n\r\n constructor() {\r\n this.cache = [];\r\n }\r\n\r\n public get(key: SQFillRuleExpr): IColorAllocator {\r\n debug.assertValue(key, 'key');\r\n\r\n for (let entry of this.cache) {\r\n if (entry.key === key)\r\n return entry.allocator;\r\n }\r\n }\r\n\r\n public register(key: SQFillRuleExpr, colorAllocator: IColorAllocator): this {\r\n debug.assertValue(key, 'key');\r\n debug.assertValue(colorAllocator, 'colorAllocator');\r\n debug.assert(this.get(key) == null, 'Trying to re-register for same key expr.');\r\n\r\n this.cache.push({\r\n key: key,\r\n allocator: colorAllocator,\r\n });\r\n\r\n return this;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import RoleKindByQueryRef = DataViewAnalysis.RoleKindByQueryRef;\r\n\r\n export interface DataViewRegressionRunOptions {\r\n dataViewMappings: DataViewMapping[];\r\n visualDataViews: DataView[];\r\n dataRoles: VisualDataRole[];\r\n objectDescriptors: DataViewObjectDescriptors;\r\n objectDefinitions: DataViewObjectDefinitions;\r\n colorAllocatorFactory: IColorAllocatorFactory;\r\n transformSelects: DataViewSelectTransform[];\r\n metadata: DataViewMetadata;\r\n projectionActiveItems: DataViewProjectionActiveItems;\r\n }\r\n\r\n export module DataViewRegression {\r\n // TODO VSTS 6842046: Currently we are using a constant queryName since we don't have a way to generate\r\n // unique ones. There is a bug filed to do this by lawong, so this part will be fixed with that bug.\r\n const regressionXQueryName: string = 'RegressionX';\r\n const regressionSeriesQueryName: string = 'RegressionSeries';\r\n export const regressionYQueryName: string = 'RegressionY';\r\n\r\n export function run(options: DataViewRegressionRunOptions): DataView[] {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataViewMappings: DataViewMapping[] = options.dataViewMappings;\r\n let visualDataViews: DataView[] = options.visualDataViews;\r\n let dataRoles: VisualDataRole[] = options.dataRoles;\r\n let objectDescriptors: DataViewObjectDescriptors = options.objectDescriptors;\r\n let objectDefinitions: DataViewObjectDefinitions = options.objectDefinitions;\r\n let colorAllocatorFactory: IColorAllocatorFactory = options.colorAllocatorFactory;\r\n let transformSelects: DataViewSelectTransform[] = options.transformSelects;\r\n let projectionActiveItems = options.projectionActiveItems;\r\n let metadata: DataViewMetadata = options.metadata;\r\n\r\n if (!_.isEmpty(visualDataViews) && transformSelects && metadata) {\r\n // compute linear regression line if applicable\r\n let roleKindByQueryRef: RoleKindByQueryRef = DataViewSelectTransform.createRoleKindFromMetadata(transformSelects, metadata);\r\n let projections: QueryProjectionsByRole = DataViewSelectTransform.projectionsFromSelects(transformSelects, projectionActiveItems);\r\n if (!roleKindByQueryRef || !projections || _.isEmpty(dataViewMappings) || !objectDescriptors || !objectDefinitions)\r\n return visualDataViews;\r\n\r\n let applicableDataViewMappings: DataViewMapping[] = DataViewAnalysis.chooseDataViewMappings(projections, dataViewMappings, roleKindByQueryRef, objectDescriptors, objectDefinitions).supportedMappings;\r\n\r\n if (applicableDataViewMappings) {\r\n let regressionDataViewMapping: DataViewMapping = _.find(applicableDataViewMappings, (dataViewMapping) => {\r\n return dataViewMapping.usage && dataViewMapping.usage.regression;\r\n });\r\n\r\n if (regressionDataViewMapping) {\r\n let regressionDataViews: DataView[] = [];\r\n for (let visualDataView of visualDataViews) {\r\n let regressionDataView: DataView = this.linearRegressionTransform(visualDataView, dataRoles, regressionDataViewMapping, objectDescriptors, objectDefinitions, colorAllocatorFactory);\r\n\r\n if (regressionDataView)\r\n regressionDataViews.push(regressionDataView);\r\n }\r\n\r\n if (!_.isEmpty(regressionDataViews))\r\n visualDataViews.push(...regressionDataViews);\r\n }\r\n }\r\n }\r\n\r\n return visualDataViews;\r\n }\r\n\r\n /**\r\n * This function will compute the linear regression algorithm on the sourceDataView and create a new dataView.\r\n * It works on scalar axis only.\r\n * The algorithm is as follows\r\n *\r\n * 1. Find the cartesian X and Y roles and the columns that correspond to those roles\r\n * 2. Get the data points, (X, Y) pairs, for each series, combining if needed.\r\n * 3. Compute the X and Y points for regression line using Y = Slope * X + Intercept\r\n * If highlights values are present, repeat steps 2 & 3 using highlight values.\r\n * 4. Create the new dataView using the points computed above\r\n */\r\n export function linearRegressionTransform(\r\n sourceDataView: DataView,\r\n dataRoles: VisualDataRole[],\r\n regressionDataViewMapping: DataViewMapping,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n objectDefinitions: DataViewObjectDefinitions,\r\n colorAllocatorFactory: IColorAllocatorFactory): DataView {\r\n debug.assertValue(sourceDataView, 'sourceDataView');\r\n debug.assertValue(sourceDataView.categorical, 'sourceDataView.categorical');\r\n debug.assertValue(dataRoles, 'dataRoles');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(objectDefinitions, 'objectDefinitions');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n\r\n if (!sourceDataView.categorical)\r\n return;\r\n\r\n // Step 1\r\n let xColumns: DataViewCategoricalColumn[] = getColumnsForCartesianRoleKind(CartesianRoleKind.X, sourceDataView.categorical, dataRoles);\r\n let yColumns: DataViewCategoricalColumn[] = getColumnsForCartesianRoleKind(CartesianRoleKind.Y, sourceDataView.categorical, dataRoles);\r\n\r\n if (_.isEmpty(xColumns) || _.isEmpty(yColumns))\r\n return;\r\n\r\n let xColumnSource = xColumns[0].source;\r\n let yColumnSource = yColumns[0].source;\r\n\r\n let combineSeries = true;\r\n if (regressionDataViewMapping.usage && regressionDataViewMapping.usage.regression && sourceDataView.metadata.objects) {\r\n let regressionUsage = regressionDataViewMapping.usage.regression;\r\n\r\n let combineSeriesPropertyId = regressionUsage['combineSeries'];\r\n if (combineSeriesPropertyId) {\r\n combineSeries = DataViewObjects.getValue<boolean>(sourceDataView.metadata.objects, combineSeriesPropertyId, true);\r\n }\r\n }\r\n\r\n // Step 2\r\n let dataPointsBySeries = getDataPointsBySeries(xColumns, yColumns, combineSeries, /* preferHighlights */ false);\r\n let lineDefSet = calculateLineDefinitions(dataPointsBySeries);\r\n let xMin = lineDefSet.xMin;\r\n let xMax = lineDefSet.xMax;\r\n\r\n let shouldComputeHightlights = hasHighlightValues(yColumns) || hasHighlightValues(xColumns);\r\n let highlightsLineDefSet: LineDefinitionSet;\r\n if (shouldComputeHightlights) {\r\n let highlightDataPointsBySeries = getDataPointsBySeries(xColumns, yColumns, combineSeries, /* preferHighlights */ true);\r\n highlightsLineDefSet = calculateLineDefinitions(highlightDataPointsBySeries);\r\n if (highlightsLineDefSet) {\r\n xMin = _.min([xMin, highlightsLineDefSet.xMin]);\r\n xMax = _.max([xMax, highlightsLineDefSet.xMax]);\r\n }\r\n else {\r\n shouldComputeHightlights = false;\r\n }\r\n }\r\n\r\n // Step 3\r\n let valuesByTrend: number[][] = [];\r\n for (let trend of lineDefSet.lineDefs) {\r\n valuesByTrend.push(computeLineYValues(trend, +xMin, +xMax));\r\n }\r\n\r\n let highlightsByTrend: number[][];\r\n if (shouldComputeHightlights) {\r\n highlightsByTrend = [];\r\n for (let trend of highlightsLineDefSet.lineDefs) {\r\n highlightsByTrend.push(computeLineYValues(trend, +xMin, +xMax));\r\n }\r\n }\r\n\r\n // Step 4\r\n let groupValues: PrimitiveValue[];\r\n if (combineSeries) {\r\n groupValues = ['combinedRegressionSeries'];\r\n }\r\n else {\r\n // If we are producing a trend line per series we need to maintain the group identities so that we can map between the \r\n // trend line and the original series (to match the color for example).\r\n if (sourceDataView.categorical.values.source) {\r\n // Source data view has dynamic series.\r\n let groups = sourceDataView.categorical.values.grouped();\r\n groupValues = _.map(groups, (group) => group.name);\r\n }\r\n else {\r\n // Source data view has static or no series.\r\n groupValues = _.map(yColumns, (column) => column.source.queryName);\r\n }\r\n }\r\n\r\n // Step 5\r\n let regressionDataView: DataView = createRegressionDataView(\r\n xColumnSource,\r\n yColumnSource,\r\n groupValues,\r\n [xMin, xMax],\r\n valuesByTrend,\r\n highlightsByTrend,\r\n sourceDataView,\r\n regressionDataViewMapping,\r\n objectDescriptors,\r\n objectDefinitions,\r\n colorAllocatorFactory);\r\n\r\n return regressionDataView;\r\n }\r\n\r\n function calculateLineDefinitions(dataPointsBySeries: DataPointSet[]): LineDefinitionSet {\r\n let xMin: PrimitiveValue;\r\n let xMax: PrimitiveValue;\r\n let lineDefs: LineDefinition[] = [];\r\n for (let dataPointSet of dataPointsBySeries) {\r\n let unsortedXValues: PrimitiveValue[] = dataPointSet.xValues;\r\n let unsortedYValues: PrimitiveValue[] = dataPointSet.yValues;\r\n\r\n if (_.isEmpty(unsortedXValues) || _.isEmpty(unsortedYValues))\r\n return;\r\n\r\n // get the data type for each column; we will have null type when dataPoints have different type or if a value is null\r\n let xDataType: string = getDataType(unsortedXValues);\r\n if (!xDataType)\r\n return;\r\n let yDataType: string = getDataType(unsortedYValues);\r\n if (!yDataType)\r\n return;\r\n\r\n let sortedDataPointSet: DataPointSet = sortValues(unsortedXValues, unsortedYValues);\r\n let minCategoryValue: PrimitiveValue = sortedDataPointSet.xValues[0];\r\n let maxCategoryValue: PrimitiveValue = sortedDataPointSet.xValues[sortedDataPointSet.xValues.length - 1];\r\n\r\n let lineDef: LineDefinition = computeRegressionLine(sortedDataPointSet.xValues, sortedDataPointSet.yValues);\r\n\r\n xMin = _.min([xMin, minCategoryValue]);\r\n xMax = _.max([xMax, maxCategoryValue]);\r\n\r\n lineDefs.push(lineDef);\r\n }\r\n\r\n return {\r\n lineDefs: lineDefs,\r\n xMin: xMin,\r\n xMax: xMax,\r\n };\r\n }\r\n\r\n function getColumnsForCartesianRoleKind(roleKind: CartesianRoleKind, categorical: DataViewCategorical, roles: VisualDataRole[]): DataViewCategoricalColumn[] {\r\n debug.assertValue(roleKind, 'roleKind');\r\n debug.assertValue(categorical, 'categorical');\r\n\r\n let columns = getColumnsWithRoleKind(roleKind, categorical.values, roles);\r\n if (!_.isEmpty(columns))\r\n return columns;\r\n\r\n let categories = categorical.categories;\r\n if (_.isEmpty(categories))\r\n return;\r\n\r\n debug.assert(categories.length === 1, 'composite category columns not supported');\r\n let categoryColumn = categories[0];\r\n columns = getColumnsWithRoleKind(roleKind, [categoryColumn], roles);\r\n if (!_.isEmpty(columns))\r\n return columns;\r\n }\r\n\r\n function getColumnsWithRoleKind(roleKind: CartesianRoleKind, columns: DataViewCategoricalColumn[], roles: VisualDataRole[]): DataViewCategoricalColumn[] {\r\n if (_.isEmpty(columns))\r\n return;\r\n\r\n return _.filter(columns, (column) => {\r\n for (let roleName in column.source.roles) {\r\n if (!column.source.roles[roleName])\r\n continue;\r\n\r\n let role = _.find(roles, (role) => role.name === roleName);\r\n if (role && role.cartesianKind === roleKind)\r\n return true;\r\n }\r\n\r\n return false;\r\n });\r\n }\r\n\r\n function getDataType(values: PrimitiveValue[]): string {\r\n let firstNonNull: PrimitiveValue = _.find(values, (value) => value != null);\r\n if (firstNonNull == null)\r\n return;\r\n\r\n let dataType: string = typeof firstNonNull;\r\n\r\n if (_.some(values, (value) => value != null && typeof value !== dataType))\r\n return;\r\n\r\n return dataType;\r\n }\r\n\r\n function sortValues(unsortedXValues: PrimitiveValue[], unsortedYValues: PrimitiveValue[]): DataPointSet {\r\n debug.assertValue(unsortedXValues, 'unsortedXValues');\r\n debug.assertValue(unsortedYValues, 'unsortedYValues');\r\n\r\n let zippedValues = _.zip(unsortedXValues, unsortedYValues);\r\n let [xValues, yValues] = _.chain(zippedValues)\r\n .filter((valuePair) => valuePair[0] != null && valuePair[1] != null)\r\n .sortBy((valuePair) => valuePair[0])\r\n .unzip()\r\n .value();\r\n\r\n return {\r\n xValues: xValues,\r\n yValues: yValues\r\n };\r\n }\r\n\r\n /**\r\n * Computes a line definition using linear regression.\r\n * xBar: average of X values, yBar: average of Y values\r\n * ssXX: sum of squares of X values = Sum(xi - xBar)^2\r\n * ssXY: sum of squares of X and Y values = Sum((xi - xBar)(yi - yBar)\r\n * Slope: ssXY / ssXX\r\n * Intercept: yBar - xBar * slope\r\n */\r\n function computeRegressionLine(xValues: number[], yValues: number[]): LineDefinition {\r\n debug.assertValue(xValues, 'xValues');\r\n debug.assertValue(yValues, 'yValues');\r\n\r\n let xBar = _.sum(xValues) / xValues.length;\r\n let yBar = _.sum(yValues) / yValues.length;\r\n\r\n let ssXX = _.chain(xValues)\r\n .map((x) => {\r\n return (x - xBar) ** 2;\r\n })\r\n .sum();\r\n\r\n let ssXY = _.chain(xValues)\r\n .map((x, i) => {\r\n return (x - xBar) * (yValues[i] - yBar);\r\n })\r\n .sum();\r\n\r\n let slope = ssXY / ssXX;\r\n let intercept = yBar - (xBar * slope);\r\n\r\n return {\r\n slope: slope,\r\n intercept: intercept\r\n };\r\n }\r\n\r\n function computeLineYValues(lineDef: LineDefinition, x1: number, x2: number): number[] {\r\n return [x1 * lineDef.slope + lineDef.intercept, x2 * lineDef.slope + lineDef.intercept];\r\n }\r\n\r\n function getValuesFromColumn(column: DataViewCategoricalColumn, preferHighlights: boolean): PrimitiveValue[] {\r\n if (preferHighlights) {\r\n // Attempt to use highlight values. When X is categorical, we may not have highlight values so we should fall back to the non-highlight values.\r\n let valueColumn = <DataViewValueColumn>column;\r\n if (valueColumn.highlights) {\r\n return valueColumn.highlights;\r\n }\r\n }\r\n\r\n return column.values;\r\n }\r\n\r\n function getDataPointsBySeries(xColumns: DataViewCategoricalColumn[], yColumns: DataViewCategoricalColumn[], combineSeries: boolean, preferHighlights: boolean): DataPointSet[] {\r\n let dataPointsBySeries: DataPointSet[] = [];\r\n let xValueArray: PrimitiveValue[][] = _.map(xColumns, (column) => getValuesFromColumn(column, preferHighlights));\r\n let seriesYValues: PrimitiveValue[][] = _.map(yColumns, (column) => getValuesFromColumn(column, preferHighlights));\r\n\r\n let multipleXValueColumns: boolean = xColumns.length > 1;\r\n for (let i = 0; i < seriesYValues.length; i++) {\r\n let xValues = multipleXValueColumns ? xValueArray[i] : xValueArray[0];\r\n let yValues = seriesYValues[i];\r\n\r\n if (combineSeries && dataPointsBySeries.length > 0) {\r\n dataPointsBySeries[0].xValues = dataPointsBySeries[0].xValues.concat(xValues);\r\n dataPointsBySeries[0].yValues = dataPointsBySeries[0].yValues.concat(yValues);\r\n }\r\n else {\r\n dataPointsBySeries.push({\r\n xValues: xValues,\r\n yValues: yValues,\r\n });\r\n }\r\n }\r\n\r\n return dataPointsBySeries;\r\n }\r\n\r\n function createRegressionDataView(\r\n xColumnSource: DataViewMetadataColumn,\r\n yColumnSource: DataViewMetadataColumn,\r\n groupValues: PrimitiveValue[],\r\n categories: PrimitiveValue[],\r\n values: PrimitiveValue[][],\r\n highlights: PrimitiveValue[][],\r\n sourceDataView: DataView,\r\n regressionDataViewMapping: DataViewMapping,\r\n objectDescriptors: DataViewObjectDescriptors,\r\n objectDefinitions: DataViewObjectDefinitions,\r\n colorAllocatorFactory: IColorAllocatorFactory): DataView {\r\n debug.assertValue(xColumnSource, 'xColumnSource');\r\n debug.assertValue(yColumnSource, 'yColumnSource');\r\n debug.assertValue(categories, 'categories');\r\n debug.assertValue(values, 'values');\r\n debug.assertValue(sourceDataView, 'sourceDataView');\r\n debug.assertValue(objectDescriptors, 'objectDescriptors');\r\n debug.assertValue(objectDefinitions, 'objectDefinitions');\r\n debug.assertValue(colorAllocatorFactory, 'colorAllocatorFactory');\r\n debug.assertAnyValue(highlights, 'highlights');\r\n debug.assert(!highlights || highlights.length === values.length, 'highlights should have the same length as values');\r\n\r\n let xRole: string = (<DataViewRoleForMapping>regressionDataViewMapping.categorical.categories).for.in;\r\n let grouped = (<DataViewGroupedRoleMapping>regressionDataViewMapping.categorical.values).group;\r\n let yRole: string;\r\n let seriesRole: string;\r\n if (grouped && !_.isEmpty(grouped.select)) {\r\n yRole = (<DataViewRoleForMapping>grouped.select[0]).for ?\r\n (<DataViewRoleForMapping>grouped.select[0]).for.in :\r\n (<DataViewRoleBindMapping>grouped.select[0]).bind.to;\r\n seriesRole = grouped.by;\r\n }\r\n if (!yRole || !seriesRole)\r\n return;\r\n\r\n let categoricalRoles: { [name: string]: boolean } = {[xRole]: true};\r\n let valueRoles: { [name: string]: boolean } = {[yRole]: true};\r\n let seriesRoles: { [name: string]: boolean } = {[seriesRole]: true};\r\n\r\n let valuesBySeries: DataViewBuilderSeriesData[][] = [];\r\n for (let index in values) {\r\n let seriesData: DataViewBuilderSeriesData = {\r\n values: values[index],\r\n };\r\n\r\n if (highlights)\r\n seriesData.highlights = highlights[index];\r\n\r\n valuesBySeries.push([seriesData]);\r\n }\r\n\r\n let regressionDataView: DataView = createCategoricalDataViewBuilder()\r\n .withCategory({\r\n source: {\r\n displayName: xColumnSource.displayName,\r\n queryName: regressionXQueryName,\r\n type: xColumnSource.type,\r\n isMeasure: false,\r\n roles: categoricalRoles\r\n },\r\n values: categories,\r\n identityFrom: {\r\n fields: [SQExprBuilder.columnRef(SQExprBuilder.entity('s', 'RegressionEntity'), 'RegressionCategories')],\r\n },\r\n })\r\n .withGroupedValues({\r\n groupColumn: {\r\n source: {\r\n displayName: yColumnSource.displayName + 'Regression',\r\n queryName: regressionSeriesQueryName,\r\n type: yColumnSource.type,\r\n isMeasure: yColumnSource.isMeasure,\r\n roles: seriesRoles\r\n },\r\n values: groupValues,\r\n identityFrom: {\r\n fields: [SQExprBuilder.columnRef(SQExprBuilder.entity('s', 'RegressionEntity'), 'RegressionSeries')],\r\n }\r\n },\r\n valueColumns: [{\r\n source: {\r\n displayName: yColumnSource.displayName,\r\n queryName: regressionYQueryName,\r\n type: yColumnSource.type,\r\n isMeasure: yColumnSource.isMeasure,\r\n roles: valueRoles\r\n },\r\n }],\r\n data: valuesBySeries\r\n })\r\n .build();\r\n DataViewTransform.transformObjects(regressionDataView, data.StandardDataViewKinds.Categorical, objectDescriptors, objectDefinitions, [], colorAllocatorFactory);\r\n return regressionDataView;\r\n }\r\n\r\n function hasHighlightValues(columns: DataViewCategoricalColumn[]): boolean {\r\n return _.any(columns, (column) => {\r\n let valueColumn = <DataViewValueColumn>column;\r\n return valueColumn.highlights != null;\r\n });\r\n }\r\n }\r\n\r\n interface DataPointSet {\r\n xValues: any[];\r\n yValues: any[];\r\n }\r\n\r\n interface LineDefinition {\r\n slope: number;\r\n intercept: number;\r\n }\r\n\r\n interface LineDefinitionSet {\r\n lineDefs: LineDefinition[];\r\n xMin: PrimitiveValue;\r\n xMax: PrimitiveValue;\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import RoleKindByQueryRef = DataViewAnalysis.RoleKindByQueryRef;\r\n\r\n export interface DataViewSelectTransform {\r\n displayName?: string;\r\n queryName?: string;\r\n format?: string;\r\n type?: ValueType;\r\n roles?: { [roleName: string]: boolean };\r\n kpi?: DataViewKpiColumnMetadata;\r\n sort?: SortDirection;\r\n expr?: SQExpr;\r\n discourageAggregationAcrossGroups?: boolean;\r\n\r\n /** Describes the default value applied to a column, if any. */\r\n defaultValue?: DefaultValueDefinition;\r\n }\r\n\r\n export module DataViewSelectTransform {\r\n /** Convert selection info to projections */\r\n export function projectionsFromSelects(selects: DataViewSelectTransform[], projectionActiveItems: DataViewProjectionActiveItems): QueryProjectionsByRole {\r\n debug.assertAnyValue(selects, \"selects\");\r\n debug.assertAnyValue(projectionActiveItems, \"projectionActiveItems\");\r\n\r\n let projections: QueryProjectionsByRole = {};\r\n for (let select of selects) {\r\n let roles = select.roles;\r\n if (!roles)\r\n continue;\r\n\r\n for (let roleName in roles) {\r\n if (roles[roleName]) {\r\n let qp = projections[roleName];\r\n if (!qp)\r\n qp = projections[roleName] = new QueryProjectionCollection([]);\r\n qp.all().push({ queryRef: select.queryName });\r\n\r\n if (projectionActiveItems && projectionActiveItems[roleName])\r\n qp.activeProjectionRefs = _.map(projectionActiveItems[roleName], (activeItem: DataViewProjectionActiveItemInfo) => activeItem.queryRef);\r\n }\r\n }\r\n }\r\n\r\n return projections;\r\n }\r\n\r\n /** Use selections and metadata to fashion query role kinds */\r\n export function createRoleKindFromMetadata(selects: DataViewSelectTransform[], metadata: DataViewMetadata): RoleKindByQueryRef {\r\n let roleKindByQueryRef: DataViewAnalysis.RoleKindByQueryRef = {};\r\n for (let column of metadata.columns) {\r\n if ((!column.index && column.index !== 0) || column.index < 0 || column.index >= selects.length)\r\n continue;\r\n\r\n let select = selects[column.index];\r\n if (select) {\r\n let queryRef = select.queryName;\r\n if (queryRef && roleKindByQueryRef[queryRef] === undefined) {\r\n roleKindByQueryRef[queryRef] = column.isMeasure ? VisualDataRoleKind.Measure : VisualDataRoleKind.Grouping;\r\n }\r\n }\r\n }\r\n return roleKindByQueryRef;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export interface ICategoricalEvalContext extends IEvalContext {\r\n setCurrentRowIndex(index: number): void;\r\n }\r\n\r\n export function createCategoricalEvalContext(colorAllocatorProvider: IColorAllocatorCache, dataViewCategorical: DataViewCategorical): ICategoricalEvalContext {\r\n return new CategoricalEvalContext(colorAllocatorProvider, dataViewCategorical);\r\n }\r\n\r\n class CategoricalEvalContext implements ICategoricalEvalContext {\r\n private colorAllocatorProvider: IColorAllocatorCache;\r\n private dataView: DataViewCategorical;\r\n private columnsByRole: { [name: string]: DataViewCategoricalColumn };\r\n private index: number;\r\n\r\n constructor(colorAllocatorProvider: IColorAllocatorCache, dataView: DataViewCategorical) {\r\n debug.assertValue(colorAllocatorProvider, 'colorAllocatorProvider');\r\n debug.assertValue(dataView, 'dataView');\r\n\r\n this.colorAllocatorProvider = colorAllocatorProvider;\r\n this.dataView = dataView;\r\n this.columnsByRole = {};\r\n }\r\n\r\n public getColorAllocator(expr: SQFillRuleExpr): IColorAllocator {\r\n return this.colorAllocatorProvider.get(expr);\r\n }\r\n\r\n public getExprValue(expr: SQExpr): PrimitiveValue {\r\n return;\r\n }\r\n\r\n public getRoleValue(roleName: string): PrimitiveValue {\r\n let columnsByRole = this.columnsByRole;\r\n let column = columnsByRole[roleName];\r\n if (!column)\r\n column = columnsByRole[roleName] = findRuleInputColumn(this.dataView, roleName);\r\n \r\n if (!column)\r\n return;\r\n\r\n let index = this.index;\r\n if (index != null)\r\n return column.values[this.index];\r\n }\r\n\r\n public setCurrentRowIndex(index: number): void {\r\n debug.assertValue(index, 'index');\r\n\r\n this.index = index;\r\n }\r\n }\r\n\r\n function findRuleInputColumn(dataViewCategorical: DataViewCategorical, inputRole: string): DataViewCategoricalColumn {\r\n debug.assertValue(dataViewCategorical, 'dataViewCategorical');\r\n\r\n return findRuleInputInColumns(dataViewCategorical.values, inputRole) ||\r\n findRuleInputInColumns(dataViewCategorical.categories, inputRole);\r\n }\r\n\r\n function findRuleInputInColumns(columns: DataViewCategoricalColumn[], inputRole: string): DataViewCategoricalColumn {\r\n debug.assertAnyValue(columns, 'columns');\r\n\r\n if (!columns)\r\n return;\r\n\r\n for (let column of columns) {\r\n let roles = column.source.roles;\r\n if (!roles || !roles[inputRole])\r\n continue;\r\n\r\n return column;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import SQExpr = powerbi.data.SQExpr;\r\n\r\n export interface ITableEvalContext extends IEvalContext {\r\n setCurrentRowIndex(index: number): void;\r\n }\r\n\r\n export function createTableEvalContext(colorAllocatorProvider: IColorAllocatorCache, dataViewTable: DataViewTable, selectTransforms: DataViewSelectTransform[]): ITableEvalContext {\r\n return new TableEvalContext(colorAllocatorProvider, dataViewTable, selectTransforms);\r\n }\r\n\r\n class TableEvalContext implements ITableEvalContext {\r\n private colorAllocatorProvider: IColorAllocatorCache;\r\n private dataView: DataViewTable;\r\n private rowIdx: number;\r\n private selectTransforms: DataViewSelectTransform[];\r\n\r\n constructor(colorAllocatorProvider: IColorAllocatorCache, dataView: DataViewTable, selectTransforms: DataViewSelectTransform[]) {\r\n debug.assertValue(colorAllocatorProvider, 'colorAllocatorProvider');\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(selectTransforms, 'selectTransforms');\r\n\r\n this.colorAllocatorProvider = colorAllocatorProvider;\r\n this.dataView = dataView;\r\n this.selectTransforms = selectTransforms;\r\n }\r\n\r\n public getColorAllocator(expr: SQFillRuleExpr): IColorAllocator {\r\n return this.colorAllocatorProvider.get(expr);\r\n }\r\n\r\n public getExprValue(expr: SQExpr): PrimitiveValue {\r\n debug.assertValue(expr, 'expr');\r\n\r\n let rowIdx = this.rowIdx;\r\n if (rowIdx == null)\r\n return;\r\n\r\n return getExprValueFromTable(expr, this.selectTransforms, this.dataView, rowIdx);\r\n }\r\n\r\n public getRoleValue(roleName: string): PrimitiveValue {\r\n return;\r\n }\r\n\r\n public setCurrentRowIndex(index: number): void {\r\n debug.assertValue(index, 'index');\r\n\r\n this.rowIdx = index;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export class RuleEvaluation {\r\n // NOTE: even though this class has no behaviour, we still use a class to facilitate instanceof checks.\r\n\r\n public evaluate(evalContext: IEvalContext): any {\r\n debug.assertFail('Abstract method RuleEvaluation.evaluate not implemented.');\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export class ColorRuleEvaluation extends RuleEvaluation {\r\n private inputRole: string;\r\n private allocator: IColorAllocator;\r\n\r\n constructor(inputRole: string, allocator: IColorAllocator) {\r\n debug.assertValue(inputRole, 'inputRole');\r\n debug.assertValue(allocator, 'allocator');\r\n\r\n super();\r\n this.inputRole = inputRole;\r\n this.allocator = allocator;\r\n }\r\n\r\n public evaluate(evalContext: IEvalContext): any {\r\n debug.assertValue(evalContext, 'evalContext');\r\n\r\n let value: any = evalContext.getRoleValue(this.inputRole);\r\n if (value !== undefined)\r\n return this.allocator.color(value);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data.utils {\r\n import inherit = Prototype.inherit;\r\n import inheritSingle = Prototype.inheritSingle;\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n\r\n export module DataViewMatrixUtils {\r\n\r\n /**\r\n * Invokes the specified callback once per leaf nodes (including root-level leaves and descendent leaves) of the \r\n * specified rootNodes, with an optional index parameter in the callback that is the 0-based index of the \r\n * particular leaf node in the context of this forEachLeafNode(...) invocation.\r\n *\r\n * If rootNodes is null or undefined or empty, the specified callback will not get invoked.\r\n *\r\n * The treePath parameter in the callback is an ordered set of nodes that form the path from the specified \r\n * rootNodes down to the leafNode argument itself. If callback leafNode is one of the specified rootNodes,\r\n * then treePath will be an array of length 1 containing that very node.\r\n *\r\n * IMPORTANT: The treePath array passed to the callback will be modified after the callback function returns!\r\n * If your callback needs to retain a copy of the treePath, please clone the array before returning.\r\n */\r\n export function forEachLeafNode(\r\n rootNodes: DataViewMatrixNode | DataViewMatrixNode[],\r\n callback: (leafNode: DataViewMatrixNode, index?: number, treePath?: DataViewMatrixNode[]) => void): void {\r\n debug.assertAnyValue(rootNodes, 'rootNodes');\r\n debug.assertValue(callback, 'callback');\r\n\r\n // Note: Don't do \"if (!_.isEmpty(rootNodes))\" for checking whether rootNodes is an empty array DataViewMatrixNode[],\r\n // because rootNodes can also be an non-array DataViewMatrixNode, and an empty object can be a valid root node DataViewMatrixNode, \r\n // for the fact that all the properties on DataViewMatrixNode are optional...\r\n if (rootNodes) {\r\n if (isNodeArray(rootNodes)) {\r\n let index = 0;\r\n for (let rootNode of rootNodes) {\r\n if (rootNode) {\r\n index = forEachLeafNodeRecursive(rootNode, index, [], callback);\r\n }\r\n }\r\n }\r\n else {\r\n forEachLeafNodeRecursive(rootNodes, 0, [], callback);\r\n }\r\n }\r\n }\r\n\r\n function isNodeArray(nodeOrNodeArray: DataViewMatrixNode | DataViewMatrixNode[]): nodeOrNodeArray is DataViewMatrixNode[] {\r\n return ArrayExtensions.isArrayOrInheritedArray(nodeOrNodeArray);\r\n }\r\n\r\n /**\r\n * Recursively traverses to each leaf node of the specified matrixNode and invokes callback with each of them.\r\n * Returns the index for the next node after the last node that this function invokes callback with.\r\n *\r\n * @treePath an array that contains the path from the specified rootNodes in forEachLeafNode() down to the parent of the argument matrixNode (i.e. treePath does not contain the matrixNode argument yet).\r\n */\r\n function forEachLeafNodeRecursive(\r\n matrixNode: DataViewMatrixNode,\r\n nextIndex: number,\r\n treePath: DataViewMatrixNode[],\r\n callback: (leafNode: DataViewMatrixNode, index?: number, treePath?: DataViewMatrixNode[]) => void): number {\r\n debug.assertValue(matrixNode, 'matrixNode');\r\n debug.assertValue(treePath, 'treePath');\r\n debug.assertValue(callback, 'callback');\r\n\r\n // If treePath already contains matrixNode, then either one of the following errors has happened:\r\n // 1. the caller code mistakenly added matrixNode to treePath, or\r\n // 2. the callback modified treePath by adding a node to it, or\r\n // 3. the matrix hierarchy contains a cyclical node reference.');\r\n debug.assert(!_.contains(treePath, matrixNode),\r\n 'pre-condition: treePath must not already contain matrixNode');\r\n\r\n treePath.push(matrixNode);\r\n\r\n if (_.isEmpty(matrixNode.children)) { // if it is a leaf node\r\n callback(matrixNode, nextIndex, treePath);\r\n nextIndex++;\r\n }\r\n else {\r\n let children = matrixNode.children;\r\n for (let nextChild of children) {\r\n if (nextChild) {\r\n nextIndex = forEachLeafNodeRecursive(nextChild, nextIndex, treePath, callback);\r\n }\r\n }\r\n }\r\n\r\n debug.assert(_.last(treePath) === matrixNode, 'pre-condition: the callback given to forEachLeafNode() is not supposed to modify the treePath argument array.');\r\n treePath.pop();\r\n\r\n return nextIndex;\r\n }\r\n\r\n /**\r\n * Returned an object tree where each node and its children property are inherited from the specified node \r\n * hierarchy, from the root down to the nodes at the specified deepestLevelToInherit, inclusively.\r\n *\r\n * The inherited nodes at level === deepestLevelToInherit will NOT get an inherited version of children array \r\n * property, i.e. its children property is the same array object referenced in the input node's object tree.\r\n *\r\n * @param node The input node with the hierarchy object tree.\r\n * @param deepestLevelToInherit The highest level for a node to get inherited. See DataViewMatrixNode.level property.\r\n * @param useInheritSingle If true, then a node will get inherited in the returned object tree only if it is \r\n * not already an inherited object. Same goes for the node's children property. This is useful for creating \r\n * \"visual DataView\" objects from \"query DataView\" objects, as object inheritance is the mechanism for \r\n * \"visual DataView\" to override properties in \"query DataView\", and that \"query DataView\" never contains \r\n * inherited objects.\r\n */\r\n export function inheritMatrixNodeHierarchy(\r\n node: DataViewMatrixNode,\r\n deepestLevelToInherit: number,\r\n useInheritSingle: boolean): DataViewMatrixNode {\r\n debug.assertValue(node, 'node');\r\n debug.assert(deepestLevelToInherit >= 0, 'deepestLevelToInherit >= 0');\r\n debug.assertValue(useInheritSingle, 'useInheritSingle');\r\n\r\n let returnNode = node;\r\n\r\n // Note: The level property of DataViewMatrix.rows.root and DataViewMatrix.columns.root are always undefined.\r\n // Also, in a matrix with multiple column grouping fields and multiple value fields, the DataViewMatrixNode\r\n // for the Grand Total column in the column hierarchy will have children nodes where level > (parent.level + 1):\r\n // {\r\n // \"level\": 0,\r\n // \"isSubtotal\": true,\r\n // \"children\": [\r\n // { \"level\": 2, \"isSubtotal\": true },\r\n // { \"level\": 2, \"levelSourceIndex\": 1, \"isSubtotal\": true }\r\n // ]\r\n // }\r\n let isRootNode = _.isUndefined(node.level);\r\n let shouldInheritCurrentNode = isRootNode || (node.level <= deepestLevelToInherit);\r\n if (shouldInheritCurrentNode) {\r\n let inheritFunc = useInheritSingle ? inheritSingle : inherit;\r\n let inheritedNode: DataViewMatrixNode = inheritFunc(node);\r\n\r\n let shouldInheritChildNodes = isRootNode || (node.level < deepestLevelToInherit);\r\n if (shouldInheritChildNodes && !_.isEmpty(node.children)) {\r\n inheritedNode.children = inheritFunc(node.children); // first, make an inherited array\r\n for (let i = 0, ilen = inheritedNode.children.length; i < ilen; i++) {\r\n inheritedNode.children[i] =\r\n inheritMatrixNodeHierarchy(inheritedNode.children[i], deepestLevelToInherit, useInheritSingle);\r\n }\r\n }\r\n\r\n returnNode = inheritedNode;\r\n }\r\n\r\n return returnNode;\r\n }\r\n\r\n /**\r\n * Returns true if the specified matrixOrHierarchy contains any composite grouping, i.e. a grouping on multiple columns.\r\n * An example of composite grouping is one on [Year, Quarter, Month], where a particular group instance can have\r\n * Year === 2016, Quarter === 'Qtr 1', Month === 1.\r\n *\r\n * Returns false if the specified matrixOrHierarchy does not contain any composite group, \r\n * or if matrixOrHierarchy is null or undefined.\r\n */\r\n export function containsCompositeGroup(matrixOrHierarchy: DataViewMatrix | DataViewHierarchy): boolean {\r\n debug.assertAnyValue(matrixOrHierarchy, 'matrixOrHierarchy');\r\n\r\n let hasCompositeGroup = false;\r\n\r\n if (matrixOrHierarchy) {\r\n if (isMatrix(matrixOrHierarchy)) {\r\n hasCompositeGroup = containsCompositeGroup(matrixOrHierarchy.rows) ||\r\n containsCompositeGroup(matrixOrHierarchy.columns);\r\n }\r\n else {\r\n let hierarchyLevels = matrixOrHierarchy.levels;\r\n if (!_.isEmpty(hierarchyLevels)) {\r\n for (var level of hierarchyLevels) {\r\n // it takes at least 2 columns at the same hierarchy level to form a composite group...\r\n if (level.sources && (level.sources.length >= 2)) {\r\n\r\n debug.assert(_.all(level.sources, sourceColumn => sourceColumn.isMeasure === level.sources[0].isMeasure),\r\n 'pre-condition: in a valid DataViewMatrix, the source columns in each of its hierarchy levels must either be all non-measure columns (i.e. a grouping level) or all measure columns (i.e. a measure headers level)');\r\n\r\n // Measure headers are not group\r\n let isMeasureHeadersLevel = level.sources[0].isMeasure;\r\n if (!isMeasureHeadersLevel) {\r\n hasCompositeGroup = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return hasCompositeGroup;\r\n }\r\n\r\n function isMatrix(matrixOrHierarchy: DataViewMatrix | DataViewHierarchy): matrixOrHierarchy is DataViewMatrix {\r\n return 'rows' in matrixOrHierarchy &&\r\n 'columns' in matrixOrHierarchy &&\r\n 'valueSources' in matrixOrHierarchy;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data.utils {\r\n export module DataViewMetadataColumnUtils {\r\n\r\n export interface MetadataColumnAndProjectionIndex {\r\n /**\r\n * A metadata column taken from a source collection, e.g. DataViewHierarchyLevel.sources, DataViewMatrix.valueSources...\r\n */\r\n metadataColumn: DataViewMetadataColumn;\r\n\r\n /**\r\n * The index of this.metadataColumn in its sources collection.\r\n *\r\n * E.g.1 This can be the value of the property DataViewMatrixGroupValue.levelSourceIndex which is the index of this.metadataColumn in DataViewHierarchyLevel.sources.\r\n * E.g.2 This can be the value of the property DataViewMatrixNodeValue.valueSourceIndex which refer to columns in DataViewMatrix.valueSources.\r\n */\r\n sourceIndex: number;\r\n\r\n /**\r\n * The index of this.metadataColumn in the projection ordering of a given role.\r\n */\r\n projectionOrderIndex: number;\r\n }\r\n\r\n /**\r\n * Returns true iff the specified metadataColumn is assigned to the specified targetRole.\r\n */\r\n export function isForRole(metadataColumn: DataViewMetadataColumn, targetRole: string): boolean {\r\n debug.assertValue(metadataColumn, 'metadataColumn');\r\n debug.assertValue(targetRole, 'targetRole');\r\n\r\n let roles = metadataColumn.roles;\r\n return roles && roles[targetRole];\r\n }\r\n\r\n /**\r\n * Joins each column in the specified columnSources with projection ordering index into a wrapper object.\r\n *\r\n * Note: In order for this function to reliably calculate the \"source index\" of a particular column, the \r\n * specified columnSources must be a non-filtered array of column sources from the DataView, such as\r\n * the DataViewHierarchyLevel.sources and DataViewMatrix.valueSources array properties.\r\n *\r\n * @param columnSources E.g. DataViewHierarchyLevel.sources, DataViewMatrix.valueSources...\r\n * @param projection The projection ordering. It must contain an ordering for the specified role.\r\n * @param role The role for getting the relevant projection ordering, as well as for filtering out the irrevalent columns in columnSources.\r\n */\r\n export function joinMetadataColumnsAndProjectionOrder(\r\n columnSources: DataViewMetadataColumn[],\r\n projection: DataViewProjectionOrdering,\r\n role: string): MetadataColumnAndProjectionIndex[] {\r\n debug.assertAnyValue(columnSources, 'columnSources');\r\n debug.assert(_.all(columnSources, column => _.isNumber(column.index)),\r\n 'pre-condition: Every value in columnSources must already have its Select Index property initialized.');\r\n debug.assertNonEmpty(projection[role], 'projection[role]');\r\n debug.assert(_.all(columnSources, column => !isForRole(column, role) || _.contains(projection[role], column.index)),\r\n 'pre-condition: The projection order for the specified role must contain the Select Index of every column with matching role in the specified columnSources.');\r\n\r\n let jointResult: MetadataColumnAndProjectionIndex[] = [];\r\n\r\n if (!_.isEmpty(columnSources)) {\r\n let projectionOrderSelectIndices = projection[role];\r\n let selectIndexToProjectionIndexMap: { [selectIndex: number]: number } = {};\r\n for (let i = 0, ilen = projectionOrderSelectIndices.length; i < ilen; i++) {\r\n let selectIndex = projectionOrderSelectIndices[i];\r\n selectIndexToProjectionIndexMap[selectIndex] = i;\r\n }\r\n\r\n for (let j = 0, jlen = columnSources.length; j < jlen; j++) {\r\n var column = columnSources[j];\r\n if (isForRole(column, role)) {\r\n let jointColumnInfo: MetadataColumnAndProjectionIndex = {\r\n metadataColumn: column,\r\n sourceIndex: j,\r\n projectionOrderIndex: selectIndexToProjectionIndexMap[column.index]\r\n };\r\n\r\n jointResult.push(jointColumnInfo);\r\n }\r\n }\r\n }\r\n\r\n return jointResult;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import ArrayNamedItems = jsCommon.ArrayNamedItems;\r\n\r\n export class ConceptualSchema {\r\n public entities: ArrayNamedItems<ConceptualEntity>;\r\n public capabilities: ConceptualCapabilities;\r\n\r\n /** Indicates whether the user can edit this ConceptualSchema. This is used to enable/disable model authoring UX. */\r\n public canEdit: boolean;\r\n\r\n public findProperty(entityName: string, propertyName: string): ConceptualProperty {\r\n let entity = this.entities.withName(entityName);\r\n if (!entity || _.isEmpty(entity.properties))\r\n return;\r\n\r\n return entity.properties.withName(propertyName);\r\n }\r\n\r\n public findHierarchy(entityName: string, name: string): ConceptualHierarchy {\r\n let entity = this.entities.withName(entityName);\r\n if (!entity || _.isEmpty(entity.hierarchies))\r\n return;\r\n\r\n return entity.hierarchies.withName(name);\r\n }\r\n\r\n public findHierarchyByVariation(\r\n variationEntityName: string,\r\n variationColumnName: string,\r\n variationName: string,\r\n hierarchyName: string): ConceptualHierarchy {\r\n\r\n let variationEntity = this.entities.withName(variationEntityName);\r\n if (!variationEntity || _.isEmpty(variationEntity.properties))\r\n return;\r\n\r\n let variationProperty = variationEntity.properties.withName(variationColumnName);\r\n if (!variationProperty)\r\n return;\r\n\r\n let variationColumn = variationProperty.column;\r\n if (!variationColumn || _.isEmpty(variationColumn.variations))\r\n return;\r\n\r\n let variation = variationColumn.variations.withName(variationName);\r\n if (variation) {\r\n let targetEntity = variation.navigationProperty ? variation.navigationProperty.targetEntity : variationEntity;\r\n if (!targetEntity || _.isEmpty(targetEntity.hierarchies))\r\n return;\r\n\r\n return targetEntity.hierarchies.withName(hierarchyName);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the first property of the entity whose kpi is tied to kpiProperty\r\n */\r\n public findPropertyWithKpi(entityName: string, kpiProperty: ConceptualProperty): ConceptualProperty {\r\n debug.assertValue(kpiProperty, 'kpiProperty');\r\n\r\n let entity = this.entities.withName(entityName);\r\n if (!entity || _.isEmpty(entity.properties))\r\n return;\r\n\r\n for (let prop of entity.properties) {\r\n if (prop &&\r\n prop.measure &&\r\n prop.measure.kpi &&\r\n (prop.measure.kpi.status === kpiProperty || prop.measure.kpi.goal === kpiProperty))\r\n return prop;\r\n }\r\n\r\n return;\r\n }\r\n }\r\n\r\n export interface ConceptualCapabilities {\r\n discourageQueryAggregateUsage: boolean;\r\n normalizedFiveStateKpiRange: boolean;\r\n supportsMedian: boolean;\r\n supportsPercentile: boolean;\r\n supportsScopedEval: boolean;\r\n }\r\n\r\n export interface ConceptualPropertyItemContainer {\r\n properties: ArrayNamedItems<ConceptualProperty>;\r\n hierarchies?: ArrayNamedItems<ConceptualHierarchy>;\r\n displayFolders?: ArrayNamedItems<ConceptualDisplayFolder>;\r\n }\r\n\r\n export interface ConceptualPropertyItem {\r\n name: string;\r\n displayName: string;\r\n hidden?: boolean;\r\n }\r\n\r\n export interface ConceptualEntity extends ConceptualPropertyItemContainer {\r\n name: string;\r\n displayName: string;\r\n visibility?: ConceptualVisibility;\r\n calculated?: boolean;\r\n queryable?: ConceptualQueryableState;\r\n navigationProperties?: ArrayNamedItems<ConceptualNavigationProperty>;\r\n }\r\n\r\n export interface ConceptualDisplayFolder extends ConceptualPropertyItem, ConceptualPropertyItemContainer {\r\n }\r\n\r\n export interface ConceptualProperty extends ConceptualPropertyItem {\r\n type: ValueType;\r\n kind: ConceptualPropertyKind;\r\n format?: string;\r\n column?: ConceptualColumn;\r\n queryable?: ConceptualQueryableState;\r\n measure?: ConceptualMeasure;\r\n kpiValue?: ConceptualProperty;\r\n }\r\n\r\n export interface ConceptualHierarchy extends ConceptualPropertyItem {\r\n levels: ArrayNamedItems<ConceptualHierarchyLevel>;\r\n }\r\n\r\n export interface ConceptualHierarchyLevel extends ConceptualPropertyItem {\r\n column: ConceptualProperty;\r\n }\r\n\r\n export interface ConceptualNavigationProperty {\r\n name: string;\r\n isActive: boolean;\r\n sourceColumn?: ConceptualColumn;\r\n targetEntity: ConceptualEntity;\r\n sourceMultiplicity: ConceptualMultiplicity;\r\n targetMultiplicity: ConceptualMultiplicity;\r\n }\r\n\r\n export interface ConceptualVariationSource {\r\n name: string;\r\n isDefault: boolean;\r\n navigationProperty?: ConceptualNavigationProperty;\r\n defaultHierarchy?: ConceptualHierarchy;\r\n defaultProperty?: ConceptualProperty;\r\n }\r\n\r\n export interface ConceptualColumn {\r\n defaultAggregate?: ConceptualDefaultAggregate;\r\n keys?: ArrayNamedItems<ConceptualProperty>;\r\n idOnEntityKey?: boolean;\r\n calculated?: boolean;\r\n defaultValue?: SQConstantExpr;\r\n variations?: ArrayNamedItems<ConceptualVariationSource>;\r\n aggregateBehavior?: ConceptualAggregateBehavior;\r\n }\r\n\r\n export interface ConceptualMeasure {\r\n kpi?: ConceptualPropertyKpi;\r\n }\r\n\r\n export interface ConceptualPropertyKpi {\r\n statusMetadata: DataViewKpiColumnMetadata;\r\n trendMetadata?: DataViewKpiColumnMetadata;\r\n status?: ConceptualProperty;\r\n goal?: ConceptualProperty;\r\n trend?: ConceptualProperty;\r\n }\r\n\r\n export const enum ConceptualVisibility {\r\n Visible = 0,\r\n Hidden = 1,\r\n ShowAsVariationsOnly = 2,\r\n IsPrivate = 4,\r\n }\r\n\r\n export const enum ConceptualQueryableState {\r\n Queryable = 0,\r\n Error = 1,\r\n }\r\n\r\n export const enum ConceptualMultiplicity {\r\n ZeroOrOne = 0,\r\n One = 1,\r\n Many = 2,\r\n }\r\n\r\n export const enum ConceptualPropertyKind {\r\n Column,\r\n Measure,\r\n Kpi,\r\n }\r\n\r\n export const enum ConceptualDefaultAggregate {\r\n Default,\r\n None,\r\n Sum,\r\n Count,\r\n Min,\r\n Max,\r\n Average,\r\n DistinctCount,\r\n }\r\n\r\n // TODO: Remove this (replaced by ValueType)\r\n export enum ConceptualDataCategory {\r\n None,\r\n Address,\r\n City,\r\n Company,\r\n Continent,\r\n Country,\r\n County,\r\n Date,\r\n Image,\r\n ImageUrl,\r\n Latitude,\r\n Longitude,\r\n Organization,\r\n Place,\r\n PostalCode,\r\n Product,\r\n StateOrProvince,\r\n WebUrl,\r\n }\r\n\r\n export const enum ConceptualAggregateBehavior {\r\n Default,\r\n DiscourageAcrossGroups,\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import ArrayNamedItems = jsCommon.ArrayNamedItems;\r\n import StringExtensions = jsCommon.StringExtensions;\r\n import FederatedConceptualSchema = powerbi.data.FederatedConceptualSchema;\r\n import FieldExprColumnPattern = powerbi.data.FieldExprColumnPattern;\r\n import FieldExprColumnAggrPattern = powerbi.data.FieldExprColumnAggrPattern;\r\n import FieldExprColumnHierarchyLevelVariationPattern = powerbi.data.FieldExprColumnHierarchyLevelVariationPattern;\r\n import FieldExprEntityPattern = powerbi.data.FieldExprEntityPattern;\r\n import FieldExprEntityAggrPattern = powerbi.data.FieldExprEntityAggrPattern;\r\n import FieldExprHierarchyPattern = powerbi.data.FieldExprHierarchyPattern;\r\n import FieldExprHierarchyLevelPattern = powerbi.data.FieldExprHierarchyLevelPattern;\r\n import FieldExprHierarchyLevelAggrPattern = powerbi.data.FieldExprHierarchyLevelAggrPattern;\r\n import FieldExprMeasurePattern = powerbi.data.FieldExprMeasurePattern;\r\n import FieldExprPattern = powerbi.data.FieldExprPattern;\r\n import FieldExprPercentilePattern = powerbi.data.FieldExprPercentilePattern;\r\n import FieldExprSelectRefPattern = powerbi.data.FieldExprSelectRefPattern;\r\n import FieldExprPercentOfGrandTotalPattern = powerbi.data.FieldExprPercentOfGrandTotalPattern;\r\n import IFieldExprPatternVisitor = powerbi.data.IFieldExprPatternVisitor;\r\n import QueryProjectionsByRole = data.QueryProjectionsByRole;\r\n\r\n export interface ScriptResult {\r\n source: string;\r\n provider: string;\r\n }\r\n\r\n export module ScriptResultUtil {\r\n\r\n export function findScriptResult(dataViewMappings: DataViewMapping[] | data.CompiledDataViewMapping[]): DataViewScriptResultMapping | data.CompiledDataViewScriptResultMapping {\r\n if (dataViewMappings && dataViewMappings.length === 1) {\r\n return dataViewMappings[0].scriptResult;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n export function extractScriptResult(dataViewMappings: data.CompiledDataViewMapping[]): ScriptResult {\r\n let scriptResult = findScriptResult(dataViewMappings);\r\n if (scriptResult) {\r\n let objects = dataViewMappings[0].metadata.objects;\r\n let source: string = DataViewObjects.getValue<string>(objects, scriptResult.script.source);\r\n let provider: string = DataViewObjects.getValue<string>(objects, scriptResult.script.provider);\r\n return {\r\n source: source,\r\n provider: provider\r\n };\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n export function extractScriptResultFromVisualConfig(dataViewMappings: DataViewMapping[], objects: powerbi.data.DataViewObjectDefinitions): ScriptResult {\r\n let scriptResult = findScriptResult(dataViewMappings);\r\n if (scriptResult && objects) {\r\n let scriptSource = <data.SQConstantExpr>data.DataViewObjectDefinitions.getValue(objects, scriptResult.script.source, null);\r\n let provider = <data.SQConstantExpr>data.DataViewObjectDefinitions.getValue(objects, scriptResult.script.provider, null);\r\n return {\r\n source: scriptSource ? scriptSource.value : null,\r\n provider: provider ? provider.value : null\r\n };\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n export function getScriptInput(projections: QueryProjectionsByRole, selects: ArrayNamedItems<data.NamedSQExpr>, schema: FederatedConceptualSchema): data.ScriptInput {\r\n let scriptInput: data.ScriptInput = {\r\n VariableName: \"dataset\",\r\n Columns: []\r\n };\r\n\r\n // Go over all the projections, and create an input column according to the order\r\n // of the projections (including duplicate expressions)\r\n if (projections && selects && !_.isEmpty(selects)) {\r\n let scriptInputColumnNames: string[] = [];\r\n let scriptInputColumns: data.ScriptInputColumn[] = [];\r\n for (let role in projections) {\r\n for (let projection of projections[role].all()) {\r\n let select = selects.withName(projection.queryRef);\r\n if (select) {\r\n let scriptInputColumn = <data.ScriptInputColumn>{\r\n QueryName: select.name,\r\n Name: FieldExprPattern.visit(select.expr, new ScriptInputColumnNameVisitor(schema))\r\n };\r\n\r\n scriptInputColumns.push(scriptInputColumn);\r\n scriptInputColumnNames.push(scriptInputColumn.Name);\r\n }\r\n }\r\n }\r\n\r\n // Make sure the names of the columns are unique\r\n scriptInputColumnNames = StringExtensions.ensureUniqueNames(scriptInputColumnNames);\r\n\r\n // Update the names of the columns\r\n for (let i = 0; i < scriptInputColumnNames.length; i++) {\r\n let scriptInputColumn = scriptInputColumns[i];\r\n scriptInputColumn.Name = scriptInputColumnNames[i];\r\n }\r\n\r\n scriptInput.Columns = scriptInputColumns;\r\n }\r\n\r\n return scriptInput;\r\n }\r\n\r\n class ScriptInputColumnNameVisitor implements IFieldExprPatternVisitor<string>\r\n {\r\n private federatedSchema: FederatedConceptualSchema;\r\n\r\n constructor(federatedSchema: FederatedConceptualSchema) {\r\n this.federatedSchema = federatedSchema;\r\n }\r\n\r\n public visitColumn(column: FieldExprColumnPattern): string {\r\n return ScriptInputColumnNameVisitor.getNameForProperty(column, this.federatedSchema);\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): string {\r\n return ScriptInputColumnNameVisitor.getNameForProperty(columnAggr, this.federatedSchema);\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): string {\r\n return ScriptInputColumnNameVisitor.getVariationLevelName(columnHierarchyLevelVariation, this.federatedSchema);\r\n }\r\n\r\n public visitEntity(entity: FieldExprEntityPattern): string {\r\n return entity.entity;\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): string {\r\n return entityAggr.entity;\r\n }\r\n\r\n public visitHierarchy(hierarchy: FieldExprHierarchyPattern): string {\r\n return ScriptInputColumnNameVisitor.getNameForHierarchy(hierarchy, this.federatedSchema);\r\n }\r\n\r\n public visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): string {\r\n /*Hierarchy levels are not supported yet*/\r\n return;\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): string {\r\n return ScriptInputColumnNameVisitor.getNameForProperty(hierarchyLevelAggr, this.federatedSchema);\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): string {\r\n return ScriptInputColumnNameVisitor.getNameForProperty(measure, this.federatedSchema);\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): string {\r\n return FieldExprPattern.visit(selectRef, this);\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): string {\r\n return FieldExprPattern.visit(percentile.arg, this);\r\n }\r\n\r\n public visitPercentOfGrandTotal(percentOfGrandTotal: FieldExprPercentOfGrandTotalPattern): string {\r\n return FieldExprPattern.visit(percentOfGrandTotal.baseExpr, this);\r\n }\r\n\r\n private static getNameForHierarchy(pattern: FieldExprHierarchyPattern, federatedScheam: FederatedConceptualSchema): string {\r\n debug.assertValue(pattern, 'pattern');\r\n\r\n let schema = federatedScheam.schema(pattern.schema),\r\n hierarchy = schema.findHierarchy(pattern.entity, pattern.name);\r\n\r\n if (hierarchy)\r\n return hierarchy.name;\r\n }\r\n\r\n private static getNameForProperty(pattern: data.FieldExprPropertyPattern, federatedSchema: FederatedConceptualSchema): string {\r\n debug.assertValue(pattern, 'pattern');\r\n\r\n let schema = federatedSchema.schema(pattern.schema),\r\n property = schema.findProperty(pattern.entity, pattern.name);\r\n\r\n if (property)\r\n return property.name;\r\n }\r\n\r\n private static getVariationLevelName(pattern: FieldExprColumnHierarchyLevelVariationPattern, federatedSchema: FederatedConceptualSchema): string {\r\n debug.assertValue(pattern, 'pattern');\r\n\r\n let source = pattern.source;\r\n let prop = federatedSchema.schema(source.schema).findProperty(source.entity, source.name);\r\n if (!prop)\r\n return;\r\n\r\n let variations = prop.column.variations;\r\n for (let variation of variations)\r\n if (variation.name === pattern.variationName)\r\n for (let level of variation.defaultHierarchy.levels)\r\n if (level.name === pattern.level.level)\r\n return level.column.name;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data.segmentation {\r\n\r\n export interface DataViewTableSegment extends DataViewTable {\r\n /**\r\n * Index of the last item that had a merge flag in the underlying data.\r\n * We assume merge flags are not random but adjacent to each other.\r\n */\r\n lastMergeIndex?: number;\r\n }\r\n\r\n export interface DataViewTreeSegmentNode extends DataViewTreeNode {\r\n /** Indicates whether the node is a duplicate of a node from a previous segment. */\r\n isMerge?: boolean;\r\n }\r\n\r\n export interface DataViewCategoricalSegment extends DataViewCategorical {\r\n /**\r\n * Index of the last item that had a merge flag in the underlying data.\r\n * We assume merge flags are not random but adjacent to each other.\r\n */\r\n lastMergeIndex?: number;\r\n }\r\n\r\n export interface DataViewMatrixSegmentNode extends DataViewMatrixNode {\r\n /**\r\n * Index of the last item that had a merge flag in the underlying data.\r\n * We assume merge flags are not random but adjacent to each other.\r\n */\r\n isMerge?: boolean;\r\n }\r\n\r\n export module DataViewMerger {\r\n\r\n export function mergeDataViews(source: DataView, segment: DataView): void {\r\n\r\n if (!DataViewAnalysis.isMetadataEquivalent(source.metadata, segment.metadata)) {\r\n debug.assertFail(\"Cannot merge data views with different metadata columns\");\r\n }\r\n\r\n // The last segment is complete. We mark the source as complete.\r\n if (!segment.metadata.segment)\r\n delete source.metadata.segment;\r\n\r\n if (source.table && segment.table)\r\n mergeTables(source.table, <DataViewTableSegment>segment.table);\r\n\r\n if (source.categorical && segment.categorical)\r\n mergeCategorical(source.categorical, <DataViewCategoricalSegment>segment.categorical);\r\n\r\n // Tree cannot support subtotals hence we can get into situations\r\n // where a node has no children in one segment and more than 1 child\r\n // in another segment.\r\n if (source.tree && segment.tree)\r\n mergeTreeNodes(source.tree.root, segment.tree.root, true /*allowDifferentStructure*/);\r\n\r\n if (source.matrix && segment.matrix)\r\n mergeTreeNodes(source.matrix.rows.root, segment.matrix.rows.root, false /*allowDifferentStructure*/);\r\n }\r\n\r\n /** Note: Public for testability */\r\n export function mergeTables(source: DataViewTable, segment: DataViewTableSegment): void {\r\n debug.assertValue(source, 'source');\r\n debug.assertValue(segment, 'segment');\r\n\r\n if (_.isEmpty(segment.rows))\r\n return;\r\n\r\n let mergeIndex = segment.lastMergeIndex + 1;\r\n merge(source.rows, segment.rows, mergeIndex);\r\n\r\n debug.assert(!source.identity === !segment.identity, 'The existence of identity in the new segment is different than the source');\r\n if (segment.identity)\r\n merge(source.identity, segment.identity, mergeIndex);\r\n }\r\n\r\n /**\r\n * Merge categories values and identities\r\n *\r\n * Note: Public for testability\r\n */\r\n export function mergeCategorical(source: DataViewCategorical, segment: DataViewCategoricalSegment): void {\r\n debug.assertValue(source, 'source');\r\n debug.assertValue(segment, 'segment');\r\n\r\n // Merge categories values and identities\r\n if (source.categories && segment.categories) {\r\n let segmentCategoriesLength = segment.categories.length;\r\n debug.assert(source.categories.length === segmentCategoriesLength, \"Source and segment categories have different lengths.\");\r\n\r\n for (let categoryIndex: number = 0; categoryIndex < segmentCategoriesLength; categoryIndex++) {\r\n let segmentCategory = segment.categories[categoryIndex];\r\n let sourceCategory = source.categories[categoryIndex];\r\n\r\n debug.assert(DataViewAnalysis.areMetadataColumnsEquivalent(sourceCategory.source, segmentCategory.source), \"Source and segment category have different sources.\");\r\n debug.assert(_.isUndefined(sourceCategory.values) ? _.isUndefined(sourceCategory.identity) : true, 'Source category is missing values but has identities.');\r\n\r\n let mergeIndex = segment.lastMergeIndex + 1;\r\n if (segmentCategory.values) {\r\n merge(sourceCategory.values, segmentCategory.values, mergeIndex);\r\n }\r\n\r\n if (segmentCategory.identity) {\r\n merge(sourceCategory.identity, segmentCategory.identity, mergeIndex);\r\n }\r\n }\r\n }\r\n\r\n // Merge values for each value column\r\n if (source.values && segment.values) {\r\n let segmentValuesLength = segment.values.length;\r\n debug.assert(source.values.length === segmentValuesLength, \"Source and segment values have different lengths.\");\r\n\r\n for (let valueIndex: number = 0; valueIndex < segmentValuesLength; valueIndex++) {\r\n let segmentValue = segment.values[valueIndex];\r\n let sourceValue = source.values[valueIndex];\r\n\r\n debug.assert(DataViewAnalysis.areMetadataColumnsEquivalent(sourceValue.source, segmentValue.source), \"Source and segment value have different sources.\");\r\n\r\n if (!sourceValue.values && segmentValue.values) {\r\n sourceValue.values = [];\r\n }\r\n\r\n let mergeIndex = segment.lastMergeIndex + 1;\r\n if (segmentValue.values) {\r\n merge(sourceValue.values, segmentValue.values, mergeIndex);\r\n }\r\n\r\n if (segmentValue.highlights) {\r\n merge(sourceValue.highlights, segmentValue.highlights, mergeIndex);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Merges the segment array starting at the specified index into the source array\r\n * and returns the segment slice that wasn't merged.\r\n * The segment array is spliced up to specified index in the process.\r\n */\r\n function merge(source: any[], segment: any[], index?: number): any[] {\r\n if (index >= segment.length)\r\n return segment;\r\n\r\n let result: any[] = [];\r\n if (index !== undefined)\r\n result = segment.splice(0, index);\r\n\r\n Array.prototype.push.apply(source, segment);\r\n\r\n return result;\r\n }\r\n\r\n /** Note: Public for testability */\r\n export function mergeTreeNodes(sourceRoot: DataViewTreeNode, segmentRoot: DataViewTreeNode, allowDifferentStructure: boolean): void {\r\n debug.assertValue(sourceRoot, 'sourceRoot');\r\n debug.assertValue(segmentRoot, 'segmentRoot');\r\n\r\n if (!segmentRoot.children || segmentRoot.children.length === 0)\r\n return;\r\n\r\n if (allowDifferentStructure && (!sourceRoot.children || sourceRoot.children.length === 0)) {\r\n sourceRoot.children = segmentRoot.children;\r\n return;\r\n }\r\n\r\n debug.assert(sourceRoot.children && sourceRoot.children.length >= 0,\r\n \"Source tree has different structure than segment.\");\r\n\r\n let firstAppendIndex = findFirstAppendIndex(segmentRoot.children);\r\n let lastSourceChild = sourceRoot.children[sourceRoot.children.length - 1];\r\n let mergedChildren = merge(sourceRoot.children, segmentRoot.children, firstAppendIndex);\r\n\r\n if (mergedChildren.length > 0)\r\n mergeTreeNodes(lastSourceChild, mergedChildren[mergedChildren.length - 1], allowDifferentStructure);\r\n }\r\n\r\n function findFirstAppendIndex(children: DataViewTreeNode[]): number {\r\n if (children.length === 0)\r\n return 0;\r\n\r\n let i: number = 0;\r\n for (; i < children.length; i++) {\r\n let childSegment: DataViewTreeSegmentNode = <DataViewTreeSegmentNode>children[i];\r\n if (!childSegment.isMerge)\r\n break;\r\n }\r\n\r\n return i;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n\r\n /** Rewrites an expression tree, including all descendant nodes. */\r\n export class SQExprRewriter implements ISQExprVisitor<SQExpr>, IFillRuleDefinitionVisitor<LinearGradient2Definition, LinearGradient3Definition> {\r\n public visitColumnRef(expr: SQColumnRefExpr): SQExpr {\r\n let origArg = expr.source,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return expr;\r\n\r\n return new SQColumnRefExpr(rewrittenArg, expr.ref);\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr): SQExpr {\r\n let origArg = expr.source,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return expr;\r\n\r\n return new SQMeasureRefExpr(rewrittenArg, expr.ref);\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): SQExpr {\r\n let origArg = expr.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return expr;\r\n\r\n return new SQAggregationExpr(rewrittenArg, expr.func);\r\n }\r\n\r\n public visitSelectRef(expr: SQSelectRefExpr): SQExpr {\r\n return expr;\r\n }\r\n\r\n public visitPercentile(expr: SQPercentileExpr): SQExpr {\r\n let origArg = expr.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return expr;\r\n\r\n return new SQPercentileExpr(rewrittenArg, expr.k, expr.exclusive);\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): SQExpr {\r\n let origArg = expr.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return expr;\r\n\r\n return new SQHierarchyExpr(rewrittenArg, expr.hierarchy);\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): SQExpr {\r\n let origArg = expr.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return expr;\r\n\r\n return new SQHierarchyLevelExpr(rewrittenArg, expr.level);\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr): SQExpr {\r\n let origArg = expr.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return expr;\r\n\r\n return new SQPropertyVariationSourceExpr(rewrittenArg, expr.name, expr.property);\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): SQExpr {\r\n return expr;\r\n }\r\n\r\n public visitAnd(orig: SQAndExpr): SQExpr {\r\n let origLeft = orig.left,\r\n rewrittenLeft = origLeft.accept(this),\r\n origRight = orig.right,\r\n rewrittenRight = origRight.accept(this);\r\n\r\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\r\n return orig;\r\n\r\n return new SQAndExpr(rewrittenLeft, rewrittenRight);\r\n }\r\n\r\n public visitBetween(orig: SQBetweenExpr): SQExpr {\r\n let origArg = orig.arg,\r\n rewrittenArg = origArg.accept(this),\r\n origLower = orig.lower,\r\n rewrittenLower = origLower.accept(this),\r\n origUpper = orig.upper,\r\n rewrittenUpper = origUpper.accept(this);\r\n\r\n if (origArg === rewrittenArg && origLower === rewrittenLower && origUpper === rewrittenUpper)\r\n return orig;\r\n\r\n return new SQBetweenExpr(rewrittenArg, rewrittenLower, rewrittenUpper);\r\n }\r\n\r\n public visitIn(orig: SQInExpr): SQExpr {\r\n let origArgs = orig.args,\r\n rewrittenArgs = this.rewriteAll(origArgs),\r\n origValues: SQExpr[][] = orig.values,\r\n rewrittenValues: SQExpr[][];\r\n\r\n for (let i = 0, len = origValues.length; i < len; i++) {\r\n let origValueTuple = origValues[i],\r\n rewrittenValueTuple = this.rewriteAll(origValueTuple);\r\n\r\n if (origValueTuple !== rewrittenValueTuple && !rewrittenValues)\r\n rewrittenValues = ArrayExtensions.take(origValues, i);\r\n\r\n if (rewrittenValues)\r\n rewrittenValues.push(rewrittenValueTuple);\r\n }\r\n\r\n if (origArgs === rewrittenArgs && !rewrittenValues)\r\n return orig;\r\n\r\n return new SQInExpr(rewrittenArgs, rewrittenValues || origValues);\r\n }\r\n\r\n private rewriteAll(origExprs: SQExpr[]): SQExpr[] {\r\n debug.assertValue(origExprs, 'origExprs');\r\n\r\n let rewrittenResult: SQExpr[];\r\n for (let i = 0, len = origExprs.length; i < len; i++) {\r\n let origExpr = origExprs[i],\r\n rewrittenExpr = origExpr.accept(this);\r\n\r\n if (origExpr !== rewrittenExpr && !rewrittenResult)\r\n rewrittenResult = ArrayExtensions.take(origExprs, i);\r\n\r\n if (rewrittenResult)\r\n rewrittenResult.push(rewrittenExpr);\r\n }\r\n\r\n return rewrittenResult || origExprs;\r\n }\r\n\r\n public visitOr(orig: SQOrExpr): SQExpr {\r\n let origLeft = orig.left,\r\n rewrittenLeft = origLeft.accept(this),\r\n origRight = orig.right,\r\n rewrittenRight = origRight.accept(this);\r\n\r\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\r\n return orig;\r\n\r\n return new SQOrExpr(rewrittenLeft, rewrittenRight);\r\n }\r\n\r\n public visitCompare(orig: SQCompareExpr): SQExpr {\r\n let origLeft = orig.left,\r\n rewrittenLeft = origLeft.accept(this),\r\n origRight = orig.right,\r\n rewrittenRight = origRight.accept(this);\r\n\r\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\r\n return orig;\r\n\r\n return new SQCompareExpr(orig.comparison, rewrittenLeft, rewrittenRight);\r\n }\r\n\r\n public visitContains(orig: SQContainsExpr): SQExpr {\r\n let origLeft = orig.left,\r\n rewrittenLeft = origLeft.accept(this),\r\n origRight = orig.right,\r\n rewrittenRight = origRight.accept(this);\r\n\r\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\r\n return orig;\r\n\r\n return new SQContainsExpr(rewrittenLeft, rewrittenRight);\r\n }\r\n\r\n public visitExists(orig: SQExistsExpr): SQExpr {\r\n let origArg = orig.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return orig;\r\n\r\n return new SQExistsExpr(rewrittenArg);\r\n }\r\n\r\n public visitNot(orig: SQNotExpr): SQExpr {\r\n let origArg = orig.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return orig;\r\n\r\n return new SQNotExpr(rewrittenArg);\r\n }\r\n\r\n public visitStartsWith(orig: SQStartsWithExpr): SQExpr {\r\n let origLeft = orig.left,\r\n rewrittenLeft = origLeft.accept(this),\r\n origRight = orig.right,\r\n rewrittenRight = origRight.accept(this);\r\n\r\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\r\n return orig;\r\n\r\n return new SQStartsWithExpr(rewrittenLeft, rewrittenRight);\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr): SQExpr {\r\n return expr;\r\n }\r\n\r\n public visitDateSpan(orig: SQDateSpanExpr): SQExpr {\r\n let origArg = orig.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return orig;\r\n\r\n return new SQDateSpanExpr(orig.unit, rewrittenArg);\r\n }\r\n\r\n public visitDateAdd(orig: SQDateAddExpr): SQExpr {\r\n let origArg = orig.arg,\r\n rewrittenArg = origArg.accept(this);\r\n\r\n if (origArg === rewrittenArg)\r\n return orig;\r\n\r\n return new SQDateAddExpr(orig.unit, orig.amount, rewrittenArg);\r\n }\r\n\r\n public visitNow(orig: SQNowExpr): SQExpr {\r\n return orig;\r\n }\r\n\r\n public visitDefaultValue(orig: SQDefaultValueExpr): SQExpr {\r\n return orig;\r\n }\r\n\r\n public visitAnyValue(orig: SQAnyValueExpr): SQExpr {\r\n return orig;\r\n }\r\n\r\n public visitArithmetic(orig: SQArithmeticExpr): SQExpr {\r\n let origLeft = orig.left,\r\n rewrittenLeft = origLeft.accept(this),\r\n origRight = orig.right,\r\n rewrittenRight = origRight.accept(this);\r\n\r\n if (origLeft === rewrittenLeft && origRight === rewrittenRight)\r\n return orig;\r\n\r\n return new SQArithmeticExpr(rewrittenLeft, rewrittenRight, orig.operator);\r\n }\r\n\r\n public visitScopedEval(orig: SQScopedEvalExpr): SQExpr {\r\n let origExpression = orig.expression,\r\n rewrittenExpression = origExpression.accept(this),\r\n origScope = orig.scope,\r\n rewrittenScope = this.rewriteAll(origScope);\r\n\r\n if (origExpression === rewrittenExpression && origScope === rewrittenScope)\r\n return orig;\r\n\r\n return new SQScopedEvalExpr(rewrittenExpression, rewrittenScope);\r\n }\r\n\r\n public visitFillRule(orig: SQFillRuleExpr): SQExpr {\r\n let origInput = orig.input,\r\n rewrittenInput = origInput.accept(this);\r\n\r\n let origRule = orig.rule;\r\n\r\n let origGradient2 = origRule.linearGradient2,\r\n rewrittenGradient2 = origGradient2;\r\n if (origGradient2) {\r\n rewrittenGradient2 = this.visitLinearGradient2(origGradient2);\r\n }\r\n\r\n let origGradient3 = origRule.linearGradient3,\r\n rewrittenGradient3 = origGradient3;\r\n if (origGradient3) {\r\n rewrittenGradient3 = this.visitLinearGradient3(origGradient3);\r\n }\r\n\r\n if (origInput !== rewrittenInput ||\r\n origGradient2 !== rewrittenGradient2 ||\r\n origGradient3 !== rewrittenGradient3) {\r\n let rewrittenRule: FillRuleDefinition = {};\r\n if (rewrittenGradient2)\r\n rewrittenRule.linearGradient2 = rewrittenGradient2;\r\n if (rewrittenGradient3)\r\n rewrittenRule.linearGradient3 = rewrittenGradient3;\r\n\r\n return new SQFillRuleExpr(rewrittenInput, rewrittenRule);\r\n }\r\n\r\n return orig;\r\n }\r\n\r\n public visitLinearGradient2(origGradient2: LinearGradient2Definition): LinearGradient2Definition {\r\n debug.assertValue(origGradient2, 'origGradient2');\r\n\r\n let origMin = origGradient2.min,\r\n rewrittenMin = this.visitFillRuleStop(origMin),\r\n origMax = origGradient2.max,\r\n rewrittenMax = this.visitFillRuleStop(origMax);\r\n\r\n if (origMin !== rewrittenMin || origMax !== rewrittenMax) {\r\n return {\r\n min: rewrittenMin,\r\n max: rewrittenMax,\r\n };\r\n }\r\n\r\n return origGradient2;\r\n }\r\n\r\n public visitLinearGradient3(origGradient3: LinearGradient3Definition): LinearGradient3Definition {\r\n debug.assertValue(origGradient3, 'origGradient3');\r\n\r\n let origMin = origGradient3.min,\r\n rewrittenMin = this.visitFillRuleStop(origMin),\r\n origMid = origGradient3.mid,\r\n rewrittenMid = this.visitFillRuleStop(origMid),\r\n origMax = origGradient3.max,\r\n rewrittenMax = this.visitFillRuleStop(origMax);\r\n\r\n if (origMin !== rewrittenMin || origMid !== rewrittenMid || origMax !== rewrittenMax) {\r\n return {\r\n min: rewrittenMin,\r\n mid: rewrittenMid,\r\n max: rewrittenMax,\r\n };\r\n }\r\n\r\n return origGradient3;\r\n }\r\n\r\n private visitFillRuleStop(stop: RuleColorStopDefinition): RuleColorStopDefinition {\r\n debug.assertValue(stop, 'stop');\r\n\r\n let origColor = stop.color,\r\n rewrittenColor = stop.color.accept(this);\r\n\r\n let origValue = stop.value,\r\n rewrittenValue = origValue;\r\n if (origValue)\r\n rewrittenValue = origValue.accept(this);\r\n\r\n if (origColor !== rewrittenColor || origValue !== rewrittenValue) {\r\n let rewrittenStop: RuleColorStopDefinition = {\r\n color: rewrittenColor\r\n };\r\n\r\n if (rewrittenValue)\r\n rewrittenStop.value = rewrittenValue;\r\n\r\n return rewrittenStop;\r\n }\r\n\r\n return stop;\r\n }\r\n\r\n public visitResourcePackageItem(orig: SQResourcePackageItemExpr): SQExpr {\r\n return orig;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n /** Responsible for writing equality comparisons against a field to an SQInExpr. */\r\n export module EqualsToInRewriter {\r\n export function run(expr: SQExpr): SQExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.accept(new Rewriter());\r\n }\r\n\r\n class Rewriter extends SQExprRewriter {\r\n private current: InBuilder;\r\n\r\n constructor() {\r\n super();\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr): SQExpr {\r\n if (expr.comparison !== QueryComparisonKind.Equal)\r\n return this.visitUnsupported(expr);\r\n if (!this.isSupported(expr.left) || !this.isSupported(expr.right))\r\n return this.visitUnsupported(expr);\r\n\r\n let leftIsComparand = this.isComparand(expr.left);\r\n let rightIsComparand = this.isComparand(expr.right);\r\n if (leftIsComparand === rightIsComparand)\r\n return this.visitUnsupported(expr);\r\n\r\n let operand: SQExpr = leftIsComparand\r\n ? expr.left\r\n : expr.right;\r\n let value: SQExpr = leftIsComparand\r\n ? expr.right\r\n : expr.left;\r\n\r\n let current = this.current;\r\n if (!current) {\r\n return SQExprBuilder.inExpr([operand], [[value]]);\r\n }\r\n\r\n current.add(operand, value);\r\n\r\n return expr;\r\n }\r\n\r\n public visitOr(expr: SQOrExpr): SQExpr {\r\n if (!this.isSupported(expr.left) || !this.isSupported(expr.right))\r\n return this.visitUnsupported(expr);\r\n\r\n let current: InBuilder;\r\n if (!this.current) {\r\n current = this.current = new InBuilder();\r\n }\r\n\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n\r\n if (current) {\r\n this.current = null;\r\n return current.complete() || expr;\r\n }\r\n\r\n return expr;\r\n }\r\n\r\n public visitAnd(expr: SQAndExpr): SQExpr {\r\n if (!this.isSupported(expr.left) || !this.isSupported(expr.right))\r\n return this.visitUnsupported(expr);\r\n\r\n let current = this.current;\r\n if (current) {\r\n // NOTE: Composite keys are not supported by this algorithm.\r\n current.cancel();\r\n return expr;\r\n }\r\n\r\n return super.visitAnd(expr);\r\n }\r\n\r\n private visitUnsupported(expr: SQExpr): SQExpr {\r\n let current = this.current;\r\n if (current)\r\n current.cancel();\r\n\r\n return expr;\r\n }\r\n\r\n private isSupported(expr: SQExpr): boolean {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr instanceof SQCompareExpr\r\n || expr instanceof SQColumnRefExpr\r\n || expr instanceof SQConstantExpr\r\n || expr instanceof SQHierarchyLevelExpr\r\n || expr instanceof SQOrExpr\r\n || expr instanceof SQAndExpr;\r\n }\r\n\r\n private isComparand(expr: SQExpr): boolean {\r\n return expr instanceof SQColumnRefExpr\r\n || expr instanceof SQHierarchyLevelExpr;\r\n }\r\n }\r\n\r\n class InBuilder {\r\n private operand: SQExpr;\r\n private values: SQExpr[];\r\n private cancelled: boolean;\r\n\r\n public add(operand: SQExpr, value: SQExpr): void {\r\n debug.assertValue(operand, 'operand');\r\n debug.assertValue(value, 'value');\r\n\r\n if (this.cancelled)\r\n return;\r\n\r\n if (this.operand && !SQExpr.equals(operand, this.operand)) {\r\n this.cancel();\r\n return;\r\n }\r\n\r\n this.operand = operand;\r\n\r\n let values = this.values;\r\n if (!values)\r\n values = this.values = [];\r\n\r\n values.push(value);\r\n }\r\n\r\n public cancel(): void {\r\n this.cancelled = true;\r\n }\r\n\r\n public complete(): SQInExpr {\r\n if (this.cancelled || !this.operand)\r\n return;\r\n\r\n return SQExprBuilder.inExpr([this.operand], _.map(this.values, v => [v]));\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n export interface FilterValueScopeIdsContainer {\r\n isNot: boolean;\r\n scopeIds: DataViewScopeIdentity[];\r\n }\r\n\r\n export module SQExprConverter {\r\n export function asScopeIdsContainer(filter: SemanticFilter, fieldSQExprs: SQExpr[]): FilterValueScopeIdsContainer {\r\n debug.assertValue(filter, 'filter');\r\n debug.assertValue(fieldSQExprs, 'fieldSQExprs');\r\n debug.assert(fieldSQExprs.length > 0, 'There should be at least 1 field expression.');\r\n\r\n let filterItems = filter.conditions();\r\n debug.assert(filterItems.length === 1, 'There should be exactly 1 filter expression.');\r\n let filterItem = filterItems[0];\r\n if (filterItem) {\r\n let visitor = new FilterScopeIdsCollectorVisitor(fieldSQExprs);\r\n if (filterItem.accept(visitor))\r\n return visitor.getResult();\r\n }\r\n }\r\n\r\n /** Gets a comparand value from the given DataViewScopeIdentity. */\r\n export function getFirstComparandValue(identity: DataViewScopeIdentity): any {\r\n debug.assertValue(identity, 'identity');\r\n\r\n let comparandExpr = (<SQExpr>identity.expr).accept(new FindComparandVisitor());\r\n if (comparandExpr)\r\n return comparandExpr.value;\r\n }\r\n }\r\n\r\n /** Collect filter values from simple semantic filter that is similar to 'is any of' or 'is not any of', getResult() returns a collection of scopeIds.**/\r\n class FilterScopeIdsCollectorVisitor extends DefaultSQExprVisitor<boolean>{\r\n private isRoot: boolean;\r\n private isNot: boolean;\r\n private keyExprsCount: number;\r\n private valueExprs: SQExpr[];\r\n private fieldExprs: SQExpr[];\r\n\r\n constructor(fieldSQExprs:SQExpr[]) {\r\n super();\r\n this.isRoot = true;\r\n this.isNot = false;\r\n this.keyExprsCount = null;\r\n this.valueExprs = [];\r\n\r\n // Need to drop the entitylet before create the scopeIdentity. The ScopeIdentity created on the client is used to\r\n // compare the ScopeIdentity came from the server. But server doesn't have the entity variable concept, so we will\r\n // need to drop it in order to use JsonComparer.\r\n this.fieldExprs = [];\r\n for (let field of fieldSQExprs) {\r\n this.fieldExprs.push(SQExprBuilder.removeEntityVariables(field));\r\n }\r\n }\r\n\r\n public getResult(): FilterValueScopeIdsContainer {\r\n debug.assert(this.fieldExprs.length > 0, 'fieldExprs has at least one fieldExpr'); \r\n\r\n let valueExprs = this.valueExprs,\r\n scopeIds: DataViewScopeIdentity[] = [];\r\n let valueCount: number = this.keyExprsCount || 1;\r\n\r\n for (let startIndex = 0, endIndex = valueCount, len = valueExprs.length; startIndex < len && endIndex <= len;) {\r\n let values = valueExprs.slice(startIndex, endIndex);\r\n let scopeId = FilterScopeIdsCollectorVisitor.getScopeIdentity(this.fieldExprs, values);\r\n\r\n if (!jsCommon.ArrayExtensions.isInArray(scopeIds, scopeId, DataViewScopeIdentity.equals))\r\n scopeIds.push(scopeId);\r\n\r\n startIndex += valueCount;\r\n endIndex += valueCount;\r\n }\r\n\r\n return {\r\n isNot: this.isNot,\r\n scopeIds: scopeIds,\r\n };\r\n }\r\n\r\n private static getScopeIdentity(fieldExprs: SQExpr[], valueExprs: SQExpr[]): DataViewScopeIdentity {\r\n debug.assert(valueExprs.length > 0, 'valueExprs has at least one valueExpr');\r\n debug.assert(valueExprs.length === fieldExprs.length, 'fieldExpr and valueExpr count should match');\r\n\r\n let compoundSQExpr: SQExpr;\r\n for (let i = 0, len = fieldExprs.length; i < len; i++) {\r\n let equalsExpr = SQExprBuilder.equal(fieldExprs[i], valueExprs[i]);\r\n if (!compoundSQExpr)\r\n compoundSQExpr = equalsExpr;\r\n else\r\n compoundSQExpr = SQExprBuilder.and(compoundSQExpr, equalsExpr);\r\n }\r\n\r\n return createDataViewScopeIdentity(compoundSQExpr);\r\n }\r\n\r\n public visitOr(expr: SQOrExpr): boolean {\r\n if (this.keyExprsCount !== null)\r\n return this.unsupportedSQExpr();\r\n\r\n this.isRoot = false;\r\n return expr.left.accept(this) && expr.right.accept(this);\r\n }\r\n\r\n public visitNot(expr: SQNotExpr): boolean {\r\n if (!this.isRoot)\r\n return this.unsupportedSQExpr();\r\n\r\n this.isNot = true;\r\n return expr.arg.accept(this);\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr): boolean {\r\n if (this.isRoot && expr.type.primitiveType === PrimitiveType.Null)\r\n return this.unsupportedSQExpr();\r\n\r\n this.valueExprs.push(expr); \r\n return true;\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr): boolean {\r\n if (this.keyExprsCount !== null)\r\n return this.unsupportedSQExpr();\r\n\r\n this.isRoot = false;\r\n\r\n if (expr.comparison !== QueryComparisonKind.Equal)\r\n return this.unsupportedSQExpr();\r\n\r\n return expr.left.accept(this) && expr.right.accept(this);\r\n }\r\n\r\n public visitIn(expr: SQInExpr): boolean {\r\n this.keyExprsCount = 0;\r\n let result: boolean;\r\n this.isRoot = false;\r\n for (let arg of expr.args) {\r\n result = arg.accept(this);\r\n if (!result)\r\n return this.unsupportedSQExpr();\r\n\r\n this.keyExprsCount++;\r\n }\r\n\r\n if (this.keyExprsCount !== this.fieldExprs.length)\r\n return this.unsupportedSQExpr();\r\n\r\n let values = expr.values;\r\n for (let valueTuple of values) {\r\n let jlen = valueTuple.length;\r\n debug.assert(jlen === this.keyExprsCount, \"keys count and values count should match\");\r\n\r\n for (let value of valueTuple) {\r\n result = value.accept(this);\r\n if (!result)\r\n return this.unsupportedSQExpr();\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): boolean {\r\n if (this.isRoot)\r\n return this.unsupportedSQExpr();\r\n\r\n let fixedExpr = SQExprBuilder.removeEntityVariables(expr);\r\n if (this.keyExprsCount !== null)\r\n return SQExpr.equals(this.fieldExprs[this.keyExprsCount], fixedExpr);\r\n\r\n return SQExpr.equals(this.fieldExprs[0], fixedExpr);\r\n }\r\n\r\n public visitDefaultValue(expr: SQDefaultValueExpr): boolean {\r\n if (this.isRoot || this.keyExprsCount !== null)\r\n return this.unsupportedSQExpr();\r\n\r\n this.valueExprs.push(expr);\r\n return true;\r\n }\r\n\r\n public visitAnyValue(expr: SQAnyValueExpr): boolean {\r\n if (this.isRoot || this.keyExprsCount !== null)\r\n return this.unsupportedSQExpr();\r\n\r\n this.valueExprs.push(expr);\r\n return true;\r\n }\r\n\r\n public visitDefault(expr: SQExpr): boolean {\r\n return this.unsupportedSQExpr();\r\n }\r\n\r\n private unsupportedSQExpr(): boolean {\r\n return false;\r\n }\r\n }\r\n\r\n class FindComparandVisitor extends DefaultSQExprVisitor<SQConstantExpr> {\r\n public visitAnd(expr: SQAndExpr): SQConstantExpr {\r\n return expr.left.accept(this) || expr.right.accept(this);\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr): SQConstantExpr {\r\n if (expr.comparison === QueryComparisonKind.Equal) {\r\n if (expr.right instanceof SQConstantExpr)\r\n return <SQConstantExpr>expr.right;\r\n if (expr.left instanceof SQConstantExpr)\r\n return <SQConstantExpr>expr.left;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n\r\n /** Recognizes DataViewScopeIdentity expression trees to extract comparison keys. */\r\n export module ScopeIdentityExtractor {\r\n export function getKeys(expr: SQExpr): SQExpr[] {\r\n let extractor = new ScopeIdExtractorImpl();\r\n expr.accept(extractor);\r\n\r\n if (extractor.malformed)\r\n return null;\r\n\r\n return ArrayExtensions.emptyToNull(extractor.keys);\r\n }\r\n\r\n export function getInExpr(expr: SQExpr): SQInExpr{\r\n let extractor = new ScopeIdExtractorImpl();\r\n expr.accept(extractor);\r\n\r\n if (extractor.malformed)\r\n return;\r\n \r\n let keys = ArrayExtensions.emptyToNull(extractor.keys);\r\n let keyValues = ArrayExtensions.emptyToNull(extractor.values);\r\n\r\n if (keys && keyValues)\r\n return data.SQExprBuilder.inExpr(keys, [keyValues]);\r\n }\r\n\r\n /**\r\n * Recognizes expressions of the form:\r\n * 1) Equals(ColRef, Constant)\r\n * 2) And(Equals(ColRef1, Constant1), Equals(ColRef2, Constant2))\r\n * or And(And(Equals(ColRef1, Constant1), Equals(ColRef2, Constant2)), Equals(ColRef3, Constant3)) etc..\r\n */\r\n class ScopeIdExtractorImpl extends DefaultSQExprVisitor<void> {\r\n public keys: SQExpr[] = [];\r\n public values: SQConstantExpr[] = [];\r\n public malformed: boolean;\r\n\r\n public visitAnd(expr: SQAndExpr): void {\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr): void {\r\n if (expr.comparison !== QueryComparisonKind.Equal) {\r\n this.visitDefault(expr);\r\n return;\r\n }\r\n debug.assert(expr.left instanceof SQExpr && expr.right instanceof SQConstantExpr, 'invalid compare expr operands');\r\n expr.left.accept(this);\r\n expr.right.accept(this);\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): void {\r\n this.keys.push(expr);\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): void {\r\n this.keys.push(expr);\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr): void {\r\n this.values.push(expr);\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr): void {\r\n this.keys.push(expr);\r\n }\r\n\r\n public visitDefault(expr: SQExpr): void {\r\n this.malformed = true;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export module PrimitiveValueEncoding {\r\n const SingleQuoteRegex = /'/g;\r\n\r\n export function decimal(value: number): string {\r\n debug.assertValue(value, 'value');\r\n\r\n return value + 'M';\r\n }\r\n\r\n export function double(value: number): string {\r\n debug.assertValue(value, 'value');\r\n\r\n return value + 'D';\r\n }\r\n\r\n export function integer(value: number): string {\r\n debug.assertValue(value, 'value');\r\n\r\n return value + 'L';\r\n }\r\n\r\n export function dateTime(value: Date): string {\r\n debug.assertValue(value, 'value');\r\n\r\n // Currently, server doesn't support timezone. All date time data on the server don't have time zone information.\r\n // So, when we construct a dateTime object on the client, we will need to ignor user's time zone and force it to be UTC time.\r\n // When we subtract the timeZone offset, the date time object will remain the same value as you entered but dropped the local timeZone.\r\n let date = new Date(value.getTime() - (value.getTimezoneOffset() * 60000));\r\n let dateTimeString = date.toISOString();\r\n\r\n // If it ends with Z, we want to get rid of it, because with trailing Z, it will assume the dateTime is UTC, but we don't want any timeZone information, so\r\n // we will drop it.\r\n // Also, we need to add Prefix and Suffix to match the dsr value format for dateTime object.\r\n if (jsCommon.StringExtensions.endsWith(dateTimeString, 'Z'))\r\n dateTimeString = dateTimeString.substr(0, dateTimeString.length - 1);\r\n return \"datetime'\" + dateTimeString + \"'\";\r\n }\r\n\r\n export function text(value: string): string {\r\n debug.assertValue(value, 'value');\r\n\r\n return \"'\" + value.replace(SingleQuoteRegex, \"''\") + \"'\";\r\n }\r\n\r\n export function nullEncoding(): string {\r\n return 'null';\r\n }\r\n\r\n export function boolean(value: boolean): string {\r\n return value ? 'true' : 'false';\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import Agg = powerbi.data.QueryAggregateFunction;\r\n\r\n export interface ISQAggregationOperations {\r\n /** Returns an array of supported aggregates for a given expr and role type. */\r\n getSupportedAggregates(\r\n expr: SQExpr,\r\n schema: FederatedConceptualSchema,\r\n targetTypes: ValueTypeDescriptor[]): QueryAggregateFunction[];\r\n\r\n isSupportedAggregate(\r\n expr: SQExpr,\r\n schema: FederatedConceptualSchema,\r\n aggregate: QueryAggregateFunction,\r\n targetTypes: ValueTypeDescriptor[]): boolean;\r\n\r\n createExprWithAggregate(\r\n expr: SQExpr,\r\n schema: FederatedConceptualSchema,\r\n aggregateNonNumericFields: boolean,\r\n targetTypes: ValueTypeDescriptor[],\r\n preferredAggregate?: QueryAggregateFunction): SQExpr;\r\n }\r\n\r\n export function createSQAggregationOperations(datetimeMinMaxSupported: boolean): ISQAggregationOperations {\r\n return new SQAggregationOperations(datetimeMinMaxSupported);\r\n }\r\n\r\n class SQAggregationOperations implements ISQAggregationOperations {\r\n constructor(private datetimeMinMaxSupported: boolean) {\r\n }\r\n\r\n public getSupportedAggregates(\r\n expr: SQExpr,\r\n schema: FederatedConceptualSchema,\r\n targetTypes: ValueTypeDescriptor[]): QueryAggregateFunction[] {\r\n\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(schema, 'schema');\r\n debug.assertAnyValue(targetTypes, 'targetTypes');\r\n\r\n let metadata = getMetadataForUnderlyingType(expr, schema);\r\n\r\n // don't use expr.validate as validate will be using this function and we end up in a recursive loop\r\n if (!metadata)\r\n return [];\r\n\r\n let valueType = metadata.type,\r\n fieldKind = metadata.kind,\r\n isPropertyIdentity = metadata.idOnEntityKey;\r\n\r\n if (!valueType)\r\n return [];\r\n\r\n // Cannot aggregate on model measures\r\n if (fieldKind === FieldKind.Measure)\r\n return [];\r\n\r\n if (valueType.numeric || valueType.integer) {\r\n let aggregates = [Agg.Sum, Agg.Avg, Agg.Min, Agg.Max, Agg.Count, Agg.CountNonNull, Agg.StandardDeviation, Agg.Variance];\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n\r\n let currentSchema = schema.schema(fieldExprItem.schema);\r\n if (currentSchema.capabilities.supportsMedian)\r\n aggregates.push(Agg.Median);\r\n\r\n return aggregates;\r\n }\r\n\r\n let aggregates: QueryAggregateFunction[] = [];\r\n\r\n // Min/Max of DateTime\r\n if (this.datetimeMinMaxSupported &&\r\n valueType.dateTime &&\r\n (_.isEmpty(targetTypes) || ValueType.isCompatibleTo(valueType, targetTypes))) {\r\n aggregates.push(Agg.Min);\r\n aggregates.push(Agg.Max);\r\n }\r\n\r\n // The supported aggregation types for an identity field are restricted to 'Count Non-Null' (e.g. for the field well aggregation options)\r\n // but a valid semantic query can return a less-restricted aggregation option which we should honor. (e.g. this results from Q&A)\r\n let distinctCountAggExists = SQExprInfo.getAggregate(expr) === Agg.Count;\r\n if (!(isPropertyIdentity && !distinctCountAggExists))\r\n aggregates.push(Agg.Count);\r\n\r\n aggregates.push(Agg.CountNonNull);\r\n\r\n return aggregates;\r\n }\r\n\r\n public isSupportedAggregate(\r\n expr: SQExpr,\r\n schema: FederatedConceptualSchema,\r\n aggregate: QueryAggregateFunction,\r\n targetTypes: ValueTypeDescriptor[]): boolean {\r\n\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(schema, 'schema');\r\n\r\n let supportedAggregates = this.getSupportedAggregates(expr, schema, targetTypes);\r\n return _.contains(supportedAggregates, aggregate);\r\n }\r\n\r\n public createExprWithAggregate(\r\n expr: SQExpr,\r\n schema: FederatedConceptualSchema,\r\n aggregateNonNumericFields: boolean,\r\n targetTypes: ValueTypeDescriptor[],\r\n preferredAggregate?: QueryAggregateFunction): SQExpr {\r\n\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(schema, 'schema');\r\n\r\n let aggregate: QueryAggregateFunction;\r\n if (preferredAggregate != null && this.isSupportedAggregate(expr, schema, preferredAggregate, targetTypes)) {\r\n aggregate = preferredAggregate;\r\n }\r\n else {\r\n aggregate = expr.getDefaultAggregate(schema, aggregateNonNumericFields);\r\n }\r\n if (aggregate !== undefined)\r\n expr = SQExprBuilder.aggregate(expr, aggregate);\r\n\r\n return expr;\r\n }\r\n }\r\n\r\n function getMetadataForUnderlyingType(expr: SQExpr, schema: FederatedConceptualSchema): SQExprMetadata {\r\n // Unwrap the aggregate (if the expr has one), and look at the underlying type.\r\n let metadata = SQExprBuilder.removeAggregate(expr).getMetadata(schema);\r\n\r\n if (!metadata)\r\n metadata = expr.getMetadata(schema);\r\n\r\n return metadata;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n export module SQHierarchyExprUtils {\r\n export function getConceptualHierarchyLevelFromExpr(\r\n conceptualSchema: FederatedConceptualSchema,\r\n fieldExpr: FieldExprPattern): ConceptualHierarchyLevel {\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n let hierarchyLevel = fieldExpr.hierarchyLevel || fieldExpr.hierarchyLevelAggr;\r\n if (hierarchyLevel)\r\n return SQHierarchyExprUtils.getConceptualHierarchyLevel(\r\n conceptualSchema,\r\n fieldExprItem.schema,\r\n fieldExprItem.entity,\r\n hierarchyLevel.name,\r\n hierarchyLevel.level);\r\n }\r\n\r\n export function getConceptualHierarchyLevel(\r\n conceptualSchema: FederatedConceptualSchema,\r\n schemaName: string,\r\n entity: string,\r\n hierarchy: string,\r\n hierarchyLevel: string): ConceptualHierarchyLevel {\r\n\r\n let schema = conceptualSchema.schema(schemaName);\r\n let conceptualHierarchy = schema.findHierarchy(entity, hierarchy);\r\n if (conceptualHierarchy) {\r\n return conceptualHierarchy.levels.withName(hierarchyLevel);\r\n }\r\n }\r\n\r\n export function getConceptualHierarchy(sqExpr: SQExpr, federatedSchema: FederatedConceptualSchema): ConceptualHierarchy {\r\n if (sqExpr instanceof SQHierarchyExpr) {\r\n let hierarchy = <SQHierarchyExpr>sqExpr;\r\n\r\n if (sqExpr.arg instanceof SQEntityExpr) {\r\n let entityExpr = <SQEntityExpr>sqExpr.arg;\r\n return federatedSchema\r\n .schema(entityExpr.schema)\r\n .findHierarchy(entityExpr.entity, hierarchy.hierarchy);\r\n } else if (sqExpr.arg instanceof SQPropertyVariationSourceExpr) {\r\n let variationExpr = <SQPropertyVariationSourceExpr>sqExpr.arg;\r\n let sourceEntityExpr = <SQEntityExpr>variationExpr.arg;\r\n return federatedSchema\r\n .schema(sourceEntityExpr.schema)\r\n .findHierarchyByVariation(sourceEntityExpr.entity, variationExpr.property, variationExpr.name, hierarchy.hierarchy);\r\n }\r\n }\r\n }\r\n\r\n export function expandExpr(schema: FederatedConceptualSchema, expr: SQExpr, suppressHierarchyLevelExpansion?: boolean): SQExpr | SQExpr[] {\r\n return SQExprHierarchyToHierarchyLevelConverter.convert(expr, schema) ||\r\n SQExprVariationConverter.expand(expr, schema) ||\r\n // If we are calling expandExpr from suppressHierarchyLevelExpansion, we should not expand the hierarchylevels\r\n (!suppressHierarchyLevelExpansion && SQExprHierarchyLevelConverter.expand(expr, schema)) ||\r\n expr;\r\n }\r\n\r\n export function isHierarchyOrVariation(schema: FederatedConceptualSchema, expr: SQExpr): boolean {\r\n if (expr instanceof SQHierarchyExpr || expr instanceof SQHierarchyLevelExpr)\r\n return true;\r\n\r\n let conceptualProperty = expr.getConceptualProperty(schema);\r\n if (conceptualProperty) {\r\n let column = conceptualProperty.column;\r\n if (column && column.variations && column.variations.length > 0)\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n // Return column reference expression for hierarchy level expression.\r\n export function getSourceVariationExpr(hierarchyLevelExpr: data.SQHierarchyLevelExpr): SQColumnRefExpr {\r\n let fieldExprPattern: data.FieldExprPattern = data.SQExprConverter.asFieldPattern(hierarchyLevelExpr);\r\n if (fieldExprPattern.columnHierarchyLevelVariation) {\r\n let entity: data.SQExpr = SQExprBuilder.entity(fieldExprPattern.columnHierarchyLevelVariation.source.schema, fieldExprPattern.columnHierarchyLevelVariation.source.entity);\r\n\r\n return SQExprBuilder.columnRef(entity, fieldExprPattern.columnHierarchyLevelVariation.source.name);\r\n }\r\n }\r\n\r\n // Return hierarchy expression for hierarchy level expression.\r\n export function getSourceHierarchy(hierarchyLevelExpr: data.SQHierarchyLevelExpr): SQHierarchyExpr {\r\n let fieldExprPattern: data.FieldExprPattern = data.SQExprConverter.asFieldPattern(hierarchyLevelExpr);\r\n let hierarchyLevel = fieldExprPattern.hierarchyLevel;\r\n if (hierarchyLevel) {\r\n let entity: data.SQExpr = SQExprBuilder.entity(hierarchyLevel.schema, hierarchyLevel.entity, hierarchyLevel.entityVar);\r\n return SQExprBuilder.hierarchy(entity, hierarchyLevel.name);\r\n }\r\n }\r\n\r\n export function getHierarchySourceAsVariationSource(hierarchyLevelExpr: SQHierarchyLevelExpr): SQPropertyVariationSourceExpr {\r\n\r\n // Make sure the hierarchy level source is a hierarchy\r\n if (!(hierarchyLevelExpr.arg instanceof SQHierarchyExpr))\r\n return;\r\n \r\n // Check if the hierarchy source if a variation\r\n let hierarchyRef = <SQHierarchyExpr>hierarchyLevelExpr.arg;\r\n if (hierarchyRef.arg instanceof SQPropertyVariationSourceExpr)\r\n return <SQPropertyVariationSourceExpr>hierarchyRef.arg;\r\n }\r\n\r\n /**\r\n * Returns true if firstExpr and secondExpr are levels in the same hierarchy and firstExpr is before secondExpr in allLevels.\r\n */\r\n export function areHierarchyLevelsOrdered(allLevels: SQHierarchyLevelExpr[], firstExpr: SQExpr, secondExpr: SQExpr): boolean {\r\n\r\n // Validate that both items hierarchy levels\r\n if (!(firstExpr instanceof SQHierarchyLevelExpr) || !(secondExpr instanceof SQHierarchyLevelExpr))\r\n return false;\r\n\r\n let firstLevel = <SQHierarchyLevelExpr>firstExpr;\r\n let secondLevel = <SQHierarchyLevelExpr>secondExpr;\r\n\r\n // Validate that both items belong to the same hierarchy\r\n if (!SQExpr.equals(firstLevel.arg, secondLevel.arg))\r\n return false;\r\n\r\n // Determine the order\r\n let firstIndex = SQExprUtils.indexOfExpr(allLevels, firstLevel);\r\n let secondIndex = SQExprUtils.indexOfExpr(allLevels, secondLevel);\r\n\r\n return firstIndex !== -1 && secondIndex !== -1 && firstIndex < secondIndex;\r\n }\r\n\r\n /**\r\n * Given an ordered set of levels and an ordered subset of those levels, returns the index where\r\n * expr should be inserted into the subset to maintain the correct order.\r\n */\r\n export function getInsertionIndex(allLevels: SQHierarchyLevelExpr[], orderedSubsetOfLevels: SQHierarchyLevelExpr[], expr: SQHierarchyLevelExpr): number {\r\n\r\n let insertIndex = 0;\r\n\r\n // Loop through the supplied levels until the insertion would no longer be in the correct order\r\n while (insertIndex < orderedSubsetOfLevels.length &&\r\n areHierarchyLevelsOrdered(allLevels, orderedSubsetOfLevels[insertIndex], expr)) {\r\n insertIndex++;\r\n }\r\n\r\n return insertIndex;\r\n }\r\n }\r\n\r\n export module SQExprHierarchyToHierarchyLevelConverter {\r\n export function convert(sqExpr: SQExpr, federatedSchema: FederatedConceptualSchema): SQExpr[] {\r\n debug.assertValue(sqExpr, 'sqExpr');\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n if (sqExpr instanceof SQHierarchyExpr) {\r\n let hierarchyExpr = <SQHierarchyExpr>sqExpr;\r\n\r\n let conceptualHierarchy = SQHierarchyExprUtils.getConceptualHierarchy(hierarchyExpr, federatedSchema);\r\n if (conceptualHierarchy)\r\n return _.map(conceptualHierarchy.levels, hierarchyLevel => SQExprBuilder.hierarchyLevel(sqExpr, hierarchyLevel.name));\r\n }\r\n }\r\n }\r\n\r\n module SQExprHierarchyLevelConverter {\r\n export function expand(expr: SQExpr, schema: FederatedConceptualSchema): SQExpr[] {\r\n debug.assertValue(expr, 'sqExpr');\r\n debug.assertValue(schema, 'federatedSchema');\r\n let exprs: SQExpr[] = [];\r\n\r\n if (expr instanceof SQHierarchyLevelExpr) {\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n if (fieldExpr.hierarchyLevel) {\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n let hierarchy = schema\r\n .schema(fieldExprItem.schema)\r\n .findHierarchy(fieldExprItem.entity, fieldExpr.hierarchyLevel.name);\r\n\r\n if (hierarchy) {\r\n let hierarchyLevels = hierarchy.levels;\r\n for (let hierarchyLevel of hierarchyLevels) {\r\n if (hierarchyLevel.name === fieldExpr.hierarchyLevel.level) {\r\n exprs.push(expr);\r\n break;\r\n }\r\n else\r\n exprs.push(\r\n SQExprBuilder.hierarchyLevel(\r\n SQExprBuilder.hierarchy(\r\n SQExprBuilder.entity(fieldExprItem.schema, fieldExprItem.entity, fieldExprItem.entityVar),\r\n hierarchy.name),\r\n hierarchyLevel.name)\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!_.isEmpty(exprs))\r\n return exprs;\r\n }\r\n }\r\n\r\n module SQExprVariationConverter {\r\n export function expand(expr: SQExpr, schema: FederatedConceptualSchema): SQExpr[] {\r\n debug.assertValue(expr, 'sqExpr');\r\n debug.assertValue(schema, 'federatedSchema');\r\n\r\n let exprs: SQExpr[];\r\n let conceptualProperty = expr.getConceptualProperty(schema);\r\n\r\n if (conceptualProperty) {\r\n let column = conceptualProperty.column;\r\n if (column && column.variations && column.variations.length > 0) {\r\n let variations = column.variations;\r\n\r\n // for SU11, we support only one variation\r\n debug.assert(variations.length === 1, \"variations.length\");\r\n let variation = variations[0];\r\n\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n\r\n exprs = [];\r\n if (variation.defaultHierarchy) {\r\n let hierarchyExpr = SQExprBuilder.hierarchy(\r\n SQExprBuilder.propertyVariationSource(\r\n SQExprBuilder.entity(fieldExprItem.schema, fieldExprItem.entity, fieldExprItem.entityVar),\r\n variation.name, conceptualProperty.name),\r\n variation.defaultHierarchy.name);\r\n\r\n for (let level of variation.defaultHierarchy.levels)\r\n exprs.push(SQExprBuilder.hierarchyLevel(hierarchyExpr, level.name));\r\n }\r\n }\r\n }\r\n\r\n return exprs;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n // A group can consist of either a single expression, or a collection of hierarchy expressions\r\n export interface SQExprGroup {\r\n expr: SQExpr;\r\n children: SQHierarchyLevelExpr[];\r\n\r\n /** Index of expression in the query. */\r\n selectQueryIndex: number;\r\n };\r\n\r\n export module SQExprGroupUtils {\r\n /** Group all projections. Eacch group can consist of either a single property, or a collection of hierarchy items. */\r\n export function groupExprs(schema: FederatedConceptualSchema, exprs: SQExpr[]): SQExprGroup[] {\r\n let groups: SQExprGroup[] = [];\r\n for (let i = 0, len = exprs.length; i < len; i++) {\r\n let expr = exprs[i];\r\n debug.assertValue(expr, \"Expression not found\");\r\n\r\n if (!(expr instanceof SQHierarchyLevelExpr)) {\r\n groups.push({ expr: expr, children: null, selectQueryIndex: i });\r\n }\r\n else {\r\n addChildToGroup(schema, groups, expr, i);\r\n }\r\n }\r\n\r\n return groups;\r\n }\r\n\r\n function addChildToGroup(\r\n schema: FederatedConceptualSchema,\r\n groups: SQExprGroup[],\r\n expr: SQHierarchyLevelExpr,\r\n selectQueryIndex: number): void {\r\n\r\n // shouldAddExpressionToNewGroup is used to control whether we should add the passed expr to \r\n // a new Group or to the last Group\r\n let shouldAddExpressionToNewGroup = true;\r\n let exprSource = SQHierarchyExprUtils.getSourceVariationExpr(expr) || SQHierarchyExprUtils.getSourceHierarchy(expr);\r\n let lastGroup = _.last(groups);\r\n\r\n // The relevant group is always the last added. If it has the same source hierarchy,\r\n // and is properly ordered within that hierarchy, we will need to add to this group.\r\n if (lastGroup && lastGroup.children && SQExpr.equals(lastGroup.expr, exprSource)) {\r\n let expandedExpr = SQHierarchyExprUtils.expandExpr(schema, expr.arg);\r\n if (expandedExpr instanceof Array) {\r\n let allHierarchyLevels = <SQHierarchyLevelExpr[]>expandedExpr;\r\n shouldAddExpressionToNewGroup = !SQHierarchyExprUtils.areHierarchyLevelsOrdered(allHierarchyLevels, _.last(lastGroup.children), expr);\r\n }\r\n }\r\n\r\n if (shouldAddExpressionToNewGroup)\r\n // Use the Sourcevariation as the expression for the group.\r\n groups.push({ expr: exprSource, children: [expr], selectQueryIndex: selectQueryIndex });\r\n else {\r\n debug.assertValue(lastGroup, 'There should be a group to add the variation to');\r\n debug.assertValue(lastGroup.children, 'The group should have children to add the variation to');\r\n lastGroup.children.push(expr);\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import StringExtensions = jsCommon.StringExtensions;\r\n\r\n /** Represents an immutable expression within a SemanticQuery. */\r\n export abstract class SQExpr implements ISQExpr {\r\n private _kind: SQExprKind;\r\n\r\n constructor(kind: SQExprKind) {\r\n debug.assertValue(kind, 'kind');\r\n\r\n this._kind = kind;\r\n }\r\n\r\n public static equals(x: SQExpr, y: SQExpr, ignoreCase?: boolean): boolean {\r\n return SQExprEqualityVisitor.run(x, y, ignoreCase);\r\n }\r\n\r\n public validate(schema: FederatedConceptualSchema, aggrUtils: ISQAggregationOperations, errors?: SQExprValidationError[]): SQExprValidationError[] {\r\n let validator = new SQExprValidationVisitor(schema, aggrUtils, errors);\r\n this.accept(validator);\r\n return validator.errors;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n debug.assertFail('abstract method');\r\n return;\r\n }\r\n\r\n public get kind(): SQExprKind {\r\n return this._kind;\r\n }\r\n\r\n public static isColumn(expr: SQExpr): expr is SQColumnRefExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.ColumnRef;\r\n }\r\n\r\n public static isConstant(expr: SQExpr): expr is SQConstantExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.Constant;\r\n }\r\n\r\n public static isEntity(expr: SQExpr): expr is SQEntityExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.Entity;\r\n }\r\n\r\n public static isHierarchy(expr: SQExpr): expr is SQHierarchyExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.Hierarchy;\r\n }\r\n\r\n public static isHierarchyLevel(expr: SQExpr): expr is SQHierarchyLevelExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.HierarchyLevel;\r\n }\r\n\r\n public static isAggregation(expr: SQExpr): expr is SQAggregationExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.Aggregation;\r\n }\r\n\r\n public static isMeasure(expr: SQExpr): expr is SQMeasureRefExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.MeasureRef;\r\n }\r\n\r\n public static isSelectRef(expr: SQExpr): expr is SQSelectRefExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.SelectRef;\r\n }\r\n\r\n public static isResourcePackageItem(expr: SQExpr): expr is SQResourcePackageItemExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.kind === SQExprKind.ResourcePackageItem;\r\n }\r\n\r\n public getMetadata(federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n let field = SQExprConverter.asFieldPattern(this);\r\n if (!field)\r\n return;\r\n\r\n if (field.column || field.columnAggr || field.measure)\r\n return this.getMetadataForProperty(field, federatedSchema);\r\n\r\n if (field.hierarchyLevel || field.hierarchyLevelAggr)\r\n return this.getMetadataForHierarchyLevel(field, federatedSchema);\r\n\r\n if (field.columnHierarchyLevelVariation)\r\n return this.getMetadataForVariation(field, federatedSchema);\r\n\r\n if (field.percentOfGrandTotal)\r\n return this.getMetadataForPercentOfGrandTotal();\r\n\r\n return SQExpr.getMetadataForEntity(field, federatedSchema);\r\n }\r\n\r\n public getDefaultAggregate(federatedSchema: FederatedConceptualSchema, forceAggregation: boolean = false): QueryAggregateFunction {\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n let property = this.getConceptualProperty(federatedSchema) || this.getHierarchyLevelConceptualProperty(federatedSchema);\r\n if (!property)\r\n return;\r\n\r\n let aggregate: QueryAggregateFunction;\r\n\r\n if (property && property.kind === ConceptualPropertyKind.Column) {\r\n let propertyDefaultAggregate = property.column ? property.column.defaultAggregate : null;\r\n\r\n if ((property.type.integer || property.type.numeric) &&\r\n propertyDefaultAggregate !== ConceptualDefaultAggregate.None) {\r\n aggregate = defaultAggregateToQueryAggregateFunction(propertyDefaultAggregate);\r\n if (aggregate === undefined)\r\n aggregate = defaultAggregateForDataType(property.type);\r\n }\r\n\r\n // If we haven't found an appropriate aggregate, and want to force aggregation anyway, \r\n // aggregate on CountNonNull.\r\n if (aggregate === undefined && forceAggregation) {\r\n aggregate = QueryAggregateFunction.CountNonNull;\r\n }\r\n }\r\n\r\n return aggregate;\r\n }\r\n\r\n /** Return the SQExpr[] of group on columns if it has group on keys otherwise return the SQExpr of the column.*/\r\n public getKeyColumns(schema: FederatedConceptualSchema): SQExpr[] {\r\n let columnRefExpr = SQExprColumnRefInfoVisitor.getColumnRefSQExpr(schema, this);\r\n if (!columnRefExpr)\r\n return;\r\n\r\n let keySQExprs: SQExpr[] = [];\r\n let keys = this.getPropertyKeys(schema);\r\n if (keys && keys.length > 0) {\r\n for (let i = 0, len = keys.length; i < len; i++) {\r\n keySQExprs.push(SQExprBuilder.columnRef(columnRefExpr.source, keys[i].name));\r\n }\r\n }\r\n else\r\n keySQExprs.push(columnRefExpr);\r\n\r\n return keySQExprs;\r\n }\r\n\r\n /** Returns a value indicating whether the expression would group on keys other than itself.*/\r\n public hasGroupOnKeys(schema: FederatedConceptualSchema): boolean {\r\n let columnRefExpr = SQExprColumnRefInfoVisitor.getColumnRefSQExpr(schema, this);\r\n if (!columnRefExpr)\r\n return;\r\n let keys = this.getPropertyKeys(schema);\r\n\r\n if (!keys || keys.length < 1)\r\n return false;\r\n\r\n if (keys.length > 1)\r\n return true;\r\n\r\n let keySqExpr = SQExprBuilder.columnRef(columnRefExpr.source, keys[0].name);\r\n return !SQExpr.equals(keySqExpr, this);\r\n }\r\n\r\n private getPropertyKeys(schema: FederatedConceptualSchema): jsCommon.ArrayNamedItems<ConceptualProperty> {\r\n let property = this.getConceptualProperty(schema) || this.getHierarchyLevelConceptualProperty(schema);\r\n if (!property)\r\n return;\r\n\r\n return property.column ? property.column.keys : undefined;\r\n }\r\n\r\n public getConceptualProperty(federatedSchema: FederatedConceptualSchema): ConceptualProperty {\r\n let field = SQExprConverter.asFieldPattern(this);\r\n if (!field)\r\n return;\r\n\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(field);\r\n let propertyName = FieldExprPattern.getPropertyName(field);\r\n\r\n if (propertyName)\r\n return federatedSchema\r\n .schema(fieldExprItem.schema)\r\n .findProperty(fieldExprItem.entity, propertyName);\r\n }\r\n\r\n public getTargetEntityForVariation(federatedSchema: FederatedConceptualSchema, variationName: string): string {\r\n let property = this.getConceptualProperty(federatedSchema);\r\n if (property && property.column && !_.isEmpty(property.column.variations)) {\r\n let variations = property.column.variations;\r\n for (let variation of variations)\r\n if (variation.name === variationName)\r\n return variation.navigationProperty.targetEntity.name;\r\n }\r\n }\r\n\r\n public getTargetEntity(federatedSchema: FederatedConceptualSchema): SQEntityExpr {\r\n return SQEntityExprInfoVisitor.getEntityExpr(federatedSchema, this);\r\n }\r\n\r\n private getHierarchyLevelConceptualProperty(federatedSchema: FederatedConceptualSchema): ConceptualProperty {\r\n let field = SQExprConverter.asFieldPattern(this);\r\n if (!field)\r\n return;\r\n\r\n let fieldExprHierachyLevel = field.hierarchyLevel || field.hierarchyLevelAggr;\r\n if (fieldExprHierachyLevel) {\r\n let fieldExprEntity = FieldExprPattern.toFieldExprEntityItemPattern(field);\r\n\r\n let hierarchy = federatedSchema\r\n .schema(fieldExprEntity.schema)\r\n .findHierarchy(fieldExprEntity.entity, fieldExprHierachyLevel.name);\r\n\r\n if (hierarchy) {\r\n let hierarchyLevel = hierarchy.levels.withName(fieldExprHierachyLevel.level);\r\n if (hierarchyLevel)\r\n return hierarchyLevel.column;\r\n }\r\n }\r\n }\r\n\r\n private getMetadataForVariation(field: data.FieldExprPattern, federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n debug.assertValue(field, 'field');\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n let columnHierarchyLevelVariation = field.columnHierarchyLevelVariation;\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(field);\r\n let sourceProperty = federatedSchema\r\n .schema(fieldExprItem.schema)\r\n .findProperty(fieldExprItem.entity, columnHierarchyLevelVariation.source.name);\r\n\r\n if (sourceProperty && sourceProperty.column && sourceProperty.column.variations) {\r\n for (let variation of sourceProperty.column.variations) {\r\n if (variation.defaultHierarchy && variation.defaultHierarchy.levels) {\r\n for (let level of variation.defaultHierarchy.levels) {\r\n if (level.name === columnHierarchyLevelVariation.level.level) {\r\n let property = level.column;\r\n return {\r\n kind: (property.kind === ConceptualPropertyKind.Measure) ? FieldKind.Measure : FieldKind.Column,\r\n type: property.type,\r\n format: property.format,\r\n idOnEntityKey: property.column ? property.column.idOnEntityKey : false,\r\n defaultAggregate: property.column ? property.column.defaultAggregate : null\r\n };\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n private getMetadataForHierarchyLevel(field: FieldExprPattern, federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n debug.assertValue(field, 'field');\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n let property = this.getHierarchyLevelConceptualProperty(federatedSchema);\r\n if (!property)\r\n return;\r\n\r\n return this.getPropertyMetadata(field, property);\r\n }\r\n\r\n private getMetadataForPercentOfGrandTotal(): SQExprMetadata {\r\n return {\r\n kind: FieldKind.Measure,\r\n format: '#,##0.##%',\r\n type: ValueType.fromExtendedType(ExtendedType.Double)\r\n };\r\n }\r\n\r\n private getPropertyMetadata(field: FieldExprPattern, property: ConceptualProperty): SQExprMetadata {\r\n let format = property.format;\r\n let type = property.type;\r\n let columnAggregate = field.columnAggr || field.hierarchyLevelAggr;\r\n\r\n if (columnAggregate) {\r\n switch (columnAggregate.aggregate) {\r\n case QueryAggregateFunction.Count:\r\n case QueryAggregateFunction.CountNonNull:\r\n type = ValueType.fromExtendedType(ExtendedType.Integer);\r\n format = undefined;\r\n break;\r\n case QueryAggregateFunction.Avg:\r\n if (type.integer)\r\n type = ValueType.fromExtendedType(ExtendedType.Double);\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n kind: (property.kind === ConceptualPropertyKind.Measure || (columnAggregate && columnAggregate.aggregate !== undefined)) ? FieldKind.Measure : FieldKind.Column,\r\n type: type,\r\n format: format,\r\n idOnEntityKey: property.column ? property.column.idOnEntityKey : false,\r\n aggregate: columnAggregate ? columnAggregate.aggregate : undefined,\r\n defaultAggregate: property.column ? property.column.defaultAggregate : null\r\n };\r\n }\r\n\r\n private getMetadataForProperty(field: FieldExprPattern, federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n debug.assertValue(field, 'field');\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n let property = this.getConceptualProperty(federatedSchema);\r\n if (!property)\r\n return;\r\n\r\n return this.getPropertyMetadata(field, property);\r\n }\r\n\r\n private static getMetadataForEntity(field: FieldExprPattern, federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n debug.assertValue(field, 'field');\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(field);\r\n let entity = federatedSchema\r\n .schema(fieldExprItem.schema)\r\n .entities\r\n .withName(fieldExprItem.entity);\r\n\r\n if (!entity)\r\n return;\r\n\r\n // We only support count and countnonnull for entity.\r\n if (field.entityAggr) {\r\n switch (field.entityAggr.aggregate) {\r\n case QueryAggregateFunction.Count:\r\n case QueryAggregateFunction.CountNonNull:\r\n return {\r\n kind: FieldKind.Measure,\r\n type: ValueType.fromExtendedType(ExtendedType.Integer),\r\n format: undefined,\r\n idOnEntityKey: false,\r\n aggregate: field.entityAggr.aggregate\r\n };\r\n }\r\n }\r\n }\r\n }\r\n\r\n export const enum SQExprKind {\r\n Entity,\r\n ColumnRef,\r\n MeasureRef,\r\n Aggregation,\r\n PropertyVariationSource,\r\n Hierarchy,\r\n HierarchyLevel,\r\n And,\r\n Between,\r\n In,\r\n Or,\r\n Contains,\r\n Compare,\r\n StartsWith,\r\n Exists,\r\n Not,\r\n Constant,\r\n DateSpan,\r\n DateAdd,\r\n Now,\r\n AnyValue,\r\n DefaultValue,\r\n Arithmetic,\r\n FillRule,\r\n ResourcePackageItem,\r\n ScopedEval,\r\n Scope,\r\n Percentile,\r\n SelectRef,\r\n }\r\n\r\n export interface SQExprMetadata {\r\n kind: FieldKind;\r\n type: ValueType;\r\n format?: string;\r\n idOnEntityKey?: boolean;\r\n aggregate?: QueryAggregateFunction;\r\n defaultAggregate?: ConceptualDefaultAggregate;\r\n }\r\n\r\n export const enum FieldKind {\r\n /** Indicates the field references a column, which evaluates to a distinct set of values (e.g., Year, Name, SalesQuantity, etc.). */\r\n Column,\r\n\r\n /** Indicates the field references a measure, which evaluates to a single value (e.g., SalesYTD, Sum(Sales), etc.). */\r\n Measure,\r\n }\r\n\r\n /** Note: Exported for testability */\r\n export function defaultAggregateForDataType(type: ValueType): QueryAggregateFunction {\r\n if (type.integer || type.numeric)\r\n return QueryAggregateFunction.Sum;\r\n\r\n return QueryAggregateFunction.Count;\r\n }\r\n\r\n /** Note: Exported for testability */\r\n export function defaultAggregateToQueryAggregateFunction(aggregate: ConceptualDefaultAggregate): QueryAggregateFunction {\r\n switch (aggregate) {\r\n case ConceptualDefaultAggregate.Average:\r\n return QueryAggregateFunction.Avg;\r\n case ConceptualDefaultAggregate.Count:\r\n return QueryAggregateFunction.CountNonNull;\r\n case ConceptualDefaultAggregate.DistinctCount:\r\n return QueryAggregateFunction.Count;\r\n case ConceptualDefaultAggregate.Max:\r\n return QueryAggregateFunction.Max;\r\n case ConceptualDefaultAggregate.Min:\r\n return QueryAggregateFunction.Min;\r\n case ConceptualDefaultAggregate.Sum:\r\n return QueryAggregateFunction.Sum;\r\n default:\r\n return;\r\n }\r\n }\r\n\r\n export class SQEntityExpr extends SQExpr {\r\n public schema: string;\r\n public entity: string;\r\n public variable: string;\r\n\r\n constructor(schema: string, entity: string, variable?: string) {\r\n debug.assertValue(entity, 'entity');\r\n\r\n super(SQExprKind.Entity);\r\n this.schema = schema;\r\n this.entity = entity;\r\n if (variable)\r\n this.variable = variable;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitEntity(this, arg);\r\n }\r\n }\r\n\r\n export class SQArithmeticExpr extends SQExpr {\r\n public left: SQExpr;\r\n public right: SQExpr;\r\n public operator: ArithmeticOperatorKind;\r\n\r\n constructor(left: SQExpr, right: SQExpr, operator: ArithmeticOperatorKind) {\r\n debug.assertValue(left, 'left');\r\n debug.assertValue(right, 'right');\r\n debug.assertValue(operator, 'operator');\r\n\r\n super(SQExprKind.Arithmetic);\r\n this.left = left;\r\n this.right = right;\r\n this.operator = operator;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitArithmetic(this, arg);\r\n }\r\n }\r\n\r\n export class SQScopedEvalExpr extends SQExpr {\r\n public expression: SQExpr;\r\n public scope: SQExpr[];\r\n\r\n constructor(expression: SQExpr, scope: SQExpr[]) {\r\n debug.assertValue(expression, 'expression');\r\n debug.assertValue(scope, 'scope');\r\n\r\n super(SQExprKind.ScopedEval);\r\n this.expression = expression;\r\n this.scope = scope;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitScopedEval(this, arg);\r\n }\r\n\r\n public getMetadata(federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n return this.expression.getMetadata(federatedSchema);\r\n }\r\n }\r\n\r\n export abstract class SQPropRefExpr extends SQExpr {\r\n public ref: string;\r\n public source: SQExpr;\r\n\r\n constructor(kind: SQExprKind, source: SQExpr, ref: string) {\r\n debug.assertValue(kind, 'kind');\r\n debug.assertValue(source, 'source');\r\n debug.assertValue(ref, 'ref');\r\n\r\n super(kind);\r\n this.source = source;\r\n this.ref = ref;\r\n }\r\n }\r\n\r\n export class SQColumnRefExpr extends SQPropRefExpr {\r\n constructor(source: SQExpr, ref: string) {\r\n super(SQExprKind.ColumnRef, source, ref);\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitColumnRef(this, arg);\r\n }\r\n }\r\n\r\n export class SQMeasureRefExpr extends SQPropRefExpr {\r\n constructor(source: SQExpr, ref: string) {\r\n super(SQExprKind.MeasureRef, source, ref);\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitMeasureRef(this, arg);\r\n }\r\n }\r\n\r\n export class SQAggregationExpr extends SQExpr {\r\n public arg: SQExpr;\r\n public func: QueryAggregateFunction;\r\n\r\n constructor(arg: SQExpr, func: QueryAggregateFunction) {\r\n debug.assertValue(arg, 'arg');\r\n debug.assertValue(func, 'func');\r\n\r\n super(SQExprKind.Aggregation);\r\n this.arg = arg;\r\n this.func = func;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitAggr(this, arg);\r\n }\r\n }\r\n\r\n export class SQPercentileExpr extends SQExpr {\r\n public arg: SQExpr;\r\n public k: number;\r\n public exclusive: boolean;\r\n\r\n constructor(arg: SQExpr, k: number, exclusive: boolean) {\r\n debug.assertValue(arg, 'arg');\r\n debug.assertValue(k, 'k');\r\n debug.assert(0 <= k && k <= 1, '0 <= k && k <= 1');\r\n debug.assertValue(exclusive, 'exclusive');\r\n\r\n super(SQExprKind.Percentile);\r\n this.arg = arg;\r\n this.k = k;\r\n this.exclusive = exclusive;\r\n }\r\n\r\n public getMetadata(federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n let argMetadata = this.arg.getMetadata(federatedSchema);\r\n if (argMetadata) {\r\n return {\r\n kind: FieldKind.Measure,\r\n type: argMetadata.type,\r\n };\r\n }\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitPercentile(this, arg);\r\n }\r\n }\r\n\r\n export class SQPropertyVariationSourceExpr extends SQExpr {\r\n public arg: SQExpr;\r\n public name: string;\r\n public property: string;\r\n\r\n constructor(arg: SQExpr, name: string, property: string) {\r\n debug.assertValue(arg, 'arg');\r\n debug.assertValue(name, 'name');\r\n debug.assertValue(property, 'property');\r\n\r\n super(SQExprKind.PropertyVariationSource);\r\n this.arg = arg;\r\n this.name = name;\r\n this.property = property;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitPropertyVariationSource(this, arg);\r\n }\r\n }\r\n\r\n export class SQHierarchyExpr extends SQExpr {\r\n public arg: SQExpr;\r\n public hierarchy: string;\r\n\r\n constructor(arg: SQExpr, hierarchy: string) {\r\n debug.assertValue(arg, 'arg');\r\n debug.assertValue(hierarchy, 'hierarchy');\r\n\r\n super(SQExprKind.Hierarchy);\r\n this.arg = arg;\r\n this.hierarchy = hierarchy;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitHierarchy(this, arg);\r\n }\r\n }\r\n\r\n export class SQHierarchyLevelExpr extends SQExpr {\r\n public arg: SQExpr;\r\n public level: string;\r\n\r\n constructor(arg: SQExpr, level: string) {\r\n debug.assertValue(arg, 'arg');\r\n debug.assertValue(level, 'level');\r\n\r\n super(SQExprKind.HierarchyLevel);\r\n this.arg = arg;\r\n this.level = level;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitHierarchyLevel(this, arg);\r\n }\r\n }\r\n\r\n export class SQSelectRefExpr extends SQExpr {\r\n public expressionName: string;\r\n\r\n constructor(expressionName: string) {\r\n debug.assertValue(expressionName, 'arg');\r\n\r\n super(SQExprKind.SelectRef);\r\n this.expressionName = expressionName;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitSelectRef(this, arg);\r\n }\r\n }\r\n\r\n export class SQAndExpr extends SQExpr {\r\n left: SQExpr;\r\n right: SQExpr;\r\n\r\n constructor(left: SQExpr, right: SQExpr) {\r\n debug.assertValue(left, 'left');\r\n debug.assertValue(right, 'right');\r\n\r\n super(SQExprKind.And);\r\n this.left = left;\r\n this.right = right;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitAnd(this, arg);\r\n }\r\n }\r\n\r\n export class SQBetweenExpr extends SQExpr {\r\n arg: SQExpr;\r\n lower: SQExpr;\r\n upper: SQExpr;\r\n\r\n constructor(arg: SQExpr, lower: SQExpr, upper: SQExpr) {\r\n debug.assertValue(arg, 'arg');\r\n debug.assertValue(lower, 'lower');\r\n debug.assertValue(upper, 'upper');\r\n\r\n super(SQExprKind.Between);\r\n this.arg = arg;\r\n this.lower = lower;\r\n this.upper = upper;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitBetween(this, arg);\r\n }\r\n }\r\n\r\n export class SQInExpr extends SQExpr {\r\n args: SQExpr[];\r\n values: SQExpr[][];\r\n\r\n constructor(args: SQExpr[], values: SQExpr[][]) {\r\n debug.assertValue(args, 'args');\r\n debug.assertValue(values, 'values');\r\n\r\n super(SQExprKind.In);\r\n this.args = args;\r\n this.values = values;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitIn(this, arg);\r\n }\r\n }\r\n\r\n export class SQOrExpr extends SQExpr {\r\n left: SQExpr;\r\n right: SQExpr;\r\n\r\n constructor(left: SQExpr, right: SQExpr) {\r\n debug.assertValue(left, 'left');\r\n debug.assertValue(right, 'right');\r\n\r\n super(SQExprKind.Or);\r\n this.left = left;\r\n this.right = right;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitOr(this, arg);\r\n }\r\n }\r\n\r\n export class SQCompareExpr extends SQExpr {\r\n comparison: QueryComparisonKind;\r\n left: SQExpr;\r\n right: SQExpr;\r\n\r\n constructor(comparison: QueryComparisonKind, left: SQExpr, right: SQExpr) {\r\n debug.assertValue(comparison, 'kind');\r\n debug.assertValue(left, 'left');\r\n debug.assertValue(right, 'right');\r\n\r\n super(SQExprKind.Compare);\r\n this.comparison = comparison;\r\n this.left = left;\r\n this.right = right;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitCompare(this, arg);\r\n }\r\n }\r\n\r\n export class SQContainsExpr extends SQExpr {\r\n left: SQExpr;\r\n right: SQExpr;\r\n\r\n constructor(left: SQExpr, right: SQExpr) {\r\n debug.assertValue(left, 'left');\r\n debug.assertValue(right, 'right');\r\n\r\n super(SQExprKind.Contains);\r\n this.left = left;\r\n this.right = right;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitContains(this, arg);\r\n }\r\n }\r\n\r\n export class SQStartsWithExpr extends SQExpr {\r\n left: SQExpr;\r\n right: SQExpr;\r\n\r\n constructor(left: SQExpr, right: SQExpr) {\r\n debug.assertValue(left, 'left');\r\n debug.assertValue(right, 'right');\r\n\r\n super(SQExprKind.StartsWith);\r\n this.left = left;\r\n this.right = right;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitStartsWith(this, arg);\r\n }\r\n }\r\n\r\n export class SQExistsExpr extends SQExpr {\r\n arg: SQExpr;\r\n\r\n constructor(arg: SQExpr) {\r\n debug.assertValue(arg, 'arg');\r\n\r\n super(SQExprKind.Exists);\r\n this.arg = arg;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitExists(this, arg);\r\n }\r\n }\r\n\r\n export class SQNotExpr extends SQExpr {\r\n arg: SQExpr;\r\n\r\n constructor(arg: SQExpr) {\r\n debug.assertValue(arg, 'arg');\r\n\r\n super(SQExprKind.Not);\r\n this.arg = arg;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitNot(this, arg);\r\n }\r\n }\r\n\r\n export class SQConstantExpr extends SQExpr implements ISQConstantExpr {\r\n public type: ValueType;\r\n\r\n /** The native JavaScript representation of the value. */\r\n public value: any;\r\n\r\n /** The string encoded, lossless representation of the value. */\r\n public valueEncoded: string;\r\n\r\n constructor(type: ValueType, value: any, valueEncoded: string) {\r\n debug.assertValue(type, 'type');\r\n\r\n super(SQExprKind.Constant);\r\n this.type = type;\r\n this.value = value;\r\n this.valueEncoded = valueEncoded;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitConstant(this, arg);\r\n }\r\n\r\n public getMetadata(federatedSchema: FederatedConceptualSchema): SQExprMetadata {\r\n debug.assertValue(federatedSchema, 'federatedSchema');\r\n\r\n return {\r\n // Returning Measure as the kind for a SQConstantExpr is slightly ambiguous allowing the return object to conform to SQEXprMetadata.\r\n // A getType or similiar function in the future would be more appropriate. \r\n kind: FieldKind.Measure,\r\n type: this.type,\r\n };\r\n }\r\n }\r\n\r\n export class SQDateSpanExpr extends SQExpr {\r\n public unit: TimeUnit;\r\n public arg: SQExpr;\r\n\r\n constructor(unit: TimeUnit, arg: SQExpr) {\r\n debug.assertValue(unit, 'unit');\r\n debug.assertValue(arg, 'arg');\r\n\r\n super(SQExprKind.DateSpan);\r\n this.unit = unit;\r\n this.arg = arg;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitDateSpan(this, arg);\r\n }\r\n }\r\n\r\n export class SQDateAddExpr extends SQExpr {\r\n public unit: TimeUnit;\r\n public amount: number;\r\n public arg: SQExpr;\r\n\r\n constructor(unit: TimeUnit, amount: number, arg: SQExpr) {\r\n debug.assertValue(unit, 'unit');\r\n debug.assertValue(amount, 'amount');\r\n debug.assertValue(arg, 'arg');\r\n\r\n super(SQExprKind.DateAdd);\r\n this.unit = unit;\r\n this.arg = arg;\r\n this.amount = amount;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitDateAdd(this, arg);\r\n }\r\n }\r\n\r\n export class SQNowExpr extends SQExpr {\r\n constructor() {\r\n super(SQExprKind.Now);\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitNow(this, arg);\r\n }\r\n }\r\n\r\n export class SQDefaultValueExpr extends SQExpr {\r\n constructor() {\r\n super(SQExprKind.DefaultValue);\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitDefaultValue(this, arg);\r\n }\r\n }\r\n\r\n export class SQAnyValueExpr extends SQExpr {\r\n constructor() {\r\n super(SQExprKind.AnyValue);\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitAnyValue(this, arg);\r\n }\r\n }\r\n\r\n export class SQFillRuleExpr extends SQExpr {\r\n public input: SQExpr;\r\n public rule: FillRuleDefinition;\r\n\r\n constructor(\r\n input: SQExpr,\r\n fillRule: FillRuleDefinition) {\r\n debug.assertValue(input, 'input');\r\n debug.assertValue(fillRule, 'fillRule');\r\n\r\n super(SQExprKind.FillRule);\r\n this.input = input;\r\n this.rule = fillRule;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitFillRule(this, arg);\r\n }\r\n }\r\n\r\n export class SQResourcePackageItemExpr extends SQExpr {\r\n public packageName: string;\r\n public packageType: number;\r\n public itemName: string;\r\n\r\n constructor(packageName: string, packageType: number, itemName: string) {\r\n debug.assertValue(packageName, 'packageName');\r\n debug.assertValue(itemName, 'itemName');\r\n\r\n super(SQExprKind.ResourcePackageItem);\r\n this.packageName = packageName;\r\n this.packageType = packageType;\r\n this.itemName = itemName;\r\n }\r\n\r\n public accept<T, TArg>(visitor: ISQExprVisitorWithArg<T, TArg>, arg?: TArg): T {\r\n return visitor.visitResourcePackageItem(this, arg);\r\n }\r\n }\r\n\r\n /** Provides utilities for creating & manipulating expressions. */\r\n export module SQExprBuilder {\r\n export function entity(schema: string, entity: string, variable?: string): SQEntityExpr {\r\n return new SQEntityExpr(schema, entity, variable);\r\n }\r\n\r\n export function columnRef(source: SQExpr, prop: string): SQColumnRefExpr {\r\n return new SQColumnRefExpr(source, prop);\r\n }\r\n\r\n export function measureRef(source: SQExpr, prop: string): SQMeasureRefExpr {\r\n return new SQMeasureRefExpr(source, prop);\r\n }\r\n\r\n export function aggregate(source: SQExpr, aggregate: QueryAggregateFunction): SQAggregationExpr {\r\n return new SQAggregationExpr(source, aggregate);\r\n }\r\n\r\n export function selectRef(expressionName: string): SQSelectRefExpr {\r\n return new SQSelectRefExpr(expressionName);\r\n }\r\n\r\n export function percentile(source: SQExpr, k: number, exclusive: boolean): SQPercentileExpr {\r\n return new SQPercentileExpr(source, k, exclusive);\r\n }\r\n\r\n export function arithmetic(left: SQExpr, right: SQExpr, operator: ArithmeticOperatorKind): SQArithmeticExpr {\r\n return new SQArithmeticExpr(left, right, operator);\r\n }\r\n\r\n export function scopedEval(expression: SQExpr, scope: SQExpr[]): SQScopedEvalExpr {\r\n return new SQScopedEvalExpr(expression, scope);\r\n }\r\n\r\n export function hierarchy(source: SQExpr, hierarchy: string): SQHierarchyExpr {\r\n return new SQHierarchyExpr(source, hierarchy);\r\n }\r\n\r\n export function propertyVariationSource(source: SQExpr, name: string, property: string): SQPropertyVariationSourceExpr {\r\n return new SQPropertyVariationSourceExpr(source, name, property);\r\n }\r\n\r\n export function hierarchyLevel(source: SQExpr, level: string): SQHierarchyLevelExpr {\r\n return new SQHierarchyLevelExpr(source, level);\r\n }\r\n\r\n export function and(left: SQExpr, right: SQExpr): SQExpr {\r\n if (!left)\r\n return right;\r\n if (!right)\r\n return left;\r\n\r\n return new SQAndExpr(left, right);\r\n }\r\n\r\n export function between(arg: SQExpr, lower: SQExpr, upper: SQExpr): SQBetweenExpr {\r\n return new SQBetweenExpr(arg, lower, upper);\r\n }\r\n\r\n export function inExpr(args: SQExpr[], values: SQExpr[][]): SQInExpr {\r\n return new SQInExpr(args, values);\r\n }\r\n\r\n export function or(left: SQExpr, right: SQExpr): SQExpr {\r\n if (!left)\r\n return right;\r\n if (!right)\r\n return left;\r\n if (left instanceof SQInExpr && right instanceof SQInExpr) {\r\n let inExpr = tryUseInExprs(<SQInExpr>left, <SQInExpr>right);\r\n if (inExpr)\r\n return inExpr;\r\n }\r\n\r\n return new SQOrExpr(left, right);\r\n }\r\n\r\n function tryUseInExprs(left: SQInExpr, right: SQInExpr): SQInExpr {\r\n if (!left.args || !right.args)\r\n return;\r\n\r\n let leftArgLen = left.args.length;\r\n let rightArgLen = right.args.length;\r\n if (leftArgLen !== rightArgLen)\r\n return;\r\n\r\n for (let i = 0; i < leftArgLen; ++i) {\r\n if (!SQExpr.equals(left.args[i], right.args[i]))\r\n return;\r\n }\r\n\r\n let combinedValues = left.values.concat(right.values);\r\n return SQExprBuilder.inExpr(left.args, combinedValues);\r\n }\r\n\r\n export function compare(kind: QueryComparisonKind, left: SQExpr, right: SQExpr): SQCompareExpr {\r\n return new SQCompareExpr(kind, left, right);\r\n }\r\n\r\n export function contains(left: SQExpr, right: SQExpr): SQContainsExpr {\r\n return new SQContainsExpr(left, right);\r\n }\r\n\r\n export function exists(arg: SQExpr): SQExistsExpr {\r\n return new SQExistsExpr(arg);\r\n }\r\n\r\n export function equal(left: SQExpr, right: SQExpr): SQCompareExpr {\r\n return compare(QueryComparisonKind.Equal, left, right);\r\n }\r\n\r\n export function not(arg: SQExpr): SQNotExpr {\r\n return new SQNotExpr(arg);\r\n }\r\n\r\n export function startsWith(left: SQExpr, right: SQExpr): SQStartsWithExpr {\r\n return new SQStartsWithExpr(left, right);\r\n }\r\n\r\n export function nullConstant(): SQConstantExpr {\r\n return new SQConstantExpr(\r\n ValueType.fromExtendedType(ExtendedType.Null),\r\n null,\r\n PrimitiveValueEncoding.nullEncoding());\r\n }\r\n\r\n export function now(): SQNowExpr {\r\n return new SQNowExpr();\r\n }\r\n\r\n export function defaultValue(): SQDefaultValueExpr {\r\n return new SQDefaultValueExpr();\r\n }\r\n\r\n export function anyValue(): SQAnyValueExpr {\r\n return new SQAnyValueExpr();\r\n }\r\n\r\n export function boolean(value: boolean): SQConstantExpr {\r\n return new SQConstantExpr(\r\n ValueType.fromExtendedType(ExtendedType.Boolean),\r\n value,\r\n PrimitiveValueEncoding.boolean(value));\r\n }\r\n\r\n export function dateAdd(unit: TimeUnit, amount: number, arg: SQExpr): SQDateAddExpr {\r\n return new SQDateAddExpr(unit, amount, arg);\r\n }\r\n\r\n export function dateTime(value: Date, valueEncoded?: string): SQConstantExpr {\r\n if (valueEncoded === undefined)\r\n valueEncoded = PrimitiveValueEncoding.dateTime(value);\r\n\r\n return new SQConstantExpr(ValueType.fromExtendedType(ExtendedType.DateTime), value, valueEncoded);\r\n }\r\n\r\n export function dateSpan(unit: TimeUnit, arg: SQExpr): SQDateSpanExpr {\r\n return new SQDateSpanExpr(unit, arg);\r\n }\r\n\r\n export function decimal(value: number, valueEncoded?: string): SQConstantExpr {\r\n if (valueEncoded === undefined)\r\n valueEncoded = PrimitiveValueEncoding.decimal(value);\r\n\r\n return new SQConstantExpr(ValueType.fromExtendedType(ExtendedType.Decimal), value, valueEncoded);\r\n }\r\n\r\n export function double(value: number, valueEncoded?: string): SQConstantExpr {\r\n if (valueEncoded === undefined)\r\n valueEncoded = PrimitiveValueEncoding.double(value);\r\n\r\n return new SQConstantExpr(ValueType.fromExtendedType(ExtendedType.Double), value, valueEncoded);\r\n }\r\n\r\n export function integer(value: number, valueEncoded?: string): SQConstantExpr {\r\n if (valueEncoded === undefined)\r\n valueEncoded = PrimitiveValueEncoding.integer(value);\r\n\r\n return new SQConstantExpr(ValueType.fromExtendedType(ExtendedType.Integer), value, valueEncoded);\r\n }\r\n\r\n export function text(value: string, valueEncoded?: string): SQConstantExpr {\r\n debug.assert(!valueEncoded || valueEncoded === PrimitiveValueEncoding.text(value), 'Incorrect encoded value specified.');\r\n\r\n return new SQConstantExpr(\r\n ValueType.fromExtendedType(ExtendedType.Text),\r\n value,\r\n valueEncoded || PrimitiveValueEncoding.text(value));\r\n }\r\n\r\n /** Returns an SQExpr that evaluates to the constant value. */\r\n export function typedConstant(value: PrimitiveValue, type: ValueTypeDescriptor): SQConstantExpr {\r\n if (value == null)\r\n return nullConstant();\r\n\r\n if (_.isBoolean(value)) {\r\n return boolean(<boolean>value);\r\n }\r\n\r\n if (_.isString(value)) {\r\n return text(<string>value);\r\n }\r\n\r\n if (_.isNumber(value)) {\r\n if (type.integer && Double.isInteger(<number>value))\r\n return integer(<number>value);\r\n\r\n return double(<number>value);\r\n }\r\n\r\n if (value instanceof Date) {\r\n return dateTime(value);\r\n }\r\n }\r\n\r\n export function setAggregate(expr: SQExpr, aggregate: QueryAggregateFunction): SQExpr {\r\n return FieldExprChangeAggregateRewriter.rewrite(expr, aggregate);\r\n }\r\n\r\n export function removeAggregate(expr: SQExpr): SQExpr {\r\n return FieldExprRemoveAggregateRewriter.rewrite(expr);\r\n }\r\n\r\n export function setPercentOfGrandTotal(expr: SQExpr): SQExpr {\r\n return SQExprSetPercentOfGrandTotalRewriter.rewrite(expr);\r\n }\r\n\r\n export function removePercentOfGrandTotal(expr: SQExpr): SQExpr {\r\n return SQExprRemovePercentOfGrandTotalRewriter.rewrite(expr);\r\n }\r\n\r\n export function removeEntityVariables(expr: SQExpr): SQExpr {\r\n return SQExprRemoveEntityVariablesRewriter.rewrite(expr);\r\n }\r\n\r\n export function fillRule(expr: SQExpr, rule: FillRuleDefinition): SQFillRuleExpr {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(rule, 'rule');\r\n\r\n return new SQFillRuleExpr(expr, rule);\r\n }\r\n\r\n export function resourcePackageItem(packageName: string, packageType: number, itemName: string): SQResourcePackageItemExpr {\r\n return new SQResourcePackageItemExpr(packageName, packageType, itemName);\r\n }\r\n }\r\n\r\n /** Provides utilities for obtaining information about expressions. */\r\n export module SQExprInfo {\r\n export function getAggregate(expr: SQExpr): QueryAggregateFunction {\r\n return SQExprAggregateInfoVisitor.getAggregate(expr);\r\n }\r\n }\r\n\r\n class SQExprEqualityVisitor implements ISQExprVisitorWithArg<boolean, SQExpr>, IFillRuleDefinitionVisitor<boolean, boolean> {\r\n private static instance: SQExprEqualityVisitor = new SQExprEqualityVisitor(/* ignoreCase */ false);\r\n private static ignoreCaseInstance: SQExprEqualityVisitor = new SQExprEqualityVisitor(true);\r\n private ignoreCase: boolean;\r\n\r\n public static run(x: SQExpr, y: SQExpr, ignoreCase?: boolean): boolean {\r\n // Normalize falsy to null\r\n x = x || null;\r\n y = y || null;\r\n\r\n if (x === y)\r\n return true;\r\n\r\n if (!x !== !y)\r\n return false;\r\n\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n if (ignoreCase)\r\n return x.accept(SQExprEqualityVisitor.ignoreCaseInstance, y);\r\n\r\n return x.accept(SQExprEqualityVisitor.instance, y);\r\n }\r\n\r\n constructor(ignoreCase: boolean) {\r\n this.ignoreCase = ignoreCase;\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr, comparand: SQColumnRefExpr): boolean {\r\n return comparand instanceof SQColumnRefExpr &&\r\n expr.ref === (<SQColumnRefExpr>comparand).ref &&\r\n this.equals(expr.source, (<SQColumnRefExpr>comparand).source);\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr, comparand: SQMeasureRefExpr): boolean {\r\n return comparand instanceof SQMeasureRefExpr &&\r\n expr.ref === (<SQMeasureRefExpr>comparand).ref &&\r\n this.equals(expr.source, (<SQMeasureRefExpr>comparand).source);\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQAggregationExpr &&\r\n expr.func === (<SQAggregationExpr>comparand).func &&\r\n this.equals(expr.arg, (<SQAggregationExpr>comparand).arg);\r\n }\r\n\r\n public visitPercentile(expr: SQPercentileExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQPercentileExpr &&\r\n expr.exclusive === comparand.exclusive &&\r\n expr.k === comparand.k &&\r\n this.equals(expr.arg, comparand.arg);\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr, comparand: SQHierarchyExpr): boolean {\r\n return comparand instanceof SQHierarchyExpr &&\r\n expr.hierarchy === comparand.hierarchy &&\r\n this.equals(expr.arg, comparand.arg);\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr, comparand: SQHierarchyLevelExpr): boolean {\r\n return comparand instanceof SQHierarchyLevelExpr &&\r\n expr.level === comparand.level &&\r\n this.equals(expr.arg, comparand.arg);\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr, comparand: SQPropertyVariationSourceExpr): boolean {\r\n return comparand instanceof SQPropertyVariationSourceExpr &&\r\n expr.name === comparand.name &&\r\n expr.property === comparand.property &&\r\n this.equals(expr.arg, comparand.arg);\r\n }\r\n\r\n public visitSelectRef(expr: SQSelectRefExpr, comparand: SQSelectRefExpr): boolean {\r\n return comparand instanceof SQSelectRefExpr &&\r\n expr.expressionName === comparand.expressionName;\r\n }\r\n\r\n public visitBetween(expr: SQBetweenExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQBetweenExpr &&\r\n this.equals(expr.arg, (<SQBetweenExpr>comparand).arg) &&\r\n this.equals(expr.lower, (<SQBetweenExpr>comparand).lower) &&\r\n this.equals(expr.upper, (<SQBetweenExpr>comparand).upper);\r\n }\r\n\r\n public visitIn(expr: SQInExpr, comparand: SQExpr): boolean {\r\n if (!(comparand instanceof SQInExpr) || !this.equalsAll(expr.args, (<SQInExpr>comparand).args))\r\n return false;\r\n\r\n let values = expr.values,\r\n compareValues = (<SQInExpr>comparand).values;\r\n if (values.length !== compareValues.length)\r\n return false;\r\n\r\n for (let i = 0, len = values.length; i < len; i++) {\r\n if (!this.equalsAll(values[i], compareValues[i]))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQEntityExpr &&\r\n expr.schema === (<SQEntityExpr>comparand).schema &&\r\n expr.entity === (<SQEntityExpr>comparand).entity &&\r\n this.optionalEqual(expr.variable, (<SQEntityExpr>comparand).variable);\r\n }\r\n\r\n public visitAnd(expr: SQAndExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQAndExpr &&\r\n this.equals(expr.left, (<SQAndExpr>comparand).left) &&\r\n this.equals(expr.right, (<SQAndExpr>comparand).right);\r\n }\r\n\r\n public visitOr(expr: SQOrExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQOrExpr &&\r\n this.equals(expr.left, (<SQOrExpr>comparand).left) &&\r\n this.equals(expr.right, (<SQOrExpr>comparand).right);\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQCompareExpr &&\r\n expr.comparison === (<SQCompareExpr>comparand).comparison &&\r\n this.equals(expr.left, (<SQCompareExpr>comparand).left) &&\r\n this.equals(expr.right, (<SQCompareExpr>comparand).right);\r\n }\r\n\r\n public visitContains(expr: SQContainsExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQContainsExpr &&\r\n this.equals(expr.left, (<SQContainsExpr>comparand).left) &&\r\n this.equals(expr.right, (<SQContainsExpr>comparand).right);\r\n }\r\n\r\n public visitDateSpan(expr: SQDateSpanExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQDateSpanExpr &&\r\n expr.unit === (<SQDateSpanExpr>comparand).unit &&\r\n this.equals(expr.arg, (<SQDateSpanExpr>comparand).arg);\r\n }\r\n\r\n public visitDateAdd(expr: SQDateAddExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQDateAddExpr &&\r\n expr.unit === (<SQDateAddExpr>comparand).unit &&\r\n expr.amount === (<SQDateAddExpr>comparand).amount &&\r\n this.equals(expr.arg, (<SQDateAddExpr>comparand).arg);\r\n }\r\n\r\n public visitExists(expr: SQExistsExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQExistsExpr &&\r\n this.equals(expr.arg, (<SQExistsExpr>comparand).arg);\r\n }\r\n\r\n public visitNot(expr: SQNotExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQNotExpr &&\r\n this.equals(expr.arg, (<SQNotExpr>comparand).arg);\r\n }\r\n\r\n public visitNow(expr: SQNowExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQNowExpr;\r\n }\r\n\r\n public visitDefaultValue(expr: SQDefaultValueExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQDefaultValueExpr;\r\n }\r\n\r\n public visitAnyValue(expr: SQAnyValueExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQAnyValueExpr;\r\n }\r\n\r\n public visitResourcePackageItem(expr: SQResourcePackageItemExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQResourcePackageItemExpr &&\r\n expr.packageName === comparand.packageName &&\r\n expr.packageType === comparand.packageType &&\r\n expr.itemName === comparand.itemName;\r\n }\r\n\r\n public visitStartsWith(expr: SQStartsWithExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQStartsWithExpr &&\r\n this.equals(expr.left, (<SQStartsWithExpr>comparand).left) &&\r\n this.equals(expr.right, (<SQStartsWithExpr>comparand).right);\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr, comparand: SQExpr): boolean {\r\n if (comparand instanceof SQConstantExpr && expr.type === (<SQConstantExpr>comparand).type)\r\n return expr.type.text && this.ignoreCase ?\r\n StringExtensions.equalIgnoreCase(expr.valueEncoded, (<SQConstantExpr>comparand).valueEncoded) :\r\n expr.valueEncoded === (<SQConstantExpr>comparand).valueEncoded;\r\n\r\n return false;\r\n }\r\n\r\n public visitFillRule(expr: SQFillRuleExpr, comparand: SQExpr): boolean {\r\n if (comparand instanceof SQFillRuleExpr && this.equals(expr.input, comparand.input)) {\r\n let leftRule = expr.rule,\r\n rightRule = comparand.rule;\r\n\r\n if (leftRule === rightRule)\r\n return true;\r\n\r\n let leftLinearGradient2 = leftRule.linearGradient2,\r\n rightLinearGradient2 = rightRule.linearGradient2;\r\n if (leftLinearGradient2 && rightLinearGradient2) {\r\n return this.visitLinearGradient2(leftLinearGradient2, rightLinearGradient2);\r\n }\r\n\r\n let leftLinearGradient3 = leftRule.linearGradient3,\r\n rightLinearGradient3 = rightRule.linearGradient3;\r\n if (leftLinearGradient3 && rightLinearGradient3) {\r\n return this.visitLinearGradient3(leftLinearGradient3, rightLinearGradient3);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n public visitLinearGradient2(left2: LinearGradient2Definition, right2: LinearGradient2Definition): boolean {\r\n debug.assertValue(left2, 'left2');\r\n debug.assertValue(right2, 'right2');\r\n\r\n return this.equalsFillRuleStop(left2.min, right2.min) &&\r\n this.equalsFillRuleStop(left2.max, right2.max);\r\n }\r\n\r\n public visitLinearGradient3(left3: LinearGradient3Definition, right3: LinearGradient3Definition): boolean {\r\n debug.assertValue(left3, 'left3');\r\n debug.assertValue(right3, 'right3');\r\n\r\n return this.equalsFillRuleStop(left3.min, right3.min) &&\r\n this.equalsFillRuleStop(left3.mid, right3.mid) &&\r\n this.equalsFillRuleStop(left3.max, right3.max);\r\n }\r\n\r\n private equalsFillRuleStop(stop1: RuleColorStopDefinition, stop2: RuleColorStopDefinition): boolean {\r\n debug.assertValue(stop1, 'stop1');\r\n debug.assertValue(stop2, 'stop2');\r\n\r\n if (!this.equals(stop1.color, stop2.color))\r\n return false;\r\n\r\n if (!stop1.value)\r\n return stop1.value === stop2.value;\r\n\r\n return this.equals(stop1.value, stop2.value);\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQArithmeticExpr &&\r\n expr.operator === (<SQArithmeticExpr>comparand).operator &&\r\n this.equals(expr.left, (<SQArithmeticExpr>comparand).left) &&\r\n this.equals(expr.right, (<SQArithmeticExpr>comparand).right);\r\n }\r\n\r\n public visitScopedEval(expr: SQScopedEvalExpr, comparand: SQExpr): boolean {\r\n return comparand instanceof SQScopedEvalExpr &&\r\n this.equals(expr.expression, comparand.expression) &&\r\n this.equalsAll(expr.scope, comparand.scope);\r\n }\r\n\r\n private optionalEqual(x: string, y: string) {\r\n // Only check equality if both values are specified.\r\n if (x && y)\r\n return x === y;\r\n\r\n return true;\r\n }\r\n\r\n private equals(x: SQExpr, y: SQExpr): boolean {\r\n return x.accept(this, y);\r\n }\r\n\r\n private equalsAll(x: SQExpr[], y: SQExpr[]): boolean {\r\n let len = x.length;\r\n if (len !== y.length)\r\n return false;\r\n\r\n for (let i = 0; i < len; i++) {\r\n if (!this.equals(x[i], y[i]))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n }\r\n\r\n /** Rewrites a root-level expression. */\r\n class SQExprRootRewriter extends DefaultSQExprVisitor<SQExpr> {\r\n public visitDefault(expr: SQExpr): SQExpr {\r\n return expr;\r\n }\r\n }\r\n\r\n export const enum SQExprValidationError {\r\n invalidAggregateFunction,\r\n invalidSchemaReference,\r\n invalidEntityReference,\r\n invalidColumnReference,\r\n invalidMeasureReference,\r\n invalidHierarchyReference,\r\n invalidHierarchyLevelReference,\r\n invalidLeftOperandType,\r\n invalidRightOperandType,\r\n invalidValueType,\r\n invalidPercentileArgument,\r\n }\r\n\r\n export class SQExprValidationVisitor extends SQExprRewriter {\r\n public errors: SQExprValidationError[];\r\n private schema: FederatedConceptualSchema;\r\n private aggrUtils: ISQAggregationOperations;\r\n\r\n constructor(schema: FederatedConceptualSchema, aggrUtils: ISQAggregationOperations, errors?: SQExprValidationError[]) {\r\n debug.assertValue(schema, 'schema');\r\n debug.assertValue(aggrUtils, 'aggrUtils');\r\n\r\n super();\r\n this.schema = schema;\r\n this.aggrUtils = aggrUtils;\r\n if (errors)\r\n this.errors = errors;\r\n }\r\n\r\n public visitIn(expr: SQInExpr): SQExpr {\r\n let inExpr = <SQInExpr>super.visitIn(expr);\r\n let args = inExpr.args;\r\n let values = inExpr.values;\r\n for (let valueTuple of values) {\r\n debug.assert(valueTuple.length === args.length, 'args and value tuple are not the same length');\r\n for (let i = 0, len = valueTuple.length; i < len; ++i)\r\n this.validateCompatibleType(args[i], valueTuple[i]);\r\n }\r\n\r\n return inExpr;\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr): SQExpr {\r\n let compareExpr = <SQCompareExpr>super.visitCompare(expr);\r\n this.validateCompatibleType(compareExpr.left, compareExpr.right);\r\n\r\n return compareExpr;\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): SQExpr {\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n if (fieldExpr) {\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n let entity = this.validateEntity(fieldExprItem.schema, fieldExprItem.entity);\r\n if (entity) {\r\n let prop = entity.properties.withName(fieldExpr.column.name);\r\n if (!prop ||\r\n prop.kind !== ConceptualPropertyKind.Column ||\r\n !this.isQueryable(fieldExpr))\r\n this.register(SQExprValidationError.invalidColumnReference);\r\n }\r\n }\r\n return expr;\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr): SQExpr {\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n if (fieldExpr) {\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n let entity = this.validateEntity(fieldExprItem.schema, fieldExprItem.entity);\r\n if (entity) {\r\n let prop = entity.properties.withName(fieldExpr.measure.name);\r\n if (!prop ||\r\n prop.kind !== ConceptualPropertyKind.Measure ||\r\n !this.isQueryable(fieldExpr))\r\n this.register(SQExprValidationError.invalidMeasureReference);\r\n }\r\n }\r\n return expr;\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): SQExpr {\r\n let aggregateExpr = <SQAggregationExpr>super.visitAggr(expr);\r\n\r\n let columnRefExpr = SQExprColumnRefInfoVisitor.getColumnRefSQExpr(this.schema, aggregateExpr.arg);\r\n if (columnRefExpr) {\r\n if (!this.aggrUtils.isSupportedAggregate(expr, this.schema, expr.func, /*targetTypes*/null))\r\n this.register(SQExprValidationError.invalidAggregateFunction);\r\n }\r\n\r\n return aggregateExpr;\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): SQExpr {\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n if (fieldExpr) {\r\n let fieldExprItem: FieldExprHierarchyPattern = <FieldExprHierarchyPattern>fieldExpr.hierarchy;\r\n if (fieldExprItem) {\r\n this.validateHierarchy(fieldExprItem.schema, fieldExprItem.entity, fieldExprItem.name);\r\n } else {\r\n this.register(SQExprValidationError.invalidHierarchyReference);\r\n }\r\n }\r\n return expr;\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): SQExpr {\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n if (fieldExpr) {\r\n let hierarchyLevelFieldExprItem: FieldExprHierarchyLevelPattern = <FieldExprHierarchyLevelPattern>fieldExpr.hierarchyLevel;\r\n if (hierarchyLevelFieldExprItem) {\r\n this.validateHierarchyLevel(hierarchyLevelFieldExprItem.schema, hierarchyLevelFieldExprItem.entity, hierarchyLevelFieldExprItem.name, hierarchyLevelFieldExprItem.level);\r\n } else if (!fieldExpr.columnHierarchyLevelVariation) {\r\n this.register(SQExprValidationError.invalidHierarchyLevelReference);\r\n }\r\n }\r\n return expr;\r\n }\r\n\r\n public visitPercentile(expr: SQPercentileExpr): SQExpr {\r\n expr.arg.accept(this);\r\n\r\n if (_.isEmpty(this.errors)) {\r\n let argMetadata = expr.arg.getMetadata(this.schema);\r\n if (!argMetadata ||\r\n argMetadata.kind !== FieldKind.Column ||\r\n !(argMetadata.type && (argMetadata.type.integer || argMetadata.type.numeric))) {\r\n this.register(SQExprValidationError.invalidPercentileArgument);\r\n }\r\n }\r\n\r\n return expr;\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): SQExpr {\r\n this.validateEntity(expr.schema, expr.entity);\r\n return expr;\r\n }\r\n\r\n public visitContains(expr: SQContainsExpr): SQExpr {\r\n this.validateOperandsAndTypeForStartOrContains(expr.left, expr.right);\r\n return expr;\r\n }\r\n\r\n public visitStartsWith(expr: SQContainsExpr): SQExpr {\r\n this.validateOperandsAndTypeForStartOrContains(expr.left, expr.right);\r\n return expr;\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr): SQExpr {\r\n this.validateArithmeticTypes(expr.left, expr.right);\r\n return expr;\r\n }\r\n\r\n public visitScopedEval(expr: SQScopedEvalExpr): SQExpr {\r\n // No validation necessary\r\n return expr;\r\n }\r\n\r\n private validateOperandsAndTypeForStartOrContains(left: SQExpr, right: SQExpr): void {\r\n if (left instanceof SQColumnRefExpr) {\r\n this.visitColumnRef(<SQColumnRefExpr>left);\r\n } else if (left instanceof SQHierarchyLevelExpr) {\r\n this.visitHierarchyLevel(<SQHierarchyLevelExpr>left);\r\n } else {\r\n this.register(SQExprValidationError.invalidLeftOperandType);\r\n }\r\n\r\n if (!(right instanceof SQConstantExpr) || !(<SQConstantExpr>right).type.text)\r\n this.register(SQExprValidationError.invalidRightOperandType);\r\n else\r\n this.validateCompatibleType(left, right);\r\n }\r\n\r\n private validateArithmeticTypes(left: SQExpr, right: SQExpr): void {\r\n if (!SQExprUtils.supportsArithmetic(left, this.schema))\r\n this.register(SQExprValidationError.invalidLeftOperandType);\r\n if (!SQExprUtils.supportsArithmetic(right, this.schema))\r\n this.register(SQExprValidationError.invalidRightOperandType);\r\n }\r\n\r\n private validateCompatibleType(left: SQExpr, right: SQExpr): void {\r\n let leftMetadata = left.getMetadata(this.schema),\r\n leftType = leftMetadata && leftMetadata.type,\r\n rightMetadata = right.getMetadata(this.schema),\r\n rightType = rightMetadata && rightMetadata.type;\r\n\r\n if (leftType && rightType && !leftType.isCompatibleFrom(rightType))\r\n this.register(SQExprValidationError.invalidValueType);\r\n }\r\n\r\n private validateEntity(schemaName: string, entityName: string): ConceptualEntity {\r\n let schema = this.schema.schema(schemaName);\r\n if (schema) {\r\n let entity = schema.entities.withName(entityName);\r\n if (entity)\r\n return entity;\r\n\r\n this.register(SQExprValidationError.invalidEntityReference);\r\n }\r\n else {\r\n this.register(SQExprValidationError.invalidSchemaReference);\r\n }\r\n }\r\n\r\n private validateHierarchy(schemaName: string, entityName: string, hierarchyName: string): ConceptualHierarchy {\r\n let entity = this.validateEntity(schemaName, entityName);\r\n if (entity) {\r\n let hierarchy = entity.hierarchies.withName(hierarchyName);\r\n if (hierarchy)\r\n return hierarchy;\r\n\r\n this.register(SQExprValidationError.invalidHierarchyReference);\r\n }\r\n }\r\n\r\n private validateHierarchyLevel(schemaName: string, entityName: string, hierarchyName: string, levelName: string): ConceptualHierarchyLevel {\r\n let hierarchy = this.validateHierarchy(schemaName, entityName, hierarchyName);\r\n if (hierarchy) {\r\n let hierarchyLevel = hierarchy.levels.withName(levelName);\r\n if (hierarchyLevel)\r\n return hierarchyLevel;\r\n\r\n this.register(SQExprValidationError.invalidHierarchyLevelReference);\r\n }\r\n }\r\n\r\n private register(error: SQExprValidationError) {\r\n if (!this.errors)\r\n this.errors = [];\r\n this.errors.push(error);\r\n }\r\n\r\n private isQueryable(fieldExpr: FieldExprPattern): boolean {\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(fieldExpr);\r\n if (fieldExpr.hierarchyLevel || fieldExpr.hierarchyLevelAggr) {\r\n let hierarchyLevelConceptualProperty = SQHierarchyExprUtils.getConceptualHierarchyLevelFromExpr(this.schema, fieldExpr);\r\n return hierarchyLevelConceptualProperty && hierarchyLevelConceptualProperty.column.queryable !== ConceptualQueryableState.Error;\r\n }\r\n\r\n return this.schema.schema(fieldExprItem.schema).findProperty(fieldExprItem.entity, FieldExprPattern.getPropertyName(fieldExpr)).queryable !== ConceptualQueryableState.Error;\r\n }\r\n }\r\n\r\n /** Returns an expression's aggregate function, or undefined if it doesn't have one. */\r\n class SQExprAggregateInfoVisitor extends DefaultSQExprVisitor<QueryAggregateFunction> {\r\n public visitAggr(expr: SQAggregationExpr): QueryAggregateFunction {\r\n return expr.func;\r\n }\r\n\r\n public visitDefault(expr: SQExpr): QueryAggregateFunction {\r\n return;\r\n }\r\n\r\n public static getAggregate(expr: SQExpr): QueryAggregateFunction {\r\n let visitor = new SQExprAggregateInfoVisitor();\r\n return expr.accept(visitor);\r\n }\r\n }\r\n\r\n /** Returns a SQExprColumnRef expression or undefined.*/\r\n class SQExprColumnRefInfoVisitor extends DefaultSQExprVisitor<SQColumnRefExpr> {\r\n private schema: FederatedConceptualSchema;\r\n\r\n constructor(schema: FederatedConceptualSchema) {\r\n super();\r\n this.schema = schema;\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): SQColumnRefExpr {\r\n return expr;\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): SQColumnRefExpr {\r\n let ref: string = expr.level;\r\n let hierarchy = <SQHierarchyExpr>(expr.arg);\r\n let sourceExpr: SQColumnRefExpr = hierarchy.accept(this);\r\n\r\n if (hierarchy && hierarchy.arg instanceof SQPropertyVariationSourceExpr) {\r\n let propertyVariationSource = <SQPropertyVariationSourceExpr>hierarchy.arg;\r\n let targetEntity = sourceExpr.getTargetEntityForVariation(this.schema, propertyVariationSource.name);\r\n\r\n if (sourceExpr && targetEntity) {\r\n let schemaName = (<SQEntityExpr>(sourceExpr.source)).schema;\r\n let targetEntityExpr = SQExprBuilder.entity(schemaName, targetEntity);\r\n let schemaHierarchy = this.schema.schema(schemaName).findHierarchy(targetEntity, hierarchy.hierarchy);\r\n\r\n if (schemaHierarchy) {\r\n for (let level of schemaHierarchy.levels)\r\n if (level.name === ref)\r\n return new SQColumnRefExpr(targetEntityExpr, level.column.name);\r\n }\r\n }\r\n }\r\n else {\r\n let entityExpr = <SQEntityExpr>(hierarchy.arg);\r\n let hierarchyLevelRef = SQHierarchyExprUtils.getConceptualHierarchyLevel(this.schema,\r\n entityExpr.schema,\r\n entityExpr.entity,\r\n hierarchy.hierarchy,\r\n expr.level);\r\n\r\n if (hierarchyLevelRef)\r\n return new SQColumnRefExpr(hierarchy.arg, hierarchyLevelRef.column.name);\r\n }\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): SQColumnRefExpr {\r\n return expr.arg.accept(this);\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr): SQColumnRefExpr {\r\n let propertyName = expr.property;\r\n return new SQColumnRefExpr(expr.arg, propertyName);\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): SQColumnRefExpr {\r\n return expr.arg.accept(this);\r\n }\r\n\r\n public visitDefault(expr: SQExpr): SQColumnRefExpr {\r\n return;\r\n }\r\n\r\n public static getColumnRefSQExpr(schema: FederatedConceptualSchema, expr: SQExpr): SQColumnRefExpr {\r\n let visitor = new SQExprColumnRefInfoVisitor(schema);\r\n return expr.accept(visitor);\r\n }\r\n }\r\n\r\n /** Returns a SQEntityExpr expression or undefined.*/\r\n class SQEntityExprInfoVisitor extends DefaultSQExprVisitor<SQEntityExpr> {\r\n private schema: FederatedConceptualSchema;\r\n\r\n constructor(schema: FederatedConceptualSchema) {\r\n super();\r\n this.schema = schema;\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): SQEntityExpr {\r\n return expr;\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): SQEntityExpr {\r\n return SQEntityExprInfoVisitor.getEntity(expr);\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): SQEntityExpr {\r\n let columnRef = SQEntityExprInfoVisitor.getColumnRefSQExpr(this.schema, expr);\r\n return SQEntityExprInfoVisitor.getEntity(columnRef);\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): SQEntityExpr {\r\n return expr.arg.accept(this);\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr): SQEntityExpr {\r\n let columnRef = SQEntityExprInfoVisitor.getColumnRefSQExpr(this.schema, expr);\r\n return SQEntityExprInfoVisitor.getEntity(columnRef);\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): SQEntityExpr {\r\n let columnRef = SQEntityExprInfoVisitor.getColumnRefSQExpr(this.schema, expr);\r\n return SQEntityExprInfoVisitor.getEntity(columnRef);\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr): SQEntityExpr {\r\n return expr.source.accept(this);\r\n }\r\n\r\n public static getColumnRefSQExpr(schema: FederatedConceptualSchema, expr: SQExpr): SQColumnRefExpr {\r\n let visitor = new SQExprColumnRefInfoVisitor(schema);\r\n return expr.accept(visitor);\r\n }\r\n\r\n public static getEntity(columnRef: SQColumnRefExpr): SQEntityExpr {\r\n let field = SQExprConverter.asFieldPattern(columnRef);\r\n let column = field.column;\r\n return SQExprBuilder.entity(column.schema, column.entity, column.entityVar);\r\n }\r\n\r\n public static getEntityExpr(schema: FederatedConceptualSchema, expr: SQExpr): SQEntityExpr {\r\n let visitor = new SQEntityExprInfoVisitor(schema);\r\n return expr.accept(visitor);\r\n }\r\n }\r\n\r\n class SQExprChangeAggregateRewriter extends SQExprRootRewriter {\r\n private func: QueryAggregateFunction;\r\n\r\n constructor(func: QueryAggregateFunction) {\r\n debug.assertValue(func, 'func');\r\n\r\n super();\r\n this.func = func;\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): SQExpr {\r\n if (expr.func === this.func)\r\n return expr;\r\n\r\n return new SQAggregationExpr(expr.arg, this.func);\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): SQExpr {\r\n return new SQAggregationExpr(expr, this.func);\r\n }\r\n\r\n public static rewrite(expr: SQExpr, func: QueryAggregateFunction): SQExpr {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(func, 'func');\r\n\r\n let rewriter = new SQExprChangeAggregateRewriter(func);\r\n return expr.accept(rewriter);\r\n }\r\n }\r\n\r\n class FieldExprChangeAggregateRewriter implements IFieldExprPatternVisitor<SQExpr> {\r\n private sqExpr: SQExpr;\r\n private aggregate: QueryAggregateFunction;\r\n\r\n constructor(sqExpr: SQExpr, aggregate: QueryAggregateFunction) {\r\n this.sqExpr = sqExpr;\r\n this.aggregate = aggregate;\r\n }\r\n\r\n public static rewrite(sqExpr: SQExpr, aggregate: QueryAggregateFunction): SQExpr {\r\n return FieldExprPattern.visit(sqExpr, new FieldExprChangeAggregateRewriter(sqExpr, aggregate));\r\n }\r\n\r\n public visitPercentOfGrandTotal(pattern: FieldExprPercentOfGrandTotalPattern): SQExpr {\r\n pattern.baseExpr = SQExprConverter.asFieldPattern(\r\n SQExprChangeAggregateRewriter.rewrite(\r\n SQExprBuilder.fieldExpr(pattern.baseExpr),\r\n this.aggregate));\r\n return SQExprBuilder.fieldExpr({ percentOfGrandTotal: pattern });\r\n }\r\n\r\n public visitColumn(column: FieldExprColumnPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitEntity(entity: FieldExprEntityPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitHierarchy(hierarchy: FieldExprHierarchyPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n private defaultRewrite(): SQExpr {\r\n return SQExprChangeAggregateRewriter.rewrite(this.sqExpr, this.aggregate);\r\n }\r\n }\r\n\r\n class FieldExprRemoveAggregateRewriter implements IFieldExprPatternVisitor<SQExpr> {\r\n\r\n constructor(private sqExpr: SQExpr) {\r\n }\r\n\r\n public static rewrite(sqExpr: SQExpr): SQExpr {\r\n return FieldExprPattern.visit(sqExpr, new FieldExprRemoveAggregateRewriter(sqExpr));\r\n }\r\n\r\n public visitPercentOfGrandTotal(pattern: FieldExprPercentOfGrandTotalPattern): SQExpr {\r\n return FieldExprRemoveAggregateRewriter.rewrite(SQExprBuilder.fieldExpr(pattern.baseExpr));\r\n }\r\n\r\n public visitColumn(column: FieldExprColumnPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitColumnAggr(columnAggr: FieldExprColumnAggrPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitColumnHierarchyLevelVariation(columnHierarchyLevelVariation: FieldExprColumnHierarchyLevelVariationPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitSelectRef(selectRef: FieldExprSelectRefPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitEntity(entity: FieldExprEntityPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitEntityAggr(entityAggr: FieldExprEntityAggrPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitHierarchy(hierarchy: FieldExprHierarchyPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitHierarchyLevel(hierarchyLevel: FieldExprHierarchyLevelPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitHierarchyLevelAggr(hierarchyLevelAggr: FieldExprHierarchyLevelAggrPattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitMeasure(measure: FieldExprMeasurePattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n public visitPercentile(percentile: FieldExprPercentilePattern): SQExpr {\r\n return this.defaultRewrite();\r\n }\r\n\r\n private defaultRewrite(): SQExpr {\r\n return SQExprRemoveAggregateRewriter.rewrite(this.sqExpr);\r\n }\r\n }\r\n\r\n class SQExprRemoveAggregateRewriter extends SQExprRootRewriter {\r\n private static instance: SQExprRemoveAggregateRewriter = new SQExprRemoveAggregateRewriter();\r\n\r\n public visitAggr(expr: SQAggregationExpr): SQExpr {\r\n return expr.arg;\r\n }\r\n\r\n public static rewrite(expr: SQExpr): SQExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.accept(SQExprRemoveAggregateRewriter.instance);\r\n }\r\n }\r\n\r\n class SQExprRemoveEntityVariablesRewriter extends SQExprRewriter {\r\n private static instance: SQExprRemoveEntityVariablesRewriter = new SQExprRemoveEntityVariablesRewriter();\r\n\r\n public visitEntity(expr: SQEntityExpr): SQExpr {\r\n if (expr.variable)\r\n return SQExprBuilder.entity(expr.schema, expr.entity);\r\n\r\n return expr;\r\n }\r\n\r\n public static rewrite(expr: SQExpr): SQExpr {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.accept(SQExprRemoveEntityVariablesRewriter.instance);\r\n }\r\n }\r\n\r\n class SQExprRemovePercentOfGrandTotalRewriter extends SQExprRootRewriter {\r\n private static instance: SQExprRemovePercentOfGrandTotalRewriter = new SQExprRemovePercentOfGrandTotalRewriter();\r\n\r\n public static rewrite(expr: SQExpr): SQExpr {\r\n debug.assertValue(expr, 'expr');\r\n return expr.accept(SQExprRemovePercentOfGrandTotalRewriter.instance);\r\n }\r\n\r\n public visitDefault(expr: SQExpr): SQExpr {\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n if (fieldExpr && fieldExpr.percentOfGrandTotal)\r\n expr = SQExprBuilder.fieldExpr(fieldExpr.percentOfGrandTotal.baseExpr);\r\n\r\n return expr;\r\n }\r\n }\r\n\r\n class SQExprSetPercentOfGrandTotalRewriter extends SQExprRootRewriter {\r\n private static instance: SQExprSetPercentOfGrandTotalRewriter = new SQExprSetPercentOfGrandTotalRewriter();\r\n\r\n public static rewrite(expr: SQExpr): SQExpr {\r\n debug.assertValue(expr, 'expr');\r\n return expr.accept(SQExprSetPercentOfGrandTotalRewriter.instance);\r\n }\r\n\r\n public visitDefault(expr: SQExpr): SQExpr {\r\n let fieldExpr = SQExprConverter.asFieldPattern(expr);\r\n if (fieldExpr && !fieldExpr.percentOfGrandTotal)\r\n expr = SQExprBuilder.fieldExpr({ percentOfGrandTotal: { baseExpr: SQExprConverter.asFieldPattern(expr) } });\r\n\r\n return expr;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n import ArrayNamedItems = jsCommon.ArrayNamedItems;\r\n import ConceptualEntity = powerbi.data.ConceptualEntity;\r\n import ConceptualMultiplicity = powerbi.data.ConceptualMultiplicity;\r\n import SQEntityExpr = powerbi.data.SQEntityExpr;\r\n import StringExtensions = jsCommon.StringExtensions;\r\n\r\n export module SQExprUtils {\r\n export function supportsArithmetic(expr: SQExpr, schema: FederatedConceptualSchema): boolean {\r\n let metadata = expr.getMetadata(schema),\r\n type = metadata && metadata.type;\r\n\r\n if (!metadata || !type) {\r\n return false;\r\n }\r\n \r\n return type.numeric || type.dateTime || type.duration;\r\n }\r\n\r\n export function indexOfExpr(items: SQExpr[], searchElement: SQExpr): number {\r\n debug.assertValue(items, 'items');\r\n debug.assertValue(searchElement, 'searchElement');\r\n\r\n for (let i = 0, len = items.length; i < len; i++) {\r\n if (SQExpr.equals(items[i], searchElement))\r\n return i;\r\n }\r\n return -1;\r\n }\r\n\r\n export function sequenceEqual(x: SQExpr[], y: SQExpr[]): boolean {\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n\r\n let len = x.length;\r\n if (len !== y.length)\r\n return false;\r\n\r\n for (let i = 0; i < len; i++) {\r\n if (!SQExpr.equals(x[i], y[i]))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n \r\n export function uniqueName(namedItems: NamedSQExpr[], expr: SQExpr, exprDefaultName?: string): string {\r\n debug.assertValue(namedItems, 'namedItems');\r\n\r\n // Determine all names\r\n let names: { [name: string]: boolean } = {};\r\n for (let i = 0, len = namedItems.length; i < len; i++)\r\n names[namedItems[i].name] = true;\r\n\r\n return StringExtensions.findUniqueName(names, exprDefaultName || defaultName(expr));\r\n }\r\n\r\n /** Generates a default expression name */\r\n export function defaultName(expr: SQExpr, fallback: string = 'select'): string {\r\n if (!expr)\r\n return fallback;\r\n\r\n return expr.accept(SQExprDefaultNameGenerator.instance, fallback);\r\n }\r\n\r\n /** Gets a value indicating whether the expr is a model measure or an aggregate. */\r\n export function isMeasure(expr: SQExpr): boolean {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.accept(IsMeasureVisitor.instance);\r\n }\r\n\r\n /** Gets a value indicating whether the expr is an AnyValue or equals comparison to AnyValue*/\r\n export function isAnyValue(expr: SQExpr): boolean {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.accept(IsAnyValueVisitor.instance);\r\n }\r\n\r\n /** Gets a value indicating whether the expr is a DefaultValue or equals comparison to DefaultValue*/\r\n export function isDefaultValue(expr: SQExpr): boolean {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return expr.accept(IsDefaultValueVisitor.instance);\r\n }\r\n\r\n export function discourageAggregation(expr: SQExpr, schema: FederatedConceptualSchema): boolean {\r\n let capabilities = getSchemaCapabilities(expr, schema);\r\n return capabilities && capabilities.discourageQueryAggregateUsage;\r\n }\r\n\r\n export function getAggregateBehavior(expr: SQExpr, schema: FederatedConceptualSchema): ConceptualAggregateBehavior {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(schema, 'schema');\r\n\r\n let column = getConceptualColumn(expr, schema);\r\n if (column)\r\n return column.aggregateBehavior;\r\n }\r\n\r\n export function getSchemaCapabilities(expr: SQExpr, schema: FederatedConceptualSchema): ConceptualCapabilities {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(schema, 'schema');\r\n\r\n let field = SQExprConverter.asFieldPattern(expr);\r\n if (!field)\r\n return;\r\n\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(field);\r\n let conceptualSchema = schema.schema(fieldExprItem.schema);\r\n if (conceptualSchema)\r\n return conceptualSchema.capabilities;\r\n }\r\n\r\n export function getKpiMetadata(expr: SQExpr, schema: FederatedConceptualSchema): DataViewKpiColumnMetadata {\r\n let kpiStatusProperty = getKpiStatusProperty(expr, schema);\r\n if (kpiStatusProperty)\r\n return kpiStatusProperty.kpiValue.measure.kpi.statusMetadata;\r\n\r\n let kpiTrendProperty = getKpiTrendProperty(expr, schema);\r\n if (kpiTrendProperty)\r\n return kpiTrendProperty.kpiValue.measure.kpi.trendMetadata;\r\n }\r\n\r\n export function getConceptualEntity(entityExpr: SQEntityExpr, schema: FederatedConceptualSchema): ConceptualEntity {\r\n debug.assertValue(entityExpr, 'entityExpr');\r\n\r\n let conceptualEntity = schema\r\n .schema(entityExpr.schema)\r\n .entities\r\n .withName(entityExpr.entity);\r\n return conceptualEntity;\r\n }\r\n\r\n function getKpiStatusProperty(expr: SQExpr, schema: FederatedConceptualSchema): ConceptualProperty {\r\n let property = expr.getConceptualProperty(schema);\r\n if (!property)\r\n return;\r\n\r\n let kpiValue = property.kpiValue;\r\n if (kpiValue && kpiValue.measure.kpi.status === property)\r\n return property;\r\n }\r\n\r\n function getKpiTrendProperty(expr: SQExpr, schema: FederatedConceptualSchema): ConceptualProperty {\r\n let property = expr.getConceptualProperty(schema);\r\n if (!property)\r\n return;\r\n\r\n let kpiValue = property.kpiValue;\r\n if (kpiValue && kpiValue.measure.kpi.trend === property)\r\n return property;\r\n }\r\n\r\n export function getDefaultValue(fieldSQExpr: SQExpr, schema: FederatedConceptualSchema): SQConstantExpr {\r\n let column = getConceptualColumn(fieldSQExpr, schema);\r\n if (column)\r\n return column.defaultValue;\r\n }\r\n\r\n function getConceptualColumn(fieldSQExpr: SQExpr, schema: FederatedConceptualSchema): ConceptualColumn {\r\n if (!fieldSQExpr || !schema)\r\n return;\r\n\r\n let sqField = SQExprConverter.asFieldPattern(fieldSQExpr);\r\n if (!sqField)\r\n return;\r\n\r\n let column: FieldExprPropertyPattern = sqField.column;\r\n\r\n if (column) {\r\n if (schema.schema(column.schema) && sqField.column.name) {\r\n let property = schema.schema(column.schema).findProperty(column.entity, sqField.column.name);\r\n\r\n if (property)\r\n return property.column;\r\n }\r\n }\r\n else {\r\n let hierarchyLevelField: FieldExprHierarchyLevelPattern = sqField.hierarchyLevel;\r\n if (hierarchyLevelField) {\r\n let fieldExprItem = FieldExprPattern.toFieldExprEntityItemPattern(sqField);\r\n let schemaName = fieldExprItem.schema;\r\n if (schema.schema(schemaName)) {\r\n let hierarchy = schema.schema(schemaName)\r\n .findHierarchy(fieldExprItem.entity, hierarchyLevelField.name);\r\n\r\n if (hierarchy) {\r\n let hierarchyLevel: ConceptualHierarchyLevel = hierarchy.levels.withName(hierarchyLevelField.level);\r\n if (hierarchyLevel && hierarchyLevel.column)\r\n return hierarchyLevel.column.column;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n export function getDefaultValues(fieldSQExprs: SQExpr[], schema: FederatedConceptualSchema): SQConstantExpr[] {\r\n if (_.isEmpty(fieldSQExprs) || !schema)\r\n return;\r\n let result: SQConstantExpr[] = [];\r\n for (let sqExpr of fieldSQExprs) {\r\n let defaultValue = getDefaultValue(sqExpr, schema);\r\n if (defaultValue)\r\n result.push(defaultValue);\r\n }\r\n return result;\r\n }\r\n\r\n /** Return compare or and expression for key value pairs. */\r\n export function getDataViewScopeIdentityComparisonExpr(fieldsExpr: SQExpr[], values: SQConstantExpr[]): SQExpr {\r\n debug.assert(fieldsExpr.length === values.length, \"fileds and values need to be the same size\");\r\n\r\n let compareExprs: SQCompareExpr[] = [];\r\n for (let i = 0; i < fieldsExpr.length; i++) {\r\n compareExprs.push(SQExprBuilder.compare(QueryComparisonKind.Equal, fieldsExpr[i], values[i]));\r\n }\r\n\r\n if (_.isEmpty(compareExprs))\r\n return;\r\n\r\n let resultExpr: SQExpr;\r\n for (let compareExpr of compareExprs) {\r\n resultExpr = SQExprBuilder.and(resultExpr, compareExpr);\r\n }\r\n\r\n return resultExpr;\r\n }\r\n\r\n export function getActiveTablesNames(queryDefn: data.SemanticQuery): string[] {\r\n let tables: string[] = [];\r\n if (queryDefn) {\r\n let selectedItems = queryDefn.from();\r\n if (selectedItems !== undefined) {\r\n for (let key of selectedItems.keys()) {\r\n let entityObj = selectedItems.entity(key);\r\n if (tables.indexOf(entityObj.entity) < 0)\r\n tables.push(entityObj.entity);\r\n }\r\n }\r\n }\r\n return tables;\r\n }\r\n\r\n export function isRelatedToMany(\r\n schema: FederatedConceptualSchema,\r\n sourceExpr: SQEntityExpr,\r\n targetExpr: SQEntityExpr): boolean {\r\n\r\n return isRelated(schema, sourceExpr, targetExpr, ConceptualMultiplicity.ZeroOrOne, ConceptualMultiplicity.Many) ||\r\n isRelated(schema, targetExpr, sourceExpr, ConceptualMultiplicity.Many, ConceptualMultiplicity.ZeroOrOne);\r\n }\r\n\r\n export function isRelatedToOne(\r\n schema: FederatedConceptualSchema,\r\n sourceExpr: SQEntityExpr,\r\n targetExpr: SQEntityExpr): boolean {\r\n\r\n return isRelated(schema, sourceExpr, targetExpr, ConceptualMultiplicity.Many, ConceptualMultiplicity.ZeroOrOne) ||\r\n isRelated(schema, targetExpr, sourceExpr, ConceptualMultiplicity.ZeroOrOne, ConceptualMultiplicity.Many);\r\n }\r\n\r\n function isRelated(\r\n schema: FederatedConceptualSchema,\r\n sourceExpr: SQEntityExpr,\r\n targetExpr: SQEntityExpr,\r\n sourceMultiplicity: ConceptualMultiplicity,\r\n targetMultiplicity: ConceptualMultiplicity): boolean {\r\n\r\n let source = SQExprUtils.getConceptualEntity(sourceExpr, schema);\r\n debug.assertValue(source, \"could not resolve conceptual entity form sourceExpr.\");\r\n\r\n if (_.isEmpty(source.navigationProperties))\r\n return false;\r\n\r\n let target = SQExprUtils.getConceptualEntity(targetExpr, schema);\r\n debug.assertValue(target, \"could not resolve conceptual entity form targetExpr.\");\r\n\r\n let queue: ConceptualEntity[] = [];\r\n queue.push(source);\r\n\r\n // walk the relationship path from source.\r\n while (!_.isEmpty(queue)) {\r\n let current = queue.shift();\r\n\r\n let navProperties = current.navigationProperties;\r\n if (_.isEmpty(navProperties))\r\n continue;\r\n\r\n for (let navProperty of navProperties) {\r\n if (!navProperty.isActive)\r\n continue;\r\n\r\n if (navProperty.targetMultiplicity === targetMultiplicity && navProperty.sourceMultiplicity === sourceMultiplicity) {\r\n if (navProperty.targetEntity === target)\r\n return true;\r\n queue.push(navProperty.targetEntity);\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n export function isRelatedOneToOne(\r\n schema: FederatedConceptualSchema,\r\n sourceExpr: SQEntityExpr,\r\n targetExpr: SQEntityExpr): boolean {\r\n\r\n let source = SQExprUtils.getConceptualEntity(sourceExpr, schema);\r\n debug.assertValue(source, \"could not resolve conceptual entity form sourceExpr.\");\r\n let target = SQExprUtils.getConceptualEntity(targetExpr, schema);\r\n debug.assertValue(target, \"could not resolve conceptual entity form targetExpr.\");\r\n\r\n let sourceNavigations = source.navigationProperties;\r\n let targetNavigations = target.navigationProperties;\r\n\r\n if (_.isEmpty(sourceNavigations) && _.isEmpty(targetNavigations))\r\n return false;\r\n\r\n return hasOneToOneNavigation(sourceNavigations, target) || hasOneToOneNavigation(targetNavigations, source);\r\n }\r\n\r\n function hasOneToOneNavigation(navigationProperties: ArrayNamedItems<ConceptualNavigationProperty>, targetEntity: ConceptualEntity): boolean {\r\n if (_.isEmpty(navigationProperties))\r\n return false;\r\n\r\n for (let navigationProperty of navigationProperties) {\r\n if (!navigationProperty.isActive)\r\n continue;\r\n\r\n if (navigationProperty.targetEntity !== targetEntity)\r\n continue;\r\n\r\n if (navigationProperty.sourceMultiplicity === ConceptualMultiplicity.ZeroOrOne &&\r\n navigationProperty.targetMultiplicity === ConceptualMultiplicity.ZeroOrOne) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /** Performs a union of the 2 arrays with SQExpr.equals as comparator to skip duplicate items,\r\n and returns a new array. When available, we should use _.unionWith from lodash. */\r\n export function concatUnique(leftExprs: SQExpr[], rightExprs: SQExpr[]): SQExpr[] {\r\n debug.assertValue(leftExprs, 'leftExprs');\r\n debug.assertValue(rightExprs, 'rightExprs');\r\n\r\n let concatExprs = ArrayExtensions.copy(leftExprs);\r\n for (let expr of rightExprs) {\r\n if (indexOfExpr(concatExprs, expr) === -1) {\r\n concatExprs.push(expr);\r\n }\r\n }\r\n\r\n return concatExprs;\r\n }\r\n\r\n class SQExprDefaultNameGenerator extends DefaultSQExprVisitorWithArg<string, string> {\r\n public static instance: SQExprDefaultNameGenerator = new SQExprDefaultNameGenerator();\r\n\r\n public visitEntity(expr: SQEntityExpr): string {\r\n return expr.entity;\r\n }\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): string {\r\n return expr.source.accept(this) + '.' + expr.ref;\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr, fallback: string): string {\r\n return expr.source.accept(this) + '.' + expr.ref;\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr, fallback: string): string {\r\n return QueryAggregateFunction[expr.func] + '(' + expr.arg.accept(this) + ')';\r\n }\r\n\r\n public visitPercentile(expr: SQPercentileExpr, fallback: string): string {\r\n let func = expr.exclusive\r\n ? 'Percentile.Exc('\r\n : 'Percentile.Inc(';\r\n\r\n return func + expr.arg.accept(this) + ', ' + expr.k + ')';\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr, fallback: string): string {\r\n return powerbi.data.getArithmeticOperatorName(expr.operator) + '(' + expr.left.accept(this) + ', ' + expr.right.accept(this) + ')';\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr): string {\r\n return 'const';\r\n }\r\n\r\n public visitDefault(expr: SQExpr, fallback: string): string {\r\n return fallback || 'expr';\r\n }\r\n }\r\n\r\n class IsMeasureVisitor extends DefaultSQExprVisitor<boolean> {\r\n public static instance: IsMeasureVisitor = new IsMeasureVisitor();\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr): boolean {\r\n return true;\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): boolean {\r\n return true;\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr): boolean {\r\n return true;\r\n }\r\n\r\n public visitDefault(expr: SQExpr): boolean {\r\n return false;\r\n }\r\n }\r\n\r\n class IsDefaultValueVisitor extends DefaultSQExprVisitor<boolean> {\r\n public static instance: IsDefaultValueVisitor = new IsDefaultValueVisitor();\r\n\r\n public visitCompare(expr: SQCompareExpr): boolean {\r\n if (expr.comparison !== QueryComparisonKind.Equal)\r\n return false;\r\n\r\n return expr.right.accept(this);\r\n }\r\n\r\n public visitAnd(expr: SQAndExpr): boolean {\r\n return expr.left.accept(this) && expr.right.accept(this);\r\n }\r\n\r\n public visitDefaultValue(expr: SQDefaultValueExpr): boolean {\r\n return true;\r\n }\r\n\r\n public visitDefault(expr: SQExpr): boolean {\r\n return false;\r\n }\r\n }\r\n\r\n class IsAnyValueVisitor extends DefaultSQExprVisitor<boolean> {\r\n public static instance: IsAnyValueVisitor = new IsAnyValueVisitor();\r\n\r\n public visitCompare(expr: SQCompareExpr): boolean {\r\n if (expr.comparison !== QueryComparisonKind.Equal)\r\n return false;\r\n\r\n return expr.right.accept(this);\r\n }\r\n\r\n public visitAnd(expr: SQAndExpr): boolean {\r\n return expr.left.accept(this) && expr.right.accept(this);\r\n }\r\n\r\n public visitAnyValue(expr: SQAnyValueExpr): boolean {\r\n return true;\r\n }\r\n\r\n public visitDefault(expr: SQExpr): boolean {\r\n return false;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n\r\n export class SemanticQueryRewriter {\r\n private exprRewriter: ISQExprVisitor<SQExpr>;\r\n\r\n constructor(exprRewriter: ISQExprVisitor<SQExpr>) {\r\n this.exprRewriter = exprRewriter;\r\n }\r\n\r\n public rewriteFrom(fromValue: SQFrom): SQFrom {\r\n let fromContents: { [name: string]: SQFromEntitySource } = {};\r\n let originalFrom = fromValue,\r\n originalFromKeys = originalFrom.keys();\r\n for (let i = 0, len = originalFromKeys.length; i < len; i++) {\r\n let keyName = originalFromKeys[i],\r\n originalEntityRef = originalFrom.entity(keyName),\r\n originalEntityExpr = SQExprBuilder.entity(originalEntityRef.schema, originalEntityRef.entity, keyName),\r\n updatedEntityExpr = <SQEntityExpr>originalEntityExpr.accept(this.exprRewriter);\r\n \r\n fromContents[keyName] = {\r\n schema: updatedEntityExpr.schema,\r\n entity: updatedEntityExpr.entity,\r\n };\r\n }\r\n return new SQFrom(fromContents);\r\n }\r\n\r\n public rewriteSelect(selectItems: NamedSQExpr[], from: SQFrom): NamedSQExpr[]{\r\n debug.assertValue(selectItems, 'selectItems');\r\n debug.assertValue(from, 'from');\r\n\r\n return this.rewriteNamedSQExpressions(selectItems, from);\r\n }\r\n\r\n public rewriteGroupBy(groupByitems: NamedSQExpr[], from: SQFrom): NamedSQExpr[] {\r\n debug.assertAnyValue(groupByitems, 'groupByitems');\r\n debug.assertValue(from, 'from');\r\n\r\n if (_.isEmpty(groupByitems))\r\n return;\r\n\r\n return this.rewriteNamedSQExpressions(groupByitems, from);\r\n }\r\n\r\n private rewriteNamedSQExpressions(expressions: NamedSQExpr[], from: SQFrom): NamedSQExpr[] {\r\n debug.assertValue(expressions, 'expressions');\r\n\r\n return _.map(expressions, item => {\r\n return {\r\n name: item.name,\r\n expr: SQExprRewriterWithSourceRenames.rewrite(item.expr.accept(this.exprRewriter), from)\r\n };\r\n });\r\n }\r\n\r\n public rewriteOrderBy(orderByItems: SQSortDefinition[], from: SQFrom): SQSortDefinition[]{\r\n debug.assertAnyValue(orderByItems, 'orderByItems');\r\n debug.assertValue(from, 'from');\r\n\r\n if (_.isEmpty(orderByItems))\r\n return;\r\n\r\n let orderBy: SQSortDefinition[] = [];\r\n for (let i = 0, len = orderByItems.length; i < len; i++) {\r\n let item = orderByItems[i],\r\n updatedExpr = SQExprRewriterWithSourceRenames.rewrite(item.expr.accept(this.exprRewriter), from);\r\n orderBy.push({\r\n direction: item.direction,\r\n expr: updatedExpr,\r\n });\r\n }\r\n\r\n return orderBy;\r\n }\r\n\r\n public rewriteWhere(whereItems: SQFilter[], from: SQFrom): SQFilter[]{\r\n debug.assertAnyValue(whereItems, 'whereItems');\r\n debug.assertValue(from, 'from');\r\n\r\n if (_.isEmpty(whereItems))\r\n return;\r\n\r\n let where: SQFilter[] = [];\r\n for (let i = 0, len = whereItems.length; i < len; i++) {\r\n let originalWhere = whereItems[i];\r\n\r\n let updatedWhere: SQFilter = {\r\n condition: SQExprRewriterWithSourceRenames.rewrite(originalWhere.condition.accept(this.exprRewriter), from),\r\n };\r\n\r\n if (originalWhere.target)\r\n updatedWhere.target = _.map(originalWhere.target, e => SQExprRewriterWithSourceRenames.rewrite(e.accept(this.exprRewriter), from));\r\n\r\n where.push(updatedWhere);\r\n }\r\n\r\n return where;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n import ArrayNamedItems = jsCommon.ArrayNamedItems;\r\n\r\n export interface NamedSQExpr {\r\n name: string;\r\n expr: SQExpr;\r\n }\r\n\r\n export interface SQFilter {\r\n target?: SQExpr[];\r\n condition: SQExpr;\r\n }\r\n\r\n /** Represents an entity reference in SemanticQuery from. */\r\n export interface SQFromEntitySource {\r\n entity: string;\r\n schema: string;\r\n }\r\n\r\n /** Represents a sort over an expression. */\r\n export interface SQSortDefinition {\r\n expr: SQExpr;\r\n direction: SortDirection;\r\n }\r\n\r\n export interface QueryFromEnsureEntityResult {\r\n name: string;\r\n new?: boolean;\r\n }\r\n\r\n export interface SQSourceRenames {\r\n [from: string]: string;\r\n }\r\n\r\n /**\r\n * Represents a semantic query that is:\r\n * 1) Round-trippable with a JSON QueryDefinition.\r\n * 2) Immutable\r\n * 3) Long-lived and does not have strong references to a conceptual model (only names).\r\n */\r\n export class SemanticQuery {\r\n private static empty: SemanticQuery;\r\n private fromValue: SQFrom;\r\n private whereItems: SQFilter[];\r\n private orderByItems: SQSortDefinition[];\r\n private selectItems: NamedSQExpr[];\r\n private groupByItems: NamedSQExpr[];\r\n\r\n constructor(from: SQFrom, where: SQFilter[], orderBy: SQSortDefinition[], select: NamedSQExpr[], groupBy: NamedSQExpr[]) {\r\n debug.assertValue(from, 'from');\r\n debug.assertValue(select, 'select');\r\n\r\n this.fromValue = from;\r\n this.whereItems = where;\r\n this.orderByItems = orderBy;\r\n this.selectItems = select;\r\n this.groupByItems = groupBy;\r\n }\r\n\r\n public static create(): SemanticQuery {\r\n if (!SemanticQuery.empty)\r\n SemanticQuery.empty = new SemanticQuery(new SQFrom(), null, null, [], null);\r\n\r\n return SemanticQuery.empty;\r\n }\r\n\r\n private static createWithTrimmedFrom(\r\n from: SQFrom,\r\n where: SQFilter[],\r\n orderBy: SQSortDefinition[],\r\n select: NamedSQExpr[],\r\n groupBy: NamedSQExpr[]): SemanticQuery {\r\n\r\n let unreferencedKeyFinder = new UnreferencedKeyFinder(from.keys());\r\n\r\n // Where\r\n if (where) {\r\n for (let i = 0, len = where.length; i < len; i++) {\r\n let filter = where[i];\r\n\r\n filter.condition.accept(unreferencedKeyFinder);\r\n\r\n let filterTarget = filter.target;\r\n if (filterTarget) {\r\n for (let j = 0, jlen = filterTarget.length; j < jlen; j++)\r\n if (filterTarget[j])\r\n filterTarget[j].accept(unreferencedKeyFinder);\r\n }\r\n }\r\n }\r\n\r\n // OrderBy\r\n if (orderBy) {\r\n for (let i = 0, len = orderBy.length; i < len; i++)\r\n orderBy[i].expr.accept(unreferencedKeyFinder);\r\n }\r\n\r\n // Select\r\n for (let i = 0, len = select.length; i < len; i++)\r\n select[i].expr.accept(unreferencedKeyFinder);\r\n\r\n // GroupBy\r\n if (groupBy) {\r\n for (let i = 0, len = groupBy.length; i < len; i++)\r\n groupBy[i].expr.accept(unreferencedKeyFinder);\r\n }\r\n\r\n let unreferencedKeys = unreferencedKeyFinder.result();\r\n for (let i = 0, len = unreferencedKeys.length; i < len; i++)\r\n from.remove(unreferencedKeys[i]);\r\n\r\n return new SemanticQuery(from, where, orderBy, select, groupBy);\r\n }\r\n\r\n public from(): SQFrom {\r\n return this.fromValue.clone();\r\n }\r\n\r\n /** Returns a query equivalent to this, with the specified selected items. */\r\n select(values: NamedSQExpr[]): SemanticQuery;\r\n /** Gets the items being selected in this query. */\r\n select(): ArrayNamedItems<NamedSQExpr>;\r\n public select(values?: NamedSQExpr[]): any {\r\n if (_.isEmpty(arguments))\r\n return this.getSelect();\r\n\r\n return this.setSelect(values);\r\n }\r\n\r\n private getSelect(): ArrayNamedItems<NamedSQExpr> {\r\n return SemanticQuery.createNamedExpressionArray(this.selectItems);\r\n }\r\n\r\n private static createNamedExpressionArray(items: NamedSQExpr[]): ArrayNamedItems<NamedSQExpr> {\r\n return ArrayExtensions.extendWithName<NamedSQExpr>(_.map(items, s => {\r\n return {\r\n name: s.name,\r\n expr: s.expr,\r\n };\r\n }));\r\n }\r\n\r\n private setSelect(values: NamedSQExpr[]): SemanticQuery {\r\n let from = this.fromValue.clone();\r\n let selectItems = SemanticQuery.rewriteExpressionsWithSourceRenames(values, from);\r\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, selectItems, this.groupByItems);\r\n }\r\n\r\n private static rewriteExpressionsWithSourceRenames(values: NamedSQExpr[], from: SQFrom): NamedSQExpr[] {\r\n let items: NamedSQExpr[] = [];\r\n\r\n for (let i = 0, len = values.length; i < len; i++) {\r\n let value = values[i];\r\n items.push({\r\n name: value.name,\r\n expr: SQExprRewriterWithSourceRenames.rewrite(value.expr, from)\r\n });\r\n }\r\n\r\n return items;\r\n } \r\n\r\n /** Removes the given expression from the select. */\r\n public removeSelect(expr: SQExpr): SemanticQuery {\r\n debug.assertValue(expr, 'expr');\r\n\r\n let originalItems = this.selectItems,\r\n selectItems: NamedSQExpr[] = [];\r\n for (let i = 0, len = originalItems.length; i < len; i++) {\r\n let originalExpr = originalItems[i];\r\n if (SQExpr.equals(originalExpr.expr, expr))\r\n continue;\r\n\r\n selectItems.push(originalExpr);\r\n }\r\n\r\n return SemanticQuery.createWithTrimmedFrom(this.fromValue.clone(), this.whereItems, this.orderByItems, selectItems, this.groupByItems);\r\n }\r\n\r\n /** Removes the given expression from order by. */\r\n public removeOrderBy(expr: SQExpr): SemanticQuery {\r\n let sorts = this.orderBy();\r\n for (let i = sorts.length - 1; i >= 0; i--) {\r\n if (SQExpr.equals(sorts[i].expr, expr))\r\n sorts.splice(i, 1);\r\n }\r\n\r\n return SemanticQuery.createWithTrimmedFrom(this.fromValue.clone(), this.whereItems, sorts, this.selectItems, this.groupByItems);\r\n }\r\n\r\n public selectNameOf(expr: SQExpr): string {\r\n let index = SQExprUtils.indexOfExpr(_.map(this.selectItems, s => s.expr), expr);\r\n if (index >= 0)\r\n return this.selectItems[index].name;\r\n }\r\n\r\n public setSelectAt(index: number, expr: SQExpr): SemanticQuery {\r\n debug.assertValue(expr, 'expr');\r\n\r\n if (index >= this.selectItems.length)\r\n return;\r\n\r\n let select = this.select(),\r\n from = this.fromValue.clone(),\r\n originalName = select[index].name;\r\n select[index] = {\r\n name: originalName,\r\n expr: SQExprRewriterWithSourceRenames.rewrite(expr, from)\r\n };\r\n\r\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, select, this.groupByItems);\r\n }\r\n\r\n /** Adds a the expression to the select clause. */\r\n public addSelect(expr: SQExpr, exprName?: string): SemanticQuery {\r\n debug.assertValue(expr, 'expr');\r\n\r\n let selectItems = this.select(),\r\n from = this.fromValue.clone();\r\n selectItems.push(this.createNamedExpr(selectItems, from, expr, exprName));\r\n\r\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, selectItems, this.groupByItems);\r\n }\r\n\r\n private createNamedExpr(currentNames: ArrayNamedItems<NamedSQExpr>, from: SQFrom, expr: SQExpr, exprName?: string): NamedSQExpr{\r\n return {\r\n name: SQExprUtils.uniqueName(currentNames, expr, exprName),\r\n expr: SQExprRewriterWithSourceRenames.rewrite(expr, from)\r\n };\r\n } \r\n\r\n /** Returns a query equivalent to this, with the specified groupBy items. */\r\n groupBy(values: NamedSQExpr[]): SemanticQuery;\r\n /** Gets the groupby items in this query. */\r\n groupBy(): ArrayNamedItems<NamedSQExpr>;\r\n public groupBy(values?: NamedSQExpr[]): any {\r\n if (_.isEmpty(arguments))\r\n return this.getGroupBy();\r\n\r\n return this.setGroupBy(values);\r\n }\r\n\r\n private getGroupBy(): ArrayNamedItems<NamedSQExpr> {\r\n return SemanticQuery.createNamedExpressionArray(this.groupByItems);\r\n }\r\n\r\n private setGroupBy(values: NamedSQExpr[]): SemanticQuery {\r\n let from = this.fromValue.clone();\r\n let groupByItems = SemanticQuery.rewriteExpressionsWithSourceRenames(values, from);\r\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, this.selectItems, groupByItems);\r\n }\r\n\r\n public addGroupBy(expr: SQExpr): SemanticQuery {\r\n debug.assertValue(expr, 'expr');\r\n\r\n let groupByItems = this.groupBy(),\r\n from = this.fromValue.clone();\r\n groupByItems.push(this.createNamedExpr(groupByItems, from, expr));\r\n\r\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, this.orderByItems, this.selectItems, groupByItems);\r\n }\r\n\r\n /** Gets or sets the sorting for this query. */\r\n orderBy(values: SQSortDefinition[]): SemanticQuery;\r\n orderBy(): SQSortDefinition[];\r\n\r\n public orderBy(values?: SQSortDefinition[]): any {\r\n if (_.isEmpty(arguments))\r\n return this.getOrderBy();\r\n\r\n return this.setOrderBy(values);\r\n }\r\n\r\n private getOrderBy(): SQSortDefinition[] {\r\n let result: SQSortDefinition[] = [];\r\n\r\n let orderBy = this.orderByItems;\r\n if (orderBy) {\r\n for (let i = 0, len = orderBy.length; i < len; i++) {\r\n let clause = orderBy[i];\r\n\r\n result.push({\r\n expr: clause.expr,\r\n direction: clause.direction,\r\n });\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private setOrderBy(values: SQSortDefinition[]): SemanticQuery {\r\n debug.assertValue(values, 'values');\r\n\r\n let updatedOrderBy: SQSortDefinition[] = [],\r\n from = this.fromValue.clone();\r\n for (let i = 0, len = values.length; i < len; i++) {\r\n let clause = values[i];\r\n updatedOrderBy.push({\r\n expr: SQExprRewriterWithSourceRenames.rewrite(clause.expr, from),\r\n direction: clause.direction,\r\n });\r\n }\r\n\r\n return SemanticQuery.createWithTrimmedFrom(from, this.whereItems, updatedOrderBy, this.selectItems, this.groupByItems);\r\n }\r\n\r\n /** Gets or sets the filters for this query. */\r\n where(values: SQFilter[]): SemanticQuery;\r\n where(): SQFilter[];\r\n\r\n public where(values?: SQFilter[]): any {\r\n if (_.isEmpty(arguments))\r\n return this.getWhere();\r\n\r\n return this.setWhere(values);\r\n }\r\n\r\n private getWhere(): SQFilter[] {\r\n let result: SQFilter[] = [];\r\n\r\n let whereItems = this.whereItems;\r\n if (whereItems) {\r\n for (let i = 0, len = whereItems.length; i < len; i++)\r\n result.push(whereItems[i]);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private setWhere(values: SQFilter[]): SemanticQuery {\r\n debug.assertValue(values, 'values');\r\n\r\n let updatedWhere: SQFilter[] = [],\r\n from = this.fromValue.clone();\r\n for (let i = 0, len = values.length; i < len; i++) {\r\n let filter = values[i];\r\n let updatedFilter: SQFilter = {\r\n condition: SQExprRewriterWithSourceRenames.rewrite(filter.condition, from),\r\n };\r\n\r\n let filterTarget = filter.target;\r\n if (filterTarget) {\r\n updatedFilter.target = [];\r\n for (let j = 0, jlen = filterTarget.length; j < jlen; j++)\r\n if (filterTarget[j]) {\r\n let updatedTarget = SQExprRewriterWithSourceRenames.rewrite(filterTarget[j], from);\r\n updatedFilter.target.push(updatedTarget);\r\n }\r\n }\r\n\r\n updatedWhere.push(updatedFilter);\r\n }\r\n\r\n return SemanticQuery.createWithTrimmedFrom(from, updatedWhere, this.orderByItems, this.selectItems, this.groupByItems);\r\n }\r\n\r\n public addWhere(filter: SemanticFilter): SemanticQuery {\r\n debug.assertValue(filter, 'filter');\r\n\r\n let updatedWhere: SQFilter[] = this.where(),\r\n incomingWhere: SQFilter[] = filter.where(),\r\n from = this.fromValue.clone();\r\n\r\n for (let i = 0, len = incomingWhere.length; i < len; i++) {\r\n let clause = incomingWhere[i];\r\n\r\n let updatedClause: SQFilter = {\r\n condition: SQExprRewriterWithSourceRenames.rewrite(clause.condition, from),\r\n };\r\n\r\n if (clause.target)\r\n updatedClause.target = _.map(clause.target, t => SQExprRewriterWithSourceRenames.rewrite(t, from));\r\n\r\n updatedWhere.push(updatedClause);\r\n }\r\n\r\n return SemanticQuery.createWithTrimmedFrom(from, updatedWhere, this.orderByItems, this.selectItems, this.groupByItems);\r\n }\r\n\r\n public rewrite(exprRewriter: ISQExprVisitor<SQExpr>): SemanticQuery {\r\n let rewriter = new SemanticQueryRewriter(exprRewriter);\r\n let from = rewriter.rewriteFrom(this.fromValue);\r\n let where = rewriter.rewriteWhere(this.whereItems, from);\r\n let orderBy = rewriter.rewriteOrderBy(this.orderByItems, from);\r\n let select = rewriter.rewriteSelect(this.selectItems, from);\r\n let groupBy = rewriter.rewriteGroupBy(this.groupByItems, from);\r\n\r\n return SemanticQuery.createWithTrimmedFrom(from, where, orderBy, select, groupBy);\r\n }\r\n }\r\n\r\n /** Represents a semantic filter condition. Round-trippable with a JSON FilterDefinition. Instances of this class are immutable. */\r\n export class SemanticFilter implements ISemanticFilter {\r\n private fromValue: SQFrom;\r\n private whereItems: SQFilter[];\r\n\r\n constructor(from: SQFrom, where: SQFilter[]) {\r\n debug.assertValue(from, 'from');\r\n debug.assertValue(where, 'where');\r\n\r\n this.fromValue = from;\r\n this.whereItems = where;\r\n }\r\n\r\n public static fromSQExpr(contract: SQExpr): SemanticFilter {\r\n debug.assertValue(contract, 'contract');\r\n\r\n let from = new SQFrom();\r\n\r\n let rewrittenContract = SQExprRewriterWithSourceRenames.rewrite(contract, from);\r\n // DEVNOTE targets of some filters are visual specific and will get resolved only during query generation.\r\n // Thus not setting a target here.\r\n let where: SQFilter[] = [{\r\n condition: rewrittenContract\r\n }];\r\n\r\n return new SemanticFilter(from, where);\r\n }\r\n\r\n public static getDefaultValueFilter(fieldSQExprs: SQExpr | SQExpr[]): SemanticFilter {\r\n return SemanticFilter.getDataViewScopeIdentityComparisonFilters(fieldSQExprs, SQExprBuilder.defaultValue());\r\n }\r\n\r\n public static getAnyValueFilter(fieldSQExprs: SQExpr | SQExpr[]): SemanticFilter {\r\n return SemanticFilter.getDataViewScopeIdentityComparisonFilters(fieldSQExprs, SQExprBuilder.anyValue());\r\n }\r\n\r\n private static getDataViewScopeIdentityComparisonFilters(fieldSQExprs: SQExpr | SQExpr[], value: SQExpr): SemanticFilter {\r\n debug.assertValue(fieldSQExprs, 'fieldSQExprs');\r\n debug.assertValue(value, 'value');\r\n\r\n if (fieldSQExprs instanceof Array) {\r\n let values: SQConstantExpr[] = Array.apply(null, Array(fieldSQExprs.length)).map(() => { return value; });\r\n return SemanticFilter.fromSQExpr(SQExprUtils.getDataViewScopeIdentityComparisonExpr(<SQExpr[]>fieldSQExprs, values));\r\n }\r\n\r\n return SemanticFilter.fromSQExpr(SQExprBuilder.equal(<SQExpr>fieldSQExprs, value));\r\n }\r\n\r\n public from(): SQFrom {\r\n return this.fromValue.clone();\r\n }\r\n\r\n public conditions(): SQExpr[] {\r\n let expressions: SQExpr[] = [];\r\n\r\n let where = this.whereItems;\r\n for (let i = 0, len = where.length; i < len; i++) {\r\n let filter = where[i];\r\n expressions.push(filter.condition);\r\n }\r\n return expressions;\r\n }\r\n\r\n public where(): SQFilter[] {\r\n let result: SQFilter[] = [];\r\n\r\n let whereItems = this.whereItems;\r\n for (let i = 0, len = whereItems.length; i < len; i++)\r\n result.push(whereItems[i]);\r\n\r\n return result;\r\n }\r\n\r\n public rewrite(exprRewriter: ISQExprVisitor<SQExpr>): SemanticFilter {\r\n let rewriter = new SemanticQueryRewriter(exprRewriter);\r\n let from = rewriter.rewriteFrom(this.fromValue);\r\n let where = rewriter.rewriteWhere(this.whereItems, from);\r\n\r\n return new SemanticFilter(from, where);\r\n }\r\n\r\n public validate(schema: FederatedConceptualSchema, aggrUtils: ISQAggregationOperations, errors?: SQExprValidationError[]): SQExprValidationError[] {\r\n let validator = new SQExprValidationVisitor(schema, aggrUtils, errors);\r\n this.rewrite(validator);\r\n return validator.errors;\r\n }\r\n\r\n /** Merges a list of SemanticFilters into one. */\r\n public static merge(filters: SemanticFilter[]): SemanticFilter {\r\n if (_.isEmpty(filters))\r\n return null;\r\n\r\n if (filters.length === 1)\r\n return filters[0];\r\n\r\n let firstFilter = filters[0];\r\n let from = firstFilter.from(),\r\n where: SQFilter[] = ArrayExtensions.take(firstFilter.whereItems, firstFilter.whereItems.length);\r\n\r\n for (let i = 1, len = filters.length; i < len; i++)\r\n SemanticFilter.applyFilter(filters[i], from, where);\r\n\r\n return new SemanticFilter(from, where);\r\n }\r\n\r\n public static isDefaultFilter(filter: SemanticFilter): boolean {\r\n if (!filter || filter.where().length !== 1)\r\n return false;\r\n\r\n return SQExprUtils.isDefaultValue(filter.where()[0].condition);\r\n }\r\n\r\n public static isAnyFilter(filter: SemanticFilter): boolean {\r\n if (!filter || filter.where().length !== 1)\r\n return false;\r\n\r\n return SQExprUtils.isAnyValue(filter.where()[0].condition);\r\n }\r\n\r\n public static isSameFilter(leftFilter: SemanticFilter, rightFilter: SemanticFilter): boolean {\r\n if (jsCommon.JsonComparer.equals<SemanticFilter>(leftFilter, rightFilter)) {\r\n return !((SemanticFilter.isDefaultFilter(leftFilter) && SemanticFilter.isAnyFilter(rightFilter))\r\n || (SemanticFilter.isAnyFilter(leftFilter) && SemanticFilter.isDefaultFilter(rightFilter)));\r\n }\r\n return false;\r\n }\r\n\r\n private static applyFilter(filter: SemanticFilter, from: SQFrom, where: SQFilter[]): void {\r\n debug.assertValue(filter, 'filter');\r\n debug.assertValue(from, 'from');\r\n debug.assertValue(where, 'where');\r\n\r\n // Where\r\n let filterWhereItems = filter.whereItems;\r\n for (let i = 0; i < filterWhereItems.length; i++) {\r\n let filterWhereItem = filterWhereItems[i];\r\n\r\n let updatedWhereItem: SQFilter = {\r\n condition: SQExprRewriterWithSourceRenames.rewrite(filterWhereItem.condition, from),\r\n };\r\n\r\n if (filterWhereItem.target)\r\n updatedWhereItem.target = _.map(filterWhereItem.target, e => SQExprRewriterWithSourceRenames.rewrite(e, from));\r\n\r\n where.push(updatedWhereItem);\r\n }\r\n }\r\n }\r\n\r\n /** Represents a SemanticQuery/SemanticFilter from clause. */\r\n export class SQFrom {\r\n private items: { [name: string]: SQFromEntitySource };\r\n\r\n constructor(items?: { [name: string]: SQFromEntitySource }) {\r\n this.items = items || {};\r\n }\r\n\r\n public keys(): string[] {\r\n return Object.keys(this.items);\r\n }\r\n\r\n public entity(key: string): SQFromEntitySource {\r\n return this.items[key];\r\n }\r\n\r\n public ensureEntity(entity: SQFromEntitySource, desiredVariableName?: string): QueryFromEnsureEntityResult {\r\n debug.assertValue(entity, 'entity');\r\n\r\n // 1) Reuse a reference to the entity among the already referenced\r\n let keys = this.keys();\r\n for (let i = 0, len = keys.length; i < len; i++) {\r\n let key = keys[i],\r\n item = this.items[key];\r\n if (item && entity.entity === item.entity && entity.schema === item.schema)\r\n return { name: key };\r\n }\r\n\r\n // 2) Add a reference to the entity\r\n let candidateName = desiredVariableName || this.candidateName(entity.entity),\r\n uniqueName: string = candidateName,\r\n i = 2;\r\n while (this.items[uniqueName]) {\r\n uniqueName = candidateName + i++;\r\n }\r\n\r\n this.items[uniqueName] = entity;\r\n return { name: uniqueName, new: true };\r\n }\r\n\r\n public remove(key: string): void {\r\n delete this.items[key];\r\n }\r\n\r\n /** Converts the entity name into a short reference name. Follows the Semantic Query convention of a short name. */\r\n private candidateName(ref: string): string {\r\n debug.assertValue(ref, 'ref');\r\n\r\n let idx = ref.lastIndexOf('.');\r\n if (idx >= 0 && (idx !== ref.length - 1))\r\n ref = ref.substr(idx + 1);\r\n\r\n return ref.substring(0, 1).toLowerCase();\r\n }\r\n\r\n public clone(): SQFrom {\r\n // NOTE: consider deprecating this method and instead making QueryFrom be CopyOnWrite (currently we proactively clone).\r\n let cloned = new SQFrom();\r\n\r\n // NOTE: we use extend rather than prototypical inheritance on items because we use Object.keys.\r\n $.extend(cloned.items, this.items);\r\n\r\n return cloned;\r\n }\r\n }\r\n\r\n export class SQExprRewriterWithSourceRenames extends SQExprRewriter {\r\n private renames: SQSourceRenames;\r\n\r\n constructor(renames: SQSourceRenames) {\r\n debug.assertValue(renames, 'renames');\r\n\r\n super();\r\n this.renames = renames;\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): SQExpr {\r\n let updatedName = this.renames[expr.entity];\r\n\r\n if (updatedName)\r\n return new SQEntityExpr(expr.schema, expr.entity, updatedName);\r\n\r\n return super.visitEntity(expr);\r\n }\r\n\r\n public rewriteFilter(filter: SQFilter): SQFilter {\r\n debug.assertValue(filter, 'filter');\r\n\r\n let updatedTargets = undefined;\r\n if (filter.target)\r\n updatedTargets = this.rewriteArray(filter.target);\r\n\r\n let updatedCondition = filter.condition.accept(this);\r\n\r\n if (filter.condition === updatedCondition && filter.target === updatedTargets)\r\n return filter;\r\n\r\n let updatedFilter: SQFilter = {\r\n condition: updatedCondition,\r\n };\r\n\r\n if (updatedTargets)\r\n updatedFilter.target = updatedTargets;\r\n\r\n return updatedFilter;\r\n }\r\n\r\n public rewriteArray(exprs: SQExpr[]): SQExpr[] {\r\n debug.assertValue(exprs, 'exprs');\r\n\r\n let updatedExprs: SQExpr[];\r\n\r\n for (let i = 0, len = exprs.length; i < len; i++) {\r\n let expr = exprs[i],\r\n rewrittenExpr = expr.accept(this);\r\n\r\n if (expr !== rewrittenExpr && !updatedExprs)\r\n updatedExprs = ArrayExtensions.take(exprs, i);\r\n\r\n if (updatedExprs)\r\n updatedExprs.push(rewrittenExpr);\r\n }\r\n\r\n return updatedExprs || exprs;\r\n }\r\n\r\n public static rewrite(expr: SQExpr, from: SQFrom): SQExpr {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(from, 'from');\r\n\r\n let renames = QuerySourceRenameDetector.run(expr, from);\r\n let rewriter = new SQExprRewriterWithSourceRenames(renames);\r\n return expr.accept(rewriter);\r\n }\r\n }\r\n\r\n /** Responsible for updating a QueryFrom based on SQExpr references. */\r\n class QuerySourceRenameDetector extends DefaultSQExprVisitorWithTraversal {\r\n private from: SQFrom;\r\n private renames: SQSourceRenames;\r\n\r\n public static run(expr: SQExpr, from: SQFrom): SQSourceRenames {\r\n let detector = new QuerySourceRenameDetector(from);\r\n expr.accept(detector);\r\n\r\n return detector.renames;\r\n }\r\n\r\n constructor(from: SQFrom) {\r\n debug.assertValue(from, 'from');\r\n super();\r\n\r\n this.from = from;\r\n this.renames = {};\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): void {\r\n // TODO: Renames must take the schema into account, not just entity set name.\r\n let existingEntity = this.from.entity(expr.variable);\r\n if (existingEntity && existingEntity.schema === expr.schema && existingEntity.entity === expr.entity)\r\n return;\r\n\r\n let actualEntity = this.from.ensureEntity(\r\n {\r\n schema: expr.schema,\r\n entity: expr.entity,\r\n },\r\n expr.variable);\r\n\r\n this.renames[expr.entity] = actualEntity.name;\r\n }\r\n }\r\n\r\n /** Visitor for finding unreferenced sources. */\r\n class UnreferencedKeyFinder extends DefaultSQExprVisitorWithTraversal {\r\n private keys: string[];\r\n\r\n constructor(keys: string[]) {\r\n debug.assertValue(keys, 'keys');\r\n\r\n super();\r\n this.keys = keys;\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): void {\r\n let index = this.keys.indexOf(expr.variable);\r\n if (index >= 0)\r\n this.keys.splice(index, 1);\r\n }\r\n\r\n public result(): string[] {\r\n return this.keys;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import DataViewTransform = powerbi.data.DataViewTransform;\r\n import SQExprBuilder = powerbi.data.SQExprBuilder;\r\n\r\n /** Utility for creating a DataView from columns of data. */\r\n export interface IDataViewBuilderCategorical {\r\n withCategory(options: DataViewBuilderCategoryColumnOptions): IDataViewBuilderCategorical;\r\n withCategories(categories: DataViewCategoryColumn[]): IDataViewBuilderCategorical;\r\n withValues(options: DataViewBuilderValuesOptions): IDataViewBuilderCategorical;\r\n withGroupedValues(options: DataViewBuilderGroupedValuesOptions): IDataViewBuilderCategorical;\r\n\r\n build(): DataView;\r\n }\r\n\r\n export interface DataViewBuilderColumnOptions {\r\n source: DataViewMetadataColumn;\r\n }\r\n\r\n export interface DataViewBuilderCategoryColumnOptions extends DataViewBuilderColumnOptions {\r\n values: PrimitiveValue[];\r\n identityFrom: DataViewBuilderColumnIdentitySource;\r\n }\r\n\r\n export interface DataViewBuilderValuesOptions {\r\n columns: DataViewBuilderValuesColumnOptions[];\r\n }\r\n\r\n export interface DataViewBuilderGroupedValuesOptions {\r\n groupColumn: DataViewBuilderCategoryColumnOptions;\r\n valueColumns: DataViewBuilderColumnOptions[];\r\n data: DataViewBuilderSeriesData[][];\r\n }\r\n\r\n /** Indicates the source set of identities. */\r\n export interface DataViewBuilderColumnIdentitySource {\r\n fields: SQExpr[];\r\n identities?: DataViewScopeIdentity[];\r\n }\r\n\r\n export interface DataViewBuilderValuesColumnOptions extends DataViewBuilderColumnOptions, DataViewBuilderSeriesData {\r\n }\r\n\r\n export interface DataViewBuilderSeriesData {\r\n values: PrimitiveValue[];\r\n highlights?: PrimitiveValue[];\r\n\r\n /** Client-computed maximum value for a column. */\r\n maxLocal?: any;\r\n\r\n /** Client-computed maximum value for a column. */\r\n minLocal?: any;\r\n }\r\n\r\n export function createCategoricalDataViewBuilder(): IDataViewBuilderCategorical {\r\n return new CategoricalDataViewBuilder();\r\n }\r\n\r\n interface ColumnMetadata {\r\n column: DataViewMetadataColumn;\r\n identityFrom: DataViewBuilderColumnIdentitySource;\r\n values: PrimitiveValue[];\r\n }\r\n\r\n class CategoricalDataViewBuilder implements IDataViewBuilderCategorical {\r\n private categories: DataViewCategoryColumn[];\r\n private staticMeasureColumns: DataViewMetadataColumn[];\r\n private dynamicMeasureColumns: DataViewMetadataColumn[];\r\n private dynamicSeriesMetadata: ColumnMetadata;\r\n private columnIndex: number;\r\n private staticSeriesValues: DataViewBuilderValuesColumnOptions[];\r\n private dynamicSeriesValues: DataViewBuilderSeriesData[][];\r\n\r\n constructor() {\r\n this.categories = [];\r\n this.staticMeasureColumns = [];\r\n this.dynamicMeasureColumns = [];\r\n this.columnIndex = 0;\r\n }\r\n\r\n public withCategory(options: DataViewBuilderCategoryColumnOptions): IDataViewBuilderCategorical {\r\n let categoryValues = options.values,\r\n identityFrom = options.identityFrom,\r\n type = options.source.type;\r\n\r\n let categoryColumn: DataViewCategoryColumn = {\r\n source: options.source,\r\n identityFields: options.identityFrom.fields,\r\n identity: options.identityFrom.identities || [],\r\n values: categoryValues,\r\n };\r\n\r\n if (!options.identityFrom.identities) {\r\n for (let categoryIndex = 0, categoryLength = categoryValues.length; categoryIndex < categoryLength; categoryIndex++) {\r\n categoryColumn.identity.push(\r\n getScopeIdentity(identityFrom, categoryIndex, categoryValues[categoryIndex], type));\r\n }\r\n }\r\n\r\n if (!this.categories)\r\n this.categories = [];\r\n\r\n this.categories.push(categoryColumn);\r\n\r\n return this;\r\n }\r\n\r\n public withCategories(categories: DataViewCategoryColumn[]): IDataViewBuilderCategorical {\r\n if (_.isEmpty(this.categories))\r\n this.categories = categories;\r\n else\r\n Array.prototype.push.apply(this.categories, categories);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Adds static series columns.\r\n *\r\n * Note that it is illegal to have both dynamic series and static series in a visual DataViewCategorical. It is only legal to have them both in \r\n * a query DataViewCategorical, where DataViewTransform is expected to split them up into separate visual DataViewCategorical objects.\r\n */\r\n public withValues(options: DataViewBuilderValuesOptions): IDataViewBuilderCategorical {\r\n debug.assertValue(options, 'options');\r\n\r\n let columns = options.columns;\r\n debug.assertValue(columns, 'columns');\r\n\r\n for (let column of columns) {\r\n this.staticMeasureColumns.push(column.source);\r\n }\r\n\r\n this.staticSeriesValues = columns;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Adds dynamic series columns.\r\n *\r\n * Note that it is illegal to have both dynamic series and static series in a visual DataViewCategorical. It is only legal to have them both in \r\n * a query DataViewCategorical, where DataViewTransform is expected to split them up into separate visual DataViewCategorical objects.\r\n */\r\n public withGroupedValues(options: DataViewBuilderGroupedValuesOptions): IDataViewBuilderCategorical {\r\n debug.assertValue(options, 'options');\r\n\r\n let groupColumn = options.groupColumn;\r\n debug.assertValue(groupColumn, 'groupColumn');\r\n\r\n this.dynamicSeriesMetadata = {\r\n column: groupColumn.source,\r\n identityFrom: groupColumn.identityFrom,\r\n values: groupColumn.values,\r\n };\r\n\r\n let valueColumns = options.valueColumns;\r\n for (let valueColumn of valueColumns) {\r\n this.dynamicMeasureColumns.push(valueColumn.source);\r\n }\r\n\r\n this.dynamicSeriesValues = options.data;\r\n\r\n return this;\r\n }\r\n\r\n private fillData(dataViewValues: DataViewValueColumns) {\r\n let categoryColumn = _.first(this.categories);\r\n let categoryLength = (categoryColumn && categoryColumn.values) ? categoryColumn.values.length : 1;\r\n\r\n if (this.hasDynamicSeries) {\r\n for (let seriesIndex = 0; seriesIndex < this.dynamicSeriesMetadata.values.length; seriesIndex++) {\r\n let seriesMeasures = this.dynamicSeriesValues[seriesIndex];\r\n debug.assert(seriesMeasures.length === this.dynamicMeasureColumns.length, 'seriesMeasures.length === this.dynamicMeasureColumns.length');\r\n\r\n for (let measureIndex = 0, measuresLen = this.dynamicMeasureColumns.length; measureIndex < measuresLen; measureIndex++) {\r\n let groupIndex = seriesIndex * measuresLen + measureIndex;\r\n\r\n applySeriesData(dataViewValues[groupIndex], seriesMeasures[measureIndex], categoryLength);\r\n }\r\n }\r\n }\r\n\r\n if (this.hasStaticSeries) {\r\n // Note: when the target categorical has both dynamic and static series, append static measures at the end of the values array.\r\n let staticColumnsStartingIndex = this.hasDynamicSeries ? (this.dynamicSeriesValues.length * this.dynamicMeasureColumns.length) : 0;\r\n\r\n for (let measureIndex = 0, measuresLen = this.staticMeasureColumns.length; measureIndex < measuresLen; measureIndex++) {\r\n applySeriesData(dataViewValues[staticColumnsStartingIndex + measureIndex], this.staticSeriesValues[measureIndex], categoryLength);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the DataView with metadata and DataViewCategorical.\r\n * Returns undefined if the combination of parameters is illegal, such as having both dynamic series and static series when building a visual DataView.\r\n */\r\n public build(): DataView {\r\n let metadataColumns: DataViewMetadataColumn[] = [];\r\n let categorical: DataViewCategorical = {};\r\n\r\n let categoryMetadata = this.categories;\r\n let dynamicSeriesMetadata = this.dynamicSeriesMetadata;\r\n\r\n // --- Build metadata columns and value groups ---\r\n for (let columnMetadata of categoryMetadata) {\r\n pushIfNotExists(metadataColumns, columnMetadata.source);\r\n }\r\n\r\n if (this.hasDynamicSeries) {\r\n // Dynamic series, or Dyanmic & Static series.\r\n pushIfNotExists(metadataColumns, dynamicSeriesMetadata.column);\r\n\r\n categorical.values = DataViewTransform.createValueColumns([], dynamicSeriesMetadata.identityFrom.fields, dynamicSeriesMetadata.column);\r\n\r\n // For each series value we will make one column per measure\r\n let seriesValues = dynamicSeriesMetadata.values;\r\n for (let seriesIndex = 0; seriesIndex < seriesValues.length; seriesIndex++) {\r\n let seriesValue = seriesValues[seriesIndex];\r\n let seriesIdentity = getScopeIdentity(dynamicSeriesMetadata.identityFrom, seriesIndex, seriesValue, dynamicSeriesMetadata.column.type);\r\n\r\n for (let measure of this.dynamicMeasureColumns) {\r\n let column = _.clone(measure);\r\n column.groupName = <string>seriesValue;\r\n\r\n pushIfNotExists(metadataColumns, column);\r\n categorical.values.push({\r\n source: column,\r\n values: [],\r\n identity: seriesIdentity,\r\n });\r\n }\r\n }\r\n\r\n if (this.hasStaticSeries) {\r\n // IMPORTANT: In the Dyanmic & Static series case, the groups array shall not include any static group. This is to match the behavior of dsrReader.\r\n // Get the current return value of grouped() before adding static measure columns, an use that as the return value of this categorical.\r\n // Otherwise, the default behavior of DataViewValueColumns.grouped() from DataViewTransform.createValueColumns() is to create series groups from all measure columns.\r\n let dynamicSeriesGroups = categorical.values.grouped();\r\n categorical.values.grouped = () => dynamicSeriesGroups;\r\n\r\n this.appendStaticMeasureColumns(metadataColumns, categorical.values);\r\n }\r\n }\r\n else {\r\n // Static series only / no series\r\n categorical.values = DataViewTransform.createValueColumns();\r\n this.appendStaticMeasureColumns(metadataColumns, categorical.values);\r\n }\r\n\r\n let categories = this.categories;\r\n if (!_.isEmpty(categories))\r\n categorical.categories = categories;\r\n\r\n // --- Fill in data point values ---\r\n this.fillData(categorical.values);\r\n\r\n let dataView: DataView = {\r\n metadata: {\r\n columns: metadataColumns,\r\n },\r\n categorical: categorical,\r\n };\r\n\r\n if (this.isLegalDataView(dataView)) {\r\n return dataView;\r\n }\r\n }\r\n\r\n private appendStaticMeasureColumns(metadataColumns: DataViewMetadataColumn[], valueColumns: DataViewValueColumns): void {\r\n debug.assertValue(metadataColumns, 'metadataColumns');\r\n debug.assertValue(valueColumns, 'valueColumns');\r\n\r\n if (!_.isEmpty(this.staticMeasureColumns)) {\r\n for (let column of this.staticMeasureColumns) {\r\n pushIfNotExists(metadataColumns, column);\r\n valueColumns.push({\r\n source: column,\r\n values: [],\r\n });\r\n }\r\n }\r\n }\r\n\r\n private isLegalDataView(dataView: DataView): boolean {\r\n if (this.hasDynamicSeries && this.hasStaticSeries && CategoricalDataViewBuilder.isVisualDataView(dataView.metadata.columns)) {\r\n // It is illegal to have both dynamic series and static series in a visual DataViewCategorical,\r\n // because the DataViewValueColumns interface today cannot express that 100% (see its 'source' property and return value of its 'grouped()' function).\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * This function infers that if any metdata column has 'queryName', \r\n * then the user of this builder is building a visual DataView (as opposed to query DataView).\r\n *\r\n * @param metadataColumns The complete collection of metadata columns in the categorical.\r\n */\r\n private static isVisualDataView(metadataColumns: DataViewMetadataColumn[]): boolean {\r\n return !_.isEmpty(metadataColumns) &&\r\n _.any(metadataColumns, (metadataColumn) => !!metadataColumn.queryName);\r\n }\r\n\r\n private get hasDynamicSeries(): boolean {\r\n return !!this.dynamicSeriesMetadata; // In Map visual scenarios, you can have dynamic series without measure columns\r\n }\r\n\r\n private get hasStaticSeries(): boolean {\r\n return !!this.staticSeriesValues;\r\n }\r\n }\r\n\r\n function getScopeIdentity(\r\n source: DataViewBuilderColumnIdentitySource,\r\n index: number,\r\n value: PrimitiveValue,\r\n valueType: ValueTypeDescriptor): DataViewScopeIdentity {\r\n let identities = source.identities;\r\n if (identities) {\r\n return identities[index];\r\n }\r\n\r\n debug.assert(source.fields && source.fields.length === 1, 'Inferring identity, expect exactly one field.');\r\n\r\n return createDataViewScopeIdentity(\r\n SQExprBuilder.equal(\r\n source.fields[0],\r\n SQExprBuilder.typedConstant(value, valueType)));\r\n }\r\n\r\n function pushIfNotExists(items: DataViewMetadataColumn[], itemToAdd: DataViewMetadataColumn): void {\r\n if (_.contains(items, itemToAdd))\r\n return;\r\n\r\n items.push(itemToAdd);\r\n }\r\n\r\n function applySeriesData(target: DataViewValueColumn, source: DataViewBuilderSeriesData, categoryLength: number): void {\r\n debug.assertValue(target, 'target');\r\n debug.assertValue(source, 'source');\r\n debug.assertValue(categoryLength, 'categoryLength');\r\n\r\n let values = source.values;\r\n debug.assert(categoryLength === values.length, 'categoryLength === values.length');\r\n\r\n target.values = values;\r\n\r\n let highlights = source.highlights;\r\n if (highlights) {\r\n debug.assert(categoryLength === highlights.length, 'categoryLength === highlights.length');\r\n\r\n target.highlights = highlights;\r\n }\r\n\r\n let aggregates: DataViewColumnAggregates;\r\n if (source.minLocal !== undefined) {\r\n if (!aggregates)\r\n aggregates = {};\r\n\r\n aggregates.minLocal = source.minLocal;\r\n }\r\n\r\n if (source.maxLocal !== undefined) {\r\n if (!aggregates)\r\n aggregates = {};\r\n\r\n aggregates.maxLocal = source.maxLocal;\r\n }\r\n\r\n if (aggregates) {\r\n target.source.aggregates = aggregates;\r\n _.extend(target, aggregates);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n import SQExpr = powerbi.data.SQExpr;\r\n\r\n export function createStaticEvalContext(colorAllocatorCache?: IColorAllocatorCache): IEvalContext;\r\n export function createStaticEvalContext(colorAllocatorCache: IColorAllocatorCache, dataView: DataView, selectTransforms: DataViewSelectTransform[]): IEvalContext;\r\n export function createStaticEvalContext(colorAllocatorCache: IColorAllocatorCache, dataView?: DataView, selectTransforms?: DataViewSelectTransform[]): IEvalContext {\r\n return new StaticEvalContext(\r\n colorAllocatorCache || createColorAllocatorCache(),\r\n dataView || { metadata: { columns: [] } },\r\n selectTransforms);\r\n }\r\n\r\n /**\r\n * Represents an eval context over a potentially empty DataView. Only static repetition data view objects\r\n * are supported.\r\n */\r\n class StaticEvalContext implements IEvalContext {\r\n private colorAllocatorCache: IColorAllocatorCache;\r\n private dataView: DataView;\r\n private selectTransforms: DataViewSelectTransform[];\r\n\r\n constructor(colorAllocatorCache: IColorAllocatorCache, dataView: DataView, selectTransforms: DataViewSelectTransform[]) {\r\n debug.assertValue(colorAllocatorCache, 'colorAllocatorCache');\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertAnyValue(selectTransforms, 'selectTransforms');\r\n\r\n this.colorAllocatorCache = colorAllocatorCache;\r\n this.dataView = dataView;\r\n this.selectTransforms = selectTransforms;\r\n }\r\n\r\n public getColorAllocator(expr: SQFillRuleExpr): IColorAllocator {\r\n return this.colorAllocatorCache.get(expr);\r\n }\r\n\r\n public getExprValue(expr: SQExpr): PrimitiveValue {\r\n let dataView = this.dataView,\r\n selectTransforms = this.selectTransforms;\r\n if (dataView && dataView.table && selectTransforms)\r\n return getExprValueFromTable(expr, selectTransforms, dataView.table, /*rowIdx*/ 0);\r\n }\r\n\r\n public getRoleValue(roleName: string): PrimitiveValue {\r\n return;\r\n }\r\n }\r\n\r\n export function getExprValueFromTable(expr: SQExpr, selectTransforms: DataViewSelectTransform[], table: DataViewTable, rowIdx: number): PrimitiveValue {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(selectTransforms, 'selectTransforms');\r\n debug.assertValue(table, 'table');\r\n debug.assertValue(rowIdx, 'rowIdx');\r\n\r\n let rows = table.rows;\r\n if (_.isEmpty(rows) || rows.length <= rowIdx)\r\n return;\r\n\r\n let targetExpr = getTargetExpr(expr, selectTransforms);\r\n let cols = table.columns;\r\n for (let selectIdx = 0, selectLen = selectTransforms.length; selectIdx < selectLen; selectIdx++) {\r\n let selectTransform = selectTransforms[selectIdx];\r\n\r\n if (!SQExpr.equals(selectTransform.expr, targetExpr) || !selectTransform.queryName)\r\n continue;\r\n\r\n for (let colIdx = 0, colLen = cols.length; colIdx < colLen; colIdx++) {\r\n if (selectIdx !== cols[colIdx].index)\r\n continue;\r\n\r\n return rows[rowIdx][colIdx];\r\n }\r\n }\r\n }\r\n\r\n function getTargetExpr(expr: SQExpr, selectTransforms: DataViewSelectTransform[]): SQExpr {\r\n if (SQExpr.isSelectRef(expr)) {\r\n for (let selectTransform of selectTransforms) {\r\n if (selectTransform.queryName === expr.expressionName) {\r\n return selectTransform.expr;\r\n }\r\n }\r\n }\r\n\r\n return expr;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n export function createMatrixEvalContext(colorAllocatorProvider: IColorAllocatorCache, dataViewMatrix: DataViewMatrix): IEvalContext {\r\n // NOTE: Matrix context-sensitive evaluation is not yet implemented.\r\n return createStaticEvalContext(colorAllocatorProvider);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n import StringExtensions = jsCommon.StringExtensions;\r\n import Formatting = jsCommon.Formatting;\r\n import RegExpExtensions = jsCommon.RegExpExtensions;\r\n\r\n /** Culture interfaces. These match the Globalize library interfaces intentionally. */\r\n export interface Culture {\r\n name: string;\r\n calendar: Calendar;\r\n calendars: CalendarDictionary;\r\n numberFormat: NumberFormatInfo;\r\n }\r\n\r\n export interface Calendar {\r\n patterns: any;\r\n firstDay: number;\r\n }\r\n\r\n export interface CalendarDictionary {\r\n [key: string]: Calendar;\r\n }\r\n\r\n export interface NumberFormatInfo {\r\n decimals: number;\r\n groupSizes: number[];\r\n negativeInfinity: string;\r\n positiveInfinity: string;\r\n }\r\n\r\n /**\r\n * Creating a dummy module to declare cultureInfo string, so we could do a strongly typed usage in Visuals\r\n */\r\n declare module powerbi.common {\r\n let cultureInfo: string;\r\n }\r\n\r\n /** Formatting Encoder */\r\n module FormattingEncoder {\r\n export function preserveEscaped(format: string, specialChars: string): string {\r\n // Unicode U+E000 - U+F8FF is a private area and so we can use the chars from the range to encode the escaped sequences\r\n let length = specialChars.length;\r\n for (let i = 0; i < length; i++) {\r\n let oldText = \"\\\\\" + specialChars[i];\r\n let newText = String.fromCharCode(0xE000 + i);\r\n format = StringExtensions.replaceAll(format, oldText, newText);\r\n }\r\n return format;\r\n }\r\n\r\n export function restoreEscaped(format: string, specialChars: string): string {\r\n // After formatting is complete we should restore the encoded escaped chars into the unescaped chars\r\n let length = specialChars.length;\r\n for (let i = 0; i < length; i++) {\r\n let oldText = String.fromCharCode(0xE000 + i);\r\n let newText = specialChars[i];\r\n format = StringExtensions.replaceAll(format, oldText, newText);\r\n }\r\n return StringExtensions.replaceAll(format, \"\\\\\", \"\");\r\n }\r\n\r\n export function preserveLiterals(format: string, literals: string[]): string {\r\n // Unicode U+E000 - U+F8FF is a private area and so we can use the chars from the range to encode the escaped sequences\r\n format = StringExtensions.replaceAll(format, \"\\\"\", \"'\");\r\n for (let i = 0; ; i++) {\r\n let fromIndex = format.indexOf(\"'\");\r\n if (fromIndex < 0) {\r\n break;\r\n }\r\n let toIndex = format.indexOf(\"'\", fromIndex + 1);\r\n if (toIndex < 0) {\r\n break;\r\n }\r\n let literal = format.substring(fromIndex, toIndex + 1);\r\n literals.push(literal.substring(1, toIndex - fromIndex));\r\n let token = String.fromCharCode(0xE100 + i);\r\n format = format.replace(literal, token);\r\n }\r\n return format;\r\n }\r\n\r\n export function restoreLiterals(format: string, literals: string[]): string {\r\n let count = literals.length;\r\n for (let i = 0; i < count; i++) {\r\n let token = String.fromCharCode(0xE100 + i);\r\n let literal = literals[i];\r\n format = format.replace(token, literal);\r\n }\r\n return format;\r\n }\r\n }\r\n\r\n const IndexedTokensRegex = /({{)|(}})|{(\\d+[^}]*)}/g;\r\n const ZeroPlaceholder = '0';\r\n const DigitPlaceholder = '#';\r\n const ExponentialFormatChar = 'E';\r\n const NumericPlaceholders = [ZeroPlaceholder, DigitPlaceholder];\r\n const NumericPlaceholderRegex = new RegExp(NumericPlaceholders.join('|'), 'g');\r\n\r\n /** Formatting Service */\r\n class FormattingService implements IFormattingService {\r\n\r\n _currentCultureSelector: string;\r\n _currentCulture: Culture;\r\n _dateTimeScaleFormatInfo: DateTimeScaleFormatInfo;\r\n\r\n public formatValue(value: any, format?: string, culture?: string): string {\r\n // Handle special cases\r\n if (value === undefined || value === null) {\r\n return '';\r\n }\r\n let gculture = this.getCulture(culture);\r\n\r\n if (DateTimeFormat.canFormat(value)) {\r\n // Dates\r\n return DateTimeFormat.format(value, format, gculture);\r\n } else if (NumberFormat.canFormat(value)) {\r\n // Numbers\r\n return NumberFormat.format(value, format, gculture);\r\n } else {\r\n // Other data types - return as string\r\n return value.toString();\r\n }\r\n }\r\n\r\n public format(formatWithIndexedTokens: string, args: any[], culture?: string): string {\r\n if (!formatWithIndexedTokens) {\r\n return \"\";\r\n }\r\n let result = formatWithIndexedTokens.replace(IndexedTokensRegex, (match: string, left: string, right: string, argToken: string) => {\r\n if (left) {\r\n return \"{\";\r\n } else if (right) {\r\n return \"}\";\r\n } else {\r\n let parts = argToken.split(\":\");\r\n let argIndex = parseInt(parts[0], 10);\r\n let argFormat = parts[1];\r\n return this.formatValue(args[argIndex], argFormat, culture);\r\n }\r\n });\r\n\r\n return result;\r\n }\r\n\r\n public isStandardNumberFormat(format: string): boolean {\r\n return NumberFormat.isStandardFormat(format);\r\n }\r\n\r\n public formatNumberWithCustomOverride(value: number, format: string, nonScientificOverrideFormat: string, culture?: string): string {\r\n let gculture = this.getCulture(culture);\r\n\r\n return NumberFormat.formatWithCustomOverride(value, format, nonScientificOverrideFormat, gculture);\r\n }\r\n\r\n public dateFormatString(unit: DateTimeUnit): string {\r\n if (!this._dateTimeScaleFormatInfo)\r\n this.initialize();\r\n return this._dateTimeScaleFormatInfo.getFormatString(unit);\r\n }\r\n\r\n /**\r\n * Sets the current localization culture\r\n * @param cultureSelector - name of a culture: \"en\", \"en-UK\", \"fr-FR\" etc. (See National Language Support (NLS) for full lists. Use \"default\" for invariant culture).\r\n */\r\n private setCurrentCulture(cultureSelector: string): void {\r\n if (this._currentCultureSelector !== cultureSelector) {\r\n this._currentCulture = this.getCulture(cultureSelector);\r\n this._currentCultureSelector = cultureSelector;\r\n this._dateTimeScaleFormatInfo = new DateTimeScaleFormatInfo(this._currentCulture);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the culture assotiated with the specified cultureSelector (\"en\", \"en-US\", \"fr-FR\" etc).\r\n * @param cultureSelector - name of a culture: \"en\", \"en-UK\", \"fr-FR\" etc. (See National Language Support (NLS) for full lists. Use \"default\" for invariant culture).\r\n * Exposing this function for testability of unsupported cultures\r\n */\r\n public getCulture(cultureSelector?: string): Culture {\r\n if (cultureSelector == null) {\r\n if (this._currentCulture == null) {\r\n this.initialize();\r\n }\r\n return this._currentCulture;\r\n } else {\r\n let culture = Globalize.findClosestCulture(cultureSelector);\r\n if (!culture)\r\n culture = Globalize.culture(\"en-US\");\r\n return culture;\r\n }\r\n }\r\n\r\n /** By default the Globalization module initializes to the culture/calendar provided in the language/culture URL params */\r\n private initialize() {\r\n let cultureName = this.getCurrentCulture();\r\n this.setCurrentCulture(cultureName);\r\n let calendarName = this.getUrlParam(\"calendar\");\r\n if (calendarName) {\r\n let culture = this._currentCulture;\r\n let c = culture.calendars[calendarName];\r\n if (c) {\r\n culture.calendar = c;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Exposing this function for testability \r\n */\r\n public getCurrentCulture(): string {\r\n let urlParam = this.getUrlParam(\"language\");\r\n\r\n if (urlParam) {\r\n return urlParam;\r\n }\r\n\r\n if (powerbi && powerbi.common && powerbi.common.cultureInfo) {\r\n // Get cultureInfo set in powerbi\r\n return powerbi.common.cultureInfo;\r\n }\r\n\r\n return window.navigator.userLanguage || window.navigator[\"language\"] || Globalize.culture().name;\r\n }\r\n\r\n /**\r\n * Exposing this function for testability\r\n * @param name: queryString name\r\n */\r\n public getUrlParam(name: string): string {\r\n let param = window.location.search.match(RegExp(\"[?&]\" + name + \"=([^&]*)\"));\r\n return param ? param[1] : undefined;\r\n }\r\n }\r\n\r\n /**\r\n * DateTimeFormat module contains the static methods for formatting the DateTimes.\r\n * It extends the JQuery.Globalize functionality to support complete set of .NET\r\n * formatting expressions for dates.\r\n */\r\n module DateTimeFormat {\r\n\r\n let _currentCachedFormat: string;\r\n let _currentCachedProcessedFormat: string;\r\n\r\n /** Evaluates if the value can be formatted using the NumberFormat */\r\n export function canFormat(value: any) {\r\n let result = value instanceof Date;\r\n return result;\r\n }\r\n\r\n /** Formats the date using provided format and culture */\r\n export function format(value: Date, format: string, culture: Culture): string {\r\n format = format || \"G\";\r\n let isStandard = format.length === 1;\r\n try {\r\n if (isStandard) {\r\n return formatDateStandard(value, format, culture);\r\n } else {\r\n return formatDateCustom(value, format, culture);\r\n }\r\n } catch (e) {\r\n return formatDateStandard(value, \"G\", culture);\r\n }\r\n }\r\n\r\n /** Formats the date using standard format expression */\r\n function formatDateStandard(value: Date, format: string, culture: Culture) {\r\n // In order to provide parity with .NET we have to support additional set of DateTime patterns.\r\n let patterns = culture.calendar.patterns;\r\n // Extend supported set of patterns\r\n ensurePatterns(culture.calendar);\r\n // Handle extended set of formats\r\n let output = Formatting.findDateFormat(value, format, culture.name);\r\n if (output.format.length === 1)\r\n format = patterns[output.format];\r\n else\r\n format = output.format;\r\n //need to revisit when globalization is enabled\r\n culture = Globalize.culture(\"en-US\");\r\n return Globalize.format(output.value, format, culture);\r\n }\r\n\r\n /** Formats the date using custom format expression */\r\n function formatDateCustom(value: Date, format: string, culture: Culture): string {\r\n let result: string;\r\n let literals: string[] = [];\r\n format = FormattingEncoder.preserveEscaped(format, \"\\\\dfFghHKmstyz:/%'\\\"\");\r\n format = FormattingEncoder.preserveLiterals(format, literals);\r\n format = StringExtensions.replaceAll(format, \"\\\"\", \"'\");\r\n if (format.indexOf(\"F\") > -1) {\r\n // F is not supported so we need to replace the F with f based on the milliseconds\r\n // Replace all sequences of F longer than 3 with \"FFF\"\r\n format = StringExtensions.replaceAll(format, \"FFFF\", \"FFF\");\r\n // Based on milliseconds update the format to use fff\r\n let milliseconds = value.getMilliseconds();\r\n if (milliseconds % 10 >= 1) {\r\n format = StringExtensions.replaceAll(format, \"FFF\", \"fff\");\r\n }\r\n format = StringExtensions.replaceAll(format, \"FFF\", \"FF\");\r\n if ((milliseconds % 100) / 10 >= 1) {\r\n format = StringExtensions.replaceAll(format, \"FF\", \"ff\");\r\n }\r\n format = StringExtensions.replaceAll(format, \"FF\", \"F\");\r\n if ((milliseconds % 1000) / 100 >= 1) {\r\n format = StringExtensions.replaceAll(format, \"F\", \"f\");\r\n }\r\n format = StringExtensions.replaceAll(format, \"F\", \"\");\r\n if (format === \"\" || format === \"%\")\r\n return \"\";\r\n }\r\n format = processCustomDateTimeFormat(format);\r\n result = Globalize.format(value, format, culture);\r\n result = localize(result, culture.calendar);\r\n result = FormattingEncoder.restoreLiterals(result, literals);\r\n result = FormattingEncoder.restoreEscaped(result, \"\\\\dfFghHKmstyz:/%'\\\"\");\r\n return result;\r\n }\r\n\r\n /** Translates unsupported .NET custom format expressions to the custom expressions supported by JQuery.Globalize */\r\n function processCustomDateTimeFormat(format: string): string {\r\n if (format === _currentCachedFormat) {\r\n return _currentCachedProcessedFormat;\r\n }\r\n _currentCachedFormat = format;\r\n format = Formatting.fixDateTimeFormat(format);\r\n _currentCachedProcessedFormat = format;\r\n return format;\r\n }\r\n\r\n /** Localizes the time separator symbol */\r\n function localize(value: string, dictionary: any): string {\r\n let timeSeparator = dictionary[\":\"];\r\n if (timeSeparator === \":\") {\r\n return value;\r\n }\r\n let result = \"\";\r\n let count = value.length;\r\n for (let i = 0; i < count; i++) {\r\n let char = value.charAt(i);\r\n switch (char) {\r\n case \":\":\r\n result += timeSeparator;\r\n break;\r\n default:\r\n result += char;\r\n break;\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n function ensurePatterns(calendar: GlobalizeCalendar) {\r\n let patterns = calendar.patterns;\r\n if (patterns[\"g\"] === undefined) {\r\n patterns[\"g\"] = patterns[\"f\"].replace(patterns[\"D\"], patterns[\"d\"]); // Generic: Short date, short time\r\n patterns[\"G\"] = patterns[\"F\"].replace(patterns[\"D\"], patterns[\"d\"]); // Generic: Short date, long time\r\n }\r\n }\r\n\r\n }\r\n\r\n /**\r\n * NumberFormat module contains the static methods for formatting the numbers.\r\n * It extends the JQuery.Globalize functionality to support complete set of .NET\r\n * formatting expressions for numeric types including custom formats.\r\n */\r\n export module NumberFormat {\r\n\r\n const NonScientificFormatRegex = /^\\{.+\\}.*/;\r\n const NumericalPlaceHolderRegex = /\\{.+\\}/;\r\n const ScientificFormatRegex = /e[+-]*[0#]+/i;\r\n const StandardFormatRegex = /^[a-z]\\d{0,2}$/i; // a letter + up to 2 digits for precision specifier\r\n const TrailingZerosRegex = /0+$/;\r\n const DecimalFormatRegex = /\\.([0#]*)/g;\r\n const NumericFormatRegex = /[0#,\\.]+[0,#]*/g;\r\n const LastNumericPlaceholderRegex = /(0|#)([^(0|#)]*)$/;\r\n const DecimalFormatCharacter = '.';\r\n\r\n export const NumberFormatComponentsDelimeter = ';';\r\n\r\n export interface NumericFormatMetadata {\r\n format: string;\r\n hasEscapes: boolean;\r\n hasQuotes: boolean;\r\n hasE: boolean;\r\n hasCommas: boolean;\r\n hasDots: boolean;\r\n hasPercent: boolean;\r\n hasPermile: boolean;\r\n precision: number;\r\n scale: number;\r\n }\r\n\r\n export interface NumberFormatComponents {\r\n hasNegative: boolean;\r\n positive: string;\r\n negative: string;\r\n zero: string;\r\n }\r\n\r\n function getNonScientificFormatWithPrecision(baseFormat: string, numericFormat: string): string {\r\n if (!numericFormat || baseFormat === undefined)\r\n return baseFormat;\r\n\r\n let newFormat = \"{0:\" + numericFormat + \"}\";\r\n\r\n return baseFormat.replace(\"{0}\", newFormat);\r\n }\r\n\r\n export function getNumericFormat(value: number, baseFormat: string): string {\r\n if (baseFormat == null)\r\n return baseFormat;\r\n\r\n if (hasFormatComponents(baseFormat)) {\r\n let {positive, negative, zero} = NumberFormat.getComponents(baseFormat);\r\n\r\n if (value > 0)\r\n return getNumericFormatFromComponent(value, positive);\r\n else if (value === 0)\r\n return getNumericFormatFromComponent(value, zero);\r\n\r\n return getNumericFormatFromComponent(value, negative);\r\n }\r\n\r\n return getNumericFormatFromComponent(value, baseFormat);\r\n }\r\n\r\n function getNumericFormatFromComponent(value: number, format: string): string {\r\n let match = RegExpExtensions.run(NumericFormatRegex, format);\r\n if (match)\r\n return match[0];\r\n\r\n return format;\r\n }\r\n\r\n export function addDecimalsToFormat(baseFormat: string, decimals: number, trailingZeros: boolean): string {\r\n if (decimals == null)\r\n return baseFormat;\r\n\r\n // Default format string\r\n if (baseFormat == null)\r\n baseFormat = ZeroPlaceholder;\r\n\r\n if (hasFormatComponents(baseFormat)) {\r\n let {positive, negative, zero} = NumberFormat.getComponents(baseFormat);\r\n let formats = [positive, negative, zero];\r\n for (let i = 0; i < formats.length; i++) {\r\n // Update format in formats array\r\n formats[i] = addDecimalsToFormatComponent(formats[i], decimals, trailingZeros);\r\n }\r\n\r\n return formats.join(NumberFormat.NumberFormatComponentsDelimeter);\r\n }\r\n\r\n return addDecimalsToFormatComponent(baseFormat, decimals, trailingZeros);\r\n }\r\n\r\n function addDecimalsToFormatComponent(format: string, decimals: number, trailingZeros: boolean): string {\r\n decimals = Math.abs(decimals);\r\n\r\n if (decimals >= 0) {\r\n let placeholder = trailingZeros ? ZeroPlaceholder : DigitPlaceholder;\r\n let decimalPlaceholders = StringExtensions.repeat(placeholder, Math.abs(decimals));\r\n\r\n let match = RegExpExtensions.run(DecimalFormatRegex, format);\r\n if (match) {\r\n let beforeDecimal = format.substr(0, match.index);\r\n let formatDecimal = format.substr(match.index + 1, match[1].length);\r\n let afterDecimal = format.substr(match.index + match[0].length);\r\n\r\n if (trailingZeros)\r\n // Use explicit decimals argument as placeholders\r\n formatDecimal = decimalPlaceholders;\r\n else {\r\n let decimalChange = decimalPlaceholders.length - formatDecimal.length;\r\n if (decimalChange > 0)\r\n // Append decimalPlaceholders to existing decimal portion of format string\r\n formatDecimal = formatDecimal + decimalPlaceholders.slice(-decimalChange);\r\n else if (decimalChange < 0)\r\n // Remove decimals from formatDecimal\r\n formatDecimal = formatDecimal.slice(0, decimalChange);\r\n }\r\n\r\n if (formatDecimal.length > 0)\r\n formatDecimal = DecimalFormatCharacter + formatDecimal;\r\n\r\n return beforeDecimal + formatDecimal + afterDecimal;\r\n }\r\n else if (decimalPlaceholders.length > 0)\r\n // Replace last numeric placeholder with decimal portion\r\n return format.replace(LastNumericPlaceholderRegex, '$1' + DecimalFormatCharacter + decimalPlaceholders);\r\n }\r\n\r\n return format;\r\n }\r\n\r\n export function hasFormatComponents(format: string): boolean {\r\n return format.indexOf(NumberFormat.NumberFormatComponentsDelimeter) !== -1;\r\n }\r\n\r\n export function getComponents(format: string): NumberFormatComponents {\r\n let signFormat: NumberFormatComponents = {\r\n hasNegative: false,\r\n positive: format,\r\n negative: format,\r\n zero: format,\r\n };\r\n\r\n let signSpecificFormats = format.split(NumberFormatComponentsDelimeter);\r\n let formatCount = signSpecificFormats.length;\r\n debug.assert(!(formatCount > 3), 'format string should be of form positive[;negative;zero]');\r\n\r\n if (formatCount > 1) {\r\n signFormat.hasNegative = true;\r\n\r\n signFormat.positive = signFormat.zero = signSpecificFormats[0];\r\n signFormat.negative = signSpecificFormats[1];\r\n\r\n if (formatCount > 2)\r\n signFormat.zero = signSpecificFormats[2];\r\n }\r\n\r\n return signFormat;\r\n }\r\n\r\n let _lastCustomFormatMeta: NumericFormatMetadata;\r\n\r\n /** Evaluates if the value can be formatted using the NumberFormat */\r\n export function canFormat(value: any) {\r\n let result = typeof (value) === \"number\";\r\n return result;\r\n }\r\n\r\n export function isStandardFormat(format: string): boolean {\r\n debug.assertValue(format, 'format');\r\n return StandardFormatRegex.test(format);\r\n }\r\n\r\n /** Formats the number using specified format expression and culture */\r\n export function format(\r\n value: number,\r\n format: string,\r\n culture: Culture): string {\r\n format = format || \"G\";\r\n try {\r\n if (isStandardFormat(format))\r\n return formatNumberStandard(value, format, culture);\r\n\r\n return formatNumberCustom(value, format, culture);\r\n } catch (e) {\r\n return Globalize.format(value, undefined, culture);\r\n }\r\n }\r\n\r\n /** Performs a custom format with a value override. Typically used for custom formats showing scaled values. */\r\n export function formatWithCustomOverride(\r\n value: number,\r\n format: string,\r\n nonScientificOverrideFormat: string,\r\n culture: Culture): string {\r\n debug.assertValue(value, 'value');\r\n debug.assertValue(format, 'format');\r\n debug.assertValue(nonScientificOverrideFormat, 'nonScientificOverrideFormat');\r\n debug.assertValue(culture, 'culture');\r\n debug.assert(!isStandardFormat(format), 'Standard format');\r\n\r\n return formatNumberCustom(value, format, culture, nonScientificOverrideFormat);\r\n }\r\n\r\n /** Formats the number using standard format expression */\r\n function formatNumberStandard(value: number, format: string, culture: Culture): string {\r\n let result: string;\r\n let precision = <number>(format.length > 1 ? parseInt(format.substr(1, format.length - 1), 10) : undefined);\r\n let numberFormatInfo = culture.numberFormat;\r\n let formatChar = format.charAt(0);\r\n switch (formatChar) {\r\n case \"e\":\r\n case \"E\":\r\n if (precision === undefined) {\r\n precision = 6;\r\n }\r\n let mantissaDecimalDigits = StringExtensions.repeat(\"0\", precision);\r\n format = \"0.\" + mantissaDecimalDigits + formatChar + \"+000\";\r\n result = formatNumberCustom(value, format, culture);\r\n break;\r\n case \"f\":\r\n case \"F\":\r\n result = precision !== undefined ? value.toFixed(precision) : value.toFixed(numberFormatInfo.decimals);\r\n result = localize(result, numberFormatInfo);\r\n break;\r\n case \"g\":\r\n case \"G\":\r\n let abs = Math.abs(value);\r\n if (abs === 0 || (1E-4 <= abs && abs < 1E15)) {\r\n // For the range of 0.0001 to 1,000,000,000,000,000 - use the normal form\r\n result = precision !== undefined ? value.toPrecision(precision) : value.toString();\r\n } else {\r\n // Otherwise use exponential\r\n // Assert that value is a number and fall back on returning value if it is not\r\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\r\n if (typeof (value) !== \"number\")\r\n return String(value);\r\n result = precision !== undefined ? value.toExponential(precision) : value.toExponential();\r\n result = result.replace(\"e\", \"E\");\r\n }\r\n result = localize(result, numberFormatInfo);\r\n break;\r\n case \"r\":\r\n case \"R\":\r\n result = value.toString();\r\n result = localize(result, numberFormatInfo);\r\n break;\r\n case \"x\":\r\n case \"X\":\r\n result = value.toString(16);\r\n if (formatChar === \"X\") {\r\n result = result.toUpperCase();\r\n }\r\n if (precision !== undefined) {\r\n let actualPrecision = result.length;\r\n let isNegative = value < 0;\r\n if (isNegative) {\r\n actualPrecision--;\r\n }\r\n let paddingZerosCount = precision - actualPrecision;\r\n let paddingZeros = undefined;\r\n if (paddingZerosCount > 0) {\r\n paddingZeros = StringExtensions.repeat(\"0\", paddingZerosCount);\r\n }\r\n if (isNegative) {\r\n result = \"-\" + paddingZeros + result.substr(1);\r\n } else {\r\n result = paddingZeros + result;\r\n }\r\n }\r\n result = localize(result, numberFormatInfo);\r\n break;\r\n default:\r\n result = Globalize.format(value, format, culture);\r\n }\r\n return result;\r\n }\r\n\r\n /** Formats the number using custom format expression */\r\n function formatNumberCustom(\r\n value: number,\r\n format: string,\r\n culture: Culture,\r\n nonScientificOverrideFormat?: string): string {\r\n let result: string;\r\n let numberFormatInfo = culture.numberFormat;\r\n if (isFinite(value)) {\r\n // Split format by positive[;negative;zero] pattern\r\n let formatComponents = getComponents(format);\r\n\r\n // Pick a format based on the sign of value\r\n if (value > 0) {\r\n format = formatComponents.positive;\r\n } else if (value === 0) {\r\n format = formatComponents.zero;\r\n } else {\r\n format = formatComponents.negative;\r\n }\r\n\r\n // Normalize value if we have an explicit negative format\r\n if (formatComponents.hasNegative)\r\n value = Math.abs(value);\r\n\r\n // Get format metadata\r\n let formatMeta = getCustomFormatMetadata(format, true /*calculatePrecision*/);\r\n\r\n // Preserve literals and escaped chars\r\n if (formatMeta.hasEscapes) {\r\n format = FormattingEncoder.preserveEscaped(format, \"\\\\0#.,%‰\");\r\n }\r\n let literals: string[] = [];\r\n if (formatMeta.hasQuotes) {\r\n format = FormattingEncoder.preserveLiterals(format, literals);\r\n }\r\n\r\n // Scientific format\r\n if (formatMeta.hasE && !nonScientificOverrideFormat) {\r\n let scientificMatch = RegExpExtensions.run(ScientificFormatRegex, format);\r\n if (scientificMatch) {\r\n // Case 2.1. Scientific custom format\r\n let formatM = format.substr(0, scientificMatch.index);\r\n let formatE = format.substr(scientificMatch.index + 2); // E(+|-)\r\n let precision = getCustomFormatPrecision(formatM, formatMeta);\r\n let scale = getCustomFormatScale(formatM, formatMeta);\r\n if (scale !== 1) {\r\n value = value * scale;\r\n }\r\n // Assert that value is a number and fall back on returning value if it is not\r\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\r\n if (typeof (value) !== \"number\")\r\n return String(value);\r\n let s = value.toExponential(precision);\r\n let indexOfE = s.indexOf(\"e\");\r\n let mantissa = s.substr(0, indexOfE);\r\n let exp = s.substr(indexOfE + 1);\r\n let resultM = fuseNumberWithCustomFormat(mantissa, formatM, numberFormatInfo);\r\n let resultE = fuseNumberWithCustomFormat(exp, formatE, numberFormatInfo);\r\n if (resultE.charAt(0) === \"+\" && scientificMatch[0].charAt(1) !== \"+\") {\r\n resultE = resultE.substr(1);\r\n }\r\n let e = scientificMatch[0].charAt(0);\r\n result = resultM + e + resultE;\r\n }\r\n }\r\n\r\n // Non scientific format\r\n if (result === undefined) {\r\n let valueFormatted: string;\r\n let isValueGlobalized: boolean = false;\r\n let precision = getCustomFormatPrecision(format, formatMeta);\r\n let scale = getCustomFormatScale(format, formatMeta);\r\n\r\n if (scale !== 1)\r\n value = value * scale;\r\n\r\n // Rounding\r\n value = parseFloat(toNonScientific(value, precision));\r\n\r\n if (nonScientificOverrideFormat) {\r\n // Get numeric format from format string\r\n let numericFormat = NumberFormat.getNumericFormat(value, format);\r\n\r\n // Add separators and decimalFormat to nonScientificFormat\r\n nonScientificOverrideFormat = getNonScientificFormatWithPrecision(nonScientificOverrideFormat, numericFormat);\r\n\r\n // Format the value\r\n valueFormatted = formattingService.format(nonScientificOverrideFormat, [value], culture.name);\r\n isValueGlobalized = true;\r\n }\r\n else\r\n valueFormatted = toNonScientific(value, precision);\r\n\r\n result = fuseNumberWithCustomFormat(valueFormatted, format, numberFormatInfo, nonScientificOverrideFormat, isValueGlobalized);\r\n }\r\n if (formatMeta.hasQuotes) {\r\n result = FormattingEncoder.restoreLiterals(result, literals);\r\n }\r\n if (formatMeta.hasEscapes) {\r\n result = FormattingEncoder.restoreEscaped(result, \"\\\\0#.,%‰\");\r\n }\r\n\r\n _lastCustomFormatMeta = formatMeta;\r\n } else {\r\n return Globalize.format(value, undefined);\r\n }\r\n return result;\r\n }\r\n\r\n /** Returns string with the fixed point respresentation of the number */\r\n function toNonScientific(value: number, precision: number): string {\r\n let result = \"\";\r\n let precisionZeros = 0;\r\n // Double precision numbers support actual 15-16 decimal digits of precision.\r\n if (precision > 16) {\r\n precisionZeros = precision - 16;\r\n precision = 16;\r\n }\r\n let digitsBeforeDecimalPoint = Double.log10(Math.abs(value));\r\n if (digitsBeforeDecimalPoint < 16) {\r\n if (digitsBeforeDecimalPoint > 0) {\r\n let maxPrecision = 16 - digitsBeforeDecimalPoint;\r\n if (precision > maxPrecision) {\r\n precisionZeros += precision - maxPrecision;\r\n precision = maxPrecision;\r\n }\r\n }\r\n result = value.toFixed(precision);\r\n } else if (digitsBeforeDecimalPoint === 16) {\r\n result = value.toFixed(0);\r\n precisionZeros += precision;\r\n if (precisionZeros > 0) {\r\n result += \".\";\r\n }\r\n } else { // digitsBeforeDecimalPoint > 16\r\n // Different browsers have different implementations of the toFixed().\r\n // In IE it returns fixed format no matter what's the number. In FF and Chrome the method returns exponential format for numbers greater than 1E21.\r\n // So we need to check for range and convert the to exponential with the max precision.\r\n // Then we convert exponential string to fixed by removing the dot and padding with \"power\" zeros.\r\n // Assert that value is a number and fall back on returning value if it is not\r\n debug.assert(typeof (value) === \"number\", \"value must be a number\");\r\n if (typeof (value) !== \"number\")\r\n return String(value);\r\n result = value.toExponential(15);\r\n let indexOfE = result.indexOf(\"e\");\r\n if (indexOfE > 0) {\r\n let indexOfDot = result.indexOf(\".\");\r\n let mantissa = result.substr(0, indexOfE);\r\n let exp = result.substr(indexOfE + 1);\r\n let powerZeros = parseInt(exp, 10) - (mantissa.length - indexOfDot - 1);\r\n result = mantissa.replace(\".\", \"\") + StringExtensions.repeat(\"0\", powerZeros);\r\n if (precision > 0) {\r\n result = result + \".\" + StringExtensions.repeat(\"0\", precision);\r\n }\r\n }\r\n }\r\n if (precisionZeros > 0) {\r\n result = result + StringExtensions.repeat(\"0\", precisionZeros);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Returns the formatMetadata of the format\r\n * When calculating precision and scale, if format string of\r\n * positive[;negative;zero] => positive format will be used\r\n * @param (required) format - format string\r\n * @param (optional) calculatePrecision - calculate precision of positive format\r\n * @param (optional) calculateScale - calculate scale of positive format\r\n */\r\n export function getCustomFormatMetadata(format: string, calculatePrecision?: boolean, calculateScale?: boolean): NumericFormatMetadata {\r\n if (_lastCustomFormatMeta !== undefined && format === _lastCustomFormatMeta.format) {\r\n return _lastCustomFormatMeta;\r\n }\r\n\r\n let result = {\r\n format: format,\r\n hasEscapes: false,\r\n hasQuotes: false,\r\n hasE: false,\r\n hasCommas: false,\r\n hasDots: false,\r\n hasPercent: false,\r\n hasPermile: false,\r\n precision: undefined,\r\n scale: undefined,\r\n };\r\n\r\n for (let i = 0, length = format.length; i < length; i++) {\r\n let c = format.charAt(i);\r\n switch (c) {\r\n case \"\\\\\":\r\n result.hasEscapes = true;\r\n break;\r\n case \"'\":\r\n case \"\\\"\":\r\n result.hasQuotes = true;\r\n break;\r\n case \"e\":\r\n case \"E\":\r\n result.hasE = true;\r\n break;\r\n case \",\":\r\n result.hasCommas = true;\r\n break;\r\n case \".\":\r\n result.hasDots = true;\r\n break;\r\n case \"%\":\r\n result.hasPercent = true;\r\n break;\r\n case \"‰\":\r\n result.hasPermile = true;\r\n break;\r\n }\r\n }\r\n\r\n // Use positive format for calculating these values\r\n let formatComponents = getComponents(format);\r\n\r\n if (calculatePrecision)\r\n result.precision = getCustomFormatPrecision(formatComponents.positive, result);\r\n if (calculateScale)\r\n result.scale = getCustomFormatScale(formatComponents.positive, result);\r\n\r\n return result;\r\n }\r\n\r\n /** Returns the decimal precision of format based on the number of # and 0 chars after the decimal point\r\n * Important: The input format string needs to be split to the appropriate pos/neg/zero portion to work correctly */\r\n function getCustomFormatPrecision(format: string, formatMeta: NumericFormatMetadata): number {\r\n if (formatMeta.precision > -1) {\r\n return formatMeta.precision;\r\n }\r\n let result = 0;\r\n if (formatMeta.hasDots) {\r\n let dotIndex = format.indexOf(\".\");\r\n if (dotIndex > -1) {\r\n let count = format.length;\r\n for (let i = dotIndex; i < count; i++) {\r\n let char = format.charAt(i);\r\n if (char.match(NumericPlaceholderRegex))\r\n result++;\r\n // 0.00E+0 :: Break before counting 0 in\r\n // exponential portion of format string\r\n if (char === ExponentialFormatChar)\r\n break;\r\n }\r\n result = Math.min(19, result);\r\n }\r\n }\r\n\r\n formatMeta.precision = result;\r\n return result;\r\n }\r\n\r\n /** Returns the scale factor of the format based on the \"%\" and scaling \",\" chars in the format */\r\n function getCustomFormatScale(format: string, formatMeta: NumericFormatMetadata): number {\r\n if (formatMeta.scale > -1) {\r\n return formatMeta.scale;\r\n }\r\n let result = 1;\r\n if (formatMeta.hasPercent && format.indexOf(\"%\") > -1) {\r\n result = result * 100;\r\n }\r\n if (formatMeta.hasPermile && format.indexOf(\"‰\") > -1) {\r\n result = result * 1000;\r\n }\r\n if (formatMeta.hasCommas) {\r\n let dotIndex = format.indexOf(\".\");\r\n if (dotIndex === -1) {\r\n dotIndex = format.length;\r\n }\r\n for (let i = dotIndex - 1; i > -1; i--) {\r\n let char = format.charAt(i);\r\n if (char === \",\") {\r\n result = result / 1000;\r\n } else {\r\n break;\r\n }\r\n }\r\n }\r\n formatMeta.scale = result;\r\n return result;\r\n }\r\n\r\n function fuseNumberWithCustomFormat(value: string, format: string, numberFormatInfo: GlobalizeNumberFormat, nonScientificOverrideFormat?: string, isValueGlobalized?: boolean): string {\r\n let suppressModifyValue = !!nonScientificOverrideFormat;\r\n let formatParts = format.split(\".\", 2);\r\n if (formatParts.length === 2) {\r\n let wholeFormat = formatParts[0];\r\n let fractionFormat = formatParts[1];\r\n let displayUnit = \"\";\r\n\r\n // Remove display unit from value before splitting on \".\" as localized display units sometimes end with \".\"\r\n if (nonScientificOverrideFormat) {\r\n debug.assert(NonScientificFormatRegex.test(nonScientificOverrideFormat), \"Number should always precede the display unit\");\r\n displayUnit = nonScientificOverrideFormat.replace(NumericalPlaceHolderRegex, \"\");\r\n value = value.replace(displayUnit, \"\");\r\n }\r\n\r\n let globalizedDecimalSeparator = numberFormatInfo[\".\"];\r\n let decimalSeparator = isValueGlobalized ? globalizedDecimalSeparator : \".\";\r\n let valueParts = value.split(decimalSeparator, 2);\r\n let wholeValue = valueParts.length === 1 ? valueParts[0] + displayUnit : valueParts[0];\r\n let fractionValue = valueParts.length === 2 ? valueParts[1] + displayUnit : \"\";\r\n fractionValue = fractionValue.replace(TrailingZerosRegex, \"\");\r\n\r\n let wholeFormattedValue = fuseNumberWithCustomFormatLeft(wholeValue, wholeFormat, numberFormatInfo, suppressModifyValue);\r\n let fractionFormattedValue = fuseNumberWithCustomFormatRight(fractionValue, fractionFormat, suppressModifyValue);\r\n\r\n if (fractionFormattedValue.fmtOnly || fractionFormattedValue.value === \"\")\r\n return wholeFormattedValue + fractionFormattedValue.value;\r\n\r\n return wholeFormattedValue + globalizedDecimalSeparator + fractionFormattedValue.value;\r\n }\r\n return fuseNumberWithCustomFormatLeft(value, format, numberFormatInfo, suppressModifyValue);\r\n }\r\n\r\n function fuseNumberWithCustomFormatLeft(value: string, format: string, numberFormatInfo: GlobalizeNumberFormat, suppressModifyValue?: boolean): string {\r\n let groupSymbolIndex = format.indexOf(\",\");\r\n let enableGroups = groupSymbolIndex > -1 && groupSymbolIndex < Math.max(format.lastIndexOf(\"0\"), format.lastIndexOf(\"#\")) && numberFormatInfo[\",\"];\r\n let groupDigitCount = 0;\r\n let groupIndex = 0;\r\n let groupSizes = numberFormatInfo.groupSizes || [3];\r\n let groupSize = groupSizes[0];\r\n let groupSeparator = numberFormatInfo[\",\"];\r\n let sign = \"\";\r\n let firstChar = value.charAt(0);\r\n if (firstChar === \"+\" || firstChar === \"-\") {\r\n sign = numberFormatInfo[firstChar];\r\n value = value.substr(1);\r\n }\r\n let isZero = value === \"0\";\r\n let result = \"\";\r\n let leftBuffer = \"\";\r\n let vi = value.length - 1;\r\n let fmtOnly = true;\r\n // Iterate through format chars and replace 0 and # with the digits from the value string\r\n for (let fi = format.length - 1; fi > -1; fi--) {\r\n let formatChar = format.charAt(fi);\r\n switch (formatChar) {\r\n case ZeroPlaceholder:\r\n case DigitPlaceholder:\r\n fmtOnly = false;\r\n if (leftBuffer !== \"\") {\r\n result = leftBuffer + result;\r\n leftBuffer = \"\";\r\n }\r\n if (!suppressModifyValue) {\r\n if (vi > -1 || formatChar === ZeroPlaceholder) {\r\n if (enableGroups) {\r\n // If the groups are enabled we'll need to keep track of the current group index and periodically insert group separator,\r\n if (groupDigitCount === groupSize) {\r\n result = groupSeparator + result;\r\n groupIndex++;\r\n if (groupIndex < groupSizes.length) {\r\n groupSize = groupSizes[groupIndex];\r\n }\r\n groupDigitCount = 1;\r\n } else {\r\n groupDigitCount++;\r\n }\r\n }\r\n }\r\n if (vi > -1) {\r\n if (isZero && formatChar === DigitPlaceholder) {\r\n // Special case - if we need to format a zero value and the # symbol is used - we don't copy it into the result)\r\n } else {\r\n result = value.charAt(vi) + result;\r\n }\r\n vi--;\r\n } else if (formatChar !== DigitPlaceholder) {\r\n result = formatChar + result;\r\n }\r\n }\r\n break;\r\n case \",\":\r\n // We should skip all the , chars\r\n break;\r\n default:\r\n leftBuffer = formatChar + leftBuffer;\r\n break;\r\n }\r\n }\r\n\r\n // If the value didn't fit into the number of zeros provided in the format then we should insert the missing part of the value into the result\r\n if (!suppressModifyValue) {\r\n if (vi > -1 && result !== \"\") {\r\n if (enableGroups) {\r\n while (vi > -1) {\r\n if (groupDigitCount === groupSize) {\r\n result = groupSeparator + result;\r\n groupIndex++;\r\n if (groupIndex < groupSizes.length) {\r\n groupSize = groupSizes[groupIndex];\r\n }\r\n groupDigitCount = 1;\r\n } else {\r\n groupDigitCount++;\r\n }\r\n result = value.charAt(vi) + result;\r\n vi--;\r\n }\r\n } else {\r\n result = value.substr(0, vi + 1) + result;\r\n }\r\n }\r\n // Insert sign in front of the leftBuffer and result\r\n return sign + leftBuffer + result;\r\n }\r\n\r\n if (fmtOnly)\r\n // If the format doesn't specify any digits to be displayed, then just return the format we've parsed up until now.\r\n return sign + leftBuffer + result;\r\n\r\n return sign + leftBuffer + value + result;\r\n }\r\n\r\n function fuseNumberWithCustomFormatRight(value: string, format: string, suppressModifyValue?: boolean): { value: string; fmtOnly?: boolean } {\r\n let vi = 0;\r\n let fCount = format.length;\r\n let vCount = value.length;\r\n\r\n if (suppressModifyValue) {\r\n debug.assert(fCount > 0, \"Empty formatting string\");\r\n\r\n let lastChar = format.charAt(fCount - 1);\r\n if (!lastChar.match(NumericPlaceholderRegex))\r\n return {\r\n value: value + lastChar,\r\n fmtOnly: value === \"\",\r\n };\r\n\r\n return {\r\n value: value,\r\n fmtOnly: value === \"\",\r\n };\r\n }\r\n\r\n let result = \"\",\r\n fmtOnly: boolean = true;\r\n for (let fi = 0; fi < fCount; fi++) {\r\n let formatChar = format.charAt(fi);\r\n if (vi < vCount) {\r\n switch (formatChar) {\r\n case ZeroPlaceholder:\r\n case DigitPlaceholder:\r\n result += value[vi++];\r\n fmtOnly = false;\r\n break;\r\n default:\r\n result += formatChar;\r\n }\r\n } else {\r\n if (formatChar !== DigitPlaceholder) {\r\n result += formatChar;\r\n fmtOnly = fmtOnly && (formatChar !== ZeroPlaceholder);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n value: result,\r\n fmtOnly: fmtOnly,\r\n };\r\n }\r\n\r\n function localize(value: string, dictionary: any): string {\r\n let plus = dictionary[\"+\"];\r\n let minus = dictionary[\"-\"];\r\n let dot = dictionary[\".\"];\r\n let comma = dictionary[\",\"];\r\n if (plus === \"+\" && minus === \"-\" && dot === \".\" && comma === \",\") {\r\n return value;\r\n }\r\n let count = value.length;\r\n let result = \"\";\r\n for (let i = 0; i < count; i++) {\r\n let char = value.charAt(i);\r\n switch (char) {\r\n case \"+\":\r\n result = result + plus;\r\n break;\r\n case \"-\":\r\n result = result + minus;\r\n break;\r\n case \".\":\r\n result = result + dot;\r\n break;\r\n case \",\":\r\n result = result + comma;\r\n break;\r\n default:\r\n result = result + char;\r\n break;\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n }\r\n\r\n /** DateTimeScaleFormatInfo is used to calculate and keep the Date formats used for different units supported by the DateTimeScaleModel */\r\n class DateTimeScaleFormatInfo {\r\n\r\n // Fields\r\n public YearPattern: string;\r\n public MonthPattern: string;\r\n public DayPattern: string;\r\n public HourPattern: string;\r\n public MinutePattern: string;\r\n public SecondPattern: string;\r\n public MillisecondPattern: string;\r\n\r\n // Constructor\r\n /**\r\n * Creates new instance of the DateTimeScaleFormatInfo class.\r\n * @param culture - culture which calendar info is going to be used to derive the formats.\r\n */\r\n constructor(culture: Culture) {\r\n let calendar: Calendar = culture.calendar;\r\n let patterns: any = calendar.patterns;\r\n let monthAbbreviations: any = calendar[\"months\"][\"namesAbbr\"];\r\n let cultureHasMonthAbbr: boolean = monthAbbreviations && monthAbbreviations[0];\r\n let yearMonthPattern: string = patterns[\"Y\"];\r\n let monthDayPattern: string = patterns[\"M\"];\r\n let fullPattern: string = patterns[\"f\"];\r\n let longTimePattern: string = patterns[\"T\"];\r\n let shortTimePattern: string = patterns[\"t\"];\r\n let separator: string = fullPattern.indexOf(\",\") > -1 ? \", \" : \" \";\r\n\r\n let hasYearSymbol: boolean = yearMonthPattern.indexOf(\"yyyy'\") === 0 && yearMonthPattern.length > 6 && yearMonthPattern[6] === '\\'';\r\n this.YearPattern = hasYearSymbol ? yearMonthPattern.substr(0, 7) : \"yyyy\";\r\n\r\n let yearPos: number = fullPattern.indexOf(\"yy\");\r\n let monthPos: number = fullPattern.indexOf(\"MMMM\");\r\n this.MonthPattern = cultureHasMonthAbbr && monthPos > -1 ? (yearPos > monthPos ? \"MMM yyyy\" : \"yyyy MMM\") : yearMonthPattern;\r\n\r\n this.DayPattern = cultureHasMonthAbbr ? monthDayPattern.replace(\"MMMM\", \"MMM\") : monthDayPattern;\r\n\r\n let minutePos: number = fullPattern.indexOf(\"mm\");\r\n let pmPos: number = fullPattern.indexOf(\"tt\");\r\n let shortHourPattern: string = pmPos > -1 ? shortTimePattern.replace(\":mm \", \"\") : shortTimePattern;\r\n this.HourPattern = yearPos < minutePos ? this.DayPattern + separator + shortHourPattern : shortHourPattern + separator + this.DayPattern;\r\n\r\n this.MinutePattern = shortTimePattern;\r\n\r\n this.SecondPattern = longTimePattern;\r\n\r\n this.MillisecondPattern = longTimePattern.replace(\"ss\", \"ss.fff\");\r\n\r\n // Special cases\r\n switch (culture.name) {\r\n case \"fi-FI\":\r\n this.DayPattern = this.DayPattern.replace(\"'ta'\", \"\"); // Fix for finish 'ta' suffix for month names.\r\n this.HourPattern = this.HourPattern.replace(\"'ta'\", \"\");\r\n break;\r\n }\r\n }\r\n\r\n // Methods\r\n\r\n /**\r\n * Returns the format string of the provided DateTimeUnit.\r\n * @param unit - date or time unit\r\n */\r\n public getFormatString(unit: DateTimeUnit): string {\r\n switch (unit) {\r\n case DateTimeUnit.Year:\r\n return this.YearPattern;\r\n case DateTimeUnit.Month:\r\n return this.MonthPattern;\r\n case DateTimeUnit.Week:\r\n case DateTimeUnit.Day:\r\n return this.DayPattern;\r\n case DateTimeUnit.Hour:\r\n return this.HourPattern;\r\n case DateTimeUnit.Minute:\r\n return this.MinutePattern;\r\n case DateTimeUnit.Second:\r\n return this.SecondPattern;\r\n case DateTimeUnit.Millisecond:\r\n return this.MillisecondPattern;\r\n }\r\n\r\n debug.assertFail('Unexpected unit: ' + unit);\r\n }\r\n }\r\n\r\n export var formattingService: IFormattingService = new FormattingService();\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.data {\r\n /** Serializes SQExpr in a form optimized in-memory comparison, but not intended for storage on disk. */\r\n export module SQExprShortSerializer {\r\n export function serialize(expr: SQExpr): string {\r\n return JSON.stringify(expr.accept(SQExprSerializer.instance));\r\n }\r\n\r\n export function serializeArray(exprs: SQExpr[]): string {\r\n let str = '[';\r\n for (let i = 0, len = exprs.length; i < len; i++) {\r\n if (i > 0)\r\n str += ',';\r\n str += SQExprShortSerializer.serialize(exprs[i]);\r\n }\r\n return str + ']';\r\n }\r\n\r\n /** Responsible for serializing an SQExpr into a comparable string. */\r\n class SQExprSerializer extends DefaultSQExprVisitor<{}> {\r\n public static instance: SQExprSerializer = new SQExprSerializer();\r\n\r\n public visitColumnRef(expr: SQColumnRefExpr): {} {\r\n return {\r\n col: {\r\n s: expr.source.accept(this),\r\n r: expr.ref,\r\n }\r\n };\r\n }\r\n\r\n public visitMeasureRef(expr: SQMeasureRefExpr): {} {\r\n return {\r\n measure: {\r\n s: expr.source.accept(this),\r\n r: expr.ref,\r\n }\r\n };\r\n }\r\n\r\n public visitAggr(expr: SQAggregationExpr): {} {\r\n return {\r\n agg: {\r\n a: expr.arg.accept(this),\r\n f: expr.func,\r\n }\r\n };\r\n }\r\n\r\n public visitEntity(expr: SQEntityExpr): {} {\r\n debug.assertValue(expr, 'expr');\r\n debug.assertValue(expr.entity, 'expr.entity');\r\n\r\n return {\r\n e: expr.entity\r\n };\r\n }\r\n\r\n public visitHierarchyLevel(expr: SQHierarchyLevelExpr): {} {\r\n return {\r\n h: expr.arg.accept(this),\r\n l: expr.level,\r\n };\r\n }\r\n\r\n public visitHierarchy(expr: SQHierarchyExpr): {} {\r\n return {\r\n e: expr.arg.accept(this),\r\n h: expr.hierarchy,\r\n };\r\n }\r\n\r\n public visitPropertyVariationSource(expr: SQPropertyVariationSourceExpr): {} {\r\n return {\r\n e: expr.arg.accept(this),\r\n n: expr.name,\r\n p: expr.property,\r\n };\r\n }\r\n\r\n public visitAnd(expr: SQAndExpr): {} {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return {\r\n and: {\r\n l: expr.left.accept(this),\r\n r: expr.right.accept(this),\r\n }\r\n };\r\n }\r\n\r\n public visitCompare(expr: SQCompareExpr): {} {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return {\r\n comp: {\r\n k: expr.comparison,\r\n l: expr.left.accept(this),\r\n r: expr.right.accept(this),\r\n }\r\n };\r\n }\r\n\r\n public visitConstant(expr: SQConstantExpr): {} {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return {\r\n const: {\r\n t: expr.type.primitiveType,\r\n v: expr.value,\r\n }\r\n };\r\n }\r\n\r\n public visitArithmetic(expr: SQArithmeticExpr): {} {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return {\r\n arithmetic: {\r\n o: expr.operator,\r\n l: expr.left.accept(this),\r\n r: expr.right.accept(this)\r\n }\r\n };\r\n }\r\n\r\n public visitScopedEval(expr: SQScopedEvalExpr): {} {\r\n debug.assertValue(expr, 'expr');\r\n\r\n return {\r\n scopedEval: {\r\n e: expr.expression.accept(this),\r\n s: serializeArray(expr.scope)\r\n }\r\n };\r\n }\r\n\r\n public visitDefault(expr: SQExpr): {} {\r\n debug.assertFail('Unexpected expression type found in DataViewScopeIdentity.');\r\n\r\n return;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import Selector = powerbi.data.Selector;\r\n import SelectorsByColumn = powerbi.SelectorsByColumn;\r\n import SelectorForColumn = powerbi.SelectorForColumn;\r\n\r\n /**\r\n * A combination of identifiers used to uniquely identify\r\n * data points and their bound geometry.\r\n */\r\n export class SelectionId implements ISelectionId {\r\n private selector: Selector;\r\n // This is a new data structure to support drilling -- in the long term it should replace the 'selector' field\r\n private selectorsByColumn: SelectorsByColumn;\r\n private key: string;\r\n private keyWithoutHighlight: string;\r\n\r\n public highlight: boolean;\r\n\r\n constructor(selector: Selector, highlight: boolean) {\r\n this.selector = selector;\r\n this.highlight = highlight;\r\n this.key = JSON.stringify({ selector: selector ? Selector.getKey(selector) : null, highlight: highlight });\r\n this.keyWithoutHighlight = JSON.stringify({ selector: selector ? Selector.getKey(selector) : null });\r\n }\r\n\r\n public equals(other: SelectionId): boolean {\r\n if (!this.selector || !other.selector) {\r\n return (!this.selector === !other.selector) && this.highlight === other.highlight;\r\n }\r\n return this.highlight === other.highlight && Selector.equals(this.selector, other.selector);\r\n }\r\n \r\n /**\r\n * Checks equality against other for all identifiers existing in this.\r\n */\r\n public includes(other: SelectionId, ignoreHighlight: boolean = false): boolean {\r\n let thisSelector = this.selector;\r\n let otherSelector = other.selector;\r\n if (!thisSelector || !otherSelector) {\r\n return false;\r\n }\r\n let thisData = thisSelector.data;\r\n let otherData = otherSelector.data;\r\n if (!thisData && (thisSelector.metadata && thisSelector.metadata !== otherSelector.metadata))\r\n return false;\r\n if (!ignoreHighlight && this.highlight !== other.highlight)\r\n return false;\r\n if (thisData) {\r\n if (!otherData)\r\n return false;\r\n if (thisData.length > 0) {\r\n for (let i = 0, ilen = thisData.length; i < ilen; i++) {\r\n var thisValue = <DataViewScopeIdentity>thisData[i];\r\n if (!otherData.some((otherValue: DataViewScopeIdentity) => DataViewScopeIdentity.equals(thisValue, otherValue)))\r\n return false;\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n public getKey(): string {\r\n return this.key;\r\n }\r\n\r\n public getKeyWithoutHighlight(): string {\r\n return this.keyWithoutHighlight;\r\n }\r\n \r\n public hasIdentity(): boolean {\r\n return (this.selector && !!this.selector.data);\r\n }\r\n\r\n public getSelector(): Selector {\r\n return this.selector;\r\n }\r\n\r\n public getSelectorsByColumn(): Selector {\r\n return this.selectorsByColumn;\r\n }\r\n\r\n public static createNull(highlight: boolean = false): SelectionId {\r\n return new SelectionId(null, highlight);\r\n }\r\n\r\n public static createWithId(id: DataViewScopeIdentity, highlight: boolean = false): SelectionId {\r\n let selector: Selector = null;\r\n if (id) {\r\n selector = {\r\n data: [id]\r\n };\r\n }\r\n return new SelectionId(selector, highlight);\r\n }\r\n\r\n public static createWithMeasure(measureId: string, highlight: boolean = false): SelectionId {\r\n debug.assertValue(measureId, 'measureId');\r\n\r\n let selector: Selector = {\r\n metadata: measureId\r\n };\r\n\r\n let selectionId = new SelectionId(selector, highlight);\r\n selectionId.selectorsByColumn = { metadata: measureId };\r\n return selectionId;\r\n }\r\n\r\n public static createWithIdAndMeasure(id: DataViewScopeIdentity, measureId: string, highlight: boolean = false): SelectionId {\r\n let selector: powerbi.data.Selector = {};\r\n if (id) {\r\n selector.data = [id];\r\n }\r\n if (measureId)\r\n selector.metadata = measureId;\r\n if (!id && !measureId)\r\n selector = null;\r\n\r\n let selectionId = new SelectionId(selector, highlight);\r\n\r\n return selectionId;\r\n }\r\n\r\n public static createWithIdAndMeasureAndCategory(id: DataViewScopeIdentity, measureId: string, queryName: string, highlight: boolean = false): SelectionId {\r\n let selectionId = this.createWithIdAndMeasure(id, measureId, highlight);\r\n\r\n if (selectionId.selector) {\r\n selectionId.selectorsByColumn = {};\r\n if (id && queryName) {\r\n selectionId.selectorsByColumn.dataMap = {};\r\n selectionId.selectorsByColumn.dataMap[queryName] = id;\r\n }\r\n if (measureId)\r\n selectionId.selectorsByColumn.metadata = measureId;\r\n }\r\n\r\n return selectionId;\r\n }\r\n\r\n public static createWithIds(id1: DataViewScopeIdentity, id2: DataViewScopeIdentity, highlight: boolean = false): SelectionId {\r\n let selector: Selector = null;\r\n let selectorData = SelectionId.idArray(id1, id2);\r\n if (selectorData)\r\n selector = { data: selectorData };\r\n \r\n return new SelectionId(selector, highlight);\r\n }\r\n\r\n public static createWithIdsAndMeasure(id1: DataViewScopeIdentity, id2: DataViewScopeIdentity, measureId: string, highlight: boolean = false): SelectionId {\r\n let selector: Selector = {};\r\n let selectorData = SelectionId.idArray(id1, id2);\r\n if (selectorData)\r\n selector.data = selectorData;\r\n\r\n if (measureId)\r\n selector.metadata = measureId;\r\n if (!id1 && !id2 && !measureId)\r\n selector = null;\r\n return new SelectionId(selector, highlight);\r\n }\r\n\r\n public static createWithSelectorForColumnAndMeasure(dataMap: SelectorForColumn, measureId: string, highlight: boolean = false): SelectionId {\r\n\r\n let selectionId: visuals.SelectionId;\r\n let keys = Object.keys(dataMap);\r\n if (keys.length === 2) {\r\n selectionId = this.createWithIdsAndMeasure(<DataViewScopeIdentity>dataMap[keys[0]], <DataViewScopeIdentity>dataMap[keys[1]], measureId, highlight);\r\n } else if (keys.length === 1) {\r\n selectionId = this.createWithIdsAndMeasure(<DataViewScopeIdentity>dataMap[keys[0]], null, measureId, highlight);\r\n } else {\r\n selectionId = this.createWithIdsAndMeasure(null, null, measureId, highlight);\r\n }\r\n\r\n let selectorsByColumn: SelectorsByColumn = {};\r\n if (!_.isEmpty(dataMap))\r\n selectorsByColumn.dataMap = dataMap;\r\n if (measureId)\r\n selectorsByColumn.metadata = measureId;\r\n if (!dataMap && !measureId)\r\n selectorsByColumn = null;\r\n\r\n selectionId.selectorsByColumn = selectorsByColumn;\r\n\r\n return selectionId;\r\n }\r\n\r\n public static createWithHighlight(original: SelectionId): SelectionId {\r\n debug.assertValue(original, 'original');\r\n debug.assert(!original.highlight, '!original.highlight');\r\n\r\n let newId = new SelectionId(original.getSelector(), /*highlight*/ true);\r\n newId.selectorsByColumn = original.selectorsByColumn;\r\n\r\n return newId;\r\n }\r\n\r\n private static idArray(id1: DataViewScopeIdentity, id2: DataViewScopeIdentity): DataViewScopeIdentity[] {\r\n if (id1 || id2) {\r\n let data = [];\r\n if (id1)\r\n data.push(id1);\r\n if (id2 && id2 !== id1)\r\n data.push(id2);\r\n return data;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * This class is designed to simplify the creation of SelectionId objects\r\n * It allows chaining to build up an object before calling 'create' to build a SelectionId\r\n */\r\n export class SelectionIdBuilder implements ISelectionIdBuilder {\r\n private dataMap: SelectorForColumn;\r\n private measure: string;\r\n\r\n public static builder(): SelectionIdBuilder {\r\n return new SelectionIdBuilder();\r\n }\r\n\r\n public withCategory(categoryColumn: DataViewCategoryColumn, index: number): this{\r\n if (categoryColumn && categoryColumn.source && categoryColumn.source.queryName && categoryColumn.identity)\r\n this.ensureDataMap()[categoryColumn.source.queryName] = categoryColumn.identity[index];\r\n \r\n return this;\r\n }\r\n\r\n public withSeries(seriesColumn: DataViewValueColumns, valueColumn: DataViewValueColumn | DataViewValueColumnGroup): this {\r\n if (seriesColumn && seriesColumn.source && seriesColumn.source.queryName && valueColumn)\r\n this.ensureDataMap()[seriesColumn.source.queryName] = valueColumn.identity;\r\n\r\n return this;\r\n }\r\n\r\n public withMeasure(measureId: string): this {\r\n this.measure = measureId;\r\n\r\n return this;\r\n }\r\n\r\n public createSelectionId(): SelectionId {\r\n return SelectionId.createWithSelectorForColumnAndMeasure(this.ensureDataMap(), this.measure);\r\n }\r\n\r\n private ensureDataMap(): SelectorForColumn {\r\n if (!this.dataMap)\r\n this.dataMap = {};\r\n\r\n return this.dataMap;\r\n }\r\n }\r\n}\r\n","var __extends = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n};\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n///<reference path=\"../../Typedefs/d3/d3.d.ts\"/>\n///<reference path=\"../../Typedefs/jquery-visible/jquery-visible.d.ts\"/>\n///<reference path=\"../../Typedefs/jquery/jquery.d.ts\"/>\n///<reference path=\"../../Typedefs/microsoftMaps/Microsoft.Maps.d.ts\" />\n///<reference path=\"../../Typedefs/moment/moment.d.ts\"/>\n///<reference path=\"../../Typedefs/velocity/velocity-animate.d.ts\"/>\n///<reference path=\"../../Typedefs/lodash/lodash.d.ts\"/>\n///<reference path=\"../../Typedefs/quill/quill.d.ts\"/>\n///<reference path=\"../../Typedefs/ie/ie.d.ts\"/>\n///<reference path=\"../../Typedefs/noUiSlider/noUiSlider.d.ts\"/>\n///<reference path=\"../../Typedefs/jquery.scrollbar/jquery.scrollbar.d.ts\"/>\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Point = (function () {\n function Point(x, y) {\n this.x = x || 0;\n this.y = y || 0;\n }\n return Point;\n }());\n visuals.Point = Point;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Rect = (function () {\n // Constructor\n function Rect(left, top, width, height) {\n this.left = left || 0;\n this.top = top || 0;\n this.width = width || 0;\n this.height = height || 0;\n }\n return Rect;\n }());\n visuals.Rect = Rect;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n (function (LegendIcon) {\n LegendIcon[LegendIcon[\"Box\"] = 0] = \"Box\";\n LegendIcon[LegendIcon[\"Circle\"] = 1] = \"Circle\";\n LegendIcon[LegendIcon[\"Line\"] = 2] = \"Line\";\n })(visuals.LegendIcon || (visuals.LegendIcon = {}));\n var LegendIcon = visuals.LegendIcon;\n (function (LegendPosition) {\n LegendPosition[LegendPosition[\"Top\"] = 0] = \"Top\";\n LegendPosition[LegendPosition[\"Bottom\"] = 1] = \"Bottom\";\n LegendPosition[LegendPosition[\"Right\"] = 2] = \"Right\";\n LegendPosition[LegendPosition[\"Left\"] = 3] = \"Left\";\n LegendPosition[LegendPosition[\"None\"] = 4] = \"None\";\n LegendPosition[LegendPosition[\"TopCenter\"] = 5] = \"TopCenter\";\n LegendPosition[LegendPosition[\"BottomCenter\"] = 6] = \"BottomCenter\";\n LegendPosition[LegendPosition[\"RightCenter\"] = 7] = \"RightCenter\";\n LegendPosition[LegendPosition[\"LeftCenter\"] = 8] = \"LeftCenter\";\n })(visuals.LegendPosition || (visuals.LegendPosition = {}));\n var LegendPosition = visuals.LegendPosition;\n visuals.legendProps = {\n show: 'show',\n position: 'position',\n titleText: 'titleText',\n showTitle: 'showTitle',\n labelColor: 'labelColor',\n fontSize: 'fontSize',\n };\n function createLegend(legendParentElement, interactive, interactivityService, isScrollable, legendPosition) {\n if (isScrollable === void 0) { isScrollable = false; }\n if (legendPosition === void 0) { legendPosition = LegendPosition.Top; }\n if (interactive)\n return new CartesianChartInteractiveLegend(legendParentElement);\n else\n return new SVGLegend(legendParentElement, legendPosition, interactivityService, isScrollable);\n }\n visuals.createLegend = createLegend;\n var Legend;\n (function (Legend) {\n function isLeft(orientation) {\n switch (orientation) {\n case LegendPosition.Left:\n case LegendPosition.LeftCenter:\n return true;\n default:\n return false;\n }\n }\n Legend.isLeft = isLeft;\n function isTop(orientation) {\n switch (orientation) {\n case LegendPosition.Top:\n case LegendPosition.TopCenter:\n return true;\n default:\n return false;\n }\n }\n Legend.isTop = isTop;\n function positionChartArea(chartArea, legend) {\n var legendMargins = legend.getMargins();\n var legendOrientation = legend.getOrientation();\n chartArea.style({\n 'margin-left': Legend.isLeft(legendOrientation) ? legendMargins.width + 'px' : null,\n 'margin-top': Legend.isTop(legendOrientation) ? legendMargins.height + 'px' : null,\n });\n }\n Legend.positionChartArea = positionChartArea;\n })(Legend = visuals.Legend || (visuals.Legend = {}));\n var SVGLegend = (function () {\n function SVGLegend(element, legendPosition, interactivityService, isScrollable) {\n this.legendDataStartIndex = 0;\n this.arrowPosWindow = 1;\n this.lastCalculatedWidth = 0;\n this.visibleLegendWidth = 0;\n this.visibleLegendHeight = 0;\n this.legendFontSizeMarginDifference = 0;\n this.legendFontSizeMarginValue = 0;\n this.svg = d3.select(element.get(0)).append('svg').style('position', 'absolute');\n this.svg.style('display', 'inherit');\n this.svg.classed('legend', true);\n if (interactivityService)\n this.clearCatcher = visuals.appendClearCatcher(this.svg);\n this.group = this.svg.append('g').attr('id', 'legendGroup');\n this.interactivityService = interactivityService;\n this.isScrollable = isScrollable;\n this.element = element;\n this.changeOrientation(legendPosition);\n this.parentViewport = { height: 0, width: 0 };\n this.calculateViewport();\n this.updateLayout();\n }\n SVGLegend.prototype.updateLayout = function () {\n var legendViewport = this.viewport;\n var orientation = this.orientation;\n this.svg.attr({\n 'height': legendViewport.height || (orientation === LegendPosition.None ? 0 : this.parentViewport.height),\n 'width': legendViewport.width || (orientation === LegendPosition.None ? 0 : this.parentViewport.width)\n });\n var isRight = orientation === LegendPosition.Right || orientation === LegendPosition.RightCenter;\n var isBottom = orientation === LegendPosition.Bottom || orientation === LegendPosition.BottomCenter;\n this.svg.style({\n 'margin-left': isRight ? (this.parentViewport.width - legendViewport.width) + 'px' : null,\n 'margin-top': isBottom ? (this.parentViewport.height - legendViewport.height) + 'px' : null,\n });\n };\n SVGLegend.prototype.calculateViewport = function () {\n switch (this.orientation) {\n case LegendPosition.Top:\n case LegendPosition.Bottom:\n case LegendPosition.TopCenter:\n case LegendPosition.BottomCenter:\n var pixelHeight = PixelConverter.fromPointToPixel(this.data && this.data.fontSize ? this.data.fontSize : SVGLegend.DefaultFontSizeInPt);\n var fontHeightSize = SVGLegend.TopLegendHeight + (pixelHeight - SVGLegend.DefaultFontSizeInPt);\n this.viewport = { height: fontHeightSize, width: 0 };\n return;\n case LegendPosition.Right:\n case LegendPosition.Left:\n case LegendPosition.RightCenter:\n case LegendPosition.LeftCenter:\n var width = this.lastCalculatedWidth ? this.lastCalculatedWidth : this.parentViewport.width * SVGLegend.LegendMaxWidthFactor;\n this.viewport = { height: 0, width: width };\n return;\n case LegendPosition.None:\n this.viewport = { height: 0, width: 0 };\n }\n };\n SVGLegend.prototype.getMargins = function () {\n return this.viewport;\n };\n SVGLegend.prototype.isVisible = function () {\n return this.orientation !== LegendPosition.None;\n };\n SVGLegend.prototype.changeOrientation = function (orientation) {\n if (orientation) {\n this.orientation = orientation;\n }\n else {\n this.orientation = LegendPosition.Top;\n }\n this.svg.attr('orientation', orientation);\n };\n SVGLegend.prototype.getOrientation = function () {\n return this.orientation;\n };\n SVGLegend.prototype.drawLegend = function (data, viewport) {\n // clone because we modify legend item label with ellipsis if it is truncated\n var clonedData = powerbi.Prototype.inherit(data);\n var newDataPoints = [];\n for (var _i = 0, _a = data.dataPoints; _i < _a.length; _i++) {\n var dp = _a[_i];\n newDataPoints.push(powerbi.Prototype.inherit(dp));\n }\n clonedData.dataPoints = newDataPoints;\n this.setTooltipToLegendItems(clonedData);\n this.drawLegendInternal(clonedData, viewport, true /* perform auto width */);\n };\n SVGLegend.prototype.drawLegendInternal = function (data, viewport, autoWidth) {\n this.parentViewport = viewport;\n this.data = data;\n if (this.interactivityService)\n this.interactivityService.applySelectionStateToData(data.dataPoints);\n if (data.dataPoints.length === 0) {\n this.changeOrientation(LegendPosition.None);\n }\n if (this.getOrientation() === LegendPosition.None) {\n data.dataPoints = [];\n }\n // Adding back the workaround for Legend Left/Right position for Map\n var mapControl = this.element.children(\".mapControl\");\n if (mapControl.length > 0 && !this.isTopOrBottom(this.orientation)) {\n mapControl.css(\"display\", \"inline-block\");\n }\n this.calculateViewport();\n var layout = this.calculateLayout(data, autoWidth);\n var titleLayout = layout.title;\n var titleData = titleLayout ? [titleLayout] : [];\n var hasSelection = this.interactivityService && powerbi.visuals.dataHasSelection(data.dataPoints);\n var group = this.group;\n //transform the wrapping group if position is centered\n if (this.isCentered(this.orientation)) {\n var centerOffset = 0;\n if (this.isTopOrBottom(this.orientation)) {\n centerOffset = Math.max(0, (this.parentViewport.width - this.visibleLegendWidth) / 2);\n group.attr('transform', visuals.SVGUtil.translate(centerOffset, 0));\n }\n else {\n centerOffset = Math.max((this.parentViewport.height - this.visibleLegendHeight) / 2);\n group.attr('transform', visuals.SVGUtil.translate(0, centerOffset));\n }\n }\n else {\n group.attr('transform', null);\n }\n var legendTitle = group\n .selectAll(SVGLegend.LegendTitle.selector)\n .data(titleData);\n legendTitle.enter()\n .append('text')\n .classed(SVGLegend.LegendTitle.class, true);\n legendTitle\n .style({\n 'fill': data.labelColor,\n 'font-size': PixelConverter.fromPoint(data.fontSize),\n 'font-family': SVGLegend.DefaultTitleFontFamily\n })\n .text(function (d) { return d.text; })\n .attr({\n 'x': function (d) { return d.x; },\n 'y': function (d) { return d.y; }\n })\n .append('title').text(data.title);\n legendTitle.exit().remove();\n var virtualizedDataPoints = data.dataPoints.slice(this.legendDataStartIndex, this.legendDataStartIndex + layout.numberOfItems);\n var iconRadius = powerbi.TextMeasurementService.estimateSvgTextHeight(SVGLegend.getTextProperties(false, '', this.data.fontSize)) / SVGLegend.LegendIconRadiusFactor;\n iconRadius = (this.legendFontSizeMarginValue > SVGLegend.DefaultTextMargin) && iconRadius > SVGLegend.LegendIconRadius\n ? iconRadius :\n SVGLegend.LegendIconRadius;\n var legendItems = group\n .selectAll(SVGLegend.LegendItem.selector)\n .data(virtualizedDataPoints, function (d) { return d.identity.getKey() + (d.layerNumber != null ? d.layerNumber : ''); });\n var itemsEnter = legendItems.enter()\n .append('g')\n .classed(SVGLegend.LegendItem.class, true);\n itemsEnter\n .append('circle')\n .classed(SVGLegend.LegendIcon.class, true);\n itemsEnter\n .append('text')\n .classed(SVGLegend.LegendText.class, true);\n itemsEnter\n .append('title')\n .text(function (d) { return d.tooltip; });\n itemsEnter\n .style({\n 'font-family': SVGLegend.DefaultFontFamily\n });\n legendItems\n .select(SVGLegend.LegendIcon.selector)\n .attr({\n 'cx': function (d, i) { return d.glyphPosition.x; },\n 'cy': function (d) { return d.glyphPosition.y; },\n 'r': iconRadius,\n })\n .style({\n 'fill': function (d) {\n if (hasSelection && !d.selected)\n return visuals.LegendBehavior.dimmedLegendColor;\n else\n return d.color;\n }\n });\n legendItems\n .select('title')\n .text(function (d) { return d.tooltip; });\n legendItems\n .select(SVGLegend.LegendText.selector)\n .attr({\n 'x': function (d) { return d.textPosition.x; },\n 'y': function (d) { return d.textPosition.y; },\n })\n .text(function (d) { return d.label; })\n .style({\n 'fill': data.labelColor,\n 'font-size': PixelConverter.fromPoint(data.fontSize)\n });\n if (this.interactivityService) {\n var iconsSelection = legendItems.select(SVGLegend.LegendIcon.selector);\n var behaviorOptions = {\n legendItems: legendItems,\n legendIcons: iconsSelection,\n clearCatcher: this.clearCatcher,\n };\n this.interactivityService.bind(data.dataPoints, new visuals.LegendBehavior(), behaviorOptions, { isLegend: true });\n }\n legendItems.exit().remove();\n this.drawNavigationArrows(layout.navigationArrows);\n this.updateLayout();\n };\n SVGLegend.prototype.normalizePosition = function (points) {\n if (this.legendDataStartIndex >= points.length) {\n this.legendDataStartIndex = points.length - 1;\n }\n if (this.legendDataStartIndex < 0) {\n this.legendDataStartIndex = 0;\n }\n };\n SVGLegend.prototype.calculateTitleLayout = function (title) {\n var width = 0;\n var hasTitle = !_.isEmpty(title);\n if (hasTitle) {\n var isHorizontal = this.isTopOrBottom(this.orientation);\n var maxMeasureLength = void 0;\n if (isHorizontal) {\n var fontSizeMargin = this.legendFontSizeMarginValue > SVGLegend.DefaultTextMargin ? SVGLegend.TextAndIconPadding + this.legendFontSizeMarginDifference : SVGLegend.TextAndIconPadding;\n var fixedHorizontalIconShift = SVGLegend.TextAndIconPadding + SVGLegend.LegendIconRadius;\n var fixedHorizontalTextShift = SVGLegend.LegendIconRadius + fontSizeMargin + fixedHorizontalIconShift;\n // TODO This can be negative for narrow viewports. May need to rework this logic.\n maxMeasureLength = this.parentViewport.width * SVGLegend.LegendMaxWidthFactor - fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth;\n }\n else {\n maxMeasureLength = this.legendFontSizeMarginValue < SVGLegend.DefaultTextMargin ? SVGLegend.MaxTitleLength :\n SVGLegend.MaxTitleLength + (SVGLegend.DefaultMaxLegendFactor * this.legendFontSizeMarginDifference);\n }\n var textProperties = SVGLegend.getTextProperties(true, title, this.data.fontSize);\n var text = title;\n width = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n if (width > maxMeasureLength) {\n text = powerbi.TextMeasurementService.getTailoredTextOrDefault(textProperties, maxMeasureLength);\n textProperties.text = text;\n // Remeasure the text since its measurement may be different than the max (ex. when the max is negative, the text will be ellipsis, and not have a negative width)\n width = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n }\n ;\n if (isHorizontal)\n width += SVGLegend.TitlePadding;\n else\n text = powerbi.TextMeasurementService.getTailoredTextOrDefault(textProperties, this.viewport.width);\n return {\n x: 0,\n y: 0,\n text: text,\n width: width,\n height: powerbi.TextMeasurementService.estimateSvgTextHeight(textProperties)\n };\n }\n return null;\n };\n /** Performs layout offline for optimal perfomance */\n SVGLegend.prototype.calculateLayout = function (data, autoWidth) {\n var dataPoints = data.dataPoints;\n if (data.dataPoints.length === 0) {\n return {\n startIndex: null,\n numberOfItems: 0,\n title: null,\n navigationArrows: []\n };\n }\n this.legendFontSizeMarginValue = PixelConverter.fromPointToPixel(this.data && this.data.fontSize !== undefined ? this.data.fontSize : SVGLegend.DefaultFontSizeInPt);\n this.legendFontSizeMarginDifference = (this.legendFontSizeMarginValue - SVGLegend.DefaultTextMargin);\n this.normalizePosition(dataPoints);\n if (this.legendDataStartIndex < dataPoints.length) {\n dataPoints = dataPoints.slice(this.legendDataStartIndex);\n }\n var title = this.calculateTitleLayout(data.title);\n var navArrows;\n var numberOfItems;\n if (this.isTopOrBottom(this.orientation)) {\n navArrows = this.isScrollable ? this.calculateHorizontalNavigationArrowsLayout(title) : [];\n numberOfItems = this.calculateHorizontalLayout(dataPoints, title, navArrows);\n }\n else {\n navArrows = this.isScrollable ? this.calculateVerticalNavigationArrowsLayout(title) : [];\n numberOfItems = this.calculateVerticalLayout(dataPoints, title, navArrows, autoWidth);\n }\n return {\n numberOfItems: numberOfItems,\n title: title,\n navigationArrows: navArrows\n };\n };\n SVGLegend.prototype.updateNavigationArrowLayout = function (navigationArrows, remainingDataLength, visibleDataLength) {\n if (this.legendDataStartIndex === 0) {\n navigationArrows.shift();\n }\n var lastWindow = this.arrowPosWindow;\n this.arrowPosWindow = visibleDataLength;\n if (navigationArrows && navigationArrows.length > 0 && this.arrowPosWindow === remainingDataLength) {\n this.arrowPosWindow = lastWindow;\n navigationArrows.length = navigationArrows.length - 1;\n }\n };\n SVGLegend.prototype.calculateHorizontalNavigationArrowsLayout = function (title) {\n var height = SVGLegend.LegendArrowHeight;\n var width = SVGLegend.LegendArrowWidth;\n var translateY = (this.viewport.height / 2) - (height / 2);\n var data = [];\n var rightShift = title ? title.x + title.width : 0;\n var arrowLeft = visuals.SVGUtil.createArrow(width, height, 180 /*angle*/);\n var arrowRight = visuals.SVGUtil.createArrow(width, height, 0 /*angle*/);\n data.push({\n x: rightShift,\n y: translateY,\n path: arrowLeft.path,\n rotateTransform: arrowLeft.transform,\n type: 1 /* Decrease */\n });\n data.push({\n x: this.parentViewport.width - width,\n y: translateY,\n path: arrowRight.path,\n rotateTransform: arrowRight.transform,\n type: 0 /* Increase */\n });\n return data;\n };\n SVGLegend.prototype.calculateVerticalNavigationArrowsLayout = function (title) {\n var height = SVGLegend.LegendArrowHeight;\n var width = SVGLegend.LegendArrowWidth;\n var verticalCenter = this.viewport.height / 2;\n var data = [];\n var rightShift = verticalCenter + height / 2;\n var arrowTop = visuals.SVGUtil.createArrow(width, height, 270 /*angle*/);\n var arrowBottom = visuals.SVGUtil.createArrow(width, height, 90 /*angle*/);\n var titleHeight = title ? title.height : 0;\n data.push({\n x: rightShift,\n y: width + titleHeight,\n path: arrowTop.path,\n rotateTransform: arrowTop.transform,\n type: 1 /* Decrease */\n });\n data.push({\n x: rightShift,\n y: this.parentViewport.height - height,\n path: arrowBottom.path,\n rotateTransform: arrowBottom.transform,\n type: 0 /* Increase */\n });\n return data;\n };\n /**\n * Calculates the widths for each horizontal legend item.\n */\n SVGLegend.calculateHorizontalLegendItemsWidths = function (dataPoints, availableWidth, iconPadding, fontSize) {\n var dataPointsLength = dataPoints.length;\n // Set the maximum amount of space available to each item. They can use less, but can't go over this number.\n var maxItemWidth = dataPointsLength > 0 ? availableWidth / dataPointsLength | 0 : 0;\n var maxItemTextWidth = maxItemWidth - iconPadding;\n // Makes sure the amount of space available to each item is at least SVGLegend.MaxTextLength wide.\n // If you had many items and/or a narrow amount of available width, the availableTextWidthPerItem would be small, essentially making everything ellipsis.\n // This prevents that from happening by giving each item at least SVGLegend.MaxTextLength of space.\n if (maxItemTextWidth < SVGLegend.MaxTextLength) {\n maxItemTextWidth = SVGLegend.MaxTextLength;\n maxItemWidth = maxItemTextWidth + iconPadding;\n }\n // Make sure the availableWidthPerItem is less than the availableWidth. This lets the long text properly add ellipsis when we're displaying one item at a time.\n if (maxItemWidth > availableWidth) {\n maxItemWidth = availableWidth;\n maxItemTextWidth = maxItemWidth - iconPadding;\n }\n var occupiedWidth = 0;\n var legendItems = [];\n // Add legend items until we can't fit any more (the last one doesn't fit) or we've added all of them\n for (var _i = 0, dataPoints_1 = dataPoints; _i < dataPoints_1.length; _i++) {\n var dataPoint = dataPoints_1[_i];\n var textProperties = SVGLegend.getTextProperties(false, dataPoint.label, fontSize);\n var itemTextWidth = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n var desiredWidth = itemTextWidth + iconPadding;\n var overMaxWidth = desiredWidth > maxItemWidth;\n var actualWidth = overMaxWidth ? maxItemWidth : desiredWidth;\n occupiedWidth += actualWidth;\n if (occupiedWidth >= availableWidth) {\n // Always add at least 1 element\n if (legendItems.length === 0) {\n legendItems.push({\n dataPoint: dataPoint,\n textProperties: textProperties,\n desiredWidth: desiredWidth,\n desiredOverMaxWidth: true,\n width: desiredWidth\n });\n // Set the width to the amount of space we actually have\n occupiedWidth = availableWidth;\n }\n else {\n // Subtract the width from what was just added since it won't fit\n occupiedWidth -= actualWidth;\n }\n break;\n }\n legendItems.push({\n dataPoint: dataPoint,\n textProperties: textProperties,\n desiredWidth: desiredWidth,\n desiredOverMaxWidth: overMaxWidth,\n width: desiredWidth\n });\n }\n // If there are items at max width, evenly redistribute the extra space to them\n var itemsOverMax = _.filter(legendItems, function (li) { return li.desiredOverMaxWidth; });\n var numItemsOverMax = itemsOverMax.length;\n if (numItemsOverMax > 0) {\n var extraWidth = availableWidth - occupiedWidth;\n for (var _a = 0, itemsOverMax_1 = itemsOverMax; _a < itemsOverMax_1.length; _a++) {\n var item = itemsOverMax_1[_a];\n // Divvy up the extra space and add it to the max\n // We need to do this calculation in every loop since the remainingWidth may not be changed by the same amount every time\n var extraWidthPerItem = extraWidth / numItemsOverMax;\n var newMaxItemWidth = maxItemWidth + extraWidthPerItem;\n var usedExtraWidth = void 0;\n if (item.desiredWidth <= newMaxItemWidth) {\n // If the item doesn't need all the extra space, it's not at max anymore\n item.desiredOverMaxWidth = false;\n usedExtraWidth = item.desiredWidth - maxItemWidth;\n }\n else {\n // Otherwise the item is taking up all the extra space so update the actual width to indicate that\n item.width = newMaxItemWidth;\n usedExtraWidth = newMaxItemWidth - maxItemWidth;\n }\n extraWidth -= usedExtraWidth;\n numItemsOverMax--;\n }\n }\n return legendItems;\n };\n SVGLegend.prototype.calculateHorizontalLayout = function (dataPoints, title, navigationArrows) {\n debug.assertValue(navigationArrows, 'navigationArrows');\n // calculate the text shift\n var HorizontalTextShift = 4 + SVGLegend.LegendIconRadius;\n // check if we need more space for the margin, or use the default text padding\n var fontSizeBiggerThanDefault = this.legendFontSizeMarginDifference > 0;\n var fontSizeMargin = fontSizeBiggerThanDefault ? SVGLegend.TextAndIconPadding + this.legendFontSizeMarginDifference : SVGLegend.TextAndIconPadding;\n var fixedTextShift = (fontSizeMargin / (SVGLegend.LegendIconRadiusFactor / 2)) + HorizontalTextShift;\n var occupiedWidth = 0;\n // calculate the size of the space for both sides of the radius\n var iconTotalItemPadding = SVGLegend.LegendIconRadius * 2 + fontSizeMargin * 1.5;\n var numberOfItems = dataPoints.length;\n // get the Y coordinate which is the middle of the container + the middle of the text height - the delta of the text \n var defaultTextProperties = SVGLegend.getTextProperties(false, '', this.data.fontSize);\n var verticalCenter = this.viewport.height / 2;\n var textYCoordinate = verticalCenter + powerbi.TextMeasurementService.estimateSvgTextHeight(defaultTextProperties) / 2\n - powerbi.TextMeasurementService.estimateSvgTextBaselineDelta(defaultTextProperties);\n if (title) {\n occupiedWidth += title.width;\n // get the Y coordinate which is the middle of the container + the middle of the text height - the delta of the text \n title.y = verticalCenter + title.height / 2 - powerbi.TextMeasurementService.estimateSvgTextBaselineDelta(SVGLegend.getTextProperties(true, title.text, this.data.fontSize));\n }\n // if an arrow should be added, we add space for it\n if (this.legendDataStartIndex > 0) {\n occupiedWidth += SVGLegend.LegendArrowOffset;\n }\n // Calculate the width for each of the legend items\n var dataPointsLength = dataPoints.length;\n var availableWidth = this.parentViewport.width - occupiedWidth;\n var legendItems = SVGLegend.calculateHorizontalLegendItemsWidths(dataPoints, availableWidth, iconTotalItemPadding, this.data.fontSize);\n numberOfItems = legendItems.length;\n // If we can't show all the legend items, subtract the \"next\" arrow space from the available space and re-run the width calculations \n if (numberOfItems !== dataPointsLength) {\n availableWidth -= SVGLegend.LegendArrowOffset;\n legendItems = SVGLegend.calculateHorizontalLegendItemsWidths(dataPoints, availableWidth, iconTotalItemPadding, this.data.fontSize);\n numberOfItems = legendItems.length;\n }\n for (var _i = 0, legendItems_1 = legendItems; _i < legendItems_1.length; _i++) {\n var legendItem = legendItems_1[_i];\n var dataPoint = legendItem.dataPoint;\n dataPoint.glyphPosition = {\n // the space taken so far + the radius + the margin / radiusFactor to prevent huge spaces\n x: occupiedWidth + SVGLegend.LegendIconRadius + (this.legendFontSizeMarginDifference / SVGLegend.LegendIconRadiusFactor),\n // The middle of the container but a bit lower due to text not being in the middle (qP for example making middle between q and P)\n y: (this.viewport.height * SVGLegend.LegendIconYRatio),\n };\n dataPoint.textPosition = {\n x: occupiedWidth + fixedTextShift,\n y: textYCoordinate,\n };\n // If we're over the max width, process it so it fits\n if (legendItem.desiredOverMaxWidth) {\n var textWidth = legendItem.width - iconTotalItemPadding;\n var text = powerbi.TextMeasurementService.getTailoredTextOrDefault(legendItem.textProperties, textWidth);\n dataPoint.label = text;\n }\n occupiedWidth += legendItem.width;\n }\n this.visibleLegendWidth = occupiedWidth;\n this.updateNavigationArrowLayout(navigationArrows, dataPointsLength, numberOfItems);\n return numberOfItems;\n };\n SVGLegend.prototype.calculateVerticalLayout = function (dataPoints, title, navigationArrows, autoWidth) {\n var _this = this;\n // check if we need more space for the margin, or use the default text padding\n var fontSizeBiggerThenDefault = this.legendFontSizeMarginDifference > 0;\n var fontFactor = fontSizeBiggerThenDefault ? this.legendFontSizeMarginDifference : 0;\n // calculate the size needed after font size change\n var verticalLegendHeight = 20 + fontFactor;\n var spaceNeededByTitle = 15 + fontFactor;\n var extraShiftForTextAlignmentToIcon = 4 + fontFactor;\n var totalSpaceOccupiedThusFar = verticalLegendHeight;\n // the default space for text and icon radius + the margin after the font size change\n var fixedHorizontalIconShift = SVGLegend.TextAndIconPadding + SVGLegend.LegendIconRadius + (this.legendFontSizeMarginDifference / SVGLegend.LegendIconRadiusFactor);\n var fixedHorizontalTextShift = fixedHorizontalIconShift * 2;\n // check how much space is needed\n var maxHorizontalSpaceAvaliable = autoWidth\n ? this.parentViewport.width * SVGLegend.LegendMaxWidthFactor\n - fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth\n : this.lastCalculatedWidth\n - fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth;\n var numberOfItems = dataPoints.length;\n var maxHorizontalSpaceUsed = 0;\n var parentHeight = this.parentViewport.height;\n if (title) {\n totalSpaceOccupiedThusFar += spaceNeededByTitle;\n title.x = SVGLegend.TextAndIconPadding;\n title.y = spaceNeededByTitle;\n maxHorizontalSpaceUsed = title.width || 0;\n }\n // if an arrow should be added, we add space for it\n if (this.legendDataStartIndex > 0)\n totalSpaceOccupiedThusFar += SVGLegend.LegendArrowOffset;\n var dataPointsLength = dataPoints.length;\n for (var i = 0; i < dataPointsLength; i++) {\n var dp = dataPoints[i];\n var textProperties = SVGLegend.getTextProperties(false, dp.label, this.data.fontSize);\n dp.glyphPosition = {\n x: fixedHorizontalIconShift,\n y: (totalSpaceOccupiedThusFar + extraShiftForTextAlignmentToIcon) - powerbi.TextMeasurementService.estimateSvgTextBaselineDelta(textProperties)\n };\n dp.textPosition = {\n x: fixedHorizontalTextShift,\n y: totalSpaceOccupiedThusFar + extraShiftForTextAlignmentToIcon\n };\n // TODO: [PERF] Get rid of this extra measurement, and modify\n // getTailoredTextToReturnWidth + Text\n var width = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n if (width > maxHorizontalSpaceUsed) {\n maxHorizontalSpaceUsed = width;\n }\n if (width > maxHorizontalSpaceAvaliable) {\n var text = powerbi.TextMeasurementService.getTailoredTextOrDefault(textProperties, maxHorizontalSpaceAvaliable);\n dp.label = text;\n }\n totalSpaceOccupiedThusFar += verticalLegendHeight;\n if (totalSpaceOccupiedThusFar > parentHeight) {\n numberOfItems = i;\n break;\n }\n }\n if (autoWidth) {\n if (maxHorizontalSpaceUsed < maxHorizontalSpaceAvaliable) {\n this.lastCalculatedWidth = this.viewport.width = Math.ceil(maxHorizontalSpaceUsed + fixedHorizontalTextShift + SVGLegend.LegendEdgeMariginWidth);\n }\n else {\n this.lastCalculatedWidth = this.viewport.width = Math.ceil(this.parentViewport.width * SVGLegend.LegendMaxWidthFactor);\n }\n }\n else {\n this.viewport.width = this.lastCalculatedWidth;\n }\n this.visibleLegendHeight = totalSpaceOccupiedThusFar;\n navigationArrows.forEach(function (d) { return d.x = _this.lastCalculatedWidth / 2; });\n this.updateNavigationArrowLayout(navigationArrows, dataPointsLength, numberOfItems);\n return numberOfItems;\n };\n SVGLegend.prototype.drawNavigationArrows = function (layout) {\n var _this = this;\n var arrows = this.group.selectAll(SVGLegend.NavigationArrow.selector)\n .data(layout);\n arrows\n .enter()\n .append('g')\n .on('click', function (d) {\n var pos = _this.legendDataStartIndex;\n _this.legendDataStartIndex = d.type === 0 /* Increase */\n ? pos + _this.arrowPosWindow : pos - _this.arrowPosWindow;\n _this.drawLegendInternal(_this.data, _this.parentViewport, false);\n })\n .classed(SVGLegend.NavigationArrow.class, true)\n .append('path');\n arrows\n .attr('transform', function (d) { return visuals.SVGUtil.translate(d.x, d.y); })\n .select('path')\n .attr({\n 'd': function (d) { return d.path; },\n 'transform': function (d) { return d.rotateTransform; }\n });\n arrows.exit().remove();\n };\n SVGLegend.prototype.isTopOrBottom = function (orientation) {\n switch (orientation) {\n case LegendPosition.Top:\n case LegendPosition.Bottom:\n case LegendPosition.BottomCenter:\n case LegendPosition.TopCenter:\n return true;\n default:\n return false;\n }\n };\n SVGLegend.prototype.isCentered = function (orientation) {\n switch (orientation) {\n case LegendPosition.BottomCenter:\n case LegendPosition.LeftCenter:\n case LegendPosition.RightCenter:\n case LegendPosition.TopCenter:\n return true;\n default:\n return false;\n }\n };\n SVGLegend.prototype.reset = function () {\n // Intentionally left blank. \n };\n SVGLegend.getTextProperties = function (isTitle, text, fontSize) {\n return {\n text: text,\n fontFamily: isTitle ? SVGLegend.DefaultTitleFontFamily : SVGLegend.DefaultFontFamily,\n fontSize: PixelConverter.fromPoint(fontSize || SVGLegend.DefaultFontSizeInPt)\n };\n };\n SVGLegend.prototype.setTooltipToLegendItems = function (data) {\n //we save the values to tooltip before cut\n for (var _i = 0, _a = data.dataPoints; _i < _a.length; _i++) {\n var dataPoint = _a[_i];\n dataPoint.tooltip = dataPoint.label;\n }\n };\n SVGLegend.DefaultFontSizeInPt = 8;\n SVGLegend.LegendIconRadius = 5;\n SVGLegend.LegendIconRadiusFactor = 5;\n SVGLegend.MaxTextLength = 60;\n SVGLegend.MaxTitleLength = 80;\n SVGLegend.TextAndIconPadding = 5;\n SVGLegend.TitlePadding = 15;\n SVGLegend.LegendEdgeMariginWidth = 10;\n SVGLegend.LegendMaxWidthFactor = 0.3;\n SVGLegend.TopLegendHeight = 24;\n SVGLegend.DefaultTextMargin = PixelConverter.fromPointToPixel(SVGLegend.DefaultFontSizeInPt);\n SVGLegend.DefaultMaxLegendFactor = SVGLegend.MaxTitleLength / SVGLegend.DefaultTextMargin;\n SVGLegend.LegendIconYRatio = 0.52;\n // Navigation Arrow constants\n SVGLegend.LegendArrowOffset = 10;\n SVGLegend.LegendArrowHeight = 15;\n SVGLegend.LegendArrowWidth = 7.5;\n SVGLegend.DefaultFontFamily = 'wf_segoe-ui_normal';\n SVGLegend.DefaultTitleFontFamily = 'wf_segoe-ui_Semibold';\n SVGLegend.LegendItem = createClassAndSelector('legendItem');\n SVGLegend.LegendText = createClassAndSelector('legendText');\n SVGLegend.LegendIcon = createClassAndSelector('legendIcon');\n SVGLegend.LegendTitle = createClassAndSelector('legendTitle');\n SVGLegend.NavigationArrow = createClassAndSelector('navArrow');\n return SVGLegend;\n }());\n visuals.SVGLegend = SVGLegend;\n var CartesianChartInteractiveLegend = (function () {\n function CartesianChartInteractiveLegend(element) {\n this.legendContainerParent = d3.select(element.get(0));\n }\n CartesianChartInteractiveLegend.prototype.getMargins = function () {\n return {\n height: CartesianChartInteractiveLegend.LegendHeight,\n width: 0\n };\n };\n CartesianChartInteractiveLegend.prototype.drawLegend = function (legendData) {\n debug.assertValue(legendData, 'legendData');\n var data = legendData.dataPoints;\n debug.assertValue(data, 'dataPoints');\n if (data.length < 1)\n return;\n var legendContainerDiv = this.legendContainerParent.select(CartesianChartInteractiveLegend.LegendContainerSelector);\n if (legendContainerDiv.empty()) {\n if (!data.length)\n return;\n var divToPrepend = $('<div></div>')\n .height(this.getMargins().height)\n .addClass(CartesianChartInteractiveLegend.LegendContainerClass);\n // Prepending, as legend should always be on topmost visual.\n $(this.legendContainerParent[0]).prepend(divToPrepend);\n legendContainerDiv = d3.select(divToPrepend.get(0));\n }\n this.legendContainerDiv = legendContainerDiv;\n // Construct the legend title and items.\n this.drawTitle(data);\n this.drawLegendItems(data);\n };\n CartesianChartInteractiveLegend.prototype.reset = function () {\n if (this.legendContainerDiv) {\n this.legendContainerDiv.remove();\n this.legendContainerDiv = null;\n }\n };\n CartesianChartInteractiveLegend.prototype.isVisible = function () {\n return true;\n };\n CartesianChartInteractiveLegend.prototype.changeOrientation = function (orientation) {\n // Not supported\n };\n CartesianChartInteractiveLegend.prototype.getOrientation = function () {\n return LegendPosition.Top;\n };\n /**\n * Draw the legend title\n */\n CartesianChartInteractiveLegend.prototype.drawTitle = function (data) {\n debug.assert(data && data.length > 0, 'data is null or empty');\n var titleDiv = this.legendContainerDiv.selectAll('div.' + CartesianChartInteractiveLegend.LegendTitleClass);\n var item = titleDiv.data([data[0]]);\n // Enter\n var itemEnter = item.enter();\n var titleDivEnter = itemEnter.append('div').attr('class', CartesianChartInteractiveLegend.LegendTitleClass);\n titleDivEnter\n .filter(function (d) { return d.iconOnlyOnLabel; })\n .append('span')\n .attr('class', CartesianChartInteractiveLegend.legendIconClass)\n .html(CartesianChartInteractiveLegend.legendPlaceSelector);\n titleDivEnter.append('span');\n // Update\n item.filter(function (d) { return d.iconOnlyOnLabel; })\n .select('span.' + CartesianChartInteractiveLegend.legendIconClass)\n .style(CartesianChartInteractiveLegend.legendColorCss, function (d) { return d.color; });\n item.select('span:last-child').text(function (d) { return d.category; });\n };\n /**\n * Draw the legend items\n */\n CartesianChartInteractiveLegend.prototype.drawLegendItems = function (data) {\n // Add Mesaures - the items of the category in the legend\n this.ensureLegendTableCreated();\n var dataPointsMatrix = CartesianChartInteractiveLegend.splitArrayToOddEven(data);\n var legendItemsContainer = this.legendContainerDiv.select('tbody').selectAll('tr').data(dataPointsMatrix);\n // trs is table rows. \n // there are two table rows.\n // the order of insertion to the legend table is:\n // Even data points got inserted into the 1st line\n // Odd data points got inserted into the 2nd line\n // ----------------------------\n // | value0 | value 2 | value 4\n // ----------------------------\n // | value1 | value 3 | \n // ----------------------------\n // \n // Enter\n var legendItemsEnter = legendItemsContainer.enter();\n var rowEnter = legendItemsEnter.append('tr');\n var cellEnter = rowEnter.selectAll('td')\n .data(function (d) { return d; }, function (d) { return d.label; })\n .enter()\n .append('td').attr('class', CartesianChartInteractiveLegend.LegendItem);\n var cellSpanEnter = cellEnter.append('span');\n cellSpanEnter.filter(function (d) { return !d.iconOnlyOnLabel; })\n .append('span')\n .html(CartesianChartInteractiveLegend.legendPlaceSelector)\n .attr('class', CartesianChartInteractiveLegend.legendIconClass)\n .attr('white-space', 'nowrap');\n cellSpanEnter.append('span').attr('class', CartesianChartInteractiveLegend.legendItemNameClass);\n cellSpanEnter.append('span').attr('class', CartesianChartInteractiveLegend.legendItemMeasureClass);\n // Update\n var legendCells = legendItemsContainer.selectAll('td').data(function (d) { return d; }, function (d) { return d.label; });\n legendCells.select('span.' + CartesianChartInteractiveLegend.legendItemNameClass).html(function (d) { return powerbi.visuals.TextUtil.removeBreakingSpaces(d.label); });\n legendCells.select('span.' + CartesianChartInteractiveLegend.legendItemMeasureClass).html(function (d) { return '&nbsp;' + d.measure; });\n legendCells.select('span.' + CartesianChartInteractiveLegend.legendIconClass).style('color', function (d) { return d.color; });\n // Exit\n legendCells.exit().remove();\n };\n /**\n * Ensure legend table is created and set horizontal pan gestures on it\n */\n CartesianChartInteractiveLegend.prototype.ensureLegendTableCreated = function () {\n if (this.legendContainerDiv.select('div table').empty()) {\n var legendTable = this.legendContainerDiv.append('div').append('table');\n legendTable.style('table-layout', 'fixed').append('tbody');\n // Setup Pan Gestures of the legend\n this.setPanGestureOnLegend(legendTable);\n }\n };\n /**\n * Set Horizontal Pan gesture for the legend\n */\n CartesianChartInteractiveLegend.prototype.setPanGestureOnLegend = function (legendTable) {\n var viewportWidth = $(this.legendContainerDiv.select('div:nth-child(2)')[0]).width();\n var xscale = d3.scale.linear().domain([0, viewportWidth]).range([0, viewportWidth]);\n var zoom = d3.behavior.zoom()\n .scaleExtent([1, 1]) // disable scaling\n .x(xscale)\n .on(\"zoom\", function () {\n // horizontal pan is valid only in case the legend items width are bigger than the viewport width\n if ($(legendTable[0]).width() > viewportWidth) {\n var t = zoom.translate();\n var tx_1 = t[0];\n var ty = t[1];\n tx_1 = Math.min(tx_1, 0);\n tx_1 = Math.max(tx_1, viewportWidth - $(legendTable[0]).width());\n zoom.translate([tx_1, ty]);\n legendTable.style(\"-ms-transform\", function () {\n return visuals.SVGUtil.translateXWithPixels(tx_1);\n });\n legendTable.style(\"-webkit-transform\", function () {\n return visuals.SVGUtil.translateXWithPixels(tx_1);\n });\n legendTable.style(\"transform\", function () {\n return visuals.SVGUtil.translateXWithPixels(tx_1);\n });\n }\n });\n if (this.legendContainerDiv) {\n this.legendContainerDiv.call(zoom);\n }\n else {\n legendTable.call(zoom);\n }\n };\n /**\n * Split legend data points array into odd and even arrays\n * Even array will be the legend first line and Odd array will be the 2nd legend line\n */\n CartesianChartInteractiveLegend.splitArrayToOddEven = function (data) {\n var oddData = [];\n var evenData = [];\n for (var i = 0; i < data.length; ++i) {\n if (i % 2 === 0) {\n evenData.push(data[i]);\n }\n else {\n oddData.push(data[i]);\n }\n }\n return [evenData, oddData];\n };\n CartesianChartInteractiveLegend.LegendHeight = 70;\n CartesianChartInteractiveLegend.LegendContainerClass = 'interactive-legend';\n CartesianChartInteractiveLegend.LegendContainerSelector = '.interactive-legend';\n CartesianChartInteractiveLegend.LegendTitleClass = 'title';\n CartesianChartInteractiveLegend.LegendItem = 'item';\n CartesianChartInteractiveLegend.legendPlaceSelector = '\\u25A0';\n CartesianChartInteractiveLegend.legendIconClass = 'icon';\n CartesianChartInteractiveLegend.legendColorCss = 'color';\n CartesianChartInteractiveLegend.legendItemNameClass = 'itemName';\n CartesianChartInteractiveLegend.legendItemMeasureClass = 'itemMeasure';\n return CartesianChartInteractiveLegend;\n }());\n var LegendData;\n (function (LegendData) {\n LegendData.DefaultLegendLabelFillColor = '#666666';\n function update(legendData, legendObject) {\n debug.assertValue(legendData, 'legendData');\n debug.assertValue(legendObject, 'legendObject');\n if (legendObject[visuals.legendProps.show] == null) {\n legendObject[visuals.legendProps.show] = true;\n }\n if (legendObject[visuals.legendProps.show] === false)\n legendData.dataPoints = [];\n if (legendObject[visuals.legendProps.show] === true && legendObject[visuals.legendProps.position] == null)\n legendObject[visuals.legendProps.position] = visuals.legendPosition.top;\n if (legendObject[visuals.legendProps.fontSize] !== undefined)\n legendData.fontSize = legendObject[visuals.legendProps.fontSize];\n if (legendObject[visuals.legendProps.labelColor] !== undefined) {\n var fillColor = legendObject[visuals.legendProps.labelColor];\n if (fillColor != null) {\n legendData.labelColor = fillColor.solid.color;\n }\n }\n if (legendObject[visuals.legendProps.showTitle] === false)\n legendData.title = \"\";\n else if (legendObject[visuals.legendProps.titleText] !== undefined) {\n legendData.title = legendObject[visuals.legendProps.titleText];\n }\n }\n LegendData.update = update;\n })(LegendData = visuals.LegendData || (visuals.LegendData = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var axisScale;\n (function (axisScale) {\n axisScale.linear = 'linear';\n axisScale.log = 'log';\n axisScale.type = powerbi.createEnumType([\n { value: axisScale.linear, displayName: function (resources) { return resources.get('Visual_Axis_Linear'); } },\n { value: axisScale.log, displayName: function (resources) { return resources.get('Visual_Axis_Log'); } }\n ]);\n })(axisScale = visuals.axisScale || (visuals.axisScale = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var axisStyle;\n (function (axisStyle) {\n axisStyle.showBoth = 'showBoth';\n axisStyle.showTitleOnly = 'showTitleOnly';\n axisStyle.showUnitOnly = 'showUnitOnly';\n axisStyle.type = powerbi.createEnumType([\n { value: axisStyle.showTitleOnly, displayName: function (resources) { return resources.get('Visual_Axis_ShowTitleOnly'); } },\n { value: axisStyle.showUnitOnly, displayName: function (resources) { return resources.get('Visual_Axis_ShowUnitOnly'); } },\n { value: axisStyle.showBoth, displayName: function (resources) { return resources.get('Visual_Axis_ShowBoth'); } }\n ]);\n })(axisStyle = visuals.axisStyle || (visuals.axisStyle = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var axisType;\n (function (axisType) {\n axisType.scalar = 'Scalar';\n axisType.categorical = 'Categorical';\n axisType.both = 'Both';\n axisType.type = powerbi.createEnumType([\n { value: axisType.scalar, displayName: function (resources) { return resources.get('Visual_Axis_Scalar'); } },\n { value: axisType.categorical, displayName: function (resources) { return resources.get('Visual_Axis_Categorical'); } },\n ]);\n })(axisType = visuals.axisType || (visuals.axisType = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var basicShapeType;\n (function (basicShapeType) {\n basicShapeType.rectangle = 'rectangle';\n basicShapeType.oval = 'oval';\n basicShapeType.line = 'line';\n basicShapeType.arrow = 'arrow';\n basicShapeType.triangle = 'triangle';\n basicShapeType.type = powerbi.createEnumType([\n { value: basicShapeType.rectangle, displayName: 'rectangle' },\n { value: basicShapeType.oval, displayName: 'oval' },\n { value: basicShapeType.line, displayName: 'line' },\n { value: basicShapeType.arrow, displayName: 'arrow' },\n { value: basicShapeType.triangle, displayName: 'triangle' }\n ]);\n })(basicShapeType = visuals.basicShapeType || (visuals.basicShapeType = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var imageScalingType;\n (function (imageScalingType) {\n imageScalingType.normal = 'Normal';\n imageScalingType.fit = 'Fit';\n imageScalingType.fill = 'Fill';\n imageScalingType.type = powerbi.createEnumType([\n { value: imageScalingType.normal, displayName: function (resources) { return resources.get('Visual_ImageScalingType_Normal'); } },\n { value: imageScalingType.fit, displayName: function (resources) { return resources.get('Visual_ImageScalingType_Fit'); } },\n { value: imageScalingType.fill, displayName: function (resources) { return resources.get('Visual_ImageScalingType_Fill'); } },\n ]);\n })(imageScalingType = visuals.imageScalingType || (visuals.imageScalingType = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var labelPosition;\n (function (labelPosition) {\n labelPosition.insideEnd = 'InsideEnd';\n labelPosition.insideCenter = 'InsideCenter';\n labelPosition.outsideEnd = 'OutsideEnd';\n labelPosition.insideBase = 'InsideBase';\n labelPosition.type = powerbi.createEnumType([\n { value: labelPosition.insideEnd, displayName: function (resources) { return resources.get('Visual_LabelPosition_InsideEnd'); } },\n { value: labelPosition.outsideEnd, displayName: function (resources) { return resources.get('Visual_LabelPosition_OutsideEnd'); } },\n { value: labelPosition.insideCenter, displayName: function (resources) { return resources.get('Visual_LabelPosition_InsideCenter'); } },\n { value: labelPosition.insideBase, displayName: function (resources) { return resources.get('Visual_LabelPosition_InsideBase'); } },\n ]);\n })(labelPosition = visuals.labelPosition || (visuals.labelPosition = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var labelStyle;\n (function (labelStyle) {\n labelStyle.category = 'Category';\n labelStyle.data = 'Data';\n labelStyle.both = 'Both';\n labelStyle.type = powerbi.createEnumType([\n { value: labelStyle.category, displayName: function (resources) { return resources.get('Visual_LabelStyle_Category'); } },\n { value: labelStyle.data, displayName: function (resources) { return resources.get('Visual_LabelStyle_DataValue'); } },\n { value: labelStyle.both, displayName: function (resources) { return resources.get('Visual_LabelStyle_Both'); } },\n ]);\n })(labelStyle = visuals.labelStyle || (visuals.labelStyle = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var legendPosition;\n (function (legendPosition) {\n legendPosition.top = 'Top';\n legendPosition.bottom = 'Bottom';\n legendPosition.left = 'Left';\n legendPosition.right = 'Right';\n legendPosition.topCenter = 'TopCenter';\n legendPosition.bottomCenter = 'BottomCenter';\n legendPosition.leftCenter = 'LeftCenter';\n legendPosition.rightCenter = 'RightCenter';\n legendPosition.type = powerbi.createEnumType([\n { value: legendPosition.top, displayName: function (resources) { return resources.get('Visual_LegendPosition_Top'); } },\n { value: legendPosition.bottom, displayName: function (resources) { return resources.get('Visual_LegendPosition_Bottom'); } },\n { value: legendPosition.left, displayName: function (resources) { return resources.get('Visual_LegendPosition_Left'); } },\n { value: legendPosition.right, displayName: function (resources) { return resources.get('Visual_LegendPosition_Right'); } },\n { value: legendPosition.topCenter, displayName: function (resources) { return resources.get('Visual_LegendPosition_TopCenter'); } },\n { value: legendPosition.bottomCenter, displayName: function (resources) { return resources.get('Visual_LegendPosition_BottomCenter'); } },\n { value: legendPosition.leftCenter, displayName: function (resources) { return resources.get('Visual_LegendPosition_LeftCenter'); } },\n { value: legendPosition.rightCenter, displayName: function (resources) { return resources.get('Visual_LegendPosition_RightCenter'); } },\n ]);\n })(legendPosition = visuals.legendPosition || (visuals.legendPosition = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var kpiDirection;\n (function (kpiDirection) {\n kpiDirection.positive = 'Positive';\n kpiDirection.negative = 'Negative';\n kpiDirection.type = powerbi.createEnumType([\n { value: kpiDirection.positive, displayName: function (resources) { return resources.get('Visual_KPI_Direction_Positive'); } },\n { value: kpiDirection.negative, displayName: function (resources) { return resources.get('Visual_KPI_Direction_Negative'); } }\n ]);\n })(kpiDirection = visuals.kpiDirection || (visuals.kpiDirection = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var lineStyle;\n (function (lineStyle) {\n lineStyle.dashed = 'dashed';\n lineStyle.solid = 'solid';\n lineStyle.dotted = 'dotted';\n lineStyle.type = powerbi.createEnumType([\n { value: lineStyle.dashed, displayName: function (resources) { return resources.get('Visual_LineStyle_Dashed'); } },\n { value: lineStyle.solid, displayName: function (resources) { return resources.get('Visual_LineStyle_Solid'); } },\n { value: lineStyle.dotted, displayName: function (resources) { return resources.get('Visual_LineStyle_Dotted'); } }\n ]);\n })(lineStyle = visuals.lineStyle || (visuals.lineStyle = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var outline;\n (function (outline_1) {\n outline_1.none = 'None';\n outline_1.bottomOnly = 'BottomOnly';\n outline_1.topOnly = 'TopOnly';\n outline_1.leftOnly = 'LeftOnly';\n outline_1.rightOnly = 'RightOnly';\n outline_1.topBottom = 'TopBottom';\n outline_1.leftRight = 'LeftRight';\n outline_1.frame = 'Frame';\n function showTop(outline) {\n return [outline_1.topOnly, outline_1.topBottom, outline_1.frame].some(function (o) { return o === outline; });\n }\n outline_1.showTop = showTop;\n function showRight(outline) {\n return [outline_1.rightOnly, outline_1.leftRight, outline_1.frame].some(function (o) { return o === outline; });\n }\n outline_1.showRight = showRight;\n function showBottom(outline) {\n return [outline_1.bottomOnly, outline_1.topBottom, outline_1.frame].some(function (o) { return o === outline; });\n }\n outline_1.showBottom = showBottom;\n function showLeft(outline) {\n return [outline_1.leftOnly, outline_1.leftRight, outline_1.frame].some(function (o) { return o === outline; });\n }\n outline_1.showLeft = showLeft;\n outline_1.type = powerbi.createEnumType([\n { value: outline_1.none, displayName: function (resources) { return resources.get('Visual_Outline_none'); } },\n { value: outline_1.bottomOnly, displayName: function (resources) { return resources.get('Visual_Outline_bottom_only'); } },\n { value: outline_1.topOnly, displayName: function (resources) { return resources.get('Visual_Outline_top_only'); } },\n { value: outline_1.leftOnly, displayName: function (resources) { return resources.get('Visual_Outline_LeftOnly'); } },\n { value: outline_1.rightOnly, displayName: function (resources) { return resources.get('Visual_Outline_RightOnly'); } },\n { value: outline_1.topBottom, displayName: function (resources) { return resources.get('Visual_Outline_top_Bottom'); } },\n { value: outline_1.leftRight, displayName: function (resources) { return resources.get('Visual_Outline_leftRight'); } },\n { value: outline_1.frame, displayName: function (resources) { return resources.get('Visual_Outline_frame'); } }\n ]);\n })(outline = visuals.outline || (visuals.outline = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var referenceLinePosition;\n (function (referenceLinePosition) {\n referenceLinePosition.back = 'back';\n referenceLinePosition.front = 'front';\n referenceLinePosition.type = powerbi.createEnumType([\n { value: referenceLinePosition.back, displayName: function (resources) { return resources.get('Visual_Reference_Line_Behind'); } },\n { value: referenceLinePosition.front, displayName: function (resources) { return resources.get('Visual_Reference_Line_InFront'); } },\n ]);\n })(referenceLinePosition = visuals.referenceLinePosition || (visuals.referenceLinePosition = {}));\n var referenceLineDataLabelHorizontalPosition;\n (function (referenceLineDataLabelHorizontalPosition) {\n referenceLineDataLabelHorizontalPosition.left = 'left';\n referenceLineDataLabelHorizontalPosition.right = 'right';\n referenceLineDataLabelHorizontalPosition.type = powerbi.createEnumType([\n { value: referenceLineDataLabelHorizontalPosition.left, displayName: function (resources) { return resources.get('Visual_Reference_Line_Data_Label_Left'); } },\n { value: referenceLineDataLabelHorizontalPosition.right, displayName: function (resources) { return resources.get('Visual_Reference_Line_Data_Label_Right'); } },\n ]);\n })(referenceLineDataLabelHorizontalPosition = visuals.referenceLineDataLabelHorizontalPosition || (visuals.referenceLineDataLabelHorizontalPosition = {}));\n var referenceLineDataLabelVerticalPosition;\n (function (referenceLineDataLabelVerticalPosition) {\n referenceLineDataLabelVerticalPosition.above = 'above';\n referenceLineDataLabelVerticalPosition.under = 'under';\n referenceLineDataLabelVerticalPosition.type = powerbi.createEnumType([\n { value: referenceLineDataLabelVerticalPosition.above, displayName: function (resources) { return resources.get('Visual_Reference_Line_Data_Label_Above'); } },\n { value: referenceLineDataLabelVerticalPosition.under, displayName: function (resources) { return resources.get('Visual_Reference_Line_Data_Label_Under'); } },\n ]);\n })(referenceLineDataLabelVerticalPosition = visuals.referenceLineDataLabelVerticalPosition || (visuals.referenceLineDataLabelVerticalPosition = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var slicerOrientation;\n (function (slicerOrientation) {\n slicerOrientation.type = powerbi.createEnumType([\n { value: 0 /* Vertical */, displayName: function (resources) { return resources.get('Slicer_Orientation_Vertical'); } },\n { value: 1 /* Horizontal */, displayName: function (resources) { return resources.get('Slicer_Orientation_Horizontal'); } },\n ]);\n })(slicerOrientation = visuals.slicerOrientation || (visuals.slicerOrientation = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var yAxisPosition;\n (function (yAxisPosition) {\n yAxisPosition.left = 'Left';\n yAxisPosition.right = 'Right';\n yAxisPosition.type = powerbi.createEnumType([\n { value: yAxisPosition.left, displayName: function (resources) { return resources.get('Visual_yAxis_Left'); } },\n { value: yAxisPosition.right, displayName: function (resources) { return resources.get('Visual_yAxis_Right'); } },\n ]);\n })(yAxisPosition = visuals.yAxisPosition || (visuals.yAxisPosition = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var AnimatorCommon;\n (function (AnimatorCommon) {\n AnimatorCommon.MinervaAnimationDuration = 250;\n // The maximum number of data points we can performantly animate with SVG. If we have more, turn off animations.\n AnimatorCommon.MaxDataPointsToAnimate = 1000;\n function GetAnimationDuration(animator, suppressAnimations) {\n return (suppressAnimations || !animator) ? 0 : animator.getDuration();\n }\n AnimatorCommon.GetAnimationDuration = GetAnimationDuration;\n })(AnimatorCommon = visuals.AnimatorCommon || (visuals.AnimatorCommon = {}));\n /**\n * We just need to have a non-null animator to allow axis animations in cartesianChart.\n * Note: Use this temporarily for Line/Scatter until we add more animations (MinervaPlugins only).\n */\n var BaseAnimator = (function () {\n function BaseAnimator(options) {\n if (options && options.duration) {\n this.animationDuration = options.duration;\n }\n this.animationDuration = this.animationDuration >= 0 ? this.animationDuration : AnimatorCommon.MinervaAnimationDuration;\n }\n BaseAnimator.prototype.getDuration = function () {\n return this.animationDuration;\n };\n BaseAnimator.prototype.animate = function (options) {\n return null;\n };\n BaseAnimator.prototype.getEasing = function () {\n return 'cubic-in-out';\n };\n return BaseAnimator;\n }());\n visuals.BaseAnimator = BaseAnimator;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var WebColumnChartAnimator = (function (_super) {\n __extends(WebColumnChartAnimator, _super);\n function WebColumnChartAnimator(options) {\n _super.call(this, options);\n }\n WebColumnChartAnimator.prototype.animate = function (options) {\n var result = {\n failed: true,\n shapes: null,\n };\n var viewModel = options.viewModel;\n var previousViewModel = this.previousViewModel;\n var dataPointCount = viewModel.categories.length * viewModel.series.length;\n if (dataPointCount > visuals.AnimatorCommon.MaxDataPointsToAnimate) {\n // Too many data points to animate.\n return result;\n }\n if (!previousViewModel) {\n }\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\n result = this.animateNormalToHighlighted(options);\n }\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToHighlighted(options);\n }\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToNormal(options);\n }\n this.previousViewModel = viewModel;\n return result;\n };\n WebColumnChartAnimator.prototype.animateNormalToHighlighted = function (options) {\n var data = options.viewModel;\n var itemCS = options.itemCS;\n var shapeSelection = options.series.selectAll(itemCS.selector);\n var shapes = shapeSelection.data(function (d) { return d.data; }, function (d) { return d.key; });\n var hasHighlights = data.hasHighlights;\n shapes\n .enter()\n .append('rect')\n .attr(\"class\", function (d) { return itemCS.class.concat(d.highlight ? \" highlight\" : \"\"); })\n .attr(options.layout.shapeLayoutWithoutHighlights); // Start out at the non-highlight layout\n shapes\n .style(\"fill\", function (d) { return d.color; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, false, hasHighlights); })\n .transition()\n .duration(this.animationDuration)\n .attr(options.layout.shapeLayout);\n shapes\n .exit()\n .remove();\n return {\n failed: false,\n shapes: shapes,\n };\n };\n WebColumnChartAnimator.prototype.animateHighlightedToHighlighted = function (options) {\n var shapes = this.animateDefaultShapes(options.viewModel, options.series, options.layout, options.itemCS);\n return {\n failed: false,\n shapes: shapes,\n };\n };\n WebColumnChartAnimator.prototype.animateHighlightedToNormal = function (options) {\n var itemCS = options.itemCS;\n var shapeSelection = options.series.selectAll(itemCS.selector);\n var shapes = shapeSelection.data(function (d) { return d.data; }, function (d) { return d.key; });\n var hasSelection = options.interactivityService && options.interactivityService.hasSelection();\n shapes\n .enter()\n .append('rect')\n .attr(\"class\", function (d) { return itemCS.class.concat(d.highlight ? \" highlight\" : \"\"); });\n shapes\n .style(\"fill\", function (d) { return d.color; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, d.selected, !d.selected); })\n .transition()\n .duration(this.animationDuration)\n .attr(options.layout.shapeLayout)\n .transition()\n .duration(0)\n .delay(this.animationDuration)\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false); });\n shapes\n .exit()\n .transition()\n .duration(this.animationDuration)\n .attr(hasSelection ? options.layout.zeroShapeLayout : options.layout.shapeLayoutWithoutHighlights)\n .remove();\n return {\n failed: false,\n shapes: shapes,\n };\n };\n WebColumnChartAnimator.prototype.animateDefaultShapes = function (data, series, layout, itemCS) {\n var shapeSelection = series.selectAll(itemCS.selector);\n var shapes = shapeSelection.data(function (d) { return d.data; }, function (d) { return d.key; });\n shapes\n .enter()\n .append('rect')\n .attr(\"class\", function (d) { return itemCS.class.concat(d.highlight ? \" highlight\" : \"\"); });\n shapes\n .style(\"fill\", function (d) { return d.color; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, false, data.hasHighlights); })\n .transition()\n .duration(this.animationDuration)\n .attr(layout.shapeLayout);\n shapes\n .exit()\n .remove();\n return shapes;\n };\n return WebColumnChartAnimator;\n }(visuals.BaseAnimator));\n visuals.WebColumnChartAnimator = WebColumnChartAnimator;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var WebDonutChartAnimator = (function (_super) {\n __extends(WebDonutChartAnimator, _super);\n function WebDonutChartAnimator(options) {\n _super.call(this, options);\n }\n WebDonutChartAnimator.prototype.animate = function (options) {\n var result = {\n failed: true,\n shapes: null,\n highlightShapes: null,\n };\n var viewModel = options.viewModel;\n var previousViewModel = this.previousViewModel;\n if (!previousViewModel) {\n }\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\n result = this.animateNormalToHighlighted(options);\n }\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToHighlighted(options);\n }\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToNormal(options);\n }\n this.previousViewModel = viewModel;\n return result;\n };\n WebDonutChartAnimator.prototype.animateNormalToHighlighted = function (options) {\n var shapes = this.animateDefaultShapes(options);\n var highlightShapes = options.graphicsContext.select('.slices')\n .selectAll('path.slice-highlight')\n .data(options.viewModel.dataPoints.filter(function (value) { return value.data.highlightRatio != null; }), function (d) { return d.data.identity.getKey(); });\n highlightShapes.enter()\n .insert('path')\n .classed('slice-highlight', true)\n .each(function (d) { this._current = d; });\n visuals.DonutChart.isSingleColor(options.viewModel.dataPoints.filter(function (value) { return value.data.highlightRatio != null; }));\n highlightShapes\n .style('fill', function (d) { return d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, true, false, options.viewModel.hasHighlights); })\n .style(\"stroke-dasharray\", function (d) { return visuals.DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio, d.data.highlightRatio); })\n .style(\"stroke-width\", function (d) { return d.data.strokeWidth; })\n .attr(options.layout.shapeLayout) // Start at the non-highlight layout, then transition to the highlight layout.\n .transition()\n .duration(this.animationDuration)\n .attr(options.layout.highlightShapeLayout);\n highlightShapes.exit()\n .remove();\n visuals.NewDataLabelUtils.drawDefaultLabels(options.labelGraphicsContext, options.labels, false, true, true /*has tooltip */);\n visuals.NewDataLabelUtils.drawLabelLeaderLines(options.labelGraphicsContext, options.labels);\n return {\n failed: false,\n shapes: shapes,\n highlightShapes: highlightShapes,\n };\n };\n WebDonutChartAnimator.prototype.animateHighlightedToHighlighted = function (options) {\n var shapes = this.animateDefaultShapes(options);\n var highlightShapes = this.animateDefaultHighlightShapes(options);\n visuals.NewDataLabelUtils.drawDefaultLabels(options.labelGraphicsContext, options.labels, false, true, true /*has tooltip */);\n visuals.NewDataLabelUtils.drawLabelLeaderLines(options.labelGraphicsContext, options.labels);\n return {\n failed: false,\n shapes: shapes,\n highlightShapes: highlightShapes,\n };\n };\n WebDonutChartAnimator.prototype.animateHighlightedToNormal = function (options) {\n var hasSelection = options.interactivityService && options.interactivityService.hasSelection();\n var duration = this.animationDuration;\n var shapes = options.graphicsContext.select('.slices')\n .selectAll('path.slice')\n .data(options.viewModel.dataPoints, function (d) { return d.data.identity.getKey(); });\n shapes.enter()\n .insert('path')\n .classed('slice', true)\n .each(function (d) { this._current = d; });\n visuals.DonutChart.isSingleColor(options.viewModel.dataPoints);\n // For any slice that is selected we want to keep showing it as dimmed (partially highlighted). After the highlight animation\n // finishes we will set the opacity based on the selection state.\n shapes\n .style('fill', function (d) { return d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, d.data.selected, !d.data.selected); })\n .style(\"stroke-dasharray\", function (d) { return visuals.DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio); })\n .style(\"stroke-width\", function (d) { return d.data.strokeWidth; })\n .transition()\n .duration(duration)\n .attr(options.layout.shapeLayout)\n .transition()\n .duration(0)\n .delay(duration)\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false); });\n ;\n shapes.exit()\n .remove();\n var highlightShapes = options.graphicsContext.select('.slices')\n .selectAll('path.slice-highlight')\n .data(options.viewModel.dataPoints.filter(function (value) { return value.data.highlightRatio != null; }), function (d) { return d.data.identity.getKey(); });\n highlightShapes.enter()\n .insert('path')\n .classed('slice-highlight', true)\n .each(function (d) { this._current = d; });\n visuals.DonutChart.isSingleColor(options.viewModel.dataPoints.filter(function (value) { return value.data.highlightRatio != null; }));\n highlightShapes\n .style('fill', function (d) { return d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(false, true, false, true); })\n .style(\"stroke-dasharray\", function (d) { return visuals.DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio, d.data.highlightRatio); })\n .style(\"stroke-width\", function (d) { return d.data.strokeWidth; })\n .transition()\n .duration(duration)\n .attr(hasSelection ? options.layout.zeroShapeLayout : options.layout.shapeLayout) // Transition to the non-highlight layout\n .remove();\n highlightShapes.exit()\n .remove();\n visuals.NewDataLabelUtils.drawDefaultLabels(options.labelGraphicsContext, options.labels, false, true, true /*has tooltip */);\n visuals.NewDataLabelUtils.drawLabelLeaderLines(options.labelGraphicsContext, options.labels);\n return {\n failed: false,\n shapes: shapes,\n highlightShapes: highlightShapes,\n };\n };\n WebDonutChartAnimator.prototype.animateDefaultShapes = function (options) {\n var shapes = options.graphicsContext.select('.slices')\n .selectAll('path.slice')\n .data(options.viewModel.dataPoints, function (d) { return d.data.identity.getKey(); });\n shapes.enter()\n .insert('path')\n .classed('slice', true)\n .each(function (d) { this._current = d; });\n visuals.DonutChart.isSingleColor(options.viewModel.dataPoints);\n shapes\n .style('fill', function (d) { return d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, false, options.viewModel.hasHighlights); })\n .style(\"stroke-dasharray\", function (d) { return visuals.DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio); })\n .style(\"stroke-width\", function (d) { return d.data.strokeWidth; })\n .transition()\n .duration(this.animationDuration)\n .attr(options.layout.shapeLayout);\n shapes.exit()\n .remove();\n return shapes;\n };\n WebDonutChartAnimator.prototype.animateDefaultHighlightShapes = function (options) {\n var highlightShapes = options.graphicsContext.select('.slices')\n .selectAll('path.slice-highlight')\n .data(options.viewModel.dataPoints.filter(function (value) { return value.data.highlightRatio != null; }), function (d) { return d.data.identity.getKey(); });\n highlightShapes.enter()\n .insert('path')\n .classed('slice-highlight', true)\n .each(function (d) { this._current = d; });\n visuals.DonutChart.isSingleColor(options.viewModel.dataPoints.filter(function (value) { return value.data.highlightRatio != null; }));\n highlightShapes\n .style('fill', function (d) { return d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, true, false, options.viewModel.hasHighlights); })\n .style(\"stroke-dasharray\", function (d) { return visuals.DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio, d.data.highlightRatio); })\n .style(\"stroke-width\", function (d) { return d.data.strokeWidth; })\n .transition()\n .duration(this.animationDuration)\n .attr(options.layout.highlightShapeLayout);\n highlightShapes.exit()\n .remove();\n return highlightShapes;\n };\n return WebDonutChartAnimator;\n }(visuals.BaseAnimator));\n visuals.WebDonutChartAnimator = WebDonutChartAnimator;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var WebFunnelAnimator = (function (_super) {\n __extends(WebFunnelAnimator, _super);\n function WebFunnelAnimator(options) {\n _super.call(this, options);\n }\n WebFunnelAnimator.prototype.animate = function (options) {\n var result = {\n failed: true,\n shapes: null,\n dataLabels: null,\n };\n var viewModel = options.viewModel;\n var previousViewModel = this.previousViewModel;\n if (!previousViewModel) {\n }\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\n result = this.animateNormalToHighlighted(options);\n }\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToHighlighted(options);\n }\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToNormal(options);\n }\n this.previousViewModel = viewModel;\n return result;\n };\n WebFunnelAnimator.prototype.animateNormalToHighlighted = function (options) {\n var data = options.viewModel;\n var layout = options.layout;\n var hasHighlights = true;\n var hasSelection = false;\n this.animateDefaultAxis(options.axisGraphicsContext, options.axisOptions, options.isHidingPercentBars);\n var shapes = options.shapeGraphicsContext.selectAll(visuals.FunnelChart.Selectors.funnel.bars.selector).data(data.slices, function (d) { return d.key; });\n shapes.enter()\n .append('rect')\n .attr(\"class\", function (d) { return d.highlight ? visuals.FunnelChart.FunnelBarHighlightClass : visuals.FunnelChart.Selectors.funnel.bars.class; })\n .attr(layout.shapeLayoutWithoutHighlights); // Start by laying out all rectangles ignoring highlights\n shapes\n .style(\"fill\", function (d) { return d.color; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights); })\n .transition()\n .duration(this.animationDuration)\n .attr(layout.shapeLayout); // Then transition to the layout that uses highlights\n shapes.exit().remove();\n this.animatePercentBars(options);\n var dataLabels = this.animateDefaultDataLabels(options);\n return {\n failed: false,\n shapes: shapes,\n dataLabels: dataLabels,\n };\n };\n WebFunnelAnimator.prototype.animateHighlightedToHighlighted = function (options) {\n var data = options.viewModel;\n var layout = options.layout;\n this.animateDefaultAxis(options.axisGraphicsContext, options.axisOptions, options.isHidingPercentBars);\n // Simply animate to the new shapes.\n var shapes = this.animateDefaultShapes(data, data.slices, options.shapeGraphicsContext, layout);\n this.animatePercentBars(options);\n var dataLabels = this.animateDefaultDataLabels(options);\n return {\n failed: false,\n shapes: shapes,\n dataLabels: dataLabels,\n };\n };\n WebFunnelAnimator.prototype.animateHighlightedToNormal = function (options) {\n var data = options.viewModel;\n var layout = options.layout;\n var hasSelection = options.interactivityService ? options.interactivityService.hasSelection() : false;\n this.animateDefaultAxis(options.axisGraphicsContext, options.axisOptions, options.isHidingPercentBars);\n var shapes = options.shapeGraphicsContext.selectAll(visuals.FunnelChart.Selectors.funnel.bars.selector).data(data.slices, function (d) { return d.key; });\n shapes.enter()\n .append('rect')\n .attr(\"class\", function (d) { return d.highlight ? visuals.FunnelChart.FunnelBarHighlightClass : visuals.FunnelChart.Selectors.funnel.bars.class; });\n shapes\n .style(\"fill\", function (d) { return d.color; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, !d.selected); })\n .transition()\n .duration(this.animationDuration)\n .attr(layout.shapeLayoutWithoutHighlights) // Transition to layout without highlights\n .transition()\n .duration(0)\n .delay(this.animationDuration)\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false); });\n var exitShapes = shapes.exit();\n exitShapes\n .transition()\n .duration(this.animationDuration)\n .attr(hasSelection ? layout.zeroShapeLayout : layout.shapeLayoutWithoutHighlights) // Transition to layout without highlights\n .remove();\n this.animatePercentBars(options);\n var dataLabels = this.animateDefaultDataLabels(options);\n return {\n failed: false,\n shapes: shapes,\n dataLabels: dataLabels,\n };\n };\n WebFunnelAnimator.prototype.animateDefaultAxis = function (graphicsContext, axisOptions, isHidingPercentBars) {\n var xScaleForAxis = d3.scale.ordinal()\n .domain(axisOptions.categoryLabels)\n .rangeBands([axisOptions.rangeStart, axisOptions.rangeEnd], axisOptions.barToSpaceRatio, isHidingPercentBars ? axisOptions.barToSpaceRatio : visuals.FunnelChart.PercentBarToBarRatio);\n var xAxis = d3.svg.axis()\n .scale(xScaleForAxis)\n .orient(\"right\")\n .tickPadding(visuals.FunnelChart.TickPadding)\n .innerTickSize(visuals.FunnelChart.InnerTickSize);\n graphicsContext.classed('axis', true)\n .transition()\n .duration(this.animationDuration)\n .attr('transform', visuals.SVGUtil.translate(0, axisOptions.margin.top))\n .call(xAxis);\n };\n WebFunnelAnimator.prototype.animateDefaultShapes = function (data, slices, graphicsContext, layout) {\n var hasHighlights = data.hasHighlights;\n var shapes = graphicsContext.selectAll(visuals.FunnelChart.Selectors.funnel.bars.selector).data(slices, function (d) { return d.key; });\n shapes.enter()\n .append('rect')\n .attr(\"class\", function (d) { return d.highlight ? visuals.FunnelChart.FunnelBarHighlightClass : visuals.FunnelChart.Selectors.funnel.bars.class; });\n shapes\n .style(\"fill\", function (d) { return d.color; })\n .style(\"fill-opacity\", function (d) { return function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, false, hasHighlights); }; })\n .transition()\n .duration(this.animationDuration)\n .attr(layout.shapeLayout);\n shapes.exit().remove();\n return shapes;\n };\n WebFunnelAnimator.prototype.animateDefaultDataLabels = function (options) {\n var dataLabels;\n if (options.viewModel.dataLabelsSettings.show && options.viewModel.canShowDataLabels) {\n dataLabels = visuals.dataLabelUtils.drawDefaultLabelsForFunnelChart(options.viewModel.slices, options.labelGraphicsContext, options.labelLayout, true, this.animationDuration);\n }\n else {\n visuals.dataLabelUtils.cleanDataLabels(options.labelGraphicsContext);\n }\n return dataLabels;\n };\n WebFunnelAnimator.prototype.animatePercentBars = function (options) {\n var data = options.viewModel;\n var isHidingPercentBars = options.isHidingPercentBars;\n if (isHidingPercentBars || !data.slices || (data.hasHighlights ? data.slices.length / 2 : data.slices.length) < 2) {\n // TODO: call percentBarComponents with flag with empty data to clear drawing smoothly\n this.animatePercentBarComponents([], options);\n return;\n }\n var slices = [data.slices[data.hasHighlights ? 1 : 0], data.slices[data.slices.length - 1]];\n var baseline = visuals.FunnelChart.getFunnelSliceValue(slices[0]);\n if (baseline <= 0) {\n // TODO: call percentBarComponents with flag with empty data to clear drawing smoothly\n this.animatePercentBarComponents([], options);\n return;\n }\n var percentData = slices.map(function (slice, i) { return {\n value: visuals.FunnelChart.getFunnelSliceValue(slice),\n percent: i === 0 ? 1 : visuals.FunnelChart.getFunnelSliceValue(slice) / baseline,\n isTop: i === 0,\n }; });\n this.animatePercentBarComponents(percentData, options);\n };\n WebFunnelAnimator.prototype.animateToFunnelPercent = function (context, targetData, layout) {\n return context\n .data(targetData)\n .transition()\n .duration(this.animationDuration)\n .attr(layout);\n };\n WebFunnelAnimator.prototype.animatePercentBarComponents = function (data, options) {\n var graphicsContext = options.percentGraphicsContext;\n var layout = options.layout;\n var zeroData = [\n { percent: 0, value: 0, isTop: true },\n { percent: 0, value: 0, isTop: false },\n ];\n // Main line\n var mainLine = graphicsContext.selectAll(visuals.FunnelChart.Selectors.percentBar.mainLine.selector).data(data);\n this.animateToFunnelPercent(mainLine.exit(), zeroData, layout.percentBarLayout.mainLine)\n .remove();\n mainLine.enter()\n .append('line')\n .classed(visuals.FunnelChart.Selectors.percentBar.mainLine.class, true)\n .data(zeroData)\n .attr(layout.percentBarLayout.mainLine);\n this.animateToFunnelPercent(mainLine, data, layout.percentBarLayout.mainLine);\n // Left tick\n var leftTick = graphicsContext.selectAll(visuals.FunnelChart.Selectors.percentBar.leftTick.selector).data(data);\n this.animateToFunnelPercent(leftTick.exit(), zeroData, layout.percentBarLayout.leftTick)\n .remove();\n leftTick.enter()\n .append('line')\n .classed(visuals.FunnelChart.Selectors.percentBar.leftTick.class, true)\n .data(zeroData)\n .attr(layout.percentBarLayout.leftTick);\n this.animateToFunnelPercent(leftTick, data, layout.percentBarLayout.leftTick);\n // Right tick\n var rightTick = graphicsContext.selectAll(visuals.FunnelChart.Selectors.percentBar.rightTick.selector).data(data);\n this.animateToFunnelPercent(rightTick.exit(), zeroData, layout.percentBarLayout.rightTick)\n .remove();\n rightTick.enter()\n .append('line')\n .classed(visuals.FunnelChart.Selectors.percentBar.rightTick.class, true)\n .data(zeroData)\n .attr(layout.percentBarLayout.rightTick);\n this.animateToFunnelPercent(rightTick, data, layout.percentBarLayout.rightTick);\n // Text\n var text = graphicsContext.selectAll(visuals.FunnelChart.Selectors.percentBar.text.selector).data(data);\n this.animateToFunnelPercent(text.exit(), zeroData, layout.percentBarLayout.text)\n .remove();\n text.enter()\n .append('text')\n .classed(visuals.FunnelChart.Selectors.percentBar.text.class, true)\n .data(zeroData)\n .attr(layout.percentBarLayout.text);\n this.animateToFunnelPercent(text, data, layout.percentBarLayout.text)\n .text(function (fp) {\n return powerbi.formattingService.formatValue(fp.percent, visuals.valueFormatter.getLocalizedString(\"Percentage1\"));\n });\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(options.visualInitOptions);\n };\n return WebFunnelAnimator;\n }(visuals.BaseAnimator));\n visuals.WebFunnelAnimator = WebFunnelAnimator;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var WebTreemapAnimator = (function (_super) {\n __extends(WebTreemapAnimator, _super);\n function WebTreemapAnimator(options) {\n _super.call(this, options);\n }\n WebTreemapAnimator.prototype.animate = function (options) {\n var result = {\n failed: true,\n shapes: null,\n highlightShapes: null,\n majorLabels: null,\n minorLabels: null,\n };\n var viewModel = options.viewModel;\n var previousViewModel = this.previousViewModel;\n if (!previousViewModel) {\n }\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\n result = this.animateNormalToHighlighted(options);\n }\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToHighlighted(options);\n }\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\n result = this.animateHighlightedToNormal(options);\n }\n this.previousViewModel = viewModel;\n return result;\n };\n WebTreemapAnimator.prototype.animateNormalToHighlighted = function (options) {\n var hasSelection = false;\n var hasHighlights = true;\n var shapes = this.animateDefaultShapes(options.shapeGraphicsContext, options.nodes, hasSelection, hasHighlights, options.layout);\n var highlightShapes = options.shapeGraphicsContext.selectAll('.' + visuals.Treemap.HighlightNodeClassName)\n .data(options.highlightNodes, function (d) { return d.key + \"highlight\"; });\n highlightShapes.enter().append('rect')\n .attr('class', options.layout.highlightShapeClass)\n .attr(options.layout.shapeLayout); // Start using the normal shape layout\n highlightShapes\n .style(\"fill\", function (d) { return visuals.Treemap.getFill(d, true); })\n .style(\"fill-opacity\", function (d) { return visuals.Treemap.getFillOpacity(d, hasSelection, hasHighlights, true); })\n .transition()\n .duration(this.animationDuration)\n .attr(options.layout.highlightShapeLayout); // Animate to the highlighted positions\n highlightShapes.exit().remove();\n var majorLabels = this.animateDefaultMajorLabels(options.labelGraphicsContext, options.majorLabeledNodes, options.labelSettings, options.layout);\n var minorLabels = this.animateDefaultMinorLabels(options.labelGraphicsContext, options.minorLabeledNodes, options.labelSettings, options.layout);\n return {\n failed: false,\n shapes: shapes,\n highlightShapes: highlightShapes,\n majorLabels: majorLabels,\n minorLabels: minorLabels,\n };\n };\n WebTreemapAnimator.prototype.animateHighlightedToHighlighted = function (options) {\n var hasSelection = false;\n var hasHighlights = true;\n var shapes = this.animateDefaultShapes(options.shapeGraphicsContext, options.nodes, hasSelection, hasHighlights, options.layout);\n options.shapeGraphicsContext.selectAll('.' + visuals.Treemap.HighlightNodeClassName)\n .data(options.highlightNodes, function (d) { return d.key + \"highlight\"; });\n var highlightShapes = this.animateDefaultHighlightShapes(options.shapeGraphicsContext, options.highlightNodes, hasSelection, hasHighlights, options.layout);\n var majorLabels = this.animateDefaultMajorLabels(options.labelGraphicsContext, options.majorLabeledNodes, options.labelSettings, options.layout);\n var minorLabels = this.animateDefaultMinorLabels(options.labelGraphicsContext, options.minorLabeledNodes, options.labelSettings, options.layout);\n return {\n failed: false,\n shapes: shapes,\n highlightShapes: highlightShapes,\n majorLabels: majorLabels,\n minorLabels: minorLabels,\n };\n };\n WebTreemapAnimator.prototype.animateHighlightedToNormal = function (options) {\n var hasSelection = options.interactivityService ? options.interactivityService.hasSelection() : false;\n var shapes = options.shapeGraphicsContext.selectAll('.' + visuals.Treemap.TreemapNodeClassName)\n .data(options.nodes, function (d) { return d.key; });\n shapes.enter().append('rect')\n .attr('class', options.layout.shapeClass);\n shapes\n .transition()\n .duration(this.animationDuration)\n .style(\"fill\", function (d) { return visuals.Treemap.getFill(d, false); })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, d.selected, !d.selected); })\n .attr(options.layout.shapeLayout)\n .transition()\n .duration(0)\n .delay(this.animationDuration)\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); });\n shapes.exit().remove();\n var highlightShapes = options.shapeGraphicsContext.selectAll('.' + visuals.Treemap.HighlightNodeClassName)\n .data(options.nodes, function (d) { return d.key + \"highlight\"; });\n highlightShapes.enter().append('rect')\n .attr('class', options.layout.highlightShapeClass);\n highlightShapes\n .style(\"fill\", function (d) { return visuals.Treemap.getFill(d, true); })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, true, d.selected, !d.selected); })\n .transition()\n .duration(this.animationDuration)\n .attr(hasSelection ? options.layout.zeroShapeLayout : options.layout.shapeLayout) // Animate to the normal shape layout or zero shape layout depending on whether we have a selection or not\n .remove();\n highlightShapes.exit().remove();\n var majorLabels = this.animateDefaultMajorLabels(options.labelGraphicsContext, options.majorLabeledNodes, options.labelSettings, options.layout);\n var minorLabels = this.animateDefaultMinorLabels(options.labelGraphicsContext, options.minorLabeledNodes, options.labelSettings, options.layout);\n return {\n failed: false,\n shapes: shapes,\n highlightShapes: highlightShapes,\n majorLabels: majorLabels,\n minorLabels: minorLabels,\n };\n };\n WebTreemapAnimator.prototype.animateDefaultShapes = function (context, nodes, hasSelection, hasHighlights, layout) {\n var isHighlightShape = false;\n var shapes = context.selectAll('.' + visuals.Treemap.TreemapNodeClassName)\n .data(nodes, function (d) { return d.key; });\n shapes.enter().append('rect')\n .attr('class', layout.shapeClass);\n shapes\n .transition()\n .duration(this.animationDuration)\n .style(\"fill\", function (d) { return visuals.Treemap.getFill(d, isHighlightShape); })\n .style(\"fill-opacity\", function (d) { return visuals.Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape); })\n .attr(layout.shapeLayout);\n shapes.exit().remove();\n return shapes;\n };\n WebTreemapAnimator.prototype.animateDefaultHighlightShapes = function (context, nodes, hasSelection, hasHighlights, layout) {\n var isHighlightShape = true;\n var highlightShapes = context.selectAll('.' + visuals.Treemap.HighlightNodeClassName)\n .data(nodes, function (d) { return d.key + \"highlight\"; });\n highlightShapes.enter().append('rect')\n .attr('class', layout.highlightShapeClass);\n highlightShapes\n .transition()\n .duration(this.animationDuration)\n .style(\"fill\", function (d) { return visuals.Treemap.getFill(d, isHighlightShape); })\n .style(\"fill-opacity\", function (d) { return visuals.Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape); })\n .attr(layout.highlightShapeLayout);\n highlightShapes.exit().remove();\n return highlightShapes;\n };\n WebTreemapAnimator.prototype.animateDefaultMajorLabels = function (context, nodes, labelSettings, layout) {\n var labels = context\n .selectAll('.' + visuals.Treemap.MajorLabelClassName)\n .data(nodes, function (d) { return d.key; });\n labels.enter().append('text')\n .attr('class', layout.majorLabelClass);\n labels\n .text(layout.majorLabelText)\n .style('fill', function () { return labelSettings.labelColor; })\n .transition()\n .duration(this.animationDuration)\n .attr(layout.majorLabelLayout);\n labels.exit().remove();\n return labels;\n };\n WebTreemapAnimator.prototype.animateDefaultMinorLabels = function (context, nodes, labelSettings, layout) {\n var labels = context\n .selectAll('.' + visuals.Treemap.MinorLabelClassName)\n .data(nodes, function (d) { return d.key; });\n labels.enter().append('text')\n .attr('class', layout.minorLabelClass);\n labels\n .text(layout.minorLabelText)\n .style('fill', function () { return labelSettings.labelColor; })\n .transition()\n .duration(this.animationDuration)\n .attr(layout.minorLabelLayout);\n labels.exit().remove();\n return labels;\n };\n return WebTreemapAnimator;\n }(visuals.BaseAnimator));\n visuals.WebTreemapAnimator = WebTreemapAnimator;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * This is the baseline for some most common used object properties across visuals.\n * When adding new properties, please try to reuse the existing ones.\n */\n visuals.StandardObjectProperties = {\n axisEnd: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_End'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_EndDescription'),\n placeHolderText: powerbi.data.createDisplayNameGetter('Visual_Precision_Auto'),\n type: { numeric: true },\n suppressFormatPainterCopy: true,\n },\n axisScale: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Scale'),\n type: { enumeration: visuals.axisScale.type }\n },\n axisStart: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Start'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_StartDescription'),\n placeHolderText: powerbi.data.createDisplayNameGetter('Visual_Precision_Auto'),\n type: { numeric: true },\n suppressFormatPainterCopy: true,\n },\n axisStyle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Style'),\n type: { enumeration: visuals.axisStyle.type }\n },\n axisType: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Type'),\n type: { enumeration: visuals.axisType.type },\n },\n backColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColor'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColor_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n dataColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LabelsFill'),\n description: powerbi.data.createDisplayNameGetter('Visual_LabelsFillDescription'),\n type: { fill: { solid: { color: true } } }\n },\n dataLabelColor: {\n displayName: powerbi.data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Label_Color\"),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Color_Description'),\n type: { fill: { solid: { color: true } } }\n },\n dataLabelDecimalPoints: {\n displayName: powerbi.data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Decimal_Points\"),\n placeHolderText: powerbi.data.createDisplayNameGetter('Visual_Precision_Auto'),\n type: { numeric: true }\n },\n dataLabelDisplayUnits: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DisplayUnits'),\n description: powerbi.data.createDisplayNameGetter('Visual_DisplayUnitsDescription'),\n type: { formatting: { labelDisplayUnits: true } },\n suppressFormatPainterCopy: true,\n },\n dataLabelHorizontalPosition: {\n displayName: powerbi.data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Horizontal_Position\"),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Horizontal_Position_Description'),\n type: { enumeration: visuals.referenceLineDataLabelHorizontalPosition.type }\n },\n dataLabelShow: {\n displayName: powerbi.data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Label\"),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Show_Description'),\n type: { bool: true }\n },\n dataLabelVerticalPosition: {\n displayName: powerbi.data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Vertical_Position\"),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Vertical_Position_Description'),\n type: { enumeration: visuals.referenceLineDataLabelVerticalPosition.type }\n },\n defaultColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DefaultColor'),\n type: { fill: { solid: { color: true } } }\n },\n fill: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Fill'),\n type: { fill: { solid: { color: true } } }\n },\n fontColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_FontColor'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColor_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n fontSize: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_TextSize'),\n type: { formatting: { fontSize: true } }\n },\n formatString: {\n type: { formatting: { formatString: true } },\n },\n image: {\n type: { image: {} },\n },\n labelColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LegendTitleColor'),\n type: { fill: { solid: { color: true } } }\n },\n labelDisplayUnits: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DisplayUnits'),\n description: powerbi.data.createDisplayNameGetter('Visual_DisplayUnitsDescription'),\n type: { formatting: { labelDisplayUnits: true } }\n },\n labelPrecision: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Precision'),\n description: powerbi.data.createDisplayNameGetter('Visual_PrecisionDescription'),\n placeHolderText: powerbi.data.createDisplayNameGetter('Visual_Precision_Auto'),\n type: { numeric: true }\n },\n legendPosition: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LegendPosition'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendPositionDescription'),\n type: { enumeration: visuals.legendPosition.type },\n },\n legendTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LegendName'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendNameDescription'),\n type: { text: true },\n },\n lineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Color_Description'),\n type: { fill: { solid: { color: true } } }\n },\n outline: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Outline'),\n type: { enumeration: visuals.outline.type }\n },\n outlineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_OutlineColor'),\n description: powerbi.data.createDisplayNameGetter('Visual_OutlineColor_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n outlineWeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_OutlineWeight'),\n description: powerbi.data.createDisplayNameGetter('Visual_OutlineWeight_Desc'),\n type: { numeric: true }\n },\n show: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Show'),\n type: { bool: true }\n },\n showAllDataPoints: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint_Show_All'),\n type: { bool: true }\n },\n showLegendTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LegendShowTitle'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendShowTitleDescription'),\n type: { bool: true }\n },\n referenceLinePosition: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Arrange'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Arrange_Description'),\n type: { enumeration: visuals.referenceLinePosition.type }\n },\n referenceLineStyle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Style'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Style_Description'),\n type: { enumeration: visuals.lineStyle.type }\n },\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Background_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Background_TransparencyDescription'),\n type: { numeric: true }\n },\n yAxisPosition: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis_Position'),\n description: powerbi.data.createDisplayNameGetter('Visual_YAxis_PositionDescription'),\n type: { enumeration: visuals.yAxisPosition.type },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.animatedTextObjectDescs = {\n general: {\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n }\n };\n visuals.animatedNumberCapabilities = {\n objects: visuals.animatedTextObjectDescs,\n dataViewMappings: [{\n single: { role: \"Values\" }\n }],\n supportsSelection: false,\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.basicShapeCapabilities = {\n objects: {\n line: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_BasicShape_Line'),\n properties: {\n lineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_BasicShape_LineColor'),\n type: { fill: { solid: { color: true } } }\n },\n transparency: visuals.StandardObjectProperties.transparency,\n weight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_BasicShape_Weight'),\n type: { numeric: true }\n },\n roundEdge: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_BasicShape_RoundEdges'),\n type: { numeric: true }\n }\n }\n },\n fill: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Fill'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n fillColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_BasicShape_FillColor'),\n type: { fill: { solid: { color: true } } }\n },\n transparency: visuals.StandardObjectProperties.transparency,\n }\n },\n rotation: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_BasicShape_Rotate'),\n properties: {\n angle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_BasicShape_Rotate'),\n type: { numeric: true }\n }\n }\n },\n general: {\n properties: {\n shapeType: {\n type: { text: true },\n suppressFormatPainterCopy: true,\n }\n }\n }\n },\n suppressDefaultTitle: true,\n suppressDefaultPadding: true,\n canRotate: false,\n supportsSelection: false,\n };\n visuals.basicShapeProps = {\n general: {\n shapeType: { objectName: 'general', propertyName: 'shapeType' },\n },\n line: {\n transparency: { objectName: 'line', propertyName: 'transparency' },\n weight: { objectName: 'line', propertyName: 'weight' },\n roundEdge: { objectName: 'line', propertyName: 'roundEdge' },\n lineColor: { objectName: 'line', propertyName: 'lineColor' }\n },\n fill: {\n transparency: { objectName: 'fill', propertyName: 'transparency' },\n fillColor: { objectName: 'fill', propertyName: 'fillColor' },\n show: { objectName: 'fill', propertyName: 'show' }\n },\n rotation: {\n angle: { objectName: 'rotation', propertyName: 'angle' }\n }\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n function getColumnChartCapabilities(transposeAxes) {\n if (transposeAxes === void 0) { transposeAxes = false; }\n return {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Axis'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_AxisDescription'),\n cartesianKind: 0 /* X */,\n }, {\n name: 'Series',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Legend'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Value'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n cartesianKind: 1 /* Y */,\n }, {\n name: 'Gradient',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Gradient'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: $.extend({}, visuals.StandardObjectProperties.legendTitle, {\n suppressFormatPainterCopy: true\n }),\n labelColor: visuals.StandardObjectProperties.labelColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n categoryAxis: {\n displayName: transposeAxes ? powerbi.data.createDisplayNameGetter('Visual_YAxis') : powerbi.data.createDisplayNameGetter('Visual_XAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.yAxisPosition,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n axisType: visuals.StandardObjectProperties.axisType,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: transposeAxes ? powerbi.data.createDisplayNameGetter('Visual_Axis_YTitleDescription') : powerbi.data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n valueAxis: {\n displayName: transposeAxes ? powerbi.data.createDisplayNameGetter('Visual_XAxis') : powerbi.data.createDisplayNameGetter('Visual_YAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.yAxisPosition,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n intersection: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Intersection'),\n type: { numeric: true },\n placeHolderText: powerbi.data.createDisplayNameGetter('Visual_Precision_Auto'),\n },\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: transposeAxes ? powerbi.data.createDisplayNameGetter('Visual_Axis_YTitleDescription') : powerbi.data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n y1AxisReferenceLine: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Description'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n value: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\n type: { numeric: true }\n },\n lineColor: visuals.StandardObjectProperties.lineColor,\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: visuals.StandardObjectProperties.referenceLineStyle,\n position: visuals.StandardObjectProperties.referenceLinePosition,\n dataLabelShow: visuals.StandardObjectProperties.dataLabelShow,\n dataLabelColor: visuals.StandardObjectProperties.dataLabelColor,\n dataLabelDecimalPoints: visuals.StandardObjectProperties.dataLabelDecimalPoints,\n dataLabelHorizontalPosition: visuals.StandardObjectProperties.dataLabelHorizontalPosition,\n dataLabelVerticalPosition: visuals.StandardObjectProperties.dataLabelVerticalPosition,\n dataLabelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n },\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: visuals.StandardObjectProperties.defaultColor,\n showAllDataPoints: visuals.StandardObjectProperties.showAllDataPoints,\n fill: visuals.StandardObjectProperties.fill,\n fillRule: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gradient'),\n type: { fillRule: {} },\n rule: {\n inputRole: 'Gradient',\n output: {\n property: 'fill',\n selector: ['Category'],\n },\n },\n }\n }\n },\n trend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line'),\n properties: {\n show: {\n type: { bool: true }\n },\n lineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\n type: { fill: { solid: { color: true } } }\n },\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\n type: { enumeration: visuals.lineStyle.type }\n },\n combineSeries: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\n type: { bool: true }\n },\n useHighlightValues: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues_Description'),\n type: { bool: true }\n },\n }\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n showSeries: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Show'),\n type: { bool: true }\n },\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n labelPrecision: $.extend({}, visuals.StandardObjectProperties.labelPrecision, {\n suppressFormatPainterCopy: true\n }),\n showAll: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LabelSeriesShowAll'),\n type: { bool: true }\n },\n fontSize: visuals.StandardObjectProperties.fontSize,\n },\n },\n plotArea: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Plot'),\n //description: data.createDisplayNameGetter('Visual_PlotDescription'),\n properties: {\n transparency: visuals.StandardObjectProperties.transparency,\n image: visuals.StandardObjectProperties.image,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Gradient': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 }, 'Gradient': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Y': { min: 0, max: 1 }, 'Gradient': { max: 1 } },\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Series',\n select: [{ for: { in: 'Y' } }, { bind: { to: 'Gradient' } }],\n dataReductionAlgorithm: { top: {} }\n }\n },\n rowCount: { preferred: { min: 2 }, supported: { min: 0 } }\n },\n }, {\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Gradient': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 }, 'Gradient': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Y': { min: 0, max: 1 }, 'Gradient': { max: 1 } },\n ],\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\n usage: {\n regression: {\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\n },\n },\n categorical: {\n categories: {\n for: { in: 'regression.X' },\n },\n values: {\n group: {\n by: 'regression.Series',\n select: [{ for: { in: 'regression.Y' } }],\n },\n }\n }\n }],\n supportsHighlight: true,\n sorting: {\n default: {},\n },\n drilldown: {\n roles: ['Category']\n },\n };\n }\n visuals.getColumnChartCapabilities = getColumnChartCapabilities;\n visuals.columnChartProps = {\n dataPoint: {\n defaultColor: { objectName: 'dataPoint', propertyName: 'defaultColor' },\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n showAllDataPoints: { objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\n },\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n categoryAxis: {\n axisType: { objectName: 'categoryAxis', propertyName: 'axisType' },\n },\n legend: {\n labelColor: { objectName: 'legend', propertyName: 'labelColor' },\n },\n plotArea: {\n image: { objectName: 'plotArea', propertyName: 'image' },\n transparency: { objectName: 'plotArea', propertyName: 'transparency' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.comboChartCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_ComboChart_Category'),\n description: powerbi.data.createDisplayNameGetter('Role_ComboChart_CategoryDescription'),\n cartesianKind: 0 /* X */,\n }, {\n name: 'Series',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_ComboChart_Series'),\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_ComboChart_Y'),\n description: powerbi.data.createDisplayNameGetter('Role_ComboChart_YDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n cartesianKind: 1 /* Y */,\n }, {\n name: 'Y2',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_ComboChart_Y2'),\n description: powerbi.data.createDisplayNameGetter('Role_ComboChart_Y2Description'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n cartesianKind: 1 /* Y */,\n },\n ],\n objects: {\n general: {\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n visualType1: {\n type: { text: true }\n },\n visualType2: {\n type: { text: true }\n },\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: $.extend({}, visuals.StandardObjectProperties.legendTitle, {\n suppressFormatPainterCopy: true\n }),\n labelColor: visuals.StandardObjectProperties.labelColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n categoryAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_XAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n axisType: visuals.StandardObjectProperties.axisType,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n valueAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n axisLabel: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis_ColumnTitle'),\n type: { none: true },\n },\n position: visuals.StandardObjectProperties.yAxisPosition,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n secShow: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis_ShowSecondary'),\n type: { bool: true },\n },\n secAxisLabel: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis_LineTitle'),\n type: { none: true },\n },\n secPosition: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis_Position'),\n type: { enumeration: visuals.yAxisPosition.type },\n },\n secAxisScale: visuals.StandardObjectProperties.axisScale,\n secStart: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Start'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_StartDescription'),\n type: { numeric: true },\n },\n secEnd: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_End'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_EndDescription'),\n type: { numeric: true },\n },\n secShowAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\n type: { bool: true },\n },\n secAxisStyle: visuals.StandardObjectProperties.axisStyle,\n secLabelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n secLabelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: $.extend({}, visuals.StandardObjectProperties.defaultColor, {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DefaultColumnColor'),\n }),\n showAllDataPoints: visuals.StandardObjectProperties.showAllDataPoints,\n fill: visuals.StandardObjectProperties.fill,\n fillRule: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gradient'),\n type: { fillRule: {} },\n rule: {\n inputRole: 'Gradient',\n output: {\n property: 'fill',\n selector: ['Category'],\n },\n },\n }\n }\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n labelPrecision: $.extend({}, visuals.StandardObjectProperties.labelPrecision, {\n suppressFormatPainterCopy: true,\n }),\n fontSize: visuals.StandardObjectProperties.fontSize,\n },\n },\n plotArea: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Plot'),\n properties: {\n transparency: visuals.StandardObjectProperties.transparency,\n image: visuals.StandardObjectProperties.image,\n },\n },\n trend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line'),\n properties: {\n show: {\n type: { bool: true }\n },\n lineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\n type: { fill: { solid: { color: true } } }\n },\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\n type: { enumeration: visuals.lineStyle.type }\n },\n combineSeries: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\n type: { bool: true }\n },\n useHighlightValues: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues_Description'),\n type: { bool: true }\n },\n }\n },\n },\n dataViewMappings: [\n {\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } },\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Series',\n select: [\n { for: { in: 'Y' } }\n ],\n dataReductionAlgorithm: { top: {} }\n }\n },\n rowCount: { preferred: { min: 2 }, supported: { min: 0 } }\n }\n }, {\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Y2': { min: 1 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 }, 'Y2': { min: 1 } },\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n select: [\n { for: { in: 'Y2' } }\n ],\n },\n rowCount: { preferred: { min: 2 }, supported: { min: 0 } }\n },\n }, {\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } },\n ],\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\n usage: {\n regression: {\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\n },\n },\n categorical: {\n categories: {\n for: { in: 'regression.X' }\n },\n values: {\n group: {\n by: 'regression.Series',\n select: [{ for: { in: 'regression.Y' } }],\n },\n },\n }\n },\n ],\n supportsHighlight: true,\n sorting: {\n default: {},\n },\n drilldown: {\n roles: ['Category']\n },\n };\n visuals.comboChartProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n valueAxis: {\n secShow: { objectName: 'valueAxis', propertyName: 'secShow' },\n },\n legend: {\n labelColor: { objectName: 'legend', propertyName: 'labelColor' },\n },\n dataPoint: {\n showAllDataPoints: { objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.donutChartCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Legend'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\n }, {\n name: 'Series',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Details'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_DetailsDonutChartDescription'),\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: $.extend({}, visuals.StandardObjectProperties.legendTitle, {\n suppressFormatPainterCopy: true\n }),\n labelColor: visuals.StandardObjectProperties.labelColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: visuals.StandardObjectProperties.defaultColor,\n fill: visuals.StandardObjectProperties.fill,\n }\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DetailLabels'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n labelPrecision: $.extend({}, visuals.StandardObjectProperties.labelPrecision, {\n suppressFormatPainterCopy: true,\n }),\n fontSize: $.extend({}, visuals.StandardObjectProperties.fontSize, {\n suppressFormatPainterCopy: true,\n }),\n labelStyle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LabelStyle'),\n type: { enumeration: visuals.labelStyle.type }\n },\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } }\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Series',\n select: [{ bind: { to: 'Y' } }],\n dataReductionAlgorithm: { top: {} }\n }\n },\n rowCount: { preferred: { min: 2 }, supported: { min: 1 } }\n },\n }],\n sorting: {\n default: {},\n },\n supportsHighlight: true,\n drilldown: {\n roles: ['Category']\n },\n };\n visuals.donutChartProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n dataPoint: {\n defaultColor: { objectName: 'dataPoint', propertyName: 'defaultColor' },\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n },\n legend: {\n show: { objectName: 'legend', propertyName: 'show' },\n position: { objectName: 'legend', propertyName: 'position' },\n showTitle: { objectName: 'legend', propertyName: 'showTitle' },\n titleText: { objectName: 'legend', propertyName: 'titleText' },\n labelColor: { objectName: 'legend', propertyName: 'labelColor' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n // I support a categorical (ordinal) X with measure Y for a single series\n visuals.dataDotChartCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Axis'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_AxisDescription')\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Value'),\n requiredTypes: [{ numeric: true }, { integer: true }]\n },\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { max: 1 }, 'Y': { max: 1 } }\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n select: [{\n for: { in: 'Y' },\n dataReductionAlgorithm: { top: {} }\n }]\n },\n },\n }]\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.filledMapCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Location'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LocationFilledMapDescription'),\n preferredTypes: [\n { geography: { address: true } },\n { geography: { city: true } },\n { geography: { continent: true } },\n { geography: { country: true } },\n { geography: { county: true } },\n { geography: { place: true } },\n { geography: { postalCode: true } },\n { geography: { region: true } },\n { geography: { stateOrProvince: true } },\n ],\n }, {\n name: 'Series',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Legend'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\n }, {\n name: 'X',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Longitude'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LongitudeFilledMapDescription'),\n preferredTypes: [\n { geography: { longitude: true } }\n ],\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Latitude'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LatitudeFilledMapDescription'),\n preferredTypes: [\n { geography: { latitude: true } }\n ],\n }, {\n name: 'Size',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Gradient'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: visuals.StandardObjectProperties.legendTitle,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: visuals.StandardObjectProperties.defaultColor,\n showAllDataPoints: visuals.StandardObjectProperties.showAllDataPoints,\n fill: visuals.StandardObjectProperties.fill,\n fillRule: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\n type: { fillRule: {} },\n rule: {\n inputRole: 'Size',\n output: {\n property: 'fill',\n selector: ['Category'],\n },\n },\n }\n }\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n },\n },\n categoryLabels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_CategoryLabels'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n },\n }\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 } },\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 } }\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Series',\n select: [\n { bind: { to: 'X' } },\n { bind: { to: 'Y' } },\n { bind: { to: 'Size' } },\n ],\n dataReductionAlgorithm: { top: {} }\n }\n },\n rowCount: { preferred: { min: 2 } },\n dataVolume: 4,\n },\n }],\n sorting: {\n custom: {},\n },\n drilldown: {\n roles: ['Category']\n },\n };\n visuals.filledMapProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n dataPoint: {\n defaultColor: { objectName: 'dataPoint', propertyName: 'defaultColor' },\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n showAllDataPoints: { objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\n },\n legend: {\n show: { objectName: 'legend', propertyName: 'show' },\n position: { objectName: 'legend', propertyName: 'position' },\n showTitle: { objectName: 'legend', propertyName: 'showTitle' },\n titleText: { objectName: 'legend', propertyName: 'titleText' },\n },\n labels: {\n show: { objectName: 'labels', propertyName: 'show' },\n color: { objectName: 'labels', propertyName: 'color' },\n labelDisplayUnits: { objectName: 'labels', propertyName: 'labelDisplayUnits' },\n labelPrecision: { objectName: 'labels', propertyName: 'labelPrecision' },\n },\n categoryLabels: {\n show: { objectName: 'categoryLabels', propertyName: 'show' },\n }\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.funnelChartCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Group'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GroupFunnelDescription')\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: 'Gradient',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Gradient'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }\n ],\n dataViewMappings: [{\n conditions: [\n // NOTE: Ordering of the roles prefers to add measures to Y before Gradient.\n { 'Category': { max: 0 }, 'Gradient': { max: 0 } },\n { 'Category': { max: 1 }, 'Y': { max: 1 }, 'Gradient': { max: 1 } },\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n select: [{ for: { in: 'Y' } }, { bind: { to: 'Gradient' } }],\n dataReductionAlgorithm: { top: {} }\n },\n rowCount: { preferred: { min: 1 } }\n },\n }],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: visuals.StandardObjectProperties.defaultColor,\n fill: visuals.StandardObjectProperties.fill,\n fillRule: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gradient'),\n type: { fillRule: {} },\n rule: {\n inputRole: 'Gradient',\n output: {\n property: 'fill',\n selector: ['Category'],\n },\n },\n }\n }\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelPosition: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Position'),\n type: { enumeration: visuals.labelPosition.type },\n suppressFormatPainterCopy: true,\n },\n labelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n labelPrecision: $.extend({}, visuals.StandardObjectProperties.labelPrecision, {\n suppressFormatPainterCopy: true,\n }),\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n percentBarLabel: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_PercentBarLabel'),\n description: powerbi.data.createDisplayNameGetter('Visual_PercentBarLabelDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n },\n supportsHighlight: true,\n sorting: {\n default: {},\n },\n drilldown: {\n roles: ['Category']\n },\n };\n visuals.funnelChartProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n dataPoint: {\n defaultColor: { objectName: 'dataPoint', propertyName: 'defaultColor' },\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.gaugeRoleNames = {\n y: 'Y',\n minValue: 'MinValue',\n maxValue: 'MaxValue',\n targetValue: 'TargetValue'\n };\n visuals.gaugeCapabilities = {\n dataRoles: [\n {\n name: visuals.gaugeRoleNames.y,\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Value'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_ValueDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: visuals.gaugeRoleNames.minValue,\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_MinValue'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_MinValueDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: visuals.gaugeRoleNames.maxValue,\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_MaxValue'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_MaxValueDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: visuals.gaugeRoleNames.targetValue,\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_TargetValue'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_TargetValueDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }\n ],\n objects: {\n general: {\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n axis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gauge_Axis'),\n properties: {\n min: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gauge_Axis_Min'),\n type: { numeric: true }\n },\n max: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gauge_Axis_Max'),\n type: { numeric: true }\n },\n target: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gauge_Axis_Target'),\n type: { numeric: true }\n },\n },\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n fontSize: visuals.StandardObjectProperties.fontSize,\n },\n },\n calloutValue: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gauge_CalloutValue'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n },\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n properties: {\n fill: visuals.StandardObjectProperties.fill,\n target: {\n // TODO find a better string\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gauge_Axis_Target'),\n type: { fill: { solid: { color: true } } }\n }\n }\n }\n },\n dataViewMappings: [{\n conditions: [\n { 'Y': { max: 1 }, 'MinValue': { max: 1 }, 'MaxValue': { max: 1 }, 'TargetValue': { max: 1 } },\n ],\n categorical: {\n values: {\n select: [\n { bind: { to: 'Y' } },\n { bind: { to: 'MinValue' } },\n { bind: { to: 'MaxValue' } },\n { bind: { to: 'TargetValue' } },\n ]\n },\n },\n }],\n supportsSelection: false,\n };\n visuals.gaugeProps = {\n dataPoint: {\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n target: { objectName: 'dataPoint', propertyName: 'target' }\n }\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.imageVisualCapabilities = {\n objects: {\n general: {\n properties: {\n imageUrl: {\n type: { misc: { imageUrl: true } }\n }\n }\n },\n imageScaling: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Image_Scaling_Type'),\n properties: {\n imageScalingType: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Image_Scaling_Type'),\n type: { enumeration: visuals.imageScalingType.type }\n },\n }\n },\n },\n suppressDefaultTitle: true,\n supportsSelection: false,\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.scriptVisualCapabilities = {\n dataRoles: [{\n name: 'Values',\n kind: powerbi.VisualDataRoleKind.GroupingOrMeasure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values'),\n }],\n dataViewMappings: [{\n scriptResult: {\n dataInput: {\n table: {\n rows: {\n for: {\n in: 'Values'\n },\n dataReductionAlgorithm: {\n top: {}\n }\n },\n },\n },\n script: {\n source: {\n objectName: 'script',\n propertyName: 'source'\n },\n provider: {\n objectName: 'script',\n propertyName: 'provider'\n },\n }\n }\n }],\n objects: {\n script: {\n properties: {\n provider: {\n type: { text: true }\n },\n source: {\n type: { scripting: { source: true }\n }\n },\n }\n },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var samples;\n (function (samples) {\n samples.consoleWriterCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Axis'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_AxisDescription')\n },\n {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Y'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_YDescription')\n },\n ],\n dataViewMappings: [{\n categorical: {\n categories: {\n for: { in: 'Category' },\n },\n },\n }],\n };\n })(samples = visuals.samples || (visuals.samples = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var samples;\n (function (samples) {\n var ConsoleWriter = (function () {\n function ConsoleWriter() {\n }\n ConsoleWriter.converter = function (dataView) {\n window.console.log('converter');\n window.console.log(dataView);\n return {};\n };\n ConsoleWriter.prototype.init = function (options) {\n var div = d3.select(options.element.get(0)).append(\"div\");\n div.append(\"h1\").text(\"ConsoleWriter\");\n div.append(\"p\").text(\"This IVisual writes messages passed to it to the javscript console output. Check your console for the actual messages passed. For more information, click below\");\n var anchor = div.append('a');\n anchor.attr('href', \"http://microsoft.github.io/PowerBI-visuals/modules/powerbi.html\")\n .text(\"Online help\");\n window.console.log('init');\n window.console.log(options);\n };\n ConsoleWriter.prototype.onResizing = function (viewport) { };\n ConsoleWriter.prototype.update = function (options) {\n window.console.log('update');\n window.console.log(options);\n };\n return ConsoleWriter;\n }());\n samples.ConsoleWriter = ConsoleWriter;\n })(samples = visuals.samples || (visuals.samples = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.lineChartCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Axis'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_AxisDescription'),\n cartesianKind: 0 /* X */,\n }, {\n name: 'Series',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Legend'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n cartesianKind: 1 /* Y */,\n },\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: $.extend({}, visuals.StandardObjectProperties.legendTitle, {\n suppressFormatPainterCopy: true\n }),\n labelColor: visuals.StandardObjectProperties.labelColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: visuals.StandardObjectProperties.defaultColor,\n fill: visuals.StandardObjectProperties.fill,\n }\n },\n trend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n lineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\n type: { fill: { solid: { color: true } } }\n },\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\n type: { enumeration: visuals.lineStyle.type }\n },\n combineSeries: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\n type: { bool: true }\n },\n useHighlightValues: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues_Description'),\n type: { bool: true }\n },\n }\n },\n categoryAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_XAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n axisType: visuals.StandardObjectProperties.axisType,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n valueAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.yAxisPosition,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n y1AxisReferenceLine: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Description'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n value: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\n type: { numeric: true }\n },\n lineColor: visuals.StandardObjectProperties.lineColor,\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: visuals.StandardObjectProperties.referenceLineStyle,\n position: visuals.StandardObjectProperties.referenceLinePosition,\n dataLabelShow: visuals.StandardObjectProperties.dataLabelShow,\n dataLabelColor: visuals.StandardObjectProperties.dataLabelColor,\n dataLabelDecimalPoints: visuals.StandardObjectProperties.dataLabelDecimalPoints,\n dataLabelHorizontalPosition: visuals.StandardObjectProperties.dataLabelHorizontalPosition,\n dataLabelVerticalPosition: visuals.StandardObjectProperties.dataLabelVerticalPosition,\n dataLabelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n },\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n showSeries: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Show'),\n type: { bool: true }\n },\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n labelPrecision: $.extend({}, visuals.StandardObjectProperties.labelPrecision, {\n suppressFormatPainterCopy: true,\n }),\n showAll: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LabelSeriesShowAll'),\n type: { bool: true }\n },\n fontSize: visuals.StandardObjectProperties.fontSize,\n labelDensity: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_LabelDensity'),\n type: { formatting: { labelDensity: true } },\n },\n },\n },\n plotArea: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Plot'),\n //description: data.createDisplayNameGetter('Visual_PlotDescription'),\n properties: {\n transparency: visuals.StandardObjectProperties.transparency,\n image: visuals.StandardObjectProperties.image,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } }\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Series',\n select: [{ for: { in: 'Y' } }],\n dataReductionAlgorithm: { top: {} }\n }\n },\n },\n }, {\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } }\n ],\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\n usage: {\n regression: {\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\n },\n },\n categorical: {\n categories: {\n for: { in: 'regression.X' },\n },\n values: {\n group: {\n by: 'regression.Series',\n select: [{ for: { in: 'regression.Y' } }],\n },\n }\n }\n }],\n sorting: {\n default: {},\n },\n };\n visuals.lineChartProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n dataPoint: {\n defaultColor: { objectName: 'dataPoint', propertyName: 'defaultColor' },\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n },\n trend: {\n show: { objectName: 'trend', propertyName: 'show' },\n },\n categoryAxis: {\n axisType: { objectName: 'categoryAxis', propertyName: 'axisType' },\n },\n legend: {\n labelColor: { objectName: 'legend', propertyName: 'labelColor' },\n },\n labels: {\n labelDensity: { objectName: 'labels', propertyName: 'labelDensity' },\n },\n plotArea: {\n image: { objectName: 'plotArea', propertyName: 'image' },\n transparency: { objectName: 'plotArea', propertyName: 'transparency' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.mapCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Location'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LocationMapDescription'),\n preferredTypes: [\n { geography: { address: true } },\n { geography: { city: true } },\n { geography: { continent: true } },\n { geography: { country: true } },\n { geography: { county: true } },\n { geography: { place: true } },\n { geography: { postalCode: true } },\n { geography: { region: true } },\n { geography: { stateOrProvince: true } },\n ],\n }, {\n name: 'Series',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Legend'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\n }, {\n name: 'X',\n kind: powerbi.VisualDataRoleKind.GroupingOrMeasure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Longitude'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LongitudeMapDescription'),\n preferredTypes: [\n { geography: { longitude: true } }\n ],\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.GroupingOrMeasure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Latitude'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LatitudeMapDescription'),\n preferredTypes: [\n { geography: { latitude: true } }\n ],\n }, {\n name: 'Size',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Size'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_SizeDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: 'Gradient',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Gradient'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: visuals.StandardObjectProperties.legendTitle,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: visuals.StandardObjectProperties.defaultColor,\n showAllDataPoints: visuals.StandardObjectProperties.showAllDataPoints,\n fill: visuals.StandardObjectProperties.fill,\n fillRule: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gradient'),\n type: { fillRule: {} },\n rule: {\n inputRole: 'Gradient',\n output: {\n property: 'fill',\n selector: ['Category'],\n },\n },\n }\n }\n },\n categoryLabels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_CategoryLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { min: 1, max: 1 }, 'Series': { max: 1 }, 'X': { max: 1, kind: powerbi.VisualDataRoleKind.Measure }, 'Y': { max: 1, kind: powerbi.VisualDataRoleKind.Measure }, 'Size': { max: 1 }, 'Gradient': { max: 0 } },\n { 'Category': { min: 1, max: 1 }, 'Series': { max: 0 }, 'X': { max: 1, kind: powerbi.VisualDataRoleKind.Measure }, 'Y': { max: 1, kind: powerbi.VisualDataRoleKind.Measure }, 'Size': { max: 1 }, 'Gradient': { max: 1 } },\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Series',\n select: [\n { bind: { to: 'X' } },\n { bind: { to: 'Y' } },\n { bind: { to: 'Size' } },\n { bind: { to: 'Gradient' } },\n ],\n dataReductionAlgorithm: { top: {} }\n }\n },\n rowCount: { preferred: { min: 2 } },\n dataVolume: 4,\n }\n }, {\n conditions: [\n { 'Category': { max: 0 }, 'Series': { max: 1 }, 'X': { max: 1, kind: powerbi.VisualDataRoleKind.Grouping }, 'Y': { max: 1, kind: powerbi.VisualDataRoleKind.Grouping }, 'Size': { max: 1 }, 'Gradient': { max: 0 } },\n { 'Category': { max: 0 }, 'Series': { max: 0 }, 'X': { max: 1, kind: powerbi.VisualDataRoleKind.Grouping }, 'Y': { max: 1, kind: powerbi.VisualDataRoleKind.Grouping }, 'Size': { max: 1 }, 'Gradient': { max: 1 } }\n ],\n categorical: {\n categories: {\n select: [\n { bind: { to: 'X' } },\n { bind: { to: 'Y' } },\n ],\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Series',\n select: [\n { bind: { to: 'Size' } },\n { bind: { to: 'Gradient' } },\n ],\n dataReductionAlgorithm: { top: {} }\n }\n },\n rowCount: { preferred: { min: 2 } },\n dataVolume: 4,\n },\n }],\n sorting: {\n custom: {},\n },\n drilldown: {\n roles: ['Category']\n },\n };\n visuals.mapProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n dataPoint: {\n defaultColor: { objectName: 'dataPoint', propertyName: 'defaultColor' },\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n showAllDataPoints: { objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\n },\n legend: {\n show: { objectName: 'legend', propertyName: 'show' },\n position: { objectName: 'legend', propertyName: 'position' },\n showTitle: { objectName: 'legend', propertyName: 'showTitle' },\n titleText: { objectName: 'legend', propertyName: 'titleText' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.multiRowCardCapabilities = {\n dataRoles: [\n {\n name: 'Values',\n kind: powerbi.VisualDataRoleKind.GroupingOrMeasure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Fields'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_FieldsDescription')\n }\n ],\n objects: {\n general: {\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n cardTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_CardTitle'),\n description: powerbi.data.createDisplayNameGetter('Visual_CardTitleDescription'),\n properties: {\n color: visuals.StandardObjectProperties.dataColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n dataLabels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\n properties: {\n color: visuals.StandardObjectProperties.dataColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n categoryLabels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_CategoryLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n card: {\n displayName: powerbi.data.createDisplayNameGetter('Card_ToolTip'),\n properties: {\n outline: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Outline'),\n type: { enumeration: visuals.outline.type }\n },\n outlineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_OutlineColor'),\n description: powerbi.data.createDisplayNameGetter('Visual_OutlineColor_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n outlineWeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_OutlineWeight'),\n description: powerbi.data.createDisplayNameGetter('Visual_OutlineWeight_Desc'),\n type: { numeric: true }\n },\n barShow: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_MultiRowCard_BarShow'),\n description: powerbi.data.createDisplayNameGetter('Visual_MultiRowCard_BarShow_Desc'),\n type: { bool: true }\n },\n barColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_MultiRowCard_BarColor'),\n type: { fill: { solid: { color: true } } }\n },\n barWeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_MultiRowCard_BarWeight'),\n description: powerbi.data.createDisplayNameGetter('Visual_MultiRowCard_BarWeight_Desc'),\n type: { numeric: true }\n },\n cardPadding: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_MultiRowCard_CardPadding'),\n description: powerbi.data.createDisplayNameGetter('Visual_MultiRowCard_CardBackground'),\n type: { numeric: true }\n },\n cardBackground: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Background'),\n type: { fill: { solid: { color: true } } }\n }\n }\n }\n },\n dataViewMappings: [{\n table: {\n rows: {\n for: { in: 'Values' },\n dataReductionAlgorithm: { window: {} }\n },\n rowCount: { preferred: { min: 1 } }\n },\n }],\n sorting: {\n default: {},\n },\n suppressDefaultTitle: true,\n supportsSelection: false,\n disableVisualDetails: true,\n };\n visuals.multiRowCardProps = {\n card: {\n outline: { objectName: 'card', propertyName: 'outline' },\n outlineColor: { objectName: 'card', propertyName: 'outlineColor' },\n outlineWeight: { objectName: 'card', propertyName: 'outlineWeight' },\n barShow: { objectName: 'card', propertyName: 'barShow' },\n barColor: { objectName: 'card', propertyName: 'barColor' },\n barWeight: { objectName: 'card', propertyName: 'barWeight' },\n cardPadding: { objectName: 'card', propertyName: 'cardPadding' },\n cardBackground: { objectName: 'card', propertyName: 'cardBackground' },\n }\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.textboxCapabilities = {\n objects: {\n general: {\n properties: {\n paragraphs: {\n type: { paragraphs: {} },\n suppressFormatPainterCopy: true,\n }\n }\n }\n },\n suppressDefaultTitle: true,\n supportsSelection: false,\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.cheerMeterCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Axis'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_AxisDescription')\n },\n {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n requiredTypes: [{ numeric: true }, { integer: true }],\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Y'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_YDescription')\n },\n ],\n dataViewMappings: [{\n categorical: {\n categories: {\n for: { in: 'Category' },\n },\n },\n }],\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n fill: visuals.StandardObjectProperties.fill,\n }\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.scatterChartCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Details'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_DetailsScatterChartDescription'),\n }, {\n name: 'Series',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Legend'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\n }, {\n name: 'X',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_X'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_XScatterChartDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n cartesianKind: 0 /* X */,\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Y'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_YScatterChartDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n cartesianKind: 1 /* Y */,\n }, {\n name: 'Size',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Size'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_SizeDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: 'Gradient',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Gradient'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: 'Play',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Play'),\n }\n ],\n objects: {\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n defaultColor: visuals.StandardObjectProperties.defaultColor,\n showAllDataPoints: visuals.StandardObjectProperties.showAllDataPoints,\n fill: visuals.StandardObjectProperties.fill,\n fillRule: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gradient'),\n type: { fillRule: {} },\n rule: {\n inputRole: 'Gradient',\n output: {\n property: 'fill',\n selector: ['Category'],\n },\n },\n }\n }\n },\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n trend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n lineColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\n type: { fill: { solid: { color: true } } }\n },\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\n type: { enumeration: visuals.lineStyle.type }\n },\n combineSeries: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\n description: powerbi.data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\n type: { bool: true }\n },\n }\n },\n categoryAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_XAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n valueAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.yAxisPosition,\n axisScale: visuals.StandardObjectProperties.axisScale,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n xAxisReferenceLine: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_X'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Description'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n value: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\n type: { numeric: true }\n },\n lineColor: visuals.StandardObjectProperties.lineColor,\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: visuals.StandardObjectProperties.referenceLineStyle,\n position: visuals.StandardObjectProperties.referenceLinePosition,\n dataLabelShow: visuals.StandardObjectProperties.dataLabelShow,\n dataLabelColor: visuals.StandardObjectProperties.dataLabelColor,\n dataLabelDecimalPoints: visuals.StandardObjectProperties.dataLabelDecimalPoints,\n dataLabelHorizontalPosition: visuals.StandardObjectProperties.dataLabelHorizontalPosition,\n dataLabelVerticalPosition: visuals.StandardObjectProperties.dataLabelVerticalPosition,\n dataLabelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n },\n },\n y1AxisReferenceLine: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Y'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Description'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n value: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\n type: { numeric: true }\n },\n lineColor: visuals.StandardObjectProperties.lineColor,\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: visuals.StandardObjectProperties.referenceLineStyle,\n position: visuals.StandardObjectProperties.referenceLinePosition,\n dataLabelShow: visuals.StandardObjectProperties.dataLabelShow,\n dataLabelColor: visuals.StandardObjectProperties.dataLabelColor,\n dataLabelDecimalPoints: visuals.StandardObjectProperties.dataLabelDecimalPoints,\n dataLabelHorizontalPosition: visuals.StandardObjectProperties.dataLabelHorizontalPosition,\n dataLabelVerticalPosition: visuals.StandardObjectProperties.dataLabelVerticalPosition,\n dataLabelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: $.extend({}, visuals.StandardObjectProperties.legendTitle, {\n suppressFormatPainterCopy: true\n }),\n labelColor: visuals.StandardObjectProperties.labelColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n categoryLabels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_CategoryLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n },\n },\n colorBorder: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_ColorBorder'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n },\n },\n fillPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_FillPoint'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n },\n },\n colorByCategory: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_ColorByCategory'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n }\n },\n currentFrameIndex: {\n properties: {\n index: {\n type: { numeric: true },\n }\n }\n },\n plotArea: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Plot'),\n //description: data.createDisplayNameGetter('Visual_PlotDescription'),\n properties: {\n transparency: visuals.StandardObjectProperties.transparency,\n image: visuals.StandardObjectProperties.image,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 0 }, 'Play': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 1 }, 'Play': { max: 0 } },\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n },\n values: {\n group: {\n by: 'Series',\n select: [\n { bind: { to: 'X' } },\n { bind: { to: 'Y' } },\n { bind: { to: 'Size' } },\n { bind: { to: 'Gradient' } },\n ],\n }\n },\n rowCount: { preferred: { min: 2 } },\n dataReductionAlgorithm: { sample: {} },\n dataVolume: 4,\n }\n }, {\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 0 }, 'Play': { min: 1, max: 1 } },\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 1 }, 'Play': { min: 1, max: 1 } },\n ],\n // Long term: consider adding the 'name' concept and have this be a reference to the other dataViewMapping above.\n // Then we'd also move the splitting logic of Matrix->Categorical[] into DataViewTransform, and other visuals would benefit.\n matrix: {\n rows: {\n select: [\n { bind: { to: 'Play' } },\n { bind: { to: 'Category' } },\n ],\n /* Explicitly override the server data reduction to make it appropriate for matrix/play. */\n dataReductionAlgorithm: { bottom: { count: 5000 } }\n },\n columns: {\n for: { in: 'Series' },\n /* Explicitly override the server data reduction to make it appropriate for matrix/play. */\n dataReductionAlgorithm: { top: { count: 60 } }\n },\n values: {\n select: [\n { bind: { to: 'X' } },\n { bind: { to: 'Y' } },\n { bind: { to: 'Size' } },\n ]\n }\n }\n }, {\n conditions: [\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 0 }, 'Gradient': { max: 0 }, 'Play': { max: 0 } },\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 0 }, 'Gradient': { max: 1 }, 'Play': { max: 0 } },\n ],\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\n usage: {\n regression: {\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\n },\n },\n categorical: {\n categories: {\n for: { in: 'regression.X' }\n },\n values: {\n group: {\n by: 'regression.Series',\n select: [{ for: { in: 'regression.Y' } }],\n },\n },\n dataReductionAlgorithm: { sample: {} },\n dataVolume: 4,\n }\n }],\n sorting: {\n custom: {},\n implicit: {\n clauses: [{ role: 'Play', direction: 1 /* Ascending */ }] //typically a datetime field, sort asc\n },\n },\n drilldown: {\n roles: ['Category']\n },\n };\n visuals.scatterChartProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n dataPoint: {\n defaultColor: { objectName: 'dataPoint', propertyName: 'defaultColor' },\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n },\n trend: {\n show: { objectName: 'trend', propertyName: 'show' },\n },\n colorBorder: {\n show: { objectName: 'colorBorder', propertyName: 'show' },\n },\n fillPoint: {\n show: { objectName: 'fillPoint', propertyName: 'show' },\n },\n colorByCategory: {\n show: { objectName: 'colorByCategory', propertyName: 'show' },\n },\n currentFrameIndex: {\n index: { objectName: 'currentFrameIndex', propertyName: 'index' },\n },\n legend: {\n labelColor: { objectName: 'legend', propertyName: 'labelColor' },\n },\n plotArea: {\n image: { objectName: 'plotArea', propertyName: 'image' },\n transparency: { objectName: 'plotArea', propertyName: 'transparency' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.slicerCapabilities = {\n dataRoles: [\n {\n name: 'Values',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Field'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_FieldDescription')\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n filter: {\n type: { filter: {} },\n },\n defaultValue: {\n type: { expression: { defaultValue: true } },\n },\n formatString: visuals.StandardObjectProperties.formatString,\n outlineColor: visuals.StandardObjectProperties.outlineColor,\n outlineWeight: visuals.StandardObjectProperties.outlineWeight,\n orientation: {\n displayName: powerbi.data.createDisplayNameGetter('Slicer_Orientation'),\n type: { enumeration: visuals.slicerOrientation.type }\n },\n count: {\n type: { integer: true }\n },\n },\n },\n selection: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_SelectionControls'),\n properties: {\n selectAllCheckboxEnabled: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_SelectAll'),\n type: { bool: true }\n },\n singleSelect: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_SingleSelect'),\n type: { bool: true }\n }\n },\n },\n header: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Header'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n fontColor: visuals.StandardObjectProperties.fontColor,\n background: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Background'),\n type: { fill: { solid: { color: true } } }\n },\n outline: visuals.StandardObjectProperties.outline,\n textSize: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_TextSize'),\n type: { numeric: true }\n },\n }\n },\n items: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Items'),\n properties: {\n fontColor: visuals.StandardObjectProperties.fontColor,\n background: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Background'),\n type: { fill: { solid: { color: true } } }\n },\n outline: visuals.StandardObjectProperties.outline,\n textSize: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_TextSize'),\n type: { numeric: true }\n },\n }\n }\n },\n dataViewMappings: [{\n conditions: [{ 'Values': { max: 1 } }],\n categorical: {\n categories: {\n for: { in: 'Values' },\n dataReductionAlgorithm: { window: {} }\n },\n includeEmptyGroups: true,\n }\n }],\n sorting: {\n default: {},\n },\n suppressDefaultTitle: true,\n disableVisualDetails: true,\n };\n // TODO: Generate these from above, defining twice just introduces potential for error\n visuals.slicerProps = {\n general: {\n outlineColor: { objectName: 'general', propertyName: 'outlineColor' },\n outlineWeight: { objectName: 'general', propertyName: 'outlineWeight' },\n orientation: { objectName: 'general', propertyName: 'orientation' },\n count: { objectName: 'general', propertyName: 'count' },\n },\n selection: {\n selectAllCheckboxEnabled: { objectName: 'selection', propertyName: 'selectAllCheckboxEnabled' },\n singleSelect: { objectName: 'selection', propertyName: 'singleSelect' }\n },\n header: {\n show: { objectName: 'header', propertyName: 'show' },\n fontColor: { objectName: 'header', propertyName: 'fontColor' },\n background: { objectName: 'header', propertyName: 'background' },\n outline: { objectName: 'header', propertyName: 'outline' },\n textSize: { objectName: 'header', propertyName: 'textSize' },\n },\n items: {\n fontColor: { objectName: 'items', propertyName: 'fontColor' },\n background: { objectName: 'items', propertyName: 'background' },\n outline: { objectName: 'items', propertyName: 'outline' },\n textSize: { objectName: 'items', propertyName: 'textSize' },\n },\n selectedPropertyIdentifier: { objectName: 'general', propertyName: 'selected' },\n filterPropertyIdentifier: { objectName: 'general', propertyName: 'filter' },\n formatString: { objectName: 'general', propertyName: 'formatString' },\n defaultValue: { objectName: 'general', propertyName: 'defaultValue' },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.tableCapabilities = {\n dataRoles: [{\n name: 'Values',\n kind: powerbi.VisualDataRoleKind.GroupingOrMeasure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values'),\n }],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n columnWidth: {\n type: { numeric: true }\n },\n totals: {\n type: { bool: true },\n displayName: powerbi.data.createDisplayNameGetter('Visual_Totals'),\n suppressFormatPainterCopy: true,\n },\n autoSizeColumnWidth: {\n type: { bool: true },\n displayName: powerbi.data.createDisplayNameGetter('Visual_Adjust_Column_Width'),\n suppressFormatPainterCopy: true,\n },\n textSize: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_TextSize'),\n type: { numeric: true }\n },\n },\n },\n grid: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Grid'),\n properties: {\n outlineColor: visuals.StandardObjectProperties.outlineColor,\n outlineWeight: visuals.StandardObjectProperties.outlineWeight,\n gridVertical: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridVertical'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Desc'),\n type: { bool: true }\n },\n gridVerticalColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Color_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n gridVerticalWeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Weight'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Weight_Desc'),\n type: { numeric: true }\n },\n gridHorizontal: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Desc'),\n type: { bool: true }\n },\n gridHorizontalColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Color_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n gridHorizontalWeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Weight'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Weight_Desc'),\n type: { numeric: true }\n },\n rowPadding: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_RowPadding'),\n description: powerbi.data.createDisplayNameGetter('Visual_RowPadding_Desc'),\n type: { numeric: true }\n },\n imageHeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_ImageHeight'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_ImageHeight_Desc'),\n type: { numeric: true }\n },\n }\n },\n columnHeaders: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_ColumnHeaders'),\n properties: {\n outline: visuals.StandardObjectProperties.outline,\n fontColor: visuals.StandardObjectProperties.fontColor,\n backColor: visuals.StandardObjectProperties.backColor,\n }\n },\n values: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_Values'),\n properties: {\n outline: visuals.StandardObjectProperties.outline,\n // backColor overrides backColorPrimary and Secondary (e.g., in the case of conditional formatting)\n backColor: {\n type: { fill: { solid: { color: true } } }\n },\n fontColorPrimary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n backColorPrimary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n fontColorSecondary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n backColorSecondary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n urlIcon: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_UrlIcon'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_UrlIcon_Desc'),\n type: { bool: true }\n },\n }\n },\n total: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_TotalGrand'),\n properties: {\n outline: visuals.StandardObjectProperties.outline,\n fontColor: visuals.StandardObjectProperties.fontColor,\n backColor: visuals.StandardObjectProperties.backColor,\n }\n },\n },\n dataViewMappings: [{\n table: {\n rows: {\n for: { in: 'Values' },\n dataReductionAlgorithm: { window: { count: 500 } }\n },\n rowCount: { preferred: { min: 1 } }\n },\n }],\n sorting: {\n custom: {},\n },\n suppressDefaultTitle: true,\n supportsSelection: false,\n disableVisualDetails: true,\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.matrixRoleNames = {\n rows: 'Rows',\n columns: 'Columns',\n values: 'Values',\n };\n visuals.matrixCapabilities = {\n dataRoles: [\n {\n name: visuals.matrixRoleNames.rows,\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Rows'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_RowsDescription')\n }, {\n name: visuals.matrixRoleNames.columns,\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Columns'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_ColumnsDescription')\n }, {\n name: visuals.matrixRoleNames.values,\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values')\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n columnWidth: {\n type: { numeric: true }\n },\n rowSubtotals: {\n type: { bool: true },\n displayName: powerbi.data.createDisplayNameGetter('Visual_TotalRow'),\n suppressFormatPainterCopy: true,\n },\n columnSubtotals: {\n type: { bool: true },\n displayName: powerbi.data.createDisplayNameGetter('Visual_TotalColumn'),\n suppressFormatPainterCopy: true,\n },\n autoSizeColumnWidth: {\n type: { bool: true },\n displayName: powerbi.data.createDisplayNameGetter('Visual_Adjust_Column_Width'),\n suppressFormatPainterCopy: true,\n },\n textSize: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_TextSize'),\n type: { numeric: true }\n },\n },\n },\n grid: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Grid'),\n properties: {\n outlineColor: visuals.StandardObjectProperties.outlineColor,\n outlineWeight: visuals.StandardObjectProperties.outlineWeight,\n gridVertical: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridVertical'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Desc'),\n type: { bool: true }\n },\n gridVerticalColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Color_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n gridVerticalWeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Weight'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridVertical_Weight_Desc'),\n type: { numeric: true }\n },\n gridHorizontal: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Desc'),\n type: { bool: true }\n },\n gridHorizontalColor: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Color'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Color_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n gridHorizontalWeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Weight'),\n description: powerbi.data.createDisplayNameGetter('Visual_GridHorizontal_Weight_Desc'),\n type: { numeric: true }\n },\n rowPadding: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_RowPadding'),\n description: powerbi.data.createDisplayNameGetter('Visual_RowPadding_Desc'),\n type: { numeric: true }\n },\n imageHeight: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_ImageHeight'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_ImageHeight_Desc'),\n type: { numeric: true }\n },\n },\n },\n columnHeaders: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_ColumnHeaders'),\n properties: {\n outline: visuals.StandardObjectProperties.outline,\n fontColor: visuals.StandardObjectProperties.fontColor,\n backColor: visuals.StandardObjectProperties.backColor,\n }\n },\n rowHeaders: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_RowHeaders'),\n properties: {\n outline: visuals.StandardObjectProperties.outline,\n fontColor: visuals.StandardObjectProperties.fontColor,\n backColor: visuals.StandardObjectProperties.backColor,\n }\n },\n values: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_Values'),\n properties: {\n outline: visuals.StandardObjectProperties.outline,\n fontColorPrimary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n backColorPrimary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n fontColorSecondary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n backColorSecondary: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary'),\n description: powerbi.data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary_Desc'),\n type: { fill: { solid: { color: true } } }\n },\n }\n },\n subTotals: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Tablix_TotalSub'),\n properties: {\n outline: visuals.StandardObjectProperties.outline,\n fontColor: visuals.StandardObjectProperties.fontColor,\n backColor: visuals.StandardObjectProperties.backColor,\n }\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Rows': { max: 0 }, 'Columns': { max: 0 }, 'Values': { min: 1 } },\n { 'Rows': { min: 1 }, 'Columns': { min: 0 }, 'Values': { min: 0 } },\n { 'Rows': { min: 0 }, 'Columns': { min: 1 }, 'Values': { min: 0 } }\n ],\n matrix: {\n rows: {\n for: { in: 'Rows' },\n /* Explicitly override the server data reduction to make it appropriate for matrix. */\n dataReductionAlgorithm: { window: { count: 500 } }\n },\n columns: {\n for: { in: 'Columns' },\n /* Explicitly override the server data reduction to make it appropriate for matrix. */\n dataReductionAlgorithm: { top: { count: 100 } }\n },\n values: {\n for: { in: 'Values' }\n }\n }\n }],\n filterMappings: {\n measureFilter: {\n targetRoles: [visuals.matrixRoleNames.rows]\n }\n },\n sorting: {\n custom: {},\n },\n suppressDefaultTitle: true,\n supportsSelection: false,\n disableVisualDetails: true,\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.treemapCapabilities = {\n dataRoles: [\n {\n name: 'Group',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Group'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GroupTreemapDescription')\n }, {\n name: 'Details',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Details'),\n }, {\n name: 'Values',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Values'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }, {\n name: 'Gradient',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Gradient'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\n requiredTypes: [{ numeric: true }, { integer: true }],\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: visuals.StandardObjectProperties.legendTitle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n fill: {\n type: { fill: { solid: { color: true } } }\n },\n fillRule: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Gradient'),\n type: { fillRule: {} },\n rule: {\n inputRole: 'Gradient',\n output: {\n property: 'fill',\n selector: ['Group'],\n }\n }\n }\n }\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n categoryLabels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_CategoryLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Group': { max: 1 }, 'Details': { max: 0 }, 'Gradient': { max: 1 } },\n { 'Group': { max: 1 }, 'Details': { min: 1, max: 1 }, 'Values': { max: 1 }, 'Gradient': { max: 0 } }\n ],\n categorical: {\n categories: {\n for: { in: 'Group' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n group: {\n by: 'Details',\n select: [{ bind: { to: 'Values' } }, { bind: { to: 'Gradient' } }],\n dataReductionAlgorithm: { top: {} }\n }\n },\n rowCount: { preferred: { min: 2 } }\n }\n }],\n supportsHighlight: true,\n sorting: {\n custom: {},\n implicit: {\n clauses: [{ role: 'Values', direction: 2 /* Descending */ }]\n },\n },\n drilldown: {\n roles: ['Group']\n },\n };\n visuals.treemapProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n dataPoint: {\n fill: { objectName: 'dataPoint', propertyName: 'fill' },\n },\n legend: {\n show: { objectName: 'legend', propertyName: 'show' },\n position: { objectName: 'legend', propertyName: 'position' },\n showTitle: { objectName: 'legend', propertyName: 'showTitle' },\n titleText: { objectName: 'legend', propertyName: 'titleText' },\n labelColor: { objectName: 'legend', propertyName: 'labelColor' },\n },\n labels: {\n show: { objectName: 'labels', propertyName: 'show' },\n color: { objectName: 'labels', propertyName: 'color' },\n labelDisplayUnits: { objectName: 'labels', propertyName: 'labelDisplayUnits' },\n labelPrecision: { objectName: 'labels', propertyName: 'labelPrecision' },\n },\n categoryLabels: {\n show: { objectName: 'categoryLabels', propertyName: 'show' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.cardCapabilities = {\n dataRoles: [\n {\n name: 'Values',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Fields'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_FieldsDescription'),\n }\n ],\n objects: {\n general: {\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointLabel'),\n properties: {\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n // NOTE: Consider adding a ValueType for fontSize.\n fontSize: visuals.StandardObjectProperties.fontSize,\n },\n },\n categoryLabels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_CategoryLabel'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n // NOTE: Consider adding a ValueType for fontSize.\n fontSize: visuals.StandardObjectProperties.fontSize,\n },\n },\n wordWrap: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_WordWrap'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Values': { max: 1 } }\n ],\n single: { role: \"Values\" }\n }],\n suppressDefaultTitle: true,\n supportsSelection: false,\n };\n visuals.cardProps = {\n categoryLabels: {\n show: { objectName: 'categoryLabels', propertyName: 'show' },\n color: { objectName: 'categoryLabels', propertyName: 'color' },\n fontSize: { objectName: 'categoryLabels', propertyName: 'fontSize' },\n },\n labels: {\n color: { objectName: 'labels', propertyName: 'color' },\n labelPrecision: { objectName: 'labels', propertyName: 'labelPrecision' },\n labelDisplayUnits: { objectName: 'labels', propertyName: 'labelDisplayUnits' },\n fontSize: { objectName: 'labels', propertyName: 'fontSize' },\n },\n wordWrap: {\n show: { objectName: 'wordWrap', propertyName: 'show' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.waterfallChartCapabilities = {\n dataRoles: [\n {\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Category'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_CategoryWaterfallDescription')\n }, {\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n requiredTypes: [{ numeric: true }, { integer: true }],\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Y'),\n }\n ],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n legend: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Legend'),\n description: powerbi.data.createDisplayNameGetter('Visual_LegendDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.legendPosition,\n showTitle: visuals.StandardObjectProperties.showLegendTitle,\n titleText: $.extend({}, visuals.StandardObjectProperties.legendTitle, {\n suppressFormatPainterCopy: true,\n }),\n labelColor: visuals.StandardObjectProperties.labelColor,\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n labels: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabels'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n color: visuals.StandardObjectProperties.dataColor,\n labelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n labelPrecision: $.extend({}, visuals.StandardObjectProperties.labelPrecision, {\n suppressFormatPainterCopy: true,\n }),\n fontSize: visuals.StandardObjectProperties.fontSize,\n }\n },\n sentimentColors: {\n displayName: powerbi.data.createDisplayNameGetter('Waterfall_SentimentColors'),\n properties: {\n increaseFill: {\n displayName: powerbi.data.createDisplayNameGetter('Waterfall_IncreaseLabel'),\n type: { fill: { solid: { color: true } } }\n },\n decreaseFill: {\n displayName: powerbi.data.createDisplayNameGetter('Waterfall_DecreaseLabel'),\n type: { fill: { solid: { color: true } } }\n },\n totalFill: {\n displayName: powerbi.data.createDisplayNameGetter('Waterfall_TotalLabel'),\n type: { fill: { solid: { color: true } } }\n }\n },\n },\n categoryAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_XAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n }\n },\n valueAxis: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n position: visuals.StandardObjectProperties.yAxisPosition,\n start: visuals.StandardObjectProperties.axisStart,\n end: visuals.StandardObjectProperties.axisEnd,\n showAxisTitle: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Axis_Title'),\n description: powerbi.data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\n type: { bool: true }\n },\n axisStyle: visuals.StandardObjectProperties.axisStyle,\n labelColor: visuals.StandardObjectProperties.labelColor,\n labelDisplayUnits: visuals.StandardObjectProperties.labelDisplayUnits,\n labelPrecision: visuals.StandardObjectProperties.labelPrecision,\n }\n },\n y1AxisReferenceLine: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Description'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n value: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\n type: { numeric: true }\n },\n lineColor: visuals.StandardObjectProperties.lineColor,\n transparency: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\n description: powerbi.data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\n type: { numeric: true }\n },\n style: visuals.StandardObjectProperties.referenceLineStyle,\n position: visuals.StandardObjectProperties.referenceLinePosition,\n dataLabelShow: visuals.StandardObjectProperties.dataLabelShow,\n dataLabelColor: visuals.StandardObjectProperties.dataLabelColor,\n dataLabelDecimalPoints: visuals.StandardObjectProperties.dataLabelDecimalPoints,\n dataLabelHorizontalPosition: visuals.StandardObjectProperties.dataLabelHorizontalPosition,\n dataLabelVerticalPosition: visuals.StandardObjectProperties.dataLabelVerticalPosition,\n dataLabelDisplayUnits: visuals.StandardObjectProperties.dataLabelDisplayUnits,\n },\n },\n plotArea: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Plot'),\n properties: {\n transparency: visuals.StandardObjectProperties.transparency,\n image: visuals.StandardObjectProperties.image,\n },\n },\n },\n dataViewMappings: [{\n conditions: [\n { 'Category': { max: 1 }, 'Y': { max: 1 } },\n ],\n categorical: {\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n select: [{ bind: { to: 'Y' } }]\n },\n },\n }],\n drilldown: {\n roles: ['Category']\n },\n };\n visuals.waterfallChartProps = {\n general: {\n formatString: { objectName: 'general', propertyName: 'formatString' },\n },\n sentimentColors: {\n increaseFill: { objectName: 'sentimentColors', propertyName: 'increaseFill' },\n decreaseFill: { objectName: 'sentimentColors', propertyName: 'decreaseFill' },\n totalFill: { objectName: 'sentimentColors', propertyName: 'totalFill' },\n },\n legend: {\n labelColor: { objectName: 'legend', propertyName: 'labelColor' },\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n visuals.KPIStatusWithHistoryCapabilities = {\n dataRoles: [\n {\n name: 'Indicator',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Indicator'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_IndicatorDescription')\n }, {\n name: 'TrendLine',\n kind: powerbi.VisualDataRoleKind.Grouping,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_TrendLine'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Trendline_Description')\n }, {\n name: 'Goal',\n kind: powerbi.VisualDataRoleKind.Measure,\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Goal'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_GoalDescription')\n }],\n dataViewMappings: [{\n conditions: [\n { 'Indicator': { max: 1 }, 'TrendLine': { max: 1 }, 'Goal': { max: 2 } },\n ],\n categorical: {\n categories: {\n for: { in: 'TrendLine' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n select: [\n { bind: { to: 'Indicator' } },\n { bind: { to: 'Goal' } }\n ]\n }\n },\n }],\n objects: {\n general: {\n properties: {\n formatString: visuals.StandardObjectProperties.formatString,\n },\n },\n indicator: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Indicator'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_IndicatorDescription'),\n properties: {\n indicatorDisplayUnits: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DisplayUnits'),\n description: powerbi.data.createDisplayNameGetter('Visual_DisplayUnitsDescription'),\n type: { formatting: { labelDisplayUnits: true } }\n },\n indicatorPrecision: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Precision'),\n description: powerbi.data.createDisplayNameGetter('Visual_PrecisionDescription'),\n placeHolderText: powerbi.data.createDisplayNameGetter('Visual_Precision_Auto'),\n type: { numeric: true }\n },\n kpiFormat: {\n displayName: powerbi.data.createDisplayNameGetter('TaskPane_Format'),\n type: { text: true },\n }\n }\n },\n trendline: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_TrendLine'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Trendline_Description'),\n properties: {\n show: visuals.StandardObjectProperties.show,\n }\n },\n goals: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Goals'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Goals'),\n properties: {\n showGoal: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Show_Goal'),\n type: { bool: true }\n },\n showDistance: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Show_Distance'),\n type: { bool: true }\n },\n }\n },\n status: {\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Status'),\n description: powerbi.data.createDisplayNameGetter('Role_DisplayName_KPI_Status'),\n properties: {\n direction: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_KPI_Direction'),\n type: { enumeration: visuals.kpiDirection.type }\n }\n }\n }\n },\n };\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var capabilities;\n (function (capabilities) {\n // This file registers the built-in capabilities\n // Please use this file to register the capabilities in the plugins.ts/pluginsNotForOSS.ts\n capabilities.animatedNumber = powerbi.visuals.animatedNumberCapabilities;\n capabilities.areaChart = powerbi.visuals.lineChartCapabilities;\n capabilities.barChart = powerbi.visuals.getColumnChartCapabilities(true);\n capabilities.card = powerbi.visuals.cardCapabilities;\n capabilities.multiRowCard = powerbi.visuals.multiRowCardCapabilities;\n capabilities.clusteredBarChart = powerbi.visuals.getColumnChartCapabilities(true);\n capabilities.clusteredColumnChart = powerbi.visuals.getColumnChartCapabilities();\n capabilities.columnChart = powerbi.visuals.getColumnChartCapabilities();\n capabilities.comboChart = powerbi.visuals.comboChartCapabilities;\n capabilities.dataDotChart = powerbi.visuals.dataDotChartCapabilities;\n capabilities.dataDotClusteredColumnComboChart = powerbi.visuals.comboChartCapabilities;\n capabilities.dataDotStackedColumnComboChart = powerbi.visuals.comboChartCapabilities;\n capabilities.donutChart = powerbi.visuals.donutChartCapabilities;\n capabilities.funnel = powerbi.visuals.funnelChartCapabilities;\n capabilities.gauge = powerbi.visuals.gaugeCapabilities;\n capabilities.hundredPercentStackedBarChart = powerbi.visuals.getColumnChartCapabilities(true);\n capabilities.hundredPercentStackedColumnChart = powerbi.visuals.getColumnChartCapabilities();\n capabilities.image = powerbi.visuals.imageVisualCapabilities;\n capabilities.lineChart = powerbi.visuals.lineChartCapabilities;\n capabilities.lineStackedColumnComboChart = powerbi.visuals.comboChartCapabilities;\n capabilities.lineClusteredColumnComboChart = powerbi.visuals.comboChartCapabilities;\n capabilities.map = powerbi.visuals.mapCapabilities;\n capabilities.filledMap = powerbi.visuals.filledMapCapabilities;\n capabilities.treemap = powerbi.visuals.treemapCapabilities;\n capabilities.pieChart = powerbi.visuals.donutChartCapabilities;\n capabilities.scatterChart = powerbi.visuals.scatterChartCapabilities;\n capabilities.table = powerbi.visuals.tableCapabilities;\n capabilities.matrix = powerbi.visuals.matrixCapabilities;\n capabilities.slicer = powerbi.visuals.slicerCapabilities;\n capabilities.textbox = powerbi.visuals.textboxCapabilities;\n capabilities.waterfallChart = powerbi.visuals.waterfallChartCapabilities;\n capabilities.cheerMeter = powerbi.visuals.cheerMeterCapabilities;\n capabilities.scriptVisual = powerbi.visuals.scriptVisualCapabilities;\n capabilities.kpi = powerbi.visuals.KPIStatusWithHistoryCapabilities;\n })(capabilities = visuals.capabilities || (visuals.capabilities = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var ColumnChartWebBehavior = (function () {\n function ColumnChartWebBehavior() {\n }\n ColumnChartWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n this.options = options;\n var eventGroup = options.eventGroup;\n eventGroup.on('click', function () {\n var d = ColumnChartWebBehavior.getDatumForLastInputEvent();\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\n });\n eventGroup.on('contextmenu', function () {\n if (d3.event.ctrlKey)\n return;\n d3.event.preventDefault();\n var d = ColumnChartWebBehavior.getDatumForLastInputEvent();\n var position = visuals.InteractivityUtils.getPositionOfLastInputEvent();\n selectionHandler.handleContextMenu(d, position);\n });\n };\n ColumnChartWebBehavior.prototype.renderSelection = function (hasSelection) {\n var options = this.options;\n options.bars.style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && options.hasHighlights); });\n };\n ColumnChartWebBehavior.getDatumForLastInputEvent = function () {\n var target = d3.event.target;\n return d3.select(target).datum();\n };\n return ColumnChartWebBehavior;\n }());\n visuals.ColumnChartWebBehavior = ColumnChartWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var DataDotChartWebBehavior = (function () {\n function DataDotChartWebBehavior() {\n }\n DataDotChartWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var dots = this.dots = options.dots;\n var dotLabels = options.dotLabels;\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(dots, selectionHandler);\n if (dotLabels) {\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(dotLabels, selectionHandler);\n }\n };\n DataDotChartWebBehavior.prototype.renderSelection = function (hasSelection) {\n this.dots.style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false); });\n };\n return DataDotChartWebBehavior;\n }());\n visuals.DataDotChartWebBehavior = DataDotChartWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var DonutChartWebBehavior = (function () {\n function DonutChartWebBehavior() {\n }\n DonutChartWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var slices = this.slices = options.slices;\n var highlightSlices = this.highlightSlices = options.highlightSlices;\n var clearCatcher = options.clearCatcher;\n this.hasHighlights = options.hasHighlights;\n var clickHandler = function (d) {\n selectionHandler.handleSelection(d.data, d3.event.ctrlKey);\n };\n var contextMenuHandler = function (d) {\n if (d3.event.ctrlKey)\n return;\n var position = visuals.InteractivityUtils.getPositionOfLastInputEvent();\n selectionHandler.handleContextMenu(d.data, position);\n d3.event.preventDefault();\n };\n slices.on('click', clickHandler);\n slices.on('contextmenu', contextMenuHandler);\n highlightSlices.on('click', clickHandler);\n highlightSlices.on('contextmenu', contextMenuHandler);\n clearCatcher.on('click', function () {\n selectionHandler.handleClearSelection();\n });\n };\n DonutChartWebBehavior.prototype.renderSelection = function (hasSelection) {\n var hasHighlights = this.hasHighlights;\n this.slices.style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, hasHighlights && !d.data.selected); });\n this.highlightSlices.style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, true, false, hasHighlights); });\n };\n return DonutChartWebBehavior;\n }());\n visuals.DonutChartWebBehavior = DonutChartWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var FunnelWebBehavior = (function () {\n function FunnelWebBehavior() {\n }\n FunnelWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var bars = this.bars = options.bars;\n var interactors = this.interactors = options.interactors;\n var clearCatcher = options.clearCatcher;\n this.hasHighlights = options.hasHighlights;\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(bars, selectionHandler);\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(interactors, selectionHandler);\n clearCatcher.on('click', function () {\n selectionHandler.handleClearSelection();\n });\n };\n FunnelWebBehavior.prototype.renderSelection = function (hasSelection) {\n var hasHighlights = this.hasHighlights;\n this.bars.style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && hasHighlights); });\n };\n return FunnelWebBehavior;\n }());\n visuals.FunnelWebBehavior = FunnelWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var LineChartWebBehavior = (function () {\n function LineChartWebBehavior() {\n }\n LineChartWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n this.lines = options.lines;\n var interactivityLines = options.interactivityLines;\n var dots = this.dots = options.dots;\n var areas = this.areas = options.areas;\n var tooltipOverlay = this.tooltipOverlay = options.tooltipOverlay;\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(interactivityLines, selectionHandler);\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(dots, selectionHandler);\n if (areas) {\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(areas, selectionHandler);\n }\n if (tooltipOverlay)\n tooltipOverlay.on('click', function () { return selectionHandler.handleClearSelection(); });\n };\n LineChartWebBehavior.prototype.renderSelection = function (hasSelection) {\n this.lines.style(\"stroke-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); });\n this.dots.style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); });\n if (this.areas)\n this.areas.style(\"fill-opacity\", function (d) { return (hasSelection && !d.selected) ? visuals.LineChart.DimmedAreaFillOpacity : visuals.LineChart.AreaFillOpacity; });\n };\n return LineChartWebBehavior;\n }());\n visuals.LineChartWebBehavior = LineChartWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var MapBehavior = (function () {\n function MapBehavior() {\n this.mapPointerEventsDisabled = false;\n this.mapPointerTimeoutSet = false;\n this.viewChangedSinceLastClearMouseDown = false;\n this.receivedZoomOrPanEvent = false;\n }\n MapBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var _this = this;\n var bubbles = this.bubbles = options.bubbles;\n var slices = this.slices = options.slices;\n var shapes = this.shapes = options.shapes;\n var clearCatcher = options.clearCatcher;\n var clickHandler = function () {\n var target = d3.event.target;\n var d = d3.select(target).datum();\n if (bubbles)\n bubbles.style(\"pointer-events\", \"all\");\n if (shapes)\n shapes.style(\"pointer-events\", \"all\");\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\n };\n if (!this.mapPointerEventsDisabled) {\n if (bubbles)\n bubbles.style(\"pointer-events\", \"all\");\n if (slices)\n slices.style(\"pointer-events\", \"all\");\n if (shapes)\n shapes.style(\"pointer-events\", \"all\");\n }\n if (bubbles) {\n options.bubbleEventGroup.on('click', clickHandler);\n options.bubbleEventGroup.on('mousewheel', function () {\n if (!_this.mapPointerEventsDisabled)\n bubbles.style(\"pointer-events\", \"none\");\n _this.mapPointerEventsDisabled = true;\n if (!_this.mapPointerTimeoutSet) {\n _this.mapPointerTimeoutSet = true;\n setTimeout(function () {\n if (bubbles)\n bubbles.style(\"pointer-events\", \"all\");\n _this.mapPointerEventsDisabled = false;\n _this.mapPointerTimeoutSet = false;\n }, 200);\n }\n });\n visuals.InteractivityUtils.registerGroupContextMenuHandler(options.bubbleEventGroup, selectionHandler);\n }\n if (slices) {\n options.sliceEventGroup.on('click', function () {\n slices.style(\"pointer-events\", \"all\");\n _this.mapPointerEventsDisabled = false;\n var target = d3.event.target;\n var d = d3.select(target).datum();\n selectionHandler.handleSelection(d.data, d3.event.ctrlKey);\n });\n options.sliceEventGroup.on('mousewheel', function () {\n if (!_this.mapPointerEventsDisabled)\n slices.style(\"pointer-events\", \"none\");\n _this.mapPointerEventsDisabled = true;\n if (!_this.mapPointerTimeoutSet) {\n _this.mapPointerTimeoutSet = true;\n setTimeout(function () {\n if (slices)\n slices.style(\"pointer-events\", \"all\");\n _this.mapPointerEventsDisabled = false;\n _this.mapPointerTimeoutSet = false;\n }, 200);\n }\n });\n options.sliceEventGroup.on('contextmenu', function () {\n if (d3.event.ctrlKey)\n return;\n d3.event.preventDefault();\n var position = visuals.InteractivityUtils.getPositionOfLastInputEvent();\n var target = d3.event.target;\n var d = d3.select(target).datum();\n selectionHandler.handleContextMenu(d.data, position);\n });\n }\n if (shapes) {\n options.shapeEventGroup.on('click', clickHandler);\n options.shapeEventGroup.on('mousewheel', function () {\n if (!_this.mapPointerEventsDisabled) {\n shapes.style(\"pointer-events\", \"none\");\n }\n _this.mapPointerEventsDisabled = true;\n if (!_this.mapPointerTimeoutSet) {\n _this.mapPointerTimeoutSet = true;\n setTimeout(function () {\n if (shapes)\n shapes.style(\"pointer-events\", \"all\");\n _this.mapPointerEventsDisabled = false;\n _this.mapPointerTimeoutSet = false;\n }, 200);\n }\n });\n visuals.InteractivityUtils.registerGroupContextMenuHandler(options.shapeEventGroup, selectionHandler);\n }\n clearCatcher.on('mouseup', function () {\n if (!_this.viewChangedSinceLastClearMouseDown) {\n selectionHandler.handleClearSelection();\n _this.receivedZoomOrPanEvent = true;\n }\n });\n clearCatcher.on('mousedown', function () {\n _this.viewChangedSinceLastClearMouseDown = false;\n });\n clearCatcher.on('mousewheel', function () {\n _this.receivedZoomOrPanEvent = true;\n });\n };\n MapBehavior.prototype.renderSelection = function (hasSelection) {\n if (this.bubbles) {\n this.bubbles\n .style({\n 'fill-opacity': function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); },\n 'stroke-opacity': function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); },\n });\n }\n if (this.slices) {\n this.slices\n .style({\n \"fill-opacity\": function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false); },\n \"stroke-opacity\": function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false); },\n });\n }\n if (this.shapes) {\n this.shapes\n .style({\n \"fill-opacity\": function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); },\n \"stroke-opacity\": function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); },\n });\n }\n };\n MapBehavior.prototype.viewChanged = function () {\n this.viewChangedSinceLastClearMouseDown = true;\n };\n MapBehavior.prototype.resetZoomPan = function () {\n this.receivedZoomOrPanEvent = false;\n };\n MapBehavior.prototype.hasReceivedZoomOrPanEvent = function () {\n return this.receivedZoomOrPanEvent;\n };\n return MapBehavior;\n }());\n visuals.MapBehavior = MapBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var ScatterChartWebBehavior = (function () {\n function ScatterChartWebBehavior() {\n }\n ScatterChartWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var bubbles = this.bubbles = options.dataPointsSelection;\n var data = options.data;\n var eventGroup = options.eventGroup;\n // If we are removing play-axis, remove the trace lines as well\n // TODO: revisit this design, I think ideally this is done when rendering scatter.\n if (this.playOptions\n && this.playOptions.traceLineRenderer\n && (!options.playOptions || !options.playOptions.traceLineRenderer)) {\n this.playOptions.traceLineRenderer.remove();\n }\n this.playOptions = options.playOptions;\n this.shouldEnableFill = (!data.sizeRange || !data.sizeRange.min) && data.fillPoint;\n this.colorBorder = data.colorBorder;\n if (eventGroup) {\n visuals.InteractivityUtils.registerGroupInteractivityHandlers(eventGroup, selectionHandler);\n }\n else {\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(bubbles, selectionHandler);\n }\n };\n ScatterChartWebBehavior.prototype.renderSelection = function (hasSelection) {\n var shouldEnableFill = this.shouldEnableFill;\n var colorBorder = this.colorBorder;\n this.bubbles.style(\"fill-opacity\", function (d) { return visuals.ScatterChart.getMarkerFillOpacity(d.size != null, shouldEnableFill, hasSelection, d.selected); });\n this.bubbles.style(\"stroke-opacity\", function (d) { return visuals.ScatterChart.getMarkerStrokeOpacity(d.size != null, colorBorder, hasSelection, d.selected); });\n if (this.playOptions && this.bubbles) {\n var selectedPoints = this.bubbles.filter(function (d) { return d.selected; }).data();\n var traceLineRenderer = this.playOptions.traceLineRenderer;\n if (selectedPoints && selectedPoints.length > 0 && traceLineRenderer != null) {\n traceLineRenderer.render(selectedPoints, true);\n }\n else {\n traceLineRenderer.remove();\n }\n }\n };\n return ScatterChartWebBehavior;\n }());\n visuals.ScatterChartWebBehavior = ScatterChartWebBehavior;\n var ScatterChartMobileBehavior = (function () {\n function ScatterChartMobileBehavior() {\n }\n ScatterChartMobileBehavior.prototype.bindEvents = function (options, selectionHandler) {\n this.setOptions(options);\n if (!options.visualInitOptions || !options.visualInitOptions.interactivity.isInteractiveLegend) {\n // Don't bind events if we are not in interactiveLegend mode\n // This case happend when on mobile we show the whole dashboard in still not on focus\n return;\n }\n this.makeDataPointsSelectable(options.dataPointsSelection);\n this.makeRootSelectable(options.root);\n this.makeDragable(options.root);\n this.disableDefaultTouchInteractions(options.root);\n this.selectRoot();\n };\n ScatterChartMobileBehavior.prototype.renderSelection = function (HasSelection) { };\n ScatterChartMobileBehavior.prototype.setSelectionHandler = function (selectionHandler) { };\n ScatterChartMobileBehavior.prototype.makeDataPointsSelectable = function () {\n var _this = this;\n var selection = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n selection[_i - 0] = arguments[_i];\n }\n for (var i = 0, len = selection.length; i < len; i++) {\n var sel = selection[i];\n sel.on('click', function (d, i) {\n _this.select(i);\n });\n }\n };\n ScatterChartMobileBehavior.prototype.makeRootSelectable = function (selection) {\n var _this = this;\n selection.on('click', function (d, i) {\n _this.selectRoot();\n });\n };\n ScatterChartMobileBehavior.prototype.makeDragable = function () {\n var _this = this;\n var selection = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n selection[_i - 0] = arguments[_i];\n }\n for (var i = 0, len = selection.length; i < len; i++) {\n var sel = selection[i];\n var drag = d3.behavior.drag()\n .on('drag', function (d) { _this.drag(0 /* Drag */); })\n .on('dragend', function (d) { _this.drag(1 /* DragEnd */); });\n sel.call(drag);\n }\n };\n ScatterChartMobileBehavior.prototype.disableDefaultTouchInteractions = function (selection) {\n selection.style('touch-action', 'none');\n };\n ScatterChartMobileBehavior.prototype.setOptions = function (options) {\n this.data = options.data;\n this.mainGraphicsContext = options.plotContext;\n this.xAxisProperties = options.xAxisProperties;\n this.yAxisProperties = options.yAxisProperties;\n this.host = options.host;\n };\n ScatterChartMobileBehavior.prototype.select = function (index) {\n this.selectDotByIndex(index);\n };\n ScatterChartMobileBehavior.prototype.selectRoot = function () {\n var marker = jsCommon.PerformanceUtil.create('selectRoot');\n this.onClick();\n marker.end();\n };\n ScatterChartMobileBehavior.prototype.drag = function (t) {\n switch (t) {\n case 0 /* Drag */:\n this.onDrag();\n break;\n case 1 /* DragEnd */:\n this.onClick();\n break;\n default:\n debug.assertFail('Unknown Drag Type');\n }\n };\n ScatterChartMobileBehavior.prototype.onDrag = function () {\n //find the current x and y position\n var xy = this.getMouseCoordinates();\n //move the crosshair to the current position\n this.moveCrosshairToXY(xy.x, xy.y);\n //update the style and the legend of the dots\n var selectedIndex = this.findClosestDotIndex(xy.x, xy.y);\n this.selectDot(selectedIndex);\n this.updateLegend(selectedIndex);\n };\n ScatterChartMobileBehavior.prototype.onClick = function () {\n //find the current x and y position\n var xy = this.getMouseCoordinates();\n var selectedIndex = this.findClosestDotIndex(xy.x, xy.y);\n if (selectedIndex !== -1)\n this.selectDotByIndex(selectedIndex);\n };\n ScatterChartMobileBehavior.prototype.getMouseCoordinates = function () {\n var mainGfxContext = this.mainGraphicsContext;\n // select (0,0) in cartesian coordinates\n var x = 0;\n var y = parseInt(mainGfxContext.attr('height'), 10);\n y = y || 0;\n try {\n var mouse = d3.mouse(mainGfxContext.node());\n x = mouse[0];\n y = mouse[1];\n }\n catch (e) {\n }\n return { x: x, y: y, };\n };\n ScatterChartMobileBehavior.prototype.selectDotByIndex = function (index) {\n this.selectDot(index);\n this.moveCrosshairToIndexDot(index);\n this.updateLegend(index);\n };\n ScatterChartMobileBehavior.prototype.selectDot = function (dotIndex) {\n var _this = this;\n var root = this.mainGraphicsContext;\n root.selectAll(ScatterChartMobileBehavior.ScatterChartCircleTagName + ScatterChartMobileBehavior.DotClassSelector).classed({ selected: false, notSelected: true });\n root.selectAll(ScatterChartMobileBehavior.ScatterChartCircleTagName + ScatterChartMobileBehavior.DotClassSelector).filter(function (d, i) {\n var dataPoints = _this.data.dataPoints;\n debug.assert(dataPoints.length > dotIndex, \"dataPoints length:\" + dataPoints.length + \"is smaller than index:\" + dotIndex);\n var currentPoint = dataPoints[dotIndex];\n return (d.x === currentPoint.x) && (d.y === currentPoint.y);\n }).classed({ selected: true, notSelected: false });\n };\n ScatterChartMobileBehavior.prototype.moveCrosshairToIndexDot = function (index) {\n var dataPoints = this.data.dataPoints;\n var root = this.mainGraphicsContext;\n debug.assert(dataPoints.length > index, \"dataPoints length:\" + dataPoints.length + \"is smaller than index:\" + index);\n var x = this.xAxisProperties.scale(dataPoints[index].x);\n var y = this.yAxisProperties.scale(dataPoints[index].y);\n if (this.crosshair == null) {\n var width = +root.attr('width');\n var height = +root.attr('height');\n this.crosshair = this.drawCrosshair(root, x, y, width, height);\n this.crosshairHorizontal = this.crosshair.select(ScatterChartMobileBehavior.Horizontal.selector);\n this.crosshairVertical = this.crosshair.select(ScatterChartMobileBehavior.Vertical.selector);\n }\n else {\n this.moveCrosshairToXY(x, y);\n }\n };\n ScatterChartMobileBehavior.prototype.moveCrosshairToXY = function (x, y) {\n this.crosshairHorizontal.attr({ y1: y, y2: y });\n this.crosshairVertical.attr({ x1: x, x2: x });\n };\n ScatterChartMobileBehavior.prototype.drawCrosshair = function (addTo, x, y, width, height) {\n var crosshair = addTo.append(\"g\");\n crosshair.classed(ScatterChartMobileBehavior.CrosshairClassName, true);\n crosshair.append('line').classed(ScatterChartMobileBehavior.Horizontal.class, true).attr({ x1: 0, x2: width, y1: y, y2: y });\n crosshair.append('line').classed(ScatterChartMobileBehavior.Vertical.class, true).attr({ x1: x, x2: x, y1: height, y2: 0 });\n return crosshair;\n };\n ScatterChartMobileBehavior.prototype.findClosestDotIndex = function (x, y) {\n var selectedIndex = -1;\n var minDistance = Number.MAX_VALUE;\n var dataPoints = this.data.dataPoints;\n var xAxisPropertiesScale = this.xAxisProperties.scale;\n var yAxisPropertiesScale = this.yAxisProperties.scale;\n for (var i in dataPoints) {\n var currentPoint = dataPoints[i];\n var circleX = xAxisPropertiesScale(currentPoint.x);\n var circleY = yAxisPropertiesScale(currentPoint.y);\n var horizontalDistance = circleX - x;\n var verticalDistance = circleY - y;\n var distanceSqrd = (horizontalDistance * horizontalDistance) + (verticalDistance * verticalDistance);\n if (minDistance === Number.MAX_VALUE) {\n selectedIndex = i;\n minDistance = distanceSqrd;\n }\n else if (minDistance && minDistance > distanceSqrd) {\n selectedIndex = i;\n minDistance = distanceSqrd;\n }\n }\n return selectedIndex;\n };\n ScatterChartMobileBehavior.prototype.updateLegend = function (dotIndex) {\n if (this.lastDotIndex == null || this.lastDotIndex !== dotIndex) {\n var legendItems = this.createLegendDataPoints(dotIndex);\n this.host.updateLegend(legendItems);\n this.lastDotIndex = dotIndex;\n }\n };\n ScatterChartMobileBehavior.prototype.createLegendDataPoints = function (dotIndex) {\n var formatStringProp = visuals.scatterChartProps.general.formatString;\n var legendItems = [];\n var data = this.data;\n debug.assert(data.dataPoints.length > dotIndex, \"dataPoints length:\" + data.dataPoints.length + \"is smaller than index:\" + dotIndex);\n var point = data.dataPoints[dotIndex];\n //set the title of the legend to be the category or radius or group or blank\n var blank = visuals.valueFormatter.format(null);\n var title = blank;\n var legendData = data.legendData;\n debug.assertValue(legendData, \"legendData\");\n debug.assertValue(legendData.dataPoints, \"legendData\");\n var legendDataPoints = legendData.dataPoints;\n var category = point.formattedCategory.getValue();\n if (category !== blank) {\n title = category;\n }\n else if (point.radius.sizeMeasure != null) {\n title = visuals.valueFormatter.format(point.radius.sizeMeasure.source.groupName);\n }\n else if (legendDataPoints.length >= dotIndex && legendDataPoints[dotIndex].label !== blank) {\n title = legendDataPoints[dotIndex].label;\n }\n if (data.xCol != null) {\n legendItems.push({\n category: title,\n color: point.fill,\n identity: visuals.SelectionIdBuilder.builder().withMeasure(data.xCol.queryName).createSelectionId(),\n selected: point.selected,\n icon: visuals.LegendIcon.Box,\n label: visuals.valueFormatter.format(this.data.axesLabels.x),\n measure: visuals.valueFormatter.format(point.x, visuals.valueFormatter.getFormatString(data.xCol, formatStringProp)),\n iconOnlyOnLabel: true,\n });\n }\n if (data.yCol != null) {\n legendItems.push({\n category: title,\n color: point.fill,\n identity: visuals.SelectionIdBuilder.builder().withMeasure(data.yCol.queryName).createSelectionId(),\n selected: point.selected,\n icon: visuals.LegendIcon.Box,\n label: visuals.valueFormatter.format(data.axesLabels.y),\n measure: visuals.valueFormatter.format(point.y, visuals.valueFormatter.getFormatString(data.yCol, formatStringProp)),\n iconOnlyOnLabel: true,\n });\n }\n if (data.size != null) {\n legendItems.push({\n category: title,\n color: point.fill,\n identity: visuals.SelectionIdBuilder.builder().withMeasure(data.size.queryName).createSelectionId(),\n selected: point.selected,\n icon: visuals.LegendIcon.Box,\n label: visuals.valueFormatter.format(data.size.displayName),\n measure: visuals.valueFormatter.format(point.radius.sizeMeasure.values[point.radius.index], visuals.valueFormatter.getFormatString(data.size, formatStringProp)),\n iconOnlyOnLabel: true\n });\n }\n return { dataPoints: legendItems };\n };\n ScatterChartMobileBehavior.CrosshairClassName = 'crosshair';\n ScatterChartMobileBehavior.ScatterChartCircleTagName = 'circle';\n ScatterChartMobileBehavior.DotClassName = 'dot';\n ScatterChartMobileBehavior.DotClassSelector = '.' + ScatterChartMobileBehavior.DotClassName;\n ScatterChartMobileBehavior.Horizontal = createClassAndSelector('horizontal');\n ScatterChartMobileBehavior.Vertical = createClassAndSelector('vertical');\n return ScatterChartMobileBehavior;\n }());\n visuals.ScatterChartMobileBehavior = ScatterChartMobileBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var HorizontalSlicerWebBehavior = (function () {\n function HorizontalSlicerWebBehavior() {\n }\n HorizontalSlicerWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n this.itemLabels = options.itemLabels;\n this.dataPoints = options.dataPoints;\n this.interactivityService = options.interactivityService;\n this.slicerSettings = options.settings;\n visuals.SlicerWebBehavior.bindSlicerEvents(options.slicerContainer, this.itemLabels, options.clear, selectionHandler, this.slicerSettings, this.interactivityService);\n };\n HorizontalSlicerWebBehavior.prototype.renderSelection = function (hasSelection) {\n visuals.SlicerWebBehavior.setSelectionOnSlicerItems(this.itemLabels, this.itemLabels, hasSelection, this.interactivityService, this.slicerSettings);\n };\n return HorizontalSlicerWebBehavior;\n }());\n visuals.HorizontalSlicerWebBehavior = HorizontalSlicerWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var VerticalSlicerWebBehavior = (function () {\n function VerticalSlicerWebBehavior() {\n }\n VerticalSlicerWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var slicers = options.itemContainers;\n this.itemLabels = options.itemLabels;\n this.itemInputs = options.itemInputs;\n this.dataPoints = options.dataPoints;\n this.interactivityService = options.interactivityService;\n this.settings = options.settings;\n visuals.SlicerWebBehavior.bindSlicerEvents(options.slicerContainer, slicers, options.clear, selectionHandler, this.settings, this.interactivityService);\n };\n VerticalSlicerWebBehavior.prototype.renderSelection = function (hasSelection) {\n visuals.SlicerWebBehavior.setSelectionOnSlicerItems(this.itemInputs, this.itemLabels, hasSelection, this.interactivityService, this.settings);\n };\n return VerticalSlicerWebBehavior;\n }());\n visuals.VerticalSlicerWebBehavior = VerticalSlicerWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var SlicerWebBehavior = (function () {\n function SlicerWebBehavior() {\n }\n SlicerWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n this.behavior = this.createWebBehavior(options);\n this.behavior.bindEvents(options.behaviorOptions, selectionHandler);\n };\n SlicerWebBehavior.prototype.renderSelection = function (hasSelection) {\n this.behavior.renderSelection(hasSelection);\n };\n SlicerWebBehavior.bindSlicerEvents = function (slicerContainer, slicers, slicerClear, selectionHandler, slicerSettings, interactivityService) {\n SlicerWebBehavior.bindSlicerItemSelectionEvent(slicers, selectionHandler, slicerSettings, interactivityService);\n SlicerWebBehavior.bindSlicerClearEvent(slicerClear, selectionHandler);\n SlicerWebBehavior.styleSlicerContainer(slicerContainer, interactivityService);\n };\n SlicerWebBehavior.setSelectionOnSlicerItems = function (selectableItems, itemLabel, hasSelection, interactivityService, slicerSettings) {\n if (!hasSelection && !interactivityService.isSelectionModeInverted()) {\n selectableItems.filter('.selected').classed('selected', false);\n selectableItems.filter('.partiallySelected').classed('partiallySelected', false);\n var input = selectableItems.selectAll('input');\n if (input) {\n input.property('checked', false);\n }\n itemLabel.style('color', slicerSettings.slicerText.color);\n }\n else {\n SlicerWebBehavior.styleSlicerItems(selectableItems, hasSelection, interactivityService.isSelectionModeInverted());\n }\n };\n SlicerWebBehavior.styleSlicerItems = function (slicerItems, hasSelection, isSelectionInverted) {\n slicerItems.each(function (d) {\n var slicerItem = this;\n var shouldCheck = false;\n if (d.isSelectAllDataPoint) {\n if (hasSelection) {\n slicerItem.classList.add('partiallySelected');\n shouldCheck = false;\n }\n else {\n slicerItem.classList.remove('partiallySelected');\n shouldCheck = isSelectionInverted;\n }\n }\n else {\n shouldCheck = jsCommon.LogicExtensions.XOR(d.selected, isSelectionInverted);\n }\n if (shouldCheck)\n slicerItem.classList.add('selected');\n else\n slicerItem.classList.remove('selected');\n // Set input selected state to match selection\n var input = slicerItem.getElementsByTagName('input')[0];\n if (input)\n input.checked = shouldCheck;\n });\n };\n SlicerWebBehavior.bindSlicerItemSelectionEvent = function (slicers, selectionHandler, slicerSettings, interactivityService) {\n SlicerWebBehavior.isTouch = false;\n slicers.on(\"touchstart\", function (d) {\n SlicerWebBehavior.isTouch = true;\n });\n slicers.on(\"pointerdown\", function (d) {\n var e = d3.event;\n if (e && e.pointerType === \"touch\") {\n SlicerWebBehavior.isTouch = true;\n }\n });\n slicers.on(\"click\", function (d) {\n d3.event.preventDefault();\n if (d.isSelectAllDataPoint) {\n selectionHandler.toggleSelectionModeInversion();\n }\n else {\n selectionHandler.handleSelection(d, SlicerWebBehavior.isTouch || SlicerWebBehavior.isMultiSelect(d3.event, slicerSettings, interactivityService));\n }\n selectionHandler.persistSelectionFilter(visuals.slicerProps.filterPropertyIdentifier);\n SlicerWebBehavior.isTouch = false;\n });\n };\n SlicerWebBehavior.bindSlicerClearEvent = function (slicerClear, selectionHandler) {\n if (slicerClear) {\n slicerClear.on(\"click\", function (d) {\n selectionHandler.handleClearSelection();\n selectionHandler.persistSelectionFilter(visuals.slicerProps.filterPropertyIdentifier);\n });\n }\n };\n SlicerWebBehavior.styleSlicerContainer = function (slicerContainer, interactivityService) {\n var hasSelection = (interactivityService.hasSelection() && interactivityService.isDefaultValueEnabled() === undefined)\n || interactivityService.isDefaultValueEnabled() === false;\n slicerContainer.classed('hasSelection', hasSelection);\n };\n SlicerWebBehavior.isMultiSelect = function (event, settings, interactivityService) {\n // If selection is inverted, assume we're always in multi-select mode;\n // Also, Ctrl can be used to multi-select even in single-select mode.\n return interactivityService.isSelectionModeInverted()\n || !settings.selection.singleSelect\n || event.ctrlKey;\n };\n SlicerWebBehavior.prototype.createWebBehavior = function (options) {\n var behavior;\n var orientation = options.orientation;\n switch (orientation) {\n case 1 /* Horizontal */:\n behavior = new visuals.HorizontalSlicerWebBehavior();\n break;\n case 0 /* Vertical */:\n default:\n behavior = new visuals.VerticalSlicerWebBehavior();\n break;\n }\n return behavior;\n };\n return SlicerWebBehavior;\n }());\n visuals.SlicerWebBehavior = SlicerWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var LegendBehavior = (function () {\n function LegendBehavior() {\n }\n LegendBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var legendItems = options.legendItems;\n this.legendIcons = options.legendIcons;\n var clearCatcher = options.clearCatcher;\n visuals.InteractivityUtils.registerStandardSelectionHandler(legendItems, selectionHandler);\n clearCatcher.on('click', function () {\n selectionHandler.handleClearSelection();\n });\n };\n LegendBehavior.prototype.renderSelection = function (hasSelection) {\n if (hasSelection) {\n this.legendIcons.style({\n 'fill': function (d) {\n if (!d.selected)\n return LegendBehavior.dimmedLegendColor;\n else\n return d.color;\n }\n });\n }\n else {\n this.legendIcons.style({\n 'fill': function (d) {\n return d.color;\n }\n });\n }\n };\n LegendBehavior.dimmedLegendColor = '#A6A6A6';\n return LegendBehavior;\n }());\n visuals.LegendBehavior = LegendBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var TreemapWebBehavior = (function () {\n function TreemapWebBehavior() {\n }\n TreemapWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var shapes = this.shapes = options.shapes;\n var highlightShapes = this.highlightShapes = options.highlightShapes;\n var majorLabels = options.majorLabels;\n var minorLabels = options.minorLabels;\n this.hasHighlights = options.hasHighlights;\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(shapes, selectionHandler);\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(highlightShapes, selectionHandler);\n if (majorLabels) {\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(majorLabels, selectionHandler);\n }\n if (minorLabels) {\n visuals.InteractivityUtils.registerStandardInteractivityHandlers(minorLabels, selectionHandler);\n }\n };\n TreemapWebBehavior.prototype.renderSelection = function (hasSelection) {\n var hasHighlights = this.hasHighlights;\n this.shapes\n .style(\"fill\", function (d) { return visuals.Treemap.getFill(d, /* isHighlightRect */ false); })\n .style(\"fill-opacity\", function (d) { return visuals.Treemap.getFillOpacity(d, hasSelection, !d.selected && hasHighlights, /* isHighlightRect */ false); });\n this.highlightShapes\n .style(\"fill\", function (d) { return visuals.Treemap.getFill(d, /* isHighlightRect */ true); })\n .style(\"fill-opacity\", function (d) { return visuals.Treemap.getFillOpacity(d, hasSelection, !d.selected && hasHighlights, /* isHighlightRect */ true); });\n };\n return TreemapWebBehavior;\n }());\n visuals.TreemapWebBehavior = TreemapWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var WaterfallChartWebBehavior = (function () {\n function WaterfallChartWebBehavior() {\n }\n WaterfallChartWebBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var bars = this.bars = options.bars;\n bars.on('click', function (d) {\n if (!d.isTotal) {\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\n }\n });\n bars.on('contextmenu', function (d) {\n if (d3.event.ctrlKey)\n return;\n d3.event.preventDefault();\n if (!d.isTotal) {\n var position = visuals.InteractivityUtils.getPositionOfLastInputEvent();\n selectionHandler.handleContextMenu(d, position);\n }\n });\n };\n WaterfallChartWebBehavior.prototype.renderSelection = function (hasSelection) {\n this.bars.style(\"fill-opacity\", function (d) { return d.isTotal ? visuals.ColumnUtil.DefaultOpacity : visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false); });\n };\n return WaterfallChartWebBehavior;\n }());\n visuals.WaterfallChartWebBehavior = WaterfallChartWebBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var LabelsBehavior = (function () {\n function LabelsBehavior() {\n }\n LabelsBehavior.prototype.bindEvents = function (options, selectionHandler) {\n this.labelItems = options.labelItems;\n visuals.InteractivityUtils.registerStandardSelectionHandler(this.labelItems, selectionHandler);\n };\n LabelsBehavior.prototype.renderSelection = function (hasSelection) {\n if (hasSelection) {\n this.labelItems.style({\n 'opacity': function (d) {\n if (!d.selected)\n return LabelsBehavior.DimmedLabelOpacity;\n else\n return LabelsBehavior.DefaultLabelOpacity;\n }\n });\n }\n else {\n this.labelItems.style({\n 'opacity': LabelsBehavior.DefaultLabelOpacity,\n });\n }\n };\n LabelsBehavior.DefaultLabelOpacity = 1;\n LabelsBehavior.DimmedLabelOpacity = 0.6;\n return LabelsBehavior;\n }());\n visuals.LabelsBehavior = LabelsBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var CartesianChartBehavior = (function () {\n function CartesianChartBehavior(behaviors) {\n this.behaviors = behaviors;\n }\n CartesianChartBehavior.prototype.bindEvents = function (options, selectionHandler) {\n var behaviors = this.behaviors;\n for (var i = 0, ilen = behaviors.length; i < ilen; i++) {\n behaviors[i].bindEvents(options.layerOptions[i], selectionHandler);\n }\n options.clearCatcher.on('click', function () {\n selectionHandler.handleClearSelection();\n });\n };\n CartesianChartBehavior.prototype.renderSelection = function (hasSelection) {\n for (var _i = 0, _a = this.behaviors; _i < _a.length; _i++) {\n var behavior = _a[_i];\n behavior.renderSelection(hasSelection);\n }\n };\n return CartesianChartBehavior;\n }());\n visuals.CartesianChartBehavior = CartesianChartBehavior;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * Default ranges are for when we have a field chosen for the axis,\n * but no values are returned by the query.\n */\n visuals.emptyDomain = [0, 0];\n var AxisHelper;\n (function (AxisHelper) {\n var XLabelMaxAllowedOverflow = 35;\n var TextHeightConstant = 10;\n var MinTickCount = 2;\n var DefaultBestTickCount = 3;\n var LeftPadding = 10;\n var ScalarTickLabelPadding = 3;\n function getRecommendedNumberOfTicksForXAxis(availableWidth) {\n if (availableWidth < 300)\n return 3;\n if (availableWidth < 500)\n return 5;\n return 8;\n }\n AxisHelper.getRecommendedNumberOfTicksForXAxis = getRecommendedNumberOfTicksForXAxis;\n function getRecommendedNumberOfTicksForYAxis(availableWidth) {\n if (availableWidth < 150)\n return 3;\n if (availableWidth < 300)\n return 5;\n return 8;\n }\n AxisHelper.getRecommendedNumberOfTicksForYAxis = getRecommendedNumberOfTicksForYAxis;\n /**\n * Get the best number of ticks based on minimum value, maximum value,\n * measure metadata and max tick count.\n *\n * @param min The minimum of the data domain.\n * @param max The maximum of the data domain.\n * @param valuesMetadata The measure metadata array.\n * @param maxTickCount The max count of intervals.\n * @param isDateTime - flag to show single tick when min is equal to max.\n */\n function getBestNumberOfTicks(min, max, valuesMetadata, maxTickCount, isDateTime) {\n debug.assert(maxTickCount >= 0, \"maxTickCount must be greater or equal to zero\");\n if (isNaN(min) || isNaN(max))\n return DefaultBestTickCount;\n debug.assert(min <= max, \"min value needs to be less or equal to max value\");\n if (maxTickCount <= 1 || (max <= 1 && min >= -1))\n return maxTickCount;\n if (min === max) {\n // datetime needs to only show one tick value in this case so formatting works correctly\n if (!!isDateTime)\n return 1;\n return DefaultBestTickCount;\n }\n if (hasNonIntegerData(valuesMetadata))\n return maxTickCount;\n // e.g. 5 - 2 + 1 = 4, => [2,3,4,5]\n return Math.min(max - min + 1, maxTickCount);\n }\n AxisHelper.getBestNumberOfTicks = getBestNumberOfTicks;\n function hasNonIntegerData(valuesMetadata) {\n for (var i = 0, len = valuesMetadata.length; i < len; i++) {\n var currentMetadata = valuesMetadata[i];\n if (currentMetadata && currentMetadata.type && !currentMetadata.type.integer) {\n return true;\n }\n }\n return false;\n }\n AxisHelper.hasNonIntegerData = hasNonIntegerData;\n function getRecommendedTickValues(maxTicks, scale, axisType, isScalar, minTickInterval) {\n if (!isScalar || isOrdinalScale(scale)) {\n return getRecommendedTickValuesForAnOrdinalRange(maxTicks, scale.domain());\n }\n else if (isDateTime(axisType)) {\n return getRecommendedTickValuesForADateTimeRange(maxTicks, scale.domain());\n }\n return getRecommendedTickValuesForAQuantitativeRange(maxTicks, scale, minTickInterval);\n }\n AxisHelper.getRecommendedTickValues = getRecommendedTickValues;\n function getRecommendedTickValuesForAnOrdinalRange(maxTicks, labels) {\n var tickLabels = [];\n // return no ticks in this case\n if (maxTicks <= 0)\n return tickLabels;\n var len = labels.length;\n if (maxTicks > len)\n return labels;\n for (var i = 0, step = Math.ceil(len / maxTicks); i < len; i += step) {\n tickLabels.push(labels[i]);\n }\n return tickLabels;\n }\n AxisHelper.getRecommendedTickValuesForAnOrdinalRange = getRecommendedTickValuesForAnOrdinalRange;\n function getRecommendedTickValuesForAQuantitativeRange(maxTicks, scale, minInterval) {\n var tickLabels = [];\n //if maxticks is zero return none\n if (maxTicks === 0)\n return tickLabels;\n var quantitiveScale = scale;\n if (quantitiveScale.ticks) {\n tickLabels = quantitiveScale.ticks(maxTicks);\n if (tickLabels.length > maxTicks && maxTicks > 1)\n tickLabels = quantitiveScale.ticks(maxTicks - 1);\n if (tickLabels.length < MinTickCount) {\n tickLabels = quantitiveScale.ticks(maxTicks + 1);\n }\n tickLabels = createTrueZeroTickLabel(tickLabels);\n if (minInterval && tickLabels.length > 1) {\n var tickInterval = tickLabels[1] - tickLabels[0];\n while (tickInterval > 0 && tickInterval < minInterval) {\n for (var i = 1; i < tickLabels.length; i++) {\n tickLabels.splice(i, 1);\n }\n tickInterval = tickInterval * 2;\n }\n // keep at least two labels - the loop above may trim all but one if we have odd # of tick labels and dynamic range < minInterval\n if (tickLabels.length === 1) {\n tickLabels.push(tickLabels[0] + minInterval);\n }\n }\n return tickLabels;\n }\n debug.assertFail('must pass a quantitative scale to this method');\n return tickLabels;\n }\n AxisHelper.getRecommendedTickValuesForAQuantitativeRange = getRecommendedTickValuesForAQuantitativeRange;\n /**\n * Round out very small zero tick values (e.g. -1e-33 becomes 0).\n *\n * @param ticks Array of numbers (from d3.scale.ticks([maxTicks])).\n * @param epsilon Max ratio of calculated tick interval which we will recognize as zero.\n *\n * e.g.\n * ticks = [-2, -1, 1e-10, 3, 4]; epsilon = 1e-5;\n * closeZero = 1e-5 * | 2 - 1 | = 1e-5\n * // Tick values <= 1e-5 replaced with 0\n * return [-2, -1, 0, 3, 4];\n */\n function createTrueZeroTickLabel(ticks, epsilon) {\n if (epsilon === void 0) { epsilon = 1e-5; }\n if (!ticks || ticks.length < 2)\n return ticks;\n var closeZero = epsilon * Math.abs(ticks[1] - ticks[0]);\n return ticks.map(function (tick) { return Math.abs(tick) <= closeZero ? 0 : tick; });\n }\n function getRecommendedTickValuesForADateTimeRange(maxTicks, dataDomain) {\n var tickLabels = [];\n if (dataDomain[0] === 0 && dataDomain[1] === 0)\n return [];\n var dateTimeTickLabels = powerbi.DateTimeSequence.calculate(new Date(dataDomain[0]), new Date(dataDomain[1]), maxTicks).sequence;\n tickLabels = dateTimeTickLabels.map(function (d) { return d.getTime(); });\n tickLabels = ensureValuesInRange(tickLabels, dataDomain[0], dataDomain[1]);\n return tickLabels;\n }\n function normalizeLinearDomain(domain) {\n if (isNaN(domain.min) || isNaN(domain.max)) {\n domain.min = visuals.emptyDomain[0];\n domain.max = visuals.emptyDomain[1];\n }\n else if (domain.min === domain.max) {\n // d3 linear scale will give zero tickValues if max === min, so extend a little\n domain.min = domain.min < 0 ? domain.min * 1.2 : domain.min * 0.8;\n domain.max = domain.max < 0 ? domain.max * 0.8 : domain.max * 1.2;\n }\n else {\n // Check that min is very small and is a negligable portion of the whole domain.\n // (fix floating pt precision bugs)\n // sometimes highlight value math causes small negative numbers which makes the axis add\n // a large tick interval instead of just rendering at zero.\n if (Math.abs(domain.min) < 0.0001 && domain.min / (domain.max - domain.min) < 0.0001) {\n domain.min = 0;\n }\n }\n return domain;\n }\n function getMargin(availableWidth, availableHeight, xMargin, yMargin) {\n if (getRecommendedNumberOfTicksForXAxis(availableWidth - xMargin) === 0\n || getRecommendedNumberOfTicksForYAxis(availableHeight - yMargin) === 0) {\n return {\n top: 0,\n right: xMargin,\n bottom: yMargin,\n left: 0\n };\n }\n return {\n top: 20,\n right: 30,\n bottom: 40,\n left: 30\n };\n }\n AxisHelper.getMargin = getMargin;\n // TODO: Put the parameters into one object\n function getTickLabelMargins(viewport, yMarginLimit, textWidthMeasurer, textHeightMeasurer, axes, bottomMarginLimit, properties, scrollbarVisible, showOnRight, renderXAxis, renderY1Axis, renderY2Axis) {\n debug.assertValue(axes, 'axes');\n var xAxisProperties = axes.x;\n var y1AxisProperties = axes.y1;\n var y2AxisProperties = axes.y2;\n debug.assertValue(viewport, 'viewport');\n debug.assertValue(textWidthMeasurer, 'textWidthMeasurer');\n debug.assertValue(textHeightMeasurer, 'textHeightMeasurer');\n debug.assertValue(xAxisProperties, 'xAxis');\n debug.assertValue(y1AxisProperties, 'yAxis');\n var xLabels = xAxisProperties.values;\n var y1Labels = y1AxisProperties.values;\n var leftOverflow = 0;\n var rightOverflow = 0;\n var maxWidthY1 = 0;\n var maxWidthY2 = 0;\n var xMax = 0; // bottom margin\n var ordinalLabelOffset = xAxisProperties.categoryThickness ? xAxisProperties.categoryThickness / 2 : 0;\n var scaleIsOrdinal = isOrdinalScale(xAxisProperties.scale);\n var xLabelOuterPadding = 0;\n if (xAxisProperties.outerPadding !== undefined) {\n xLabelOuterPadding = xAxisProperties.outerPadding;\n }\n else if (xAxisProperties.xLabelMaxWidth !== undefined) {\n xLabelOuterPadding = Math.max(0, (viewport.width - xAxisProperties.xLabelMaxWidth * xLabels.length) / 2);\n }\n if (getRecommendedNumberOfTicksForXAxis(viewport.width) !== 0\n || getRecommendedNumberOfTicksForYAxis(viewport.height) !== 0) {\n var rotation = void 0;\n if (scrollbarVisible)\n rotation = LabelLayoutStrategy.DefaultRotationWithScrollbar;\n else\n rotation = LabelLayoutStrategy.DefaultRotation;\n if (renderY1Axis) {\n for (var i = 0, len = y1Labels.length; i < len; i++) {\n properties.text = y1Labels[i];\n maxWidthY1 = Math.max(maxWidthY1, textWidthMeasurer(properties));\n }\n }\n if (y2AxisProperties && renderY2Axis) {\n var y2Labels = y2AxisProperties.values;\n for (var i = 0, len = y2Labels.length; i < len; i++) {\n properties.text = y2Labels[i];\n maxWidthY2 = Math.max(maxWidthY2, textWidthMeasurer(properties));\n }\n }\n var textHeight = textHeightMeasurer(properties);\n var maxNumLines = Math.floor(bottomMarginLimit / textHeight);\n var xScale = xAxisProperties.scale;\n var xDomain = xScale.domain();\n if (renderXAxis && xLabels.length > 0) {\n for (var i = 0, len = xLabels.length; i < len; i++) {\n // find the max height of the x-labels, perhaps rotated or wrapped\n var height = void 0;\n properties.text = xLabels[i];\n var width = textWidthMeasurer(properties);\n if (xAxisProperties.willLabelsWordBreak) {\n // Split label and count rows\n var wordBreaks = jsCommon.WordBreaker.splitByWidth(properties.text, properties, textWidthMeasurer, xAxisProperties.xLabelMaxWidth, maxNumLines);\n height = wordBreaks.length * textHeight;\n // word wrapping will truncate at xLabelMaxWidth\n width = xAxisProperties.xLabelMaxWidth;\n }\n else if (!xAxisProperties.willLabelsFit && scaleIsOrdinal) {\n height = width * rotation.sine;\n width = width * rotation.cosine;\n }\n else {\n height = TextHeightConstant;\n }\n // calculate left and right overflow due to wide X labels\n // (Note: no right overflow when rotated)\n if (i === 0) {\n if (scaleIsOrdinal) {\n if (!xAxisProperties.willLabelsFit /*rotated text*/)\n leftOverflow = width - ordinalLabelOffset - xLabelOuterPadding;\n else\n leftOverflow = (width / 2) - ordinalLabelOffset - xLabelOuterPadding;\n leftOverflow = Math.max(leftOverflow, 0);\n }\n else if (xDomain.length > 1) {\n // Scalar - do some math\n var xPos = xScale(xDomain[0]);\n // xPos already incorporates xLabelOuterPadding, don't subtract it twice\n leftOverflow = (width / 2) - xPos;\n leftOverflow = Math.max(leftOverflow, 0);\n }\n }\n else if (i === len - 1) {\n if (scaleIsOrdinal) {\n // if we are rotating text (!willLabelsFit) there won't be any right overflow\n if (xAxisProperties.willLabelsFit || xAxisProperties.willLabelsWordBreak) {\n // assume this label is placed near the edge\n rightOverflow = (width / 2) - ordinalLabelOffset - xLabelOuterPadding;\n rightOverflow = Math.max(rightOverflow, 0);\n }\n }\n else if (xDomain.length > 1) {\n // Scalar - do some math\n var xPos = xScale(xDomain[1]);\n // xPos already incorporates xLabelOuterPadding, don't subtract it twice\n rightOverflow = (width / 2) - (viewport.width - xPos);\n rightOverflow = Math.max(rightOverflow, 0);\n }\n }\n xMax = Math.max(xMax, height);\n }\n // trim any actual overflow to the limit\n leftOverflow = Math.min(leftOverflow, XLabelMaxAllowedOverflow);\n rightOverflow = Math.min(rightOverflow, XLabelMaxAllowedOverflow);\n }\n }\n var rightMargin = 0, leftMargin = 0, bottomMargin = Math.min(Math.ceil(xMax), bottomMarginLimit);\n if (showOnRight) {\n leftMargin = Math.min(Math.max(leftOverflow, maxWidthY2), yMarginLimit);\n rightMargin = Math.min(Math.max(rightOverflow, maxWidthY1), yMarginLimit);\n }\n else {\n leftMargin = Math.min(Math.max(leftOverflow, maxWidthY1), yMarginLimit);\n rightMargin = Math.min(Math.max(rightOverflow, maxWidthY2), yMarginLimit);\n }\n return {\n xMax: Math.ceil(bottomMargin),\n yLeft: Math.ceil(leftMargin),\n yRight: Math.ceil(rightMargin),\n };\n }\n AxisHelper.getTickLabelMargins = getTickLabelMargins;\n function columnDataTypeHasValue(dataType) {\n return dataType && (dataType.bool || dataType.numeric || dataType.text || dataType.dateTime);\n }\n AxisHelper.columnDataTypeHasValue = columnDataTypeHasValue;\n function createOrdinalType() {\n return powerbi.ValueType.fromDescriptor({ text: true });\n }\n AxisHelper.createOrdinalType = createOrdinalType;\n function isOrdinal(type) {\n return !!(type && (type.text || type.bool));\n }\n AxisHelper.isOrdinal = isOrdinal;\n function isOrdinalScale(scale) {\n return typeof scale.invert === 'undefined';\n }\n AxisHelper.isOrdinalScale = isOrdinalScale;\n function isDateTime(type) {\n return !!(type && type.dateTime);\n }\n AxisHelper.isDateTime = isDateTime;\n function invertScale(scale, x) {\n if (isOrdinalScale(scale)) {\n return invertOrdinalScale(scale, x);\n }\n return scale.invert(x);\n }\n AxisHelper.invertScale = invertScale;\n function extent(scale) {\n if (isOrdinalScale(scale)) {\n return scale.rangeExtent();\n }\n return scale.range();\n }\n AxisHelper.extent = extent;\n function invertOrdinalScale(scale, x) {\n var leftEdges = scale.range();\n if (leftEdges.length < 2)\n return 0;\n var width = scale.rangeBand();\n var halfInnerPadding = (leftEdges[1] - leftEdges[0] - width) / 2;\n var j;\n for (j = 0; x > (leftEdges[j] + width + halfInnerPadding) && j < (leftEdges.length - 1); j++)\n ;\n return scale.domain()[j];\n }\n AxisHelper.invertOrdinalScale = invertOrdinalScale;\n function findClosestXAxisIndex(categoryValue, categoryAxisValues) {\n var closestValueIndex = -1;\n var minDistance = Number.MAX_VALUE;\n for (var i in categoryAxisValues) {\n var distance = Math.abs(categoryValue - categoryAxisValues[i].categoryValue);\n if (distance < minDistance) {\n minDistance = distance;\n closestValueIndex = parseInt(i, 10);\n }\n }\n return closestValueIndex;\n }\n AxisHelper.findClosestXAxisIndex = findClosestXAxisIndex;\n function lookupOrdinalIndex(scale, pixelValue) {\n var closestValueIndex = -1;\n var minDistance = Number.MAX_VALUE;\n var domain = scale.domain();\n if (domain.length < 2)\n return 0;\n var halfWidth = (scale(1) - scale(0)) / 2;\n for (var idx in domain) {\n var leftEdgeInPixels = scale(idx);\n var midPoint = leftEdgeInPixels + halfWidth;\n var distance = Math.abs(pixelValue - midPoint);\n if (distance < minDistance) {\n minDistance = distance;\n closestValueIndex = parseInt(idx, 10);\n }\n }\n return closestValueIndex;\n }\n AxisHelper.lookupOrdinalIndex = lookupOrdinalIndex;\n /** scale(value1) - scale(value2) with zero checking and min(+/-1, result) */\n function diffScaled(scale, value1, value2) {\n debug.assertValue(scale, 'scale');\n var value = scale(value1) - scale(value2);\n if (value === 0)\n return 0;\n if (value < 0)\n return Math.min(value, -1);\n return Math.max(value, 1);\n }\n AxisHelper.diffScaled = diffScaled;\n function createDomain(data, axisType, isScalar, forcedScalarDomain, ensureDomain) {\n if (isScalar && !isOrdinal(axisType)) {\n var userMin = void 0, userMax = void 0;\n if (forcedScalarDomain && forcedScalarDomain.length === 2) {\n userMin = forcedScalarDomain[0];\n userMax = forcedScalarDomain[1];\n }\n return createScalarDomain(data, userMin, userMax, axisType, ensureDomain);\n }\n return createOrdinalDomain(data);\n }\n AxisHelper.createDomain = createDomain;\n function ensureValuesInRange(values, min, max) {\n debug.assert(min <= max, \"min must be less or equal to max\");\n var filteredValues = values.filter(function (v) { return v >= min && v <= max; });\n if (filteredValues.length < 2)\n filteredValues = [min, max];\n return filteredValues;\n }\n AxisHelper.ensureValuesInRange = ensureValuesInRange;\n /**\n * Gets the ValueType of a category column, defaults to Text if the type is not present.\n */\n function getCategoryValueType(metadataColumn, isScalar) {\n if (metadataColumn && columnDataTypeHasValue(metadataColumn.type))\n return metadataColumn.type;\n if (isScalar) {\n return powerbi.ValueType.fromDescriptor({ numeric: true });\n }\n return powerbi.ValueType.fromDescriptor({ text: true });\n }\n AxisHelper.getCategoryValueType = getCategoryValueType;\n /**\n * Create a D3 axis including scale. Can be vertical or horizontal, and either datetime, numeric, or text.\n * @param options The properties used to create the axis.\n */\n function createAxis(options) {\n var pixelSpan = options.pixelSpan, dataDomain = options.dataDomain, metaDataColumn = options.metaDataColumn, formatString = options.formatString, outerPadding = options.outerPadding || 0, isCategoryAxis = !!options.isCategoryAxis, isScalar = !!options.isScalar, isVertical = !!options.isVertical, useTickIntervalForDisplayUnits = !!options.useTickIntervalForDisplayUnits, // DEPRECATE: same meaning as isScalar?\n getValueFn = options.getValueFn, categoryThickness = options.categoryThickness, axisDisplayUnits = options.axisDisplayUnits, axisPrecision = options.axisPrecision, is100Pct = !!options.is100Pct;\n var dataType = AxisHelper.getCategoryValueType(metaDataColumn, isScalar);\n // Create the Scale\n var scaleResult = AxisHelper.createScale(options);\n var scale = scaleResult.scale;\n var bestTickCount = scaleResult.bestTickCount;\n var scaleDomain = scale.domain();\n var isLogScaleAllowed = AxisHelper.isLogScalePossible(dataDomain, dataType);\n // fix categoryThickness if scalar and the domain was adjusted when making the scale \"nice\"\n if (categoryThickness && isScalar && dataDomain && dataDomain.length === 2) {\n var oldSpan = dataDomain[1] - dataDomain[0];\n var newSpan = scaleDomain[1] - scaleDomain[0];\n if (oldSpan > 0 && newSpan > 0) {\n categoryThickness = categoryThickness * oldSpan / newSpan;\n }\n }\n // Prepare Tick Values for formatting\n var tickValues;\n if (isScalar && bestTickCount === 1) {\n tickValues = [dataDomain[0]];\n }\n else {\n var minTickInterval = isScalar ? getMinTickValueInterval(formatString, dataType, is100Pct) : undefined;\n tickValues = getRecommendedTickValues(bestTickCount, scale, dataType, isScalar, minTickInterval);\n }\n if (options.scaleType && options.scaleType === visuals.axisScale.log && isLogScaleAllowed) {\n tickValues = tickValues.filter(function (d) { return AxisHelper.powerOfTen(d); });\n }\n var formatter = createFormatter(scaleDomain, dataDomain, dataType, isScalar, formatString, bestTickCount, tickValues, getValueFn, useTickIntervalForDisplayUnits, axisDisplayUnits, axisPrecision);\n // sets default orientation only, cartesianChart will fix y2 for comboChart\n // tickSize(pixelSpan) is used to create gridLines\n var axis = d3.svg.axis()\n .scale(scale)\n .tickSize(6, 0)\n .orient(isVertical ? 'left' : 'bottom')\n .ticks(bestTickCount)\n .tickValues(tickValues);\n var formattedTickValues = [];\n if (metaDataColumn)\n formattedTickValues = formatAxisTickValues(axis, tickValues, formatter, dataType, getValueFn);\n var xLabelMaxWidth;\n // Use category layout of labels if specified, otherwise use scalar layout of labels\n if (!isScalar && categoryThickness) {\n xLabelMaxWidth = Math.max(1, categoryThickness - visuals.CartesianChart.TickLabelPadding * 2);\n }\n else {\n // When there are 0 or 1 ticks, then xLabelMaxWidth = pixelSpan \n xLabelMaxWidth = tickValues.length > 1 ? getScalarLabelMaxWidth(scale, tickValues) : pixelSpan;\n xLabelMaxWidth = xLabelMaxWidth - ScalarTickLabelPadding * 2;\n }\n return {\n scale: scale,\n axis: axis,\n formatter: formatter,\n values: formattedTickValues,\n axisType: dataType,\n axisLabel: null,\n isCategoryAxis: isCategoryAxis,\n xLabelMaxWidth: xLabelMaxWidth,\n categoryThickness: categoryThickness,\n outerPadding: outerPadding,\n usingDefaultDomain: scaleResult.usingDefaultDomain,\n isLogScaleAllowed: isLogScaleAllowed,\n dataDomain: dataDomain,\n };\n }\n AxisHelper.createAxis = createAxis;\n function getScalarLabelMaxWidth(scale, tickValues) {\n debug.assertValue(scale, \"scale\");\n debug.assertNonEmpty(tickValues, \"tickValues\");\n // find the distance between two ticks. scalar ticks can be anywhere, such as:\n // |---50----------100--------|\n if (scale && !_.isEmpty(tickValues)) {\n return Math.abs(scale(tickValues[1]) - scale(tickValues[0]));\n }\n return 1;\n }\n function createScale(options) {\n var pixelSpan = options.pixelSpan, dataDomain = options.dataDomain, metaDataColumn = options.metaDataColumn, outerPadding = options.outerPadding || 0, isScalar = !!options.isScalar, isVertical = !!options.isVertical, forcedTickCount = options.forcedTickCount, categoryThickness = options.categoryThickness, shouldClamp = !!options.shouldClamp;\n var dataType = AxisHelper.getCategoryValueType(metaDataColumn, isScalar);\n var maxTicks = isVertical ? getRecommendedNumberOfTicksForYAxis(pixelSpan) : getRecommendedNumberOfTicksForXAxis(pixelSpan);\n var scalarDomain = dataDomain ? dataDomain.slice() : null;\n var bestTickCount = maxTicks;\n var scale;\n var usingDefaultDomain = false;\n if (dataDomain == null || (dataDomain.length === 2 && dataDomain[0] == null && dataDomain[1] == null) || (dataDomain.length !== 2 && isScalar)) {\n usingDefaultDomain = true;\n if (dataType.dateTime || !isOrdinal(dataType))\n dataDomain = visuals.emptyDomain;\n else\n dataDomain = [];\n if (isOrdinal(dataType)) {\n scale = createOrdinalScale(pixelSpan, dataDomain, categoryThickness ? outerPadding / categoryThickness : 0);\n }\n else {\n scale = createNumericalScale(options.scaleType, pixelSpan, dataDomain, dataType, outerPadding, bestTickCount);\n }\n }\n else {\n if (isScalar && dataDomain.length > 0) {\n bestTickCount = forcedTickCount !== undefined\n ? (maxTicks !== 0 ? forcedTickCount : 0)\n : AxisHelper.getBestNumberOfTicks(dataDomain[0], dataDomain[dataDomain.length - 1], [metaDataColumn], maxTicks, dataType.dateTime);\n var normalizedRange = normalizeLinearDomain({ min: dataDomain[0], max: dataDomain[dataDomain.length - 1] });\n scalarDomain = [normalizedRange.min, normalizedRange.max];\n }\n if (isScalar && dataType.numeric && !dataType.dateTime) {\n scale = createNumericalScale(options.scaleType, pixelSpan, scalarDomain, dataType, outerPadding, bestTickCount, shouldClamp);\n }\n else if (isScalar && dataType.dateTime) {\n // Use of a linear scale, instead of a D3.time.scale, is intentional since we want\n // to control the formatting of the time values, since d3's implementation isn't\n // in accordance to our design.\n // scalarDomain: should already be in long-int time (via category.values[0].getTime())\n scale = createLinearScale(pixelSpan, scalarDomain, outerPadding, null, shouldClamp); // DO NOT PASS TICKCOUNT\n }\n else if (dataType.text || dataType.dateTime || dataType.numeric || dataType.bool) {\n scale = createOrdinalScale(pixelSpan, scalarDomain, categoryThickness ? outerPadding / categoryThickness : 0);\n bestTickCount = maxTicks === 0 ? 0\n : Math.min(scalarDomain.length, (pixelSpan - outerPadding * 2) / visuals.CartesianChart.MinOrdinalRectThickness);\n }\n else {\n debug.assertFail('unsupported dataType, something other than text or numeric');\n }\n }\n // vertical ordinal axis (e.g. categorical bar chart) does not need to reverse\n if (isVertical && isScalar) {\n scale.range(scale.range().reverse());\n }\n visuals.ColumnUtil.normalizeInfinityInScale(scale);\n return {\n scale: scale,\n bestTickCount: bestTickCount,\n usingDefaultDomain: usingDefaultDomain,\n };\n }\n AxisHelper.createScale = createScale;\n function createFormatter(scaleDomain, dataDomain, dataType, isScalar, formatString, bestTickCount, tickValues, getValueFn, useTickIntervalForDisplayUnits, axisDisplayUnits, axisPrecision) {\n if (useTickIntervalForDisplayUnits === void 0) { useTickIntervalForDisplayUnits = false; }\n var formatter;\n if (dataType.dateTime) {\n if (isScalar) {\n var value = new Date(scaleDomain[0]);\n var value2 = new Date(scaleDomain[1]);\n // datetime with only one value needs to pass the same value\n // (from the original dataDomain value, not the adjusted scaleDomain)\n // so formatting works correctly.\n if (bestTickCount === 1)\n value = value2 = new Date(dataDomain[0]);\n // this will ignore the formatString and create one based on the smallest non-zero portion of the values supplied.\n formatter = visuals.valueFormatter.create({\n format: formatString,\n value: value,\n value2: value2,\n tickCount: bestTickCount,\n });\n }\n else {\n // Use the model formatString for ordinal datetime\n formatter = visuals.valueFormatter.createDefaultFormatter(formatString, true);\n }\n }\n else {\n if (getValueFn == null && !isScalar) {\n debug.assertFail('getValueFn must be supplied for ordinal tickValues');\n }\n if (useTickIntervalForDisplayUnits && isScalar && tickValues.length > 1) {\n var value1 = axisDisplayUnits ? axisDisplayUnits : tickValues[1] - tickValues[0];\n var options = {\n format: formatString,\n value: value1,\n value2: 0,\n allowFormatBeautification: true,\n };\n if (axisPrecision)\n options.precision = axisPrecision;\n else\n options.detectAxisPrecision = true;\n formatter = visuals.valueFormatter.create(options);\n }\n else {\n // do not use display units, just the basic value formatter\n // datetime is handled above, so we are ordinal and either boolean, numeric, or text.\n formatter = visuals.valueFormatter.createDefaultFormatter(formatString, true);\n }\n }\n return formatter;\n }\n AxisHelper.createFormatter = createFormatter;\n /**\n * Format the linear tick labels or the category labels.\n */\n function formatAxisTickValues(axis, tickValues, formatter, dataType, getValueFn) {\n var formattedTickValues = [];\n if (!getValueFn)\n getValueFn = function (data) { return data; };\n if (formatter) {\n axis.tickFormat(function (d) { return formatter.format(getValueFn(d, dataType)); });\n formattedTickValues = tickValues.map(function (d) { return formatter.format(getValueFn(d, dataType)); });\n }\n else {\n formattedTickValues = tickValues.map(function (d) { return getValueFn(d, dataType); });\n }\n return formattedTickValues;\n }\n function getMinTickValueInterval(formatString, columnType, is100Pct) {\n var isCustomFormat = formatString && !powerbi.NumberFormat.isStandardFormat(formatString);\n if (isCustomFormat) {\n var precision = powerbi.NumberFormat.getCustomFormatMetadata(formatString, true /*calculatePrecision*/).precision;\n if (formatString.indexOf('%') > -1)\n precision += 2; //percent values are multiplied by 100 during formatting\n return Math.pow(10, -precision);\n }\n else if (is100Pct)\n return 0.01;\n else if (columnType.integer)\n return 1;\n return 0;\n }\n AxisHelper.getMinTickValueInterval = getMinTickValueInterval;\n function createScalarDomain(data, userMin, userMax, axisType, ensureDomain) {\n debug.assertValue(data, 'data');\n if (data.length === 0) {\n return null;\n }\n var defaultMinX = d3.min(data, function (kv) { return d3.min(kv.data, function (d) { return d.categoryValue; }); });\n var defaultMaxX = d3.max(data, function (kv) { return d3.max(kv.data, function (d) { return d.categoryValue; }); });\n return combineDomain([userMin, userMax], [defaultMinX, defaultMaxX], ensureDomain);\n }\n /**\n * Creates a [min,max] from your Cartiesian data values.\n *\n * @param data The series array of CartesianDataPoints.\n * @param includeZero Columns and bars includeZero, line and scatter do not.\n */\n function createValueDomain(data, includeZero) {\n debug.assertValue(data, 'data');\n if (data.length === 0)\n return null;\n var minY = d3.min(data, function (kv) { return d3.min(kv.data, function (d) { return d.value; }); });\n var maxY = d3.max(data, function (kv) { return d3.max(kv.data, function (d) { return d.value; }); });\n if (includeZero)\n return [Math.min(minY, 0), Math.max(maxY, 0)];\n return [minY, maxY];\n }\n AxisHelper.createValueDomain = createValueDomain;\n function createOrdinalDomain(data) {\n if (_.isEmpty(data))\n return [];\n // each series shares the same categories for oridinal axes (even if a series has some nulls)\n var domain = [];\n var firstSeries = data[0];\n for (var _i = 0, _a = firstSeries.data; _i < _a.length; _i++) {\n var dp = _a[_i];\n if (!dp.highlight)\n domain.push(dp.categoryIndex);\n }\n return domain;\n }\n var LabelLayoutStrategy;\n (function (LabelLayoutStrategy) {\n function willLabelsFit(axisProperties, availableWidth, textMeasurer, properties) {\n var labels = axisProperties.values;\n if (labels.length === 0)\n return false;\n var labelMaxWidth = axisProperties.xLabelMaxWidth !== undefined\n ? axisProperties.xLabelMaxWidth\n : availableWidth / labels.length;\n return !labels.some(function (d) {\n properties.text = d;\n return textMeasurer(properties) > labelMaxWidth;\n });\n }\n LabelLayoutStrategy.willLabelsFit = willLabelsFit;\n function willLabelsWordBreak(axisProperties, margin, availableWidth, textWidthMeasurer, textHeightMeasurer, textTruncator, properties) {\n var labels = axisProperties.values;\n var labelMaxWidth = axisProperties.xLabelMaxWidth !== undefined\n ? axisProperties.xLabelMaxWidth\n : availableWidth / labels.length;\n var maxRotatedLength = margin.bottom / LabelLayoutStrategy.DefaultRotation.sine;\n var height = textHeightMeasurer(properties);\n var maxNumLines = Math.max(1, Math.floor(margin.bottom / height)); // TODO: not taking axis label into account\n if (labels.length === 0)\n return false;\n // If no break character and exceeds max width, word breaking will not work, return false\n var mustRotate = labels.some(function (label) {\n // Detect must rotate and return immediately\n properties.text = label;\n return !jsCommon.WordBreaker.hasBreakers(label) && textWidthMeasurer(properties) > labelMaxWidth;\n });\n if (mustRotate)\n return false;\n var moreWordBreakChars = labels.filter(function (label, index) {\n // ...otherwise compare rotation versus word breaking\n var allowedLengthProjectedOnXAxis = \n // Left margin is the width of Y axis.\n margin.left\n + axisProperties.outerPadding\n + axisProperties.categoryThickness * (index + 0.5)\n - LeftPadding;\n var allowedLength = allowedLengthProjectedOnXAxis / LabelLayoutStrategy.DefaultRotation.cosine;\n var rotatedLength = Math.min(allowedLength, maxRotatedLength);\n // Which shows more characters? Rotated or maxNumLines truncated to labelMaxWidth?\n var wordBreakChars = jsCommon.WordBreaker.splitByWidth(label, properties, textWidthMeasurer, labelMaxWidth, maxNumLines, textTruncator).join(' ');\n properties.text = label;\n var rotateChars = textTruncator(properties, rotatedLength);\n // prefer word break (>=) as it takes up less plot area\n return visuals.TextUtil.removeEllipses(wordBreakChars).length >= visuals.TextUtil.removeEllipses(rotateChars).length;\n });\n // prefer word break (>=) as it takes up less plot area\n return moreWordBreakChars.length >= Math.floor(labels.length / 2);\n }\n LabelLayoutStrategy.willLabelsWordBreak = willLabelsWordBreak;\n LabelLayoutStrategy.DefaultRotation = {\n sine: Math.sin(Math.PI * (35 / 180)),\n cosine: Math.cos(Math.PI * (35 / 180)),\n tangent: Math.tan(Math.PI * (35 / 180)),\n transform: 'rotate(-35)',\n dy: '-0.5em',\n };\n LabelLayoutStrategy.DefaultRotationWithScrollbar = {\n sine: Math.sin(Math.PI * (90 / 180)),\n cosine: Math.cos(Math.PI * (90 / 180)),\n tangent: Math.tan(Math.PI * (90 / 180)),\n transform: 'rotate(-90)',\n dy: '-0.8em',\n };\n function rotate(labelSelection, maxBottomMargin, textTruncator, textProperties, needRotate, needEllipsis, axisProperties, margin, scrollbarVisible) {\n var rotatedLength;\n var defaultRotation;\n if (scrollbarVisible)\n defaultRotation = LabelLayoutStrategy.DefaultRotationWithScrollbar;\n else\n defaultRotation = LabelLayoutStrategy.DefaultRotation;\n if (needRotate) {\n rotatedLength = maxBottomMargin / defaultRotation.sine;\n }\n labelSelection.each(function () {\n var axisLabel = d3.select(this);\n var labelText = axisLabel.text();\n textProperties.text = labelText;\n if (needRotate) {\n var textContentIndex = axisProperties.values.indexOf(this.textContent);\n var allowedLengthProjectedOnXAxis = \n // Left margin is the width of Y axis.\n margin.left\n + axisProperties.outerPadding\n + axisProperties.categoryThickness * (textContentIndex + 0.5);\n // Subtracting the left padding space from the allowed length.\n if (!scrollbarVisible)\n allowedLengthProjectedOnXAxis -= LeftPadding;\n // Truncate if scrollbar is visible or rotatedLength exceeds allowedLength\n var allowedLength = allowedLengthProjectedOnXAxis / defaultRotation.cosine;\n if (scrollbarVisible || needEllipsis || (allowedLength < rotatedLength)) {\n labelText = textTruncator(textProperties, Math.min(allowedLength, rotatedLength));\n axisLabel.text(labelText);\n }\n axisLabel.style('text-anchor', 'end')\n .attr({\n 'dx': '-0.5em',\n 'dy': defaultRotation.dy,\n 'transform': defaultRotation.transform\n });\n }\n else {\n var newLabelText = textTruncator(textProperties, axisProperties.xLabelMaxWidth);\n if (newLabelText !== labelText)\n axisLabel.text(newLabelText);\n axisLabel.style('text-anchor', 'middle')\n .attr({\n 'dx': '0em',\n 'dy': '1em',\n 'transform': 'rotate(0)'\n });\n }\n });\n }\n LabelLayoutStrategy.rotate = rotate;\n function wordBreak(text, axisProperties, maxHeight) {\n var allowedLength = axisProperties.xLabelMaxWidth;\n text.each(function () {\n var node = d3.select(this);\n // Reset style of text node\n node\n .style('text-anchor', 'middle')\n .attr({\n 'dx': '0em',\n 'dy': '1em',\n 'transform': 'rotate(0)'\n });\n powerbi.TextMeasurementService.wordBreak(this, allowedLength, maxHeight);\n });\n }\n LabelLayoutStrategy.wordBreak = wordBreak;\n function clip(text, availableWidth, svgEllipsis) {\n if (text.size() === 0)\n return;\n text.each(function () {\n var text = d3.select(this);\n svgEllipsis(text[0][0], availableWidth);\n });\n }\n LabelLayoutStrategy.clip = clip;\n })(LabelLayoutStrategy = AxisHelper.LabelLayoutStrategy || (AxisHelper.LabelLayoutStrategy = {}));\n function createOrdinalScale(pixelSpan, dataDomain, outerPaddingRatio) {\n if (outerPaddingRatio === void 0) { outerPaddingRatio = 0; }\n debug.assert(outerPaddingRatio >= 0 && outerPaddingRatio < 4, 'outerPaddingRatio should be a value between zero and four');\n var scale = d3.scale.ordinal()\n .rangeBands([0, pixelSpan], visuals.CartesianChart.InnerPaddingRatio, outerPaddingRatio)\n .domain(dataDomain);\n return scale;\n }\n AxisHelper.createOrdinalScale = createOrdinalScale;\n function isLogScalePossible(domain, axisType) {\n if (domain == null)\n return false;\n if (isDateTime(axisType))\n return false;\n return (domain[0] > 0 && domain[1] > 0) || (domain[0] < 0 && domain[1] < 0); //doman must exclude 0\n }\n AxisHelper.isLogScalePossible = isLogScalePossible;\n //this function can return different scales e.g. log, linear\n // NOTE: export only for testing, do not access directly\n function createNumericalScale(axisScaleType, pixelSpan, dataDomain, dataType, outerPadding, niceCount, shouldClamp) {\n if (outerPadding === void 0) { outerPadding = 0; }\n if (axisScaleType === visuals.axisScale.log && isLogScalePossible(dataDomain, dataType)) {\n return createLogScale(pixelSpan, dataDomain, outerPadding, niceCount);\n }\n else {\n return createLinearScale(pixelSpan, dataDomain, outerPadding, niceCount, shouldClamp);\n }\n }\n AxisHelper.createNumericalScale = createNumericalScale;\n function createLogScale(pixelSpan, dataDomain, outerPadding, niceCount) {\n if (outerPadding === void 0) { outerPadding = 0; }\n debug.assert(isLogScalePossible(dataDomain), \"dataDomain cannot include 0\");\n var scale = d3.scale.log()\n .range([outerPadding, pixelSpan - outerPadding])\n .domain([dataDomain[0], dataDomain[1]])\n .clamp(true);\n if (niceCount) {\n scale.nice(niceCount);\n }\n return scale;\n }\n // NOTE: export only for testing, do not access directly\n function createLinearScale(pixelSpan, dataDomain, outerPadding, niceCount, shouldClamp) {\n if (outerPadding === void 0) { outerPadding = 0; }\n var scale = d3.scale.linear()\n .range([outerPadding, pixelSpan - outerPadding])\n .domain([dataDomain[0], dataDomain[1]])\n .clamp(shouldClamp);\n // .nice(undefined) still modifies the scale boundaries, and for datetime this messes things up.\n // we use millisecond ticks since epoch for datetime, so we don't want any \"nice\" with numbers like 17398203392.\n if (niceCount) {\n scale.nice(niceCount);\n }\n return scale;\n }\n AxisHelper.createLinearScale = createLinearScale;\n function getRangeForColumn(sizeColumn) {\n var result = {};\n if (sizeColumn) {\n result.min = sizeColumn.min == null\n ? sizeColumn.minLocal == null ? d3.min(sizeColumn.values) : sizeColumn.minLocal\n : sizeColumn.min;\n result.max = sizeColumn.max == null\n ? sizeColumn.maxLocal == null ? d3.max(sizeColumn.values) : sizeColumn.maxLocal\n : sizeColumn.max;\n }\n return result;\n }\n AxisHelper.getRangeForColumn = getRangeForColumn;\n /**\n * Set customized domain, but don't change when nothing is set\n */\n function applyCustomizedDomain(customizedDomain, forcedDomain) {\n var domain = [undefined, undefined];\n if (forcedDomain && forcedDomain.length === 2) {\n domain = [forcedDomain[0], forcedDomain[1]];\n }\n if (customizedDomain && customizedDomain.length === 2) {\n if (customizedDomain[0] != null) {\n domain[0] = customizedDomain[0];\n }\n if (customizedDomain[1] != null) {\n domain[1] = customizedDomain[1];\n }\n }\n if (domain[0] == null && domain[1] == null) {\n return forcedDomain; //return untouched object\n }\n //do extra check to see if the user input was valid with the merged axis values.\n if (domain[0] != null && domain[1] != null) {\n if (domain[0] > domain[1]) {\n return forcedDomain;\n }\n }\n return domain;\n }\n AxisHelper.applyCustomizedDomain = applyCustomizedDomain;\n /**\n * Combine the forced domain with the actual domain if one of the values was set.\n * The forcedDomain is in 1st priority. Extends the domain if the any reference point requires it.\n */\n function combineDomain(forcedDomain, domain, ensureDomain) {\n var combinedDomain = domain ? [domain[0], domain[1]] : [];\n if (ensureDomain) {\n if (combinedDomain[0] == null || ensureDomain.min < combinedDomain[0])\n combinedDomain[0] = ensureDomain.min;\n if (combinedDomain[1] == null || ensureDomain.max > combinedDomain[1])\n combinedDomain[1] = ensureDomain.max;\n }\n var domainBeforeForced = [combinedDomain[0], combinedDomain[1]];\n if (forcedDomain && forcedDomain.length === 2) {\n if (forcedDomain[0] != null) {\n combinedDomain[0] = forcedDomain[0];\n }\n if (forcedDomain[1] != null) {\n combinedDomain[1] = forcedDomain[1];\n }\n if (combinedDomain[0] > combinedDomain[1]) {\n combinedDomain = domainBeforeForced; //this is invalid, so take the original domain considering the values and the reference line\n }\n }\n return combinedDomain;\n }\n AxisHelper.combineDomain = combineDomain;\n function createAxisLabel(properties, label, unitType, y2) {\n if (y2 === void 0) { y2 = false; }\n var propertyName = y2 ? 'secAxisStyle' : 'axisStyle';\n if (!properties || !properties[propertyName]) {\n return label;\n }\n var modifiedLabel;\n if (properties[propertyName] === visuals.axisStyle.showBoth) {\n modifiedLabel = label + ' (' + unitType + ')'; //todo: localize\n }\n else if (properties[propertyName] === visuals.axisStyle.showUnitOnly) {\n modifiedLabel = unitType;\n }\n else {\n modifiedLabel = label;\n }\n return modifiedLabel;\n }\n AxisHelper.createAxisLabel = createAxisLabel;\n function scaleShouldClamp(combinedDomain, domain) {\n if (!combinedDomain || !domain || combinedDomain.length < 2 || domain.length < 2)\n return false;\n //when the start or end is different, clamp it\n return combinedDomain[0] !== domain[0] || combinedDomain[1] !== domain[1];\n }\n AxisHelper.scaleShouldClamp = scaleShouldClamp;\n function normalizeNonFiniteNumber(value) {\n if (isNaN(value))\n return null;\n else if (value === Number.POSITIVE_INFINITY)\n return Number.MAX_VALUE;\n else if (value === Number.NEGATIVE_INFINITY)\n return -Number.MAX_VALUE;\n return value;\n }\n AxisHelper.normalizeNonFiniteNumber = normalizeNonFiniteNumber;\n /**\n * Indicates whether the number is power of 10.\n */\n function powerOfTen(d) {\n var value = Math.abs(d);\n // formula log2(Y)/log2(10) = log10(Y)\n // because double issues this won't return exact value\n // we need to ceil it to nearest number.\n var log10 = Math.log(value) / Math.LN10;\n log10 = Math.ceil(log10 - 1e-12);\n return value / Math.pow(10, log10) === 1;\n }\n AxisHelper.powerOfTen = powerOfTen;\n })(AxisHelper = visuals.AxisHelper || (visuals.AxisHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var ShapeFactory;\n (function (ShapeFactory) {\n var ShapeFactoryConsts;\n (function (ShapeFactoryConsts) {\n ShapeFactoryConsts.PaddingConstRatio = 0.01;\n ShapeFactoryConsts.TrianglePaddingConstRatio = 0.15;\n ShapeFactoryConsts.TriangleEndPaddingConstRatio = 0.85;\n ShapeFactoryConsts.ShapeConstRatio = 1.0 - (ShapeFactoryConsts.PaddingConstRatio * 2);\n ShapeFactoryConsts.SmallPaddingConstValue = 10;\n ShapeFactoryConsts.OvalRadiusConst = 2;\n ShapeFactoryConsts.OvalRadiusConstPadding = 0.2;\n ShapeFactoryConsts.ArrowLeftHeadPoint = { x: 0.05, y: 0.42 };\n ShapeFactoryConsts.ArrowMiddleHeadPoint = { x: 0.5, y: 0.016 };\n ShapeFactoryConsts.ArrowRightHeadPoint = { x: 0.95, y: 0.42 };\n ShapeFactoryConsts.ArrowRightMiddleHeadPoint = { x: 0.764, y: 0.42 };\n ShapeFactoryConsts.ArrowBottomRightPoint = { x: 0.764, y: 0.993 };\n ShapeFactoryConsts.ArrowBottomLeftPoint = { x: 0.246, y: 0.993 };\n ShapeFactoryConsts.ArrowLeftMiddleHeadPoint = { x: 0.246, y: 0.42 };\n })(ShapeFactoryConsts = ShapeFactory.ShapeFactoryConsts || (ShapeFactory.ShapeFactoryConsts = {}));\n /** this function creates a rectangle svg */\n function createRectangle(data, viewportHeight, viewportWidth, selectedElement, degrees) {\n var x = (viewportWidth * ShapeFactoryConsts.PaddingConstRatio) + (data.lineWeight / 2);\n var y = (viewportHeight * ShapeFactoryConsts.PaddingConstRatio) + (data.lineWeight / 2);\n var width = (viewportWidth * ShapeFactoryConsts.ShapeConstRatio) - (data.lineWeight);\n var height = (viewportHeight * ShapeFactoryConsts.ShapeConstRatio) - (data.lineWeight);\n var attrs = { x: x, y: y, width: width, height: height, rx: data.roundEdge, ry: data.roundEdge };\n var scale = getScale(width, height, degrees);\n createShape(data, viewportHeight, viewportWidth, selectedElement, degrees, scale, 'rect', attrs);\n }\n ShapeFactory.createRectangle = createRectangle;\n /** this function creates a oval svg */\n function createOval(data, viewportHeight, viewportWidth, selectedElement, degrees) {\n var widthForCircle = (viewportWidth / ShapeFactoryConsts.OvalRadiusConst).toString();\n var heightForCircle = (viewportHeight / ShapeFactoryConsts.OvalRadiusConst).toString();\n var radiusXForCircle = ((viewportWidth / (ShapeFactoryConsts.OvalRadiusConst + ShapeFactoryConsts.OvalRadiusConstPadding)) - data.lineWeight);\n var radiusYForCircle = ((viewportHeight / (ShapeFactoryConsts.OvalRadiusConst + ShapeFactoryConsts.OvalRadiusConstPadding)) - data.lineWeight);\n var attrs = { cx: widthForCircle, cy: heightForCircle, rx: radiusXForCircle, ry: radiusYForCircle };\n var scale = getScale(viewportWidth, viewportHeight, degrees);\n createShape(data, viewportHeight, viewportWidth, selectedElement, degrees, scale, 'ellipse', attrs);\n }\n ShapeFactory.createOval = createOval;\n /** this function creates a line svg */\n function createLine(data, viewportHeight, viewportWidth, selectedElement, degrees) {\n var x1, y1, x2, y2;\n var width = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue) - ShapeFactoryConsts.SmallPaddingConstValue;\n var height = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) - ShapeFactoryConsts.SmallPaddingConstValue;\n var ratio;\n if (degrees <= 45) {\n ratio = degrees / 90;\n x1 = viewportWidth / 2 + width * ratio;\n y1 = ShapeFactoryConsts.SmallPaddingConstValue;\n x2 = viewportWidth / 2 - width * ratio;\n y2 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue);\n }\n else if (degrees <= 135) {\n ratio = (degrees - 45) / 90;\n x1 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue);\n y1 = ShapeFactoryConsts.SmallPaddingConstValue + height * ratio;\n x2 = ShapeFactoryConsts.SmallPaddingConstValue;\n y2 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) - height * ratio;\n }\n else if (degrees <= 225) {\n ratio = (degrees - 135) / 90;\n x1 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue) - width * ratio;\n y1 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue);\n x2 = ShapeFactoryConsts.SmallPaddingConstValue + width * ratio;\n y2 = ShapeFactoryConsts.SmallPaddingConstValue;\n }\n else if (degrees <= 315) {\n ratio = (degrees - 225) / 90;\n x1 = ShapeFactoryConsts.SmallPaddingConstValue;\n y1 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) - height * ratio;\n x2 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue);\n y2 = ShapeFactoryConsts.SmallPaddingConstValue + height * ratio;\n }\n else if (degrees <= 360) {\n ratio = (degrees - 315) / 90;\n x1 = ShapeFactoryConsts.SmallPaddingConstValue + width * ratio;\n y1 = ShapeFactoryConsts.SmallPaddingConstValue;\n x2 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue) - width * ratio;\n y2 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue);\n }\n // create the inner path with the wanted shape\n selectedElement\n .append('svg')\n .attr({\n width: viewportWidth,\n height: viewportHeight\n })\n .append('line')\n .attr({\n x1: x1,\n y1: y1,\n x2: x2,\n y2: y2,\n })\n .style({\n 'vector-effect': 'non-scaling-stroke',\n 'stroke-width': data.lineWeight + 'px',\n 'stroke-opacity': (100 - data.lineTransparency) / 100,\n 'stroke': data.lineColor\n });\n }\n ShapeFactory.createLine = createLine;\n /** this function creates a arrow svg */\n function createUpArrow(data, viewportHeight, viewportWidth, selectedElement, degrees) {\n var lineWeight = data.lineWeight;\n var viewportHeightWeight = viewportHeight - lineWeight;\n var viewportWidthWeight = viewportWidth - lineWeight;\n var arrowPoints = [\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowLeftHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowLeftHeadPoint.y).toString() },\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowMiddleHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowMiddleHeadPoint.y).toString() },\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowRightHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowRightHeadPoint.y).toString() },\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowRightMiddleHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowRightMiddleHeadPoint.y).toString() },\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowBottomRightPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowBottomRightPoint.y).toString() },\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowBottomLeftPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowBottomLeftPoint.y).toString() },\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowLeftMiddleHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowLeftMiddleHeadPoint.y).toString() },\n ];\n // create the inner path with the wanted shape\n createPathFromArray(data, arrowPoints, selectedElement, viewportHeight, viewportWidth, degrees);\n }\n ShapeFactory.createUpArrow = createUpArrow;\n /** this function creates a triangle svg */\n function createTriangle(data, viewportHeight, viewportWidth, selectedElement, degrees) {\n var lineWeight = data.lineWeight;\n // remove the basic line weight\n if (lineWeight > 3) {\n lineWeight -= 3;\n }\n var firstPointX = ((viewportWidth + lineWeight) * ShapeFactoryConsts.TrianglePaddingConstRatio);\n var firstPointY = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue - lineWeight) < 0 ?\n (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) : (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue - lineWeight);\n var secondPointY = ((viewportHeight + lineWeight) * ShapeFactoryConsts.TrianglePaddingConstRatio);\n var thirdPointX = ((viewportWidth - lineWeight) * ShapeFactoryConsts.TriangleEndPaddingConstRatio) < 0 ?\n (viewportWidth * ShapeFactoryConsts.TriangleEndPaddingConstRatio) : ((viewportWidth - lineWeight) * ShapeFactoryConsts.TriangleEndPaddingConstRatio);\n var thirdPointY = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue - lineWeight) < 0 ?\n (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) : (viewportHeight - lineWeight - ShapeFactoryConsts.SmallPaddingConstValue);\n var secondPointX = ((firstPointX + thirdPointX) / 2);\n if (firstPointX < 10) {\n firstPointX = ShapeFactoryConsts.SmallPaddingConstValue;\n }\n if (secondPointY < 10) {\n secondPointY = ShapeFactoryConsts.SmallPaddingConstValue;\n }\n var trianglePoints = [\n { 'x': firstPointX, 'y': firstPointY },\n { 'x': secondPointX, 'y': secondPointY },\n { 'x': thirdPointX, 'y': thirdPointY },\n ];\n createPathFromArray(data, trianglePoints, selectedElement, viewportHeight, viewportWidth, degrees);\n }\n ShapeFactory.createTriangle = createTriangle;\n /** this funcion adds a path to an svg element from an array of points (x,y) */\n function createPathFromArray(data, points, selectedElement, viewportHeight, viewportWidth, degrees) {\n var lineFunction = d3.svg.line()\n .x(function (d) { return d.x; })\n .y(function (d) { return d.y; })\n .interpolate('linear');\n var attrs = { d: lineFunction(points) + ' Z' };\n var scale = getScale(viewportWidth, viewportHeight, degrees);\n createShape(data, viewportHeight, viewportWidth, selectedElement, degrees, scale, 'path', attrs);\n }\n function createShape(data, viewportHeight, viewportWidth, selectedElement, degrees, scale, shapeType, shapeAttrs) {\n selectedElement\n .append('div')\n .style({\n 'transform': 'rotate(' + degrees + 'deg) scale(' + scale + ')',\n 'transform-origin': 'center',\n // for testing with phantomjs we need the webkit prefix\n '-webkit-transform': 'rotate(' + degrees + 'deg) scale(' + scale + ')',\n '-webkit-transform-origin': 'center',\n 'width': viewportWidth + 'px',\n 'height': viewportHeight + 'px'\n })\n .append('svg')\n .attr({\n width: viewportWidth,\n height: viewportHeight\n })\n .append(shapeType)\n .attr(shapeAttrs)\n .style({\n 'vector-effect': 'non-scaling-stroke',\n 'stroke-width': data.lineWeight + 'px',\n 'stroke': data.lineColor,\n 'stroke-opacity': (100 - data.lineTransparency) / 100,\n 'fill': data.fillColor,\n 'fill-opacity': data.showFill === true ? ((100 - data.shapeTransparency) / 100) : 0\n });\n }\n // this function return the scale to add to the shape. \n // it calculate it by the ratio of the original shape's diagonal and the shape's diagonal after rotate (the maximum diagonal that still fit to the container).\n // it calculate the shape's diagonal by the rotate angle.\n function getScale(width, height, degrees) {\n var originalWidth = width;\n var originalHeight = height;\n var offsetAngle = Math.atan2(height, width);\n var originalFactor = Math.sqrt(Math.pow(height, 2) + Math.pow(width, 2));\n var radians = (degrees / 180) * Math.PI;\n if (width >= height) {\n if (degrees < 90) {\n radians += offsetAngle;\n }\n else if (degrees < 180) {\n radians -= offsetAngle;\n }\n else if (degrees < 270) {\n radians += offsetAngle;\n }\n else {\n radians -= offsetAngle;\n }\n return (originalHeight / Math.abs(Math.sin(radians))) / originalFactor;\n }\n else {\n if (degrees < 90) {\n radians -= offsetAngle;\n }\n else if (degrees < 180) {\n radians += offsetAngle;\n }\n else if (degrees < 270) {\n radians -= offsetAngle;\n }\n else {\n radians += offsetAngle;\n }\n return (originalWidth / Math.abs(Math.cos(radians))) / originalFactor;\n }\n }\n })(ShapeFactory = visuals.ShapeFactory || (visuals.ShapeFactory = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var CartesianHelper;\n (function (CartesianHelper) {\n function getCategoryAxisProperties(dataViewMetadata, axisTitleOnByDefault) {\n var toReturn = {};\n if (!dataViewMetadata)\n return toReturn;\n var objects = dataViewMetadata.objects;\n if (objects) {\n var categoryAxisObject = objects['categoryAxis'];\n if (categoryAxisObject) {\n toReturn = {\n show: categoryAxisObject['show'],\n axisType: categoryAxisObject['axisType'],\n axisScale: categoryAxisObject['axisScale'],\n start: categoryAxisObject['start'],\n end: categoryAxisObject['end'],\n showAxisTitle: categoryAxisObject['showAxisTitle'] == null ? axisTitleOnByDefault : categoryAxisObject['showAxisTitle'],\n axisStyle: categoryAxisObject['axisStyle'],\n labelColor: categoryAxisObject['labelColor'],\n labelDisplayUnits: categoryAxisObject['labelDisplayUnits'],\n labelPrecision: categoryAxisObject['labelPrecision'],\n duration: categoryAxisObject['duration'],\n };\n }\n }\n return toReturn;\n }\n CartesianHelper.getCategoryAxisProperties = getCategoryAxisProperties;\n function getValueAxisProperties(dataViewMetadata, axisTitleOnByDefault) {\n var toReturn = {};\n if (!dataViewMetadata)\n return toReturn;\n var objects = dataViewMetadata.objects;\n if (objects) {\n var valueAxisObject = objects['valueAxis'];\n if (valueAxisObject) {\n toReturn = {\n show: valueAxisObject['show'],\n position: valueAxisObject['position'],\n axisScale: valueAxisObject['axisScale'],\n start: valueAxisObject['start'],\n end: valueAxisObject['end'],\n showAxisTitle: valueAxisObject['showAxisTitle'] == null ? axisTitleOnByDefault : valueAxisObject['showAxisTitle'],\n axisStyle: valueAxisObject['axisStyle'],\n labelColor: valueAxisObject['labelColor'],\n labelDisplayUnits: valueAxisObject['labelDisplayUnits'],\n labelPrecision: valueAxisObject['labelPrecision'],\n secShow: valueAxisObject['secShow'],\n secPosition: valueAxisObject['secPosition'],\n secAxisScale: valueAxisObject['secAxisScale'],\n secStart: valueAxisObject['secStart'],\n secEnd: valueAxisObject['secEnd'],\n secShowAxisTitle: valueAxisObject['secShowAxisTitle'],\n secAxisStyle: valueAxisObject['secAxisStyle'],\n secLabelColor: valueAxisObject['secLabelColor'],\n secLabelDisplayUnits: valueAxisObject['secLabelDisplayUnits'],\n secLabelPrecision: valueAxisObject['secLabelPrecision'],\n };\n }\n }\n return toReturn;\n }\n CartesianHelper.getValueAxisProperties = getValueAxisProperties;\n function isScalar(isScalar, xAxisCardProperties) {\n if (isScalar) {\n //now check what the user wants\n isScalar = xAxisCardProperties && xAxisCardProperties['axisType'] ? xAxisCardProperties['axisType'] === visuals.axisType.scalar : true;\n }\n return isScalar;\n }\n CartesianHelper.isScalar = isScalar;\n function getPrecision(precision) {\n if (precision != null) {\n if (precision < 0) {\n return 0;\n }\n return precision;\n }\n return null;\n }\n CartesianHelper.getPrecision = getPrecision;\n function lookupXValue(data, index, type, isScalar) {\n debug.assertValue(data, 'data');\n debug.assertValue(type, 'type');\n var isDateTime = visuals.AxisHelper.isDateTime(type);\n if (isScalar) {\n if (isDateTime)\n return new Date(index);\n // index is the numeric value\n return index;\n }\n if (type.text) {\n debug.assert(index < data.categories.length, 'category index out of range');\n return data.categories[index];\n }\n if (data && data.series && data.series.length > 0) {\n var firstSeries = data.series[0];\n if (firstSeries) {\n var seriesValues = firstSeries.data;\n if (seriesValues) {\n if (data.hasHighlights)\n index = index * 2;\n var dataAtIndex = seriesValues[index];\n if (dataAtIndex) {\n if (isDateTime && dataAtIndex.categoryValue != null)\n return new Date(dataAtIndex.categoryValue);\n return dataAtIndex.categoryValue;\n }\n }\n }\n }\n return index;\n }\n CartesianHelper.lookupXValue = lookupXValue;\n function findMaxCategoryIndex(series) {\n if (_.isEmpty(series)) {\n return 0;\n }\n var maxCategoryIndex = 0;\n for (var _i = 0, series_1 = series; _i < series_1.length; _i++) {\n var singleSeries = series_1[_i];\n if (!_.isEmpty(singleSeries.data)) {\n var lastIndex = singleSeries.data[singleSeries.data.length - 1].categoryIndex;\n maxCategoryIndex = Math.max(lastIndex, maxCategoryIndex);\n }\n }\n return maxCategoryIndex;\n }\n CartesianHelper.findMaxCategoryIndex = findMaxCategoryIndex;\n })(CartesianHelper = visuals.CartesianHelper || (visuals.CartesianHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var SQExprShortSerializer = powerbi.data.SQExprShortSerializer;\n var ColorHelper = (function () {\n function ColorHelper(colors, fillProp, defaultDataPointColor) {\n this.colors = colors;\n this.fillProp = fillProp;\n this.defaultDataPointColor = defaultDataPointColor;\n this.defaultColorScale = colors.getNewColorScale();\n }\n /**\n * Gets the color for the given series value.\n * If no explicit color or default color has been set then the color is\n * allocated from the color scale for this series.\n */\n ColorHelper.prototype.getColorForSeriesValue = function (objects, fieldIds, value) {\n return (this.fillProp && powerbi.DataViewObjects.getFillColor(objects, this.fillProp))\n || this.defaultDataPointColor\n || this.getColorScaleForSeries(fieldIds).getColor(value).value;\n };\n /**\n * Gets the color scale for the given series.\n */\n ColorHelper.prototype.getColorScaleForSeries = function (fieldIds) {\n return this.colors.getColorScaleByKey(SQExprShortSerializer.serializeArray(fieldIds || []));\n };\n /**\n * Gets the color for the given measure.\n */\n ColorHelper.prototype.getColorForMeasure = function (objects, measureKey) {\n // Note, this allocates the color from the scale regardless of if we use it or not which helps keep colors stable.\n var scaleColor = this.defaultColorScale.getColor(measureKey).value;\n return (this.fillProp && powerbi.DataViewObjects.getFillColor(objects, this.fillProp))\n || this.defaultDataPointColor\n || scaleColor;\n };\n ColorHelper.normalizeSelector = function (selector, isSingleSeries) {\n debug.assertAnyValue(selector, 'selector');\n // For dynamic series charts, colors are set per category. So, exclude any measure (metadata repetition) from the selector.\n if (selector && (isSingleSeries || selector.data))\n return { data: selector.data };\n return selector;\n };\n return ColorHelper;\n }());\n visuals.ColorHelper = ColorHelper;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var rectName = 'rect';\n var ColumnUtil;\n (function (ColumnUtil) {\n ColumnUtil.DimmedOpacity = 0.4;\n ColumnUtil.DefaultOpacity = 1.0;\n function applyUserMinMax(isScalar, dataView, xAxisCardProperties) {\n if (isScalar) {\n var min = xAxisCardProperties['start'];\n var max = xAxisCardProperties['end'];\n return ColumnUtil.transformDomain(dataView, min, max);\n }\n return dataView;\n }\n ColumnUtil.applyUserMinMax = applyUserMinMax;\n function transformDomain(dataView, min, max) {\n if (!dataView.categories || !dataView.values || dataView.categories.length === 0 || dataView.values.length === 0)\n return dataView; // no need to do something when there are no categories \n if (typeof min !== \"number\" && typeof max !== \"number\")\n return dataView; //user did not set min max, nothing to do here \n var category = dataView.categories[0]; //at the moment we only support one category\n var categoryValues = category.values;\n var categoryObjects = category.objects;\n if (!categoryValues || !categoryObjects)\n return dataView;\n var newcategoryValues = [];\n var newValues = [];\n var newObjects = [];\n //get new min max\n if (typeof min !== \"number\") {\n min = categoryValues[0];\n }\n if (typeof max !== \"number\") {\n max = categoryValues[categoryValues.length - 1];\n }\n //don't allow this\n if (min > max)\n return dataView;\n //build measure array\n for (var j = 0, len = dataView.values.length; j < len; j++) {\n newValues.push([]);\n }\n for (var t = 0, len = categoryValues.length; t < len; t++) {\n if (categoryValues[t] >= min && categoryValues[t] <= max) {\n newcategoryValues.push(categoryValues[t]);\n if (categoryObjects) {\n newObjects.push(categoryObjects[t]);\n }\n //on each measure set the new range\n if (dataView.values) {\n for (var k = 0; k < dataView.values.length; k++) {\n newValues[k].push(dataView.values[k].values[t]);\n }\n }\n }\n }\n //don't write directly to dataview\n var resultDataView = powerbi.Prototype.inherit(dataView);\n var resultDataViewValues = resultDataView.values = powerbi.Prototype.inherit(resultDataView.values);\n var resultDataViewCategories = resultDataView.categories = powerbi.Prototype.inherit(dataView.categories);\n var resultDataViewCategories0 = resultDataView.categories[0] = powerbi.Prototype.inherit(resultDataViewCategories[0]);\n resultDataViewCategories0.values = newcategoryValues;\n //only if we had objects, then you set the new objects\n if (resultDataViewCategories0.objects) {\n resultDataViewCategories0.objects = newObjects;\n }\n //update measure array\n for (var t = 0, len = dataView.values.length; t < len; t++) {\n var measureArray = resultDataViewValues[t] = powerbi.Prototype.inherit(resultDataViewValues[t]);\n measureArray.values = newValues[t];\n }\n return resultDataView;\n }\n ColumnUtil.transformDomain = transformDomain;\n function getCategoryAxis(data, size, layout, isVertical, forcedXMin, forcedXMax, axisScaleType, axisDisplayUnits, axisPrecision, ensureXDomain) {\n var categoryThickness = layout.categoryThickness;\n var isScalar = layout.isScalar;\n var outerPaddingRatio = layout.outerPaddingRatio;\n var domain = visuals.AxisHelper.createDomain(data.series, data.categoryMetadata ? data.categoryMetadata.type : powerbi.ValueType.fromDescriptor({ text: true }), isScalar, [forcedXMin, forcedXMax], ensureXDomain);\n var axisProperties = visuals.AxisHelper.createAxis({\n pixelSpan: size,\n dataDomain: domain,\n metaDataColumn: data.categoryMetadata,\n formatString: visuals.valueFormatter.getFormatString(data.categoryMetadata, visuals.columnChartProps.general.formatString),\n outerPadding: categoryThickness * outerPaddingRatio,\n isCategoryAxis: true,\n isScalar: isScalar,\n isVertical: isVertical,\n categoryThickness: categoryThickness,\n useTickIntervalForDisplayUnits: true,\n getValueFn: function (index, type) { return visuals.CartesianHelper.lookupXValue(data, index, type, isScalar); },\n scaleType: axisScaleType,\n axisDisplayUnits: axisDisplayUnits,\n axisPrecision: axisPrecision\n });\n // intentionally updating the input layout by ref\n layout.categoryThickness = axisProperties.categoryThickness;\n return axisProperties;\n }\n ColumnUtil.getCategoryAxis = getCategoryAxis;\n function applyInteractivity(columns, onDragStart) {\n debug.assertValue(columns, 'columns');\n if (onDragStart) {\n columns\n .attr('draggable', 'true')\n .on('dragstart', onDragStart);\n }\n }\n ColumnUtil.applyInteractivity = applyInteractivity;\n function getFillOpacity(selected, highlight, hasSelection, hasPartialHighlights) {\n if ((hasPartialHighlights && !highlight) || (hasSelection && !selected))\n return ColumnUtil.DimmedOpacity;\n return ColumnUtil.DefaultOpacity;\n }\n ColumnUtil.getFillOpacity = getFillOpacity;\n function getClosestColumnIndex(coordinate, columnsCenters) {\n var currentIndex = 0;\n var distance = Number.MAX_VALUE;\n for (var i = 0, ilen = columnsCenters.length; i < ilen; i++) {\n var currentDistance = Math.abs(coordinate - columnsCenters[i]);\n if (currentDistance < distance) {\n distance = currentDistance;\n currentIndex = i;\n }\n }\n return currentIndex;\n }\n ColumnUtil.getClosestColumnIndex = getClosestColumnIndex;\n function setChosenColumnOpacity(mainGraphicsContext, columnGroupSelector, selectedColumnIndex, lastColumnIndex) {\n var series = mainGraphicsContext.selectAll(visuals.ColumnChart.SeriesClasses.selector);\n var lastColumnUndefined = typeof lastColumnIndex === 'undefined';\n // find all columns that do not belong to the selected column and set a dimmed opacity with a smooth animation to those columns\n series.selectAll(rectName + columnGroupSelector).filter(function (d) {\n return (d.categoryIndex !== selectedColumnIndex) && (lastColumnUndefined || d.categoryIndex === lastColumnIndex);\n }).transition().style('fill-opacity', ColumnUtil.DimmedOpacity);\n // set the default opacity for the selected column\n series.selectAll(rectName + columnGroupSelector).filter(function (d) {\n return d.categoryIndex === selectedColumnIndex;\n }).style('fill-opacity', ColumnUtil.DefaultOpacity);\n }\n ColumnUtil.setChosenColumnOpacity = setChosenColumnOpacity;\n function drawSeries(data, graphicsContext, axisOptions) {\n var colGroupSelection = graphicsContext.selectAll(visuals.ColumnChart.SeriesClasses.selector);\n var series = colGroupSelection.data(data.series, function (d) { return d.key; });\n series\n .enter()\n .append('g')\n .classed(visuals.ColumnChart.SeriesClasses.class, true);\n series\n .style({\n fill: function (d) { return d.color; },\n });\n series\n .exit()\n .remove();\n return series;\n }\n ColumnUtil.drawSeries = drawSeries;\n function drawDefaultShapes(data, series, layout, itemCS, filterZeros, hasSelection) {\n // We filter out invisible (0, null, etc.) values from the dataset\n // based on whether animations are enabled or not, Dashboard and\n // Exploration mode, respectively.\n var dataSelector;\n if (filterZeros) {\n dataSelector = function (d) {\n var filteredData = _.filter(d.data, function (datapoint) { return !!datapoint.value; });\n return filteredData;\n };\n }\n else {\n dataSelector = function (d) { return d.data; };\n }\n var shapeSelection = series.selectAll(itemCS.selector);\n var shapes = shapeSelection.data(dataSelector, function (d) { return d.key; });\n shapes.enter()\n .append(rectName)\n .attr(\"class\", function (d) { return itemCS.class.concat(d.highlight ? \" highlight\" : \"\"); });\n shapes\n .style(\"fill-opacity\", function (d) { return ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, data.hasHighlights); })\n .style(\"fill\", function (d) { return d.color !== data.series[d.seriesIndex].color ? d.color : null; }) // PERF: Only set the fill color if it is different than series.\n .attr(layout.shapeLayout);\n shapes\n .exit()\n .remove();\n return shapes;\n }\n ColumnUtil.drawDefaultShapes = drawDefaultShapes;\n function drawDefaultLabels(series, context, layout, viewPort, isAnimator, animationDuration) {\n if (isAnimator === void 0) { isAnimator = false; }\n if (series) {\n var seriesData = series.data();\n var dataPoints = [];\n for (var i = 0, len = seriesData.length; i < len; i++) {\n Array.prototype.push.apply(dataPoints, seriesData[i].data);\n }\n return visuals.dataLabelUtils.drawDefaultLabelsForDataPointChart(dataPoints, context, layout, viewPort, isAnimator, animationDuration);\n }\n else {\n visuals.dataLabelUtils.cleanDataLabels(context);\n }\n }\n ColumnUtil.drawDefaultLabels = drawDefaultLabels;\n function normalizeInfinityInScale(scale) {\n // When large values (eg Number.MAX_VALUE) are involved, a call to scale.nice occasionally\n // results in infinite values being included in the domain. To correct for that, we need to\n // re-normalize the domain now to not include infinities.\n var scaledDomain = scale.domain();\n for (var i = 0, len = scaledDomain.length; i < len; ++i) {\n if (scaledDomain[i] === Number.POSITIVE_INFINITY)\n scaledDomain[i] = Number.MAX_VALUE;\n else if (scaledDomain[i] === Number.NEGATIVE_INFINITY)\n scaledDomain[i] = -Number.MAX_VALUE;\n }\n scale.domain(scaledDomain);\n }\n ColumnUtil.normalizeInfinityInScale = normalizeInfinityInScale;\n function calculatePosition(d, axisOptions) {\n var xScale = axisOptions.xScale;\n var yScale = axisOptions.yScale;\n var scaledY0 = yScale(0);\n var scaledX0 = xScale(0);\n switch (d.chartType) {\n case visuals.ColumnChartType.stackedBar:\n case visuals.ColumnChartType.hundredPercentStackedBar:\n return scaledX0 + Math.abs(visuals.AxisHelper.diffScaled(xScale, 0, d.valueAbsolute)) +\n visuals.AxisHelper.diffScaled(xScale, d.position - d.valueAbsolute, 0) + visuals.dataLabelUtils.defaultColumnLabelMargin;\n case visuals.ColumnChartType.clusteredBar:\n return scaledX0 + visuals.AxisHelper.diffScaled(xScale, Math.max(0, d.value), 0) + visuals.dataLabelUtils.defaultColumnLabelMargin;\n case visuals.ColumnChartType.stackedColumn:\n case visuals.ColumnChartType.hundredPercentStackedColumn:\n return scaledY0 + visuals.AxisHelper.diffScaled(yScale, d.position, 0) - visuals.dataLabelUtils.defaultColumnLabelMargin;\n case visuals.ColumnChartType.clusteredColumn:\n return scaledY0 + visuals.AxisHelper.diffScaled(yScale, Math.max(0, d.value), 0) - visuals.dataLabelUtils.defaultColumnLabelMargin;\n }\n }\n ColumnUtil.calculatePosition = calculatePosition;\n })(ColumnUtil = visuals.ColumnUtil || (visuals.ColumnUtil = {}));\n var ClusteredUtil;\n (function (ClusteredUtil) {\n function clearColumns(mainGraphicsContext, itemCS) {\n debug.assertValue(mainGraphicsContext, 'mainGraphicsContext');\n debug.assertValue(itemCS, 'itemCS');\n var cols = mainGraphicsContext.selectAll(itemCS.selector)\n .data([]);\n cols.exit().remove();\n }\n ClusteredUtil.clearColumns = clearColumns;\n })(ClusteredUtil = visuals.ClusteredUtil || (visuals.ClusteredUtil = {}));\n var StackedUtil;\n (function (StackedUtil) {\n var PctRoundingError = 0.0001;\n function getSize(scale, size, zeroVal) {\n if (zeroVal === void 0) { zeroVal = 0; }\n return visuals.AxisHelper.diffScaled(scale, zeroVal, size);\n }\n StackedUtil.getSize = getSize;\n function calcValueDomain(data, is100pct) {\n var defaultNumberRange = {\n min: 0,\n max: 10\n };\n if (data.length === 0)\n return defaultNumberRange;\n // Can't use AxisHelper because Stacked layout has a slightly different calc, (position - valueAbs)\n var min = d3.min(data, function (d) { return d3.min(d.data, function (e) { return e.position - e.valueAbsolute; }); });\n var max = d3.max(data, function (d) { return d3.max(d.data, function (e) { return e.position; }); });\n if (is100pct) {\n min = powerbi.Double.roundToPrecision(min, PctRoundingError);\n max = powerbi.Double.roundToPrecision(max, PctRoundingError);\n }\n return {\n min: min,\n max: max,\n };\n }\n StackedUtil.calcValueDomain = calcValueDomain;\n function getStackedMultiplier(dataView, rowIdx, seriesCount, categoryCount, converterStrategy) {\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(rowIdx, 'rowIdx');\n var pos = 0, neg = 0;\n for (var i = 0; i < seriesCount; i++) {\n var value = converterStrategy.getValueBySeriesAndCategory(i, rowIdx);\n value = visuals.AxisHelper.normalizeNonFiniteNumber(value);\n if (value > 0)\n pos += value;\n else if (value < 0)\n neg -= value;\n }\n var absTotal = pos + neg;\n return {\n pos: pos ? (pos / absTotal) / pos : 1,\n neg: neg ? (neg / absTotal) / neg : 1,\n };\n }\n StackedUtil.getStackedMultiplier = getStackedMultiplier;\n function clearColumns(mainGraphicsContext, itemCS) {\n debug.assertValue(mainGraphicsContext, 'mainGraphicsContext');\n debug.assertValue(itemCS, 'itemCS');\n var bars = mainGraphicsContext.selectAll(itemCS.selector)\n .data([]);\n bars.exit().remove();\n }\n StackedUtil.clearColumns = clearColumns;\n })(StackedUtil = visuals.StackedUtil || (visuals.StackedUtil = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n var converterHelper;\n (function (converterHelper) {\n function categoryIsAlsoSeriesRole(dataView, seriesRoleName, categoryRoleName) {\n if (dataView.categories && dataView.categories.length > 0) {\n // Need to pivot data if our category soure is a series role\n var category = dataView.categories[0];\n return category.source &&\n DataRoleHelper.hasRole(category.source, seriesRoleName) &&\n DataRoleHelper.hasRole(category.source, categoryRoleName);\n }\n return false;\n }\n converterHelper.categoryIsAlsoSeriesRole = categoryIsAlsoSeriesRole;\n function getPivotedCategories(dataView, formatStringProp) {\n if (dataView.categories && dataView.categories.length > 0) {\n var category = dataView.categories[0];\n var categoryValues = category.values;\n return category.values.length > 0\n ? {\n categories: categoryValues,\n categoryFormatter: visuals.valueFormatter.create({\n format: visuals.valueFormatter.getFormatString(category.source, formatStringProp),\n value: categoryValues[0],\n value2: categoryValues[categoryValues.length - 1],\n // Do not use display units such as K/M/bn etc. on the x-axis.\n // PowerView does not use units either as large ranges will make the x-axis indecipherable.\n displayUnitSystemType: powerbi.DisplayUnitSystemType.Verbose,\n }),\n categoryIdentities: category.identity,\n categoryObjects: category.objects,\n }\n : {\n categories: [],\n categoryFormatter: { format: visuals.valueFormatter.format },\n };\n }\n // For cases where the category source is just a series role, we are pivoting the data on the role which means we\n // will have no categories.\n return defaultCategories();\n }\n converterHelper.getPivotedCategories = getPivotedCategories;\n function getSeriesName(source) {\n debug.assertValue(source, 'source');\n return (source.groupName !== undefined)\n ? source.groupName\n : source.queryName;\n }\n converterHelper.getSeriesName = getSeriesName;\n function getFormattedLegendLabel(source, values, formatStringProp) {\n debug.assertValue(source, 'source');\n debug.assertValue(values, 'values');\n var sourceForFormat = source;\n var nameForFormat = source.displayName;\n if (source.groupName !== undefined) {\n sourceForFormat = values.source;\n nameForFormat = source.groupName;\n }\n return visuals.valueFormatter.format(nameForFormat, visuals.valueFormatter.getFormatString(sourceForFormat, formatStringProp));\n }\n converterHelper.getFormattedLegendLabel = getFormattedLegendLabel;\n function defaultCategories() {\n return {\n categories: [null],\n categoryFormatter: { format: visuals.valueFormatter.format },\n };\n }\n function createAxesLabels(categoryAxisProperties, valueAxisProperties, category, values) {\n var xAxisLabel = null;\n var yAxisLabel = null;\n if (categoryAxisProperties) {\n // Take the value only if it's there\n if (category && category.displayName) {\n xAxisLabel = category.displayName;\n }\n }\n if (valueAxisProperties) {\n var valuesNames = [];\n if (values) {\n // Take the name from the values, and make it unique because there are sometimes duplications\n valuesNames = values.map(function (v) { return v ? v.displayName : ''; }).filter(function (value, index, self) { return value !== '' && self.indexOf(value) === index; });\n yAxisLabel = visuals.valueFormatter.formatListAnd(valuesNames);\n }\n }\n return { xAxisLabel: xAxisLabel, yAxisLabel: yAxisLabel };\n }\n converterHelper.createAxesLabels = createAxesLabels;\n function isImageUrlColumn(column) {\n var misc = getMiscellaneousTypeDescriptor(column);\n return misc != null && misc.imageUrl === true;\n }\n converterHelper.isImageUrlColumn = isImageUrlColumn;\n function isWebUrlColumn(column) {\n var misc = getMiscellaneousTypeDescriptor(column);\n return misc != null && misc.webUrl === true;\n }\n converterHelper.isWebUrlColumn = isWebUrlColumn;\n function getMiscellaneousTypeDescriptor(column) {\n return column\n && column.type\n && column.type.misc;\n }\n function hasImageUrlColumn(dataView) {\n if (!dataView || !dataView.metadata || _.isEmpty(dataView.metadata.columns))\n return false;\n return _.any(dataView.metadata.columns, function (column) { return isImageUrlColumn(column) === true; });\n }\n converterHelper.hasImageUrlColumn = hasImageUrlColumn;\n function formatFromMetadataColumn(value, column, formatStringProp) {\n debug.assertValue(column, 'column should exist');\n var formatString = visuals.valueFormatter.getFormatString(column, formatStringProp, true);\n if (!formatString && column) {\n formatString = column.format;\n }\n return visuals.valueFormatter.format(value, formatString);\n }\n converterHelper.formatFromMetadataColumn = formatFromMetadataColumn;\n })(converterHelper = visuals.converterHelper || (visuals.converterHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n var LabelStyle = visuals.labelStyle;\n var dataLabelUtils;\n (function (dataLabelUtils) {\n dataLabelUtils.minLabelFontSize = 8;\n dataLabelUtils.labelMargin = 8;\n dataLabelUtils.maxLabelWidth = 50;\n dataLabelUtils.defaultColumnLabelMargin = 5;\n dataLabelUtils.defaultColumnHalfLabelHeight = 4;\n dataLabelUtils.DefaultDy = '-0.15em';\n dataLabelUtils.DefaultFontSizeInPt = 9;\n dataLabelUtils.StandardFontFamily = 'wf_segoe-ui_normal';\n dataLabelUtils.LabelTextProperties = {\n fontFamily: 'wf_standard-font',\n fontSize: PixelConverter.fromPoint(dataLabelUtils.DefaultFontSizeInPt),\n fontWeight: 'normal',\n };\n dataLabelUtils.defaultLabelColor = \"#777777\";\n dataLabelUtils.defaultInsideLabelColor = \"#ffffff\";\n dataLabelUtils.hundredPercentFormat = \"0.00 %;-0.00 %;0.00 %\";\n dataLabelUtils.defaultLabelPrecision = undefined;\n var defaultCountLabelPrecision = 0;\n var labelGraphicsContextClass = createClassAndSelector('labels');\n var linesGraphicsContextClass = createClassAndSelector('lines');\n var labelsClass = createClassAndSelector('data-labels');\n var lineClass = createClassAndSelector('line-label');\n function updateLabelSettingsFromLabelsObject(labelsObj, labelSettings) {\n if (labelsObj) {\n if (labelsObj.show !== undefined)\n labelSettings.show = labelsObj.show;\n if (labelsObj.showSeries !== undefined)\n labelSettings.show = labelsObj.showSeries;\n if (labelsObj.color !== undefined)\n labelSettings.labelColor = labelsObj.color.solid.color;\n if (labelsObj.labelDisplayUnits !== undefined)\n labelSettings.displayUnits = labelsObj.labelDisplayUnits;\n if (labelsObj.labelPrecision !== undefined)\n labelSettings.precision = (labelsObj.labelPrecision >= 0) ? labelsObj.labelPrecision : dataLabelUtils.defaultLabelPrecision;\n if (labelsObj.fontSize !== undefined)\n labelSettings.fontSize = labelsObj.fontSize;\n if (labelsObj.showAll !== undefined)\n labelSettings.showLabelPerSeries = labelsObj.showAll;\n if (labelsObj.labelStyle !== undefined)\n labelSettings.labelStyle = labelsObj.labelStyle;\n }\n }\n dataLabelUtils.updateLabelSettingsFromLabelsObject = updateLabelSettingsFromLabelsObject;\n function updateLineChartLabelSettingsFromLabelsObject(labelsObj, labelSettings) {\n updateLabelSettingsFromLabelsObject(labelsObj, labelSettings);\n if (labelsObj && labelsObj.labelDensity !== undefined)\n labelSettings.labelDensity = labelsObj.labelDensity;\n }\n dataLabelUtils.updateLineChartLabelSettingsFromLabelsObject = updateLineChartLabelSettingsFromLabelsObject;\n function getDefaultLabelSettings(show, labelColor, fontSize) {\n if (show === void 0) { show = false; }\n return {\n show: show,\n position: 0 /* Above */,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: labelColor || dataLabelUtils.defaultLabelColor,\n formatterOptions: null,\n fontSize: fontSize || dataLabelUtils.DefaultFontSizeInPt,\n };\n }\n dataLabelUtils.getDefaultLabelSettings = getDefaultLabelSettings;\n function getDefaultCardLabelSettings(labelColor, categoryLabelColor, fontSize) {\n var labelSettings = getDefaultLabelSettings(true, labelColor, fontSize);\n labelSettings.showCategory = true;\n labelSettings.categoryLabelColor = categoryLabelColor;\n return labelSettings;\n }\n dataLabelUtils.getDefaultCardLabelSettings = getDefaultCardLabelSettings;\n function getDefaultTreemapLabelSettings() {\n return {\n show: false,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: dataLabelUtils.defaultInsideLabelColor,\n showCategory: true,\n formatterOptions: null,\n };\n }\n dataLabelUtils.getDefaultTreemapLabelSettings = getDefaultTreemapLabelSettings;\n function getDefaultSunburstLabelSettings() {\n return {\n show: false,\n labelColor: dataLabelUtils.defaultInsideLabelColor,\n fontSize: dataLabelUtils.DefaultFontSizeInPt,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n showCategory: true,\n };\n }\n dataLabelUtils.getDefaultSunburstLabelSettings = getDefaultSunburstLabelSettings;\n function getDefaultColumnLabelSettings(isLabelPositionInside) {\n var labelSettings = getDefaultLabelSettings(false, undefined);\n labelSettings.position = null;\n labelSettings.labelColor = undefined;\n return labelSettings;\n }\n dataLabelUtils.getDefaultColumnLabelSettings = getDefaultColumnLabelSettings;\n function getDefaultPointLabelSettings() {\n return {\n show: false,\n position: 0 /* Above */,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: dataLabelUtils.defaultLabelColor,\n formatterOptions: null,\n fontSize: dataLabelUtils.DefaultFontSizeInPt,\n };\n }\n dataLabelUtils.getDefaultPointLabelSettings = getDefaultPointLabelSettings;\n function getDefaultLineChartLabelSettings(isComboChart) {\n return {\n show: false,\n position: 0 /* Above */,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: dataLabelUtils.defaultLabelColor,\n formatterOptions: null,\n fontSize: dataLabelUtils.DefaultFontSizeInPt,\n labelDensity: isComboChart ? visuals.NewDataLabelUtils.LabelDensityMax : visuals.NewDataLabelUtils.LabelDensityMin,\n };\n }\n dataLabelUtils.getDefaultLineChartLabelSettings = getDefaultLineChartLabelSettings;\n function getDefaultMapLabelSettings() {\n return {\n show: false,\n showCategory: false,\n position: 0 /* Above */,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: dataLabelUtils.defaultInsideLabelColor,\n formatterOptions: null,\n fontSize: dataLabelUtils.DefaultFontSizeInPt,\n };\n }\n dataLabelUtils.getDefaultMapLabelSettings = getDefaultMapLabelSettings;\n function getDefaultDonutLabelSettings() {\n var labelSettings = dataLabelUtils.getDefaultLabelSettings(true, dataLabelUtils.defaultLabelColor, dataLabelUtils.DefaultFontSizeInPt);\n labelSettings.labelStyle = LabelStyle.category;\n return labelSettings;\n }\n dataLabelUtils.getDefaultDonutLabelSettings = getDefaultDonutLabelSettings;\n function getDefaultGaugeLabelSettings() {\n return {\n show: true,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: null,\n position: null,\n fontSize: dataLabelUtils.minLabelFontSize,\n formatterOptions: null,\n };\n }\n dataLabelUtils.getDefaultGaugeLabelSettings = getDefaultGaugeLabelSettings;\n function getDefaultFunnelLabelSettings() {\n return {\n show: true,\n position: powerbi.visuals.labelPosition.insideCenter,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: dataLabelUtils.defaultLabelColor,\n formatterOptions: null,\n fontSize: dataLabelUtils.DefaultFontSizeInPt,\n };\n }\n dataLabelUtils.getDefaultFunnelLabelSettings = getDefaultFunnelLabelSettings;\n function getDefaultKpiLabelSettings() {\n return {\n show: false,\n displayUnits: 0,\n precision: dataLabelUtils.defaultLabelPrecision,\n labelColor: dataLabelUtils.defaultLabelColor,\n position: null,\n showCategory: true,\n formatterOptions: null,\n };\n }\n dataLabelUtils.getDefaultKpiLabelSettings = getDefaultKpiLabelSettings;\n function getLabelPrecision(precision, format) {\n debug.assertAnyValue(format, 'format');\n if (precision !== dataLabelUtils.defaultLabelPrecision)\n return precision;\n if (format === 'g' || format === 'G')\n return;\n if (format) {\n // Calculate precision from positive format by default\n var positiveFormat = format.split(\";\")[0];\n var formatMetadata = powerbi.NumberFormat.getCustomFormatMetadata(positiveFormat, true /*calculatePrecision*/);\n if (formatMetadata.hasDots) {\n return formatMetadata.precision;\n }\n }\n // For count fields we do not want a precision by default\n return defaultCountLabelPrecision;\n }\n dataLabelUtils.getLabelPrecision = getLabelPrecision;\n function drawDefaultLabelsForDataPointChart(data, context, layout, viewport, isAnimator, animationDuration, hasSelection) {\n if (isAnimator === void 0) { isAnimator = false; }\n debug.assertValue(data, 'data cannot be null or undefined');\n // Hide and reposition labels that overlap\n var dataLabelManager = new powerbi.DataLabelManager();\n var filteredData = dataLabelManager.hideCollidedLabels(viewport, data, layout);\n var hasAnimation = isAnimator && !!animationDuration;\n var labels = selectLabels(filteredData, context, false, hasAnimation);\n if (!labels)\n return;\n if (hasAnimation) {\n labels\n .text(function (d) { return d.labeltext; })\n .transition()\n .duration(animationDuration)\n .style(layout.style)\n .style('opacity', hasSelection ? function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); } : 1)\n .attr({ x: function (d) { return d.labelX; }, y: function (d) { return d.labelY; } });\n labels\n .exit()\n .transition()\n .duration(animationDuration)\n .style('opacity', 0) //fade out labels that are removed\n .remove();\n }\n else {\n labels\n .attr({ x: function (d) { return d.labelX; }, y: function (d) { return d.labelY; } })\n .text(function (d) { return d.labeltext; })\n .style(layout.style);\n labels\n .exit()\n .remove();\n }\n return labels;\n }\n dataLabelUtils.drawDefaultLabelsForDataPointChart = drawDefaultLabelsForDataPointChart;\n /**\n * Note: Funnel chart uses animation and does not use collision detection.\n */\n function drawDefaultLabelsForFunnelChart(data, context, layout, isAnimator, animationDuration) {\n if (isAnimator === void 0) { isAnimator = false; }\n debug.assertValue(data, 'data could not be null or undefined');\n var filteredData = data.filter(layout.filter);\n var labels = selectLabels(filteredData, context);\n if (!labels)\n return;\n labels\n .attr(layout.labelLayout)\n .text(layout.labelText)\n .style(layout.style);\n if (isAnimator && animationDuration) {\n labels.transition().duration(animationDuration);\n }\n labels\n .exit()\n .remove();\n return labels;\n }\n dataLabelUtils.drawDefaultLabelsForFunnelChart = drawDefaultLabelsForFunnelChart;\n function selectLabels(filteredData, context, isDonut, forAnimation) {\n if (isDonut === void 0) { isDonut = false; }\n if (forAnimation === void 0) { forAnimation = false; }\n // Check for a case where resizing leaves no labels - then we need to remove the labels 'g'\n if (filteredData.length === 0) {\n cleanDataLabels(context, true);\n return null;\n }\n if (context.select(labelGraphicsContextClass.selector).empty())\n context.append('g').classed(labelGraphicsContextClass.class, true);\n // line chart ViewModel has a special 'key' property for point identification since the 'identity' field is set to the series identity\n var hasKey = filteredData[0].key != null;\n var hasDataPointIdentity = filteredData[0].identity != null;\n var getIdentifier = hasKey ?\n function (d) { return d.key; }\n : hasDataPointIdentity ?\n function (d) { return d.identity.getKey(); }\n : undefined;\n var labels = isDonut ?\n context.select(labelGraphicsContextClass.selector).selectAll(labelsClass.selector).data(filteredData, function (d) { return d.data.identity.getKey(); })\n : getIdentifier != null ?\n context.select(labelGraphicsContextClass.selector).selectAll(labelsClass.selector).data(filteredData, getIdentifier)\n : context.select(labelGraphicsContextClass.selector).selectAll(labelsClass.selector).data(filteredData);\n var newLabels = labels.enter()\n .append('text')\n .classed(labelsClass.class, true);\n if (forAnimation)\n newLabels.style('opacity', 0);\n return labels;\n }\n function cleanDataLabels(context, removeLines) {\n if (removeLines === void 0) { removeLines = false; }\n var empty = [];\n var labels = context.selectAll(labelsClass.selector).data(empty);\n labels.exit().remove();\n context.selectAll(labelGraphicsContextClass.selector).remove();\n if (removeLines) {\n var lines = context.selectAll(lineClass.selector).data(empty);\n lines.exit().remove();\n context.selectAll(linesGraphicsContextClass.selector).remove();\n }\n }\n dataLabelUtils.cleanDataLabels = cleanDataLabels;\n function setHighlightedLabelsOpacity(context, hasSelection, hasHighlights) {\n context.selectAll(labelsClass.selector).style(\"fill-opacity\", function (d) {\n var labelOpacity = visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && hasHighlights) < 1 ? 0 : 1;\n return labelOpacity;\n });\n }\n dataLabelUtils.setHighlightedLabelsOpacity = setHighlightedLabelsOpacity;\n function getLabelFormattedText(options) {\n var properties = {\n text: options.formatter\n ? options.formatter.format(options.label)\n : powerbi.formattingService.formatValue(options.label, options.format),\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(options.fontSize),\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\n };\n return powerbi.TextMeasurementService.getTailoredTextOrDefault(properties, options.maxWidth ? options.maxWidth : dataLabelUtils.maxLabelWidth);\n }\n dataLabelUtils.getLabelFormattedText = getLabelFormattedText;\n function getLabelLayoutXYForWaterfall(xAxisProperties, categoryWidth, yAxisProperties, dataDomain) {\n return {\n x: function (d) { return xAxisProperties.scale(d.categoryIndex) + (categoryWidth / 2); },\n y: function (d) { return getWaterfallLabelYPosition(yAxisProperties.scale, d, dataDomain); }\n };\n }\n dataLabelUtils.getLabelLayoutXYForWaterfall = getLabelLayoutXYForWaterfall;\n function getWaterfallLabelYPosition(scale, d, dataDomain) {\n var yValue = scale(0) - scale(Math.abs(d.value));\n var yPos = scale(d.position);\n var scaleMinDomain = scale(dataDomain[0]);\n var endPosition = scale(d.position + d.value);\n if (d.value < 0) {\n var properties = {\n text: d.labeltext,\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\n };\n var outsideBelowPosition = yPos + yValue + powerbi.TextMeasurementService.estimateSvgTextHeight(properties);\n // Try to honor the position, but if the label doesn't fit where specified, then swap the position.\n if (scaleMinDomain > outsideBelowPosition) {\n return outsideBelowPosition;\n }\n }\n else {\n var outsideAbovePosition = yPos - yValue - dataLabelUtils.labelMargin;\n // Try to honor the position, but if the label doesn't fit where specified, then swap the position.\n if (outsideAbovePosition > 0) {\n return outsideAbovePosition;\n }\n }\n d.isLabelInside = true;\n return getWaterfallInsideLabelYPosition(yPos, endPosition, scaleMinDomain);\n }\n function getWaterfallInsideLabelYPosition(startPosition, endPosition, scaleMinDomain) {\n // Get the start and end position of the column\n // If the start or end is outside of the visual because of clipping - adjust the position\n startPosition = startPosition < 0 ? 0 : startPosition;\n startPosition = startPosition > scaleMinDomain ? scaleMinDomain : startPosition;\n endPosition = endPosition < 0 ? 0 : endPosition;\n endPosition = endPosition > scaleMinDomain ? scaleMinDomain : endPosition;\n return (Math.abs(endPosition - startPosition) / 2) + Math.min(startPosition, endPosition);\n }\n function doesDataLabelFitInShape(d, yAxisProperties, layout) {\n if (d == null || d.value === null)\n return false;\n var properties = {\n text: layout.labelText(d),\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\n };\n var outsidePosition = visuals.WaterfallChart.getRectTop(yAxisProperties.scale, d.position, d.value) - dataLabelUtils.labelMargin;\n // The shape is fit to be outside\n if (outsidePosition > 0)\n return true;\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties);\n var shapeWidth = layout.categoryWidth;\n var shapeHeight = Math.abs(visuals.AxisHelper.diffScaled(yAxisProperties.scale, Math.max(0, Math.abs(d.value)), 0));\n //checking that labels aren't greater than shape\n if ((textWidth > shapeWidth) || (textHeight > shapeHeight))\n return false;\n return true;\n }\n dataLabelUtils.doesDataLabelFitInShape = doesDataLabelFitInShape;\n function getMapLabelLayout(labelSettings) {\n return {\n labelText: function (d) {\n return getLabelFormattedText({\n label: d.labeltext,\n fontSize: labelSettings.fontSize\n });\n },\n labelLayout: {\n x: function (d) { return d.x; },\n y: function (d) {\n var margin = d.radius + dataLabelUtils.labelMargin;\n return labelSettings.position === 0 /* Above */ ? d.y - margin : d.y + margin;\n },\n },\n filter: function (d) {\n return (d != null && d.labeltext != null);\n },\n style: {\n 'fill': function (d) { return d.labelFill; },\n 'font-size': PixelConverter.fromPoint(labelSettings.fontSize),\n },\n };\n }\n dataLabelUtils.getMapLabelLayout = getMapLabelLayout;\n function getColumnChartLabelLayout(data, labelLayoutXY, isColumn, isHundredPercent, axisFormatter, axisOptions, interactivityService, visualWidth) {\n var formatOverride = (isHundredPercent) ? dataLabelUtils.hundredPercentFormat : null;\n var formattersCache = createColumnFormatterCacheManager();\n var hasSelection = interactivityService ? interactivityService.hasSelection() : false;\n return {\n labelText: function (d) {\n var formatString = (formatOverride != null) ? formatOverride : d.labelFormatString;\n var value2 = getDisplayUnitValueFromAxisFormatter(axisFormatter, d.labelSettings);\n var formatter = formattersCache.getOrCreate(formatString, d.labelSettings, value2);\n return getLabelFormattedText({\n label: formatter.format(d.value),\n maxWidth: dataLabelUtils.maxLabelWidth\n });\n },\n labelLayout: labelLayoutXY,\n filter: function (d) { return dataLabelUtils.getColumnChartLabelFilter(d, hasSelection, data.hasHighlights, axisOptions, visualWidth); },\n style: {\n 'fill': function (d) { return d.labelFill; },\n 'text-anchor': isColumn ? 'middle' : 'start',\n },\n };\n }\n dataLabelUtils.getColumnChartLabelLayout = getColumnChartLabelLayout;\n /**\n * Valide for stacked column/bar chart and 100% stacked column/bar chart,\n * that labels that should to be inside the shape aren't bigger then shapes.\n */\n function validateLabelsSize(d, axisOptions, visualWidth) {\n var xScale = axisOptions.xScale;\n var yScale = axisOptions.yScale;\n var columnWidth = axisOptions.columnWidth;\n var properties = {\n text: d.labeltext,\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties);\n var shapeWidth, shapeHeight;\n var inside = false;\n var outsidePosition = visuals.ColumnUtil.calculatePosition(d, axisOptions);\n switch (d.chartType) {\n case visuals.ColumnChartType.stackedBar:\n case visuals.ColumnChartType.hundredPercentStackedBar:\n // if the series isn't last or the label doesn't fit where specified, then it should be inside \n if (!d.lastSeries || (outsidePosition + textWidth > visualWidth) || d.chartType === visuals.ColumnChartType.hundredPercentStackedBar) {\n shapeWidth = -visuals.StackedUtil.getSize(xScale, d.valueAbsolute);\n shapeHeight = columnWidth;\n inside = true;\n }\n break;\n case visuals.ColumnChartType.clusteredBar:\n // if the label doesn't fit where specified, then it should be inside \n if ((outsidePosition + textWidth) > visualWidth) {\n shapeWidth = Math.abs(visuals.AxisHelper.diffScaled(xScale, 0, d.value));\n shapeHeight = columnWidth;\n inside = true;\n }\n break;\n case visuals.ColumnChartType.stackedColumn:\n case visuals.ColumnChartType.hundredPercentStackedColumn:\n // if the series isn't last or the label doesn't fit where specified, then it should be inside \n if (!d.lastSeries || outsidePosition <= 0 || d.chartType === visuals.ColumnChartType.hundredPercentStackedColumn) {\n shapeWidth = columnWidth;\n shapeHeight = visuals.StackedUtil.getSize(yScale, d.valueAbsolute);\n inside = true;\n }\n break;\n case visuals.ColumnChartType.clusteredColumn:\n // if the label doesn't fit where specified, then it should be inside \n if (outsidePosition <= 0) {\n shapeWidth = columnWidth;\n shapeHeight = Math.abs(visuals.AxisHelper.diffScaled(yScale, 0, d.value));\n inside = true;\n }\n break;\n default:\n return true;\n }\n //checking that labels aren't greater than shape\n if (inside && ((textWidth > shapeWidth) || textHeight > shapeHeight))\n return false;\n return true;\n }\n function getColumnChartLabelFilter(d, hasSelection, hasHighlights, axisOptions, visualWidth) {\n //labels of dimmed are hidden\n var shapesOpacity = hasSelection ? visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && hasHighlights) :\n visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights);\n return (d != null && d.value != null && validateLabelsSize(d, axisOptions, visualWidth) && shapesOpacity === 1);\n }\n dataLabelUtils.getColumnChartLabelFilter = getColumnChartLabelFilter;\n function getScatterChartLabelLayout(xScale, yScale, labelSettings, viewport, sizeRange) {\n return {\n labelText: function (d) {\n return getLabelFormattedText({\n label: d.formattedCategory.getValue(),\n maxWidth: dataLabelUtils.maxLabelWidth * 2.0\n });\n },\n labelLayout: {\n x: function (d) { return xScale(d.x); },\n y: function (d) {\n var margin = visuals.ScatterChart.getBubbleRadius(d.radius, sizeRange, viewport) + dataLabelUtils.labelMargin;\n return labelSettings.position === 0 /* Above */ ? yScale(d.y) - margin : yScale(d.y) + margin;\n },\n },\n filter: function (d) {\n return (d != null && d.formattedCategory.getValue() != null);\n },\n style: {\n 'fill': function (d) { return d.labelFill; },\n },\n };\n }\n dataLabelUtils.getScatterChartLabelLayout = getScatterChartLabelLayout;\n function getLineChartLabelLayout(xScale, yScale, labelSettings, isScalar, axisFormatter) {\n var formattersCache = createColumnFormatterCacheManager();\n return {\n labelText: function (d) {\n var value2 = getDisplayUnitValueFromAxisFormatter(axisFormatter, d.labelSettings);\n var formatter = formattersCache.getOrCreate(d.labelFormatString, d.labelSettings, value2);\n return getLabelFormattedText({ label: formatter.format(d.value) });\n },\n labelLayout: {\n x: function (d) { return xScale(isScalar ? d.categoryValue : d.categoryIndex); },\n y: function (d) { return labelSettings.position === 0 /* Above */ ? yScale(d.value) - dataLabelUtils.labelMargin : yScale(d.value) + dataLabelUtils.labelMargin; },\n },\n filter: function (d) {\n return (d != null && d.value != null);\n },\n style: {\n 'fill': function (d) { return d.labelFill; },\n 'font-size': function (d) { return PixelConverter.fromPoint(d.labelSettings.fontSize); },\n },\n };\n }\n dataLabelUtils.getLineChartLabelLayout = getLineChartLabelLayout;\n function getFunnelChartLabelLayout(data, axisOptions, textMinimumPadding, labelSettings, currentViewport) {\n var categoryScale = axisOptions.categoryScale;\n var valueScale = axisOptions.valueScale;\n var marginLeft = axisOptions.margin.left;\n var innerTextHeightRate = 0.7;\n var rangeBand = axisOptions.categoryScale.rangeBand();\n var pixelSpan = axisOptions.maxWidth / 2;\n var formatString = visuals.valueFormatter.getFormatString(data.valuesMetadata[0], visuals.funnelChartProps.general.formatString);\n var textMeasurer = powerbi.TextMeasurementService.measureSvgTextWidth;\n var value2 = null;\n if (labelSettings.displayUnits === 0) {\n var minY = d3.min(data.slices, function (d) { return d.value; });\n var maxY = d3.max(data.slices, function (d) { return d.value; });\n value2 = Math.max(Math.abs(minY), Math.abs(maxY));\n }\n var formattersCache = createColumnFormatterCacheManager();\n return {\n labelText: function (d) {\n var barWidth = Math.abs(categoryScale(d.value) - categoryScale(0));\n var insideAvailableSpace = Math.abs(categoryScale(d.value) - categoryScale(0)) - (textMinimumPadding * 2);\n var outsideAvailableSpace = pixelSpan - (barWidth / 2) - textMinimumPadding;\n var labelFormatString = (formatString != null) ? formatString : d.labelFormatString;\n var maximumTextSize = Math.max(insideAvailableSpace, outsideAvailableSpace);\n var formatter = formattersCache.getOrCreate(labelFormatString, labelSettings, value2);\n var labelText = formatter.format(visuals.FunnelChart.getFunnelSliceValue(d, true /* asOriginal */));\n return getLabelFormattedText({\n label: labelText,\n maxWidth: maximumTextSize,\n fontSize: labelSettings.fontSize\n });\n },\n labelLayout: {\n y: function (d, i) {\n var properties = {\n text: d.labeltext,\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\n };\n //in order to make it center aligned we should 'correct' the height to not calculate text margin\n var labelHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties);\n return categoryScale(d.categoryOrMeasureIndex) + (rangeBand / 2) + (labelHeight / 2);\n },\n x: function (d) {\n var barWidth = Math.abs(valueScale(d.value) - valueScale(0));\n var insideAvailableSpace = Math.abs(valueScale(d.value) - valueScale(0)) - (textMinimumPadding * 2);\n var outsideAvailableSpace = pixelSpan - (barWidth / 2) - textMinimumPadding;\n var maximumTextSize = Math.max(insideAvailableSpace, outsideAvailableSpace);\n var labelFormatString = (formatString != null) ? formatString : d.labelFormatString;\n var formatter = formattersCache.getOrCreate(labelFormatString, labelSettings, value2);\n var labelText = formatter.format(visuals.FunnelChart.getFunnelSliceValue(d, true /* asOriginal */));\n var properties = {\n text: getLabelFormattedText({\n label: labelText,\n maxWidth: maximumTextSize\n }),\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textLength = textMeasurer(properties);\n // Try to honor the position, but if the label doesn't fit where specified, then swap the position.\n var labelPositionValue = labelSettings.position;\n if ((labelPositionValue === visuals.labelPosition.outsideEnd && outsideAvailableSpace < textLength) || d.value === 0)\n labelPositionValue = visuals.labelPosition.insideCenter;\n else if (labelPositionValue === visuals.labelPosition.insideCenter && insideAvailableSpace < textLength) {\n labelPositionValue = visuals.labelPosition.outsideEnd;\n }\n switch (labelPositionValue) {\n case visuals.labelPosition.outsideEnd:\n return marginLeft + pixelSpan + (barWidth / 2) + textMinimumPadding + (textLength / 2);\n default:\n // Inside position, change color to white unless value is 0\n d.labelFill = d.value !== 0 ? dataLabelUtils.defaultInsideLabelColor : d.labelFill;\n return marginLeft + pixelSpan;\n }\n },\n dy: '-0.15em',\n },\n filter: function (d) {\n if (!(d != null && d.value != null && data.hasHighlights === !!d.highlight))\n return false;\n var properties = {\n text: d.labeltext,\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\n };\n var labelHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties) * innerTextHeightRate;\n return labelHeight < rangeBand;\n },\n style: {\n 'fill': function (d) { return d.labelFill; },\n 'fill-opacity': function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, false, false); },\n 'font-size': function (d) { return PixelConverter.fromPoint(labelSettings.fontSize); },\n },\n };\n }\n dataLabelUtils.getFunnelChartLabelLayout = getFunnelChartLabelLayout;\n function enumerateDataLabels(options) {\n debug.assertValue(options, 'options');\n debug.assertValue(options.enumeration, 'enumeration');\n if (!options.dataLabelsSettings)\n return;\n var instance = {\n objectName: 'labels',\n selector: options.selector,\n properties: {},\n };\n if (options.show && options.selector) {\n instance.properties['showSeries'] = options.dataLabelsSettings.show;\n }\n else if (options.show) {\n instance.properties['show'] = options.dataLabelsSettings.show;\n }\n instance.properties['color'] = options.dataLabelsSettings.labelColor || dataLabelUtils.defaultLabelColor;\n if (options.displayUnits) {\n instance.properties['labelDisplayUnits'] = options.dataLabelsSettings.displayUnits;\n }\n if (options.precision) {\n var precision = options.dataLabelsSettings.precision;\n instance.properties['labelPrecision'] = precision === dataLabelUtils.defaultLabelPrecision ? null : precision;\n }\n if (options.position) {\n instance.properties['labelPosition'] = options.dataLabelsSettings.position;\n if (options.positionObject) {\n debug.assert(!instance.validValues, '!instance.validValues');\n instance.validValues = { 'labelPosition': options.positionObject };\n }\n }\n if (options.labelStyle)\n instance.properties['labelStyle'] = options.dataLabelsSettings.labelStyle;\n if (options.fontSize)\n instance.properties['fontSize'] = options.dataLabelsSettings.fontSize;\n if (options.labelDensity) {\n var lineChartSettings = options.dataLabelsSettings;\n if (lineChartSettings)\n instance.properties['labelDensity'] = lineChartSettings.labelDensity;\n }\n //Keep show all as the last property of the instance.\n if (options.showAll)\n instance.properties['showAll'] = options.dataLabelsSettings.showLabelPerSeries;\n return options.enumeration.pushInstance(instance);\n }\n dataLabelUtils.enumerateDataLabels = enumerateDataLabels;\n function enumerateCategoryLabels(enumeration, dataLabelsSettings, withFill, isShowCategory, fontSize) {\n if (isShowCategory === void 0) { isShowCategory = false; }\n var labelSettings = (dataLabelsSettings)\n ? dataLabelsSettings\n : getDefaultPointLabelSettings();\n var instance = {\n objectName: 'categoryLabels',\n selector: null,\n properties: {\n show: isShowCategory\n ? labelSettings.showCategory\n : labelSettings.show,\n fontSize: dataLabelsSettings ? dataLabelsSettings.fontSize : dataLabelUtils.DefaultFontSizeInPt,\n },\n };\n if (withFill) {\n instance.properties['color'] = labelSettings.categoryLabelColor\n ? labelSettings.categoryLabelColor\n : labelSettings.labelColor;\n }\n if (fontSize) {\n instance.properties['fontSize'] = fontSize;\n }\n enumeration.pushInstance(instance);\n }\n dataLabelUtils.enumerateCategoryLabels = enumerateCategoryLabels;\n function getDisplayUnitValueFromAxisFormatter(axisFormatter, labelSettings) {\n if (axisFormatter && axisFormatter.displayUnit && labelSettings.displayUnits === 0)\n return axisFormatter.displayUnit.value;\n return null;\n }\n function createColumnFormatterCacheManager() {\n return {\n cache: { defaultFormatter: null, },\n getOrCreate: function (formatString, labelSetting, value2) {\n if (formatString) {\n var cacheKeyObject = {\n formatString: formatString,\n displayUnits: labelSetting.displayUnits,\n precision: getLabelPrecision(labelSetting.precision, formatString),\n value2: value2\n };\n var cacheKey = JSON.stringify(cacheKeyObject);\n if (!this.cache[cacheKey])\n this.cache[cacheKey] = visuals.valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, cacheKeyObject.precision));\n return this.cache[cacheKey];\n }\n if (!this.cache.defaultFormatter) {\n this.cache.defaultFormatter = visuals.valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, labelSetting.precision));\n }\n return this.cache.defaultFormatter;\n }\n };\n }\n dataLabelUtils.createColumnFormatterCacheManager = createColumnFormatterCacheManager;\n function getOptionsForLabelFormatter(labelSetting, formatString, value2, precision) {\n return {\n displayUnitSystemType: powerbi.DisplayUnitSystemType.DataLabels,\n format: formatString,\n precision: precision,\n value: labelSetting.displayUnits,\n value2: value2,\n allowFormatBeautification: true,\n };\n }\n dataLabelUtils.getOptionsForLabelFormatter = getOptionsForLabelFormatter;\n function isTextWidthOverflows(textWidth, maxTextWidth) {\n return textWidth > maxTextWidth;\n }\n dataLabelUtils.isTextWidthOverflows = isTextWidthOverflows;\n ;\n function isTextHeightOverflows(textHeight, innerChordLength) {\n return textHeight > innerChordLength;\n }\n dataLabelUtils.isTextHeightOverflows = isTextHeightOverflows;\n ;\n })(dataLabelUtils = visuals.dataLabelUtils || (visuals.dataLabelUtils = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var DonutLabelUtils;\n (function (DonutLabelUtils) {\n DonutLabelUtils.LineStrokeWidth = 1;\n DonutLabelUtils.DiagonalLineIndex = 0;\n DonutLabelUtils.HorizontalLineIndex = 1;\n function getLabelLeaderLineForDonutChart(donutArcDescriptor, donutProperties, parentPoint, sliceArc) {\n if (sliceArc === void 0) { sliceArc = 0; }\n var innerLinePointMultiplier = 2.05;\n var textPoint;\n var midPoint;\n var chartPoint;\n // Label position has changed\n if (sliceArc) {\n var arc = sliceArc;\n var outerRadius = donutProperties.radius * donutProperties.outerArcRadiusRatio;\n var innerRadius = (donutProperties.radius / 2) * donutProperties.innerArcRadiusRatio;\n midPoint = [Math.cos(arc) * outerRadius, Math.sin(arc) * outerRadius];\n chartPoint = [Math.cos(arc) * innerRadius, Math.sin(arc) * innerRadius];\n }\n else {\n midPoint = donutProperties.outerArc.centroid(donutArcDescriptor);\n chartPoint = donutProperties.arc.centroid(donutArcDescriptor);\n }\n var textPointX = parentPoint.x;\n var lineMargin = visuals.NewDataLabelUtils.maxLabelOffset / 2;\n textPointX += textPointX < 0 ? -lineMargin : lineMargin;\n textPoint = [textPointX, parentPoint.y];\n chartPoint[0] *= innerLinePointMultiplier;\n chartPoint[1] *= innerLinePointMultiplier;\n return [chartPoint, midPoint, textPoint];\n }\n DonutLabelUtils.getLabelLeaderLineForDonutChart = getLabelLeaderLineForDonutChart;\n /** We calculate the rectangles of the leader lines for collision detection\n *width: x2 - x1; height: y2 - y1 */\n function getLabelLeaderLinesSizeForDonutChart(leaderLinePoints) {\n if (leaderLinePoints && leaderLinePoints.length > 2) {\n var diagonalLineSize = {\n width: Math.abs(leaderLinePoints[1][0] - leaderLinePoints[0][0]),\n height: Math.abs(leaderLinePoints[1][1] - leaderLinePoints[0][1]),\n };\n // For horizontal line we set 1 in the height\n var horizontalLineSize = {\n width: Math.abs(leaderLinePoints[2][0] - leaderLinePoints[1][0]),\n height: DonutLabelUtils.LineStrokeWidth,\n };\n return [diagonalLineSize, horizontalLineSize];\n }\n return null;\n }\n DonutLabelUtils.getLabelLeaderLinesSizeForDonutChart = getLabelLeaderLinesSizeForDonutChart;\n function getXPositionForDonutLabel(textPointX) {\n var margin = textPointX < 0 ? -visuals.NewDataLabelUtils.maxLabelOffset : visuals.NewDataLabelUtils.maxLabelOffset;\n return textPointX += margin;\n }\n DonutLabelUtils.getXPositionForDonutLabel = getXPositionForDonutLabel;\n function getSpaceAvailableForDonutLabels(labelXPos, viewport) {\n return viewport.width / 2 - Math.abs(labelXPos) - visuals.NewDataLabelUtils.maxLabelOffset;\n }\n DonutLabelUtils.getSpaceAvailableForDonutLabels = getSpaceAvailableForDonutLabels;\n })(DonutLabelUtils = visuals.DonutLabelUtils || (visuals.DonutLabelUtils = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n var NewDataLabelUtils;\n (function (NewDataLabelUtils) {\n NewDataLabelUtils.DefaultLabelFontSizeInPt = 9;\n NewDataLabelUtils.MapPolylineOpacity = 0.5;\n NewDataLabelUtils.LabelDensityBufferFactor = 3;\n NewDataLabelUtils.LabelDensityPadding = 6;\n NewDataLabelUtils.LabelDensityMin = 0;\n NewDataLabelUtils.LabelDensityMax = 6;\n NewDataLabelUtils.startingLabelOffset = 8;\n NewDataLabelUtils.maxLabelOffset = 8;\n NewDataLabelUtils.maxLabelWidth = 50;\n NewDataLabelUtils.hundredPercentFormat = '0.00 %;-0.00 %;0.00 %';\n NewDataLabelUtils.LabelTextProperties = {\n fontFamily: 'wf_standard-font',\n fontSize: PixelConverter.fromPoint(NewDataLabelUtils.DefaultLabelFontSizeInPt),\n fontWeight: 'normal',\n };\n NewDataLabelUtils.defaultLabelColor = \"#777777\";\n NewDataLabelUtils.defaultInsideLabelColor = \"#ffffff\"; //white\n NewDataLabelUtils.horizontalLabelBackgroundPadding = 4;\n NewDataLabelUtils.verticalLabelBackgroundPadding = 2;\n var labelBackgroundRounding = 4;\n var defaultLabelPrecision = undefined;\n var defaultCountLabelPrecision = 0;\n NewDataLabelUtils.labelGraphicsContextClass = createClassAndSelector('labelGraphicsContext');\n NewDataLabelUtils.labelBackgroundGraphicsContextClass = createClassAndSelector('labelBackgroundGraphicsContext');\n var labelsClass = createClassAndSelector('label');\n var secondLineLabelClass = createClassAndSelector('label-second-line');\n var linesGraphicsContextClass = createClassAndSelector('leader-lines');\n var lineClass = createClassAndSelector('line-label');\n function drawDefaultLabels(context, dataLabels, numeric, twoRows, hasTooltip) {\n if (numeric === void 0) { numeric = false; }\n if (twoRows === void 0) { twoRows = false; }\n if (hasTooltip === void 0) { hasTooltip = false; }\n var filteredDataLabels = _.filter(dataLabels, function (d) { return d.isVisible; });\n var labels = context.selectAll(labelsClass.selector)\n .data(filteredDataLabels, labelKeyFunction);\n labels.enter()\n .append(\"text\")\n .classed(labelsClass.class, true);\n var labelAttr = {\n x: function (d) {\n return (d.boundingBox.left + (d.boundingBox.width / 2));\n },\n y: function (d) {\n if (d.hasBackground)\n return d.boundingBox.top + d.boundingBox.height - NewDataLabelUtils.verticalLabelBackgroundPadding;\n else\n return d.boundingBox.top + d.boundingBox.height;\n },\n dy: \"-0.15em\",\n };\n if (numeric) {\n labelAttr.dy = undefined;\n }\n labels\n .text(function (d) { return d.text; })\n .attr(labelAttr)\n .style({\n 'fill': function (d) { return d.fill; },\n 'font-size': function (d) { return PixelConverter.fromPoint(d.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt); },\n 'text-anchor': function (d) { return d.textAnchor; },\n });\n labels.exit()\n .remove();\n var filteredCategoryLabels = _.filter(twoRows ? dataLabels : [], function (d) { return d.isVisible && !_.isEmpty(d.secondRowText); });\n var secondLineLabels = context.selectAll(secondLineLabelClass.selector)\n .data(filteredCategoryLabels, function (d, index) { return d.identity ? d.identity.getKeyWithoutHighlight() : index; });\n secondLineLabels.enter()\n .append(\"text\")\n .classed(secondLineLabelClass.class, true);\n labelAttr = {\n x: function (d) {\n return (d.boundingBox.left + (d.boundingBox.width / 2));\n },\n y: function (d) {\n var boundingBoxHeight = (d.text !== undefined) ? d.boundingBox.height / 2 : d.boundingBox.height;\n if (d.hasBackground)\n return d.boundingBox.top + boundingBoxHeight - NewDataLabelUtils.verticalLabelBackgroundPadding;\n else\n return d.boundingBox.top + boundingBoxHeight;\n },\n dy: \"-0.15em\",\n };\n if (numeric) {\n labelAttr.dy = undefined;\n }\n secondLineLabels\n .text(function (d) { return d.secondRowText; })\n .attr(labelAttr)\n .style({\n 'fill': function (d) { return d.fill; },\n 'font-size': function (d) { return PixelConverter.fromPoint(d.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt); },\n 'text-anchor': function (d) { return d.textAnchor; },\n });\n secondLineLabels.exit()\n .remove();\n if (hasTooltip) {\n labels.append('title').text(function (d) { return d.tooltip; });\n secondLineLabels.append('title').text(function (d) { return d.tooltip; });\n labels.style(\"pointer-events\", \"all\");\n secondLineLabels.style(\"pointer-events\", \"all\");\n }\n return labels;\n }\n NewDataLabelUtils.drawDefaultLabels = drawDefaultLabels;\n function animateDefaultLabels(context, dataLabels, duration, numeric, easeType) {\n if (numeric === void 0) { numeric = false; }\n if (easeType === void 0) { easeType = 'cubic-in-out'; }\n var labels = context.selectAll(labelsClass.selector)\n .data(_.filter(dataLabels, function (d) { return d.isVisible; }), labelKeyFunction);\n labels.enter()\n .append(\"text\")\n .classed(labelsClass.class, true)\n .style('opacity', 0);\n var labelAttr = {\n x: function (d) {\n return (d.boundingBox.left + (d.boundingBox.width / 2));\n },\n y: function (d) {\n return d.boundingBox.top + d.boundingBox.height;\n },\n dy: \"-0.15em\",\n };\n if (numeric) {\n labelAttr.dy = undefined;\n }\n labels.text(function (d) { return d.text; })\n .style({\n 'fill': function (d) { return d.fill; },\n 'font-size': function (d) { return PixelConverter.fromPoint(d.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt); },\n })\n .transition()\n .ease(easeType)\n .duration(duration)\n .attr(labelAttr)\n .style('opacity', 1);\n labels.exit()\n .transition()\n .duration(duration)\n .style('opacity', 0)\n .remove();\n return labels;\n }\n NewDataLabelUtils.animateDefaultLabels = animateDefaultLabels;\n /** Draws black rectangles based on the bounding bx of labels, to be used in debugging */\n function drawLabelBackground(context, dataLabels, fill, fillOpacity) {\n var labelRects = context.selectAll(\"rect\")\n .data(_.filter(dataLabels, function (d) { return d.isVisible; }), labelKeyFunction);\n labelRects.enter()\n .append(\"rect\");\n labelRects\n .attr({\n x: function (d) {\n return d.boundingBox.left - NewDataLabelUtils.horizontalLabelBackgroundPadding;\n },\n y: function (d) {\n return d.boundingBox.top - NewDataLabelUtils.verticalLabelBackgroundPadding;\n },\n rx: labelBackgroundRounding,\n ry: labelBackgroundRounding,\n width: function (d) {\n return d.boundingBox.width + 2 * NewDataLabelUtils.horizontalLabelBackgroundPadding;\n },\n height: function (d) {\n if (d.text === undefined && d.secondRowText === undefined) {\n return 0;\n }\n return d.boundingBox.height + 2 * NewDataLabelUtils.verticalLabelBackgroundPadding;\n },\n })\n .style(\"fill\", fill ? fill : \"#000000\")\n .style(\"fill-opacity\", fillOpacity != null ? fillOpacity : 1);\n labelRects.exit()\n .remove();\n return labelRects;\n }\n NewDataLabelUtils.drawLabelBackground = drawLabelBackground;\n function drawLabelLeaderLines(context, filteredDataLabels, key, leaderLineColor) {\n if (context.select(linesGraphicsContextClass.selector).empty())\n context.append('g').classed(linesGraphicsContextClass.class, true);\n var lines = context.select(linesGraphicsContextClass.selector).selectAll('polyline')\n .data(filteredDataLabels, key);\n lines.enter()\n .append('polyline')\n .classed(lineClass.class, true);\n lines\n .attr('points', function (d) {\n return d.leaderLinePoints;\n }).\n style({\n 'stroke': function (d) { return leaderLineColor ? leaderLineColor : d.fill; },\n 'stroke-width': visuals.DonutLabelUtils.LineStrokeWidth,\n });\n lines\n .exit()\n .remove();\n }\n NewDataLabelUtils.drawLabelLeaderLines = drawLabelLeaderLines;\n function getLabelFormattedText(label, format, formatter) {\n return formatter ? formatter.format(label) : powerbi.formattingService.formatValue(label, format);\n }\n NewDataLabelUtils.getLabelFormattedText = getLabelFormattedText;\n function getDisplayUnitValueFromAxisFormatter(axisFormatter, labelSettings) {\n if (axisFormatter && axisFormatter.displayUnit && labelSettings.displayUnits === 0)\n return axisFormatter.displayUnit.value;\n return null;\n }\n NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter = getDisplayUnitValueFromAxisFormatter;\n function getLabelPrecision(precision, format) {\n debug.assertAnyValue(format, 'format');\n if (precision !== defaultLabelPrecision)\n return precision;\n if (format) {\n // Calculate precision from positive format by default\n var positiveFormat = format.split(\";\")[0];\n var formatMetadata = powerbi.NumberFormat.getCustomFormatMetadata(positiveFormat, true /*calculatePrecision*/);\n if (formatMetadata.hasDots) {\n return formatMetadata.precision;\n }\n }\n // For count fields we do not want a precision by default\n return defaultCountLabelPrecision;\n }\n function createColumnFormatterCacheManager() {\n return {\n cache: { defaultFormatter: null, },\n getOrCreate: function (formatString, labelSetting, value2) {\n if (formatString) {\n var cacheKeyObject = {\n formatString: formatString,\n displayUnits: labelSetting.displayUnits,\n precision: getLabelPrecision(labelSetting.precision, formatString),\n value2: value2\n };\n var cacheKey = JSON.stringify(cacheKeyObject);\n if (!this.cache[cacheKey])\n this.cache[cacheKey] = visuals.valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, cacheKeyObject.precision));\n return this.cache[cacheKey];\n }\n if (!this.cache.defaultFormatter) {\n this.cache.defaultFormatter = visuals.valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, labelSetting.precision));\n }\n return this.cache.defaultFormatter;\n }\n };\n }\n NewDataLabelUtils.createColumnFormatterCacheManager = createColumnFormatterCacheManager;\n function getOptionsForLabelFormatter(labelSetting, formatString, value2, precision) {\n return {\n displayUnitSystemType: powerbi.DisplayUnitSystemType.DataLabels,\n format: formatString,\n precision: precision,\n value: labelSetting.displayUnits,\n value2: value2,\n allowFormatBeautification: true,\n };\n }\n function removeDuplicates(labelDataPoints) {\n var uniqueLabelDataPoints = [];\n var labelDataPointMap = {};\n var sameParentIsInArray = function (newValue, array, parentIsRect) {\n return array.some(function (arrayValue) {\n if (parentIsRect) {\n return visuals.shapes.Rect.equals(newValue.parentShape.rect, arrayValue.rect);\n }\n else {\n return visuals.shapes.Point.equals(newValue.parentShape.point, arrayValue.point);\n }\n });\n };\n for (var _i = 0, labelDataPoints_1 = labelDataPoints; _i < labelDataPoints_1.length; _i++) {\n var dataPoint = labelDataPoints_1[_i];\n var parentIsRect = dataPoint.parentType === 1 /* Rectangle */;\n var resultsFromMap = labelDataPointMap[dataPoint.text];\n if (!resultsFromMap) {\n uniqueLabelDataPoints.push(dataPoint);\n labelDataPointMap[dataPoint.text] = [dataPoint.parentShape];\n }\n else {\n if (!sameParentIsInArray(dataPoint, resultsFromMap, parentIsRect)) {\n uniqueLabelDataPoints.push(dataPoint);\n resultsFromMap.push(dataPoint.parentShape);\n }\n }\n }\n return uniqueLabelDataPoints;\n }\n NewDataLabelUtils.removeDuplicates = removeDuplicates;\n function getDataLabelLayoutOptions(type) {\n switch (type) {\n case 9 /* Scatter */:\n return {\n maximumOffset: visuals.ScatterChart.dataLabelLayoutMaximumOffset,\n startingOffset: visuals.ScatterChart.dataLabelLayoutStartingOffset,\n offsetIterationDelta: visuals.ScatterChart.dataLabelLayoutOffsetIterationDelta,\n allowLeaderLines: true,\n attemptToMoveLabelsIntoViewport: true,\n };\n default:\n return {\n maximumOffset: NewDataLabelUtils.maxLabelOffset,\n startingOffset: NewDataLabelUtils.startingLabelOffset,\n attemptToMoveLabelsIntoViewport: true,\n };\n }\n }\n NewDataLabelUtils.getDataLabelLayoutOptions = getDataLabelLayoutOptions;\n function getTextSize(text, fontSize) {\n var labelTextProperties = NewDataLabelUtils.LabelTextProperties;\n var properties = {\n text: text,\n fontFamily: labelTextProperties.fontFamily,\n fontSize: jsCommon.PixelConverter.fromPoint(fontSize),\n fontWeight: labelTextProperties.fontWeight,\n };\n return {\n width: powerbi.TextMeasurementService.measureSvgTextWidth(properties),\n height: powerbi.TextMeasurementService.estimateSvgTextHeight(properties),\n };\n }\n NewDataLabelUtils.getTextSize = getTextSize;\n /**\n * Obtains the key from the label. Index is required to use as a backup in cases\n * where labels have no key or identity.\n */\n function labelKeyFunction(label, index) {\n if (label.key) {\n return label.key;\n }\n if (label.identity) {\n return label.identity.getKeyWithoutHighlight();\n }\n return index;\n }\n })(NewDataLabelUtils = visuals.NewDataLabelUtils || (visuals.NewDataLabelUtils = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var KpiUtil;\n (function (KpiUtil) {\n var KPIImageClassName = 'powervisuals-glyph';\n var BigImageClassName = 'big-kpi';\n var RYGStatusIconClassNames = ['kpi-red', 'kpi-yellow', 'kpi-green'];\n var threeLights = {\n kpiIconClass: 'circle',\n statusValues: RYGStatusIconClassNames,\n };\n var roadSigns = {\n kpiIconClass: '',\n statusValues: ['circle-x kpi-red', 'circle-exclamation kpi-yellow', 'circle-checkmark kpi-green'],\n };\n var trafficLight = {\n kpiIconClass: 'traffic-light',\n statusValues: RYGStatusIconClassNames,\n };\n var shapes = {\n kpiIconClass: '',\n statusValues: ['rhombus kpi-red', 'triangle kpi-yellow', 'circle kpi-green'],\n };\n var gauge = {\n kpiIconClass: '',\n statusValues: ['circle-empty', 'circle-one-quarter', 'circle-half', 'circle-three-quarters', 'circle-full'],\n };\n var statusGraphicFormatStrings = {\n 'THREE CIRCLES COLORED': threeLights,\n 'TRAFFIC LIGHT - SINGLE': threeLights,\n 'THREE FLAGS COLORED': {\n kpiIconClass: 'flag',\n statusValues: RYGStatusIconClassNames,\n },\n 'ROAD SIGNS': roadSigns,\n 'THREE SYMBOLS CIRCLED COLORED': roadSigns,\n 'TRAFFIC LIGHT': trafficLight,\n 'THREE TRAFFIC LIGHTS RIMMED COLORED': trafficLight,\n 'THREE SYMBOLS UNCIRCLED COLORED': {\n kpiIconClass: '',\n statusValues: ['x kpi-red', 'exclamation kpi-yellow', 'checkmark kpi-green'],\n },\n 'SHAPES': shapes,\n 'SMILEY FACE': shapes,\n 'THERMOMETER': shapes,\n 'CYLINDER': shapes,\n 'THREE SIGNS COLORED': shapes,\n 'THREE STARS COLORED': {\n kpiIconClass: 'star-stacked',\n statusValues: ['star-empty', 'star-half-full', 'star-full'],\n },\n 'FIVE BARS COLORED': {\n kpiIconClass: 'bars-stacked',\n statusValues: ['bars-zero', 'bars-one', 'bars-two', 'bars-three', 'bars-four'],\n },\n 'FIVE BOXES COLORED': {\n kpiIconClass: 'boxes-stacked',\n statusValues: ['boxes-zero', 'boxes-one', 'boxes-two', 'boxes-three', 'boxes-four'],\n },\n 'FIVE QUARTERS COLORED': gauge,\n 'GAUGE - ASCENDING': gauge,\n 'GAUGE - DESCENDING': {\n kpiIconClass: '',\n statusValues: ['circle-full', 'circle-three-quarters', 'circle-half', 'circle-one-quarter', 'circle-empty'],\n },\n 'STANDARD ARROW': {\n kpiIconClass: '',\n statusValues: ['arrow-down', 'arrow-right-down', 'arrow-right', 'arrow-right-up', 'arrow-up'],\n },\n 'VARIANCE ARROW': {\n kpiIconClass: '',\n statusValues: ['arrow-down kpi-red', 'arrow-right kpi-yellow', 'arrow-up kpi-green'],\n },\n 'STATUS ARROW - ASCENDING': {\n kpiIconClass: '',\n statusValues: ['arrow-down kpi-red', 'arrow-right-down kpi-yellow', 'arrow-right kpi-yellow', 'arrow-right-up kpi-yellow', 'arrow-up kpi-green'],\n },\n 'STATUS ARROW - DESCENDING': {\n kpiIconClass: '',\n statusValues: ['arrow-up kpi-green', 'arrow-right-up kpi-yellow', 'arrow-right kpi-yellow', 'arrow-right-down kpi-yellow', 'arrow-down kpi-red'],\n },\n };\n function getKpiIcon(kpi, value) {\n var numValue = parseFloat(value);\n if (!kpi)\n return;\n var statusGraphicFormat = statusGraphicFormatStrings[kpi.graphic.toUpperCase()];\n if (!statusGraphicFormat || isNaN(numValue))\n return undefined;\n var statusValues = statusGraphicFormat.statusValues;\n // Normalize range of (-1, -0.5, 0, 0.5, 1) to (-2, -1, 0, 1, 2)\n if (kpi.normalizedFiveStateKpiRange && statusValues.length === 5)\n numValue = numValue * 2;\n // Convert values from the range of (-n/2, ..., 0, ..., n/2) to (0, 1, ..., n-1)\n var num = numValue + Math.floor(statusValues.length / 2);\n return [statusGraphicFormat.kpiIconClass, statusValues[num]].join(' ').trim();\n }\n function getKpiIconClassName(kpiIcon, kpiImageSize) {\n if (!kpiIcon)\n return undefined;\n if (kpiImageSize === 1 /* Big */)\n return [KPIImageClassName, BigImageClassName, kpiIcon].join(' ');\n else\n return [KPIImageClassName, kpiIcon].join(' ');\n }\n function getClassForKpi(kpi, value, kpiImageSize) {\n debug.assertValue(kpi, 'kpi');\n debug.assertValue(value, 'value');\n var kpiIcon = getKpiIcon(kpi, value);\n return getKpiIconClassName(kpiIcon, kpiImageSize);\n }\n KpiUtil.getClassForKpi = getClassForKpi;\n function getKpiImageMetadata(metaDataColumn, value, kpiImageSize) {\n var kpi = metaDataColumn && metaDataColumn.kpi;\n if (kpi) {\n var kpiIcon = getKpiIcon(kpi, value);\n if (kpiIcon) {\n return {\n caption: kpiIcon,\n statusGraphic: kpi.graphic,\n class: getKpiIconClassName(kpiIcon, kpiImageSize),\n };\n }\n }\n }\n KpiUtil.getKpiImageMetadata = getKpiImageMetadata;\n })(KpiUtil = visuals.KpiUtil || (visuals.KpiUtil = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var ReferenceLineHelper;\n (function (ReferenceLineHelper) {\n ReferenceLineHelper.referenceLineProps = {\n show: 'show',\n lineColor: 'lineColor',\n transparency: 'transparency',\n value: 'value',\n style: 'style',\n position: 'position',\n dataLabelShow: 'dataLabelShow',\n dataLabelColor: 'dataLabelColor',\n dataLabelDecimalPoints: 'dataLabelDecimalPoints',\n dataLabelHorizontalPosition: 'dataLabelHorizontalPosition',\n dataLabelVerticalPosition: 'dataLabelVerticalPosition',\n dataLabelDisplayUnits: 'dataLabelDisplayUnits',\n };\n function enumerateObjectInstances(enumeration, referenceLines, defaultColor, objectName) {\n debug.assertValue(enumeration, 'enumeration');\n if (_.isEmpty(referenceLines)) {\n // NOTE: We do not currently have support for object maps in the property pane. For now we will generate a single reference line \n // object that the format pane can handle.In the future we will need property pane support for multiple reference lines. Also, we're\n // assuming that the user-defined IDs will be numeric strings, this may change in the future and will likley be controlled by the property pane.\n var instance = {\n selector: {\n id: '0'\n },\n properties: {\n show: false,\n value: '',\n lineColor: { solid: { color: defaultColor } },\n transparency: 50,\n style: visuals.lineStyle.dashed,\n position: visuals.referenceLinePosition.back,\n dataLabelShow: false,\n },\n objectName: objectName\n };\n enumeration.pushInstance(instance);\n return;\n }\n for (var _i = 0, referenceLines_1 = referenceLines; _i < referenceLines_1.length; _i++) {\n var referenceLine = referenceLines_1[_i];\n var referenceLineProperties = referenceLine.object;\n var show = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.show, false);\n var value = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.value);\n var lineColor = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.lineColor, { solid: { color: defaultColor } });\n var transparency = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.transparency, 50);\n var style = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.style, visuals.lineStyle.dashed);\n var position = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.position, visuals.referenceLinePosition.back);\n var dataLabelShow = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelShow, false);\n var instance = {\n selector: {\n id: referenceLine.id\n },\n properties: {\n show: show,\n value: value,\n lineColor: lineColor,\n transparency: transparency,\n style: style,\n position: position,\n dataLabelShow: dataLabelShow,\n },\n objectName: objectName\n };\n // Show the data label properties only if the user chose to show the data label\n if (dataLabelShow) {\n var dataLabelColor = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelColor, { solid: { color: defaultColor } });\n var dataLabelHorizontalPosition = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelHorizontalPosition, visuals.referenceLineDataLabelHorizontalPosition.left);\n var dataLabelVerticalPosition = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelVerticalPosition, visuals.referenceLineDataLabelVerticalPosition.above);\n var dataLabelDecimalPoints = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelDecimalPoints, undefined) < 0\n ? undefined\n : powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelDecimalPoints, undefined);\n var dataLabelDisplayUnits = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelDisplayUnits, 0);\n instance.properties[ReferenceLineHelper.referenceLineProps.dataLabelColor] = dataLabelColor;\n instance.properties[ReferenceLineHelper.referenceLineProps.dataLabelHorizontalPosition] = dataLabelHorizontalPosition;\n instance.properties[ReferenceLineHelper.referenceLineProps.dataLabelVerticalPosition] = dataLabelVerticalPosition;\n instance.properties[ReferenceLineHelper.referenceLineProps.dataLabelDecimalPoints] = dataLabelDecimalPoints;\n instance.properties[ReferenceLineHelper.referenceLineProps.dataLabelDisplayUnits] = dataLabelDisplayUnits;\n }\n enumeration.pushInstance(instance);\n }\n }\n ReferenceLineHelper.enumerateObjectInstances = enumerateObjectInstances;\n function render(options) {\n var graphicContext = options.graphicContext;\n var axes = options.axes;\n var referenceLineProperties = options.referenceLineProperties;\n var isHorizontal = options.isHorizontal;\n var viewport = options.viewport;\n var classAndSelector = options.classAndSelector;\n var xScale = axes.x.scale;\n var yScale = axes.y1.scale;\n var refValue = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.value, 0);\n var lineColor = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.lineColor, { solid: { color: options.defaultColor } });\n var transparency = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.transparency);\n var style = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.style, visuals.lineStyle.dashed);\n var position = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.position, visuals.referenceLinePosition.back);\n var refLine = graphicContext.select(classAndSelector.selector);\n var index = $(refLine[0]).index();\n var currentPosition = index > 1 ? visuals.referenceLinePosition.front : visuals.referenceLinePosition.back;\n var isRefLineExists = index !== -1;\n var isPositionChanged = currentPosition !== position;\n if (isRefLineExists && isPositionChanged)\n refLine.remove();\n if (!isRefLineExists || isPositionChanged)\n refLine = (position === visuals.referenceLinePosition.back) ? graphicContext.insert('line', \":first-child\") : graphicContext.append('line');\n var refLineX1 = isHorizontal ? 0 : xScale(refValue);\n var refLineY1 = isHorizontal ? yScale(refValue) : 0;\n var refLineX2 = isHorizontal ? viewport.width : xScale(refValue);\n var refLineY2 = isHorizontal ? yScale(refValue) : viewport.height;\n refLine.attr({\n 'class': classAndSelector.class,\n x1: refLineX1,\n y1: refLineY1,\n x2: refLineX2,\n y2: refLineY2,\n })\n .style({\n 'stroke': lineColor.solid.color,\n });\n if (transparency != null)\n refLine.style('stroke-opacity', ((100 - transparency) / 100));\n if (style === visuals.lineStyle.dashed) {\n refLine.style('stroke-dasharray', (\"5, 5\"));\n }\n else if (style === visuals.lineStyle.dotted) {\n refLine.style({\n 'stroke-dasharray': (\"1, 5\"),\n 'stroke-linecap': \"round\"\n });\n }\n else if (style === visuals.lineStyle.solid) {\n refLine.style({\n 'stroke-dasharray': null,\n 'stroke-linecap': null\n });\n }\n }\n ReferenceLineHelper.render = render;\n function createLabelDataPoint(options) {\n var offsetRefLine = 5;\n var axes = options.axes;\n var referenceLineProperties = options.referenceLineProperties;\n var isHorizontal = options.isHorizontal;\n var viewport = options.viewport;\n var xScale = axes.x.scale;\n var yScale = axes.y1.scale;\n // Get the data label properties \n var refValue = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.value, 0);\n var color = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelColor, { solid: { color: options.defaultColor } });\n var decimalPoints = (referenceLineProperties[ReferenceLineHelper.referenceLineProps.dataLabelDecimalPoints] < 0 ? undefined : referenceLineProperties[ReferenceLineHelper.referenceLineProps.dataLabelDecimalPoints]);\n var horizontalPosition = referenceLineProperties[ReferenceLineHelper.referenceLineProps.dataLabelHorizontalPosition] || visuals.referenceLineDataLabelHorizontalPosition.left;\n var verticalPosition = referenceLineProperties[ReferenceLineHelper.referenceLineProps.dataLabelVerticalPosition] || visuals.referenceLineDataLabelVerticalPosition.above;\n var displayUnits = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.dataLabelDisplayUnits, 0);\n // Format the reference line data label text according to the matching axis formatter\n // When options is null default formatter is used either boolean, numeric, or text\n var axisFormatter = isHorizontal ? axes.y1.formatter : axes.x.formatter;\n var formatterForReferenceLineDataLabel = axisFormatter;\n if (axisFormatter.options != null) {\n var formatterOptions = powerbi.Prototype.inherit(axisFormatter.options);\n formatterOptions.precision = decimalPoints;\n formatterOptions.value = displayUnits;\n formatterOptions.detectAxisPrecision = false;\n formatterForReferenceLineDataLabel = visuals.valueFormatter.create(formatterOptions);\n }\n var text = visuals.NewDataLabelUtils.getLabelFormattedText(formatterForReferenceLineDataLabel.format(refValue));\n var properties = {\n text: text,\n fontFamily: visuals.dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: visuals.dataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: visuals.dataLabelUtils.LabelTextProperties.fontWeight,\n };\n // Get the height and with of the text element that will be created in order to place it correctly\n var rectWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var rectHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties);\n var dataLabelX;\n var dataLabelY;\n var x1 = isHorizontal ? 0 : xScale(refValue);\n var y1 = isHorizontal ? yScale(refValue) : 0;\n var x2 = isHorizontal ? viewport.width : xScale(refValue);\n var y2 = isHorizontal ? yScale(refValue) : viewport.height;\n var validPositions = [1 /* Above */];\n if (isHorizontal) {\n // Horizontal line. y1 = y2\n dataLabelX = (horizontalPosition === visuals.referenceLineDataLabelHorizontalPosition.left) ? x1 + offsetRefLine : x2 - (rectWidth / 2) - offsetRefLine;\n dataLabelY = y1;\n validPositions = (verticalPosition === visuals.referenceLineDataLabelVerticalPosition.above) ? [1 /* Above */] : [2 /* Below */];\n }\n else {\n // Vertical line. x1 = x2 \n dataLabelX = x1;\n dataLabelY = (verticalPosition === visuals.referenceLineDataLabelVerticalPosition.above) ? y1 + (rectHeight / 2) + offsetRefLine : y2 - (rectHeight / 2) - offsetRefLine;\n validPositions = (horizontalPosition === visuals.referenceLineDataLabelHorizontalPosition.left) ? [4 /* Left */] : [8 /* Right */];\n }\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\n var parentShape;\n parentShape = {\n point: {\n x: dataLabelX,\n y: dataLabelY,\n },\n radius: 0,\n validPositions: validPositions,\n };\n return {\n isPreferred: true,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: color.solid.color,\n insideFill: null,\n parentShape: parentShape,\n parentType: 0 /* Point */,\n fontSize: 9,\n identity: null,\n secondRowText: null,\n key: options.key,\n };\n }\n ReferenceLineHelper.createLabelDataPoint = createLabelDataPoint;\n function extractReferenceLineValue(referenceLineProperties) {\n var referenceLineValue = null;\n if (referenceLineProperties && powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.show, false))\n referenceLineValue = powerbi.DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.value, null);\n return referenceLineValue;\n }\n ReferenceLineHelper.extractReferenceLineValue = extractReferenceLineValue;\n })(ReferenceLineHelper = visuals.ReferenceLineHelper || (visuals.ReferenceLineHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var InteractivityUtils;\n (function (InteractivityUtils) {\n function getPositionOfLastInputEvent() {\n return {\n x: d3.event.clientX,\n y: d3.event.clientY\n };\n }\n InteractivityUtils.getPositionOfLastInputEvent = getPositionOfLastInputEvent;\n function registerStandardInteractivityHandlers(selection, selectionHandler) {\n registerStandardSelectionHandler(selection, selectionHandler);\n registerStandardContextMenuHandler(selection, selectionHandler);\n }\n InteractivityUtils.registerStandardInteractivityHandlers = registerStandardInteractivityHandlers;\n function registerStandardSelectionHandler(selection, selectionHandler) {\n selection.on('click', function (d) { return handleSelection(d, selectionHandler); });\n }\n InteractivityUtils.registerStandardSelectionHandler = registerStandardSelectionHandler;\n function registerStandardContextMenuHandler(selection, selectionHandler) {\n selection.on('contextmenu', function (d) { return handleContextMenu(d, selectionHandler); });\n }\n InteractivityUtils.registerStandardContextMenuHandler = registerStandardContextMenuHandler;\n function registerGroupInteractivityHandlers(group, selectionHandler) {\n registerGroupSelectionHandler(group, selectionHandler);\n registerGroupContextMenuHandler(group, selectionHandler);\n }\n InteractivityUtils.registerGroupInteractivityHandlers = registerGroupInteractivityHandlers;\n function registerGroupSelectionHandler(group, selectionHandler) {\n group.on('click', function () {\n var target = d3.event.target;\n var d = d3.select(target).datum();\n handleSelection(d, selectionHandler);\n });\n }\n InteractivityUtils.registerGroupSelectionHandler = registerGroupSelectionHandler;\n function registerGroupContextMenuHandler(group, selectionHandler) {\n group.on('contextmenu', function () {\n var target = d3.event.target;\n var d = d3.select(target).datum();\n handleContextMenu(d, selectionHandler);\n });\n }\n InteractivityUtils.registerGroupContextMenuHandler = registerGroupContextMenuHandler;\n function handleContextMenu(d, selectionHandler) {\n if (d3.event.ctrlKey)\n return;\n d3.event.preventDefault();\n var position = InteractivityUtils.getPositionOfLastInputEvent();\n selectionHandler.handleContextMenu(d, position);\n }\n function handleSelection(d, selectionHandler) {\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\n }\n })(InteractivityUtils = visuals.InteractivityUtils || (visuals.InteractivityUtils = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n function getInvalidValueWarnings(dataViews, supportsNaN, supportsNegativeInfinity, supportsPositiveInfinity) {\n var checker = new InvalidDataValuesChecker(supportsNaN /*supportsNaN*/, supportsNegativeInfinity /*supportsNegativeInfinity*/, supportsPositiveInfinity /*supportsPositiveInfinity*/);\n // Show a warning if necessary.\n return checker.getWarningMessages(dataViews);\n }\n visuals.getInvalidValueWarnings = getInvalidValueWarnings;\n var InvalidDataValuesChecker = (function () {\n function InvalidDataValuesChecker(supportsNaN, supportsNegativeInfinity, supportsPositiveInfinity) {\n this.supportsNaN = supportsNaN;\n this.supportsNegativeInfinity = supportsNegativeInfinity;\n this.supportsPositiveInfinity = supportsPositiveInfinity;\n }\n InvalidDataValuesChecker.prototype.getWarningMessages = function (dataViews) {\n this.loadWarningStatus(dataViews);\n var warnings = [];\n if (this.hasNaN && !this.supportsNaN) {\n warnings.push(new visuals.NaNNotSupportedWarning());\n }\n if ((this.hasNegativeInfinity && !this.supportsNegativeInfinity)\n || (this.hasPositiveInfinity && !this.supportsPositiveInfinity)) {\n warnings.push(new visuals.InfinityValuesNotSupportedWarning());\n }\n if (this.hasOutOfRange) {\n warnings.push(new visuals.ValuesOutOfRangeWarning());\n }\n return warnings;\n };\n InvalidDataValuesChecker.prototype.loadWarningStatus = function (dataViews) {\n this.hasNaN = false;\n this.hasNegativeInfinity = false;\n this.hasOutOfRange = false;\n this.hasPositiveInfinity = false;\n for (var k = 0; k < dataViews.length; k++) {\n var dataView = dataViews[k];\n var values = dataView && dataView.categorical && dataView.categorical.values\n ? dataView.categorical.values\n : null;\n if (!values)\n return;\n var valueLength = values.length;\n for (var i = 0; i < valueLength; i++) {\n var value = values[i];\n if (value.values) {\n var valueValueLength = value.values.length;\n for (var j = 0; j < valueValueLength; j++) {\n var v = value.values[j];\n if (isNaN(v))\n this.hasNaN = true;\n else if (v === Number.POSITIVE_INFINITY)\n this.hasPositiveInfinity = true;\n else if (v === Number.NEGATIVE_INFINITY)\n this.hasNegativeInfinity = true;\n else if (v < -1e300 || v > 1e300)\n this.hasOutOfRange = true;\n }\n }\n }\n }\n };\n return InvalidDataValuesChecker;\n }());\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var ListViewFactory;\n (function (ListViewFactory) {\n function createListView(options) {\n return new ListView(options);\n }\n ListViewFactory.createListView = createListView;\n })(ListViewFactory = visuals.ListViewFactory || (visuals.ListViewFactory = {}));\n /**\n * A UI Virtualized List, that uses the D3 Enter, Update & Exit pattern to update rows.\n * It can create lists containing either HTML or SVG elements.\n */\n var ListView = (function () {\n function ListView(options) {\n var _this = this;\n // make a copy of options so that it is not modified later by caller\n this.options = $.extend(true, {}, options);\n this.scrollbarInner = options.baseContainer\n .append('div')\n .classed('scrollbar-inner', true)\n .on('scroll', function () { return _this.renderImpl(_this.options.rowHeight); });\n this.scrollContainer = this.scrollbarInner\n .append('div')\n .classed('scrollRegion', true)\n .on('touchstart', function () { return _this.stopTouchPropagation(); })\n .on('touchmove', function () { return _this.stopTouchPropagation(); });\n this.visibleGroupContainer = this.scrollContainer\n .append('div')\n .classed('visibleGroup', true);\n $(options.baseContainer.node()).find('.scroll-element').attr('drag-resize-disabled', 'true');\n ListView.SetDefaultOptions(options);\n }\n ListView.SetDefaultOptions = function (options) {\n options.rowHeight = options.rowHeight || ListView.defaultRowHeight;\n };\n ListView.prototype.rowHeight = function (rowHeight) {\n this.options.rowHeight = Math.ceil(rowHeight);\n return this;\n };\n ListView.prototype.data = function (data, getDatumIndex, dataReset) {\n if (dataReset === void 0) { dataReset = false; }\n this._data = data;\n this.getDatumIndex = getDatumIndex;\n this.setTotalRows();\n if (dataReset)\n $(this.scrollbarInner.node()).scrollTop(0);\n this.render();\n return this;\n };\n ListView.prototype.viewport = function (viewport) {\n this.options.viewport = viewport;\n this.render();\n return this;\n };\n ListView.prototype.empty = function () {\n this._data = [];\n this.render();\n };\n ListView.prototype.render = function () {\n var _this = this;\n if (this.renderTimeoutId)\n window.clearTimeout(this.renderTimeoutId);\n this.renderTimeoutId = window.setTimeout(function () {\n _this.getRowHeight().then(function (rowHeight) {\n _this.renderImpl(rowHeight);\n });\n _this.renderTimeoutId = undefined;\n }, 0);\n };\n ListView.prototype.renderImpl = function (rowHeight) {\n var totalHeight = this.options.scrollEnabled ? Math.max(0, (this._totalRows * rowHeight)) : this.options.viewport.height;\n this.scrollContainer\n .style('height', totalHeight + \"px\")\n .attr('height', totalHeight);\n this.scrollToFrame(true /*loadMoreData*/);\n };\n /*\n * This method is called in order to prevent a bug found in the Interact.js.\n * The bug is caused when finishing a scroll outside the scroll area.\n * In that case the Interact doesn't process a touchcancel event and thinks a touch point still exists.\n * since the Interact listens on the visualContainer, by stoping the propagation we prevent the bug from taking place.\n */\n ListView.prototype.stopTouchPropagation = function () {\n //Stop the propagation only in read mode so the drag won't be affected.\n if (this.options.isReadMode()) {\n if (d3.event.type === \"touchstart\") {\n var event_1 = d3.event;\n //If there is another touch point outside this visual than the event should be propagated.\n //This way the pinch to zoom will not be affected.\n if (event_1.touches && event_1.touches.length === 1) {\n d3.event.stopPropagation();\n }\n }\n if (d3.event.type === \"touchmove\") {\n d3.event.stopPropagation();\n }\n }\n };\n ListView.prototype.scrollToFrame = function (loadMoreData) {\n var options = this.options;\n var visibleGroupContainer = this.visibleGroupContainer;\n var totalRows = this._totalRows;\n var rowHeight = options.rowHeight || ListView.defaultRowHeight;\n var visibleRows = this.getVisibleRows() || 1;\n var scrollTop = this.scrollbarInner.node().scrollTop;\n var scrollPosition = (scrollTop === 0) ? 0 : Math.floor(scrollTop / rowHeight);\n var transformAttr = visuals.SVGUtil.translateWithPixels(0, scrollPosition * rowHeight);\n visibleGroupContainer.style({\n //order matters for proper overriding\n 'transform': function (d) { return transformAttr; },\n '-webkit-transform': transformAttr\n });\n var position0 = Math.max(0, Math.min(scrollPosition, totalRows - visibleRows + 1)), position1 = position0 + visibleRows;\n if (this.options.scrollEnabled) {\n // Subtract the amount of height of the top row that's hidden when it's partially visible.\n var topRowHiddenHeight = scrollTop - (scrollPosition * rowHeight);\n var halfRowHeight = rowHeight * 0.5;\n // If more than half the top row is hidden, we'll need to render an extra item at the bottom\n if (topRowHiddenHeight > halfRowHeight) {\n position1++; // Add 1 to handle when rows are partially visible (when scrolling)\n }\n }\n var rowSelection = visibleGroupContainer.selectAll(\".row\")\n .data(this._data.slice(position0, Math.min(position1, totalRows)), this.getDatumIndex);\n rowSelection\n .enter()\n .append('div')\n .classed('row', true)\n .call(function (d) { return options.enter(d); });\n rowSelection.order();\n var rowUpdateSelection = visibleGroupContainer.selectAll('.row:not(.transitioning)');\n rowUpdateSelection.call(function (d) { return options.update(d); });\n rowSelection\n .exit()\n .call(function (d) { return options.exit(d); })\n .remove();\n if (loadMoreData && visibleRows !== totalRows && position1 >= totalRows * ListView.loadMoreDataThreshold)\n options.loadMoreData();\n };\n ListView.prototype.setTotalRows = function () {\n var data = this._data;\n this._totalRows = data ? data.length : 0;\n };\n ListView.prototype.getVisibleRows = function () {\n var minimumVisibleRows = 1;\n var rowHeight = this.options.rowHeight;\n var viewportHeight = this.options.viewport.height;\n if (!rowHeight || rowHeight < 1)\n return minimumVisibleRows;\n if (this.options.scrollEnabled)\n return Math.min(Math.ceil(viewportHeight / rowHeight), this._totalRows) || minimumVisibleRows;\n return Math.min(Math.floor(viewportHeight / rowHeight), this._totalRows) || minimumVisibleRows;\n };\n ListView.prototype.getRowHeight = function () {\n var deferred = $.Deferred();\n var listView = this;\n var options = listView.options;\n if (this.cancelMeasurePass)\n this.cancelMeasurePass();\n // if there is no data, resolve and return\n if (!(this._data && this._data.length && options)) {\n listView.rowHeight(ListView.defaultRowHeight);\n return deferred.resolve(options.rowHeight).promise();\n }\n //render the first item to calculate the row height\n this.scrollToFrame(false /*loadMoreData*/);\n var requestAnimationFrameId = window.requestAnimationFrame(function () {\n //measure row height\n var rows = listView.visibleGroupContainer.select(\".row\");\n if (!rows.empty()) {\n var firstRow = rows.node();\n // If the container (child) has margins amd the row (parent) doesn't, the child's margins will collapse into the parent.\n // outerHeight doesn't report the correct height for the parent in this case, but it does measure the child properly.\n // Fix for #7497261 Measures both and take the max to work around this issue.\n var rowHeight = Math.max($(firstRow).outerHeight(true), $(firstRow).children().first().outerHeight(true));\n listView.rowHeight(rowHeight);\n deferred.resolve(rowHeight);\n }\n listView.cancelMeasurePass = undefined;\n window.cancelAnimationFrame(requestAnimationFrameId);\n });\n this.cancelMeasurePass = function () {\n window.cancelAnimationFrame(requestAnimationFrameId);\n deferred.reject();\n };\n return deferred.promise();\n };\n /**\n * The value indicates the percentage of data already shown\n * in the list view that triggers a loadMoreData call.\n */\n ListView.loadMoreDataThreshold = 0.8;\n ListView.defaultRowHeight = 1;\n return ListView;\n }());\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var defaultLevelOfDetail = 11;\n var MapUtil;\n (function (MapUtil) {\n MapUtil.Settings = {\n /** Maximum Bing requests at once. The Bing have limit how many request at once you can do per socket. */\n MaxBingRequest: 6,\n /** Maximum cache size of cached geocode data. */\n MaxCacheSize: 3000,\n /** Maximum cache overflow of cached geocode data to kick the cache reducing. */\n MaxCacheSizeOverflow: 100,\n // Bing Keys and URL\n BingKey: \"insert your key\",\n BingUrl: \"https://dev.virtualearth.net/REST/v1/Locations\",\n BingUrlGeodata: \"https://platform.bing.com/geo/spatial/v1/public/Geodata?\",\n /** Switch the data result for geodata polygons to by double array instead locations array */\n UseDoubleArrayGeodataResult: true,\n UseDoubleArrayDequeueTimeout: 0,\n };\n // Bing map min/max boundaries\n MapUtil.MinAllowedLatitude = -85.05112878;\n MapUtil.MaxAllowedLatitude = 85.05112878;\n MapUtil.MinAllowedLongitude = -180;\n MapUtil.MaxAllowedLongitude = 180;\n MapUtil.TileSize = 256;\n MapUtil.MaxLevelOfDetail = 23;\n MapUtil.MinLevelOfDetail = 1;\n MapUtil.MaxAutoZoomLevel = 5;\n MapUtil.DefaultLevelOfDetail = 11;\n MapUtil.WorkerErrorName = \"___error___\";\n MapUtil.CategoryTypes = {\n Address: \"Address\",\n City: \"City\",\n Continent: \"Continent\",\n CountryRegion: \"Country\",\n County: \"County\",\n Longitude: \"Longitude\",\n Latitude: \"Latitude\",\n Place: \"Place\",\n PostalCode: \"PostalCode\",\n StateOrProvince: \"StateOrProvince\"\n };\n var safeCharacters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-\";\n function clip(n, minValue, maxValue) {\n return Math.min(Math.max(n, minValue), maxValue);\n }\n MapUtil.clip = clip;\n function getMapSize(levelOfDetail) {\n if (levelOfDetail === 23)\n return 2147483648; //256 << 23 overflow the integer and return a negative value\n if (Math.floor(levelOfDetail) === levelOfDetail)\n return 256 << levelOfDetail;\n return 256 * Math.pow(2, levelOfDetail);\n }\n MapUtil.getMapSize = getMapSize;\n /**\n * pointArrayChunkLength Motivation:\n * When the number is too small (e.g. less than 1000) the tile is rendering but VERY SLOW,\n * when it's too high there is a risk to get \"stack overflow\" error on mobile (while joining).\n * this is the lowest number I managed to get without any noticeable slowness.\n */\n var pointArrayChunkLength = 15000;\n /**\n * @param latLongArray - is a Float64Array as [lt0, lon0, lat1, long1, lat2, long2,....]\n * @param buildString - optional, if true returns also a string as \"x0 y0 x1 y1 x2 y2 ....\"\n * @returns IPixelArrayResult with Float64Array as [x0, y0, x1, y1, x2, y2,....]\n */\n function latLongToPixelXYArray(latLongArray, levelOfDetail, buildString) {\n if (buildString === void 0) { buildString = false; }\n var helperArray = [];\n var result = {\n array: new Float64Array(latLongArray.length),\n arrayString: \"\"\n };\n for (var i = 0; i < latLongArray.length; i += 2) {\n var latitude = clip(latLongArray[i], MapUtil.MinAllowedLatitude, MapUtil.MaxAllowedLatitude);\n var longitude = clip(latLongArray[i + 1], MapUtil.MinAllowedLongitude, MapUtil.MaxAllowedLongitude);\n var x = (longitude + 180) / 360;\n var sinLatitude = Math.sin(latitude * Math.PI / 180);\n var y = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);\n var mapSize = getMapSize(levelOfDetail);\n result.array[i] = clip(x * mapSize + 0.5, 0.0, mapSize - 1);\n result.array[i + 1] = clip(y * mapSize + 0.5, 0.0, mapSize - 1);\n if (buildString) {\n helperArray.push(result.array[i], result.array[i + 1]);\n if (helperArray.length >= pointArrayChunkLength) {\n result.arrayString += helperArray.join(\" \") + \" \";\n helperArray = [];\n }\n }\n }\n if (buildString) {\n result.arrayString += helperArray.join(\" \") + \" \";\n }\n return result;\n }\n MapUtil.latLongToPixelXYArray = latLongToPixelXYArray;\n function getLocationBoundaries(latLongArray) {\n var northWest = {\n latitude: -90, longitude: 180\n };\n var southEast = {\n latitude: 90, longitude: -180\n };\n for (var i = 0; i < latLongArray.length; i += 2) {\n northWest.latitude = Math.max(latLongArray[i], northWest.latitude);\n northWest.longitude = Math.min(latLongArray[i + 1], northWest.longitude);\n southEast.latitude = Math.min(latLongArray[i], southEast.latitude);\n southEast.longitude = Math.max(latLongArray[i + 1], southEast.longitude);\n }\n northWest.longitude = clip(northWest.longitude, -180, 180);\n southEast.longitude = clip(southEast.longitude, -180, 180);\n return Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(northWest.latitude, northWest.longitude), new Microsoft.Maps.Location(southEast.latitude, southEast.longitude));\n }\n MapUtil.getLocationBoundaries = getLocationBoundaries;\n /**\n * Note: this code is taken from Bing.\n * see Point Compression Algorithm http://msdn.microsoft.com/en-us/library/jj158958.aspx\n * see Decompression Algorithm in http://msdn.microsoft.com/en-us/library/dn306801.aspx\n */\n function parseEncodedSpatialValueArray(value) {\n var list = [];\n var index = 0;\n var xsum = 0;\n var ysum = 0;\n var max = 4294967296;\n while (index < value.length) {\n var n = 0;\n var k = 0;\n while (1) {\n if (index >= value.length) {\n return null;\n }\n var b = safeCharacters.indexOf(value.charAt(index++));\n if (b === -1) {\n return null;\n }\n var tmp = ((b & 31) * (Math.pow(2, k)));\n var ht = tmp / max;\n var lt = tmp % max;\n var hn = n / max;\n var ln = n % max;\n var nl = (lt | ln) >>> 0;\n n = (ht | hn) * max + nl;\n k += 5;\n if (b < 32)\n break;\n }\n var diagonal = Math.floor((Math.sqrt(8 * n + 5) - 1) / 2);\n n -= diagonal * (diagonal + 1) / 2;\n var ny = Math.floor(n);\n var nx = diagonal - ny;\n nx = (nx >> 1) ^ -(nx & 1);\n ny = (ny >> 1) ^ -(ny & 1);\n xsum += nx;\n ysum += ny;\n var lat = ysum * 0.00001;\n var lon = xsum * 0.00001;\n list.push(lat);\n list.push(lon);\n }\n return new Float64Array(list);\n }\n MapUtil.parseEncodedSpatialValueArray = parseEncodedSpatialValueArray;\n function calcGeoData(data) {\n var locations = data.locations;\n for (var i = 0; i < locations.length; i++) {\n var location_1 = locations[i];\n if (!location_1.geographic) {\n location_1.geographic = MapUtil.parseEncodedSpatialValueArray(location_1.nativeBing);\n }\n var polygon = location_1.geographic;\n if (polygon) {\n if (!location_1.absolute) {\n var result = MapUtil.latLongToPixelXYArray(polygon, MapUtil.DefaultLevelOfDetail, true);\n location_1.absolute = result.array;\n location_1.absoluteString = result.arrayString;\n var geographicBounds = MapUtil.getLocationBoundaries(polygon);\n location_1.absoluteBounds = MapUtil.locationRectToRectXY(geographicBounds, MapUtil.DefaultLevelOfDetail);\n }\n }\n }\n }\n MapUtil.calcGeoData = calcGeoData;\n function locationToPixelXY(location, levelOfDetail) {\n return latLongToPixelXY(location.latitude, location.longitude, levelOfDetail);\n }\n MapUtil.locationToPixelXY = locationToPixelXY;\n function locationRectToRectXY(locationRect, levelOfDetail) {\n var topleft = locationToPixelXY(locationRect.getNorthwest(), levelOfDetail);\n var bottomRight = locationToPixelXY(locationRect.getSoutheast(), levelOfDetail);\n return new powerbi.visuals.Rect(topleft.x, topleft.y, bottomRight.x - topleft.x, bottomRight.y - topleft.y);\n }\n MapUtil.locationRectToRectXY = locationRectToRectXY;\n function latLongToPixelXY(latitude, longitude, levelOfDetail) {\n var array = latLongToPixelXYArray(new Float64Array([latitude, longitude]), levelOfDetail).array;\n return new powerbi.visuals.Point(array[0], array[1]);\n }\n MapUtil.latLongToPixelXY = latLongToPixelXY;\n function pixelXYToLocation(pixelX, pixelY, levelOfDetail) {\n var mapSize = getMapSize(levelOfDetail);\n var x = (clip(pixelX, 0, mapSize - 1) / mapSize) - 0.5;\n var y = 0.5 - (clip(pixelY, 0, mapSize - 1) / mapSize);\n var latitude = 90 - 360 * Math.atan(Math.exp(-y * 2 * Math.PI)) / Math.PI;\n var longitude = 360 * x;\n return new Microsoft.Maps.Location(latitude, longitude);\n }\n MapUtil.pixelXYToLocation = pixelXYToLocation;\n var CurrentLocation;\n (function (CurrentLocation) {\n function createPushpin(location) {\n var template = '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">'\n + '<circle fill=\"#FF5F00\" cx=\"12\" cy=\"12\" r=\"6\"/>'\n + '<circle fill=\"none\" stroke=\"#FF5F00\" stroke-width=\"2\" cx=\"12\" cy=\"12\" r=\"10\"/>'\n + '</svg>';\n var options = {\n draggable: false,\n htmlContent: template,\n height: 24,\n width: 24\n };\n return new Microsoft.Maps.Pushpin(location, options);\n }\n CurrentLocation.createPushpin = createPushpin;\n })(CurrentLocation = MapUtil.CurrentLocation || (MapUtil.CurrentLocation = {}));\n })(MapUtil = visuals.MapUtil || (visuals.MapUtil = {}));\n var MapPolygonInfo = (function () {\n function MapPolygonInfo() {\n this._locationRect = new Microsoft.Maps.LocationRect(new Microsoft.Maps.Location(30, -30), 60, 60);\n }\n MapPolygonInfo.prototype.reCalc = function (mapControl, width, height) {\n var baseLocations = [this._locationRect.getNorthwest(), this._locationRect.getSoutheast()];\n width = width / 2.00;\n height = height / 2.00;\n if (!this._baseRect) {\n var l0 = MapUtil.locationToPixelXY(this._locationRect.getNorthwest(), defaultLevelOfDetail);\n var l1 = MapUtil.locationToPixelXY(this._locationRect.getSoutheast(), defaultLevelOfDetail);\n this._baseRect = new visuals.Rect(l0.x, l0.y, l1.x - l0.x, l1.y - l0.y);\n }\n var l = mapControl.tryLocationToPixel(baseLocations);\n this._currentRect = new visuals.Rect(l[0].x + width, l[0].y + height, l[1].x - l[0].x, l[1].y - l[0].y);\n };\n Object.defineProperty(MapPolygonInfo.prototype, \"scale\", {\n get: function () {\n if (this._baseRect) {\n return this._currentRect.width / this._baseRect.width;\n }\n return 1.0;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(MapPolygonInfo.prototype, \"transform\", {\n get: function () {\n var base = this._baseRect;\n var current = this._currentRect;\n var transform = new visuals.Transform();\n transform.translate(current.left, current.top);\n transform.scale((current.width / base.width), (current.height / base.height));\n transform.translate(-base.left, -base.top);\n return transform;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(MapPolygonInfo.prototype, \"outherTransform\", {\n get: function () {\n var base = this._baseRect;\n var current = this._currentRect;\n var transform = new visuals.Transform();\n transform.translate(current.left, current.top);\n var scale = Math.sqrt(current.width / base.width);\n transform.scale(scale, scale);\n return transform;\n },\n enumerable: true,\n configurable: true\n });\n MapPolygonInfo.prototype.setViewBox = function (svg) {\n var rect = svg.getBoundingClientRect();\n var current = this._currentRect;\n svg.setAttribute(\"viewBox\", [-current.left, -current.top, rect.width, rect.height].join(\" \"));\n };\n Object.defineProperty(MapPolygonInfo.prototype, \"innerTransform\", {\n get: function () {\n var base = this._baseRect;\n var current = this._currentRect;\n var transform = new visuals.Transform();\n var scale = current.width / base.width;\n transform.scale(scale, scale);\n transform.translate(-base.left, -base.top);\n return transform;\n },\n enumerable: true,\n configurable: true\n });\n MapPolygonInfo.prototype.transformToString = function (transform) {\n var m = transform.matrix;\n return \"matrix(\" + m.m00 + \" \" + m.m10 + \" \" + m.m01 + \" \" + m.m11 + \" \" + m.m02 + \" \" + m.m12 + \")\";\n };\n return MapPolygonInfo;\n }());\n visuals.MapPolygonInfo = MapPolygonInfo;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var utility;\n (function (utility) {\n ;\n var SelectionManager = (function () {\n function SelectionManager(options) {\n this.hostServices = options.hostServices;\n this.selectedIds = [];\n }\n SelectionManager.prototype.select = function (selectionId, multiSelect) {\n if (multiSelect === void 0) { multiSelect = false; }\n var deferred = $.Deferred();\n if (this.hostServices.shouldRetainSelection()) {\n this.sendSelectionToHost([selectionId]);\n }\n else {\n this.selectInternal(selectionId, multiSelect);\n this.sendSelectionToHost(this.selectedIds);\n }\n deferred.resolve(this.selectedIds);\n return deferred;\n };\n SelectionManager.prototype.showContextMenu = function (selectionId, position) {\n var deferred = $.Deferred();\n position = position || visuals.InteractivityUtils.getPositionOfLastInputEvent();\n this.sendContextMenuToHost(selectionId, position);\n deferred.resolve();\n return deferred;\n };\n SelectionManager.prototype.hasSelection = function () {\n return this.selectedIds.length > 0;\n };\n SelectionManager.prototype.clear = function () {\n var deferred = $.Deferred();\n this.selectedIds = [];\n this.sendSelectionToHost([]);\n deferred.resolve();\n return deferred;\n };\n SelectionManager.prototype.getSelectionIds = function () {\n return this.selectedIds;\n };\n SelectionManager.prototype.sendSelectionToHost = function (ids) {\n var selectArgs = {\n data: ids\n .filter(function (value) { return value.hasIdentity(); })\n .map(function (value) { return value.getSelector(); })\n };\n var data2 = this.getSelectorsByColumn(ids);\n if (!_.isEmpty(data2))\n selectArgs.data2 = data2;\n this.hostServices.onSelect(selectArgs);\n };\n SelectionManager.prototype.sendContextMenuToHost = function (selectionId, position) {\n var selectors = this.getSelectorsByColumn([selectionId]);\n if (_.isEmpty(selectors))\n return;\n var args = {\n data: selectors,\n position: position\n };\n this.hostServices.onContextMenu(args);\n };\n SelectionManager.prototype.getSelectorsByColumn = function (selectionIds) {\n return _(selectionIds)\n .filter(function (value) { return value.hasIdentity; })\n .map(function (value) { return value.getSelectorsByColumn(); })\n .compact()\n .value();\n };\n SelectionManager.prototype.selectInternal = function (selectionId, multiSelect) {\n if (SelectionManager.containsSelection(this.selectedIds, selectionId)) {\n this.selectedIds = multiSelect\n ? this.selectedIds.filter(function (d) { return !powerbi.data.Selector.equals(d, selectionId); })\n : this.selectedIds.length > 1\n ? [selectionId] : [];\n }\n else {\n if (multiSelect)\n this.selectedIds.push(selectionId);\n else\n this.selectedIds = [selectionId];\n }\n };\n SelectionManager.containsSelection = function (list, id) {\n return list.some(function (d) { return powerbi.data.Selector.equals(d.getSelector(), id.getSelector()); });\n };\n return SelectionManager;\n }());\n utility.SelectionManager = SelectionManager;\n })(utility = visuals.utility || (visuals.utility = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n \"use strict\";\n var shapes;\n (function (shapes) {\n var Utility = jsCommon.Utility;\n var Polygon = (function () {\n function Polygon(absolutePoints) {\n this.polygonPoints = this.convertArrayPathToPoints(absolutePoints);\n }\n Polygon.prototype.absoluteCentroid = function () {\n if (this._absoluteCentroid == null) {\n this._absoluteCentroid = this.calculatePolygonCentroid();\n }\n return this._absoluteCentroid;\n };\n Polygon.prototype.absoluteBoundingRect = function () {\n if (this._absoluteBoundingRect == null) {\n this._absoluteBoundingRect = this.calculateBoundingRect();\n }\n return this._absoluteBoundingRect;\n };\n /**\n * Check if label text contain in polygon shape.\n *\n * @return true/false is the label fit in polygon.\n * measure if rects points are inside the polygon shape\n * return true if there is at least 3 point inside the polygon\n */\n Polygon.prototype.contains = function (rect) {\n var topLeft = { x: rect.left, y: rect.top };\n var topRight = { x: rect.left + rect.width, y: rect.top };\n var bottomLeft = { x: rect.left, y: rect.top + rect.height };\n var bottomRight = { x: rect.left + rect.width, y: rect.top + rect.height };\n return (this.inside(topLeft)\n && this.inside(topRight)\n && this.inside(bottomLeft)\n && this.inside(bottomRight));\n };\n /**\n * Check if label text is outside of polygon shape.\n * It checks 8 points in the label. TopLeft, TopCenter, TopRight, MiddleLeft, MiddleRight, BottomLeft, BottomMiddle, BottomRight\n * @return true/false is there is any conflict (at least one point inside the shape).\n */\n Polygon.prototype.conflicts = function (rect) {\n if (!this.isConflictWithBoundingBox(rect)) {\n return false;\n }\n var topLeft = { x: rect.left, y: rect.top };\n var topCenter = { x: rect.left + rect.width / 2, y: rect.top };\n var topRight = { x: rect.left + rect.width, y: rect.top };\n var bottomLeft = { x: rect.left, y: rect.top + rect.height };\n var bottomCenter = { x: rect.left + rect.width / 2, y: rect.top + rect.height };\n var bottomRight = { x: rect.left + rect.width, y: rect.top + rect.height };\n var middleLeft = { x: rect.left, y: rect.top + rect.height / 2 };\n var middleRight = { x: rect.left + rect.width, y: rect.top + rect.height / 2 };\n return (this.inside(topLeft)\n || this.inside(topCenter)\n || this.inside(topRight)\n || this.inside(bottomLeft)\n || this.inside(bottomCenter)\n || this.inside(bottomRight)\n || this.inside(middleLeft)\n || this.inside(middleRight));\n };\n /**\n * returns intersection point of a line (depicted by two points) and a polygon.\n *\n * @return the point of intersection or null if there is no intersection.\n */\n Polygon.prototype.lineIntersectionPoint = function (p0, p1) {\n for (var i = 0; i < this.polygonPoints.length; i++) {\n var p2 = this.polygonPoints[i];\n var p3 = (i === this.polygonPoints.length - 1 ? this.polygonPoints[0] : this.polygonPoints[i + 1]);\n var intersection = this.getLineIntersection(p0, p1, p2, p3);\n if (intersection !== null) {\n return intersection;\n }\n }\n return null;\n };\n /**\n * calculate Polygon Area.\n *\n * @return the area of the polygon (as number).\n */\n Polygon.calculateAbsolutePolygonArea = function (polygonPoints) {\n var i, j = 1;\n var area = 0.0;\n for (i = 0; i < polygonPoints.length; i++) {\n area += polygonPoints[i].x * polygonPoints[j].y - polygonPoints[j].x * polygonPoints[i].y;\n j = (j + 1) % polygonPoints.length;\n }\n area *= 0.5;\n return area;\n };\n /**\n * Check if label text is outside of polygon bounding box.\n *\n * @return true/false is there is any conflict (at least one point inside the shape).\n */\n Polygon.prototype.isConflictWithBoundingBox = function (rect) {\n return Rect.isIntersecting(this.absoluteBoundingRect(), rect);\n };\n /**\n * Calculate Polygon Centroid.\n *\n * @return 'center' point of the polygon.\n * calculate the polygon area\n * calculate the average points of the polygon by x & y axis.\n * divided the average point by the area\n */\n Polygon.prototype.calculatePolygonCentroid = function () {\n var area, tempPoint, cx, cy, i, j;\n /* First calculate the polygon's signed area A */\n area = Polygon.calculateAbsolutePolygonArea(this.polygonPoints);\n /* Now calculate the centroid coordinates Cx and Cy */\n cx = cy = 0.0;\n j = 1;\n for (i = 0; i < this.polygonPoints.length; i++) {\n tempPoint = this.polygonPoints[i].x * this.polygonPoints[j].y - this.polygonPoints[j].x * this.polygonPoints[i].y;\n cx += (this.polygonPoints[i].x + this.polygonPoints[j].x) * tempPoint;\n cy += (this.polygonPoints[i].y + this.polygonPoints[j].y) * tempPoint;\n j = (j + 1) % this.polygonPoints.length;\n }\n cx = cx / (6.0 * area);\n cy = cy / (6.0 * area);\n return {\n x: cx,\n y: cy,\n };\n };\n Polygon.prototype.calculateBoundingRect = function () {\n var minX = Number.POSITIVE_INFINITY;\n var minY = Number.POSITIVE_INFINITY;\n var maxX = Number.NEGATIVE_INFINITY;\n var maxY = Number.NEGATIVE_INFINITY;\n for (var i = 0; i < this.polygonPoints.length; i++) {\n if (this.polygonPoints[i].x < minX) {\n minX = this.polygonPoints[i].x;\n }\n else if (this.polygonPoints[i].x > maxX) {\n maxX = this.polygonPoints[i].x;\n }\n if (this.polygonPoints[i].y < minY) {\n minY = this.polygonPoints[i].y;\n }\n else if (this.polygonPoints[i].y > maxY) {\n maxY = this.polygonPoints[i].y;\n }\n }\n return {\n left: minX,\n top: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n };\n /**\n * Check if point exist inside polygon shape.\n *\n * @return true/false if point exist inside shape.\n * ray-casting algorithm based on:\n * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\n */\n Polygon.prototype.inside = function (point) {\n var x = point.x, y = point.y;\n var insideVar = false;\n for (var i = 0, j = this.polygonPoints.length - 1; i < this.polygonPoints.length; j = i++) {\n var xi = this.polygonPoints[i].x, yi = this.polygonPoints[i].y;\n var xj = this.polygonPoints[j].x, yj = this.polygonPoints[j].y;\n var intersect = ((yi > y) !== (yj > y))\n && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);\n if (intersect) {\n insideVar = !insideVar;\n }\n }\n return insideVar;\n };\n ;\n /**\n * Checks if a line (presented as two points) intersects with a another line\n */\n Polygon.prototype.getLineIntersection = function (line0p1, line0p2, line1p1, line1p2) {\n var p0_x = line0p1.x;\n var p0_y = line0p1.y;\n var p1_x = line0p2.x;\n var p1_y = line0p2.y;\n var p2_x = line1p1.x;\n var p2_y = line1p1.y;\n var p3_x = line1p2.x;\n var p3_y = line1p2.y;\n var s1_x = p1_x - p0_x;\n var s1_y = p1_y - p0_y;\n var s2_x = p3_x - p2_x;\n var s2_y = p3_y - p2_y;\n //Calculating collisions using cross products\n var s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);\n var t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);\n // 0<=s<=1 and 0<=t<=1 ensures that the collision is part of the original line\n if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {\n // Collision detected\n return { x: (p0_x + (t * s1_x)), y: (p0_y + (t * s1_y)) };\n }\n return null; // No collision\n };\n Polygon.prototype.convertArrayPathToPoints = function (path) {\n var pointsRes = [];\n for (var i = 0; i < path.length; i += 2) {\n var x = path[i];\n var y = path[i + 1];\n var newPoint = {\n x: x,\n y: y,\n };\n pointsRes.push(newPoint);\n }\n return pointsRes;\n };\n return Polygon;\n }());\n shapes.Polygon = Polygon;\n var Point;\n (function (Point) {\n function offset(point, offsetX, offsetY) {\n var newPointX = ((point.x + offsetX) >= 0) ? (point.x + offsetX) : 0;\n var newPointY = ((point.y + offsetY) >= 0) ? (point.y + offsetY) : 0;\n return { x: newPointX, y: newPointY };\n }\n Point.offset = offset;\n function equals(point, other) {\n return point !== undefined && point !== null && other !== undefined && other !== null && point.x === other.x && point.y === other.y;\n }\n Point.equals = equals;\n function clone(point) {\n return (point !== null) ? { x: point.x, y: point.y } : null;\n }\n Point.clone = clone;\n function toString(point) {\n return \"{x:\" + point.x + \", y:\" + point.y + \"}\";\n }\n Point.toString = toString;\n function serialize(point) {\n return point.x + \",\" + point.y;\n }\n Point.serialize = serialize;\n function getDistance(point, other) {\n if ((point === null) || (other) === null) {\n return null;\n }\n var diffX = other.x - point.x;\n var diffY = other.y - point.y;\n return Math.sqrt(diffX * diffX + diffY * diffY);\n }\n Point.getDistance = getDistance;\n function equalWithPrecision(point1, point2) {\n return point1 === point2 ||\n (point1 !== undefined && point2 !== undefined && powerbi.Double.equalWithPrecision(point1.x, point2.x) && powerbi.Double.equalWithPrecision(point1.y, point2.y));\n }\n Point.equalWithPrecision = equalWithPrecision;\n function parsePoint(value, defaultValue) {\n if (value === null) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else if (value === undefined) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n if (value.length === 2) {\n return { x: Utility.parseNumber(value[0]), y: Utility.parseNumber(value[1]) };\n }\n else if (typeof value === \"string\") {\n var parts = value.split(\",\");\n if (parts.length !== 2) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n return { x: Utility.parseNumber(parts[0]), y: Utility.parseNumber(parts[1]) };\n }\n else if ((value.length !== 2) && (typeof value !== \"string\")) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n return { x: Utility.parseNumber(value.x), y: Utility.parseNumber(value.y) };\n }\n }\n }\n Point.parsePoint = parsePoint;\n })(Point = shapes.Point || (shapes.Point = {}));\n var Size;\n (function (Size) {\n function isEmpty(size) {\n return size.width === 0 && size.height === 0;\n }\n Size.isEmpty = isEmpty;\n function equals(size, other) {\n return size !== undefined && size !== null && other !== undefined && other !== null && size.width === other.width && size.height === other.height;\n }\n Size.equals = equals;\n function clone(size) {\n return (size !== null) ? { width: size.width, height: size.height } : null;\n }\n Size.clone = clone;\n function inflate(size, padding) {\n var result = clone(size);\n if (padding) {\n result.width += padding.left + padding.right;\n result.height += padding.top + padding.bottom;\n }\n return result;\n }\n Size.inflate = inflate;\n function deflate(size, padding) {\n var result = clone(size);\n if (padding) {\n result.width = result.width - padding.left - padding.right;\n if (result.width < 0) {\n result.width = 0;\n }\n result.height = result.height - padding.top - padding.bottom;\n if (result.height < 0) {\n result.height = 0;\n }\n }\n return result;\n }\n Size.deflate = deflate;\n function combine(size, other) {\n if (other) {\n size.width = Math.max(size.width, other.width);\n size.height = Math.max(size.height, other.height);\n }\n return size;\n }\n Size.combine = combine;\n function toRect(size) {\n return { left: 0, top: 0, width: size.width, height: size.height };\n }\n Size.toRect = toRect;\n function toString(size) {\n return \"{width:\" + size.width + \", height:\" + size.height + \"}\";\n }\n Size.toString = toString;\n function equal(size1, size2) {\n return size1 === size2 ||\n (size1 !== undefined && size2 !== undefined && size1.width === size2.width && size1.height === size2.height);\n }\n Size.equal = equal;\n function equalWithPrecision(size1, size2) {\n return size1 === size2 ||\n (size1 !== undefined && size2 !== undefined && powerbi.Double.equalWithPrecision(size1.width, size2.width) && powerbi.Double.equalWithPrecision(size1.height, size2.height));\n }\n Size.equalWithPrecision = equalWithPrecision;\n function parseSize(value, defaultValue) {\n if (value === null) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else if (value === undefined) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n if (value.length === 2) {\n return { width: Utility.parseNumber(value[0]), height: Utility.parseNumber(value[1]) };\n }\n else if (typeof value === \"string\") {\n var parts = value.split(\",\");\n if (parts.length !== 2) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n return { width: Utility.parseNumber(parts[0]), height: Utility.parseNumber(parts[1]) };\n }\n else if ((value.length !== 2) && (typeof value !== \"string\")) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n return { width: Utility.parseNumber(value.width), height: Utility.parseNumber(value.height) };\n }\n }\n }\n Size.parseSize = parseSize;\n })(Size = shapes.Size || (shapes.Size = {}));\n var Rect;\n (function (Rect) {\n function getOffset(rect) {\n return { x: rect.left, y: rect.top };\n }\n Rect.getOffset = getOffset;\n function getSize(rect) {\n return { width: rect.width, height: rect.height };\n }\n Rect.getSize = getSize;\n function setSize(rect, value) {\n rect.width = value.width;\n rect.height = value.height;\n }\n Rect.setSize = setSize;\n function right(rect) {\n return rect.left + rect.width;\n }\n Rect.right = right;\n function bottom(rect) {\n return rect.top + rect.height;\n }\n Rect.bottom = bottom;\n function topLeft(rect) {\n return { x: rect.left, y: rect.top };\n }\n Rect.topLeft = topLeft;\n function topRight(rect) {\n return { x: rect.left + rect.width, y: rect.top };\n }\n Rect.topRight = topRight;\n function bottomLeft(rect) {\n return { x: rect.left, y: rect.top + rect.height };\n }\n Rect.bottomLeft = bottomLeft;\n function bottomRight(rect) {\n return { x: rect.left + rect.width, y: rect.top + rect.height };\n }\n Rect.bottomRight = bottomRight;\n function equals(rect, other) {\n return other !== undefined && other !== null &&\n rect.left === other.left && rect.top === other.top && rect.width === other.width && rect.height === other.height;\n }\n Rect.equals = equals;\n function clone(rect) {\n return (rect !== null) ? { left: rect.left, top: rect.top, width: rect.width, height: rect.height } : null;\n }\n Rect.clone = clone;\n function toString(rect) {\n return \"{left:\" + rect.left + \", top:\" + rect.top + \", width:\" + rect.width + \", height:\" + rect.height + \"}\";\n }\n Rect.toString = toString;\n function offset(rect, offsetX, offsetY) {\n var newLeft = ((rect.left + offsetX) >= 0) ? rect.left + offsetX : 0;\n var newTop = ((rect.top + offsetY) >= 0) ? rect.top + offsetY : 0;\n return { left: newLeft, top: newTop, width: rect.width, height: rect.height };\n }\n Rect.offset = offset;\n function inflate(rect, padding) {\n var result = clone(rect);\n if (padding) {\n result.left -= padding.left;\n result.top -= padding.top;\n result.width += padding.left + padding.right;\n result.height += padding.top + padding.bottom;\n }\n return result;\n }\n Rect.inflate = inflate;\n function deflate(rect, padding) {\n var result = clone(rect);\n if (padding) {\n result.left += padding.left;\n result.top += padding.top;\n result.width -= padding.left + padding.right;\n result.height -= padding.top + padding.bottom;\n }\n return result;\n }\n Rect.deflate = deflate;\n function inflateBy(rect, padding) {\n return { left: rect.left - padding, top: rect.top - padding, width: rect.width + padding + padding, height: rect.height + padding + padding };\n }\n Rect.inflateBy = inflateBy;\n function deflateBy(rect, padding) {\n return { left: rect.left + padding, top: rect.top + padding, width: rect.width - padding - padding, height: rect.height - padding - padding };\n }\n Rect.deflateBy = deflateBy;\n /**\n * Get closest point.\n *\n * @return the closest point on the rect to the (x,y) point given.\n * In case the (x,y) given is inside the rect, (x,y) will be returned.\n * Otherwise, a point on a border will be returned.\n */\n function getClosestPoint(rect, x, y) {\n return {\n x: Math.min(Math.max(rect.left, x), rect.left + rect.width),\n y: Math.min(Math.max(rect.top, y), rect.top + rect.height)\n };\n }\n Rect.getClosestPoint = getClosestPoint;\n function equal(rect1, rect2) {\n return rect1 === rect2 ||\n (rect1 !== undefined && rect2 !== undefined && rect1.left === rect2.left && rect1.top === rect2.top && rect1.width === rect2.width && rect1.height === rect2.height);\n }\n Rect.equal = equal;\n function equalWithPrecision(rect1, rect2) {\n return rect1 === rect2 ||\n (rect1 !== undefined && rect2 !== undefined &&\n powerbi.Double.equalWithPrecision(rect1.left, rect2.left) && powerbi.Double.equalWithPrecision(rect1.top, rect2.top) &&\n powerbi.Double.equalWithPrecision(rect1.width, rect2.width) && powerbi.Double.equalWithPrecision(rect1.height, rect2.height));\n }\n Rect.equalWithPrecision = equalWithPrecision;\n function isEmpty(rect) {\n return rect === undefined || rect === null || (rect.width === 0 && rect.height === 0);\n }\n Rect.isEmpty = isEmpty;\n function containsPoint(rect, point) {\n if ((rect === null) || (point === null)) {\n return false;\n }\n return powerbi.Double.lessOrEqualWithPrecision(rect.left, point.x) &&\n powerbi.Double.lessOrEqualWithPrecision(point.x, rect.left + rect.width) &&\n powerbi.Double.lessOrEqualWithPrecision(rect.top, point.y) &&\n powerbi.Double.lessOrEqualWithPrecision(point.y, rect.top + rect.height);\n }\n Rect.containsPoint = containsPoint;\n function isIntersecting(rect1, rect2) {\n if (!rect1 || !rect2) {\n return false;\n }\n var left = Math.max(rect1.left, rect2.left);\n var right = Math.min(rect1.left + rect1.width, rect2.left + rect2.width);\n if (left > right) {\n return false;\n }\n var top = Math.max(rect1.top, rect2.top);\n var bottom = Math.min(rect1.top + rect1.height, rect2.top + rect2.height);\n return top <= bottom;\n }\n Rect.isIntersecting = isIntersecting;\n function intersect(rect1, rect2) {\n if (!rect1) {\n return rect2;\n }\n if (!rect2) {\n return rect1;\n }\n var left = Math.max(rect1.left, rect2.left);\n var top = Math.max(rect1.top, rect2.top);\n var right = Math.min(rect1.left + rect1.width, rect2.left + rect2.width);\n var bottom = Math.min(rect1.top + rect1.height, rect2.top + rect2.height);\n if (left <= right && top <= bottom) {\n return { left: left, top: top, width: right - left, height: bottom - top };\n }\n else {\n return { left: 0, top: 0, width: 0, height: 0 };\n }\n }\n Rect.intersect = intersect;\n function combine(rect1, rect2) {\n if (!rect1) {\n return rect2;\n }\n if (!rect2) {\n return rect1;\n }\n var left = Math.min(rect1.left, rect2.left);\n var top = Math.min(rect1.top, rect2.top);\n var right = Math.max(rect1.left + rect1.width, rect2.left + rect2.width);\n var bottom = Math.max(rect1.top + rect1.height, rect2.top + rect2.height);\n return { left: left, top: top, width: right - left, height: bottom - top };\n }\n Rect.combine = combine;\n function parseRect(value, defaultValue) {\n if (value === null) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else if (value === undefined) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n if (value.length === 4) {\n return { left: Utility.parseNumber(value[0]), top: Utility.parseNumber(value[1]), width: Utility.parseNumber(value[2]), height: Utility.parseNumber(value[3]) };\n }\n else if (typeof value === \"string\") {\n var parts = value.split(\",\");\n if (parts.length !== 4) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n return {\n left: Utility.parseNumber(parts[0]), top: Utility.parseNumber(parts[1]), width: Utility.parseNumber(parts[2]), height: Utility.parseNumber(parts[3])\n };\n }\n else if ((value.length !== 4) && (typeof value !== \"string\")) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n return { left: Utility.parseNumber(value.left), top: Utility.parseNumber(value.top), width: Utility.parseNumber(value.width), height: Utility.parseNumber(value.height) };\n }\n }\n }\n Rect.parseRect = parseRect;\n })(Rect = shapes.Rect || (shapes.Rect = {}));\n var Thickness;\n (function (Thickness) {\n function inflate(thickness, other) {\n var result = clone(thickness);\n if (other) {\n result.left = thickness.left + other.left;\n result.right = thickness.right + other.right;\n result.bottom = thickness.bottom + other.bottom;\n result.top = thickness.top + other.top;\n }\n return result;\n }\n Thickness.inflate = inflate;\n function getWidth(thickness) {\n return thickness.left + thickness.right;\n }\n Thickness.getWidth = getWidth;\n function getHeight(thickness) {\n return thickness.top + thickness.bottom;\n }\n Thickness.getHeight = getHeight;\n function clone(thickness) {\n return (thickness !== null) ? { left: thickness.left, top: thickness.top, right: thickness.right, bottom: thickness.bottom } : null;\n }\n Thickness.clone = clone;\n function equals(thickness, other) {\n return thickness !== undefined && thickness !== null && other !== undefined && other !== null && thickness.left === other.left && thickness.bottom === other.bottom && thickness.right === other.right && thickness.top === other.top;\n }\n Thickness.equals = equals;\n function flipHorizontal(thickness) {\n var temp = thickness.right;\n thickness.right = thickness.left;\n thickness.left = temp;\n }\n Thickness.flipHorizontal = flipHorizontal;\n function flipVertical(thickness) {\n var top = thickness.top;\n thickness.top = thickness.bottom;\n thickness.bottom = top;\n }\n Thickness.flipVertical = flipVertical;\n function toString(thickness) {\n return \"{top:\" + thickness.top + \", left:\" + thickness.left + \", right:\" + thickness.right + \", bottom:\" + thickness.bottom + \"}\";\n }\n Thickness.toString = toString;\n function toCssString(thickness) {\n return thickness.top + \"px \" + thickness.right + \"px \" + thickness.bottom + \"px \" + thickness.left + \"px\";\n }\n Thickness.toCssString = toCssString;\n function isEmpty(thickness) {\n return thickness.left === 0 && thickness.top === 0 && thickness.right === 0 && thickness.bottom === 0;\n }\n Thickness.isEmpty = isEmpty;\n function equal(thickness1, thickness2) {\n return thickness1 === thickness2 ||\n (thickness1 !== undefined && thickness2 !== undefined && thickness1.left === thickness2.left && thickness1.top === thickness2.top && thickness1.right === thickness2.right && thickness1.bottom === thickness2.bottom);\n }\n Thickness.equal = equal;\n function equalWithPrecision(thickness1, thickness2) {\n return thickness1 === thickness2 ||\n (thickness1 !== undefined && thickness2 !== undefined &&\n powerbi.Double.equalWithPrecision(thickness1.left, thickness2.left) && powerbi.Double.equalWithPrecision(thickness1.top, thickness2.top) &&\n powerbi.Double.equalWithPrecision(thickness1.right, thickness2.right) && powerbi.Double.equalWithPrecision(thickness1.bottom, thickness2.bottom));\n }\n Thickness.equalWithPrecision = equalWithPrecision;\n function parseThickness(value, defaultValue, resetValue) {\n if (value === null) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else if (value === undefined) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n if (value.length === 4) {\n return { left: Utility.parseNumber(value[0]), top: Utility.parseNumber(value[1]), right: Utility.parseNumber(value[2]), bottom: Utility.parseNumber(value[3]) };\n }\n else if (typeof value === \"string\") {\n var parts = value.split(\",\");\n if (parts.length !== 4) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n return { left: Utility.parseNumber(parts[0]), top: Utility.parseNumber(parts[1]), right: Utility.parseNumber(parts[2]), bottom: Utility.parseNumber(parts[3]) };\n }\n else if ((value.length !== 4) && (typeof value !== \"string\")) {\n return (defaultValue === undefined) ? null : defaultValue;\n }\n else {\n return { left: Utility.parseNumber(value.left), top: Utility.parseNumber(value.top), right: Utility.parseNumber(value.right), bottom: Utility.parseNumber(value.bottom) };\n }\n }\n }\n Thickness.parseThickness = parseThickness;\n })(Thickness = shapes.Thickness || (shapes.Thickness = {}));\n var Vector;\n (function (Vector) {\n function isEmpty(vector) {\n return vector.x === 0 && vector.y === 0;\n }\n Vector.isEmpty = isEmpty;\n function equals(vector, other) {\n return vector !== undefined && vector !== null && other !== undefined && other !== null && vector.x === other.x && vector.y === other.y;\n }\n Vector.equals = equals;\n function clone(vector) {\n return (vector !== null) ? { x: vector.x, y: vector.y } : null;\n }\n Vector.clone = clone;\n function toString(vector) {\n return \"{x:\" + vector.x + \", y:\" + vector.y + \"}\";\n }\n Vector.toString = toString;\n function getLength(vector) {\n return Math.sqrt(vector.x * vector.x + vector.y * vector.y);\n }\n Vector.getLength = getLength;\n function getLengthSqr(vector) {\n return vector.x * vector.x + vector.y * vector.y;\n }\n Vector.getLengthSqr = getLengthSqr;\n function scale(vector, scalar) {\n return { x: vector.x * scalar, y: vector.y * scalar };\n }\n Vector.scale = scale;\n function normalize(vector) {\n return !isEmpty(vector) ? scale(vector, 1 / getLength(vector)) : vector;\n }\n Vector.normalize = normalize;\n function rotate90DegCW(vector) {\n return { x: vector.y, y: -vector.x };\n }\n Vector.rotate90DegCW = rotate90DegCW;\n function rotate90DegCCW(vector) {\n return { x: -vector.y, y: vector.x };\n }\n Vector.rotate90DegCCW = rotate90DegCCW;\n function rotate(vector, angle) {\n var newX = vector.x * Math.cos(angle) - vector.y * Math.sin(angle);\n var newY = vector.x * Math.sin(angle) + vector.y * Math.cos(angle);\n return { x: newX, y: newY };\n }\n Vector.rotate = rotate;\n function equal(vector1, vector2) {\n return vector1 === vector2 ||\n (vector1 !== undefined && vector2 !== undefined && vector1.x === vector2.x && vector1.y === vector2.y);\n }\n Vector.equal = equal;\n function equalWithPrecision(vector1, vector2) {\n return vector1 === vector2 ||\n (vector1 !== undefined && vector2 !== undefined && powerbi.Double.equalWithPrecision(vector1.x, vector2.x) && powerbi.Double.equalWithPrecision(vector1.y, vector2.y));\n }\n Vector.equalWithPrecision = equalWithPrecision;\n function add(vect1, vect2) {\n if (!vect1 || !vect2) {\n return undefined;\n }\n return { x: vect1.x + vect2.x, y: vect1.y + vect2.y };\n }\n Vector.add = add;\n function subtract(vect1, vect2) {\n if (!vect1 || !vect2) {\n return undefined;\n }\n return { x: vect1.x - vect2.x, y: vect1.y - vect2.y };\n }\n Vector.subtract = subtract;\n function dotProduct(vect1, vect2) {\n if (!vect1 || !vect2) {\n return undefined;\n }\n return vect1.x * vect2.x + vect1.y * vect2.y;\n }\n Vector.dotProduct = dotProduct;\n function getDeltaVector(p0, p1) {\n if (!p0 || !p1) {\n return undefined;\n }\n return { x: p1.x - p0.x, y: p1.y - p0.y };\n }\n Vector.getDeltaVector = getDeltaVector;\n })(Vector = shapes.Vector || (shapes.Vector = {}));\n })(shapes = visuals.shapes || (visuals.shapes = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var PixelConverter = jsCommon.PixelConverter;\n /** Utility class for slicer*/\n var SlicerUtil;\n (function (SlicerUtil) {\n /** CSS selectors for slicer elements. */\n var Selectors;\n (function (Selectors) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n Selectors.HeaderContainer = createClassAndSelector('headerContainer');\n Selectors.Header = createClassAndSelector('slicerHeader');\n Selectors.HeaderText = createClassAndSelector('headerText');\n Selectors.Body = createClassAndSelector('slicerBody');\n Selectors.Label = createClassAndSelector('slicerLabel');\n Selectors.LabelText = createClassAndSelector('slicerText');\n Selectors.LabelImage = createClassAndSelector('slicerImage');\n Selectors.CountText = createClassAndSelector('slicerCountText');\n Selectors.Clear = createClassAndSelector('clear');\n Selectors.MultiSelectEnabled = createClassAndSelector('isMultiSelectEnabled');\n })(Selectors = SlicerUtil.Selectors || (SlicerUtil.Selectors = {}));\n /** Const declarations*/\n var DisplayNameKeys;\n (function (DisplayNameKeys) {\n DisplayNameKeys.Clear = 'Slicer_Clear';\n DisplayNameKeys.SelectAll = 'Slicer_SelectAll';\n })(DisplayNameKeys = SlicerUtil.DisplayNameKeys || (SlicerUtil.DisplayNameKeys = {}));\n /** Helper class for slicer settings */\n var SettingsHelper;\n (function (SettingsHelper) {\n function areSettingsDefined(data) {\n return data != null && data.slicerSettings != null;\n }\n SettingsHelper.areSettingsDefined = areSettingsDefined;\n })(SettingsHelper = SlicerUtil.SettingsHelper || (SlicerUtil.SettingsHelper = {}));\n /** Helper class for handling slicer default value */\n var DefaultValueHandler;\n (function (DefaultValueHandler) {\n function getIdentityFields(dataView) {\n if (!dataView)\n return;\n var dataViewCategorical = dataView.categorical;\n if (!dataViewCategorical || _.isEmpty(dataViewCategorical.categories))\n return;\n return dataViewCategorical.categories[0].identityFields;\n }\n DefaultValueHandler.getIdentityFields = getIdentityFields;\n })(DefaultValueHandler = SlicerUtil.DefaultValueHandler || (SlicerUtil.DefaultValueHandler = {}));\n // Compare the sqExpr of the scopeId with sqExprs of the retained values. \n // If match found, remove the item from the retainedValues list, and return true, \n // otherwise return false.\n function tryRemoveValueFromRetainedList(value, selectedScopeIds, caseInsensitive) {\n if (!value || _.isEmpty(selectedScopeIds))\n return false;\n for (var i = 0, len = selectedScopeIds.length; i < len; i++) {\n var retainedValueScopeId = selectedScopeIds[i];\n if (powerbi.DataViewScopeIdentity.equals(value, retainedValueScopeId, caseInsensitive)) {\n selectedScopeIds.splice(i, 1);\n return true;\n }\n }\n return false;\n }\n SlicerUtil.tryRemoveValueFromRetainedList = tryRemoveValueFromRetainedList;\n /** Helper class for creating and measuring slicer DOM elements */\n var DOMHelper = (function () {\n function DOMHelper() {\n }\n DOMHelper.prototype.createSlicerHeader = function (hostServices) {\n var slicerHeaderDiv = document.createElement('div');\n slicerHeaderDiv.className = Selectors.Header.class;\n var slicerHeader = d3.select(slicerHeaderDiv);\n slicerHeader.append('span')\n .classed(Selectors.Clear.class, true)\n .attr('title', hostServices.getLocalizedString(DisplayNameKeys.Clear));\n slicerHeader.append('div').classed(Selectors.HeaderText.class, true);\n return slicerHeaderDiv;\n };\n DOMHelper.prototype.getHeaderTextProperties = function (settings) {\n var headerTextProperties = {\n fontFamily: 'wf_segoe-ui_normal',\n fontSize: '10px'\n };\n if (settings.header.show) {\n headerTextProperties.fontSize = PixelConverter.fromPoint(settings.header.textSize);\n }\n return headerTextProperties;\n };\n DOMHelper.prototype.getSlicerBodyViewport = function (currentViewport, settings, headerTextProperties) {\n var headerHeight = (settings.header.show) ? this.getHeaderHeight(settings, headerTextProperties) : 0;\n var slicerBodyHeight = currentViewport.height - (headerHeight + settings.header.borderBottomWidth);\n return {\n height: slicerBodyHeight,\n width: currentViewport.width\n };\n };\n DOMHelper.prototype.updateSlicerBodyDimensions = function (currentViewport, slicerBody, settings) {\n var slicerViewport = this.getSlicerBodyViewport(currentViewport, settings, this.getHeaderTextProperties(settings));\n slicerBody.style({\n 'height': PixelConverter.toString(slicerViewport.height),\n 'width': PixelConverter.toString(slicerViewport.width),\n });\n };\n DOMHelper.prototype.getHeaderHeight = function (settings, textProperties) {\n return powerbi.TextMeasurementService.estimateSvgTextHeight(this.getTextProperties(settings.header.textSize, textProperties)) + settings.general.outlineWeight;\n };\n DOMHelper.prototype.getRowHeight = function (settings, textProperties) {\n return powerbi.TextMeasurementService.estimateSvgTextHeight(this.getTextProperties(settings.slicerText.textSize, textProperties)) + this.getRowsOutlineWidth(settings.slicerText.outline, settings.general.outlineWeight);\n };\n DOMHelper.prototype.styleSlicerHeader = function (slicerHeader, settings, headerText) {\n if (settings.header.show) {\n slicerHeader.style('display', 'block');\n var headerTextElement = slicerHeader.select(Selectors.HeaderText.selector)\n .text(headerText);\n this.setSlicerHeaderTextStyle(headerTextElement, settings);\n }\n else {\n slicerHeader.style('display', 'none');\n }\n };\n DOMHelper.prototype.setSlicerTextStyle = function (slicerText, settings) {\n slicerText\n .style({\n 'color': settings.slicerText.color,\n 'background-color': settings.slicerText.background,\n 'border-style': 'solid',\n 'border-color': settings.general.outlineColor,\n 'border-width': visuals.VisualBorderUtil.getBorderWidth(settings.slicerText.outline, settings.general.outlineWeight),\n 'font-size': PixelConverter.fromPoint(settings.slicerText.textSize),\n });\n };\n DOMHelper.prototype.getRowsOutlineWidth = function (outlineElement, outlineWeight) {\n switch (outlineElement) {\n case visuals.outline.none:\n case visuals.outline.leftRight:\n return 0;\n case visuals.outline.bottomOnly:\n case visuals.outline.topOnly:\n return outlineWeight;\n case visuals.outline.topBottom:\n case visuals.outline.frame:\n return outlineWeight * 2;\n default:\n return 0;\n }\n };\n DOMHelper.prototype.setSlicerHeaderTextStyle = function (slicerHeader, settings) {\n slicerHeader\n .style({\n 'border-style': 'solid',\n 'border-color': settings.general.outlineColor,\n 'border-width': visuals.VisualBorderUtil.getBorderWidth(settings.header.outline, settings.general.outlineWeight),\n 'color': settings.header.fontColor,\n 'background-color': settings.header.background,\n 'font-size': PixelConverter.fromPoint(settings.header.textSize),\n });\n };\n DOMHelper.prototype.getTextProperties = function (textSize, textProperties) {\n textProperties.fontSize = PixelConverter.fromPoint(textSize);\n return textProperties;\n };\n return DOMHelper;\n }());\n SlicerUtil.DOMHelper = DOMHelper;\n })(SlicerUtil = visuals.SlicerUtil || (visuals.SlicerUtil = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * Contains functions/constants to aid in adding tooltips.\n */\n var tooltipUtils;\n (function (tooltipUtils) {\n function tooltipUpdate(selection, tooltips) {\n if (tooltips.length === 0)\n return;\n debug.assert(selection.length === tooltips.length || selection[0].length === tooltips.length, 'data length should match dom element count');\n var titles = selection.selectAll('title');\n var titlesUpdate = titles.data(function (d, i) { return [tooltips[i]]; });\n titlesUpdate.enter().append('title');\n titlesUpdate.exit().remove();\n titlesUpdate.text(function (d) { return d; });\n }\n tooltipUtils.tooltipUpdate = tooltipUpdate;\n })(tooltipUtils = visuals.tooltipUtils || (visuals.tooltipUtils = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * Contains functions/constants to aid in SVG manupilation.\n */\n var SVGUtil;\n (function (SVGUtil) {\n /**\n * Very small values, when stringified, may be converted to scientific notation and cause a temporarily\n * invalid attribute or style property value.\n * For example, the number 0.0000001 is converted to the string \"1e-7\".\n * This is particularly noticeable when interpolating opacity values.\n * To avoid scientific notation, start or end the transition at 1e-6,\n * which is the smallest value that is not stringified in exponential notation.\n */\n SVGUtil.AlmostZero = 1e-6;\n /**\n * Creates a translate string for use with the SVG transform call.\n */\n function translate(x, y) {\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n return 'translate(' + x + ',' + y + ')';\n }\n SVGUtil.translate = translate;\n /**\n * Creates a translateX string for use with the SVG transform call.\n */\n function translateXWithPixels(x) {\n debug.assertValue(x, 'x');\n return 'translateX(' + x + 'px)';\n }\n SVGUtil.translateXWithPixels = translateXWithPixels;\n function translateWithPixels(x, y) {\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n return 'translate(' + x + 'px,' + y + 'px)';\n }\n SVGUtil.translateWithPixels = translateWithPixels;\n /**\n * Creates a translate + rotate string for use with the SVG transform call.\n */\n function translateAndRotate(x, y, px, py, angle) {\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n debug.assertValue(px, 'px');\n debug.assertValue(py, 'py');\n debug.assertValue(angle, 'angle');\n return 'transform', \"translate(\"\n + x + \",\" + y + \")\"\n + \" rotate(\" + angle + \",\" + px + \",\" + py + \")\";\n }\n SVGUtil.translateAndRotate = translateAndRotate;\n /**\n * Creates a scale string for use in a CSS transform property.\n */\n function scale(scale) {\n debug.assertValue(scale, 'scale');\n return \"scale(\" + scale + \")\";\n }\n SVGUtil.scale = scale;\n /**\n * Creates a translate + scale string for use with the SVG transform call.\n */\n function translateAndScale(x, y, ratio) {\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n debug.assertValue(ratio, 'ratio');\n return 'transform', \"translate(\"\n + x + \",\" + y + \")\"\n + \" scale(\" + ratio + \")\";\n }\n SVGUtil.translateAndScale = translateAndScale;\n /**\n * Creates a transform origin string for use in a CSS transform-origin property.\n */\n function transformOrigin(xOffset, yOffset) {\n debug.assertValue(xOffset, 'xOffset');\n debug.assertValue(yOffset, 'yOffset');\n return xOffset + \" \" + yOffset;\n }\n SVGUtil.transformOrigin = transformOrigin;\n /**\n * Forces all D3 transitions to complete.\n * Normally, zero-delay transitions are executed after an instantaneous delay (<10ms).\n * This can cause a brief flicker if the browser renders the page twice: once at the end of the first event loop,\n * then again immediately on the first timer callback. By flushing the timer queue at the end of the first event loop,\n * you can run any zero-delay transitions immediately and avoid the flicker.\n *\n * These flickers are noticable on IE, and with a large number of webviews(not recommend you ever do this) on iOS.\n */\n function flushAllD3Transitions() {\n var now = Date.now;\n Date.now = function () { return Infinity; };\n d3.timer.flush();\n Date.now = now;\n }\n SVGUtil.flushAllD3Transitions = flushAllD3Transitions;\n /**\n * Wrapper for flushAllD3Transitions.\n */\n function flushAllD3TransitionsIfNeeded(options) {\n if (!options)\n return;\n var animationOptions = options;\n var asVisualInitOptions = options;\n if (asVisualInitOptions.animation)\n animationOptions = asVisualInitOptions.animation;\n if (animationOptions && animationOptions.transitionImmediate) {\n flushAllD3Transitions();\n }\n }\n SVGUtil.flushAllD3TransitionsIfNeeded = flushAllD3TransitionsIfNeeded;\n /**\n * There is a known bug in IE10 that causes cryptic crashes for SVG elements with a null 'd' attribute:\n * https://github.com/mbostock/d3/issues/1737\n */\n function ensureDAttribute(pathElement) {\n if (!pathElement.getAttribute('d')) {\n pathElement.setAttribute('d', '');\n }\n }\n SVGUtil.ensureDAttribute = ensureDAttribute;\n /**\n * In IE10, it is possible to return SVGPoints with NaN members.\n */\n function ensureValidSVGPoint(point) {\n if (isNaN(point.x)) {\n point.x = 0;\n }\n if (isNaN(point.y)) {\n point.y = 0;\n }\n }\n SVGUtil.ensureValidSVGPoint = ensureValidSVGPoint;\n /**\n * Parse the Transform string with value 'translate(x,y)'.\n * In Chrome for the translate(position) string the delimiter\n * is a comma and in IE it is a spaceso checking for both.\n */\n function parseTranslateTransform(input) {\n if (!input || input.length === 0) {\n return {\n x: \"0\",\n y: \"0\",\n };\n }\n var translateCoordinates = input.split(/[\\s,]+/);\n debug.assertValue(translateCoordinates, 'translateCoordinates');\n debug.assert(translateCoordinates.length > 0, 'translate array must atleast have one value');\n var yValue = '0';\n var xValue;\n var xCoord = translateCoordinates[0];\n // Y coordinate is ommited in I.E if it is 0, so need to check against that\n if (translateCoordinates.length === 1) {\n // 10 refers to the length of 'translate('\n xValue = xCoord.substring(10, xCoord.length - 1);\n }\n else {\n var yCoord = translateCoordinates[1];\n yValue = yCoord.substring(0, yCoord.length - 1);\n // 10 refers to the length of 'translate('\n xValue = xCoord.substring(10, xCoord.length);\n }\n return {\n x: xValue,\n y: yValue\n };\n }\n SVGUtil.parseTranslateTransform = parseTranslateTransform;\n /**\n * Create an arrow.\n */\n function createArrow(width, height, rotate) {\n var transform = \"rotate(\" + rotate + \" \" + width / 2 + \" \" + height / 2 + \")\";\n var path = \"M0 0\";\n path += \"L0 \" + height;\n path += \"L\" + width + \" \" + height / 2 + \" Z\";\n return {\n path: path,\n transform: transform\n };\n }\n SVGUtil.createArrow = createArrow;\n /**\n * Use the ratio of the scaled bounding rect and the SVG DOM bounding box to get the x and y transform scale values\n * @deprecated This function is unreliable across browser implementations, prefer to use SVGScaleDetector if needed.\n */\n function getTransformScaleRatios(svgElement) {\n debug.assertFail('deprecated');\n if (svgElement != null) {\n var scaledRect = svgElement.getBoundingClientRect();\n var domRect = svgElement.getBBox();\n if (domRect.height > 0 && domRect.width > 0) {\n return {\n x: scaledRect.width / domRect.width,\n y: scaledRect.height / domRect.height\n };\n }\n }\n return { x: 1, y: 1 };\n }\n SVGUtil.getTransformScaleRatios = getTransformScaleRatios;\n })(SVGUtil = visuals.SVGUtil || (visuals.SVGUtil = {}));\n var SVGScaleDetector = (function () {\n function SVGScaleDetector(svgElement) {\n this.scaleDetectorElement = svgElement\n .append('rect') // Using a <rect> which should have a reliable bounding box across browser implementations.\n .classed('scale-detector', true)\n .attr({\n width: 1,\n height: 1,\n 'stroke-width': '0px',\n fill: 'none',\n })\n .node();\n }\n SVGScaleDetector.prototype.getScale = function () {\n var scaledRect = this.scaleDetectorElement.getBoundingClientRect();\n var domRect = this.scaleDetectorElement.getBBox();\n if (domRect.height > 0 && domRect.width > 0) {\n return {\n x: scaledRect.width / domRect.width,\n y: scaledRect.height / domRect.height\n };\n }\n return {\n x: 1,\n y: 1\n };\n };\n return SVGScaleDetector;\n }());\n visuals.SVGScaleDetector = SVGScaleDetector;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * Contains functions/constants to aid in text manupilation.\n */\n var TextUtil;\n (function (TextUtil) {\n /**\n * Remove breaking spaces from given string and replace by none breaking space (&nbsp).\n */\n function removeBreakingSpaces(str) {\n return str.toString().replace(new RegExp(' ', 'g'), '&nbsp');\n }\n TextUtil.removeBreakingSpaces = removeBreakingSpaces;\n /**\n * Remove ellipses from a given string\n */\n function removeEllipses(str) {\n return str.replace(/…/g, '');\n }\n TextUtil.removeEllipses = removeEllipses;\n /**\n * Replace every whitespace (0x20) with Non-Breaking Space (0xA0)\n * @param {string} txt String to replace White spaces\n * @returns Text after replcing white spaces\n */\n function replaceSpaceWithNBSP(txt) {\n if (txt != null)\n return txt.replace(/ /g, \"\\xA0\");\n }\n TextUtil.replaceSpaceWithNBSP = replaceSpaceWithNBSP;\n })(TextUtil = visuals.TextUtil || (visuals.TextUtil = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n ;\n var GradientUtils;\n (function (GradientUtils) {\n var SQExprBuilder = powerbi.data.SQExprBuilder;\n var DefaultMidColor = \"#ffffff\";\n var DataPointPropertyIdentifier = \"dataPoint\";\n var FillRulePropertyIdentifier = \"fillRule\";\n function getFillRuleRole(objectDescs) {\n if (!objectDescs)\n return;\n for (var objectName in objectDescs) {\n var objectDesc = objectDescs[objectName];\n for (var propertyName in objectDesc.properties) {\n var propertyDesc = objectDesc.properties[propertyName];\n if (propertyDesc.type && propertyDesc.type[FillRulePropertyIdentifier]) {\n return propertyDesc.rule.inputRole;\n }\n }\n }\n }\n GradientUtils.getFillRuleRole = getFillRuleRole;\n function shouldShowGradient(visualConfig) {\n var isShowGradienCard = visualConfig && visualConfig.query && visualConfig.query.projections && visualConfig.query.projections['Gradient'] ? true : false;\n return isShowGradienCard;\n }\n GradientUtils.shouldShowGradient = shouldShowGradient;\n function getUpdatedGradientSettings(gradientObject) {\n var gradientSettings;\n if (gradientObject && !$.isEmptyObject(gradientObject)) {\n gradientSettings = getDefaultGradientSettings();\n for (var propertyName in gradientSettings) {\n var hasProperty = gradientObject.hasOwnProperty(propertyName);\n if (hasProperty) {\n var value = gradientObject[propertyName];\n if (value && value.solid && value.solid.color) {\n value = value.solid.color;\n }\n gradientSettings[propertyName] = value;\n }\n }\n }\n return gradientSettings;\n }\n GradientUtils.getUpdatedGradientSettings = getUpdatedGradientSettings;\n function getGradientMeasureIndex(dataViewCategorical) {\n if (dataViewCategorical && dataViewCategorical.values && dataViewCategorical.values.grouped) {\n var grouped = dataViewCategorical.values.grouped();\n return DataRoleHelper.getMeasureIndexOfRole(grouped, 'Gradient');\n }\n return -1;\n }\n GradientUtils.getGradientMeasureIndex = getGradientMeasureIndex;\n function getGradientValueColumn(dataViewCategorical) {\n if (dataViewCategorical == null)\n return null;\n // check for gradient measure index\n var gradientMeasureIndex = GradientUtils.getGradientMeasureIndex(dataViewCategorical);\n var gradientValueColumn = gradientMeasureIndex === -1 ? null : dataViewCategorical.values[gradientMeasureIndex];\n return gradientValueColumn;\n }\n GradientUtils.getGradientValueColumn = getGradientValueColumn;\n function hasGradientRole(dataViewCategorical) {\n var gradientMeasureIndex = getGradientMeasureIndex(dataViewCategorical);\n return gradientMeasureIndex >= 0;\n }\n GradientUtils.hasGradientRole = hasGradientRole;\n function getDefaultGradientSettings() {\n var colors = getDefaultColors();\n var gradientSettings = {\n diverging: false,\n minColor: colors.minColor,\n midColor: DefaultMidColor,\n maxColor: colors.maxColor,\n minValue: undefined,\n midValue: undefined,\n maxValue: undefined,\n };\n return gradientSettings;\n }\n GradientUtils.getDefaultGradientSettings = getDefaultGradientSettings;\n function getDefaultFillRuleDefinition() {\n return getLinearGradien2FillRuleDefinition();\n }\n GradientUtils.getDefaultFillRuleDefinition = getDefaultFillRuleDefinition;\n function updateFillRule(propertyName, propertyValue, definitions) {\n var dataPointObjectDefinition = powerbi.data.DataViewObjectDefinitions.ensure(definitions, DataPointPropertyIdentifier, null);\n var fillRule = getFillRule(definitions);\n var numericValueExpr;\n var colorValueExpr;\n if (!fillRule) {\n return;\n }\n if ($.isNumeric(propertyValue)) {\n numericValueExpr = propertyValue !== undefined ? SQExprBuilder.double(+propertyValue) : undefined;\n ;\n }\n if (propertyName === \"minColor\" || propertyName === \"midColor\" || propertyName === \"maxColor\") {\n colorValueExpr = getColorExpressionValue(fillRule, propertyName, propertyValue);\n }\n if (propertyName === \"minColor\") {\n updateMinColor(fillRule, colorValueExpr);\n }\n else if (propertyName === \"midColor\") {\n updateMidColor(fillRule, colorValueExpr);\n }\n else if (propertyName === \"maxColor\") {\n updateMaxColor(fillRule, colorValueExpr);\n }\n else if (propertyName === \"minValue\") {\n updateMinValue(fillRule, numericValueExpr);\n }\n else if (propertyName === \"midValue\") {\n updateMidValue(fillRule, numericValueExpr);\n }\n else if (propertyName === \"maxValue\") {\n updateMaxValue(fillRule, numericValueExpr);\n }\n else if (propertyName === \"diverging\") {\n if (propertyValue) {\n fillRule = getLinearGradien3FillRuleDefinition(fillRule);\n }\n else {\n fillRule = getLinearGradien2FillRuleDefinition(fillRule);\n }\n dataPointObjectDefinition.properties[FillRulePropertyIdentifier] = fillRule;\n }\n else if (propertyName === \"revertToDefault\") {\n fillRule = this.getDefaultFillRuleDefinition();\n dataPointObjectDefinition.properties[FillRulePropertyIdentifier] = fillRule;\n }\n }\n GradientUtils.updateFillRule = updateFillRule;\n function getGradientSettings(baseFillRule) {\n if (baseFillRule) {\n return getGradientSettingsFromRule(baseFillRule);\n }\n else {\n return getDefaultGradientSettings();\n }\n }\n GradientUtils.getGradientSettings = getGradientSettings;\n function getFillRule(objectDefinitions) {\n var fillRuleDefinition = powerbi.data.DataViewObjectDefinitions.getValue(objectDefinitions, { objectName: DataPointPropertyIdentifier, propertyName: FillRulePropertyIdentifier }, null);\n return fillRuleDefinition;\n }\n GradientUtils.getFillRule = getFillRule;\n function getDefaultColors() {\n var dataColors = new powerbi.visuals.DataColorPalette();\n var maxColorInfo = dataColors.getColorByIndex(0);\n var colors = d3.scale.linear()\n .domain([0, 100])\n .range([\"#ffffff\", maxColorInfo.value]);\n var maxColor = maxColorInfo.value;\n var minColor = colors(20);\n var midColor = DefaultMidColor;\n return {\n minColor: minColor,\n midColor: midColor,\n maxColor: maxColor,\n };\n }\n function getGradientSettingsFromRule(fillRule) {\n var maxColor;\n var minColor;\n var midColor = DefaultMidColor;\n var maxValue;\n var midValue;\n var minValue;\n var diverging = fillRule.linearGradient3 !== undefined;\n if (fillRule.linearGradient2) {\n var maxColorExpr = fillRule.linearGradient2.max.color;\n var minColorExpr = fillRule.linearGradient2.min.color;\n var maxValueExpr = fillRule.linearGradient2.max.value;\n var minValueExpr = fillRule.linearGradient2.min.value;\n maxColor = maxColorExpr.value;\n minColor = minColorExpr.value;\n if (maxValueExpr) {\n maxValue = maxValueExpr.value;\n }\n if (minValueExpr) {\n minValue = minValueExpr.value;\n }\n }\n else if (fillRule.linearGradient3) {\n var maxColorExpr = fillRule.linearGradient3.max.color;\n var midColorExpr = fillRule.linearGradient3.mid.color;\n var minColorExpr = fillRule.linearGradient3.min.color;\n var maxValueExpr = fillRule.linearGradient3.max.value;\n var midValueExpr = fillRule.linearGradient3.mid.value;\n var minValueExpr = fillRule.linearGradient3.min.value;\n maxColor = maxColorExpr.value;\n midColor = midColorExpr.value;\n minColor = minColorExpr.value;\n if (maxValueExpr) {\n maxValue = maxValueExpr.value;\n }\n if (midValueExpr) {\n midValue = midValueExpr.value;\n }\n if (minValueExpr) {\n minValue = minValueExpr.value;\n }\n }\n return {\n diverging: diverging,\n minColor: minColor,\n midColor: midColor,\n maxColor: maxColor,\n minValue: minValue,\n midValue: midValue,\n maxValue: maxValue,\n };\n }\n GradientUtils.getGradientSettingsFromRule = getGradientSettingsFromRule;\n /** Returns a string representing the gradient to be used for the GradientBar directive. */\n function getGradientBarColors(gradientSettings) {\n var colors = [];\n colors.push(gradientSettings.minColor);\n if (gradientSettings.diverging) {\n colors.push(gradientSettings.midColor);\n }\n colors.push(gradientSettings.maxColor);\n return colors.join(\",\");\n }\n GradientUtils.getGradientBarColors = getGradientBarColors;\n function getLinearGradien2FillRuleDefinition(baseFillRule) {\n var gradientSettings = getGradientSettings(baseFillRule);\n var fillRuleDefinition = {\n linearGradient2: {\n max: { color: SQExprBuilder.text(gradientSettings.maxColor) },\n min: { color: SQExprBuilder.text(gradientSettings.minColor) },\n }\n };\n return fillRuleDefinition;\n }\n function getLinearGradien3FillRuleDefinition(baseFillRule) {\n var gradientSettings = getGradientSettings(baseFillRule);\n var fillRuleDefinition = {\n linearGradient3: {\n max: { color: SQExprBuilder.text(gradientSettings.maxColor) },\n mid: { color: SQExprBuilder.text(gradientSettings.midColor) },\n min: { color: SQExprBuilder.text(gradientSettings.minColor) },\n }\n };\n return fillRuleDefinition;\n }\n function getDefaultColorExpression(fillRule, propertyName) {\n var defaultColor;\n var defaultFillRule;\n if (fillRule.linearGradient3) {\n defaultFillRule = getLinearGradien3FillRuleDefinition();\n if (propertyName === \"minColor\") {\n defaultColor = defaultFillRule.linearGradient3.min.color;\n }\n else if (propertyName === \"midColor\") {\n defaultColor = defaultFillRule.linearGradient3.mid.color;\n }\n else if (propertyName === \"maxColor\") {\n defaultColor = defaultFillRule.linearGradient3.max.color;\n }\n }\n else if (fillRule.linearGradient2) {\n defaultFillRule = getLinearGradien2FillRuleDefinition();\n if (propertyName === \"minColor\") {\n defaultColor = defaultFillRule.linearGradient2.min.color;\n }\n else if (propertyName === \"maxColor\") {\n defaultColor = defaultFillRule.linearGradient2.max.color;\n }\n }\n return defaultColor;\n }\n function getColorExpressionValue(fillRule, propertyName, propertyValue) {\n var colorExpressionValue;\n if (propertyValue) {\n colorExpressionValue = SQExprBuilder.text(propertyValue);\n }\n else {\n colorExpressionValue = getDefaultColorExpression(fillRule, propertyName);\n }\n return colorExpressionValue;\n }\n function updateMinColor(fillRule, colorExpressionValue) {\n if (fillRule.linearGradient2) {\n fillRule.linearGradient2.min.color = colorExpressionValue;\n }\n else if (fillRule.linearGradient3) {\n fillRule.linearGradient3.min.color = colorExpressionValue;\n }\n }\n function updateMidColor(fillRule, colorExpressionValue) {\n if (fillRule.linearGradient3) {\n fillRule.linearGradient3.mid.color = colorExpressionValue;\n }\n }\n function updateMaxColor(fillRule, colorExpressionValue) {\n if (fillRule.linearGradient2) {\n fillRule.linearGradient2.max.color = colorExpressionValue;\n }\n else if (fillRule.linearGradient3) {\n fillRule.linearGradient3.max.color = colorExpressionValue;\n }\n }\n function updateMinValue(fillRule, value) {\n if (fillRule.linearGradient2) {\n fillRule.linearGradient2.min.value = value;\n }\n else if (fillRule.linearGradient3) {\n fillRule.linearGradient3.min.value = value;\n }\n }\n function updateMidValue(fillRule, value) {\n if (fillRule.linearGradient3) {\n fillRule.linearGradient3.mid.value = value;\n }\n }\n function updateMaxValue(fillRule, value) {\n if (fillRule.linearGradient2) {\n fillRule.linearGradient2.max.value = value;\n }\n else if (fillRule.linearGradient3) {\n fillRule.linearGradient3.max.value = value;\n }\n }\n })(GradientUtils = visuals.GradientUtils || (visuals.GradientUtils = {}));\n ;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var visualBackgroundHelper;\n (function (visualBackgroundHelper) {\n function getDefaultColor() {\n return '#FFF';\n }\n visualBackgroundHelper.getDefaultColor = getDefaultColor;\n function getDefaultTransparency() {\n return 50;\n }\n visualBackgroundHelper.getDefaultTransparency = getDefaultTransparency;\n function getDefaultShow() {\n return false;\n }\n visualBackgroundHelper.getDefaultShow = getDefaultShow;\n function getDefaultValues() {\n return {\n color: getDefaultColor(),\n transparency: getDefaultTransparency(),\n show: getDefaultShow()\n };\n }\n visualBackgroundHelper.getDefaultValues = getDefaultValues;\n function enumeratePlot(enumeration, background) {\n var transparency = (background && background.transparency);\n if (transparency == null)\n transparency = getDefaultTransparency();\n var backgroundObject = {\n selector: null,\n properties: {\n transparency: transparency,\n image: (background && background.image)\n },\n objectName: 'plotArea',\n };\n enumeration.pushInstance(backgroundObject);\n }\n visualBackgroundHelper.enumeratePlot = enumeratePlot;\n function renderBackgroundImage(background, visualElement, layout) {\n var image = background && background.image;\n var imageUrl = image && image.url;\n var imageFit = image && image.scaling;\n var imageTransparency = background && background.transparency;\n var backgroundImage = visualElement.children('.background-image');\n // If there were image and it was removed\n if (!imageUrl) {\n if (backgroundImage.length !== 0)\n backgroundImage.remove();\n return;\n }\n // If this is the first edit of the image\n if (backgroundImage.length === 0) {\n // Place the div only if the image exists in order to keep the html as clean as possible\n visualElement.prepend('<div class=\"background-image\"></div>');\n backgroundImage = visualElement.children('.background-image');\n // the div should be positioned absolute in order to get on top of the sibling svg\n backgroundImage.css('position', 'absolute');\n }\n // Get the size and margins from the visual for the div will placed inside the plot area\n backgroundImage.css({\n 'width': layout.width,\n 'height': layout.height,\n 'margin-left': layout.left,\n 'margin-top': layout.top,\n });\n // Background properties\n backgroundImage.css({\n 'background-image': 'url(' + imageUrl + ')',\n 'background-repeat': 'no-repeat',\n 'opacity': (100 - imageTransparency) / 100,\n });\n switch (imageFit) {\n // The image will be centered in its initial size\n case visuals.imageScalingType.normal: {\n backgroundImage.css({\n 'background-size': '',\n 'background-position': '50% 50%',\n });\n break;\n }\n // The image will be streched all over the background\n case visuals.imageScalingType.fit: {\n backgroundImage.css({\n 'background-size': '100% 100%',\n 'background-position': '',\n });\n break;\n }\n // The image will stretch on the width and the height will scale accordingly\n case visuals.imageScalingType.fill: {\n backgroundImage.css({\n 'background-size': '100%',\n 'background-position': '50% 50%',\n });\n break;\n }\n default: {\n backgroundImage.css({\n 'background-size': '',\n 'background-position': '50% 50%',\n });\n break;\n }\n }\n }\n visualBackgroundHelper.renderBackgroundImage = renderBackgroundImage;\n })(visualBackgroundHelper = visuals.visualBackgroundHelper || (visuals.visualBackgroundHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Selector = powerbi.data.Selector;\n /**\n * A helper class for building a VisualObjectInstanceEnumerationObject:\n * - Allows call chaining (e.g., builder.pushInstance({...}).pushInstance({...})\n * - Allows creating of containers (via pushContainer/popContainer)\n */\n var ObjectEnumerationBuilder = (function () {\n function ObjectEnumerationBuilder() {\n }\n ObjectEnumerationBuilder.prototype.pushInstance = function (instance) {\n debug.assertValue(instance, 'instance');\n var instances = this.instances;\n if (!instances) {\n instances = this.instances = [];\n }\n var containerIdx = this.containerIdx;\n if (containerIdx != null) {\n instance.containerIdx = containerIdx;\n }\n // Attempt to merge with an existing item if possible.\n for (var _i = 0, instances_1 = instances; _i < instances_1.length; _i++) {\n var existingInstance = instances_1[_i];\n if (this.canMerge(existingInstance, instance)) {\n this.extend(existingInstance, instance, 'properties');\n this.extend(existingInstance, instance, 'validValues');\n return this;\n }\n }\n instances.push(instance);\n return this;\n };\n ObjectEnumerationBuilder.prototype.pushContainer = function (container) {\n debug.assertValue(container, 'container');\n var containers = this.containers;\n if (!containers) {\n containers = this.containers = [];\n }\n var updatedLen = containers.push(container);\n this.containerIdx = updatedLen - 1;\n return this;\n };\n ObjectEnumerationBuilder.prototype.popContainer = function () {\n this.containerIdx = undefined;\n return this;\n };\n ObjectEnumerationBuilder.prototype.complete = function () {\n if (!this.instances)\n return;\n var result = {\n instances: this.instances,\n };\n var containers = this.containers;\n if (containers) {\n result.containers = containers;\n }\n return result;\n };\n ObjectEnumerationBuilder.prototype.canMerge = function (x, y) {\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n return x.objectName === y.objectName &&\n x.containerIdx === y.containerIdx &&\n Selector.equals(x.selector, y.selector);\n };\n ObjectEnumerationBuilder.prototype.extend = function (target, source, propertyName) {\n debug.assertValue(target, 'target');\n debug.assertValue(source, 'source');\n debug.assertValue(propertyName, 'propertyName');\n var sourceValues = source[propertyName];\n if (!sourceValues)\n return;\n var targetValues = target[propertyName];\n if (!targetValues)\n targetValues = target[propertyName] = {};\n for (var valuePropertyName in sourceValues) {\n if (targetValues[valuePropertyName]) {\n // Properties have first-writer-wins semantics.\n continue;\n }\n targetValues[valuePropertyName] = sourceValues[valuePropertyName];\n }\n };\n ObjectEnumerationBuilder.merge = function (x, y) {\n var xNormalized = ObjectEnumerationBuilder.normalize(x);\n var yNormalized = ObjectEnumerationBuilder.normalize(y);\n if (!xNormalized || !yNormalized)\n return xNormalized || yNormalized;\n debug.assertValue(xNormalized, 'xNormalized');\n debug.assertValue(yNormalized, 'yNormalized');\n var xCategoryCount = xNormalized.containers ? xNormalized.containers.length : 0;\n for (var _i = 0, _a = yNormalized.instances; _i < _a.length; _i++) {\n var yInstance = _a[_i];\n xNormalized.instances.push(yInstance);\n if (yInstance.containerIdx != null)\n yInstance.containerIdx += xCategoryCount;\n }\n var yContainers = yNormalized.containers;\n if (!_.isEmpty(yContainers)) {\n if (xNormalized.containers)\n Array.prototype.push.apply(xNormalized.containers, yContainers);\n else\n xNormalized.containers = yContainers;\n }\n return xNormalized;\n };\n ObjectEnumerationBuilder.normalize = function (x) {\n debug.assertAnyValue(x, 'x');\n if (_.isArray(x)) {\n return { instances: x };\n }\n return x;\n };\n ObjectEnumerationBuilder.getContainerForInstance = function (enumeration, instance) {\n debug.assertValue(enumeration, \"enumeration\");\n debug.assertValue(instance, \"instance\");\n debug.assertValue(enumeration.containers, \"containers\");\n debug.assert(enumeration.containers.length > instance.containerIdx, \"no container found in containers collection\");\n return enumeration.containers[instance.containerIdx];\n };\n return ObjectEnumerationBuilder;\n }());\n visuals.ObjectEnumerationBuilder = ObjectEnumerationBuilder;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /** Helper class for Visual border styles */\n var VisualBorderUtil;\n (function (VisualBorderUtil) {\n /**\n * Gets The Boder Width string (e.g. 0px 1px 2px 3px)\n * @param {OutlineType} string Type of the Outline, one of Visuals.outline.<XX> const strings\n * @param {number} outlineWeight Weight of the outline in pixels\n * @returns String representing the Border Width\n */\n function getBorderWidth(outlineType, outlineWeight) {\n switch (outlineType) {\n case visuals.outline.none:\n return '0px';\n case visuals.outline.bottomOnly:\n return '0px 0px ' + outlineWeight + 'px 0px';\n case visuals.outline.topOnly:\n return outlineWeight + 'px 0px 0px 0px';\n case visuals.outline.leftOnly:\n return '0px 0px 0px ' + outlineWeight + 'px';\n case visuals.outline.rightOnly:\n return '0px ' + outlineWeight + 'px 0px 0px';\n case visuals.outline.topBottom:\n return outlineWeight + 'px 0px';\n case visuals.outline.leftRight:\n return '0px ' + outlineWeight + 'px';\n case visuals.outline.frame:\n return outlineWeight + 'px';\n default:\n debug.assertFail('Unexpected OutlineType value: ' + outlineType);\n return '0px';\n }\n }\n VisualBorderUtil.getBorderWidth = getBorderWidth;\n })(VisualBorderUtil = visuals.VisualBorderUtil || (visuals.VisualBorderUtil = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /** Transformation matrix math wrapper */\n var Transform = (function () {\n // Constructor\n function Transform(m) {\n this.matrix = m || {\n m00: 1, m01: 0, m02: 0,\n m10: 0, m11: 1, m12: 0,\n };\n }\n // Methods\n Transform.prototype.applyToPoint = function (point) {\n if (!point) {\n return point;\n }\n var m = this.matrix;\n return {\n x: m.m00 * point.x + m.m01 * point.y + m.m02,\n y: m.m10 * point.x + m.m11 * point.y + m.m12,\n };\n };\n Transform.prototype.applyToRect = function (rect) {\n if (!rect) {\n return rect;\n }\n var x0 = rect.left;\n var y0 = rect.top;\n var m = this.matrix;\n var isScaled = m.m00 !== 1 || m.m11 !== 1;\n var isRotated = m.m01 !== 0 || m.m10 !== 0;\n if (!isRotated && !isScaled) {\n // Optimize for the translation only case\n return { left: x0 + m.m02, top: y0 + m.m12, width: rect.width, height: rect.height };\n }\n var x1 = rect.left + rect.width;\n var y1 = rect.top + rect.height;\n var minX;\n var maxX;\n var minY;\n var maxY;\n if (isRotated) {\n var p0x = m.m00 * x0 + m.m01 * y0 + m.m02;\n var p0y = m.m10 * x0 + m.m11 * y0 + m.m12;\n var p1x = m.m00 * x0 + m.m01 * y1 + m.m02;\n var p1y = m.m10 * x0 + m.m11 * y1 + m.m12;\n var p2x = m.m00 * x1 + m.m01 * y0 + m.m02;\n var p2y = m.m10 * x1 + m.m11 * y0 + m.m12;\n var p3x = m.m00 * x1 + m.m01 * y1 + m.m02;\n var p3y = m.m10 * x1 + m.m11 * y1 + m.m12;\n minX = Math.min(p0x, p1x, p2x, p3x);\n maxX = Math.max(p0x, p1x, p2x, p3x);\n minY = Math.min(p0y, p1y, p2y, p3y);\n maxY = Math.max(p0y, p1y, p2y, p3y);\n }\n else {\n var p0x = m.m00 * x0 + m.m02;\n var p0y = m.m11 * y0 + m.m12;\n var p3x = m.m00 * x1 + m.m02;\n var p3y = m.m11 * y1 + m.m12;\n minX = Math.min(p0x, p3x);\n maxX = Math.max(p0x, p3x);\n minY = Math.min(p0y, p3y);\n maxY = Math.max(p0y, p3y);\n }\n return { left: minX, top: minY, width: maxX - minX, height: maxY - minY };\n };\n Transform.prototype.translate = function (xOffset, yOffset) {\n if (xOffset !== 0 || yOffset !== 0) {\n var m = createTranslateMatrix(xOffset, yOffset);\n this.matrix = multiplyMatrices(this.matrix, m);\n this._inverse = null;\n }\n };\n Transform.prototype.scale = function (xScale, yScale) {\n if (xScale !== 1 || yScale !== 1) {\n var m = createScaleMatrix(xScale, yScale);\n this.matrix = multiplyMatrices(this.matrix, m);\n this._inverse = null;\n }\n };\n Transform.prototype.rotate = function (angleInRadians) {\n if (angleInRadians !== 0) {\n var m = createRotationMatrix(angleInRadians);\n this.matrix = multiplyMatrices(this.matrix, m);\n this._inverse = null;\n }\n };\n Transform.prototype.add = function (other) {\n if (other) {\n this.matrix = multiplyMatrices(this.matrix, other.matrix);\n this._inverse = null;\n }\n };\n Transform.prototype.getInverse = function () {\n if (!this._inverse) {\n this._inverse = new Transform(createInverseMatrix(this.matrix));\n }\n return this._inverse;\n };\n return Transform;\n }());\n visuals.Transform = Transform;\n function createTranslateMatrix(xOffset, yOffset) {\n return {\n m00: 1, m01: 0, m02: xOffset,\n m10: 0, m11: 1, m12: yOffset,\n };\n }\n visuals.createTranslateMatrix = createTranslateMatrix;\n function createScaleMatrix(xScale, yScale) {\n return {\n m00: xScale, m01: 0, m02: 0,\n m10: 0, m11: yScale, m12: 0\n };\n }\n visuals.createScaleMatrix = createScaleMatrix;\n function createRotationMatrix(angleInRads) {\n var a = angleInRads;\n var sinA = Math.sin(a);\n var cosA = Math.cos(a);\n return {\n m00: cosA, m01: -sinA, m02: 0,\n m10: sinA, m11: cosA, m12: 0,\n };\n }\n visuals.createRotationMatrix = createRotationMatrix;\n function createInverseMatrix(m) {\n var determinant = m.m00 * m.m11 - m.m01 * m.m10;\n var invdet = 1 / determinant;\n return {\n m00: m.m11 * invdet,\n m01: -m.m01 * invdet,\n m02: (m.m01 * m.m12 - m.m02 * m.m11) * invdet,\n m10: -m.m10 * invdet,\n m11: m.m00 * invdet,\n m12: -(m.m00 * m.m12 - m.m10 * m.m02) * invdet\n };\n }\n visuals.createInverseMatrix = createInverseMatrix;\n function multiplyMatrices(a, b) {\n return {\n m00: a.m00 * b.m00 + a.m01 * b.m10,\n m01: a.m00 * b.m01 + a.m01 * b.m11,\n m02: a.m00 * b.m02 + a.m01 * b.m12 + a.m02,\n m10: a.m10 * b.m00 + a.m11 * b.m10,\n m11: a.m10 * b.m01 + a.m11 * b.m11,\n m12: a.m10 * b.m02 + a.m11 * b.m12 + a.m12,\n };\n }\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Color = jsCommon.Color;\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n var TrendLineHelper;\n (function (TrendLineHelper) {\n var trendLinePropertyNames = {\n show: 'show',\n lineColor: 'lineColor',\n transparency: 'transparency',\n style: 'style',\n combineSeries: 'combineSeries',\n useHighlightValues: 'useHighlightValues',\n };\n var trendObjectName = 'trend';\n TrendLineHelper.defaults = {\n lineColor: { solid: { color: '#000' } },\n lineStyle: visuals.lineStyle.dashed,\n transparency: 0,\n combineSeries: true,\n useHighlightValues: true,\n };\n var TrendLineClassSelector = jsCommon.CssConstants.createClassAndSelector('trend-line');\n var TrendLineLayerClassSelector = jsCommon.CssConstants.createClassAndSelector('trend-line-layer');\n function enumerateObjectInstances(enumeration, trendLines) {\n debug.assertValue(enumeration, 'enumeration');\n if (_.isEmpty(trendLines)) {\n enumeration.pushInstance({\n selector: null,\n properties: {\n show: false,\n lineColor: TrendLineHelper.defaults.lineColor,\n transparency: TrendLineHelper.defaults.transparency,\n style: TrendLineHelper.defaults.lineStyle,\n combineSeries: TrendLineHelper.defaults.combineSeries,\n },\n objectName: trendObjectName,\n });\n return;\n }\n var trendLine = trendLines[0];\n var properties = {};\n properties['show'] = trendLine.show;\n if (trendLine.combineSeries)\n properties['lineColor'] = trendLine.lineColor;\n properties['transparency'] = trendLine.transparency;\n properties['style'] = trendLine.style;\n properties['combineSeries'] = trendLine.combineSeries;\n properties['useHighlightValues'] = trendLine.useHighlightValues;\n enumeration.pushInstance({\n selector: null,\n properties: properties,\n objectName: trendObjectName,\n });\n }\n TrendLineHelper.enumerateObjectInstances = enumerateObjectInstances;\n function isDataViewForRegression(dataView) {\n return DataRoleHelper.hasRoleInDataView(dataView, 'regression.X');\n }\n TrendLineHelper.isDataViewForRegression = isDataViewForRegression;\n function readDataView(dataView, sourceDataView, y2, colors) {\n if (!dataView || !dataView.categorical)\n return;\n var categorical = dataView.categorical;\n if (_.isEmpty(categorical.categories) || _.isEmpty(categorical.values))\n return;\n var categories = categorical.categories[0].values;\n var groups = categorical.values.grouped();\n if (!categories || !groups)\n return;\n var trendProperties = powerbi.DataViewObjects.getObject(dataView.metadata.objects, trendObjectName, {});\n var show = powerbi.DataViewObject.getValue(trendProperties, trendLinePropertyNames.show, false);\n var lineColor = powerbi.DataViewObject.getValue(trendProperties, trendLinePropertyNames.lineColor);\n var transparency = powerbi.DataViewObject.getValue(trendProperties, trendLinePropertyNames.transparency, TrendLineHelper.defaults.transparency);\n var style = powerbi.DataViewObject.getValue(trendProperties, trendLinePropertyNames.style, TrendLineHelper.defaults.lineStyle);\n var combineSeries = powerbi.DataViewObject.getValue(trendProperties, trendLinePropertyNames.combineSeries, TrendLineHelper.defaults.combineSeries);\n var useHighlightValues = powerbi.DataViewObject.getValue(trendProperties, trendLinePropertyNames.useHighlightValues, TrendLineHelper.defaults.useHighlightValues);\n // Trend lines generated by Insights will be putting line color here, we should convert the Insights code to create\n // \"trend\" objects like above and write the upgrade code to handle pinned tiles with trend lines before removing any feature switch.\n var legacyColor = powerbi.DataViewObjects.getValue(categorical.values[0].source.objects, visuals.lineChartProps.dataPoint.fill);\n if (legacyColor)\n lineColor = legacyColor;\n var objects = sourceDataView.metadata.objects;\n var defaultColor = powerbi.DataViewObjects.getFillColor(objects, { objectName: 'dataPoint', propertyName: 'defaultColor' });\n var colorHelper = new visuals.ColorHelper(colors, { objectName: 'dataPoint', propertyName: 'fill' }, defaultColor);\n var trendLines = [];\n for (var groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n var group = groups[groupIndex];\n var points = [];\n for (var i = 0; i < categories.length; i++) {\n var x = visuals.AxisHelper.normalizeNonFiniteNumber(categories[i]);\n // There is a assumption here that the group only has 1 set of values in it. Once we add more things like confidence bands,\n // this assumption will not be true. This assumption comes from the way dataViewRegresion generates the dataView\n var valueColumn = group.values[0];\n var values = void 0;\n if (useHighlightValues && valueColumn.highlights) {\n values = valueColumn.highlights;\n }\n else {\n values = valueColumn.values;\n }\n var y = visuals.AxisHelper.normalizeNonFiniteNumber(values[i]);\n if (x != null && y != null) {\n points.push({\n x: x,\n y: y,\n });\n }\n }\n var seriesLineColor = void 0;\n if (combineSeries) {\n seriesLineColor = lineColor || TrendLineHelper.defaults.lineColor;\n }\n else {\n // TODO: This should likely be delegated to the layer which knows how to choose the correct color for any given situation.\n if (sourceDataView.categorical.values.source) {\n // Dynamic series\n var sourceGroups = sourceDataView.categorical.values.grouped();\n var color = colorHelper.getColorForSeriesValue(sourceGroups[groupIndex].objects, sourceDataView.categorical.values.identityFields, group.name);\n color = darkenTrendLineColor(color);\n seriesLineColor = { solid: { color: color } };\n }\n else {\n // Static series\n var matchingMeasure = sourceDataView.categorical.values[groupIndex];\n var color = colorHelper.getColorForMeasure(matchingMeasure.source.objects, group.name);\n color = darkenTrendLineColor(color);\n seriesLineColor = { solid: { color: color } };\n }\n }\n trendLines.push({\n points: points,\n show: show,\n lineColor: seriesLineColor,\n transparency: transparency,\n style: style,\n combineSeries: combineSeries,\n useHighlightValues: useHighlightValues,\n y2Axis: y2,\n });\n }\n return trendLines;\n }\n TrendLineHelper.readDataView = readDataView;\n function darkenTrendLineColor(color) {\n var rgb = Color.parseColorString(color);\n rgb = Color.darken(rgb, 20);\n return Color.rgbString(rgb);\n }\n TrendLineHelper.darkenTrendLineColor = darkenTrendLineColor;\n function render(trendLines, graphicsContext, axes, viewport) {\n var layer = graphicsContext.select(TrendLineLayerClassSelector.selector);\n if (layer.empty()) {\n layer = graphicsContext.append('svg').classed(TrendLineLayerClassSelector.class, true);\n }\n layer.attr({\n height: viewport.height,\n width: viewport.width\n });\n var lines = layer.selectAll(TrendLineClassSelector.selector).data(trendLines || []);\n lines.enter().append('path').classed(TrendLineClassSelector.class, true);\n lines\n .attr('d', function (d) {\n var xScale = axes.x.scale;\n var yScale = (d.y2Axis && axes.y2) ? axes.y2.scale : axes.y1.scale;\n var pathGen = d3.svg.line()\n .x(function (point) { return xScale(point.x); })\n .y(function (point) { return yScale(point.y); });\n return pathGen(_.filter(d.points, function (point) { return point.x != null && point.y != null; }));\n });\n lines.each(function (d) {\n var line = d3.select(this);\n var style = {};\n style.stroke = d.lineColor.solid.color;\n if (d.transparency != null) {\n style['stroke-opacity'] = (100 - d.transparency) / 100;\n }\n if (d.style === visuals.lineStyle.dashed) {\n style['stroke-dasharray'] = \"5, 5\";\n }\n else if (d.style === visuals.lineStyle.dotted) {\n style['stroke-dasharray'] = \"1, 5\";\n style['stroke-linecap'] = \"round\";\n }\n else if (d.style === visuals.lineStyle.solid) {\n style['stroke-dasharray'] = null;\n style['stroke-linecap'] = null;\n }\n line.style(style);\n });\n lines.exit().remove();\n }\n TrendLineHelper.render = render;\n })(TrendLineHelper = visuals.TrendLineHelper || (visuals.TrendLineHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var visibilityHelper;\n (function (visibilityHelper) {\n /** Helper method that uses jQuery :visible selector to determine if visual is visible.\n Elements are considered visible if they consume space in the document. Visible elements have a width or height that is greater than zero.\n Elements with visibility: hidden or opacity: 0 are considered visible, since they still consume space in the layout.\n */\n function partiallyVisible(element) {\n return element.is(\":visible\");\n }\n visibilityHelper.partiallyVisible = partiallyVisible;\n })(visibilityHelper = visuals.visibilityHelper || (visuals.visibilityHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var Selector = powerbi.data.Selector;\n var VisualObjectRepetition;\n (function (VisualObjectRepetition) {\n /** Determines whether two repetitions are equal. */\n function equals(x, y) {\n // Normalize falsy to null\n x = x || null;\n y = y || null;\n if (x === y)\n return true;\n if (!x !== !y)\n return false;\n debug.assertValue(x, 'x');\n debug.assertValue(y, 'y');\n if (!Selector.equals(x.selector, y.selector))\n return false;\n return _.isEqual(x.objects, y.objects);\n }\n VisualObjectRepetition.equals = equals;\n })(VisualObjectRepetition = powerbi.VisualObjectRepetition || (powerbi.VisualObjectRepetition = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var SemanticFilter = powerbi.data.SemanticFilter;\n var UrlUtils = jsCommon.UrlUtils;\n /** Helper module for converting a DataView into SlicerData. */\n var DataConversion;\n (function (DataConversion) {\n function convert(dataView, localizedSelectAllText, interactivityService, hostServices) {\n debug.assertValue(hostServices, 'hostServices');\n if (!dataView || !dataView.categorical || _.isEmpty(dataView.categorical.categories))\n return;\n var identityFields = dataView.categorical.categories[0].identityFields;\n if (!identityFields)\n return;\n var filter = (dataView.metadata &&\n dataView.metadata.objects &&\n powerbi.DataViewObjects.getValue(dataView.metadata.objects, visuals.slicerProps.filterPropertyIdentifier));\n var analyzer = hostServices.analyzeFilter({\n dataView: dataView,\n defaultValuePropertyId: visuals.slicerProps.defaultValue,\n filter: filter,\n fieldSQExprs: identityFields\n });\n if (!analyzer)\n return;\n var analyzedSemanticFilter = analyzer.filter;\n if (analyzedSemanticFilter && !SemanticFilter.isSameFilter(analyzedSemanticFilter, filter)) {\n interactivityService.handleClearSelection();\n var filterPropertyIdentifier = visuals.slicerProps.filterPropertyIdentifier;\n var properties = {};\n properties[filterPropertyIdentifier.propertyName] = analyzer.filter;\n var instance = {\n objectName: filterPropertyIdentifier.objectName,\n selector: undefined,\n properties: properties\n };\n var changes = {\n merge: [instance]\n };\n hostServices.persistProperties(changes);\n }\n var slicerData = getSlicerData(analyzer, dataView.metadata, dataView.categorical, localizedSelectAllText, interactivityService, hostServices);\n return slicerData;\n }\n DataConversion.convert = convert;\n function getSlicerData(analyzer, dataViewMetadata, categorical, localizedSelectAllText, interactivityService, hostServices) {\n var isInvertedSelectionMode = interactivityService && interactivityService.isSelectionModeInverted();\n var selectedScopeIds = analyzer.selectedIdentities;\n var hasSelectionOverride = !_.isEmpty(selectedScopeIds) || isInvertedSelectionMode === true;\n if (!isInvertedSelectionMode && analyzer.filter)\n isInvertedSelectionMode = analyzer.isNotFilter;\n if (interactivityService) {\n // To indicate whether the selection is Not selected items\n interactivityService.setSelectionModeInverted(isInvertedSelectionMode);\n // defaultValueMode will be used when determine show/hide clear button.\n interactivityService.setDefaultValueMode(SemanticFilter.isDefaultFilter(analyzer.filter));\n }\n var category = categorical.categories[0];\n var categoryValuesLen = category && category.values ? category.values.length : 0;\n var slicerDataPoints = [];\n var formatString = visuals.valueFormatter.getFormatString(category.source, visuals.slicerProps.formatString);\n var numOfSelected = 0;\n var valueCounts = categorical.values && categorical.values[0] && categorical.values[0].values;\n if (valueCounts && _.isEmpty(valueCounts))\n valueCounts = undefined;\n debug.assert(!valueCounts || valueCounts.length === categoryValuesLen, \"valueCounts doesn't match values\");\n var isImageData = dataViewMetadata &&\n !_.isEmpty(dataViewMetadata.columns) && visuals.converterHelper.isImageUrlColumn(dataViewMetadata.columns[0]);\n var displayNameIdentityPairs = [];\n for (var i = 0; i < categoryValuesLen; i++) {\n var scopeId = category.identity && category.identity[i];\n var value = category.values && category.values[i];\n var count = valueCounts && valueCounts[i];\n var isRetained = hasSelectionOverride ? visuals.SlicerUtil.tryRemoveValueFromRetainedList(scopeId, selectedScopeIds) : false;\n var label = visuals.valueFormatter.format(value, formatString);\n var isImage = isImageData === true && UrlUtils.isValidImageUrl(label);\n var slicerData_1 = {\n value: label,\n tooltip: label,\n identity: visuals.SelectionId.createWithId(scopeId),\n selected: isRetained,\n count: count,\n isImage: isImage,\n };\n if (isRetained) {\n var displayNameIdentityPair = {\n displayName: label,\n identity: scopeId\n };\n displayNameIdentityPairs.push(displayNameIdentityPair);\n }\n slicerDataPoints.push(slicerData_1);\n if (slicerData_1.selected)\n numOfSelected++;\n }\n if (!_.isEmpty(displayNameIdentityPairs))\n hostServices.setIdentityDisplayNames(displayNameIdentityPairs);\n // Add retained values that are not in the returned dataview to the value list.\n if (hasSelectionOverride && !_.isEmpty(selectedScopeIds)) {\n var displayNamesIdentityPairs = hostServices.getIdentityDisplayNames(selectedScopeIds);\n if (!_.isEmpty(displayNamesIdentityPairs)) {\n for (var _i = 0, displayNamesIdentityPairs_1 = displayNamesIdentityPairs; _i < displayNamesIdentityPairs_1.length; _i++) {\n var pair = displayNamesIdentityPairs_1[_i];\n // When there is no valueCounts, set count to be undefined, otherwise use 0 as the count for retained values\n var slicerData_2 = {\n value: pair.displayName,\n tooltip: pair.displayName,\n identity: visuals.SelectionId.createWithId(pair.identity),\n selected: true,\n count: valueCounts != null ? 0 : undefined,\n };\n slicerDataPoints.push(slicerData_2);\n numOfSelected++;\n }\n }\n }\n var defaultSettings = createDefaultSettings(dataViewMetadata);\n if (defaultSettings.selection.selectAllCheckboxEnabled) {\n //If selectAllCheckboxEnabled, and all the items are selected and there is no more data to request, then unselect all and toggle the invertedSelectionMode\n if (numOfSelected > 0 && !dataViewMetadata.segment && numOfSelected === slicerDataPoints.length) {\n isInvertedSelectionMode = !isInvertedSelectionMode;\n interactivityService.setSelectionModeInverted(isInvertedSelectionMode);\n for (var _a = 0, slicerDataPoints_1 = slicerDataPoints; _a < slicerDataPoints_1.length; _a++) {\n var item = slicerDataPoints_1[_a];\n item.selected = false;\n }\n hasSelectionOverride = false;\n numOfSelected = 0;\n }\n slicerDataPoints.unshift({\n value: localizedSelectAllText,\n tooltip: localizedSelectAllText,\n identity: visuals.SelectionId.createWithMeasure(localizedSelectAllText),\n selected: !!isInvertedSelectionMode && numOfSelected === 0,\n isSelectAllDataPoint: true,\n count: undefined,\n });\n }\n var slicerData = {\n categorySourceName: category.source.displayName,\n slicerSettings: defaultSettings,\n slicerDataPoints: slicerDataPoints,\n hasSelectionOverride: hasSelectionOverride,\n defaultValue: analyzer.defaultValue,\n };\n return slicerData;\n }\n function createDefaultSettings(dataViewMetadata) {\n var defaultSettings = visuals.Slicer.DefaultStyleProperties();\n var objects = dataViewMetadata.objects;\n var forceSingleSelect = dataViewMetadata.columns && _.some(dataViewMetadata.columns, function (column) { return column.discourageAggregationAcrossGroups; });\n if (objects) {\n defaultSettings.general.outlineColor = powerbi.DataViewObjects.getFillColor(objects, visuals.slicerProps.general.outlineColor, defaultSettings.general.outlineColor);\n defaultSettings.general.outlineWeight = powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.general.outlineWeight, defaultSettings.general.outlineWeight);\n defaultSettings.general.orientation = powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.general.orientation, defaultSettings.general.orientation);\n defaultSettings.header.show = powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.header.show, defaultSettings.header.show);\n defaultSettings.header.fontColor = powerbi.DataViewObjects.getFillColor(objects, visuals.slicerProps.header.fontColor, defaultSettings.header.fontColor);\n var headerBackground = powerbi.DataViewObjects.getFillColor(objects, visuals.slicerProps.header.background);\n if (headerBackground)\n defaultSettings.header.background = headerBackground;\n defaultSettings.header.outline = powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.header.outline, defaultSettings.header.outline);\n defaultSettings.header.textSize = powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.header.textSize, defaultSettings.header.textSize);\n defaultSettings.slicerText.color = powerbi.DataViewObjects.getFillColor(objects, visuals.slicerProps.items.fontColor, defaultSettings.slicerText.color);\n var textBackground = powerbi.DataViewObjects.getFillColor(objects, visuals.slicerProps.items.background);\n if (textBackground)\n defaultSettings.slicerText.background = textBackground;\n defaultSettings.slicerText.outline = powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.items.outline, defaultSettings.slicerText.outline);\n defaultSettings.slicerText.textSize = powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.items.textSize, defaultSettings.slicerText.textSize);\n defaultSettings.selection.selectAllCheckboxEnabled = !forceSingleSelect && powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.selection.selectAllCheckboxEnabled, defaultSettings.selection.selectAllCheckboxEnabled);\n defaultSettings.selection.singleSelect = forceSingleSelect || powerbi.DataViewObjects.getValue(objects, visuals.slicerProps.selection.singleSelect, defaultSettings.selection.singleSelect);\n }\n return defaultSettings;\n }\n })(DataConversion = visuals.DataConversion || (visuals.DataConversion = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var shapes = powerbi.visuals.shapes;\n /**\n * Rectangle orientation. Rectangle orientation is used to define vertical or horizontal orientation\n * and starting/ending side of the rectangle.\n */\n (function (RectOrientation) {\n /** Rectangle with no specific orientation. */\n RectOrientation[RectOrientation[\"None\"] = 0] = \"None\";\n /** Vertical rectangle with base at the bottom. */\n RectOrientation[RectOrientation[\"VerticalBottomTop\"] = 1] = \"VerticalBottomTop\";\n /** Vertical rectangle with base at the top. */\n RectOrientation[RectOrientation[\"VerticalTopBottom\"] = 2] = \"VerticalTopBottom\";\n /** Horizontal rectangle with base at the left. */\n RectOrientation[RectOrientation[\"HorizontalLeftRight\"] = 3] = \"HorizontalLeftRight\";\n /** Horizontal rectangle with base at the right. */\n RectOrientation[RectOrientation[\"HorizontalRightLeft\"] = 4] = \"HorizontalRightLeft\";\n })(powerbi.RectOrientation || (powerbi.RectOrientation = {}));\n var RectOrientation = powerbi.RectOrientation;\n /**\n * Defines if panel elements are allowed to be positioned\n * outside of the panel boundaries.\n */\n (function (OutsidePlacement) {\n /** Elements can be positioned outside of the panel. */\n OutsidePlacement[OutsidePlacement[\"Allowed\"] = 0] = \"Allowed\";\n /** Elements can not be positioned outside of the panel. */\n OutsidePlacement[OutsidePlacement[\"Disallowed\"] = 1] = \"Disallowed\";\n /** Elements can be partially outside of the panel. */\n OutsidePlacement[OutsidePlacement[\"Partial\"] = 2] = \"Partial\";\n })(powerbi.OutsidePlacement || (powerbi.OutsidePlacement = {}));\n var OutsidePlacement = powerbi.OutsidePlacement;\n /**\n * Arranges label elements using the anchor point or rectangle. Collisions\n * between elements can be automatically detected and as a result elements\n * can be repositioned or get hidden.\n */\n var DataLabelManager = (function () {\n function DataLabelManager() {\n this.movingStep = 3;\n this.hideOverlapped = true;\n // The global settings for all labels. \n // They can be oweridden by each label we add into the panel, because contains same properties.\n this.defaultDataLabelSettings = {\n anchorMargin: DataLabelManager.DefaultAnchorMargin,\n anchorRectOrientation: RectOrientation.None,\n contentPosition: 128 /* BottomCenter */,\n outsidePlacement: OutsidePlacement.Disallowed,\n maximumMovingDistance: DataLabelManager.DefaultMaximumMovingDistance,\n minimumMovingDistance: DataLabelManager.DefaultMinimumMovingDistance,\n validContentPositions: 128 /* BottomCenter */,\n opacity: 1\n };\n }\n Object.defineProperty(DataLabelManager.prototype, \"defaultSettings\", {\n get: function () {\n return this.defaultDataLabelSettings;\n },\n enumerable: true,\n configurable: true\n });\n /** Arranges the lables position and visibility*/\n DataLabelManager.prototype.hideCollidedLabels = function (viewport, data, layout, addTransform) {\n if (addTransform === void 0) { addTransform = false; }\n // Split size into a grid\n var arrangeGrid = new DataLabelArrangeGrid(viewport, data, layout);\n var filteredData = [];\n var transform = { x: 0, y: 0 };\n if (addTransform) {\n transform.x = viewport.width / 2;\n transform.y = viewport.height / 2;\n }\n for (var i = 0, len = data.length; i < len; i++) {\n // Filter unwanted data points\n if (!layout.filter(data[i]))\n continue;\n // Set default values where properties values are undefined\n var info = this.getLabelInfo(data[i]);\n info.anchorPoint = {\n x: layout.labelLayout.x(data[i]) + transform.x,\n y: layout.labelLayout.y(data[i]) + transform.y,\n };\n var position = this.calculateContentPosition(info, info.contentPosition, data[i].size, info.anchorMargin);\n if (DataLabelManager.isValid(position) && !this.hasCollisions(arrangeGrid, info, position, viewport)) {\n data[i].labelX = position.left - transform.x;\n data[i].labelY = position.top - transform.y;\n // Keep track of all panel elements positions.\n arrangeGrid.add(info, position);\n // Save all data points to display\n filteredData.push(data[i]);\n }\n }\n return filteredData;\n };\n /**\n * Merges the label element info with the panel element info and returns correct label info.\n * @param source The label info.\n */\n DataLabelManager.prototype.getLabelInfo = function (source) {\n var settings = this.defaultDataLabelSettings;\n source.anchorMargin = source.anchorMargin !== undefined ? source.anchorMargin : settings.anchorMargin;\n source.anchorRectOrientation = source.anchorRectOrientation !== undefined ? source.anchorRectOrientation : settings.anchorRectOrientation;\n source.contentPosition = source.contentPosition !== undefined ? source.contentPosition : settings.contentPosition;\n source.maximumMovingDistance = source.maximumMovingDistance !== undefined ? source.maximumMovingDistance : settings.maximumMovingDistance;\n source.minimumMovingDistance = source.minimumMovingDistance !== undefined ? source.minimumMovingDistance : settings.minimumMovingDistance;\n source.outsidePlacement = source.outsidePlacement !== undefined ? source.outsidePlacement : settings.outsidePlacement;\n source.validContentPositions = source.validContentPositions !== undefined ? source.validContentPositions : settings.validContentPositions;\n source.opacity = source.opacity !== undefined ? source.opacity : settings.opacity;\n source.maximumMovingDistance += source.anchorMargin;\n return source;\n };\n /**\n * (Private) Calculates element position using anchor point..\n */\n DataLabelManager.prototype.calculateContentPositionFromPoint = function (anchorPoint, contentPosition, contentSize, offset) {\n var position = { x: 0, y: 0 };\n if (anchorPoint) {\n if (anchorPoint.x !== undefined && isFinite(anchorPoint.x)) {\n position.x = anchorPoint.x;\n switch (contentPosition) {\n // D3 positions the label in the middle by default.\n // The algorithem asumed the label was positioned in right so this is why we add/substract half width\n case 1 /* TopLeft */:\n case 8 /* MiddleLeft */:\n case 64 /* BottomLeft */:\n position.x -= contentSize.width / 2.0;\n break;\n case 4 /* TopRight */:\n case 32 /* MiddleRight */:\n case 256 /* BottomRight */:\n position.x += contentSize.width / 2.0;\n break;\n }\n }\n if (anchorPoint.y !== undefined && isFinite(anchorPoint.y)) {\n position.y = anchorPoint.y;\n switch (contentPosition) {\n case 8 /* MiddleLeft */:\n case 16 /* MiddleCenter */:\n case 32 /* MiddleRight */:\n position.y -= contentSize.height / 2.0;\n break;\n case 4 /* TopRight */:\n case 1 /* TopLeft */:\n case 2 /* TopCenter */:\n position.y -= contentSize.height;\n break;\n }\n }\n if (offset !== undefined && isFinite(offset)) {\n switch (contentPosition) {\n case 1 /* TopLeft */:\n position.x -= offset;\n position.y -= offset;\n break;\n case 8 /* MiddleLeft */:\n position.x -= offset;\n break;\n case 64 /* BottomLeft */:\n position.x -= offset;\n position.y += offset;\n break;\n case 2 /* TopCenter */:\n position.y -= offset;\n break;\n case 16 /* MiddleCenter */:\n // Offset is not applied\n break;\n case 128 /* BottomCenter */:\n position.y += offset;\n break;\n case 4 /* TopRight */:\n position.x += offset;\n position.y -= offset;\n break;\n case 32 /* MiddleRight */:\n position.x += offset;\n break;\n case 256 /* BottomRight */:\n position.x += offset;\n position.y += offset;\n break;\n default:\n debug.assertFail(\"Unsupported content position.\");\n break;\n }\n }\n }\n return { left: position.x, top: position.y, width: contentSize.width, height: contentSize.height };\n };\n /** (Private) Calculates element position using anchor rect. */\n DataLabelManager.prototype.calculateContentPositionFromRect = function (anchorRect, anchorRectOrientation, contentPosition, contentSize, offset) {\n switch (contentPosition) {\n case 512 /* InsideCenter */:\n return this.handleInsideCenterPosition(anchorRectOrientation, contentSize, anchorRect, offset);\n case 2048 /* InsideEnd */:\n return this.handleInsideEndPosition(anchorRectOrientation, contentSize, anchorRect, offset);\n case 1024 /* InsideBase */:\n return this.handleInsideBasePosition(anchorRectOrientation, contentSize, anchorRect, offset);\n case 8192 /* OutsideEnd */:\n return this.handleOutsideEndPosition(anchorRectOrientation, contentSize, anchorRect, offset);\n case 4096 /* OutsideBase */:\n return this.handleOutsideBasePosition(anchorRectOrientation, contentSize, anchorRect, offset);\n default:\n debug.assertFail(\"Unsupported ContentPosition.\");\n }\n return { left: 0, top: 0, width: -1, height: -1 };\n };\n /** (Private) Calculates element inside center position using anchor rect. */\n DataLabelManager.prototype.handleInsideCenterPosition = function (anchorRectOrientation, contentSize, anchorRect, offset) {\n switch (anchorRectOrientation) {\n case RectOrientation.VerticalBottomTop:\n case RectOrientation.VerticalTopBottom:\n return LocationConverter.middleVertical(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalLeftRight:\n case RectOrientation.HorizontalRightLeft:\n default:\n return LocationConverter.middleHorizontal(contentSize, anchorRect, offset);\n }\n };\n /** (Private) Calculates element inside end position using anchor rect. */\n DataLabelManager.prototype.handleInsideEndPosition = function (anchorRectOrientation, contentSize, anchorRect, offset) {\n switch (anchorRectOrientation) {\n case RectOrientation.VerticalBottomTop:\n return LocationConverter.topInside(contentSize, anchorRect, offset);\n case RectOrientation.VerticalTopBottom:\n return LocationConverter.bottomInside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalRightLeft:\n return LocationConverter.leftInside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalLeftRight:\n default:\n return LocationConverter.rightInside(contentSize, anchorRect, offset);\n }\n };\n /** (Private) Calculates element inside base position using anchor rect. */\n DataLabelManager.prototype.handleInsideBasePosition = function (anchorRectOrientation, contentSize, anchorRect, offset) {\n switch (anchorRectOrientation) {\n case RectOrientation.VerticalBottomTop:\n return LocationConverter.bottomInside(contentSize, anchorRect, offset);\n case RectOrientation.VerticalTopBottom:\n return LocationConverter.topInside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalRightLeft:\n return LocationConverter.rightInside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalLeftRight:\n default:\n return LocationConverter.leftInside(contentSize, anchorRect, offset);\n }\n };\n /** (Private) Calculates element outside end position using anchor rect. */\n DataLabelManager.prototype.handleOutsideEndPosition = function (anchorRectOrientation, contentSize, anchorRect, offset) {\n switch (anchorRectOrientation) {\n case RectOrientation.VerticalBottomTop:\n return LocationConverter.topOutside(contentSize, anchorRect, offset);\n case RectOrientation.VerticalTopBottom:\n return LocationConverter.bottomOutside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalRightLeft:\n return LocationConverter.leftOutside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalLeftRight:\n default:\n return LocationConverter.rightOutside(contentSize, anchorRect, offset);\n }\n };\n /** (Private) Calculates element outside base position using anchor rect. */\n DataLabelManager.prototype.handleOutsideBasePosition = function (anchorRectOrientation, contentSize, anchorRect, offset) {\n switch (anchorRectOrientation) {\n case RectOrientation.VerticalBottomTop:\n return LocationConverter.bottomOutside(contentSize, anchorRect, offset);\n case RectOrientation.VerticalTopBottom:\n return LocationConverter.topOutside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalRightLeft:\n return LocationConverter.rightOutside(contentSize, anchorRect, offset);\n case RectOrientation.HorizontalLeftRight:\n default:\n return LocationConverter.leftOutside(contentSize, anchorRect, offset);\n }\n };\n /** (Private) Calculates element position. */\n DataLabelManager.prototype.calculateContentPosition = function (anchoredElementInfo, contentPosition, contentSize, offset) {\n if (contentPosition !== 2048 /* InsideEnd */ &&\n contentPosition !== 512 /* InsideCenter */ &&\n contentPosition !== 1024 /* InsideBase */ &&\n contentPosition !== 4096 /* OutsideBase */ &&\n contentPosition !== 8192 /* OutsideEnd */) {\n // Determine position using anchor point.\n return this.calculateContentPositionFromPoint(anchoredElementInfo.anchorPoint, contentPosition, contentSize, offset);\n }\n // Determine position using anchor rectangle.\n return this.calculateContentPositionFromRect(anchoredElementInfo.anchorRect, anchoredElementInfo.anchorRectOrientation, contentPosition, contentSize, offset);\n };\n /** (Private) Check for collisions. */\n DataLabelManager.prototype.hasCollisions = function (arrangeGrid, info, position, size) {\n var rect = shapes.Rect;\n if (arrangeGrid.hasConflict(position)) {\n return true;\n }\n // Since we divide the height by 2 we add it back to the top of the view port so labels won't be cut off\n var intersection = { left: 0, top: position.height / 2, width: size.width, height: size.height };\n intersection = rect.inflate(intersection, { left: DataLabelManager.InflateAmount, top: 0, right: DataLabelManager.InflateAmount, bottom: 0 });\n intersection = rect.intersect(intersection, position);\n if (rect.isEmpty(intersection))\n // Empty rectangle means there is a collision\n return true;\n var lessWithPrecision = powerbi.Double.lessWithPrecision;\n switch (info.outsidePlacement) {\n // D3 positions the label in the middle by default.\n // The algorithem asumed the label was positioned in right so this is why we devide by 2 or 4\n case OutsidePlacement.Disallowed:\n return lessWithPrecision(intersection.width, position.width) ||\n lessWithPrecision(intersection.height, position.height / 2);\n case OutsidePlacement.Partial:\n return lessWithPrecision(intersection.width, position.width / 2) ||\n lessWithPrecision(intersection.height, position.height / 4);\n }\n return false;\n };\n DataLabelManager.isValid = function (rect) {\n return !shapes.Rect.isEmpty(rect) && (rect.width > 0 && rect.height > 0);\n };\n DataLabelManager.DefaultAnchorMargin = 0; // For future use\n DataLabelManager.DefaultMaximumMovingDistance = 12;\n DataLabelManager.DefaultMinimumMovingDistance = 3;\n DataLabelManager.InflateAmount = 5;\n return DataLabelManager;\n }());\n powerbi.DataLabelManager = DataLabelManager;\n /**\n * Utility class to speed up the conflict detection by collecting the arranged items in the DataLabelsPanel.\n */\n var DataLabelArrangeGrid = (function () {\n /**\n * Creates new ArrangeGrid.\n * @param size The available size\n */\n function DataLabelArrangeGrid(size, elements, layout) {\n this.grid = [];\n if (size.width === 0 || size.height === 0) {\n this.cellSize = size;\n this.rowCount = this.colCount = 0;\n }\n var baseProperties = {\n fontFamily: powerbi.visuals.dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: powerbi.visuals.dataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: powerbi.visuals.dataLabelUtils.LabelTextProperties.fontWeight,\n };\n //sets the cell size to be twice of the Max with and Max height of the elements \n this.cellSize = { width: 0, height: 0 };\n for (var i = 0, len = elements.length; i < len; i++) {\n var child = elements[i];\n // Fill label field\n child.labeltext = layout.labelText(child);\n var properties = powerbi.Prototype.inherit(baseProperties);\n properties.text = child.labeltext;\n properties.fontSize = (child.data) ? child.data.labelFontSize :\n child.labelFontSize ? child.labelFontSize : powerbi.visuals.dataLabelUtils.LabelTextProperties.fontSize;\n child.size = {\n width: powerbi.TextMeasurementService.measureSvgTextWidth(properties),\n height: powerbi.TextMeasurementService.estimateSvgTextHeight(properties),\n };\n var w = child.size.width * 2;\n var h = child.size.height * 2;\n if (w > this.cellSize.width)\n this.cellSize.width = w;\n if (h > this.cellSize.height)\n this.cellSize.height = h;\n }\n if (this.cellSize.width === 0)\n this.cellSize.width = size.width;\n if (this.cellSize.height === 0)\n this.cellSize.height = size.height;\n this.colCount = this.getGridRowColCount(this.cellSize.width, size.width, DataLabelArrangeGrid.ARRANGEGRID_MIN_COUNT, DataLabelArrangeGrid.ARRANGEGRID_MAX_COUNT);\n this.rowCount = this.getGridRowColCount(this.cellSize.height, size.height, DataLabelArrangeGrid.ARRANGEGRID_MIN_COUNT, DataLabelArrangeGrid.ARRANGEGRID_MAX_COUNT);\n this.cellSize.width = size.width / this.colCount;\n this.cellSize.height = size.height / this.rowCount;\n var grid = this.grid;\n for (var x = 0; x < this.colCount; x++) {\n grid[x] = [];\n for (var y = 0; y < this.rowCount; y++) {\n grid[x][y] = [];\n }\n }\n }\n /**\n * Register a new label element.\n * @param element The label element to register.\n * @param rect The label element position rectangle.\n */\n DataLabelArrangeGrid.prototype.add = function (element, rect) {\n var indexRect = this.getGridIndexRect(rect);\n var grid = this.grid;\n for (var x = indexRect.left; x < indexRect.right; x++) {\n for (var y = indexRect.top; y < indexRect.bottom; y++) {\n grid[x][y].push({ element: element, rect: rect });\n }\n }\n };\n /**\n * Checks for conflict of given rectangle in registered elements.\n * @param rect The rectengle to check.\n * @return True if conflict is detected.\n */\n DataLabelArrangeGrid.prototype.hasConflict = function (rect) {\n var indexRect = this.getGridIndexRect(rect);\n var grid = this.grid;\n var isIntersecting = shapes.Rect.isIntersecting;\n for (var x = indexRect.left; x < indexRect.right; x++) {\n for (var y = indexRect.top; y < indexRect.bottom; y++) {\n for (var z = 0; z < grid[x][y].length; z++) {\n var item = grid[x][y][z];\n if (isIntersecting(item.rect, rect)) {\n return true;\n }\n }\n }\n }\n return false;\n };\n /**\n * Calculates the number of rows or columns in a grid\n * @param step is the largest label size (width or height)\n * @param length is the grid size (width or height)\n * @param minCount is the minimum allowed size\n * @param maxCount is the maximum allowed size\n * @return the number of grid rows or columns\n */\n DataLabelArrangeGrid.prototype.getGridRowColCount = function (step, length, minCount, maxCount) {\n return Math.min(Math.max(Math.ceil(length / step), minCount), maxCount);\n };\n /**\n * Returns the grid index of a given recangle\n * @param rect The rectengle to check.\n * @return grid index as a thickness object.\n */\n DataLabelArrangeGrid.prototype.getGridIndexRect = function (rect) {\n var restrict = function (n, min, max) { return Math.min(Math.max(n, min), max); };\n return {\n left: restrict(Math.floor(rect.left / this.cellSize.width), 0, this.colCount),\n top: restrict(Math.floor(rect.top / this.cellSize.height), 0, this.rowCount),\n right: restrict(Math.ceil((rect.left + rect.width) / this.cellSize.width), 0, this.colCount),\n bottom: restrict(Math.ceil((rect.top + rect.height) / this.cellSize.height), 0, this.rowCount)\n };\n };\n DataLabelArrangeGrid.ARRANGEGRID_MIN_COUNT = 1;\n DataLabelArrangeGrid.ARRANGEGRID_MAX_COUNT = 100;\n return DataLabelArrangeGrid;\n }());\n powerbi.DataLabelArrangeGrid = DataLabelArrangeGrid;\n /**\n * (Private) Contains methods for calculating the top-left coordinate of rectangle based on content size and anchor rect.\n */\n var LocationConverter;\n (function (LocationConverter) {\n function topInside(size, rect, offset) {\n return {\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\n top: rect.top + offset,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.topInside = topInside;\n function bottomInside(size, rect, offset) {\n return {\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\n top: (rect.top + rect.height) - size.height - offset,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.bottomInside = bottomInside;\n function rightInside(size, rect, offset) {\n return {\n left: (rect.left + rect.width) - size.width - offset,\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.rightInside = rightInside;\n function leftInside(size, rect, offset) {\n return {\n left: rect.left + offset,\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.leftInside = leftInside;\n function topOutside(size, rect, offset) {\n return {\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\n top: rect.top - size.height - offset,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.topOutside = topOutside;\n function bottomOutside(size, rect, offset) {\n return {\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\n top: (rect.top + rect.height) + offset,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.bottomOutside = bottomOutside;\n function rightOutside(size, rect, offset) {\n return {\n left: (rect.left + rect.width) + offset,\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.rightOutside = rightOutside;\n function leftOutside(size, rect, offset) {\n return {\n left: rect.left - size.width - offset,\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.leftOutside = leftOutside;\n function middleHorizontal(size, rect, offset) {\n return {\n left: rect.left + rect.width / 2.0 - size.width / 2.0 + offset,\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.middleHorizontal = middleHorizontal;\n function middleVertical(size, rect, offset) {\n return {\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\n top: rect.top + rect.height / 2.0 - size.height / 2.0 + offset,\n width: size.width,\n height: size.height\n };\n }\n LocationConverter.middleVertical = middleVertical;\n })(LocationConverter || (LocationConverter = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var shapes = powerbi.visuals.shapes;\n var Rect = powerbi.visuals.shapes.Rect;\n var NewDataLabelUtils = powerbi.visuals.NewDataLabelUtils;\n var LabelArrangeGrid = (function () {\n function LabelArrangeGrid(labelDataPointsGroups, viewport) {\n this.viewport = viewport;\n var maxLabelWidth = 0;\n var maxLabelHeight = 0;\n for (var _i = 0, labelDataPointsGroups_1 = labelDataPointsGroups; _i < labelDataPointsGroups_1.length; _i++) {\n var labelDataPointsGroup = labelDataPointsGroups_1[_i];\n for (var _a = 0, _b = labelDataPointsGroup.labelDataPoints; _a < _b.length; _a++) {\n var labelDataPoint = _b[_a];\n if (labelDataPoint.isPreferred) {\n var dataLabelSize = labelDataPoint.labelSize;\n if (dataLabelSize.width > maxLabelWidth) {\n maxLabelWidth = dataLabelSize.width;\n }\n if (dataLabelSize.height > maxLabelHeight) {\n maxLabelHeight = dataLabelSize.height;\n }\n }\n }\n }\n if (maxLabelWidth === 0) {\n maxLabelWidth = viewport.width;\n }\n if (maxLabelHeight === 0) {\n maxLabelHeight = viewport.height;\n }\n var cellSize = this.cellSize = { width: maxLabelWidth * LabelArrangeGrid.cellSizeMultiplier, height: maxLabelHeight * LabelArrangeGrid.cellSizeMultiplier };\n this.columnCount = LabelArrangeGrid.getCellCount(cellSize.width, viewport.width, 1, 100);\n this.rowCount = LabelArrangeGrid.getCellCount(cellSize.height, viewport.height, 1, 100);\n var grid = [];\n for (var i = 0, ilen = this.columnCount; i < ilen; i++) {\n grid[i] = [];\n for (var j = 0, jlen = this.rowCount; j < jlen; j++) {\n grid[i][j] = [];\n }\n }\n this.grid = grid;\n }\n /**\n * Add a rectangle to check collision against\n */\n LabelArrangeGrid.prototype.add = function (rect) {\n var containingIndexRect = this.getContainingGridSubsection(rect);\n for (var x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\n for (var y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\n this.grid[x][y].push(rect);\n }\n }\n };\n /**\n * Check whether the rect conflicts with the grid, either bleeding outside the\n * viewport or colliding with another rect added to the grid.\n */\n LabelArrangeGrid.prototype.hasConflict = function (rect) {\n if (!this.isWithinGridViewport(rect)) {\n return true;\n }\n return this.hasCollision(rect);\n };\n /**\n * Attempt to position the given rect within the viewport. Returns\n * the adjusted rectangle or null if the rectangle couldn't fit,\n * conflicts with the viewport, or is too far outside the viewport\n */\n LabelArrangeGrid.prototype.tryPositionInViewport = function (rect) {\n // If it's too far outside the viewport, return null\n if (!this.isCloseToGridViewport(rect)) {\n return;\n }\n if (!this.isWithinGridViewport(rect)) {\n rect = this.tryMoveInsideViewport(rect);\n }\n if (rect && !this.hasCollision(rect)) {\n return rect;\n }\n };\n /**\n * Checks for a collision between the given rect and others in the grid.\n * Returns true if there is a collision.\n */\n LabelArrangeGrid.prototype.hasCollision = function (rect) {\n var containingIndexRect = this.getContainingGridSubsection(rect);\n var grid = this.grid;\n var isIntersecting = shapes.Rect.isIntersecting;\n for (var x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\n for (var y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\n for (var _i = 0, _a = grid[x][y]; _i < _a.length; _i++) {\n var currentGridRect = _a[_i];\n if (isIntersecting(currentGridRect, rect)) {\n return true;\n }\n }\n }\n }\n return false;\n };\n /**\n * Check to see if the given rect is inside the grid's viewport\n */\n LabelArrangeGrid.prototype.isWithinGridViewport = function (rect) {\n return rect.left >= 0 &&\n rect.top >= 0 &&\n rect.left + rect.width <= this.viewport.width &&\n rect.top + rect.height <= this.viewport.height;\n };\n /**\n * Checks to see if the rect is close enough to the viewport to be moved inside.\n * \"Close\" here is determined by the distance between the edge of the viewport\n * and the closest edge of the rect; if that distance is less than the appropriate\n * dimension of the rect, we will reposition the rect.\n */\n LabelArrangeGrid.prototype.isCloseToGridViewport = function (rect) {\n return rect.left + rect.width >= 0 - rect.width &&\n rect.top + rect.height >= -rect.height &&\n rect.left <= this.viewport.width + rect.width &&\n rect.top <= this.viewport.height + rect.height;\n };\n /**\n * Attempt to move the rect inside the grid's viewport. Returns the resulting\n * rectangle with the same width/height adjusted to be inside the viewport or\n * null if it couldn't fit regardless.\n */\n LabelArrangeGrid.prototype.tryMoveInsideViewport = function (rect) {\n var result = Rect.clone(rect);\n var viewport = this.viewport;\n // Return null if it's too big to fit regardless of positioning\n if (rect.width > viewport.width || rect.height > viewport.height) {\n return;\n }\n // Only one movement should be made in each direction, because we are only moving it inside enough for it to fit; there should be no overshooting.\n // Outside to the left\n if (rect.left < 0) {\n result.left = 0;\n }\n else if (rect.left + rect.width > viewport.width) {\n result.left -= (rect.left + rect.width) - viewport.width;\n }\n // Outside above\n if (rect.top < 0) {\n result.top = 0;\n }\n else if (rect.top + rect.height > viewport.height) {\n result.top -= (rect.top + rect.height) - viewport.height;\n }\n return result;\n };\n LabelArrangeGrid.prototype.getContainingGridSubsection = function (rect) {\n return {\n xMin: LabelArrangeGrid.bound(Math.floor(rect.left / this.cellSize.width), 0, this.columnCount),\n xMax: LabelArrangeGrid.bound(Math.ceil((rect.left + rect.width) / this.cellSize.width), 0, this.columnCount),\n yMin: LabelArrangeGrid.bound(Math.floor(rect.top / this.cellSize.height), 0, this.rowCount),\n yMax: LabelArrangeGrid.bound(Math.ceil((rect.top + rect.height) / this.cellSize.height), 0, this.rowCount),\n };\n };\n LabelArrangeGrid.getCellCount = function (step, length, minCount, maxCount) {\n return LabelArrangeGrid.bound(Math.ceil(length / step), minCount, maxCount);\n };\n LabelArrangeGrid.bound = function (value, min, max) {\n return Math.max(Math.min(value, max), min);\n };\n /**\n * A multiplier applied to the largest width height to attempt to balance # of\n * labels in each cell and number of cells each label belongs to\n */\n LabelArrangeGrid.cellSizeMultiplier = 2;\n return LabelArrangeGrid;\n }());\n powerbi.LabelArrangeGrid = LabelArrangeGrid;\n var LabelLayout = (function () {\n function LabelLayout(options) {\n this.startingOffset = options.startingOffset;\n this.maximumOffset = options.maximumOffset;\n if (options.offsetIterationDelta != null) {\n debug.assert(options.offsetIterationDelta > 0, \"label offset delta must be greater than 0\");\n this.offsetIterationDelta = options.offsetIterationDelta;\n }\n else {\n this.offsetIterationDelta = LabelLayout.defaultOffsetIterationDelta;\n }\n if (options.horizontalPadding != null) {\n this.horizontalPadding = options.horizontalPadding;\n }\n else {\n this.horizontalPadding = LabelLayout.defaultHorizontalPadding;\n }\n if (options.verticalPadding != null) {\n this.verticalPadding = options.verticalPadding;\n }\n else {\n this.verticalPadding = LabelLayout.defaultVerticalPadding;\n }\n this.allowLeaderLines = !!options.allowLeaderLines;\n this.attemptToMoveLabelsIntoViewport = !!options.attemptToMoveLabelsIntoViewport;\n }\n /**\n * Arrange takes a set of data labels and lays them out in order, assuming that\n * the given array has already been sorted with the most preferred labels at the\n * front, taking into considiration a maximum number of labels that are alowed\n * to display.\n *\n * Details:\n * - We iterate over offsets from the target position, increasing from 0 while\n * verifiying the maximum number of labels to display hasn't been reached\n * - For each offset, we iterate over each data label\n * - For each data label, we iterate over each position that is valid for\n * both the specific label and this layout\n * - When a valid position is found, we position the label there and no longer\n * reposition it.\n * - This prioritizes the earlier labels to be positioned closer to their\n * target points in the position they prefer.\n * - This prioritizes putting data labels close to a valid position over\n * placing them at their preferred position (it will place it at a less\n * preferred position if it will be a smaller offset)\n */\n LabelLayout.prototype.layout = function (labelDataPointsGroups, viewport) {\n // Clear data labels for a new layout\n for (var _i = 0, labelDataPointsGroups_2 = labelDataPointsGroups; _i < labelDataPointsGroups_2.length; _i++) {\n var labelDataPointsGroup = labelDataPointsGroups_2[_i];\n for (var _a = 0, _b = labelDataPointsGroup.labelDataPoints; _a < _b.length; _a++) {\n var labelPoint = _b[_a];\n labelPoint.hasBeenRendered = false;\n if (labelPoint.hasBackground) {\n labelPoint.labelSize = {\n width: labelPoint.textSize.width + 2 * NewDataLabelUtils.horizontalLabelBackgroundPadding,\n height: labelPoint.textSize.height + 2 * NewDataLabelUtils.verticalLabelBackgroundPadding,\n };\n }\n else {\n labelPoint.labelSize = labelPoint.textSize;\n }\n }\n }\n var resultingDataLabels = [];\n var grid = new LabelArrangeGrid(labelDataPointsGroups, viewport);\n // Iterates on every series\n for (var _c = 0, labelDataPointsGroups_3 = labelDataPointsGroups; _c < labelDataPointsGroups_3.length; _c++) {\n var labelDataPointsGroup = labelDataPointsGroups_3[_c];\n var maxLabelsToRender = labelDataPointsGroup.maxNumberOfLabels;\n // NOTE: we create a copy and modify the copy to keep track of preferred vs. non-preferred labels.\n var labelDataPoints = _.clone(labelDataPointsGroup.labelDataPoints);\n var preferredLabels = [];\n // Exclude preferred labels\n for (var j = labelDataPoints.length - 1, localMax = maxLabelsToRender; j >= 0 && localMax > 0; j--) {\n var labelPoint = labelDataPoints[j];\n if (labelPoint.isPreferred) {\n preferredLabels.unshift(labelDataPoints.splice(j, 1)[0]);\n localMax--;\n }\n }\n // First iterate all the preferred labels\n if (preferredLabels.length > 0) {\n var positionedLabels = this.positionDataLabels(preferredLabels, viewport, grid, maxLabelsToRender);\n maxLabelsToRender -= positionedLabels.length;\n resultingDataLabels = resultingDataLabels.concat(positionedLabels);\n }\n // While there are invisible not preferred labels and label distance is less than the max\n // allowed distance\n if (labelDataPoints.length > 0) {\n var labels = this.positionDataLabels(labelDataPoints, viewport, grid, maxLabelsToRender);\n resultingDataLabels = resultingDataLabels.concat(labels);\n }\n }\n return resultingDataLabels;\n };\n LabelLayout.prototype.positionDataLabels = function (labelDataPoints, viewport, grid, maxLabelsToRender) {\n var resultingDataLabels = [];\n var offsetDelta = this.offsetIterationDelta;\n var currentOffset = this.startingOffset;\n var currentCenteredOffset = 0;\n var drawLeaderLinesOnIteration;\n while (currentOffset <= this.maximumOffset && maxLabelsToRender > 0) {\n drawLeaderLinesOnIteration = this.allowLeaderLines && currentOffset > this.startingOffset;\n for (var _i = 0, labelDataPoints_2 = labelDataPoints; _i < labelDataPoints_2.length; _i++) {\n var labelPoint = labelDataPoints_2[_i];\n // Check if maximum number of labels to display has been reached\n if (maxLabelsToRender === 0)\n break;\n if (labelPoint.hasBeenRendered) {\n continue;\n }\n var dataLabel = void 0;\n if (labelPoint.parentType === 1 /* Rectangle */) {\n dataLabel = this.tryPositionForRectPositions(labelPoint, grid, currentOffset, currentCenteredOffset);\n }\n else {\n dataLabel = this.tryPositionForPointPositions(labelPoint, grid, currentOffset, drawLeaderLinesOnIteration);\n }\n if (dataLabel) {\n resultingDataLabels.push(dataLabel);\n maxLabelsToRender--;\n }\n }\n currentOffset += offsetDelta;\n currentCenteredOffset += offsetDelta;\n }\n return resultingDataLabels;\n };\n LabelLayout.prototype.tryPositionForRectPositions = function (labelPoint, grid, currentLabelOffset, currentCenteredLabelOffset) {\n var _this = this;\n // Function declared and reused to reduce code duplication\n var tryPosition = function (position, adjustForViewport) {\n var isPositionInside = position & 7 /* InsideAll */;\n if (isPositionInside && !DataLabelRectPositioner.canFitWithinParent(labelPoint, _this.horizontalPadding, _this.verticalPadding)) {\n return;\n }\n var resultingBoundingBox = LabelLayout.tryPositionRect(grid, position, labelPoint, currentLabelOffset, currentCenteredLabelOffset, adjustForViewport);\n if (resultingBoundingBox) {\n if (isPositionInside && !DataLabelRectPositioner.isLabelWithinParent(resultingBoundingBox, labelPoint, _this.horizontalPadding, _this.verticalPadding)) {\n return;\n }\n grid.add(resultingBoundingBox);\n labelPoint.hasBeenRendered = true;\n return {\n boundingBox: resultingBoundingBox,\n text: labelPoint.text,\n tooltip: labelPoint.tooltip,\n isVisible: true,\n fill: isPositionInside ? labelPoint.insideFill : labelPoint.outsideFill,\n identity: labelPoint.identity,\n key: labelPoint.key,\n fontSize: labelPoint.fontSize,\n selected: false,\n hasBackground: !!labelPoint.hasBackground,\n };\n }\n };\n // Iterate over all positions that are valid for the data point\n for (var _i = 0, _a = labelPoint.parentShape.validPositions; _i < _a.length; _i++) {\n var position = _a[_i];\n var label = tryPosition(position, false /* adjustForViewport */);\n if (label)\n return label;\n }\n // If no position has been found and the option is enabled, try any outside positions while moving the label inside the viewport\n if (this.attemptToMoveLabelsIntoViewport) {\n for (var _b = 0, _c = labelPoint.parentShape.validPositions; _b < _c.length; _b++) {\n var position = _c[_b];\n var label = tryPosition(position, true /* adjustForViewport */);\n if (label)\n return label;\n }\n }\n return null;\n };\n /**\n * Tests a particular position/offset combination for the given data label.\n * If the label can be placed, returns the resulting bounding box for the data\n * label. If not, returns null.\n */\n LabelLayout.tryPositionRect = function (grid, position, labelDataPoint, offset, centerOffset, adjustForViewport) {\n var offsetForPosition = offset;\n if (position & 1 /* InsideCenter */) {\n offsetForPosition = centerOffset;\n }\n var labelRect = DataLabelRectPositioner.getLabelRect(labelDataPoint, position, offsetForPosition);\n if (position !== 1 /* InsideCenter */ || labelDataPoint.parentShape.orientation === 0 /* None */) {\n if (!grid.hasConflict(labelRect)) {\n return labelRect;\n }\n if (adjustForViewport) {\n return grid.tryPositionInViewport(labelRect);\n }\n }\n else {\n // If the position is centered, attempt to offset in both a positive and negative direction\n if (!grid.hasConflict(labelRect)) {\n return labelRect;\n }\n labelRect = DataLabelRectPositioner.getLabelRect(labelDataPoint, position, -offsetForPosition);\n if (!grid.hasConflict(labelRect)) {\n return labelRect;\n }\n }\n return null;\n };\n LabelLayout.prototype.tryPositionForPointPositions = function (labelPoint, grid, currentLabelOffset, drawLeaderLines) {\n // Function declared and reused to reduce code duplication\n var tryPosition = function (position, parentShape, adjustForViewport) {\n var resultingBoundingBox = LabelLayout.tryPositionPoint(grid, position, labelPoint, currentLabelOffset, adjustForViewport);\n if (resultingBoundingBox) {\n grid.add(resultingBoundingBox);\n labelPoint.hasBeenRendered = true;\n return {\n boundingBox: resultingBoundingBox,\n text: labelPoint.text,\n tooltip: labelPoint.tooltip,\n isVisible: true,\n fill: position === 256 /* Center */ ? labelPoint.insideFill : labelPoint.outsideFill,\n isInsideParent: position === 256 /* Center */,\n identity: labelPoint.identity,\n key: labelPoint.key,\n fontSize: labelPoint.fontSize,\n selected: false,\n leaderLinePoints: drawLeaderLines ? DataLabelPointPositioner.getLabelLeaderLineEndingPoint(resultingBoundingBox, position, parentShape) : null,\n hasBackground: !!labelPoint.hasBackground,\n };\n }\n };\n // Iterate over all positions that are valid for the data point\n var parentShape = labelPoint.parentShape;\n var validPositions = parentShape.validPositions;\n for (var _i = 0, validPositions_1 = validPositions; _i < validPositions_1.length; _i++) {\n var position = validPositions_1[_i];\n var label = tryPosition(position, parentShape, false /* adjustForViewport */);\n if (label)\n return label;\n }\n // Attempt to position at the most preferred position by simply moving it inside the viewport\n if (this.attemptToMoveLabelsIntoViewport && !_.isEmpty(validPositions)) {\n var label = tryPosition(validPositions[0], parentShape, true /* adjustForViewport */);\n if (label)\n return label;\n }\n return null;\n };\n LabelLayout.tryPositionPoint = function (grid, position, labelDataPoint, offset, adjustForViewport) {\n var labelRect = DataLabelPointPositioner.getLabelRect(labelDataPoint.labelSize, labelDataPoint.parentShape, position, offset);\n if (!grid.hasConflict(labelRect)) {\n return labelRect;\n }\n if (adjustForViewport) {\n return grid.tryPositionInViewport(labelRect);\n }\n return null;\n };\n // Default values\n LabelLayout.defaultOffsetIterationDelta = 2;\n LabelLayout.defaultHorizontalPadding = 2;\n LabelLayout.defaultVerticalPadding = 2;\n return LabelLayout;\n }());\n powerbi.LabelLayout = LabelLayout;\n /**\n * (Private) Contains methods for calculating the bounding box of a data label\n */\n var DataLabelRectPositioner;\n (function (DataLabelRectPositioner) {\n function getLabelRect(labelDataPoint, position, offset) {\n var parentRect = labelDataPoint.parentShape;\n if (parentRect != null) {\n // Each combination of position and orientation results in a different actual positioning, which is then called.\n switch (position) {\n case 1 /* InsideCenter */:\n switch (parentRect.orientation) {\n case 1 /* VerticalBottomBased */:\n case 2 /* VerticalTopBased */:\n return DataLabelRectPositioner.middleVertical(labelDataPoint.labelSize, parentRect.rect, offset);\n case 3 /* HorizontalLeftBased */:\n case 4 /* HorizontalRightBased */:\n return DataLabelRectPositioner.middleHorizontal(labelDataPoint.labelSize, parentRect.rect, offset);\n case 0 /* None */:\n }\n case 2 /* InsideBase */:\n switch (parentRect.orientation) {\n case 1 /* VerticalBottomBased */:\n return DataLabelRectPositioner.bottomInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 2 /* VerticalTopBased */:\n return DataLabelRectPositioner.topInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 3 /* HorizontalLeftBased */:\n return DataLabelRectPositioner.leftInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 4 /* HorizontalRightBased */:\n return DataLabelRectPositioner.rightInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 0 /* None */:\n }\n case 4 /* InsideEnd */:\n switch (parentRect.orientation) {\n case 1 /* VerticalBottomBased */:\n return DataLabelRectPositioner.topInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 2 /* VerticalTopBased */:\n return DataLabelRectPositioner.bottomInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 3 /* HorizontalLeftBased */:\n return DataLabelRectPositioner.rightInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 4 /* HorizontalRightBased */:\n return DataLabelRectPositioner.leftInside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 0 /* None */:\n }\n case 8 /* OutsideBase */:\n switch (parentRect.orientation) {\n case 1 /* VerticalBottomBased */:\n return DataLabelRectPositioner.bottomOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 2 /* VerticalTopBased */:\n return DataLabelRectPositioner.topOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 3 /* HorizontalLeftBased */:\n return DataLabelRectPositioner.leftOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 4 /* HorizontalRightBased */:\n return DataLabelRectPositioner.rightOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 0 /* None */:\n }\n case 16 /* OutsideEnd */:\n switch (parentRect.orientation) {\n case 1 /* VerticalBottomBased */:\n return DataLabelRectPositioner.topOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 2 /* VerticalTopBased */:\n return DataLabelRectPositioner.bottomOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 3 /* HorizontalLeftBased */:\n return DataLabelRectPositioner.rightOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 4 /* HorizontalRightBased */:\n return DataLabelRectPositioner.leftOutside(labelDataPoint.labelSize, parentRect.rect, offset);\n case 0 /* None */:\n }\n default:\n debug.assertFail(\"Unsupported label position\");\n }\n }\n else {\n }\n return null;\n }\n DataLabelRectPositioner.getLabelRect = getLabelRect;\n function canFitWithinParent(labelDataPoint, horizontalPadding, verticalPadding) {\n return (labelDataPoint.labelSize.width + 2 * horizontalPadding < labelDataPoint.parentShape.rect.width) ||\n (labelDataPoint.labelSize.height + 2 * verticalPadding < labelDataPoint.parentShape.rect.height);\n }\n DataLabelRectPositioner.canFitWithinParent = canFitWithinParent;\n function isLabelWithinParent(labelRect, labelPoint, horizontalPadding, verticalPadding) {\n var parentRect = labelPoint.parentShape.rect;\n var labelRectWithPadding = shapes.Rect.inflate(labelRect, { left: horizontalPadding, right: horizontalPadding, top: verticalPadding, bottom: verticalPadding });\n return shapes.Rect.containsPoint(parentRect, {\n x: labelRectWithPadding.left,\n y: labelRectWithPadding.top,\n }) && shapes.Rect.containsPoint(parentRect, {\n x: labelRectWithPadding.left + labelRectWithPadding.width,\n y: labelRectWithPadding.top + labelRectWithPadding.height,\n });\n }\n DataLabelRectPositioner.isLabelWithinParent = isLabelWithinParent;\n function topInside(labelSize, parentRect, offset) {\n return {\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\n top: parentRect.top + offset,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.topInside = topInside;\n function bottomInside(labelSize, parentRect, offset) {\n return {\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\n top: (parentRect.top + parentRect.height) - offset - labelSize.height,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.bottomInside = bottomInside;\n function rightInside(labelSize, parentRect, offset) {\n return {\n left: (parentRect.left + parentRect.width) - labelSize.width - offset,\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.rightInside = rightInside;\n function leftInside(labelSize, parentRect, offset) {\n return {\n left: parentRect.left + offset,\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.leftInside = leftInside;\n function topOutside(labelSize, parentRect, offset) {\n return {\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\n top: parentRect.top - labelSize.height - offset,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.topOutside = topOutside;\n function bottomOutside(labelSize, parentRect, offset) {\n return {\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\n top: (parentRect.top + parentRect.height) + offset,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.bottomOutside = bottomOutside;\n function rightOutside(labelSize, parentRect, offset) {\n return {\n left: (parentRect.left + parentRect.width) + offset,\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.rightOutside = rightOutside;\n function leftOutside(labelSize, parentRect, offset) {\n return {\n left: parentRect.left - labelSize.width - offset,\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.leftOutside = leftOutside;\n function middleHorizontal(labelSize, parentRect, offset) {\n return {\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0 + offset,\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.middleHorizontal = middleHorizontal;\n function middleVertical(labelSize, parentRect, offset) {\n return {\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0 + offset,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelRectPositioner.middleVertical = middleVertical;\n })(DataLabelRectPositioner = powerbi.DataLabelRectPositioner || (powerbi.DataLabelRectPositioner = {}));\n var DataLabelPointPositioner;\n (function (DataLabelPointPositioner) {\n DataLabelPointPositioner.cos45 = Math.cos(45);\n DataLabelPointPositioner.sin45 = Math.sin(45);\n function getLabelRect(labelSize, parentPoint, position, offset) {\n switch (position) {\n case 1 /* Above */: {\n return DataLabelPointPositioner.above(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 2 /* Below */: {\n return DataLabelPointPositioner.below(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 4 /* Left */: {\n return DataLabelPointPositioner.left(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 8 /* Right */: {\n return DataLabelPointPositioner.right(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 32 /* BelowLeft */: {\n return DataLabelPointPositioner.belowLeft(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 16 /* BelowRight */: {\n return DataLabelPointPositioner.belowRight(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 128 /* AboveLeft */: {\n return DataLabelPointPositioner.aboveLeft(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 64 /* AboveRight */: {\n return DataLabelPointPositioner.aboveRight(labelSize, parentPoint.point, parentPoint.radius + offset);\n }\n case 256 /* Center */: {\n return DataLabelPointPositioner.center(labelSize, parentPoint.point);\n }\n default: {\n debug.assertFail(\"Unsupported label position\");\n }\n }\n return null;\n }\n DataLabelPointPositioner.getLabelRect = getLabelRect;\n function above(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x - (labelSize.width / 2),\n top: parentPoint.y - offset - labelSize.height,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.above = above;\n function below(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x - (labelSize.width / 2),\n top: parentPoint.y + offset,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.below = below;\n function left(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x - offset - labelSize.width,\n top: parentPoint.y - (labelSize.height / 2),\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.left = left;\n function right(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x + offset,\n top: parentPoint.y - (labelSize.height / 2),\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.right = right;\n function belowLeft(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x - (DataLabelPointPositioner.sin45 * offset) - labelSize.width,\n top: parentPoint.y + (DataLabelPointPositioner.cos45 * offset),\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.belowLeft = belowLeft;\n function belowRight(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x + (DataLabelPointPositioner.sin45 * offset),\n top: parentPoint.y + (DataLabelPointPositioner.cos45 * offset),\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.belowRight = belowRight;\n function aboveLeft(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x - (DataLabelPointPositioner.sin45 * offset) - labelSize.width,\n top: parentPoint.y - (DataLabelPointPositioner.cos45 * offset) - labelSize.height,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.aboveLeft = aboveLeft;\n function aboveRight(labelSize, parentPoint, offset) {\n return {\n left: parentPoint.x + (DataLabelPointPositioner.sin45 * offset),\n top: parentPoint.y - (DataLabelPointPositioner.cos45 * offset) - labelSize.height,\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.aboveRight = aboveRight;\n function center(labelSize, parentPoint) {\n return {\n left: parentPoint.x - (labelSize.width / 2),\n top: parentPoint.y - (labelSize.height / 2),\n width: labelSize.width,\n height: labelSize.height\n };\n }\n DataLabelPointPositioner.center = center;\n function getLabelLeaderLineEndingPoint(boundingBox, position, parentShape) {\n var x = boundingBox.left;\n var y = boundingBox.top;\n switch (position) {\n case 1 /* Above */:\n x += (boundingBox.width / 2);\n y += boundingBox.height;\n break;\n case 2 /* Below */:\n x += (boundingBox.width / 2);\n break;\n case 4 /* Left */:\n x += boundingBox.width;\n y += ((boundingBox.height * 2) / 3);\n break;\n case 8 /* Right */:\n y += ((boundingBox.height * 2) / 3);\n break;\n case 32 /* BelowLeft */:\n x += boundingBox.width;\n y += (boundingBox.height / 2);\n break;\n case 16 /* BelowRight */:\n y += (boundingBox.height / 2);\n break;\n case 128 /* AboveLeft */:\n x += boundingBox.width;\n y += boundingBox.height;\n break;\n case 64 /* AboveRight */:\n y += boundingBox.height;\n break;\n }\n return [[parentShape.point.x, parentShape.point.y], [x, y]];\n }\n DataLabelPointPositioner.getLabelLeaderLineEndingPoint = getLabelLeaderLineEndingPoint;\n })(DataLabelPointPositioner = powerbi.DataLabelPointPositioner || (powerbi.DataLabelPointPositioner = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var NewDataLabelUtils = powerbi.visuals.NewDataLabelUtils;\n var labelStyle = powerbi.visuals.labelStyle;\n var DonutLabelUtils = powerbi.visuals.DonutLabelUtils;\n var DonutLabelLayout = (function () {\n function DonutLabelLayout(options, donutChartProperties) {\n this.startingOffset = options.startingOffset;\n this.maximumOffset = options.maximumOffset;\n if (options.offsetIterationDelta != null) {\n debug.assert(options.offsetIterationDelta > 0, \"label offset delta must be greater than 0\");\n this.offsetIterationDelta = options.offsetIterationDelta;\n }\n this.donutChartProperties = donutChartProperties;\n this.center = {\n x: donutChartProperties.viewport.width / 2,\n y: donutChartProperties.viewport.height / 2,\n };\n this.outerRadius = this.donutChartProperties.radius * this.donutChartProperties.outerArcRadiusRatio;\n this.innerRadius = (this.donutChartProperties.radius / 2) * this.donutChartProperties.innerArcRadiusRatio;\n this.additionalCharsWidth = powerbi.TextMeasurementService.measureSvgTextWidth({\n text: \" ()\",\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: jsCommon.PixelConverter.fromPoint(donutChartProperties.dataLabelsSettings.fontSize),\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\n });\n }\n /**\n * Arrange takes a set of data labels and lays them out them in order, assuming that\n * the given array has already been sorted with the most preferred labels at the\n * front.\n *\n * Details:\n * - We iterate over offsets from the target position, increasing from 0\n * - For each offset, we iterate over each data label\n * - For each data label, we iterate over each position that is valid for\n * both the specific label and this layout\n * - When a valid position is found, we position the label there and no longer\n * reposition it.\n * - This prioritizes the earlier labels to be positioned closer to their\n * target points in the position they prefer.\n * - This prioritizes putting data labels close to a valid position over\n * placing them at their preferred position (it will place it at a less\n * preferred position if it will be a smaller offset)\n */\n DonutLabelLayout.prototype.layout = function (labelDataPoints) {\n // Clear data labels for a new layout\n for (var _i = 0, labelDataPoints_3 = labelDataPoints; _i < labelDataPoints_3.length; _i++) {\n var donutLabel = labelDataPoints_3[_i];\n donutLabel.hasBeenRendered = false;\n donutLabel.labelSize = donutLabel.textSize;\n }\n var resultingLabels = [];\n var preferredLabels = [];\n var viewport = this.donutChartProperties.viewport;\n var labelDataPointsGroup = {\n labelDataPoints: labelDataPoints,\n maxNumberOfLabels: labelDataPoints.length\n };\n var grid = new powerbi.LabelArrangeGrid([labelDataPointsGroup], viewport);\n for (var i = labelDataPoints.length - 1; i >= 0; i--) {\n var labelPoint = labelDataPoints[i];\n if (labelPoint.isPreferred) {\n var label = labelDataPoints.splice(i, 1);\n preferredLabels = label.concat(preferredLabels);\n }\n }\n // first iterate all the preferred labels\n if (preferredLabels.length > 0)\n resultingLabels = this.positionLabels(preferredLabels, grid);\n // While there are invisible not preferred labels and label distance is less than the max\n // allowed distance\n if (labelDataPoints.length > 0) {\n var labels = this.positionLabels(labelDataPoints, grid);\n resultingLabels = resultingLabels.concat(labels);\n }\n return resultingLabels;\n };\n DonutLabelLayout.prototype.positionLabels = function (labelDataPoints, grid) {\n var resultingLabels = [];\n var offsetDelta = this.offsetIterationDelta;\n var currentOffset = this.startingOffset;\n var currentCenteredOffset = 0;\n while (currentOffset <= this.maximumOffset) {\n for (var _i = 0, labelDataPoints_4 = labelDataPoints; _i < labelDataPoints_4.length; _i++) {\n var labelPoint = labelDataPoints_4[_i];\n if (labelPoint.hasBeenRendered)\n continue;\n var label = this.tryPositionForDonut(labelPoint, grid, currentOffset);\n if (label)\n resultingLabels.push(label);\n }\n currentOffset += offsetDelta;\n currentCenteredOffset += offsetDelta;\n }\n return resultingLabels;\n };\n /**\n * We try to move the label 25% up/down if the label is truncated or it collides with other labels.\n * after we moved it once we check that the new position doesn't failed (collides with other labels).\n */\n DonutLabelLayout.prototype.tryPositionForDonut = function (labelPoint, grid, currentLabelOffset) {\n var parentShape = labelPoint.parentShape;\n if (_.isEmpty(parentShape.validPositions) || parentShape.validPositions[0] === 0 /* None */)\n return;\n var defaultPosition = parentShape.validPositions[0];\n var bestCandidate = this.tryAllPositions(labelPoint, grid, defaultPosition, currentLabelOffset);\n if (bestCandidate && bestCandidate.score === 0) {\n return this.buildLabel(bestCandidate, grid);\n }\n // If we haven't found a non-truncated label, try to split into 2 lines.\n if (this.donutChartProperties.dataLabelsSettings.labelStyle === labelStyle.both) {\n // Try to split the label to two lines if both data and category label are on\n var splitLabelDataPoint = this.splitDonutDataPoint(labelPoint);\n var bestSplitCandidate = this.tryAllPositions(splitLabelDataPoint, grid, defaultPosition, currentLabelOffset);\n // If the best candidate with a split line is better than the best candidate with a single line, return the former.\n if (bestSplitCandidate && (!bestCandidate || (bestSplitCandidate.score < bestCandidate.score))) {\n return this.buildLabel(bestSplitCandidate, grid);\n }\n }\n // We didn't find a better candidate by splitting the label lines, so return our best single-line candidate.\n if (bestCandidate) {\n return this.buildLabel(bestCandidate, grid);\n }\n };\n DonutLabelLayout.prototype.generateCandidate = function (labelDataPoint, candidatePosition, grid, currentLabelOffset) {\n var angle = this.generateCandidateAngleForPosition(labelDataPoint.donutArcDescriptor, candidatePosition);\n var parentShape = this.getPointPositionForAngle(angle);\n var parentPoint = parentShape.point;\n var score = this.score(labelDataPoint, parentPoint);\n var leaderLinePoints = DonutLabelUtils.getLabelLeaderLineForDonutChart(labelDataPoint.donutArcDescriptor, this.donutChartProperties, parentPoint, angle);\n var leaderLinesSize = DonutLabelUtils.getLabelLeaderLinesSizeForDonutChart(leaderLinePoints);\n var newLabelDataPoint = _.clone(labelDataPoint);\n newLabelDataPoint.angle = angle;\n newLabelDataPoint.parentShape = parentShape;\n newLabelDataPoint.leaderLinePoints = leaderLinePoints;\n newLabelDataPoint.linesSize = leaderLinesSize;\n var boundingBoxs = DonutLabelLayout.tryPositionPoint(grid, parentShape.validPositions[0], newLabelDataPoint, currentLabelOffset, this.center, this.donutChartProperties.viewport);\n return {\n angle: angle,\n point: parentShape,\n score: score,\n labelRects: boundingBoxs,\n labelDataPoint: newLabelDataPoint,\n };\n };\n DonutLabelLayout.prototype.tryAllPositions = function (labelDataPoint, grid, defaultPosition, currentLabelOffset) {\n var boundingBoxs = DonutLabelLayout.tryPositionPoint(grid, defaultPosition, labelDataPoint, currentLabelOffset, this.center, this.donutChartProperties.viewport);\n var originalPoint = labelDataPoint.parentShape;\n var originalCandidate = {\n point: originalPoint,\n angle: labelDataPoint.angle,\n score: this.score(labelDataPoint, originalPoint.point),\n labelRects: boundingBoxs,\n labelDataPoint: labelDataPoint,\n };\n if (boundingBoxs && boundingBoxs.textRect && originalCandidate.score === 0) {\n return originalCandidate;\n }\n var positions = [];\n var bestCandidate;\n if (boundingBoxs && boundingBoxs.textRect) {\n // We have a truncated label here, otherwised we would have returned already\n positions = this.getLabelPointPositions(labelDataPoint, /* isTruncated */ true);\n bestCandidate = originalCandidate;\n }\n else {\n positions = this.getLabelPointPositions(labelDataPoint, /* isTruncated */ false);\n }\n // Try to reposition the label if necessary\n for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) {\n var position = positions_1[_i];\n var candidate = this.generateCandidate(labelDataPoint, position, grid, currentLabelOffset);\n if (candidate.labelRects && candidate.labelRects.textRect) {\n if (bestCandidate == null || candidate.score < bestCandidate.score) {\n bestCandidate = candidate;\n if (bestCandidate.score === 0)\n return bestCandidate;\n }\n }\n }\n return bestCandidate;\n };\n DonutLabelLayout.prototype.buildLabel = function (labelLayout, grid) {\n var resultingBoundingBox = labelLayout.labelRects.textRect;\n var labelPoint = labelLayout.labelDataPoint;\n grid.add(resultingBoundingBox);\n grid.add(labelLayout.labelRects.horizontalLineRect);\n grid.add(labelLayout.labelRects.diagonalLineRect);\n labelPoint.hasBeenRendered = true;\n var left = resultingBoundingBox.left - this.center.x;\n //We need to add or subtract half resultingBoundingBox.width because Donut chart labels get text anchor start/end\n if (left < 0)\n left += resultingBoundingBox.width / 2;\n else\n left -= resultingBoundingBox.width / 2;\n var textAnchor = labelPoint.parentShape.validPositions[0] === 8 /* Right */ ? 'start' : 'end';\n var boundingBox = {\n left: left,\n top: resultingBoundingBox.top - this.center.y,\n height: resultingBoundingBox.height,\n width: resultingBoundingBox.width,\n };\n // After repositioning the label we need to recalculate its size and format it according to the current available space\n var labelSettingsStyle = this.donutChartProperties.dataLabelsSettings.labelStyle;\n var spaceAvailableForLabels = DonutLabelUtils.getSpaceAvailableForDonutLabels(labelPoint.parentShape.point.x, this.donutChartProperties.viewport);\n var formattedDataLabel;\n var formattedCategoryLabel;\n var text;\n var getLabelFormattedText = powerbi.visuals.dataLabelUtils.getLabelFormattedText;\n var fontSize = labelPoint.fontSize;\n var hasOneLabelRow = labelSettingsStyle === labelStyle.both && labelPoint.secondRowText == null;\n // Giving 50/50 space when both category and measure are on\n if (hasOneLabelRow) {\n labelPoint.dataLabel = \" (\" + labelPoint.dataLabel + \")\";\n spaceAvailableForLabels /= 2;\n }\n if (labelSettingsStyle === labelStyle.both || labelSettingsStyle === labelStyle.data) {\n formattedDataLabel = getLabelFormattedText({\n label: labelPoint.dataLabel,\n maxWidth: spaceAvailableForLabels,\n fontSize: fontSize\n });\n }\n if (labelSettingsStyle === labelStyle.both || labelSettingsStyle === labelStyle.category) {\n formattedCategoryLabel = getLabelFormattedText({\n label: labelPoint.categoryLabel,\n maxWidth: spaceAvailableForLabels,\n fontSize: fontSize\n });\n }\n switch (labelSettingsStyle) {\n case labelStyle.both:\n if (labelPoint.secondRowText == null) {\n text = formattedCategoryLabel + formattedDataLabel;\n }\n else {\n text = formattedDataLabel;\n labelPoint.secondRowText = formattedCategoryLabel;\n }\n break;\n case labelStyle.data:\n text = formattedDataLabel;\n break;\n case labelStyle.category:\n text = formattedCategoryLabel;\n break;\n }\n // Limit text size width for correct leader line calculation\n labelPoint.textSize.width = Math.min(labelPoint.textSize.width, hasOneLabelRow ? spaceAvailableForLabels * 2 : spaceAvailableForLabels);\n return {\n boundingBox: boundingBox,\n text: text,\n tooltip: labelPoint.tooltip,\n isVisible: true,\n fill: labelPoint.outsideFill,\n identity: labelPoint.identity,\n fontSize: fontSize,\n selected: false,\n textAnchor: textAnchor,\n leaderLinePoints: labelPoint.leaderLinePoints,\n hasBackground: false,\n secondRowText: labelPoint.secondRowText,\n };\n };\n DonutLabelLayout.tryPositionPoint = function (grid, position, labelDataPoint, offset, center, viewport) {\n var parentPoint = labelDataPoint.parentShape;\n // Limit label width to fit the availabe space for labels\n var textSize = _.clone(labelDataPoint.textSize);\n textSize.width = Math.min(textSize.width, DonutLabelUtils.getSpaceAvailableForDonutLabels(parentPoint.point.x, viewport));\n // Create label rectangle\n var labelRect = powerbi.DataLabelPointPositioner.getLabelRect(textSize, parentPoint, position, offset);\n // Create label diagonal line rectangle\n var diagonalLineParentPoint = {\n point: {\n x: labelDataPoint.leaderLinePoints[0][0],\n y: labelDataPoint.leaderLinePoints[0][1] < 0 ? labelDataPoint.leaderLinePoints[1][1] : labelDataPoint.leaderLinePoints[0][1]\n },\n radius: 0,\n validPositions: null\n };\n var diagonalLineRect = powerbi.DataLabelPointPositioner.getLabelRect(labelDataPoint.linesSize[DonutLabelUtils.DiagonalLineIndex], diagonalLineParentPoint, position, offset);\n // Create label horizontal line rectangle\n var horizontalLineParentPoint = {\n point: {\n x: labelDataPoint.leaderLinePoints[1][0],\n y: labelDataPoint.leaderLinePoints[1][1]\n },\n radius: 0,\n validPositions: null\n };\n var horizontalLineRect = powerbi.DataLabelPointPositioner.getLabelRect(labelDataPoint.linesSize[DonutLabelUtils.HorizontalLineIndex], horizontalLineParentPoint, position, offset);\n if (!labelRect || !diagonalLineRect || !horizontalLineRect)\n return;\n labelRect.left += center.x;\n labelRect.top += center.y;\n var centerForLinesWidth = center.x - labelRect.width / 2;\n diagonalLineRect.left += centerForLinesWidth;\n diagonalLineRect.top += center.y;\n horizontalLineRect.left += centerForLinesWidth;\n horizontalLineRect.top += center.y;\n if (!grid.hasConflict(labelRect) && !grid.hasConflict(diagonalLineRect) && !grid.hasConflict(horizontalLineRect))\n return { textRect: labelRect, diagonalLineRect: diagonalLineRect, horizontalLineRect: horizontalLineRect };\n };\n /**\n * Returns an array of valid positions for hidden and truncated labels.\n * For truncated labels will return positions with more available space.\n * For hidden labels will return all possible positions by the order we draw labels (clockwise)\n */\n DonutLabelLayout.prototype.getLabelPointPositions = function (labelPoint, isTruncated) {\n var parentShape = labelPoint.parentShape;\n var position = parentShape.validPositions[0];\n if (!isTruncated) {\n return position === 4 /* Left */\n ? [128 /* AboveLeft */, 32 /* BelowLeft */]\n : [16 /* BelowRight */, 64 /* AboveRight */];\n }\n if (parentShape.point.y < 0) {\n return position === 8 /* Right */\n ? [64 /* AboveRight */]\n : [128 /* AboveLeft */];\n }\n else {\n return position === 8 /* Right */\n ? [16 /* BelowRight */]\n : [32 /* BelowLeft */];\n }\n };\n /**\n * Returns a new DonutLabelDataPoint after splitting it into two lines\n */\n DonutLabelLayout.prototype.splitDonutDataPoint = function (labelPoint) {\n var textSize = {\n width: Math.max(labelPoint.categoryLabelSize.width, labelPoint.dataLabelSize.width),\n height: labelPoint.dataLabelSize.height * 2,\n };\n var newLabelPoint = _.clone(labelPoint);\n newLabelPoint.textSize = textSize;\n newLabelPoint.secondRowText = labelPoint.categoryLabel;\n return newLabelPoint;\n };\n DonutLabelLayout.prototype.generateCandidateAngleForPosition = function (d, position) {\n var midAngle = d.startAngle + ((d.endAngle - d.startAngle) / 2);\n switch (position) {\n case 64 /* AboveRight */:\n case 32 /* BelowLeft */:\n return ((d.startAngle + midAngle) - Math.PI) / 2;\n case 128 /* AboveLeft */:\n case 16 /* BelowRight */:\n return ((midAngle + d.endAngle) - Math.PI) / 2;\n default:\n debug.assertFail(\"Unsupported label position\");\n }\n };\n DonutLabelLayout.prototype.getPointPositionForAngle = function (angle) {\n // Calculate the new label coordinates\n var labelX = DonutLabelUtils.getXPositionForDonutLabel(Math.cos(angle) * this.outerRadius);\n var labelY = Math.sin(angle) * this.outerRadius;\n var newPosition = labelX < 0 ? 4 /* Left */ : 8 /* Right */;\n var pointPosition = {\n point: {\n x: labelX,\n y: labelY,\n },\n validPositions: [newPosition],\n radius: 0,\n };\n return pointPosition;\n };\n DonutLabelLayout.prototype.score = function (labelPoint, point) {\n var spaceAvailableForLabels = DonutLabelUtils.getSpaceAvailableForDonutLabels(point.x, this.donutChartProperties.viewport);\n var textWidth;\n // Check if we show category and data labels in one row\n if (this.donutChartProperties.dataLabelsSettings.labelStyle === labelStyle.both && labelPoint.secondRowText == null) {\n // Each of the labels gets half of the available space for labels so we take this into consideration in the score\n textWidth = Math.max(labelPoint.categoryLabelSize.width, labelPoint.dataLabelSize.width + this.additionalCharsWidth);\n spaceAvailableForLabels /= 2;\n }\n else {\n textWidth = labelPoint.textSize.width;\n }\n return Math.max(textWidth - spaceAvailableForLabels, 0);\n };\n return DonutLabelLayout;\n }());\n powerbi.DonutLabelLayout = DonutLabelLayout;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var NewDataLabelUtils = powerbi.visuals.NewDataLabelUtils;\n var DefaultCentroidOffset = 5;\n var OffsetDelta = 10;\n var MaximumOffset = 60;\n var stemExtension = 5;\n var FilledMapLabelLayout = (function () {\n function FilledMapLabelLayout() {\n }\n FilledMapLabelLayout.prototype.layout = function (labelDataPoints, viewport, polygonInfoTransform, redrawDataLabels) {\n if (redrawDataLabels || this.labels === undefined) {\n var labelDataPointsGroup = {\n labelDataPoints: labelDataPoints,\n maxNumberOfLabels: labelDataPoints.length\n };\n for (var _i = 0, labelDataPoints_5 = labelDataPoints; _i < labelDataPoints_5.length; _i++) {\n var labelPoint = labelDataPoints_5[_i];\n labelPoint.labelSize = {\n width: labelPoint.textSize.width + 2 * NewDataLabelUtils.horizontalLabelBackgroundPadding,\n height: labelPoint.textSize.height + 2 * NewDataLabelUtils.verticalLabelBackgroundPadding,\n };\n }\n var grid = new powerbi.LabelArrangeGrid([labelDataPointsGroup], viewport);\n var resultingDataLabels = [];\n var allPolygons = [];\n for (var _a = 0, labelDataPoints_6 = labelDataPoints; _a < labelDataPoints_6.length; _a++) {\n var labelPoint = labelDataPoints_6[_a];\n var polygon = labelPoint.parentShape.polygon;\n allPolygons.push(polygon);\n polygon.pixelBoundingRect = polygonInfoTransform.applyToRect(polygon.absoluteBoundingRect());\n }\n var shapesgrid = new LabelPolygonArrangeGrid(allPolygons, viewport);\n for (var _b = 0, labelDataPoints_7 = labelDataPoints; _b < labelDataPoints_7.length; _b++) {\n var labelPoint = labelDataPoints_7[_b];\n var dataLabel = this.getLabelByPolygonPositions(labelPoint, polygonInfoTransform, grid, shapesgrid);\n if (dataLabel != null) {\n resultingDataLabels.push(dataLabel);\n }\n }\n this.labels = resultingDataLabels;\n }\n else {\n this.updateLabelOffsets(polygonInfoTransform);\n }\n return this.labels;\n };\n FilledMapLabelLayout.prototype.getLabelPolygon = function (mapDataPoint, position, pointPosition, offset) {\n var dataPointSize = {\n width: mapDataPoint.textSize.width,\n height: (mapDataPoint.textSize.height)\n };\n return this.getLabelBoundingBox(dataPointSize, position, pointPosition, offset);\n };\n FilledMapLabelLayout.prototype.getLabelBoundingBox = function (dataPointSize, position, pointPosition, offset) {\n switch (position) {\n case 1 /* Above */: {\n return powerbi.DataLabelPointPositioner.above(dataPointSize, pointPosition, offset);\n }\n case 2 /* Below */: {\n return powerbi.DataLabelPointPositioner.below(dataPointSize, pointPosition, offset);\n }\n case 4 /* Left */: {\n return powerbi.DataLabelPointPositioner.left(dataPointSize, pointPosition, offset);\n }\n case 8 /* Right */: {\n return powerbi.DataLabelPointPositioner.right(dataPointSize, pointPosition, offset);\n }\n case 128 /* AboveLeft */: {\n return powerbi.DataLabelPointPositioner.aboveLeft(dataPointSize, pointPosition, offset);\n }\n case 64 /* AboveRight */: {\n return powerbi.DataLabelPointPositioner.aboveRight(dataPointSize, pointPosition, offset);\n }\n case 32 /* BelowLeft */: {\n return powerbi.DataLabelPointPositioner.belowLeft(dataPointSize, pointPosition, offset);\n }\n case 16 /* BelowRight */: {\n return powerbi.DataLabelPointPositioner.belowRight(dataPointSize, pointPosition, offset);\n }\n case 256 /* Center */: {\n return powerbi.DataLabelPointPositioner.center(dataPointSize, pointPosition);\n }\n default: {\n debug.assertFail(\"Unsupported label position\");\n }\n }\n return null;\n };\n FilledMapLabelLayout.prototype.getLabelByPolygonPositions = function (labelPoint, polygonInfoTransform, grid, shapesGrid) {\n var offset = 0;\n var inverseTransorm = polygonInfoTransform.getInverse();\n for (var i = 0; i < 2; i++) {\n if (i === 1) {\n offset = DefaultCentroidOffset;\n }\n for (var _i = 0, _a = labelPoint.parentShape.validPositions; _i < _a.length; _i++) {\n var position = _a[_i];\n var resultingAbsoluteBoundingBox = this.tryPositionForPolygonPosition(position, labelPoint, polygonInfoTransform, offset, inverseTransorm);\n if (position === 256 /* Center */ && i !== 0) {\n continue;\n }\n if (resultingAbsoluteBoundingBox) {\n var resultingBoundingBox = polygonInfoTransform.applyToRect(resultingAbsoluteBoundingBox);\n var dataLabel = {\n text: labelPoint.text,\n secondRowText: labelPoint.secondRowText,\n boundingBox: resultingBoundingBox,\n isVisible: true,\n fill: labelPoint.insideFill,\n identity: null,\n selected: false,\n hasBackground: true,\n textAnchor: \"middle\",\n originalPixelOffset: offset,\n isPlacedInsidePolygon: true,\n absoluteBoundingBoxCenter: {\n x: resultingAbsoluteBoundingBox.left + resultingAbsoluteBoundingBox.width / 2,\n y: resultingAbsoluteBoundingBox.top + resultingAbsoluteBoundingBox.height / 2\n }\n };\n return dataLabel;\n }\n }\n }\n var currentOffset = 6;\n while (currentOffset <= MaximumOffset) {\n for (var _b = 0, _c = labelPoint.parentShape.validPositions; _b < _c.length; _b++) {\n var position = _c[_b];\n if (position === 256 /* Center */) {\n continue;\n }\n var polygon = labelPoint.parentShape.polygon;\n var pixelCentroid = polygonInfoTransform.applyToPoint(polygon.absoluteCentroid());\n var resultingAbsolutBoundingBox = this.tryPlaceLabelOutsidePolygon(grid, position, labelPoint, currentOffset, pixelCentroid, shapesGrid, inverseTransorm);\n if (resultingAbsolutBoundingBox) {\n var resultingBoundingBox = polygonInfoTransform.applyToRect(resultingAbsolutBoundingBox);\n var dataLabel = {\n text: labelPoint.text,\n secondRowText: labelPoint.secondRowText,\n boundingBox: resultingBoundingBox,\n isVisible: true,\n fill: labelPoint.insideFill,\n identity: null,\n selected: false,\n hasBackground: true,\n isPlacedInsidePolygon: false,\n textAnchor: \"middle\",\n originalPixelOffset: currentOffset,\n originalPosition: position,\n originalAbsoluteCentroid: polygon.absoluteCentroid(),\n absoluteBoundingBoxCenter: {\n x: resultingAbsolutBoundingBox.left + resultingAbsolutBoundingBox.width / 2,\n y: resultingAbsolutBoundingBox.top + resultingAbsolutBoundingBox.height / 2\n }\n };\n var pixelStemSource = this.calculateStemSource(polygonInfoTransform, inverseTransorm, polygon, resultingBoundingBox, position, pixelCentroid);\n dataLabel.leaderLinePoints = this.setLeaderLinePoints(pixelStemSource, this.calculateStemDestination(resultingBoundingBox, position));\n dataLabel.absoluteStemSource = inverseTransorm.applyToPoint(pixelStemSource);\n grid.add(resultingBoundingBox);\n return dataLabel;\n }\n }\n currentOffset += OffsetDelta;\n }\n return null;\n };\n FilledMapLabelLayout.prototype.setLeaderLinePoints = function (stemSource, stemDestination) {\n return [[stemSource.x, stemSource.y], [stemDestination.x, stemDestination.y]];\n };\n FilledMapLabelLayout.prototype.calculateStemSource = function (polygonInfoTransform, inverseTransorm, polygon, labelBoundingBox, position, pixelCentroid) {\n var absoluteStemSource = polygon.lineIntersectionPoint(polygon.absoluteCentroid(), inverseTransorm.applyToPoint({ x: labelBoundingBox.left + labelBoundingBox.width / 2, y: labelBoundingBox.top + labelBoundingBox.height / 2 }));\n if (absoluteStemSource == null) {\n return pixelCentroid;\n }\n var stemSource = polygonInfoTransform.applyToPoint(absoluteStemSource);\n switch (position) {\n case 1 /* Above */: {\n stemSource.y += stemExtension;\n break;\n }\n case 2 /* Below */: {\n stemSource.y -= stemExtension;\n break;\n }\n case 4 /* Left */: {\n stemSource.x += stemExtension;\n break;\n }\n case 8 /* Right */: {\n stemSource.x -= stemExtension;\n break;\n }\n case 128 /* AboveLeft */: {\n stemSource.x += (stemExtension / powerbi.DataLabelPointPositioner.cos45);\n stemSource.y += (stemExtension / powerbi.DataLabelPointPositioner.sin45);\n break;\n }\n case 64 /* AboveRight */: {\n stemSource.x -= (stemExtension / powerbi.DataLabelPointPositioner.cos45);\n stemSource.y += (stemExtension / powerbi.DataLabelPointPositioner.sin45);\n break;\n }\n case 32 /* BelowLeft */: {\n stemSource.x += (stemExtension / powerbi.DataLabelPointPositioner.cos45);\n stemSource.y -= (stemExtension / powerbi.DataLabelPointPositioner.sin45);\n break;\n }\n case 16 /* BelowRight */: {\n stemSource.x -= (stemExtension / powerbi.DataLabelPointPositioner.cos45);\n stemSource.y -= (stemExtension / powerbi.DataLabelPointPositioner.sin45);\n break;\n }\n case 256 /* Center */: {\n break;\n }\n default: {\n debug.assertFail(\"Unsupported label position\");\n }\n }\n return stemSource;\n };\n FilledMapLabelLayout.prototype.calculateStemDestination = function (labelBoundingBox, position) {\n var x;\n var y;\n switch (position) {\n case 1 /* Above */: {\n x = labelBoundingBox.left + labelBoundingBox.width / 2;\n y = labelBoundingBox.top + labelBoundingBox.height;\n break;\n }\n case 2 /* Below */: {\n x = labelBoundingBox.left + labelBoundingBox.width / 2;\n y = labelBoundingBox.top;\n break;\n }\n case 4 /* Left */: {\n x = labelBoundingBox.left + labelBoundingBox.width;\n y = labelBoundingBox.top + labelBoundingBox.height / 2;\n break;\n }\n case 8 /* Right */: {\n x = labelBoundingBox.left;\n y = labelBoundingBox.top + labelBoundingBox.height / 2;\n break;\n }\n case 128 /* AboveLeft */: {\n x = labelBoundingBox.left + labelBoundingBox.width;\n y = labelBoundingBox.top + labelBoundingBox.height;\n break;\n }\n case 64 /* AboveRight */: {\n x = labelBoundingBox.left;\n y = labelBoundingBox.top + labelBoundingBox.height;\n break;\n }\n case 32 /* BelowLeft */: {\n x = labelBoundingBox.left + labelBoundingBox.width;\n y = labelBoundingBox.top;\n break;\n }\n case 16 /* BelowRight */: {\n x = labelBoundingBox.left;\n y = labelBoundingBox.top;\n break;\n }\n case 256 /* Center */: {\n break;\n }\n default: {\n debug.assertFail(\"Unsupported label position\");\n }\n }\n return { x: x, y: y };\n };\n FilledMapLabelLayout.prototype.tryPositionForPolygonPosition = function (position, labelDataPoint, polygonInfoTransform, offset, inverseTransorm) {\n var polygon = labelDataPoint.parentShape.polygon;\n var pixelCentroid = polygonInfoTransform.applyToPoint(polygon.absoluteCentroid());\n var labelRect = this.getLabelPolygon(labelDataPoint, position, pixelCentroid, offset);\n var absoluteLabelRect = this.getAbsoluteRectangle(inverseTransorm, labelRect);\n return polygon.contains(absoluteLabelRect) ? absoluteLabelRect : null;\n };\n /**\n * Tests a particular position/offset combination for the given data label.\n * If the label can be placed, returns the resulting bounding box for the data\n * label. If not, returns null.\n */\n FilledMapLabelLayout.prototype.tryPlaceLabelOutsidePolygon = function (grid, position, labelDataPoint, offset, pixelCentroid, shapesGrid, inverseTransform) {\n var offsetForPosition = offset;\n var labelRect = this.getLabelPolygon(labelDataPoint, position, pixelCentroid, offsetForPosition);\n var otherLabelsConflict = grid.hasConflict(labelRect);\n if (!otherLabelsConflict) {\n var absoluteLabelRect = this.getAbsoluteRectangle(inverseTransform, labelRect);\n if (!shapesGrid.hasConflict(absoluteLabelRect, labelRect))\n return absoluteLabelRect;\n }\n return null;\n };\n FilledMapLabelLayout.prototype.updateLabelOffsets = function (polygonInfoTransform) {\n for (var _i = 0, _a = this.labels; _i < _a.length; _i++) {\n var label = _a[_i];\n if (!label.isVisible)\n continue;\n if (label.isPlacedInsidePolygon) {\n var newOffset = polygonInfoTransform.applyToPoint(label.absoluteBoundingBoxCenter);\n var xDelta = (label.boundingBox.left + label.boundingBox.width / 2) - newOffset.x;\n var yDelta = (label.boundingBox.top + label.boundingBox.height / 2) - newOffset.y;\n label.boundingBox.top -= yDelta;\n label.boundingBox.left -= xDelta;\n }\n else {\n var stemSourcePoint = polygonInfoTransform.applyToPoint(label.absoluteStemSource);\n var pixelCentroid = polygonInfoTransform.applyToPoint(label.originalAbsoluteCentroid);\n label.boundingBox = this.getLabelBoundingBox({ width: label.boundingBox.width, height: label.boundingBox.height }, label.originalPosition, pixelCentroid, label.originalPixelOffset);\n if (label.leaderLinePoints !== undefined)\n label.leaderLinePoints = this.setLeaderLinePoints(stemSourcePoint, this.calculateStemDestination(label.boundingBox, label.originalPosition));\n }\n }\n };\n FilledMapLabelLayout.prototype.getAbsoluteRectangle = function (inverseTransorm, rect) {\n return inverseTransorm.applyToRect(rect);\n };\n return FilledMapLabelLayout;\n }());\n powerbi.FilledMapLabelLayout = FilledMapLabelLayout;\n var LabelPolygonArrangeGrid = (function () {\n function LabelPolygonArrangeGrid(polygons, viewport) {\n this.viewport = viewport;\n var maxPolygonWidth = 0;\n var maxPolygonHeight = 0;\n for (var _i = 0, polygons_1 = polygons; _i < polygons_1.length; _i++) {\n var polygon = polygons_1[_i];\n var polygonSize = polygon.pixelBoundingRect;\n if (polygonSize.width > maxPolygonWidth) {\n maxPolygonWidth = polygonSize.width;\n }\n if (polygonSize.height > maxPolygonHeight) {\n maxPolygonHeight = polygonSize.height;\n }\n }\n if (maxPolygonWidth === 0) {\n maxPolygonWidth = viewport.width;\n }\n if (maxPolygonHeight === 0) {\n maxPolygonHeight = viewport.height;\n }\n var cellSize = this.cellSize = { width: maxPolygonWidth * LabelPolygonArrangeGrid.cellSizeMultiplier, height: maxPolygonHeight * LabelPolygonArrangeGrid.cellSizeMultiplier };\n this.columnCount = LabelPolygonArrangeGrid.getCellCount(cellSize.width, viewport.width, 1, 100);\n this.rowCount = LabelPolygonArrangeGrid.getCellCount(cellSize.height, viewport.height, 1, 100);\n var grid = [];\n for (var i = 0, ilen = this.columnCount; i < ilen; i++) {\n grid[i] = [];\n for (var j = 0, jlen = this.rowCount; j < jlen; j++) {\n grid[i][j] = [];\n }\n }\n this.grid = grid;\n for (var _a = 0, polygons_2 = polygons; _a < polygons_2.length; _a++) {\n var polygon = polygons_2[_a];\n this.add(polygon);\n }\n }\n LabelPolygonArrangeGrid.prototype.hasConflict = function (absolutLabelRect, pixelLabelRect) {\n var containingIndexRect = this.getContainingGridSubsection(pixelLabelRect);\n var grid = this.grid;\n for (var x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\n for (var y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\n for (var _i = 0, _a = grid[x][y]; _i < _a.length; _i++) {\n var currentPolygon = _a[_i];\n if (currentPolygon.conflicts(absolutLabelRect)) {\n return true;\n }\n }\n }\n }\n return false;\n };\n LabelPolygonArrangeGrid.prototype.add = function (polygon) {\n var containingIndexRect = this.getContainingGridSubsection(polygon.pixelBoundingRect);\n for (var x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\n for (var y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\n this.grid[x][y].push(polygon);\n }\n }\n };\n LabelPolygonArrangeGrid.prototype.getContainingGridSubsection = function (rect) {\n return {\n xMin: LabelPolygonArrangeGrid.bound(Math.floor(rect.left / this.cellSize.width), 0, this.columnCount),\n xMax: LabelPolygonArrangeGrid.bound(Math.ceil((rect.left + rect.width) / this.cellSize.width), 0, this.columnCount),\n yMin: LabelPolygonArrangeGrid.bound(Math.floor(rect.top / this.cellSize.height), 0, this.rowCount),\n yMax: LabelPolygonArrangeGrid.bound(Math.ceil((rect.top + rect.height) / this.cellSize.height), 0, this.rowCount),\n };\n };\n LabelPolygonArrangeGrid.getCellCount = function (step, length, minCount, maxCount) {\n return LabelPolygonArrangeGrid.bound(Math.ceil(length / step), minCount, maxCount);\n };\n LabelPolygonArrangeGrid.bound = function (value, min, max) {\n return Math.max(Math.min(value, max), min);\n };\n /**\n * A multiplier applied to the largest width height to attempt to balance # of\n * polygons in each cell and number of cells each polygon belongs to\n */\n LabelPolygonArrangeGrid.cellSizeMultiplier = 2;\n return LabelPolygonArrangeGrid;\n }());\n powerbi.LabelPolygonArrangeGrid = LabelPolygonArrangeGrid;\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n function createColorAllocatorFactory() {\n return new ColorAllocatorFactory();\n }\n visuals.createColorAllocatorFactory = createColorAllocatorFactory;\n var ColorAllocatorFactory = (function () {\n function ColorAllocatorFactory() {\n }\n ColorAllocatorFactory.prototype.linearGradient2 = function (options) {\n return new LinearGradient2Allocator(options);\n };\n ColorAllocatorFactory.prototype.linearGradient3 = function (options, splitScales) {\n if (splitScales)\n return new LinearGradient3AllocatorWithSplittedScales(options);\n return new LinearGradient3Allocator(options);\n };\n return ColorAllocatorFactory;\n }());\n var LinearGradient2Allocator = (function () {\n function LinearGradient2Allocator(options) {\n debug.assertValue(options, 'options');\n this.options = options;\n var min = options.min, max = options.max;\n this.scale = d3.scale.linear()\n .domain([min.value, max.value])\n .range([min.color, max.color])\n .clamp(true); // process a value outside of the domain - set to extremum values\n }\n LinearGradient2Allocator.prototype.color = function (value) {\n var min = this.options.min, max = this.options.max;\n if (min.value === max.value) {\n if (value >= max.value)\n return max.color;\n return min.color;\n }\n return this.scale(value);\n };\n return LinearGradient2Allocator;\n }());\n var LinearGradient3Allocator = (function () {\n function LinearGradient3Allocator(options) {\n debug.assertValue(options, 'options');\n this.options = options;\n var min = options.min, mid = options.mid, max = options.max;\n this.scale = d3.scale.linear()\n .domain([min.value, mid.value, max.value])\n .range([min.color, mid.color, max.color])\n .clamp(true); // process a value outside of the domain- set to extremum values\n }\n LinearGradient3Allocator.prototype.color = function (value) {\n var min = this.options.min, mid = this.options.mid, max = this.options.max;\n if (max.value === mid.value || mid.value === min.value || (max.value === mid.value && max.value === min.value)) {\n if (value >= max.value)\n return max.color;\n else if (value >= mid.value)\n return mid.color;\n return min.color;\n }\n return this.scale(value);\n };\n return LinearGradient3Allocator;\n }());\n var LinearGradient3AllocatorWithSplittedScales = (function () {\n function LinearGradient3AllocatorWithSplittedScales(options) {\n debug.assertValue(options, 'options');\n this.options = options;\n var min = options.min, mid = options.mid, max = options.max;\n /*\n If the center value is overridden, but the max and min remain automatic,\n colors are then assigned on a scale between the overridden center value and the max/min values in the data.\n Each side of the center value is assigned separately, independent of the relative scales.\n */\n this.scale1 = d3.scale.linear()\n .domain([min.value, mid.value])\n .range([min.color, mid.color])\n .clamp(true); // process a value outside of the domain- set to extremum values\n this.scale2 = d3.scale.linear()\n .domain([mid.value, max.value])\n .range([mid.color, max.color])\n .clamp(true); // process a value outside of the domain- set to extremum values\n }\n LinearGradient3AllocatorWithSplittedScales.prototype.color = function (value) {\n var min = this.options.min, mid = this.options.mid, max = this.options.max;\n if (max.value === mid.value || mid.value === min.value || (max.value === mid.value && max.value === min.value)) {\n if (value >= max.value)\n return max.color;\n else if (value >= mid.value)\n return mid.color;\n return min.color;\n }\n else if (value <= mid.value) {\n return this.scale1(value);\n }\n return this.scale2(value);\n };\n return LinearGradient3AllocatorWithSplittedScales;\n }());\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var BeautifiedFormat = {\n '0.00 %;-0.00 %;0.00 %': 'Percentage',\n '0.0 %;-0.0 %;0.0 %': 'Percentage1',\n };\n var defaultLocalizedStrings = {\n 'NullValue': '(Blank)',\n 'BooleanTrue': 'True',\n 'BooleanFalse': 'False',\n 'NaNValue': 'NaN',\n 'InfinityValue': '+Infinity',\n 'NegativeInfinityValue': '-Infinity',\n 'Restatement_Comma': '{0}, {1}',\n 'Restatement_CompoundAnd': '{0} and {1}',\n 'DisplayUnitSystem_EAuto_Title': 'Auto',\n 'DisplayUnitSystem_E0_Title': 'None',\n 'DisplayUnitSystem_E3_LabelFormat': '{0}K',\n 'DisplayUnitSystem_E3_Title': 'Thousands',\n 'DisplayUnitSystem_E6_LabelFormat': '{0}M',\n 'DisplayUnitSystem_E6_Title': 'Millions',\n 'DisplayUnitSystem_E9_LabelFormat': '{0}bn',\n 'DisplayUnitSystem_E9_Title': 'Billions',\n 'DisplayUnitSystem_E12_LabelFormat': '{0}T',\n 'DisplayUnitSystem_E12_Title': 'Trillions',\n 'Percentage': '#,0.##%',\n 'Percentage1': '#,0.#%',\n 'RichTextbox_Link_DefaultText': 'Link',\n 'TableTotalLabel': 'Total',\n 'Tooltip_HighlightedValueDisplayName': 'Highlighted',\n 'Funnel_PercentOfFirst': 'Percent of first',\n 'Funnel_PercentOfPrevious': 'Percent of previous',\n 'Funnel_PercentOfFirst_Highlight': 'Percent of first (highlighted)',\n 'Funnel_PercentOfPrevious_Highlight': 'Percent of previous (highlighted)',\n // Geotagging strings\n 'GeotaggingString_Continent': 'continent',\n 'GeotaggingString_Continents': 'continents',\n 'GeotaggingString_Country': 'country',\n 'GeotaggingString_Countries': 'countries',\n 'GeotaggingString_State': 'state',\n 'GeotaggingString_States': 'states',\n 'GeotaggingString_City': 'city',\n 'GeotaggingString_Cities': 'cities',\n 'GeotaggingString_Town': 'town',\n 'GeotaggingString_Towns': 'towns',\n 'GeotaggingString_Province': 'province',\n 'GeotaggingString_Provinces': 'provinces',\n 'GeotaggingString_County': 'county',\n 'GeotaggingString_Counties': 'counties',\n 'GeotaggingString_Village': 'village',\n 'GeotaggingString_Villages': 'villages',\n 'GeotaggingString_Post': 'post',\n 'GeotaggingString_Zip': 'zip',\n 'GeotaggingString_Code': 'code',\n 'GeotaggingString_Place': 'place',\n 'GeotaggingString_Places': 'places',\n 'GeotaggingString_Address': 'address',\n 'GeotaggingString_Addresses': 'addresses',\n 'GeotaggingString_Street': 'street',\n 'GeotaggingString_Streets': 'streets',\n 'GeotaggingString_Longitude': 'longitude',\n 'GeotaggingString_Longitude_Short': 'lon',\n 'GeotaggingString_Latitude': 'latitude',\n 'GeotaggingString_Latitude_Short': 'lat',\n 'GeotaggingString_PostalCode': 'postal code',\n 'GeotaggingString_PostalCodes': 'postal codes',\n 'GeotaggingString_ZipCode': 'zip code',\n 'GeotaggingString_ZipCodes': 'zip codes',\n 'GeotaggingString_Territory': 'territory',\n 'GeotaggingString_Territories': 'territories',\n 'Waterfall_IncreaseLabel': 'Increase',\n 'Waterfall_DecreaseLabel': 'Decrease',\n 'Waterfall_TotalLabel': 'Total',\n 'Slicer_SelectAll': 'Select All',\n };\n var DefaultVisualHostServices = (function () {\n function DefaultVisualHostServices() {\n }\n // TODO: Add locale-awareness to this host service. Currently default/english functionality only.\n DefaultVisualHostServices.initialize = function () {\n visuals.valueFormatter.setLocaleOptions(DefaultVisualHostServices.createLocaleOptions());\n visuals.TooltipManager.setLocalizedStrings(DefaultVisualHostServices.createTooltipLocaleOptions());\n };\n /**\n * Create locale options.\n *\n * Note: Public for testability.\n */\n DefaultVisualHostServices.createLocaleOptions = function () {\n return {\n null: defaultLocalizedStrings['NullValue'],\n true: defaultLocalizedStrings['BooleanTrue'],\n false: defaultLocalizedStrings['BooleanFalse'],\n NaN: defaultLocalizedStrings['NaNValue'],\n infinity: defaultLocalizedStrings['InfinityValue'],\n negativeInfinity: defaultLocalizedStrings['NegativeInfinityValue'],\n beautify: function (format) { return DefaultVisualHostServices.beautify(format); },\n describe: function (exponent) { return DefaultVisualHostServices.describeUnit(exponent); },\n restatementComma: defaultLocalizedStrings['Restatement_Comma'],\n restatementCompoundAnd: defaultLocalizedStrings['Restatement_CompoundAnd'],\n restatementCompoundOr: defaultLocalizedStrings['Restatement_CompoundOr']\n };\n };\n DefaultVisualHostServices.createTooltipLocaleOptions = function () {\n return {\n highlightedValueDisplayName: defaultLocalizedStrings['Tooltip_HighlightedValueDisplayName']\n };\n };\n DefaultVisualHostServices.prototype.getLocalizedString = function (stringId) {\n return defaultLocalizedStrings[stringId];\n };\n // NO-OP IHostServices methods\n DefaultVisualHostServices.prototype.onDragStart = function () { };\n DefaultVisualHostServices.prototype.canSelect = function () { return false; };\n DefaultVisualHostServices.prototype.onSelect = function () { };\n DefaultVisualHostServices.prototype.onContextMenu = function () { };\n DefaultVisualHostServices.prototype.loadMoreData = function () { };\n DefaultVisualHostServices.prototype.persistProperties = function (changes) { };\n DefaultVisualHostServices.prototype.onCustomSort = function (args) { };\n DefaultVisualHostServices.prototype.getViewMode = function () { return 0 /* View */; };\n DefaultVisualHostServices.prototype.setWarnings = function (warnings) { };\n DefaultVisualHostServices.prototype.setToolbar = function ($toolbar) { };\n DefaultVisualHostServices.prototype.shouldRetainSelection = function () { return false; };\n DefaultVisualHostServices.prototype.geocoder = function () { return visuals.services.createGeocoder(); };\n DefaultVisualHostServices.prototype.geolocation = function () { return visuals.services.createGeolocation(); };\n DefaultVisualHostServices.prototype.promiseFactory = function () { return powerbi.createJQueryPromiseFactory(); };\n DefaultVisualHostServices.prototype.analyzeFilter = function (options) {\n return {\n isNotFilter: false,\n selectedIdentities: [],\n filter: undefined,\n defaultValue: undefined,\n };\n };\n DefaultVisualHostServices.prototype.getIdentityDisplayNames = function (dentities) { return; };\n DefaultVisualHostServices.prototype.setIdentityDisplayNames = function (displayNamesIdentityPairs) { };\n DefaultVisualHostServices.beautify = function (format) {\n var key = BeautifiedFormat[format];\n if (key)\n return defaultLocalizedStrings[key] || format;\n return format;\n };\n DefaultVisualHostServices.describeUnit = function (exponent) {\n var exponentLookup = (exponent === -1) ? 'Auto' : exponent.toString();\n var title = defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_Title\"];\n var format = (exponent <= 0) ? '{0}' : defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_LabelFormat\"];\n if (title || format)\n return { title: title, format: format };\n };\n return DefaultVisualHostServices;\n }());\n visuals.DefaultVisualHostServices = DefaultVisualHostServices;\n visuals.defaultVisualHostServices = new DefaultVisualHostServices();\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n /**\n * Factory method to create an IInteractivityService instance.\n */\n function createInteractivityService(hostServices) {\n return new InteractivityService(hostServices);\n }\n visuals.createInteractivityService = createInteractivityService;\n /**\n * Creates a clear an svg rect to catch clear clicks.\n */\n function appendClearCatcher(selection) {\n return selection\n .append(\"rect\")\n .classed(\"clearCatcher\", true)\n .attr({ width: \"100%\", height: \"100%\" });\n }\n visuals.appendClearCatcher = appendClearCatcher;\n function isCategoryColumnSelected(propertyId, categories, idx) {\n return categories.objects != null\n && categories.objects[idx]\n && powerbi.DataViewObjects.getValue(categories.objects[idx], propertyId);\n }\n visuals.isCategoryColumnSelected = isCategoryColumnSelected;\n function dataHasSelection(data) {\n for (var i = 0, ilen = data.length; i < ilen; i++) {\n if (data[i].selected)\n return true;\n }\n return false;\n }\n visuals.dataHasSelection = dataHasSelection;\n var InteractivityService = (function () {\n function InteractivityService(hostServices) {\n this.renderSelectionInVisual = _.noop;\n this.renderSelectionInLegend = _.noop;\n this.renderSelectionInLabels = _.noop;\n // Selection state\n this.selectedIds = [];\n this.isInvertedSelectionMode = false;\n debug.assertValue(hostServices, 'hostServices');\n this.hostService = hostServices;\n }\n // IInteractivityService Implementation\n /** Binds the vsiual to the interactivityService */\n InteractivityService.prototype.bind = function (dataPoints, behavior, behaviorOptions, options) {\n var _this = this;\n // Bind the data\n if (options && options.overrideSelectionFromData) {\n // Override selection state from data points if needed\n this.takeSelectionStateFromDataPoints(dataPoints);\n }\n if (options) {\n if (options.isLegend) {\n // Bind to legend data instead of normal data if isLegend\n this.selectableLegendDataPoints = dataPoints;\n this.renderSelectionInLegend = function () { return behavior.renderSelection(_this.legendHasSelection()); };\n }\n else if (options.isLabels) {\n //Bind to label data instead of normal data if isLabels\n this.selectableLabelsDataPoints = dataPoints;\n this.renderSelectionInLabels = function () { return behavior.renderSelection(_this.labelsHasSelection()); };\n }\n else {\n this.selectableDataPoints = dataPoints;\n this.renderSelectionInVisual = function () { return behavior.renderSelection(_this.hasSelection()); };\n }\n if (options.hasSelectionOverride != null) {\n this.hasSelectionOverride = options.hasSelectionOverride;\n }\n if (options.slicerDefaultValueHandler) {\n this.slicerDefaultValueHandler = options.slicerDefaultValueHandler;\n }\n }\n else {\n this.selectableDataPoints = dataPoints;\n this.renderSelectionInVisual = function () { return behavior.renderSelection(_this.hasSelection()); };\n }\n // Bind to the behavior\n this.behavior = behavior;\n behavior.bindEvents(behaviorOptions, this);\n // Sync data points with current selection state\n this.syncSelectionState();\n };\n /**\n * Sets the selected state of all selectable data points to false and invokes the behavior's select command.\n */\n InteractivityService.prototype.clearSelection = function () {\n // if default value is already applied, don't clear the default selection\n if (this.slicerDefaultValueHandler && this.slicerDefaultValueHandler.getDefaultValue() && this.useDefaultValue) {\n this.isInvertedSelectionMode = false;\n return;\n }\n this.hasSelectionOverride = undefined;\n ArrayExtensions.clear(this.selectedIds);\n this.isInvertedSelectionMode = false;\n this.applyToAllSelectableDataPoints(function (dataPoint) { return dataPoint.selected = false; });\n this.renderAll();\n };\n InteractivityService.prototype.applySelectionStateToData = function (dataPoints) {\n for (var _i = 0, dataPoints_2 = dataPoints; _i < dataPoints_2.length; _i++) {\n var dataPoint = dataPoints_2[_i];\n dataPoint.selected = InteractivityService.checkDatapointAgainstSelectedIds(dataPoint, this.selectedIds);\n }\n return this.hasSelection();\n };\n /**\n * Checks whether there is at least one item selected.\n */\n InteractivityService.prototype.hasSelection = function () {\n return this.selectedIds.length > 0;\n };\n InteractivityService.prototype.legendHasSelection = function () {\n return this.selectableLegendDataPoints ? dataHasSelection(this.selectableLegendDataPoints) : false;\n };\n InteractivityService.prototype.labelsHasSelection = function () {\n return this.selectableLabelsDataPoints ? dataHasSelection(this.selectableLabelsDataPoints) : false;\n };\n InteractivityService.prototype.isSelectionModeInverted = function () {\n return this.isInvertedSelectionMode;\n };\n InteractivityService.prototype.setSelectionModeInverted = function (inverted) {\n this.isInvertedSelectionMode = inverted;\n };\n // ISelectionHandler Implementation\n InteractivityService.prototype.handleSelection = function (dataPoint, multiSelect) {\n // defect 7067397: should not happen so assert but also don't continue as it's\n // causing a lot of error telemetry in desktop.\n debug.assertValue(dataPoint, 'dataPoint');\n if (!dataPoint)\n return;\n this.useDefaultValue = false;\n this.select(dataPoint, multiSelect);\n this.sendSelectionToHost();\n this.renderAll();\n };\n InteractivityService.prototype.handleContextMenu = function (dataPoint, point) {\n this.sendContextMenuToHost(dataPoint, point);\n };\n InteractivityService.prototype.handleClearSelection = function () {\n this.useDefaultValue = true;\n this.clearSelection();\n this.sendSelectionToHost();\n };\n InteractivityService.prototype.toggleSelectionModeInversion = function () {\n this.useDefaultValue = false;\n this.isInvertedSelectionMode = !this.isInvertedSelectionMode;\n ArrayExtensions.clear(this.selectedIds);\n this.applyToAllSelectableDataPoints(function (dataPoint) { return dataPoint.selected = false; });\n this.sendSelectionToHost();\n this.isInvertedSelectionMode ? this.syncSelectionStateInverted() : this.syncSelectionState();\n this.renderAll();\n return this.isInvertedSelectionMode;\n };\n InteractivityService.prototype.persistSelectionFilter = function (filterPropertyIdentifier) {\n this.hostService.persistProperties(this.createChangeForFilterProperty(filterPropertyIdentifier));\n };\n InteractivityService.prototype.setDefaultValueMode = function (useDefaultValue) {\n this.useDefaultValue = useDefaultValue;\n };\n InteractivityService.prototype.isDefaultValueEnabled = function () {\n return this.useDefaultValue;\n };\n // Private utility methods\n InteractivityService.prototype.renderAll = function () {\n this.renderSelectionInVisual();\n this.renderSelectionInLegend();\n this.renderSelectionInLabels();\n };\n /** Marks a data point as selected and syncs selection with the host. */\n InteractivityService.prototype.select = function (d, multiSelect) {\n // If we're in inverted mode, use the invertedSelect instead\n if (this.isInvertedSelectionMode) {\n return this.selectInverted(d, multiSelect);\n }\n // For highlight data points we actually want to select the non-highlight data point\n if (d.identity.highlight) {\n d = _.find(this.selectableDataPoints, function (dp) { return !dp.identity.highlight && d.identity.includes(dp.identity, /* ignoreHighlight */ true); });\n debug.assertValue(d, 'Expected to find a non-highlight data point');\n }\n var id = d.identity;\n if (!id)\n return;\n var selected = !d.selected || (!multiSelect && this.selectedIds.length > 1);\n // If we have a multiselect flag, we attempt a multiselect\n if (multiSelect) {\n if (selected) {\n d.selected = true;\n this.selectedIds.push(id);\n if (id.hasIdentity()) {\n this.removeSelectionIdsWithOnlyMeasures();\n }\n else {\n this.removeSelectionIdsExceptOnlyMeasures();\n }\n }\n else {\n d.selected = false;\n this.removeId(id);\n }\n }\n // We do a single select if we didn't do a multiselect or if we find out that the multiselect is invalid.\n if (!multiSelect || !this.hostService.canSelect({ data: this.selectedIds.map(function (value) { return value.getSelector(); }) })) {\n this.clearSelection();\n if (selected) {\n d.selected = true;\n this.selectedIds.push(id);\n }\n }\n this.syncSelectionState();\n };\n InteractivityService.prototype.selectInverted = function (d, multiSelect) {\n var wasSelected = d.selected;\n var id = d.identity;\n debug.assert(!!multiSelect, \"inverted selections are only supported in multiselect mode\");\n // the current datapoint state has to be inverted\n d.selected = !wasSelected;\n if (wasSelected) {\n this.removeId(id);\n }\n else {\n this.selectedIds.push(id);\n if (id.hasIdentity()) {\n this.removeSelectionIdsWithOnlyMeasures();\n }\n else {\n this.removeSelectionIdsExceptOnlyMeasures();\n }\n }\n this.syncSelectionStateInverted();\n };\n InteractivityService.prototype.removeId = function (toRemove) {\n var selectedIds = this.selectedIds;\n for (var i = selectedIds.length - 1; i > -1; i--) {\n var currentId = selectedIds[i];\n if (toRemove.includes(currentId))\n selectedIds.splice(i, 1);\n }\n };\n /** Note: Public for UnitTesting */\n InteractivityService.prototype.createChangeForFilterProperty = function (filterPropertyIdentifier) {\n var properties = {};\n var selectors = [];\n if (this.selectedIds.length > 0) {\n selectors = _.chain(this.selectedIds)\n .filter(function (value) { return value.hasIdentity(); })\n .map(function (value) { return value.getSelector(); })\n .value();\n }\n var instance = {\n objectName: filterPropertyIdentifier.objectName,\n selector: undefined,\n properties: properties\n };\n var filter = powerbi.data.Selector.filterFromSelector(selectors, this.isInvertedSelectionMode);\n if (this.slicerDefaultValueHandler && this.slicerDefaultValueHandler.getDefaultValue()) {\n // we explicitly check for true/false because undefine means no default value\n if (this.useDefaultValue === true)\n filter = powerbi.data.SemanticFilter.getDefaultValueFilter(this.slicerDefaultValueHandler.getIdentityFields());\n else if (_.isEmpty(selectors))\n filter = powerbi.data.SemanticFilter.getAnyValueFilter(this.slicerDefaultValueHandler.getIdentityFields());\n }\n if (filter == null) {\n properties[filterPropertyIdentifier.propertyName] = {};\n return {\n remove: [instance]\n };\n }\n else {\n properties[filterPropertyIdentifier.propertyName] = filter;\n return {\n merge: [instance]\n };\n }\n };\n InteractivityService.prototype.sendContextMenuToHost = function (dataPoint, position) {\n var host = this.hostService;\n if (!host.onContextMenu)\n return;\n var selectors = this.getSelectorsByColumn([dataPoint.identity]);\n if (_.isEmpty(selectors))\n return;\n var args = {\n data: selectors,\n position: position\n };\n host.onContextMenu(args);\n };\n InteractivityService.prototype.sendSelectionToHost = function () {\n var host = this.hostService;\n if (host.onSelect) {\n var selectArgs = {\n data: this.selectedIds.filter(function (value) { return value.hasIdentity(); }).map(function (value) { return value.getSelector(); })\n };\n var data2 = this.getSelectorsByColumn(this.selectedIds);\n if (!_.isEmpty(data2))\n selectArgs.data2 = data2;\n host.onSelect(selectArgs);\n }\n };\n InteractivityService.prototype.getSelectorsByColumn = function (selectionIds) {\n return _(selectionIds)\n .filter(function (value) { return value.hasIdentity; })\n .map(function (value) { return value.getSelectorsByColumn(); })\n .compact()\n .value();\n };\n InteractivityService.prototype.takeSelectionStateFromDataPoints = function (dataPoints) {\n debug.assertValue(dataPoints, \"dataPoints\");\n var selectedIds = this.selectedIds;\n // Replace the existing selectedIds rather than merging.\n ArrayExtensions.clear(selectedIds);\n for (var _i = 0, dataPoints_3 = dataPoints; _i < dataPoints_3.length; _i++) {\n var dataPoint = dataPoints_3[_i];\n if (dataPoint.selected)\n selectedIds.push(dataPoint.identity);\n }\n };\n /**\n * Syncs the selection state for all data points that have the same category. Returns\n * true if the selection state was out of sync and corrections were made; false if\n * the data is already in sync with the service.\n *\n * If the data is not compatible with the current service's current selection state,\n * the state is cleared and the cleared selection is sent to the host.\n *\n * Ignores series for now, since we don't support series selection at the moment.\n */\n InteractivityService.prototype.syncSelectionState = function () {\n if (this.isInvertedSelectionMode) {\n return this.syncSelectionStateInverted();\n }\n var selectedIds = this.selectedIds;\n var selectableDataPoints = this.selectableDataPoints;\n var selectableLegendDataPoints = this.selectableLegendDataPoints;\n var selectableLabelsDataPoints = this.selectableLabelsDataPoints;\n var foundMatchingId = false; // Checked only against the visual's data points; it's possible to have stuff selected in the visual that's not in the legend, but not vice-verse\n if (!selectableDataPoints && !selectableLegendDataPoints)\n return;\n if (selectableDataPoints) {\n if (InteractivityService.updateSelectableDataPointsBySelectedIds(selectableDataPoints, selectedIds))\n foundMatchingId = true;\n }\n if (selectableLegendDataPoints) {\n if (InteractivityService.updateSelectableDataPointsBySelectedIds(selectableLegendDataPoints, selectedIds))\n foundMatchingId = true;\n }\n if (selectableLabelsDataPoints) {\n var labelsDataPoint_1;\n for (var i = 0, ilen = selectableLabelsDataPoints.length; i < ilen; i++) {\n labelsDataPoint_1 = selectableLabelsDataPoints[i];\n if (selectedIds.some(function (value) { return value.includes(labelsDataPoint_1.identity); }))\n labelsDataPoint_1.selected = true;\n else\n labelsDataPoint_1.selected = false;\n }\n }\n if (!foundMatchingId && selectedIds.length > 0) {\n this.clearSelection();\n this.sendSelectionToHost();\n }\n };\n InteractivityService.prototype.syncSelectionStateInverted = function () {\n var selectedIds = this.selectedIds;\n var selectableDataPoints = this.selectableDataPoints;\n if (!selectableDataPoints)\n return;\n if (selectedIds.length === 0) {\n for (var _i = 0, selectableDataPoints_1 = selectableDataPoints; _i < selectableDataPoints_1.length; _i++) {\n var dataPoint_1 = selectableDataPoints_1[_i];\n dataPoint_1.selected = false;\n }\n }\n else {\n for (var _a = 0, selectableDataPoints_2 = selectableDataPoints; _a < selectableDataPoints_2.length; _a++) {\n var dataPoint = selectableDataPoints_2[_a];\n if (selectedIds.some(function (value) { return value.includes(dataPoint.identity); }))\n dataPoint.selected = true;\n else if (dataPoint.selected)\n dataPoint.selected = false;\n }\n }\n };\n InteractivityService.prototype.applyToAllSelectableDataPoints = function (action) {\n var selectableDataPoints = this.selectableDataPoints;\n var selectableLegendDataPoints = this.selectableLegendDataPoints;\n var selectableLabelsDataPoints = this.selectableLabelsDataPoints;\n if (selectableDataPoints) {\n for (var _i = 0, selectableDataPoints_3 = selectableDataPoints; _i < selectableDataPoints_3.length; _i++) {\n var dataPoint = selectableDataPoints_3[_i];\n action(dataPoint);\n }\n }\n if (selectableLegendDataPoints) {\n for (var _a = 0, selectableLegendDataPoints_1 = selectableLegendDataPoints; _a < selectableLegendDataPoints_1.length; _a++) {\n var dataPoint = selectableLegendDataPoints_1[_a];\n action(dataPoint);\n }\n }\n if (selectableLabelsDataPoints) {\n for (var _b = 0, selectableLabelsDataPoints_1 = selectableLabelsDataPoints; _b < selectableLabelsDataPoints_1.length; _b++) {\n var dataPoint = selectableLabelsDataPoints_1[_b];\n action(dataPoint);\n }\n }\n };\n InteractivityService.updateSelectableDataPointsBySelectedIds = function (selectableDataPoints, selectedIds) {\n var foundMatchingId = false;\n for (var _i = 0, selectableDataPoints_4 = selectableDataPoints; _i < selectableDataPoints_4.length; _i++) {\n var datapoint = selectableDataPoints_4[_i];\n datapoint.selected = InteractivityService.checkDatapointAgainstSelectedIds(datapoint, selectedIds);\n if (datapoint.selected)\n foundMatchingId = true;\n }\n return foundMatchingId;\n };\n InteractivityService.checkDatapointAgainstSelectedIds = function (datapoint, selectedIds) {\n return selectedIds.some(function (value) { return value.includes(datapoint.identity); });\n };\n InteractivityService.prototype.removeSelectionIdsWithOnlyMeasures = function () {\n this.selectedIds = _.filter(this.selectedIds, function (identity) { return identity.hasIdentity(); });\n };\n InteractivityService.prototype.removeSelectionIdsExceptOnlyMeasures = function () {\n this.selectedIds = _.filter(this.selectedIds, function (identity) { return !identity.hasIdentity(); });\n };\n return InteractivityService;\n }());\n visuals.InteractivityService = InteractivityService;\n ;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var services;\n (function (services) {\n var CategoryTypes = visuals.MapUtil.CategoryTypes;\n var Settings = visuals.MapUtil.Settings;\n function createGeocoder() {\n return {\n geocode: geocode,\n geocodeBoundary: geocodeBoundary,\n geocodePoint: geocodePoint,\n tryGeocodeImmediate: tryGeocodeImmediate,\n tryGeocodeBoundaryImmediate: tryGeocodeBoundaryImmediate,\n };\n }\n services.createGeocoder = createGeocoder;\n services.safeCharacters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-\";\n /** Note: Used for test mockup */\n services.BingAjaxCall = $.ajax;\n services.CategoryTypeArray = [\n \"Address\",\n \"City\",\n \"Continent\",\n \"Country\",\n \"County\",\n \"Longitude\",\n \"Latitude\",\n \"Place\",\n \"PostalCode\",\n \"StateOrProvince\"\n ];\n function isCategoryType(value) {\n return services.CategoryTypeArray.indexOf(value) > -1;\n }\n services.isCategoryType = isCategoryType;\n services.BingEntities = {\n Continent: \"Continent\",\n Sovereign: \"Sovereign\",\n CountryRegion: \"CountryRegion\",\n AdminDivision1: \"AdminDivision1\",\n AdminDivision2: \"AdminDivision2\",\n PopulatedPlace: \"PopulatedPlace\",\n Postcode: \"Postcode\",\n Postcode1: \"Postcode1\",\n Neighborhood: \"Neighborhood\",\n Address: \"Address\",\n };\n // Static variables for caching, maps, etc.\n var geocodeQueue;\n var activeRequests;\n var categoryToBingEntity;\n var categoryToBingEntityGeodata;\n var geocodingCache;\n var GeocodeQuery = (function () {\n function GeocodeQuery(query, category) {\n this.query = query != null ? query : \"\";\n this.category = category != null ? category : \"\";\n this.key = (this.query + \"/\" + this.category).toLowerCase();\n if (!geocodingCache) {\n geocodingCache = services.createGeocodingCache(Settings.MaxCacheSize, Settings.MaxCacheSizeOverflow);\n }\n }\n GeocodeQuery.prototype.getBingEntity = function () {\n var category = this.category.toLowerCase();\n if (!categoryToBingEntity) {\n categoryToBingEntity = {};\n categoryToBingEntity[CategoryTypes.Continent.toLowerCase()] = services.BingEntities.Continent;\n categoryToBingEntity[CategoryTypes.CountryRegion.toLowerCase()] = services.BingEntities.Sovereign;\n categoryToBingEntity[CategoryTypes.StateOrProvince.toLowerCase()] = services.BingEntities.AdminDivision1;\n categoryToBingEntity[CategoryTypes.County.toLowerCase()] = services.BingEntities.AdminDivision2;\n categoryToBingEntity[CategoryTypes.City.toLowerCase()] = services.BingEntities.PopulatedPlace;\n categoryToBingEntity[CategoryTypes.PostalCode.toLowerCase()] = services.BingEntities.Postcode;\n categoryToBingEntity[CategoryTypes.Address.toLowerCase()] = services.BingEntities.Address;\n }\n return categoryToBingEntity[category] || \"\";\n };\n GeocodeQuery.prototype.getUrl = function () {\n var url = Settings.BingUrl + \"?key=\" + Settings.BingKey;\n var entityType = this.getBingEntity();\n var queryAdded = false;\n if (entityType) {\n if (entityType === services.BingEntities.Postcode) {\n url += \"&includeEntityTypes=Postcode,Postcode1,Postcode2,Postcode3,Postcode4\";\n }\n else if (this.query.indexOf(\",\") === -1 && (entityType === services.BingEntities.AdminDivision1 || entityType === services.BingEntities.AdminDivision2)) {\n queryAdded = true;\n try {\n url += \"&adminDistrict=\" + decodeURIComponent(this.query);\n }\n catch (e) {\n return null;\n }\n }\n else {\n url += \"&includeEntityTypes=\" + entityType;\n }\n }\n if (!queryAdded) {\n try {\n url += \"&q=\" + decodeURIComponent(this.query);\n }\n catch (e) {\n return null;\n }\n }\n var cultureName = navigator.userLanguage || navigator[\"language\"];\n cultureName = mapLocalesForBing(cultureName);\n if (cultureName) {\n url += \"&c=\" + cultureName;\n }\n url += \"&maxRes=20\";\n // If the query is of length 2, request the ISO 2-letter country code to be returned with the result to be compared against the query so that such results can be preferred.\n if (this.query.length === 2 && this.category === CategoryTypes.CountryRegion) {\n url += \"&include=ciso2\";\n }\n return url;\n };\n return GeocodeQuery;\n }());\n services.GeocodeQuery = GeocodeQuery;\n var GeocodePointQuery = (function (_super) {\n __extends(GeocodePointQuery, _super);\n function GeocodePointQuery(latitude, longitude) {\n _super.call(this, [latitude, longitude].join(), \"Point\");\n this.latitude = latitude;\n this.longitude = longitude;\n }\n GeocodePointQuery.prototype.getUrl = function () {\n var url = Settings.BingUrl + \"/\" +\n [this.latitude, this.longitude].join() + \"?\" +\n \"key=\" + Settings.BingKey +\n \"&includeEntityTypes=\" + [\n services.BingEntities.Address,\n services.BingEntities.Neighborhood,\n services.BingEntities.PopulatedPlace,\n services.BingEntities.Postcode1,\n services.BingEntities.AdminDivision1,\n services.BingEntities.AdminDivision2,\n services.BingEntities.CountryRegion].join() +\n \"&include=ciso2\";\n return url;\n };\n return GeocodePointQuery;\n }(GeocodeQuery));\n services.GeocodePointQuery = GeocodePointQuery;\n var GeocodeBoundaryQuery = (function (_super) {\n __extends(GeocodeBoundaryQuery, _super);\n function GeocodeBoundaryQuery(latitude, longitude, category, levelOfDetail, maxGeoData) {\n if (maxGeoData === void 0) { maxGeoData = 3; }\n _super.call(this, [latitude, longitude, levelOfDetail, maxGeoData].join(\",\"), category);\n this.latitude = latitude;\n this.longitude = longitude;\n this.levelOfDetail = levelOfDetail;\n this.maxGeoData = maxGeoData;\n }\n GeocodeBoundaryQuery.prototype.getBingEntity = function () {\n var category = this.category.toLowerCase();\n if (!categoryToBingEntityGeodata) {\n categoryToBingEntityGeodata = {};\n categoryToBingEntityGeodata[CategoryTypes.CountryRegion.toLowerCase()] = services.BingEntities.CountryRegion;\n categoryToBingEntityGeodata[CategoryTypes.StateOrProvince.toLowerCase()] = services.BingEntities.AdminDivision1;\n categoryToBingEntityGeodata[CategoryTypes.County.toLowerCase()] = services.BingEntities.AdminDivision2;\n categoryToBingEntityGeodata[CategoryTypes.City.toLowerCase()] = services.BingEntities.PopulatedPlace;\n categoryToBingEntityGeodata[CategoryTypes.PostalCode.toLowerCase()] = services.BingEntities.Postcode1;\n }\n return categoryToBingEntityGeodata[category] || \"\";\n };\n GeocodeBoundaryQuery.prototype.getUrl = function () {\n var url = Settings.BingUrlGeodata + \"key=\" + Settings.BingKey + \"&$format=json\";\n var entityType = this.getBingEntity();\n if (!entityType) {\n return null;\n }\n var cultureName = navigator.userLanguage || navigator[\"language\"];\n cultureName = mapLocalesForBing(cultureName);\n var cultures = cultureName.split(\"-\");\n var data = [this.latitude, this.longitude, this.levelOfDetail, \"'\" + entityType + \"'\", 1, 0, \"'\" + cultureName + \"'\"];\n if (cultures.length > 1) {\n data.push(\"'\" + cultures[1] + \"'\");\n }\n return url + \"&SpatialFilter=GetBoundary(\" + data.join(\", \") + \")\";\n };\n return GeocodeBoundaryQuery;\n }(GeocodeQuery));\n services.GeocodeBoundaryQuery = GeocodeBoundaryQuery;\n /**\n * Map locales that cause failures to similar locales that work\n */\n function mapLocalesForBing(locale) {\n switch (locale.toLowerCase()) {\n case 'fr':\n return 'fr-FR';\n default:\n return locale;\n }\n }\n function tryGeocodeImmediate(query, category) {\n var result = geocodingCache ? geocodingCache.getCoordinates(new GeocodeQuery(query, category).key) : undefined;\n return result;\n }\n function tryGeocodeBoundaryImmediate(latitude, longitude, category, levelOfDetail, maxGeoData) {\n if (maxGeoData === void 0) { maxGeoData = 3; }\n var result = geocodingCache ? geocodingCache.getCoordinates(new GeocodeBoundaryQuery(latitude, longitude, category, levelOfDetail, maxGeoData).key) : undefined;\n return result;\n }\n function geocodeCore(geocodeQuery) {\n var result = geocodingCache ? geocodingCache.getCoordinates(geocodeQuery.key) : undefined;\n var deferred = $.Deferred();\n if (result) {\n deferred.resolve(result);\n }\n else {\n geocodeQueue.push({ query: geocodeQuery, deferred: deferred });\n dequeue();\n }\n return deferred;\n }\n services.geocodeCore = geocodeCore;\n function geocode(query, category) {\n if (category === void 0) { category = \"\"; }\n return geocodeCore(new GeocodeQuery(query, category));\n }\n services.geocode = geocode;\n function geocodeBoundary(latitude, longitude, category, levelOfDetail, maxGeoData) {\n if (category === void 0) { category = \"\"; }\n if (levelOfDetail === void 0) { levelOfDetail = 2; }\n if (maxGeoData === void 0) { maxGeoData = 3; }\n return geocodeCore(new GeocodeBoundaryQuery(latitude, longitude, category, levelOfDetail, maxGeoData));\n }\n services.geocodeBoundary = geocodeBoundary;\n function geocodePoint(latitude, longitude) {\n return geocodeCore(new GeocodePointQuery(latitude, longitude));\n }\n services.geocodePoint = geocodePoint;\n function dequeue(decrement) {\n if (decrement === void 0) { decrement = 0; }\n activeRequests -= decrement;\n while (activeRequests < Settings.MaxBingRequest) {\n if (geocodeQueue.length === 0) {\n break;\n }\n activeRequests++;\n makeRequest(geocodeQueue.shift());\n }\n }\n function makeRequest(item) {\n // Check again if we already got the coordinate;\n var result = geocodingCache ? geocodingCache.getCoordinates(item.query.key) : undefined;\n if (result) {\n setTimeout(function () { return dequeue(1); });\n item.deferred.resolve(result);\n return;\n }\n // Unfortunately the Bing service doesn't support CORS, only jsonp. This issue must be raised and revised.\n // VSTS: 1396088 - Tracking: Ask: Bing geocoding to support CORS\n var config = {\n type: \"GET\",\n dataType: \"jsonp\",\n jsonp: \"jsonp\"\n };\n var url = item.query.getUrl();\n if (!url) {\n completeRequest(item, new Error(\"Unsupported query. \" + item.query.query));\n }\n services.BingAjaxCall(url, config).then(function (data) {\n try {\n if (item.query instanceof GeocodeBoundaryQuery) {\n var result_1 = data;\n if (result_1 && result_1.d && Array.isArray(result_1.d.results) && result_1.d.results.length > 0) {\n var entity = result_1.d.results[0];\n var primitives = entity.Primitives;\n if (primitives && primitives.length > 0) {\n var coordinates = {\n latitude: item.query.latitude,\n longitude: item.query.longitude,\n locations: []\n };\n primitives.sort(function (a, b) {\n if (a.Shape.length < b.Shape.length) {\n return 1;\n }\n if (a.Shape.length > b.Shape.length) {\n return -1;\n }\n return 0;\n });\n var maxGeoData = Math.min(primitives.length, item.query.maxGeoData);\n for (var i = 0; i < maxGeoData; i++) {\n var ringStr = primitives[i].Shape;\n var ringArray = ringStr.split(\",\");\n for (var j = 1; j < ringArray.length; j++) {\n coordinates.locations.push({ nativeBing: ringArray[j] });\n }\n }\n completeRequest(item, null, coordinates);\n }\n else {\n completeRequest(item, new Error(\"Geocode result is empty.\"));\n }\n }\n else {\n completeRequest(item, new Error(\"Geocode result is empty.\"));\n }\n }\n else if (item.query instanceof GeocodePointQuery) {\n var resources = data.resourceSets[0].resources;\n if (Array.isArray(resources) && resources.length > 0) {\n var index = getBestResultIndex(resources, item.query);\n var pointData = resources[index].point.coordinates;\n var addressData = resources[index].address;\n var coordinates = {\n latitude: parseFloat(pointData[0]),\n longitude: parseFloat(pointData[1]),\n addressLine: addressData.addressLine,\n locality: addressData.locality,\n neighborhood: addressData.neighborhood,\n adminDistrict: addressData.adminDistrict,\n adminDistrict2: addressData.adminDistrict2,\n formattedAddress: addressData.formattedAddress,\n postalCode: addressData.postalCode,\n countryRegionIso2: addressData.countryRegionIso2,\n countryRegion: addressData.countryRegion,\n landmark: addressData.landmark,\n };\n completeRequest(item, null, coordinates);\n }\n else {\n completeRequest(item, new Error(\"Geocode result is empty.\"));\n }\n }\n else {\n var resources = data.resourceSets[0].resources;\n if (Array.isArray(resources) && resources.length > 0) {\n var index = getBestResultIndex(resources, item.query);\n var pointData = resources[index].point.coordinates;\n var coordinates = {\n latitude: parseFloat(pointData[0]),\n longitude: parseFloat(pointData[1])\n };\n completeRequest(item, null, coordinates);\n }\n else {\n completeRequest(item, new Error(\"Geocode result is empty.\"));\n }\n }\n }\n catch (error) {\n completeRequest(item, error);\n }\n }, function (error) {\n completeRequest(item, error);\n });\n }\n var dequeueTimeoutId;\n function completeRequest(item, error, coordinate) {\n if (coordinate === void 0) { coordinate = null; }\n dequeueTimeoutId = setTimeout(function () { return dequeue(1); }, Settings.UseDoubleArrayGeodataResult ? Settings.UseDoubleArrayDequeueTimeout : 0);\n if (error) {\n item.deferred.reject(error);\n }\n else {\n if (geocodingCache && !(item.query instanceof GeocodePointQuery))\n geocodingCache.registerCoordinates(item.query.key, coordinate);\n item.deferred.resolve(coordinate);\n }\n }\n function getBestResultIndex(resources, query) {\n var queryString = query.query.toLowerCase();\n // If string is of length 2 and is a country, check against the ISO country code of results, prefering exact matches\n if (queryString.length === 2 && query.category === CategoryTypes.CountryRegion) {\n for (var index = 0; index < resources.length; index++) {\n var iso2 = resources[index].address && resources[index].address.countryRegionIso2;\n if (iso2 && queryString === iso2.toLowerCase()) {\n return index;\n }\n }\n }\n // Prefer results that match the targetEntity (geotagged category) on the query\n var targetEntity = query.getBingEntity().toLowerCase();\n for (var index = 0; index < resources.length; index++) {\n var resultEntity = (resources[index].entityType || \"\").toLowerCase();\n if (resultEntity === targetEntity) {\n return index;\n }\n }\n return 0;\n }\n function reset() {\n geocodeQueue = [];\n activeRequests = 0;\n categoryToBingEntity = null;\n clearTimeout(dequeueTimeoutId);\n }\n services.reset = reset;\n reset();\n })(services = visuals.services || (visuals.services = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var services;\n (function (services) {\n function createGeocodingCache(maxCacheSize, maxCacheSizeOverflow, localStorageService) {\n if (!localStorageService)\n localStorageService = powerbi.localStorageService;\n return new GeocodingCache(maxCacheSize, maxCacheSizeOverflow, localStorageService);\n }\n services.createGeocodingCache = createGeocodingCache;\n var GeocodingCache = (function () {\n function GeocodingCache(maxCacheSize, maxCacheSizeOverflow, localStorageService) {\n this.geocodeCache = {};\n this.geocodeCacheCount = 0;\n this.maxCacheSize = maxCacheSize;\n this.maxCacheSizeOverflow = maxCacheSizeOverflow;\n this.localStorageService = localStorageService;\n }\n /**\n * Retrieves the coordinate for the key from the cache, returning undefined on a cache miss.\n */\n GeocodingCache.prototype.getCoordinates = function (key) {\n // Check in-memory cache\n var pair = this.geocodeCache[key];\n if (pair) {\n ++pair.hitCount;\n return pair.coordinate;\n }\n // Check local storage cache\n pair = this.localStorageService.getData(key);\n if (pair) {\n this.registerInMemory(key, pair.coordinate);\n return pair.coordinate;\n }\n return undefined;\n };\n /**\n * Registers the query and coordinate to the cache.\n */\n GeocodingCache.prototype.registerCoordinates = function (key, coordinate) {\n this.registerInMemory(key, coordinate);\n this.registerInStorage(key, coordinate);\n };\n GeocodingCache.prototype.registerInMemory = function (key, coordinate) {\n var geocodeCache = this.geocodeCache;\n var maxCacheSize = this.maxCacheSize;\n var maxCacheCount = maxCacheSize + this.maxCacheSizeOverflow;\n // are we about to exceed the maximum?\n if (this.geocodeCacheCount >= maxCacheCount) {\n var keys = Object.keys(geocodeCache);\n var cacheSize = keys.length;\n // sort keys in *descending* hitCount order\n keys.sort(function (a, b) {\n var cachedA = geocodeCache[a];\n var cachedB = geocodeCache[b];\n var ca = cachedA ? cachedA.hitCount : 0;\n var cb = cachedB ? cachedB.hitCount : 0;\n return ca < cb ? 1 : (ca > cb ? -1 : 0);\n });\n // whack ones with the lower hitCounts.\n // - while # whacked keys is small, do a quick wipe\n // - after awhile we get lots of keys whose cached value is undefined. \n // when there are \"too many,\" make a whole new memory cache.\n if (cacheSize < 2 * maxCacheCount) {\n for (var i = maxCacheSize; i < cacheSize; i++)\n geocodeCache[keys[i]] = undefined;\n }\n else {\n var newGeocodeCache = {};\n for (var i = 0; i < maxCacheSize; ++i)\n newGeocodeCache[keys[i]] = geocodeCache[keys[i]];\n geocodeCache = this.geocodeCache = newGeocodeCache;\n }\n this.geocodeCacheCount = maxCacheSize;\n }\n geocodeCache[key] = { key: key, coordinate: coordinate, hitCount: 1 };\n ++this.geocodeCacheCount;\n };\n GeocodingCache.prototype.registerInStorage = function (key, coordinate) {\n this.localStorageService.setData(key, { coordinate: coordinate });\n };\n return GeocodingCache;\n }());\n })(services = visuals.services || (visuals.services = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var services;\n (function (services) {\n function createGeolocation() {\n return new GeolocationService();\n }\n services.createGeolocation = createGeolocation;\n /**\n * HTML5 Implementation of IGeolocation\n */\n var GeolocationService = (function () {\n function GeolocationService() {\n this.webGeolocation = navigator.geolocation;\n }\n GeolocationService.prototype.watchPosition = function (successCallback, errorCallback) {\n return this.webGeolocation.watchPosition(function (position) {\n successCallback(position);\n }, function (error) {\n if (errorCallback != null) {\n errorCallback(error);\n }\n });\n };\n GeolocationService.prototype.clearWatch = function (watchId) {\n this.webGeolocation.clearWatch(watchId);\n };\n GeolocationService.prototype.getCurrentPosition = function (successCallback, errorCallback) {\n this.webGeolocation.getCurrentPosition(function (position) {\n successCallback(position);\n }, function (error) {\n if (errorCallback != null) {\n errorCallback(error);\n }\n });\n };\n return GeolocationService;\n }());\n })(services = visuals.services || (visuals.services = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var unsupportedVisuals = ['play', 'subview', 'smallMultiple'];\n var visualPluginFactory;\n (function (visualPluginFactory) {\n var VisualPluginService = (function () {\n function VisualPluginService(featureSwitches) {\n this.plugins = powerbi.visuals.plugins;\n this.featureSwitches = featureSwitches;\n }\n /**\n * Gets metadata for all registered.\n */\n VisualPluginService.prototype.getVisuals = function () {\n var registry = this.plugins, names = Object.keys(registry);\n return names.map(function (name) { return registry[name]; });\n };\n VisualPluginService.prototype.getPlugin = function (type) {\n if (!type) {\n return;\n }\n var plugin = this.plugins[type];\n if (!plugin) {\n return;\n }\n return plugin;\n };\n VisualPluginService.prototype.capabilities = function (type) {\n var plugin = this.getPlugin(type);\n if (plugin)\n return plugin.capabilities;\n };\n VisualPluginService.prototype.requireSandbox = function (plugin) {\n return plugin && plugin.custom;\n };\n VisualPluginService.prototype.removeAnyCustomVisuals = function () {\n var plugins = powerbi.visuals.plugins;\n for (var key in plugins) {\n var p = plugins[key];\n if (p.custom) {\n delete plugins[key];\n }\n }\n };\n VisualPluginService.prototype.isCustomVisual = function (visual) {\n if (visual) {\n if (this.plugins[visual]) {\n return this.plugins[visual].custom === true;\n }\n else if (_.include(unsupportedVisuals, visual)) {\n /*use the hardcoded unsupported visual list to distinguish unsupported visual with custom visual when the plugin object is not in memory*/\n return false;\n }\n else {\n return true;\n }\n }\n return false;\n };\n VisualPluginService.prototype.isScriptVisual = function (type) {\n var visualCapabilities = this.capabilities(type);\n if (visualCapabilities && visualCapabilities.dataViewMappings && powerbi.ScriptResultUtil.findScriptResult(visualCapabilities.dataViewMappings)) {\n return true;\n }\n return false;\n };\n VisualPluginService.prototype.shouldDisableVisual = function (type, mapDisabled) {\n return (type === visuals.plugins.map.name || type === visuals.plugins.filledMap.name) && mapDisabled;\n };\n VisualPluginService.prototype.isScriptVisualQueryable = function () {\n // Feature switch determines if Script visuals are query visuals - currently non-query in PBI site\n return (this.featureSwitches !== undefined && this.featureSwitches.scriptVisualEnabled);\n };\n VisualPluginService.prototype.getInteractivityOptions = function (visualType) {\n var interactivityOptions = {\n overflow: 'hidden',\n };\n return interactivityOptions;\n };\n return VisualPluginService;\n }());\n visualPluginFactory.VisualPluginService = VisualPluginService;\n function createPlugin(visualPlugins, base, create, modifyPluginFn) {\n var visualPlugin = powerbi.Prototype.inherit(base);\n visualPlugin.create = create;\n if (modifyPluginFn) {\n modifyPluginFn(visualPlugin);\n }\n visualPlugins[base.name] = visualPlugin;\n }\n visualPluginFactory.createPlugin = createPlugin;\n function createDashboardPlugins(plugins, options, featureSwitches) {\n var tooltipsOnDashboard = options.tooltipsEnabled;\n var lineChartLabelDensityEnabled = featureSwitches && featureSwitches.lineChartLabelDensityEnabled;\n // Bar Chart\n createPlugin(plugins, powerbi.visuals.plugins.barChart, function () { return new visuals.CartesianChart({\n chartType: 6 /* StackedBar */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Clustered Bar Chart\n createPlugin(plugins, powerbi.visuals.plugins.clusteredBarChart, function () { return new visuals.CartesianChart({\n chartType: 5 /* ClusteredBar */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Clustered Column Chart\n createPlugin(plugins, powerbi.visuals.plugins.clusteredColumnChart, function () { return new visuals.CartesianChart({\n chartType: 3 /* ClusteredColumn */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Column Chart\n createPlugin(plugins, powerbi.visuals.plugins.columnChart, function () { return new visuals.CartesianChart({\n chartType: 4 /* StackedColumn */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Data Dot Clustered Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.dataDotClusteredColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 15 /* DataDotClusteredColumnCombo */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Data Dot Stacked Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.dataDotStackedColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 16 /* DataDotStackedColumnCombo */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Donut Chart\n createPlugin(plugins, powerbi.visuals.plugins.donutChart, function () { return new visuals.DonutChart({\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Funnel Chart\n createPlugin(plugins, powerbi.visuals.plugins.funnel, function () { return new visuals.FunnelChart({\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Gauge\n createPlugin(plugins, powerbi.visuals.plugins.gauge, function () { return new visuals.Gauge({\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Hundred Percent Stacked Bar Chart\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedBarChart, function () { return new visuals.CartesianChart({\n chartType: 7 /* HundredPercentStackedBar */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Hundred Percent Stacked Column Chart\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart, function () { return new visuals.CartesianChart({\n chartType: 8 /* HundredPercentStackedColumn */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Line Chart\n createPlugin(plugins, powerbi.visuals.plugins.lineChart, function () { return new visuals.CartesianChart({\n chartType: 0 /* Line */,\n tooltipsEnabled: tooltipsOnDashboard,\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\n }); });\n // Area Chart\n createPlugin(plugins, powerbi.visuals.plugins.areaChart, function () { return new visuals.CartesianChart({\n chartType: 1 /* Area */,\n tooltipsEnabled: tooltipsOnDashboard,\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\n }); });\n // Stacked Area Chart\n createPlugin(plugins, powerbi.visuals.plugins.stackedAreaChart, function () { return new visuals.CartesianChart({\n chartType: 2 /* StackedArea */,\n tooltipsEnabled: tooltipsOnDashboard,\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\n }); });\n // Line Clustered Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.lineClusteredColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 13 /* LineClusteredColumnCombo */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Line Stacked Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.lineStackedColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 14 /* LineStackedColumnCombo */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Pie Chart\n createPlugin(plugins, powerbi.visuals.plugins.pieChart, function () { return new visuals.DonutChart({\n sliceWidthRatio: 0,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Scatter Chart\n createPlugin(plugins, powerbi.visuals.plugins.scatterChart, function () { return new visuals.CartesianChart({\n chartType: 9 /* Scatter */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Treemap\n createPlugin(plugins, powerbi.visuals.plugins.treemap, function () { return new visuals.Treemap({\n isScrollable: false,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Waterfall Chart\n createPlugin(plugins, powerbi.visuals.plugins.waterfallChart, function () { return new visuals.CartesianChart({\n chartType: 12 /* Waterfall */,\n tooltipsEnabled: tooltipsOnDashboard,\n }); });\n // Map\n createPlugin(plugins, powerbi.visuals.plugins.map, function () { return new visuals.Map({\n tooltipsEnabled: tooltipsOnDashboard,\n disableZooming: true,\n disablePanning: true,\n }); });\n // Filled Map\n createPlugin(plugins, powerbi.visuals.plugins.filledMap, function () { return new visuals.Map({\n filledMap: true,\n tooltipsEnabled: tooltipsOnDashboard,\n disableZooming: true,\n disablePanning: true,\n }); });\n // Matrix\n createPlugin(plugins, powerbi.visuals.plugins.matrix, function () { return new visuals.Matrix({}); });\n // Table\n createPlugin(plugins, powerbi.visuals.plugins.table, function () { return new visuals.Table({\n isConditionalFormattingEnabled: false,\n }); });\n }\n function createMinervaPlugins(plugins, featureSwitches) {\n var scriptVisualEnabled = featureSwitches ? featureSwitches.scriptVisualEnabled : false;\n var scriptVisualAuthoringEnabled = featureSwitches ? featureSwitches.scriptVisualAuthoringEnabled : false;\n var isLabelInteractivityEnabled = featureSwitches ? featureSwitches.isLabelInteractivityEnabled : false;\n var conditionalFormattingEnabled = featureSwitches ? featureSwitches.conditionalFormattingEnabled : false;\n var fillMapDataLabelsEnabled = featureSwitches ? featureSwitches.filledMapDataLabelsEnabled : false;\n var lineChartLabelDensityEnabled = featureSwitches ? featureSwitches.lineChartLabelDensityEnabled : false;\n // Bar Chart\n createPlugin(plugins, powerbi.visuals.plugins.barChart, function () { return new visuals.CartesianChart({\n chartType: 6 /* StackedBar */,\n isScrollable: true, animator: new visuals.WebColumnChartAnimator(),\n tooltipsEnabled: true,\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Card\n createPlugin(plugins, powerbi.visuals.plugins.card, function () { return new visuals.Card({\n isScrollable: true,\n animator: new visuals.BaseAnimator(),\n }); });\n // Clustered Bar Chart\n createPlugin(plugins, powerbi.visuals.plugins.clusteredBarChart, function () { return new visuals.CartesianChart({\n chartType: 5 /* ClusteredBar */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Clustered Column Chart\n createPlugin(plugins, powerbi.visuals.plugins.clusteredColumnChart, function () { return new visuals.CartesianChart({\n chartType: 3 /* ClusteredColumn */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Column Chart\n createPlugin(plugins, powerbi.visuals.plugins.columnChart, function () { return new visuals.CartesianChart({\n chartType: 4 /* StackedColumn */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Data Dot Clustered Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.dataDotClusteredColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 15 /* DataDotClusteredColumnCombo */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior(), new visuals.DataDotChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Data Dot Stacked Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.dataDotStackedColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 16 /* DataDotStackedColumnCombo */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior(), new visuals.DataDotChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Donut Chart\n createPlugin(plugins, powerbi.visuals.plugins.donutChart, function () { return new visuals.DonutChart({\n animator: new visuals.WebDonutChartAnimator(),\n isScrollable: true,\n tooltipsEnabled: true,\n behavior: new visuals.DonutChartWebBehavior(),\n }); });\n // Funnel Chart\n createPlugin(plugins, powerbi.visuals.plugins.funnel, function () { return new visuals.FunnelChart({\n animator: new visuals.WebFunnelAnimator(),\n behavior: new visuals.FunnelWebBehavior(),\n tooltipsEnabled: true,\n }); });\n // Gauge\n createPlugin(plugins, powerbi.visuals.plugins.gauge, function () { return new visuals.Gauge({\n animator: new visuals.BaseAnimator(),\n tooltipsEnabled: true,\n }); });\n // Hundred Percent Stacked Bar Chart\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedBarChart, function () { return new visuals.CartesianChart({\n chartType: 7 /* HundredPercentStackedBar */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Hundred Percent Stacked Column Chart\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart, function () { return new visuals.CartesianChart({\n chartType: 8 /* HundredPercentStackedColumn */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Line Chart\n createPlugin(plugins, powerbi.visuals.plugins.lineChart, function () { return new visuals.CartesianChart({\n chartType: 0 /* Line */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.BaseAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.LineChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\n }); });\n // Area Chart\n createPlugin(plugins, powerbi.visuals.plugins.areaChart, function () { return new visuals.CartesianChart({\n chartType: 1 /* Area */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.BaseAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.LineChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\n }); });\n // Stacked Area Chart\n createPlugin(plugins, powerbi.visuals.plugins.stackedAreaChart, function () { return new visuals.CartesianChart({\n chartType: 2 /* StackedArea */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.BaseAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.LineChartWebBehavior()]),\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\n }); });\n // Line Clustered Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.lineClusteredColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 13 /* LineClusteredColumnCombo */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior(), new visuals.LineChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Line Stacked Combo Chart\n createPlugin(plugins, powerbi.visuals.plugins.lineStackedColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 14 /* LineStackedColumnCombo */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.WebColumnChartAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ColumnChartWebBehavior(), new visuals.LineChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Pie Chart\n createPlugin(plugins, powerbi.visuals.plugins.pieChart, function () { return new visuals.DonutChart({\n sliceWidthRatio: 0,\n animator: new visuals.WebDonutChartAnimator(),\n isScrollable: true,\n tooltipsEnabled: true,\n behavior: new visuals.DonutChartWebBehavior(),\n }); });\n // Scatter Chart\n createPlugin(plugins, powerbi.visuals.plugins.scatterChart, function () { return new visuals.CartesianChart({\n chartType: 9 /* Scatter */,\n isScrollable: true,\n tooltipsEnabled: true,\n animator: new visuals.BaseAnimator(),\n behavior: new visuals.CartesianChartBehavior([new visuals.ScatterChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Treemap\n createPlugin(plugins, powerbi.visuals.plugins.treemap, function () { return new visuals.Treemap({\n animator: new visuals.WebTreemapAnimator,\n isScrollable: true,\n behavior: new visuals.TreemapWebBehavior(),\n tooltipsEnabled: true,\n }); });\n // Waterfall Chart\n createPlugin(plugins, powerbi.visuals.plugins.waterfallChart, function () { return new visuals.CartesianChart({\n chartType: 12 /* Waterfall */,\n isScrollable: true,\n tooltipsEnabled: true,\n behavior: new visuals.CartesianChartBehavior([new visuals.WaterfallChartWebBehavior()]),\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\n }); });\n // Map\n createPlugin(plugins, powerbi.visuals.plugins.map, function () { return new visuals.Map({\n behavior: new visuals.MapBehavior(),\n tooltipsEnabled: true,\n isLegendScrollable: true,\n }); });\n // Filled Map\n createPlugin(plugins, powerbi.visuals.plugins.filledMap, function () { return new visuals.Map({\n filledMap: true,\n behavior: new visuals.MapBehavior,\n tooltipsEnabled: true,\n filledMapDataLabelsEnabled: fillMapDataLabelsEnabled,\n isLegendScrollable: true,\n }); });\n // Slicer\n createPlugin(plugins, powerbi.visuals.plugins.slicer, function () { return new visuals.Slicer({\n behavior: new visuals.SlicerWebBehavior(),\n }); });\n // Matrix\n createPlugin(plugins, powerbi.visuals.plugins.matrix, function () { return new visuals.Matrix({}); });\n // Table\n createPlugin(plugins, powerbi.visuals.plugins.table, function () { return new visuals.Table({\n isConditionalFormattingEnabled: conditionalFormattingEnabled,\n }); });\n ;\n if (scriptVisualEnabled && scriptVisualAuthoringEnabled) {\n // R visual\n createPlugin(plugins, powerbi.visuals.plugins.scriptVisual, function () { return new visuals.ScriptVisual({ canRefresh: true }); });\n }\n }\n var PlaygroundVisualPluginService = (function (_super) {\n __extends(PlaygroundVisualPluginService, _super);\n function PlaygroundVisualPluginService() {\n _super.call(this, undefined);\n this.visualPlugins = powerbi.visuals.plugins;\n createMinervaPlugins(this.visualPlugins, null);\n }\n PlaygroundVisualPluginService.prototype.getVisuals = function () {\n var registry = this.visualPlugins, names = Object.keys(registry);\n return names.map(function (name) { return registry[name]; });\n };\n PlaygroundVisualPluginService.prototype.getPlugin = function (type) {\n if (!type) {\n return;\n }\n var plugin = this.visualPlugins[type];\n if (!plugin) {\n return;\n }\n return plugin;\n };\n PlaygroundVisualPluginService.prototype.capabilities = function (type) {\n var plugin = this.getPlugin(type);\n if (plugin) {\n return plugin.capabilities;\n }\n };\n return PlaygroundVisualPluginService;\n }(VisualPluginService));\n visualPluginFactory.PlaygroundVisualPluginService = PlaygroundVisualPluginService;\n /**\n * This plug-in service is used when displaying visuals on the dashboard.\n */\n var DashboardPluginService = (function (_super) {\n __extends(DashboardPluginService, _super);\n function DashboardPluginService(featureSwitches, options) {\n _super.call(this, featureSwitches);\n debug.assertValue(featureSwitches, 'featureSwitches');\n this.visualPlugins = {};\n createDashboardPlugins(this.visualPlugins, options, this.featureSwitches);\n }\n DashboardPluginService.prototype.getPlugin = function (type) {\n if (this.visualPlugins[type]) {\n return this.visualPlugins[type];\n }\n return _super.prototype.getPlugin.call(this, type);\n };\n DashboardPluginService.prototype.requireSandbox = function (plugin) {\n return (this.featureSwitches.sandboxVisualsEnabled) && (!plugin || (plugin && plugin.custom));\n };\n return DashboardPluginService;\n }(VisualPluginService));\n visualPluginFactory.DashboardPluginService = DashboardPluginService;\n // This plug-in service is used when displaying visuals for insights.\n var InsightsPluginService = (function (_super) {\n __extends(InsightsPluginService, _super);\n function InsightsPluginService(featureSwitches) {\n _super.call(this, featureSwitches);\n debug.assertValue(featureSwitches, 'featureSwitches');\n this.visualPlugins = {};\n // Clustered Bar Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.clusteredBarChart, function () { return new visuals.CartesianChart({\n chartType: 5 /* ClusteredBar */,\n animator: new visuals.WebColumnChartAnimator(),\n tooltipsEnabled: true\n }); });\n // Column Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.columnChart, function () { return new visuals.CartesianChart({\n chartType: 4 /* StackedColumn */,\n animator: new visuals.WebColumnChartAnimator(),\n tooltipsEnabled: true\n }); });\n // Donut Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.donutChart, function () { return new visuals.DonutChart({\n animator: new visuals.WebDonutChartAnimator(),\n tooltipsEnabled: true,\n }); });\n // Hundred Percent Stacked Bar Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedBarChart, function () { return new visuals.CartesianChart({\n chartType: 7 /* HundredPercentStackedBar */,\n animator: new visuals.WebColumnChartAnimator(),\n tooltipsEnabled: true\n }); });\n // Hundred Percent Stacked Column Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart, function () { return new visuals.CartesianChart({\n chartType: 8 /* HundredPercentStackedColumn */,\n animator: new visuals.WebColumnChartAnimator(),\n tooltipsEnabled: true\n }); });\n // Line Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineChart, function () { return new visuals.CartesianChart({\n chartType: 0 /* Line */,\n animator: new visuals.BaseAnimator(),\n tooltipsEnabled: true,\n }); });\n // Area Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.areaChart, function () { return new visuals.CartesianChart({\n chartType: 1 /* Area */,\n animator: new visuals.BaseAnimator(),\n tooltipsEnabled: true,\n }); });\n // Pie Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.pieChart, function () { return new visuals.DonutChart({\n sliceWidthRatio: 0,\n animator: new visuals.WebDonutChartAnimator(),\n tooltipsEnabled: true,\n }); });\n // Scatter Chart\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.scatterChart, function () { return new visuals.CartesianChart({\n chartType: 9 /* Scatter */,\n animator: new visuals.BaseAnimator(),\n tooltipsEnabled: true,\n }); }, undefined);\n }\n InsightsPluginService.prototype.getPlugin = function (type) {\n if (this.visualPlugins[type]) {\n return this.visualPlugins[type];\n }\n return _super.prototype.getPlugin.call(this, type);\n };\n InsightsPluginService.prototype.requireSandbox = function (plugin) {\n return (this.featureSwitches.sandboxVisualsEnabled) && (!plugin || (plugin && plugin.custom));\n };\n return InsightsPluginService;\n }(VisualPluginService));\n visualPluginFactory.InsightsPluginService = InsightsPluginService;\n var MobileVisualPluginService = (function (_super) {\n __extends(MobileVisualPluginService, _super);\n function MobileVisualPluginService(smallViewPortProperties, featureSwitches) {\n var _this = this;\n _super.call(this, featureSwitches);\n this.smallViewPortProperties = smallViewPortProperties || {\n CartesianSmallViewPortProperties: {\n hideAxesOnSmallViewPort: true,\n hideLegendOnSmallViewPort: true,\n MinHeightLegendVisible: MobileVisualPluginService.MinHeightLegendVisible,\n MinHeightAxesVisible: MobileVisualPluginService.MinHeightAxesVisible,\n },\n GaugeSmallViewPortProperties: {\n hideGaugeSideNumbersOnSmallViewPort: true,\n smallGaugeMarginsOnSmallViewPort: true,\n MinHeightGaugeSideNumbersVisible: MobileVisualPluginService.MinHeightGaugeSideNumbersVisible,\n GaugeMarginsOnSmallViewPort: MobileVisualPluginService.GaugeMarginsOnSmallViewPort,\n },\n FunnelSmallViewPortProperties: {\n hideFunnelCategoryLabelsOnSmallViewPort: true,\n minHeightFunnelCategoryLabelsVisible: MobileVisualPluginService.MinHeightFunnelCategoryLabelsVisible,\n },\n DonutSmallViewPortProperties: {\n maxHeightToScaleDonutLegend: MobileVisualPluginService.MaxHeightToScaleDonutLegend,\n },\n };\n // Disable tooltips for mobile\n visuals.TooltipManager.ShowTooltips = false;\n // Don't trim overflow data on mobile\n var trimOrdinalDataOnOverflow = false;\n var mapThrottleInterval = this.getMapThrottleInterval();\n this.visualPlugins = {};\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.areaChart, function () { return new visuals.CartesianChart({\n chartType: 1 /* Area */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.barChart, function () { return new visuals.CartesianChart({\n chartType: 6 /* StackedBar */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.clusteredBarChart, function () { return new visuals.CartesianChart({\n chartType: 5 /* ClusteredBar */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.clusteredColumnChart, function () { return new visuals.CartesianChart({\n chartType: 3 /* ClusteredColumn */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.columnChart, function () { return new visuals.CartesianChart({\n chartType: 4 /* StackedColumn */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.comboChart, function () { return new visuals.CartesianChart({\n chartType: 10 /* ComboChart */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.dataDotChart, function () { return new visuals.CartesianChart({\n chartType: 11 /* DataDot */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.dataDotClusteredColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 15 /* DataDotClusteredColumnCombo */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.dataDotStackedColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 16 /* DataDotStackedColumnCombo */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedBarChart, function () { return new visuals.CartesianChart({\n chartType: 7 /* HundredPercentStackedBar */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart, function () { return new visuals.CartesianChart({\n chartType: 8 /* HundredPercentStackedColumn */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.stackedAreaChart, function () { return new visuals.CartesianChart({\n chartType: 2 /* StackedArea */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.waterfallChart, function () { return new visuals.CartesianChart({\n chartType: 12 /* Waterfall */,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineChart, function () { return new visuals.CartesianChart({\n chartType: 0 /* Line */,\n cartesianSmallViewPortProperties: _this.smallViewPortProperties.CartesianSmallViewPortProperties,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineClusteredColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 13 /* LineClusteredColumnCombo */,\n cartesianSmallViewPortProperties: _this.smallViewPortProperties.CartesianSmallViewPortProperties,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineStackedColumnComboChart, function () { return new visuals.CartesianChart({\n chartType: 14 /* LineStackedColumnCombo */,\n cartesianSmallViewPortProperties: _this.smallViewPortProperties.CartesianSmallViewPortProperties,\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.scatterChart, function () { return new visuals.CartesianChart({\n chartType: 9 /* Scatter */,\n cartesianSmallViewPortProperties: _this.smallViewPortProperties.CartesianSmallViewPortProperties,\n behavior: new visuals.CartesianChartBehavior([new visuals.ScatterChartMobileBehavior()])\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.gauge, function () { return new visuals.Gauge({\n gaugeSmallViewPortProperties: _this.smallViewPortProperties.GaugeSmallViewPortProperties\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.funnel, function () { return new visuals.FunnelChart({\n animator: null,\n funnelSmallViewPortProperties: _this.smallViewPortProperties.FunnelSmallViewPortProperties\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.donutChart, function () { return new visuals.DonutChart({\n disableGeometricCulling: true,\n smallViewPortProperties: _this.smallViewPortProperties.DonutSmallViewPortProperties\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.pieChart, function () { return new visuals.DonutChart({\n sliceWidthRatio: 0,\n disableGeometricCulling: true,\n smallViewPortProperties: _this.smallViewPortProperties.DonutSmallViewPortProperties\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.matrix, function () { return new visuals.Matrix({\n isTouchEnabled: true\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.table, function () { return new visuals.Table({\n isTouchEnabled: true\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.map, function () { return new visuals.Map({\n viewChangeThrottleInterval: mapThrottleInterval,\n enableCurrentLocation: featureSwitches ? featureSwitches.mapCurrentLocationEnabled : false\n }); });\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.filledMap, function () { return new visuals.Map({\n filledMap: true,\n viewChangeThrottleInterval: mapThrottleInterval\n }); });\n }\n MobileVisualPluginService.prototype.getPlugin = function (type) {\n if (this.visualPlugins[type])\n return this.visualPlugins[type];\n return _super.prototype.getPlugin.call(this, type);\n };\n MobileVisualPluginService.prototype.requireSandbox = function (plugin) {\n if (this.featureSwitches)\n return (this.featureSwitches.sandboxVisualsEnabled) && (!plugin || (plugin && plugin.custom));\n else\n return _super.prototype.requireSandbox.call(this, plugin);\n };\n // Windows phone webView chokes when zooming on heavy maps,\n // this is a workaround to allow a relatively smooth pinch to zoom experience.\n MobileVisualPluginService.prototype.getMapThrottleInterval = function () {\n var windowsPhoneThrottleInterval = 100;\n var userAgentLowerCase = navigator.userAgent.toLowerCase();\n if (userAgentLowerCase.indexOf('windows phone') !== -1) {\n return windowsPhoneThrottleInterval;\n }\n return undefined;\n };\n MobileVisualPluginService.prototype.getInteractivityOptions = function (visualType) {\n var mobileOptions = {\n overflow: this.getMobileOverflowString(visualType),\n isInteractiveLegend: this.isChartSupportInteractivity(visualType),\n selection: true,\n };\n return mobileOptions;\n };\n MobileVisualPluginService.prototype.getMobileOverflowString = function (visualType) {\n switch (visualType) {\n case 'multiRowCard':\n return 'visible';\n default:\n return 'hidden';\n }\n };\n MobileVisualPluginService.prototype.isChartSupportInteractivity = function (visualType) {\n switch (visualType) {\n case 'areaChart':\n case 'barChart':\n case 'clusteredBarChart':\n case 'clusteredColumnChart':\n case 'columnChart':\n case 'donutChart':\n case 'hundredPercentStackedBarChart':\n case 'hundredPercentStackedColumnChart':\n case 'lineChart':\n case 'pieChart':\n case 'scatterChart':\n case 'table':\n case 'matrix':\n case 'multiRowCard':\n return true;\n default:\n return false;\n }\n };\n MobileVisualPluginService.MinHeightLegendVisible = 125;\n MobileVisualPluginService.MinHeightAxesVisible = 125;\n MobileVisualPluginService.MinHeightGaugeSideNumbersVisible = 80;\n MobileVisualPluginService.GaugeMarginsOnSmallViewPort = 10;\n MobileVisualPluginService.MinHeightFunnelCategoryLabelsVisible = 80;\n MobileVisualPluginService.MaxHeightToScaleDonutLegend = 300;\n return MobileVisualPluginService;\n }(VisualPluginService));\n visualPluginFactory.MobileVisualPluginService = MobileVisualPluginService;\n // this function is called by tests\n function create() {\n return new VisualPluginService(undefined);\n }\n visualPluginFactory.create = create;\n function createVisualPluginService(featureSwitch) {\n return new VisualPluginService(featureSwitch);\n }\n visualPluginFactory.createVisualPluginService = createVisualPluginService;\n function createDashboard(featureSwitches, options) {\n return new DashboardPluginService(featureSwitches, options);\n }\n visualPluginFactory.createDashboard = createDashboard;\n function createInsights(featureSwitches) {\n return new InsightsPluginService(featureSwitches);\n }\n visualPluginFactory.createInsights = createInsights;\n function createMobile(smallViewPortProperties, featureSwitches) {\n return new MobileVisualPluginService(smallViewPortProperties, featureSwitches);\n }\n visualPluginFactory.createMobile = createMobile;\n })(visualPluginFactory = visuals.visualPluginFactory || (visuals.visualPluginFactory = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var UNSELECTABLE_CLASS_NAME = \"unselectable\";\n function fire(eventHandlers, eventArgs) {\n if (eventHandlers) {\n for (var i = 0; i < eventHandlers.length; i++) {\n var h = eventHandlers[i];\n h(eventArgs);\n }\n }\n }\n controls.fire = fire;\n var ScrollbarButton = (function () {\n // Constructor\n function ScrollbarButton(owner, direction) {\n this._owner = owner;\n this._direction = direction;\n this._timerHandle = undefined;\n this.createView();\n var that = this;\n this._element.addEventListener(\"mousedown\", function (e) { that.onMouseDown(e); });\n $(this._element).addClass(UNSELECTABLE_CLASS_NAME);\n $(this._svg).addClass(UNSELECTABLE_CLASS_NAME);\n $(this._polygon).addClass(UNSELECTABLE_CLASS_NAME);\n }\n Object.defineProperty(ScrollbarButton.prototype, \"element\", {\n // Properties\n get: function () {\n return this._element;\n },\n enumerable: true,\n configurable: true\n });\n // Methods\n ScrollbarButton.prototype.createView = function () {\n var svgns = \"http://www.w3.org/2000/svg\";\n this._polygon = document.createElementNS(svgns, \"polygon\");\n this._polygon.setAttributeNS(null, \"points\", \"3,3 6,3 13,8 6,13 3,13 10,8\");\n this._polygon.setAttributeNS(null, \"fill\", ScrollbarButton.ARROW_COLOR);\n this._svg = document.createElementNS(svgns, \"svg\");\n var svgStyle = this._svg.style;\n svgStyle.position = \"absolute\";\n svgStyle.left = \"0px\";\n svgStyle.top = \"0px\";\n this._svg.appendChild(this._polygon);\n this._element = document.createElement(\"div\");\n this._element.className = Scrollbar.arrowClassName;\n this._element.appendChild(this._svg);\n this._owner.element.appendChild(this._element);\n };\n ScrollbarButton.prototype.onMouseDown = function (event) {\n var that = this;\n clearTimeout(this._timerHandle);\n if (!this._mouseUpWrapper) {\n event.cancelBubble = true;\n var that_1 = this;\n this._mouseUpWrapper = function (event) { that_1.onMouseUp(event); };\n Scrollbar.addDocumentMouseUpEvent(this._mouseUpWrapper);\n }\n this._owner._scrollSmallIncrement(this._direction);\n this._owner.refresh();\n this._timerHandle = setTimeout(function () { that.onMouseDown(event); }, 100);\n if (event.preventDefault) {\n event.preventDefault(); // prevent dragging\n }\n };\n ScrollbarButton.prototype.onMouseUp = function (event) {\n clearTimeout(this._timerHandle);\n Scrollbar.removeDocumentMouseUpEvent(this._mouseUpWrapper);\n this._mouseUpWrapper = undefined;\n };\n ScrollbarButton.prototype.arrange = function (width, height, angle) {\n var size = Math.min(width, height);\n var scale = size / 16;\n var x = (width - size) / 2;\n var y = (height - size) / 2;\n this._polygon.setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \") scale(\" + scale + \") rotate(\" + angle + \",8,8)\");\n this._svg.setAttributeNS(null, \"width\", width + \"px\");\n this._svg.setAttributeNS(null, \"height\", height + \"px\");\n controls.HTMLElementUtils.setElementWidth(this._element, width);\n controls.HTMLElementUtils.setElementHeight(this._element, height);\n };\n // Const\n // TODO: Move to style\n ScrollbarButton.MIN_WIDTH = 26;\n ScrollbarButton.ARROW_COLOR = \"#404040\";\n return ScrollbarButton;\n }());\n controls.ScrollbarButton = ScrollbarButton;\n /** Scrollbar base class */\n var Scrollbar = (function () {\n function Scrollbar(parentElement, layoutKind) {\n this.MIN_BAR_SIZE = 10;\n this.min = 0;\n this.max = 10;\n this.viewMin = 0;\n this.viewSize = 2;\n this.smallIncrement = 1;\n this._onscroll = [];\n this._screenToOffsetScale = 1.0;\n this.createView(parentElement, layoutKind);\n var that = this;\n this._element.addEventListener(\"mousedown\", function (e) { that.onBackgroundMouseDown(e); });\n this._middleBar.addEventListener(\"mousedown\", function (e) { that.onMiddleBarMouseDown(e); });\n this._timerHandle = undefined;\n this._visible = true;\n this.element[\"winControl\"] = this;\n $(this._touchPanel).addClass(UNSELECTABLE_CLASS_NAME);\n }\n Scrollbar.prototype.scrollBy = function (delta) {\n this.scrollTo(this.viewMin + delta);\n };\n Scrollbar.prototype.scrollUp = function () {\n this.scrollBy(-this.smallIncrement);\n };\n Scrollbar.prototype.scrollDown = function () {\n this.scrollBy(this.smallIncrement);\n };\n Scrollbar.prototype.scrollPageUp = function () {\n this.scrollBy(-this.viewSize);\n };\n Scrollbar.prototype.scrollPageDown = function () {\n this.scrollBy(this.viewSize);\n };\n Object.defineProperty(Scrollbar.prototype, \"width\", {\n get: function () {\n return this._width;\n },\n set: function (value) {\n this._width = value;\n this._element.style.width = value;\n this.invalidateArrange();\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Scrollbar.prototype, \"height\", {\n get: function () {\n return this._height;\n },\n set: function (value) {\n this._height = value;\n this._element.style.height = value;\n this.invalidateArrange();\n },\n enumerable: true,\n configurable: true\n });\n Scrollbar.prototype.refresh = function () {\n debug.assertFail(\"PureVirtualMethod: Scrollbar.refresh()\");\n };\n Object.defineProperty(Scrollbar.prototype, \"element\", {\n get: function () {\n return this._element;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Scrollbar.prototype, \"maxButton\", {\n get: function () {\n return this._maxButton;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Scrollbar.prototype, \"middleBar\", {\n get: function () {\n return this._middleBar;\n },\n enumerable: true,\n configurable: true\n });\n Scrollbar.prototype._scrollSmallIncrement = function (direction) {\n this.scrollBy(this.smallIncrement * direction);\n };\n Object.defineProperty(Scrollbar.prototype, \"visible\", {\n get: function () {\n return this._visible;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Scrollbar.prototype, \"isInMouseCapture\", {\n get: function () {\n return this._timerHandle !== undefined;\n },\n enumerable: true,\n configurable: true\n });\n Scrollbar.prototype.show = function (value) {\n this._visible = value;\n this.element.style.visibility = value ? \"visible\" : \"hidden\";\n this.invalidateArrange();\n };\n Scrollbar.prototype._getMouseOffset = function (event) {\n if (event.offsetX !== undefined)\n return { x: event.offsetX, y: event.offsetY };\n if (event.layerX !== undefined)\n return { x: event.layerX, y: event.layerY };\n return { x: event.screenX, y: event.screenY };\n };\n Scrollbar.prototype._getOffsetXDelta = function (event) {\n return (event.screenX - this._screenPrevMousePos.x) / this._screenToOffsetScale;\n };\n Scrollbar.prototype._getOffsetYDelta = function (event) {\n return (event.screenY - this._screenPrevMousePos.y) / this._screenToOffsetScale;\n };\n Scrollbar.prototype._getOffsetXTouchDelta = function (event) {\n return this._getMouseOffset(event).x - this._offsetTouchPrevPos.x;\n };\n Scrollbar.prototype._getOffsetYTouchDelta = function (event) {\n return this._getMouseOffset(event).y - this._offsetTouchPrevPos.y;\n };\n Scrollbar.prototype.initTouch = function (panel, allowMouseDrag) {\n var _this = this;\n this._touchPanel = panel;\n this._allowMouseDrag = allowMouseDrag === undefined ? true : allowMouseDrag;\n if (\"ontouchmove\" in panel) {\n panel.addEventListener(\"touchstart\", function (e) { return _this.onTouchStart(e); });\n panel.addEventListener(\"touchmove\", function (e) { return _this.onTouchMove(e); });\n panel.addEventListener(\"touchend\", function (e) { return _this.onTouchEnd(e); });\n }\n else {\n panel.addEventListener(\"mousedown\", function (e) { return _this.onTouchMouseDown(e); });\n panel.addEventListener(\"mousemove\", function (e) { return _this.onTouchMouseMove(e); });\n panel.addEventListener(\"mouseup\", function (e) { return _this.onTouchMouseUp(e); });\n }\n };\n Scrollbar.prototype.onTouchStart = function (e) {\n if (e.touches.length === 1) {\n this.onTouchMouseDown(e.touches[0]);\n }\n };\n Scrollbar.prototype.onTouchMove = function (e) {\n if (e.touches.length === 1) {\n if (e.preventDefault)\n e.preventDefault();\n this.onTouchMouseMove(e.touches[0]);\n }\n };\n Scrollbar.prototype.onTouchEnd = function (e) {\n this.onTouchMouseUp(e.touches.length === 1 ? e.touches[0] : e, true);\n };\n Scrollbar.prototype.onTouchMouseDown = function (e) {\n // except IE touch cancels mouse so not need for detection. For IE touch and mouse difference is detected by a flag.\n if (!this._allowMouseDrag &&\n e[\"pointerType\"] === MSPointerEvent.MSPOINTER_TYPE_MOUSE) {\n return;\n }\n if (\"setCapture\" in this._touchPanel) {\n this._touchPanel.setCapture(true);\n }\n this._offsetTouchPrevPos = this._offsetTouchStartPos = null;\n this._touchStarted = true;\n };\n Scrollbar.prototype._getOffsetTouchDelta = function (e) {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getOffsetTouchDelta()\");\n return null;\n };\n Scrollbar.prototype.onTouchMouseMove = function (e) {\n if (this._touchStarted) {\n if (!this._offsetTouchStartPos) {\n this._offsetTouchPrevPos = this._offsetTouchStartPos = this._getMouseOffset(e);\n }\n var delta = this._getOffsetTouchDelta(e);\n if (delta !== 0) {\n this.scrollBy(-delta / this._getRunningSize(false) * this.viewSize);\n this._offsetTouchPrevPos = this._getMouseOffset(e);\n }\n if (e.preventDefault)\n e.preventDefault();\n e.cancelBubble = true;\n }\n };\n Scrollbar.prototype.onTouchMouseUp = function (e, bubble) {\n if (this._touchStarted) {\n if (this._offsetTouchStartPos) {\n var end = this._getMouseOffset(e);\n if (!bubble && (Math.abs(this._offsetTouchStartPos.x - end.x) > 3 || Math.abs(this._offsetTouchStartPos.y - end.y) > 3)) {\n if (e.preventDefault)\n e.preventDefault();\n e.cancelBubble = true;\n }\n }\n }\n if (\"releaseCapture\" in this._touchPanel) {\n this._touchPanel.releaseCapture();\n }\n this._touchStarted = false;\n };\n Scrollbar.prototype.registerElementForMouseWheelScrolling = function (element) {\n var _this = this;\n element.addEventListener(\"mousewheel\", function (e) { _this.onMouseWheel(e); });\n element.addEventListener(\"DOMMouseScroll\", function (e) { _this.onFireFoxMouseWheel(e); });\n };\n Scrollbar.prototype.createView = function (parentElement, layoutKind) {\n this._element = document.createElement(\"div\");\n this._element.className = Scrollbar.className;\n this._element.setAttribute(\"drag-resize-disabled\", \"true\");\n if (layoutKind === 0 /* Canvas */)\n parentElement.appendChild(this._element);\n this._minButton = new ScrollbarButton(this, -1);\n this._maxButton = new ScrollbarButton(this, 1);\n this._middleBar = document.createElement(\"div\");\n this._middleBar.className = Scrollbar.barClassName;\n this._element.appendChild(this._middleBar);\n };\n Scrollbar.prototype.scrollTo = function (pos) {\n var viewMin = Math.min(this.max - this.viewSize, Math.max(this.min, pos));\n if (viewMin !== this.viewMin) {\n this.viewMin = viewMin;\n fire(this._onscroll, null);\n }\n };\n Scrollbar.prototype._scrollByPage = function (event) {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._scrollByPage()\");\n };\n Scrollbar.prototype._getRunningSize = function (net) {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getRunningSize()\");\n return null;\n };\n Scrollbar.prototype._getOffsetDelta = function (event) {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getOffsetDelta()\");\n return null;\n };\n Scrollbar.prototype.scroll = function (event) {\n var delta = this._getOffsetDelta(event) / this._getRunningSize(true) * (this.max - this.min);\n if (delta < 0) {\n if (this._getScreenMousePos(event) >= this._screenMaxMousePos) {\n return;\n }\n }\n else if (delta > 0) {\n if (this._getScreenMousePos(event) <= this._screenMinMousePos) {\n return;\n }\n }\n this.scrollBy(delta);\n };\n Object.defineProperty(Scrollbar.prototype, \"actualWidth\", {\n get: function () {\n if (this._actualWidth === undefined) {\n this.arrange();\n }\n return this._actualWidth;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Scrollbar.prototype, \"actualHeight\", {\n get: function () {\n if (!this._actualHeight === undefined) {\n this.arrange();\n }\n return this._actualHeight;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Scrollbar.prototype, \"actualButtonWidth\", {\n get: function () {\n if (!this._actualButtonWidth === undefined) {\n this.arrange();\n }\n return this._actualButtonWidth;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Scrollbar.prototype, \"actualButtonHeight\", {\n get: function () {\n if (!this._actualButtonHeight === undefined) {\n this.arrange();\n }\n return this._actualButtonHeight;\n },\n enumerable: true,\n configurable: true\n });\n Scrollbar.prototype.arrange = function () {\n if (!this._actualWidth) {\n this._actualWidth = this._element.offsetWidth;\n this._actualHeight = this._element.offsetHeight;\n this._actualButtonWidth = this._calculateButtonWidth();\n this._actualButtonHeight = this._calculateButtonHeight();\n this._minButton.arrange(this._actualButtonWidth, this._actualButtonHeight, this._getMinButtonAngle());\n this._maxButton.arrange(this._actualButtonWidth, this._actualButtonHeight, this._getMaxButtonAngle());\n this._setMaxButtonPosition();\n }\n };\n Scrollbar.prototype._calculateButtonWidth = function () {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._calculateButtonWidth()\");\n return null;\n };\n Scrollbar.prototype._calculateButtonHeight = function () {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._calculateButtonHeight()\");\n return null;\n };\n Scrollbar.prototype._getMinButtonAngle = function () {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getMinButtonAngle()\");\n return null;\n };\n Scrollbar.prototype._getMaxButtonAngle = function () {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getMaxButtonAngle()\");\n return null;\n };\n Scrollbar.prototype._setMaxButtonPosition = function () {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._setMaxButtonPosition()\");\n };\n Scrollbar.prototype.invalidateArrange = function () {\n this._actualWidth = undefined;\n this._actualHeight = undefined;\n this._actualButtonWidth = undefined;\n this._actualButtonHeight = undefined;\n };\n Scrollbar.prototype.onHoldBackgroundMouseDown = function (event) {\n var _this = this;\n var holdDelay = this._timerHandle ?\n Scrollbar.ScrollbarBackgroundMousedownHoldDelay :\n Scrollbar.ScrollbarBackgroundFirstTimeMousedownHoldDelay;\n this._timerHandle = setTimeout(function () {\n _this.onBackgroundMouseDown(event);\n }, holdDelay);\n };\n Scrollbar.prototype.onBackgroundMouseDown = function (event) {\n var that = this;\n clearTimeout(this._timerHandle);\n if (!this._backgroundMouseUpWrapper) {\n event.cancelBubble = true;\n this._backgroundMouseUpWrapper = function (event) { that.onBackgroundMouseUp(event); };\n Scrollbar.addDocumentMouseUpEvent(this._backgroundMouseUpWrapper);\n }\n this._scrollByPage(event);\n this.refresh();\n this.onHoldBackgroundMouseDown(event);\n if (event.preventDefault)\n event.preventDefault(); // prevent dragging\n };\n Scrollbar.prototype.onBackgroundMouseUp = function (event) {\n clearTimeout(this._timerHandle);\n this._timerHandle = undefined;\n Scrollbar.removeDocumentMouseUpEvent(this._backgroundMouseUpWrapper);\n this._backgroundMouseUpWrapper = undefined;\n };\n Scrollbar.prototype.getPinchZoomY = function () {\n return document.documentElement.clientHeight / window.innerHeight;\n };\n Scrollbar.prototype.onMiddleBarMouseDown = function (event) {\n event.cancelBubble = true;\n this._screenPrevMousePos = { x: event.screenX, y: event.screenY };\n this._screenMinMousePos = this._getScreenMousePos(event) - (this._getScreenContextualLeft(this._middleBar) - this._getScreenContextualRight(this._minButton.element));\n this._screenMaxMousePos = this._getScreenMousePos(event) + (this._getScreenContextualLeft(this._maxButton.element) - this._getScreenContextualRight(this._middleBar));\n this._screenToOffsetScale = controls.HTMLElementUtils.getAccumulatedScale(this.element) * this.getPinchZoomY();\n var that = this;\n this._middleBarMouseMoveWrapper = function (e) { that.onMiddleBarMouseMove(e); };\n Scrollbar.addDocumentMouseMoveEvent(this._middleBarMouseMoveWrapper);\n this._middleBarMouseUpWrapper = function (e) { that.onMiddleBarMouseUp(e); };\n Scrollbar.addDocumentMouseUpEvent(this._middleBarMouseUpWrapper);\n if (event.preventDefault)\n event.preventDefault(); // prevent dragging\n };\n Scrollbar.prototype.onMiddleBarMouseMove = function (event) {\n if (!this._screenPrevMousePos) {\n return;\n }\n this.scroll(event);\n this.refresh();\n this._screenPrevMousePos = { x: event.screenX, y: event.screenY };\n };\n Scrollbar.prototype.onMiddleBarMouseUp = function (event) {\n this._screenPrevMousePos = undefined;\n Scrollbar.removeDocumentMouseMoveEvent(this._middleBarMouseMoveWrapper);\n this._middleBarMouseMoveWrapper = undefined;\n Scrollbar.removeDocumentMouseUpEvent(this._middleBarMouseUpWrapper);\n this._middleBarMouseUpWrapper = undefined;\n if (event.preventDefault)\n event.preventDefault(); // prevent other events\n };\n Scrollbar.prototype._getScreenContextualLeft = function (element) {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getScreenContextualLeft()\");\n return null;\n };\n Scrollbar.prototype._getScreenContextualRight = function (element) {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getScreenContextualRight()\");\n return null;\n };\n Scrollbar.prototype.onMouseWheel = function (e) {\n if (e.wheelDelta) {\n this.mouseWheel(e.wheelDelta);\n }\n e.preventDefault();\n };\n Scrollbar.prototype.onFireFoxMouseWheel = function (e) {\n if (e.detail) {\n this.mouseWheel(-e.detail);\n }\n e.preventDefault();\n };\n Scrollbar.prototype.mouseWheel = function (delta) {\n if (this.visible) {\n if (delta < 0) {\n delta = Math.min(-Scrollbar.MouseWheelRange, delta);\n }\n else if (delta > 0) {\n delta = Math.max(Scrollbar.MouseWheelRange, delta);\n }\n this.scrollBy(-delta / Scrollbar.MouseWheelRange * this.smallIncrement);\n }\n };\n Scrollbar.prototype._getScreenMousePos = function (event) {\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getScreenMousePos()\");\n return null;\n };\n Scrollbar.addDocumentMouseUpEvent = function (func) {\n document.addEventListener(\"mouseup\", func);\n };\n Scrollbar.removeDocumentMouseUpEvent = function (func) {\n document.removeEventListener(\"mouseup\", func);\n };\n Scrollbar.addDocumentMouseMoveEvent = function (func) {\n document.addEventListener(\"mousemove\", func);\n };\n Scrollbar.removeDocumentMouseMoveEvent = function (func) {\n document.removeEventListener(\"mousemove\", func);\n };\n Scrollbar.DefaultScrollbarWidth = \"15px\"; // protected\n Scrollbar.ScrollbarBackgroundFirstTimeMousedownHoldDelay = 500;\n Scrollbar.ScrollbarBackgroundMousedownHoldDelay = 50;\n Scrollbar.MouseWheelRange = 120;\n Scrollbar.className = \"scroll-bar-div\";\n Scrollbar.barClassName = \"scroll-bar-part-bar\";\n Scrollbar.arrowClassName = \"scroll-bar-part-arrow\";\n return Scrollbar;\n }());\n controls.Scrollbar = Scrollbar;\n /** Horizontal Scrollbar */\n var HorizontalScrollbar = (function (_super) {\n __extends(HorizontalScrollbar, _super);\n function HorizontalScrollbar(parentElement, layoutKind) {\n _super.call(this, parentElement, layoutKind);\n this.height = Scrollbar.DefaultScrollbarWidth;\n }\n HorizontalScrollbar.prototype._calculateButtonWidth = function () {\n return Math.min(this.actualWidth / 2, Math.max(this.actualHeight, ScrollbarButton.MIN_WIDTH));\n };\n HorizontalScrollbar.prototype._calculateButtonHeight = function () {\n return this.actualHeight;\n };\n HorizontalScrollbar.prototype._getMinButtonAngle = function () {\n return -180;\n };\n HorizontalScrollbar.prototype._getMaxButtonAngle = function () {\n return 0;\n };\n HorizontalScrollbar.prototype._setMaxButtonPosition = function () {\n controls.HTMLElementUtils.setElementLeft(this.maxButton.element, this.actualWidth - this.actualButtonWidth);\n };\n HorizontalScrollbar.prototype.refresh = function () {\n this.arrange();\n var runningSize = this.actualWidth - this.actualButtonWidth * 2 - 2;\n var barSize = this.viewSize / (this.max - this.min) * runningSize;\n if (barSize < this.MIN_BAR_SIZE) {\n runningSize -= this.MIN_BAR_SIZE - barSize;\n barSize = this.MIN_BAR_SIZE;\n }\n if (runningSize < 0) {\n runningSize = 0;\n barSize = 0;\n }\n barSize = Math.min(barSize, runningSize);\n var barPos = this.viewMin / (this.max - this.min) * runningSize;\n controls.HTMLElementUtils.setElementWidth(this.middleBar, barSize);\n controls.HTMLElementUtils.setElementHeight(this.middleBar, this.actualHeight);\n controls.HTMLElementUtils.setElementLeft(this.middleBar, this.actualButtonWidth + 1 + barPos);\n };\n HorizontalScrollbar.prototype.show = function (visible) {\n if (visible === this.visible)\n return;\n _super.prototype.show.call(this, visible);\n if (visible) {\n this.element.style.height = this.height;\n }\n else {\n controls.HTMLElementUtils.setElementHeight(this.element, 0);\n }\n };\n HorizontalScrollbar.prototype._scrollByPage = function (event) {\n var left = this.middleBar.offsetLeft;\n var right = left + this.middleBar.offsetWidth;\n var x = (event.offsetX === undefined) ? event.layerX : event.offsetX;\n if (x > right) {\n this.scrollPageDown();\n }\n else if (x < left) {\n this.scrollPageUp();\n }\n };\n HorizontalScrollbar.prototype._getRunningSize = function (net) {\n var result = this.actualWidth;\n if (net) {\n var barMinPos = this.actualButtonWidth + 1;\n result -= barMinPos * 2;\n var barSize = result * (this.viewSize / (this.max - this.min));\n if (barSize < this.MIN_BAR_SIZE)\n result -= this.MIN_BAR_SIZE - barSize;\n }\n return result;\n };\n HorizontalScrollbar.prototype._getOffsetDelta = function (event) {\n return this._getOffsetXDelta(event);\n };\n HorizontalScrollbar.prototype._getOffsetTouchDelta = function (e) {\n return this._getOffsetXTouchDelta(e);\n };\n HorizontalScrollbar.prototype._getScreenContextualLeft = function (element) {\n return element.getBoundingClientRect().left;\n };\n HorizontalScrollbar.prototype._getScreenContextualRight = function (element) {\n return element.getBoundingClientRect().right;\n };\n HorizontalScrollbar.prototype._getScreenMousePos = function (event) {\n return event.screenX;\n };\n return HorizontalScrollbar;\n }(Scrollbar));\n controls.HorizontalScrollbar = HorizontalScrollbar;\n /** Vertical Scrollbar */\n var VerticalScrollbar = (function (_super) {\n __extends(VerticalScrollbar, _super);\n function VerticalScrollbar(parentElement, layoutKind) {\n _super.call(this, parentElement, layoutKind);\n this.width = Scrollbar.DefaultScrollbarWidth;\n }\n VerticalScrollbar.prototype._calculateButtonWidth = function () {\n return this.actualWidth;\n };\n VerticalScrollbar.prototype._calculateButtonHeight = function () {\n return Math.min(this.actualHeight / 2, Math.max(this.actualWidth, ScrollbarButton.MIN_WIDTH));\n };\n VerticalScrollbar.prototype._getMinButtonAngle = function () {\n return -90;\n };\n VerticalScrollbar.prototype._getMaxButtonAngle = function () {\n return 90;\n };\n VerticalScrollbar.prototype._setMaxButtonPosition = function () {\n controls.HTMLElementUtils.setElementTop(this.maxButton.element, this.actualHeight - this.actualButtonHeight);\n };\n VerticalScrollbar.prototype.refresh = function () {\n this.arrange();\n var runningSize = this.actualHeight - this.actualButtonHeight * 2 - 2;\n var barSize = this.viewSize / (this.max - this.min) * runningSize;\n if (barSize < this.MIN_BAR_SIZE) {\n runningSize -= this.MIN_BAR_SIZE - barSize;\n barSize = this.MIN_BAR_SIZE;\n }\n if (runningSize < 0) {\n runningSize = 0;\n barSize = 0;\n }\n var barPos = this.viewMin / (this.max - this.min) * runningSize;\n controls.HTMLElementUtils.setElementWidth(this.middleBar, this.actualWidth);\n controls.HTMLElementUtils.setElementHeight(this.middleBar, barSize);\n controls.HTMLElementUtils.setElementTop(this.middleBar, this.actualButtonHeight + 1 + barPos);\n };\n VerticalScrollbar.prototype.show = function (visible) {\n if (visible === this.visible)\n return;\n _super.prototype.show.call(this, visible);\n if (visible) {\n this.element.style.width = this.width;\n }\n else {\n controls.HTMLElementUtils.setElementWidth(this.element, 0);\n }\n };\n VerticalScrollbar.prototype._scrollByPage = function (event) {\n var top = this.middleBar.offsetTop;\n var bottom = top + this.middleBar.offsetHeight;\n var y = (event.offsetY === undefined) ? event.layerY : event.offsetY;\n if (y > bottom) {\n this.scrollPageDown();\n }\n else if (y < top) {\n this.scrollPageUp();\n }\n };\n VerticalScrollbar.prototype._getRunningSize = function (net) {\n var result = this.actualHeight;\n if (net) {\n var barMinPos = this.actualButtonHeight + 1;\n result -= barMinPos * 2;\n var barSize = result * (this.viewSize / (this.max - this.min));\n if (barSize < this.MIN_BAR_SIZE)\n result -= this.MIN_BAR_SIZE - barSize;\n }\n return result;\n };\n VerticalScrollbar.prototype._getOffsetDelta = function (event) {\n return this._getOffsetYDelta(event);\n };\n VerticalScrollbar.prototype._getOffsetTouchDelta = function (e) {\n return this._getOffsetYTouchDelta(e);\n };\n VerticalScrollbar.prototype._getScreenContextualLeft = function (element) {\n return element.getBoundingClientRect().top;\n };\n VerticalScrollbar.prototype._getScreenContextualRight = function (element) {\n return element.getBoundingClientRect().bottom;\n };\n VerticalScrollbar.prototype._getScreenMousePos = function (event) {\n return event.screenY;\n };\n return VerticalScrollbar;\n }(Scrollbar));\n controls.VerticalScrollbar = VerticalScrollbar;\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var internal;\n (function (internal) {\n var UNSELECTABLE_CLASS_NAME = \"unselectable\";\n /** This class is responsible for tablix header resizing */\n var TablixResizer = (function () {\n function TablixResizer(element, handler) {\n this._element = element;\n this._handler = handler;\n this._elementMouseDownWrapper = null;\n this._elementMouseMoveWrapper = null;\n this._elementMouseOutWrapper = null;\n this._documentMouseMoveWrapper = null;\n this._documentMouseUpWrapper = null;\n this._startMousePosition = null;\n this._originalCursor = null;\n }\n TablixResizer.addDocumentMouseUpEvent = function (listener) {\n document.addEventListener(\"mouseup\", listener);\n };\n TablixResizer.removeDocumentMouseUpEvent = function (listener) {\n document.removeEventListener(\"mouseup\", listener);\n };\n TablixResizer.addDocumentMouseMoveEvent = function (listener) {\n document.addEventListener(\"mousemove\", listener);\n };\n TablixResizer.removeDocumentMouseMoveEvent = function (listener) {\n document.removeEventListener(\"mousemove\", listener);\n };\n TablixResizer.getMouseCoordinates = function (event) {\n return { x: event.pageX, y: event.pageY };\n };\n TablixResizer.getMouseCoordinateDelta = function (previous, current) {\n return { x: current.x - previous.x, y: current.y - previous.y };\n };\n TablixResizer.prototype.initialize = function () {\n var _this = this;\n this._elementMouseDownWrapper = function (e) { return _this.onElementMouseDown(e); };\n this._element.addEventListener(\"mousedown\", this._elementMouseDownWrapper);\n this._elementMouseMoveWrapper = function (e) { return _this.onElementMouseMove(e); };\n this._element.addEventListener(\"mousemove\", this._elementMouseMoveWrapper);\n this._elementMouseOutWrapper = function (e) { return _this.onElementMouseOut(e); };\n this._element.addEventListener(\"mouseout\", this._elementMouseOutWrapper);\n this._elementMouseDoubleClickOutWrapper = function (e) { return _this.onElementMouseDoubleClick(e); };\n this._element.addEventListener(\"dblclick\", this._elementMouseDoubleClickOutWrapper);\n };\n TablixResizer.prototype.uninitialize = function () {\n this._element.removeEventListener(\"mousedown\", this._elementMouseDownWrapper);\n this._elementMouseDownWrapper = null;\n this._element.removeEventListener(\"mousemove\", this._elementMouseMoveWrapper);\n this._elementMouseMoveWrapper = null;\n this._element.removeEventListener(\"mouseout\", this._elementMouseOutWrapper);\n this._elementMouseOutWrapper = null;\n this._element.removeEventListener(\"dblclick\", this._elementMouseDoubleClickOutWrapper);\n this._elementMouseDoubleClickOutWrapper = null;\n };\n Object.defineProperty(TablixResizer.prototype, \"cell\", {\n get: function () {\n // abstract\n debug.assertFail(\"PureVirtualMethod: TablixResizer.cell\");\n return null;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixResizer.prototype, \"element\", {\n get: function () {\n return this._element;\n },\n enumerable: true,\n configurable: true\n });\n // Protected\n TablixResizer.prototype._hotSpot = function (position) {\n // abstract\n debug.assertFail(\"PureVirtualMethod: TablixResizer._hotSpot\");\n return false;\n };\n TablixResizer.prototype.onElementMouseDown = function (event) {\n var _this = this;\n var position = TablixResizer.getMouseCoordinates(event);\n if (!this._hotSpot(position))\n return;\n if (\"setCapture\" in this._element) {\n this._element.setCapture();\n }\n event.cancelBubble = true;\n this._startMousePosition = position;\n this._documentMouseMoveWrapper = function (e) { return _this.onDocumentMouseMove(e); };\n TablixResizer.addDocumentMouseMoveEvent(this._documentMouseMoveWrapper);\n this._documentMouseUpWrapper = function (e) { return _this.onDocumentMouseUp(e); };\n TablixResizer.addDocumentMouseUpEvent(this._documentMouseUpWrapper);\n if (document.documentElement) {\n this._originalCursor = document.documentElement.style.cursor;\n document.documentElement.style.cursor = TablixResizer.resizeCursor;\n }\n this._handler.onStartResize(this.cell, this._startMousePosition.x, this._startMousePosition.y);\n };\n TablixResizer.prototype.onElementMouseMove = function (event) {\n if (!this._startMousePosition) {\n if (this._hotSpot(TablixResizer.getMouseCoordinates(event))) {\n if (this._originalCursor === null) {\n this._originalCursor = this._element.style.cursor;\n this._element.style.cursor = TablixResizer.resizeCursor;\n }\n }\n else {\n if (this._originalCursor !== null) {\n this._element.style.cursor = this._originalCursor;\n this._originalCursor = null;\n }\n }\n }\n };\n TablixResizer.prototype.onElementMouseOut = function (event) {\n if (!this._startMousePosition) {\n if (this._originalCursor !== null) {\n this._element.style.cursor = this._originalCursor;\n this._originalCursor = null;\n }\n }\n };\n TablixResizer.prototype.onElementMouseDoubleClick = function (event) {\n if (!this._hotSpot(TablixResizer.getMouseCoordinates(event)))\n return;\n this._handler.onReset(this.cell);\n };\n TablixResizer.prototype.onDocumentMouseMove = function (event) {\n if (!this._startMousePosition)\n return;\n var delta = TablixResizer.getMouseCoordinateDelta(this._startMousePosition, TablixResizer.getMouseCoordinates(event));\n this._handler.onResize(this.cell, delta.x, delta.y);\n // Need to prevent default to prevent mouse move from triggering other effects (VSTS 6720639)\n event.preventDefault();\n };\n TablixResizer.prototype.onDocumentMouseUp = function (event) {\n this._startMousePosition = null;\n if (\"releaseCapture\" in this._element) {\n this._element.releaseCapture();\n }\n TablixResizer.removeDocumentMouseMoveEvent(this._documentMouseMoveWrapper);\n this._documentMouseMoveWrapper = null;\n TablixResizer.removeDocumentMouseUpEvent(this._documentMouseUpWrapper);\n this._documentMouseUpWrapper = null;\n if (document.documentElement)\n document.documentElement.style.cursor = this._originalCursor;\n if (event.preventDefault)\n event.preventDefault(); // prevent other events\n this._handler.onEndResize(this.cell);\n };\n TablixResizer.resizeHandleSize = 4;\n TablixResizer.resizeCursor = \"e-resize\";\n return TablixResizer;\n }());\n internal.TablixResizer = TablixResizer;\n var TablixDomResizer = (function (_super) {\n __extends(TablixDomResizer, _super);\n function TablixDomResizer(cell, element, handler) {\n _super.call(this, element, handler);\n this._cell = cell;\n }\n Object.defineProperty(TablixDomResizer.prototype, \"cell\", {\n get: function () {\n return this._cell;\n },\n enumerable: true,\n configurable: true\n });\n // Protected\n TablixDomResizer.prototype._hotSpot = function (position) {\n return position.x >= this.element.getBoundingClientRect().right - TablixResizer.resizeHandleSize;\n };\n return TablixDomResizer;\n }(TablixResizer));\n internal.TablixDomResizer = TablixDomResizer;\n var TablixCellPresenter = (function () {\n function TablixCellPresenter(fitProportionally, layoutKind) {\n // Table cell will be created once needed\n this._tableCell = null;\n // Content element\n this._contentElement = internal.TablixUtils.createDiv();\n // Content Host\n this._contentHost = internal.TablixUtils.createDiv();\n this.layoutKind = layoutKind;\n this._contentElement.appendChild(this._contentHost);\n this._resizer = null;\n }\n TablixCellPresenter.prototype.initialize = function (owner) {\n this._owner = owner;\n };\n Object.defineProperty(TablixCellPresenter.prototype, \"owner\", {\n get: function () {\n return this._owner;\n },\n enumerable: true,\n configurable: true\n });\n TablixCellPresenter.prototype.registerTableCell = function (tableCell) {\n this._tableCell = tableCell;\n tableCell.appendChild(this._contentElement);\n };\n Object.defineProperty(TablixCellPresenter.prototype, \"tableCell\", {\n get: function () {\n return this._tableCell;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixCellPresenter.prototype, \"contentElement\", {\n /**\n * Outer DIV\n */\n get: function () {\n return this._contentElement;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixCellPresenter.prototype, \"contentHost\", {\n /**\n * Inner DIV\n */\n get: function () {\n return this._contentHost;\n },\n enumerable: true,\n configurable: true\n });\n TablixCellPresenter.prototype.registerClickHandler = function (handler) {\n this._contentElement.onclick = handler;\n };\n TablixCellPresenter.prototype.unregisterClickHandler = function () {\n this._contentElement.onclick = null;\n };\n TablixCellPresenter.prototype.onContainerWidthChanged = function (value) {\n controls.HTMLElementUtils.setElementWidth(this._contentElement, value);\n };\n TablixCellPresenter.prototype.onContinerHeightChanged = function (height) {\n controls.HTMLElementUtils.setElementHeight(this._contentElement, height);\n };\n TablixCellPresenter.prototype.onColumnSpanChanged = function (value) {\n this._tableCell.colSpan = value;\n };\n TablixCellPresenter.prototype.onRowSpanChanged = function (value) {\n this._tableCell.rowSpan = value;\n };\n TablixCellPresenter.prototype.onTextAlignChanged = function (value) {\n this._tableCell.style.textAlign = value;\n };\n TablixCellPresenter.prototype.onClear = function () {\n this._contentHost.className = \"\";\n this._tableCell.className = \"\";\n };\n TablixCellPresenter.prototype.onHorizontalScroll = function (width, offset) {\n controls.HTMLElementUtils.setElementLeft(this._contentHost, offset);\n controls.HTMLElementUtils.setElementWidth(this._contentHost, width);\n };\n TablixCellPresenter.prototype.onVerticalScroll = function (height, offset) {\n controls.HTMLElementUtils.setElementTop(this._contentHost, offset);\n controls.HTMLElementUtils.setElementHeight(this._contentHost, height);\n };\n TablixCellPresenter.prototype.onInitializeScrolling = function () {\n controls.HTMLElementUtils.setElementLeft(this._contentHost, 0);\n controls.HTMLElementUtils.setElementTop(this._contentHost, 0);\n controls.HTMLElementUtils.setElementWidth(this._contentHost, -1);\n controls.HTMLElementUtils.setElementHeight(this._contentHost, -1);\n };\n TablixCellPresenter.prototype.enableHorizontalResize = function (enable, handler) {\n if (enable === (this._resizer !== null))\n return;\n if (enable) {\n this._resizer = new TablixDomResizer(this._owner, this._tableCell, handler);\n this._resizer.initialize();\n }\n else {\n this._resizer.uninitialize();\n this._resizer = null;\n }\n };\n /**\n * In order to allow dragging of the tableCell we need to\n * disable dragging of the container of the cell in IE.\n */\n TablixCellPresenter.prototype.disableDragResize = function () {\n this._tableCell.setAttribute(TablixCellPresenter._dragResizeDisabledAttributeName, \"true\");\n };\n // Attribute used to disable dragging in order to have cell resizing work.\n TablixCellPresenter._dragResizeDisabledAttributeName = \"drag-resize-disabled\";\n return TablixCellPresenter;\n }());\n internal.TablixCellPresenter = TablixCellPresenter;\n var TablixRowPresenter = (function () {\n function TablixRowPresenter(fitProportionally) {\n // Table row will be created once needed\n this._tableRow = null;\n this._fitProportionally = fitProportionally;\n }\n TablixRowPresenter.prototype.initialize = function (row) {\n this._row = row;\n };\n TablixRowPresenter.prototype.createCellPresenter = function (layoutKind) {\n return new TablixCellPresenter(this._fitProportionally, layoutKind);\n };\n TablixRowPresenter.prototype.registerRow = function (tableRow) {\n this._tableRow = tableRow;\n };\n TablixRowPresenter.prototype.onAppendCell = function (cell) {\n var presenter = cell._presenter;\n if (presenter.tableCell === null) {\n // For performance reason we use InsertCell() to create new table cells instead of AppendChild()\n // We use -1 to insert at the end (that's the cross-browser way of doing it)\n var tableCell = this._tableRow.insertCell(-1);\n presenter.registerTableCell(tableCell);\n }\n else {\n this._tableRow.appendChild(presenter.tableCell);\n }\n };\n TablixRowPresenter.prototype.onInsertCellBefore = function (cell, refCell) {\n debug.assertValue(refCell._presenter.tableCell, 'refTableCell');\n var presenter = cell._presenter;\n if (presenter.tableCell === null) {\n // For performance reasons we use InsertCell() to create new table cells instead of AppendChild()\n var tableCell = this._tableRow.insertCell(Math.max(0, refCell._presenter.tableCell.cellIndex - 1));\n presenter.registerTableCell(tableCell);\n }\n else {\n this._tableRow.insertBefore(cell._presenter.tableCell, refCell._presenter.tableCell);\n }\n };\n TablixRowPresenter.prototype.onRemoveCell = function (cell) {\n this._tableRow.removeChild(cell._presenter.tableCell);\n };\n TablixRowPresenter.prototype.getHeight = function () {\n return this.getCellHeight(this._row.getTablixCell());\n };\n TablixRowPresenter.prototype.getCellHeight = function (cell) {\n debug.assertFail(\"PureVirtualMethod: TablixRowPresenter.getCellHeight\");\n return -1;\n };\n TablixRowPresenter.prototype.getCellContentHeight = function (cell) {\n debug.assertFail(\"PureVirtualMethod: TablixRowPresenter.getCellHeight\");\n return -1;\n };\n Object.defineProperty(TablixRowPresenter.prototype, \"tableRow\", {\n get: function () {\n return this._tableRow;\n },\n enumerable: true,\n configurable: true\n });\n return TablixRowPresenter;\n }());\n internal.TablixRowPresenter = TablixRowPresenter;\n var DashboardRowPresenter = (function (_super) {\n __extends(DashboardRowPresenter, _super);\n function DashboardRowPresenter(gridPresenter, fitProportionally) {\n _super.call(this, fitProportionally);\n this._gridPresenter = gridPresenter;\n }\n DashboardRowPresenter.prototype.getCellHeight = function (cell) {\n return cell.containerHeight;\n };\n DashboardRowPresenter.prototype.getCellContentHeight = function (cell) {\n return cell.contentHeight;\n };\n return DashboardRowPresenter;\n }(TablixRowPresenter));\n internal.DashboardRowPresenter = DashboardRowPresenter;\n var CanvasRowPresenter = (function (_super) {\n __extends(CanvasRowPresenter, _super);\n function CanvasRowPresenter() {\n _super.apply(this, arguments);\n }\n CanvasRowPresenter.prototype.getCellHeight = function (cell) {\n return cell.containerHeight;\n };\n CanvasRowPresenter.prototype.getCellContentHeight = function (cell) {\n return cell.contentHeight;\n };\n return CanvasRowPresenter;\n }(TablixRowPresenter));\n internal.CanvasRowPresenter = CanvasRowPresenter;\n var TablixColumnPresenter = (function () {\n function TablixColumnPresenter() {\n }\n TablixColumnPresenter.prototype.initialize = function (column) {\n this._column = column;\n };\n TablixColumnPresenter.prototype.getWidth = function () {\n return this.getCellWidth(this._column.getTablixCell());\n };\n TablixColumnPresenter.prototype.getCellWidth = function (cell) {\n debug.assertFail(\"PureVirtualMethod: TablixColumnPresenter.getCellWidth\");\n return -1;\n };\n TablixColumnPresenter.prototype.getCellContentWidth = function (cell) {\n debug.assertFail(\"PureVirtualMethod: TablixColumnPresenter.getCellContentWidth\");\n return -1;\n };\n return TablixColumnPresenter;\n }());\n internal.TablixColumnPresenter = TablixColumnPresenter;\n var DashboardColumnPresenter = (function (_super) {\n __extends(DashboardColumnPresenter, _super);\n function DashboardColumnPresenter(gridPresenter) {\n _super.call(this);\n this._gridPresenter = gridPresenter;\n }\n DashboardColumnPresenter.prototype.getCellWidth = function (cell) {\n return this._gridPresenter.sizeComputationManager.cellWidth;\n };\n DashboardColumnPresenter.prototype.getCellContentWidth = function (cell) {\n return this._gridPresenter.sizeComputationManager.contentWidth;\n };\n return DashboardColumnPresenter;\n }(TablixColumnPresenter));\n internal.DashboardColumnPresenter = DashboardColumnPresenter;\n var CanvasColumnPresenter = (function (_super) {\n __extends(CanvasColumnPresenter, _super);\n function CanvasColumnPresenter(gridPresenter, index) {\n _super.call(this);\n this._gridPresenter = gridPresenter;\n this._columnIndex = index;\n }\n CanvasColumnPresenter.prototype.getCellWidth = function (cell) {\n var persistedWidth = this._gridPresenter.getPersistedCellWidth(this._columnIndex);\n // Because persistedWidth could be 0 check specifically for null or undefined \n if (_.isNumber(persistedWidth))\n return persistedWidth;\n if (!cell._presenter)\n return 0;\n return controls.HTMLElementUtils.getElementWidth(cell._presenter.tableCell);\n };\n CanvasColumnPresenter.prototype.getCellContentWidth = function (cell) {\n var persistedWidth = this._gridPresenter.getPersistedCellWidth(this._columnIndex);\n // Because persistedWidth could be 0 check specifically for null or undefined \n if (_.isNumber(persistedWidth))\n return persistedWidth;\n if (!cell._presenter)\n return 0;\n var requiredWidth = controls.HTMLElementUtils.getElementWidth(cell._presenter.contentElement);\n if (requiredWidth > 0 && cell.colSpan === 1)\n requiredWidth += 1; // Adding 1px because offsetWidth returns floored number, may risk getting ellipsis\n return requiredWidth;\n };\n return CanvasColumnPresenter;\n }(TablixColumnPresenter));\n internal.CanvasColumnPresenter = CanvasColumnPresenter;\n var TablixGridPresenter = (function () {\n function TablixGridPresenter(columnWidthManager) {\n // Main Table\n this._table = internal.TablixUtils.createTable();\n this._table.className = UNSELECTABLE_CLASS_NAME;\n // Footer Table\n this._footerTable = internal.TablixUtils.createTable();\n this._footerTable.className = UNSELECTABLE_CLASS_NAME;\n // ColumnWidthManager\n this._columnWidthManager = columnWidthManager;\n }\n TablixGridPresenter.prototype.initialize = function (owner, gridHost, footerHost, control) {\n this._owner = owner;\n gridHost.appendChild(this._table);\n footerHost.appendChild(this._footerTable);\n };\n TablixGridPresenter.prototype.getWidth = function () {\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.getWidth\");\n return -1;\n };\n TablixGridPresenter.prototype.getHeight = function () {\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.getHeight\");\n return -1;\n };\n TablixGridPresenter.prototype.getScreenToCssRatioX = function () {\n return 1;\n };\n TablixGridPresenter.prototype.getScreenToCssRatioY = function () {\n return 1;\n };\n TablixGridPresenter.prototype.createRowPresenter = function () {\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.createRowPresenter\");\n return null;\n };\n TablixGridPresenter.prototype.createColumnPresenter = function (index) {\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.createColumnPresenter\");\n return null;\n };\n TablixGridPresenter.prototype.onAppendRow = function (row) {\n var presenter = row.presenter;\n if (presenter.tableRow === null) {\n // For performance reason we use InsertRow() to create new table cells instead of AppendChild()\n // We use -1 to insert at the end (that's the cross-browser way of doing it)\n var tableRow = this._table.insertRow(-1);\n presenter.registerRow(tableRow);\n }\n else {\n this._table.tBodies[0].appendChild(row.presenter.tableRow);\n }\n };\n TablixGridPresenter.prototype.onInsertRowBefore = function (row, refRow) {\n debug.assertValue(refRow.presenter.tableRow, 'refTableRow');\n var presenter = row.presenter;\n if (presenter.tableRow === null) {\n // For performance reason we use InsertRow() to create new table cells instead of AppendChild()\n var tableRow = this._table.insertRow(Math.max(0, refRow.presenter.tableRow.rowIndex - 1));\n presenter.registerRow(tableRow);\n }\n else {\n this._table.tBodies[0].insertBefore(row.presenter.tableRow, refRow.presenter.tableRow);\n }\n };\n TablixGridPresenter.prototype.onRemoveRow = function (row) {\n this._table.tBodies[0].removeChild(row.presenter.tableRow);\n };\n TablixGridPresenter.prototype.onAddFooterRow = function (row) {\n var presenter = row.presenter;\n if (presenter.tableRow === null) {\n // For performance reason we use InsertRow() to create new table cells instead of AppendChild()\n // We use -1 to insert at the end (that's the cross-browser way of doing it)\n var tableRow = this._footerTable.insertRow(-1);\n presenter.registerRow(tableRow);\n }\n else {\n this._footerTable.tBodies[0].appendChild(row.presenter.tableRow);\n }\n };\n TablixGridPresenter.prototype.onClear = function () {\n controls.HTMLElementUtils.clearChildren(this._table);\n controls.HTMLElementUtils.clearChildren(this._footerTable);\n };\n TablixGridPresenter.prototype.onFillColumnsProportionallyChanged = function (value) {\n if (value) {\n this._table.style.width = \"100%\";\n this._footerTable.style.width = \"100%\";\n }\n else {\n this._table.style.width = \"auto\";\n this._footerTable.style.width = \"auto\";\n }\n };\n TablixGridPresenter.prototype.invokeColumnResizeEndCallback = function (columnIndex, width) {\n if (this._columnWidthManager)\n this._columnWidthManager.onColumnWidthChanged(columnIndex, width);\n };\n TablixGridPresenter.prototype.getPersistedCellWidth = function (columnIndex) {\n if (this._columnWidthManager)\n return this._columnWidthManager.getPersistedColumnWidth(columnIndex);\n };\n return TablixGridPresenter;\n }());\n internal.TablixGridPresenter = TablixGridPresenter;\n var DashboardTablixGridPresenter = (function (_super) {\n __extends(DashboardTablixGridPresenter, _super);\n function DashboardTablixGridPresenter(sizeComputationManager) {\n _super.call(this);\n this._sizeComputationManager = sizeComputationManager;\n }\n DashboardTablixGridPresenter.prototype.createRowPresenter = function () {\n return new DashboardRowPresenter(this, this._owner.fillColumnsProportionally);\n };\n DashboardTablixGridPresenter.prototype.createColumnPresenter = function (index) {\n return new DashboardColumnPresenter(this);\n };\n Object.defineProperty(DashboardTablixGridPresenter.prototype, \"sizeComputationManager\", {\n get: function () {\n return this._sizeComputationManager;\n },\n enumerable: true,\n configurable: true\n });\n DashboardTablixGridPresenter.prototype.getWidth = function () {\n return this._sizeComputationManager.gridWidth;\n };\n DashboardTablixGridPresenter.prototype.getHeight = function () {\n return this._sizeComputationManager.gridHeight;\n };\n return DashboardTablixGridPresenter;\n }(TablixGridPresenter));\n internal.DashboardTablixGridPresenter = DashboardTablixGridPresenter;\n var CanvasTablixGridPresenter = (function (_super) {\n __extends(CanvasTablixGridPresenter, _super);\n function CanvasTablixGridPresenter(columnWidthManager) {\n _super.call(this, columnWidthManager);\n }\n CanvasTablixGridPresenter.prototype.createRowPresenter = function () {\n return new CanvasRowPresenter(this._owner.fillColumnsProportionally);\n };\n CanvasTablixGridPresenter.prototype.createColumnPresenter = function (index) {\n return new CanvasColumnPresenter(this, index);\n };\n CanvasTablixGridPresenter.prototype.getWidth = function () {\n return controls.HTMLElementUtils.getElementWidth(this._table);\n };\n CanvasTablixGridPresenter.prototype.getHeight = function () {\n return controls.HTMLElementUtils.getElementHeight(this._table);\n };\n return CanvasTablixGridPresenter;\n }(TablixGridPresenter));\n internal.CanvasTablixGridPresenter = CanvasTablixGridPresenter;\n })(internal = controls.internal || (controls.internal = {}));\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var internal;\n (function (internal) {\n /**\n * Base class for Tablix realization manager.\n */\n var TablixDimensionRealizationManager = (function () {\n function TablixDimensionRealizationManager(binder) {\n this._binder = binder;\n this._adjustmentFactor = 1;\n }\n TablixDimensionRealizationManager.prototype._getOwner = function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.getOwner\");\n return null;\n };\n Object.defineProperty(TablixDimensionRealizationManager.prototype, \"binder\", {\n get: function () {\n return this._binder;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixDimensionRealizationManager.prototype, \"adjustmentFactor\", {\n get: function () {\n return this._adjustmentFactor;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixDimensionRealizationManager.prototype, \"itemsToRealizeCount\", {\n get: function () {\n return this._itemsToRealizeCount;\n },\n set: function (count) {\n this._itemsToRealizeCount = count;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixDimensionRealizationManager.prototype, \"itemsEstimatedContextualWidth\", {\n get: function () {\n return this._itemsEstimatedContextualWidth;\n },\n set: function (contextualWidth) {\n this._itemsEstimatedContextualWidth = contextualWidth;\n },\n enumerable: true,\n configurable: true\n });\n TablixDimensionRealizationManager.prototype.onStartRenderingIteration = function () {\n var owner = this._getOwner();\n if (owner.measureEnabled && !owner.done) {\n this._getEstimatedItemsToRealizeCount();\n }\n this._realizedLeavesCount = 0;\n };\n TablixDimensionRealizationManager.prototype.onEndRenderingIteration = function (gridContextualWidth, filled) {\n if (!filled && !this._getOwner().allItemsRealized)\n this._adjustmentFactor *= this._getSizeAdjustment(gridContextualWidth);\n };\n TablixDimensionRealizationManager.prototype.onEndRenderingSession = function () {\n this._adjustmentFactor = 1;\n };\n TablixDimensionRealizationManager.prototype.onCornerCellRealized = function (item, cell) {\n };\n TablixDimensionRealizationManager.prototype.onHeaderRealized = function (item, cell, leaf) {\n if (leaf) {\n this._realizedLeavesCount++;\n }\n };\n Object.defineProperty(TablixDimensionRealizationManager.prototype, \"needsToRealize\", {\n get: function () {\n return this._realizedLeavesCount < this._itemsToRealizeCount;\n },\n enumerable: true,\n configurable: true\n });\n TablixDimensionRealizationManager.prototype._getEstimatedItemsToRealizeCount = function () {\n debug.assertFail(\"PureVirtualMethod: TablixDimensionRealizationManager._calculateItemsToRealize\");\n };\n TablixDimensionRealizationManager.prototype._getSizeAdjustment = function (gridContextualWidth) {\n debug.assertFail(\"PureVirtualMethod: TablixDimensionRealizationManager._getSizeAdjustment\");\n return 1;\n };\n return TablixDimensionRealizationManager;\n }());\n internal.TablixDimensionRealizationManager = TablixDimensionRealizationManager;\n /**\n * DOM implementation for Row Tablix realization manager.\n */\n var RowRealizationManager = (function (_super) {\n __extends(RowRealizationManager, _super);\n function RowRealizationManager() {\n _super.apply(this, arguments);\n }\n Object.defineProperty(RowRealizationManager.prototype, \"owner\", {\n set: function (owner) {\n this._owner = owner;\n },\n enumerable: true,\n configurable: true\n });\n RowRealizationManager.prototype._getOwner = function () {\n return this._owner;\n };\n RowRealizationManager.prototype._getEstimatedItemsToRealizeCount = function () {\n this.estimateRowsToRealizeCount();\n };\n RowRealizationManager.prototype.estimateRowsToRealizeCount = function () {\n debug.assertValue(this._owner, '_owner');\n if (!this._owner.dimension.model) {\n this.itemsToRealizeCount = 0;\n return;\n }\n if (this._owner.alignToEnd)\n this.itemsToRealizeCount = this._owner.dimension.getItemsCount() - this._owner.dimension.getIntegerScrollOffset() + 1;\n else\n this.itemsToRealizeCount = Math.ceil((this._owner.contextualWidthToFill / (this._owner.owner.getEstimatedRowHeight() * this.adjustmentFactor)) + this._owner.dimension.getFractionScrollOffset()) - this._owner.otherLayoutManager.dimension.getDepth() + 1;\n };\n RowRealizationManager.prototype.getEstimatedRowHierarchyWidth = function () {\n if (!this._owner.dimension.model || this._owner.dimension.getItemsCount() === 0)\n return 0;\n var levels = new RowWidths();\n this.updateRowHiearchyEstimatedWidth(this._owner.dimension.model, this._owner.dimension._hierarchyNavigator.getIndex(this._owner.dimension.getFirstVisibleItem(0)), levels);\n var levelsArray = levels.items;\n var levelCount = levelsArray.length;\n var width = 0;\n for (var i = 0; i < levelCount; i++) {\n var level = levelsArray[i];\n if (level.maxNonLeafWidth !== 0)\n width += level.maxNonLeafWidth;\n else\n width += level.maxLeafWidth;\n }\n return width;\n };\n RowRealizationManager.prototype.updateRowHiearchyEstimatedWidth = function (items, firstVisibleIndex, levels) {\n var hierarchyNavigator = this._owner.owner.owner.hierarchyNavigator;\n var binder = this.binder;\n var length = hierarchyNavigator.getCount(items);\n for (var i = firstVisibleIndex; i < length; i++) {\n if (levels.leafCount === this.itemsToRealizeCount)\n return;\n var item = hierarchyNavigator.getAt(items, i);\n var label = binder.getHeaderLabel(item);\n var itemWidth = this._owner.getEstimatedHeaderWidth(label, firstVisibleIndex);\n var isLeaf = hierarchyNavigator.isLeaf(item);\n var l = hierarchyNavigator.getLevel(item);\n var level = levels.items[l];\n if (!level) {\n level = new RowWidth();\n levels.items[l] = level;\n }\n if (isLeaf) {\n level.maxLeafWidth = Math.max(level.maxLeafWidth, itemWidth);\n levels.leafCount = levels.leafCount + 1;\n }\n else {\n level.maxNonLeafWidth = Math.max(level.maxNonLeafWidth, itemWidth);\n this.updateRowHiearchyEstimatedWidth(hierarchyNavigator.getChildren(item), this._owner.dimension.getFirstVisibleChildIndex(item), levels);\n }\n }\n };\n RowRealizationManager.prototype._getSizeAdjustment = function (gridContextualWidth) {\n return gridContextualWidth / ((this._owner.getRealizedItemsCount() - this._owner.dimension.getFractionScrollOffset()) * this._owner.owner.getEstimatedRowHeight());\n };\n return RowRealizationManager;\n }(TablixDimensionRealizationManager));\n internal.RowRealizationManager = RowRealizationManager;\n /**\n * DOM implementation for Column Tablix realization manager.\n */\n var ColumnRealizationManager = (function (_super) {\n __extends(ColumnRealizationManager, _super);\n function ColumnRealizationManager() {\n _super.apply(this, arguments);\n }\n Object.defineProperty(ColumnRealizationManager.prototype, \"owner\", {\n set: function (owner) {\n this._owner = owner;\n },\n enumerable: true,\n configurable: true\n });\n ColumnRealizationManager.prototype._getOwner = function () {\n return this._owner;\n };\n ColumnRealizationManager.prototype._getEstimatedItemsToRealizeCount = function () {\n this.estimateColumnsToRealizeCount(this.getEstimatedRowHierarchyWidth());\n };\n Object.defineProperty(ColumnRealizationManager.prototype, \"rowRealizationManager\", {\n get: function () {\n return this._owner.otherLayoutManager.realizationManager;\n },\n enumerable: true,\n configurable: true\n });\n ColumnRealizationManager.prototype.getEstimatedRowHierarchyWidth = function () {\n if (this._owner.otherLayoutManager.done)\n return this._owner.getOtherHierarchyContextualHeight();\n return this.rowRealizationManager.getEstimatedRowHierarchyWidth() * this.adjustmentFactor;\n };\n ColumnRealizationManager.prototype.estimateColumnsToRealizeCount = function (rowHierarchyWidth) {\n var widthToFill = this._owner.contextualWidthToFill - rowHierarchyWidth;\n if (!this._owner.dimension.model || powerbi.Double.lessOrEqualWithPrecision(widthToFill, 0, internal.DimensionLayoutManager._pixelPrecision)) {\n this.itemsToRealizeCount = 0;\n return;\n }\n var binder = this.binder;\n var hierarchyNavigator = this._owner.owner.owner.hierarchyNavigator;\n var startColumnIndex = this._owner.dimension.getIntegerScrollOffset();\n var endColumnIndex = this._owner.dimension.getItemsCount();\n var columnCount = endColumnIndex - startColumnIndex;\n var startRowIndex = this._owner.otherLayoutManager.dimension.getIntegerScrollOffset();\n var endRowIndex = this._owner.otherLayoutManager.dimension.getItemsCount();\n this.itemsEstimatedContextualWidth = 0;\n if (this._owner.alignToEnd) {\n this.itemsToRealizeCount = columnCount;\n return;\n }\n for (var i = startColumnIndex; i < endColumnIndex; i++) {\n if (powerbi.Double.greaterOrEqualWithPrecision(this.itemsEstimatedContextualWidth, widthToFill, internal.DimensionLayoutManager._pixelPrecision)) {\n this.itemsToRealizeCount = i - startColumnIndex;\n return;\n }\n var maxWidth = 0;\n var visibleSizeRatio = void 0;\n if (i === startColumnIndex) {\n visibleSizeRatio = this._owner.getVisibleSizeRatio();\n }\n else {\n visibleSizeRatio = 1;\n }\n var columnMember = hierarchyNavigator.getLeafAt(this._owner.dimension.model, i);\n var label = binder.getHeaderLabel(columnMember);\n maxWidth = Math.max(maxWidth, this._owner.getEstimatedHeaderWidth(label, i));\n for (var j = startRowIndex; j < endRowIndex; j++) {\n var intersection = hierarchyNavigator.getIntersection(hierarchyNavigator.getLeafAt(this._owner.otherLayoutManager.dimension.model, j), columnMember);\n label = binder.getCellContent(intersection);\n maxWidth = Math.max(maxWidth, this._owner.getEstimatedBodyCellWidth(label));\n }\n this.itemsEstimatedContextualWidth += maxWidth * visibleSizeRatio * this.adjustmentFactor;\n }\n this.itemsToRealizeCount = columnCount;\n };\n ColumnRealizationManager.prototype._getSizeAdjustment = function (gridContextualWidth) {\n return gridContextualWidth / (this.getEstimatedRowHierarchyWidth() + this.itemsEstimatedContextualWidth);\n };\n return ColumnRealizationManager;\n }(TablixDimensionRealizationManager));\n internal.ColumnRealizationManager = ColumnRealizationManager;\n var RowWidths = (function () {\n function RowWidths() {\n this.items = [];\n this.leafCount = 0;\n }\n return RowWidths;\n }());\n internal.RowWidths = RowWidths;\n var RowWidth = (function () {\n function RowWidth() {\n this.maxLeafWidth = 0;\n this.maxNonLeafWidth = 0;\n }\n return RowWidth;\n }());\n internal.RowWidth = RowWidth;\n })(internal = controls.internal || (controls.internal = {}));\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var internal;\n (function (internal) {\n var TablixCell = (function () {\n function TablixCell(presenter, extension, row) {\n this._scrollable = false;\n this._presenter = presenter;\n this.extension = extension;\n this._presenter.initialize(this);\n this._row = row;\n this.item = null;\n this.type = null;\n this._horizontalOffset = 0;\n this._verticalOffset = 0;\n this._colSpan = 1;\n this._rowSpan = 1;\n this._containerWidth = -1;\n this._containerHeight = -1;\n this.contentHeight = this.contentWidth = 0;\n this.position = new internal.TablixUtils.CellPosition();\n }\n TablixCell.prototype.unfixRowHeight = function () {\n this._row.unfixSize();\n };\n Object.defineProperty(TablixCell.prototype, \"colSpan\", {\n get: function () {\n return this._colSpan;\n },\n set: function (value) {\n if (this._colSpan !== value) {\n this._presenter.onColumnSpanChanged(value);\n this._colSpan = value;\n }\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixCell.prototype, \"rowSpan\", {\n get: function () {\n return this._rowSpan;\n },\n set: function (value) {\n if (this._rowSpan !== value) {\n this._presenter.onRowSpanChanged(value);\n this._rowSpan = value;\n this._row.unfixSize();\n }\n },\n enumerable: true,\n configurable: true\n });\n TablixCell.prototype.getCellSpanningHeight = function () {\n return this._row.getCellSpanningHeight(this);\n };\n Object.defineProperty(TablixCell.prototype, \"textAlign\", {\n get: function () {\n return this._textAlign;\n },\n set: function (value) {\n if (value !== this._textAlign) {\n this._presenter.onTextAlignChanged(value);\n this._textAlign = value;\n }\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixCell.prototype, \"horizontalOffset\", {\n get: function () {\n return this._horizontalOffset;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixCell.prototype, \"verticalOffset\", {\n get: function () {\n return this._verticalOffset;\n },\n enumerable: true,\n configurable: true\n });\n TablixCell.prototype.isScrollable = function () {\n return this._scrollable;\n };\n TablixCell.prototype.clear = function () {\n if (this.isScrollable()) {\n this.initializeScrolling();\n }\n this._presenter.onClear();\n this.setContainerWidth(-1);\n this.setContainerHeight(-1);\n this.contentHeight = this.contentWidth = 0;\n };\n TablixCell.prototype.initializeScrolling = function () {\n this._presenter.onInitializeScrolling();\n this._horizontalOffset = 0;\n this._verticalOffset = 0;\n if (this.colSpan === 1)\n this.setContainerWidth(-1);\n if (this.rowSpan === 1)\n this.setContainerHeight(-1);\n };\n TablixCell.prototype.prepare = function (scrollable) {\n if (this.isScrollable())\n this.initializeScrolling();\n this._scrollable = scrollable;\n };\n TablixCell.prototype.scrollVertically = function (height, offset) {\n // Ceiling the offset because setting a fraction Width on the TD will ceil it\n // We need to let the TD and the OuterDiv to align in order for Borders to touch\n var offsetInPixels = Math.ceil(-height * offset);\n this._verticalOffset = offsetInPixels;\n if (this.isScrollable()) {\n this._presenter.onVerticalScroll(height, offsetInPixels);\n this.setContainerHeight(height + offsetInPixels);\n }\n else {\n this.setContainerHeight(this._row.getCellSpanningHeight(this) + offsetInPixels);\n }\n };\n TablixCell.prototype.scrollHorizontally = function (width, offset) {\n if (!this.isScrollable()) {\n return;\n }\n // Ceiling the offset because setting a fraction Width on the TD will ceil it\n // We need to let the TD and the OuterDiv to align in order for Borders to touch\n var offsetInPixels = Math.ceil(-width * offset);\n this._horizontalOffset = offsetInPixels;\n this._presenter.onHorizontalScroll(width, offsetInPixels);\n this.setContainerWidth(width + offsetInPixels);\n };\n TablixCell.prototype.setContainerWidth = function (value) {\n if (value === this._containerWidth)\n return;\n this._containerWidth = value;\n this._presenter.onContainerWidthChanged(value);\n };\n Object.defineProperty(TablixCell.prototype, \"containerWidth\", {\n get: function () {\n return this._containerWidth;\n },\n enumerable: true,\n configurable: true\n });\n TablixCell.prototype.setContainerHeight = function (value) {\n if (value < 0)\n value = -1;\n if (value === this._containerHeight)\n return;\n this._containerHeight = value;\n this._presenter.onContinerHeightChanged(value);\n };\n Object.defineProperty(TablixCell.prototype, \"containerHeight\", {\n get: function () {\n return this._containerHeight;\n },\n enumerable: true,\n configurable: true\n });\n TablixCell.prototype.applyStyle = function (style) {\n if (style) {\n style.applyStyle(this);\n this.contentHeight += style.getExtraBottom() + style.getExtraTop();\n this.contentWidth += style.getExtraLeft() + style.getExtraRight();\n }\n };\n TablixCell.prototype.enableHorizontalResize = function (enable, handler) {\n this._presenter.enableHorizontalResize(enable, handler);\n };\n return TablixCell;\n }());\n internal.TablixCell = TablixCell;\n var TablixColumn = (function () {\n function TablixColumn(presenter, columnIndex) {\n this._presenter = presenter;\n this._presenter.initialize(this);\n this._containerWidth = -1;\n this._width = -1;\n this._sizeFixed = false;\n this._aligningWidth = -1;\n this._fixedToAligningWidth = false;\n this._items = [];\n this._itemType = null;\n this._footerCell = null;\n this._columnIndex = columnIndex;\n }\n TablixColumn.prototype.initialize = function (owner) {\n this._owner = owner;\n this._realizedRowHeaders = [];\n this._realizedColumnHeaders = [];\n this._realizedCornerCells = [];\n this._realizedBodyCells = [];\n };\n Object.defineProperty(TablixColumn.prototype, \"owner\", {\n get: function () {\n return this._owner;\n },\n enumerable: true,\n configurable: true\n });\n TablixColumn.prototype.getType = function () {\n if (this._realizedCornerCells.length > 0)\n return 0 /* CornerCell */;\n return 2 /* ColumnHeader */;\n };\n TablixColumn.prototype.getColumnHeadersOrCorners = function () {\n if (this._realizedCornerCells.length > 0)\n return this._realizedCornerCells;\n return this._realizedColumnHeaders;\n };\n TablixColumn.prototype.columnHeadersOrCornersEqual = function (newType, headers, hierarchyNavigator) {\n if (this._items.length !== headers.length)\n return false;\n var count = this._items.length;\n for (var i = 0; i < count; i++) {\n if (!this.columnHeaderOrCornerEquals(this._itemType, this._items[i], newType, headers[i].item, hierarchyNavigator))\n return false;\n }\n return true;\n };\n Object.defineProperty(TablixColumn.prototype, \"itemType\", {\n get: function () {\n return this._itemType;\n },\n enumerable: true,\n configurable: true\n });\n TablixColumn.prototype.getLeafItem = function () {\n if (this._items.length === 0)\n return null;\n return this._items[this._items.length - 1];\n };\n TablixColumn.prototype.columnHeaderOrCornerEquals = function (type1, item1, type2, item2, hierarchyNavigator) {\n if (type1 !== type2)\n return false;\n if (type1 === 0 /* CornerCell */) {\n if (!hierarchyNavigator.cornerCellItemEquals(item1, item2))\n return false;\n }\n else {\n if (!hierarchyNavigator.headerItemEquals(item1, item2))\n return false;\n }\n return true;\n };\n TablixColumn.prototype.OnLeafRealized = function (hierarchyNavigator) {\n // if the headers/corner have changed we should clear the column size to accomodate for the new content\n var type = this.getType();\n var columnHeadersOrCorners = this.getColumnHeadersOrCorners();\n if (this.columnHeadersOrCornersEqual(type, columnHeadersOrCorners, hierarchyNavigator)) {\n this.clearSpanningCellsWidth(this._realizedColumnHeaders);\n }\n else {\n var count = columnHeadersOrCorners.length;\n this._items = [];\n for (var i = 0; i < count; i++) {\n this._items.push(columnHeadersOrCorners[i].item);\n }\n this._itemType = type;\n this.clearSize();\n }\n };\n TablixColumn.prototype.clearSpanningCellsWidth = function (cells) {\n for (var i = 0; i < cells.length; i++) {\n var cell = cells[i];\n if (cell.colSpan > 1) {\n cell.setContainerWidth(-1);\n }\n }\n };\n TablixColumn.prototype.addCornerCell = function (cell) {\n cell._column = this;\n this._realizedCornerCells.push(cell);\n cell.setContainerWidth(this._containerWidth);\n };\n TablixColumn.prototype.addRowHeader = function (cell) {\n cell._column = this;\n this._realizedRowHeaders.push(cell);\n cell.setContainerWidth(this._containerWidth);\n };\n TablixColumn.prototype.addColumnHeader = function (cell, isLeaf) {\n cell._column = this;\n this._realizedColumnHeaders.push(cell);\n if (isLeaf) {\n cell.setContainerWidth(this._containerWidth);\n }\n };\n TablixColumn.prototype.addBodyCell = function (cell) {\n cell._column = this;\n this._realizedBodyCells.push(cell);\n cell.setContainerWidth(this._containerWidth);\n };\n Object.defineProperty(TablixColumn.prototype, \"footer\", {\n get: function () {\n return this._footerCell;\n },\n set: function (footerCell) {\n this._footerCell = footerCell;\n footerCell._column = this;\n footerCell.setContainerWidth(this._containerWidth);\n },\n enumerable: true,\n configurable: true\n });\n TablixColumn.prototype.onResize = function (width) {\n if (width === this.getContentContextualWidth())\n return;\n this._containerWidth = width;\n this.setContainerWidth(this._containerWidth);\n this._sizeFixed = true;\n this._fixedToAligningWidth = false;\n this._aligningWidth = -1;\n };\n TablixColumn.prototype.onResizeEnd = function (width) {\n // Invoke resize callback\n var gridPresenter = this.owner._presenter;\n if (gridPresenter)\n gridPresenter.invokeColumnResizeEndCallback(this._columnIndex, width);\n };\n TablixColumn.prototype.fixSize = function () {\n var shouldAlign = this._aligningWidth !== -1;\n var switched = shouldAlign !== this._fixedToAligningWidth;\n if ((this._sizeFixed && !switched && !shouldAlign))\n return;\n if (this._aligningWidth === -1) {\n this.setContainerWidth(this._containerWidth);\n }\n else {\n this.setContainerWidth(this._aligningWidth);\n }\n this._sizeFixed = true;\n this._fixedToAligningWidth = this._aligningWidth !== -1;\n };\n TablixColumn.prototype.clearSize = function () {\n this._containerWidth = -1;\n this.setContainerWidth(this._containerWidth);\n this._sizeFixed = false;\n };\n TablixColumn.prototype.getContentContextualWidth = function () {\n return this._containerWidth;\n };\n TablixColumn.prototype.getCellIContentContextualWidth = function (cell) {\n return this._presenter.getCellContentWidth(cell);\n };\n TablixColumn.prototype.getCellSpanningWidthWithScrolling = function (cell, tablixGrid) {\n var width = this.getContextualWidth() + this.getScrollingOffset();\n if (cell.colSpan > 1) {\n var index = this.getIndex(tablixGrid);\n var columns = tablixGrid.realizedColumns;\n for (var i = 1; i < cell.colSpan; i++)\n width += columns[i + index].getContextualWidth();\n }\n return width;\n };\n TablixColumn.prototype.getScrollingOffset = function () {\n var offset = 0;\n if (this._realizedColumnHeaders.length > 0)\n offset = this._realizedColumnHeaders[this._realizedColumnHeaders.length - 1].horizontalOffset;\n return offset;\n };\n TablixColumn.prototype.getContextualWidth = function () {\n if (this._width === -1 || this._containerWidth === -1)\n this._width = this._presenter.getWidth();\n return this._width;\n };\n TablixColumn.prototype.calculateSize = function () {\n if (this._sizeFixed)\n return this._containerWidth;\n var contentWidth = 0;\n for (var _i = 0, _a = this._realizedColumnHeaders; _i < _a.length; _i++) {\n var cell = _a[_i];\n if (cell.colSpan === 1)\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\n }\n for (var _b = 0, _c = this._realizedRowHeaders; _b < _c.length; _b++) {\n var cell = _c[_b];\n if (cell.colSpan === 1)\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\n }\n for (var _d = 0, _e = this._realizedCornerCells; _d < _e.length; _d++) {\n var cell = _e[_d];\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\n }\n for (var _f = 0, _g = this._realizedBodyCells; _f < _g.length; _f++) {\n var cell = _g[_f];\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\n }\n if (this._footerCell !== null) {\n if (this._footerCell.colSpan === 1)\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(this._footerCell));\n }\n return this._containerWidth = contentWidth;\n };\n TablixColumn.prototype.setAligningContextualWidth = function (size) {\n this._aligningWidth = size;\n };\n TablixColumn.prototype.getAligningContextualWidth = function () {\n return this._aligningWidth;\n };\n TablixColumn.prototype.setContainerWidth = function (value) {\n for (var _i = 0, _a = this._realizedColumnHeaders; _i < _a.length; _i++) {\n var cell = _a[_i];\n if (cell.colSpan === 1)\n cell.setContainerWidth(value);\n }\n for (var _b = 0, _c = this._realizedRowHeaders; _b < _c.length; _b++) {\n var cell = _c[_b];\n if (cell.colSpan === 1)\n cell.setContainerWidth(value);\n }\n for (var _d = 0, _e = this._realizedCornerCells; _d < _e.length; _d++) {\n var cell = _e[_d];\n cell.setContainerWidth(value);\n }\n for (var _f = 0, _g = this._realizedBodyCells; _f < _g.length; _f++) {\n var cell = _g[_f];\n cell.setContainerWidth(value);\n }\n if (this._footerCell !== null) {\n if (this._footerCell.colSpan === 1)\n this._footerCell.setContainerWidth(value);\n }\n this._width = value; // set cell width to new value\n };\n TablixColumn.prototype.getTablixCell = function () {\n var realizedCells = this._realizedColumnHeaders.length > 0 ? this._realizedColumnHeaders : this._realizedCornerCells;\n //Debug.assert(realizedCells.length !== 0, \"At least on header should have been realized\");\n return realizedCells[realizedCells.length - 1];\n };\n TablixColumn.prototype.getIndex = function (grid) {\n return grid.realizedColumns.indexOf(this);\n };\n TablixColumn.prototype.getHeaders = function () {\n return this._realizedColumnHeaders;\n };\n TablixColumn.prototype.getOtherDimensionHeaders = function () {\n return this._realizedRowHeaders;\n };\n TablixColumn.prototype.getCellContextualSpan = function (cell) {\n return cell.colSpan;\n };\n TablixColumn.prototype.getOtherDimensionOwner = function (cell) {\n return cell._row;\n };\n return TablixColumn;\n }());\n internal.TablixColumn = TablixColumn;\n var TablixRow = (function () {\n function TablixRow(presenter) {\n this._containerHeight = -1;\n this._presenter = presenter;\n this._presenter.initialize(this);\n this._allocatedCells = [];\n this._heightFixed = false;\n this._containerHeight = -1;\n this._height = -1;\n }\n TablixRow.prototype.initialize = function (owner) {\n this._owner = owner;\n this._realizedRowHeaders = [];\n this._realizedBodyCells = [];\n this._realizedCornerCells = [];\n this._realizedColumnHeaders = [];\n this._realizedCellsCount = 0;\n };\n Object.defineProperty(TablixRow.prototype, \"presenter\", {\n get: function () {\n return this._presenter;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixRow.prototype, \"owner\", {\n get: function () {\n return this._owner;\n },\n enumerable: true,\n configurable: true\n });\n TablixRow.prototype.releaseUnusedCells = function (owner) {\n this.releaseCells(owner, this._realizedCellsCount);\n };\n TablixRow.prototype.releaseAllCells = function (owner) {\n this.releaseCells(owner, 0);\n };\n TablixRow.prototype.releaseCells = function (owner, startIndex) {\n var cells = this._allocatedCells;\n var length = cells.length;\n for (var i = startIndex; i < length; i++) {\n var cell = cells[i];\n owner._unbindCell(cell);\n cell.clear();\n }\n };\n TablixRow.prototype.moveScrollableCellsToEnd = function (count) {\n var frontIndex = Math.max(this._realizedRowHeaders.length, this._realizedCornerCells.length);\n for (var i = frontIndex; i < frontIndex + count; i++) {\n var cell = this._allocatedCells[i];\n this._presenter.onRemoveCell(cell);\n this._presenter.onAppendCell(cell);\n this._allocatedCells.push(cell);\n }\n this._allocatedCells.splice(frontIndex, count);\n };\n TablixRow.prototype.moveScrollableCellsToStart = function (count) {\n var frontIndex = Math.max(this._realizedRowHeaders.length, this._realizedCornerCells.length);\n for (var i = frontIndex; i < frontIndex + count; i++) {\n var cell = this._allocatedCells.pop();\n this._presenter.onRemoveCell(cell);\n this._presenter.onInsertCellBefore(cell, this._allocatedCells[frontIndex]);\n this._allocatedCells.splice(frontIndex, 0, cell);\n }\n };\n TablixRow.prototype.getOrCreateCornerCell = function (column) {\n var cell = this.getOrCreateCell();\n cell.prepare(false);\n column.addCornerCell(cell);\n this._realizedCornerCells.push(cell);\n cell.setContainerHeight(this._containerHeight);\n return cell;\n };\n TablixRow.prototype.getOrCreateRowHeader = function (column, scrollable, leaf) {\n var cell = this.getOrCreateCell();\n cell.prepare(scrollable);\n column.addRowHeader(cell);\n this._realizedRowHeaders.push(cell);\n if (leaf)\n cell.setContainerHeight(this._containerHeight);\n return cell;\n };\n TablixRow.prototype.getOrCreateColumnHeader = function (column, scrollable, leaf) {\n var cell = this.getOrCreateCell();\n cell.prepare(scrollable);\n column.addColumnHeader(cell, leaf);\n this._realizedColumnHeaders.push(cell);\n cell.setContainerHeight(this._containerHeight);\n return cell;\n };\n TablixRow.prototype.getOrCreateBodyCell = function (column, scrollable) {\n var cell = this.getOrCreateCell();\n cell.prepare(scrollable);\n column.addBodyCell(cell);\n this._realizedBodyCells.push(cell);\n cell.setContainerHeight(this._containerHeight);\n return cell;\n };\n TablixRow.prototype.getOrCreateFooterRowHeader = function (column) {\n var cell = this.getOrCreateCell();\n cell.prepare(false);\n column.footer = cell;\n this._realizedRowHeaders.push(cell);\n cell.setContainerHeight(this._containerHeight);\n return cell;\n };\n TablixRow.prototype.getOrCreateFooterBodyCell = function (column, scrollable) {\n var cell = this.getOrCreateCell();\n cell.prepare(scrollable);\n column.footer = cell;\n this._realizedBodyCells.push(cell);\n cell.setContainerHeight(this._containerHeight);\n return cell;\n };\n TablixRow.prototype.getRowHeaderLeafIndex = function () {\n var index = -1;\n var count = this._allocatedCells.length;\n for (var i = 0; i < count; i++) {\n if (this._allocatedCells[i].type !== 1 /* RowHeader */)\n break;\n index++;\n }\n return index;\n };\n TablixRow.prototype.getAllocatedCellAt = function (index) {\n return this._allocatedCells[index];\n };\n TablixRow.prototype.moveCellsBy = function (delta) {\n if (this._allocatedCells.length === 0)\n return;\n if (delta > 0) {\n var refCell = this._allocatedCells[0];\n for (var i = 0; i < delta; i++) {\n var cell = this.createCell(this);\n this._presenter.onInsertCellBefore(cell, refCell);\n this._allocatedCells.unshift(cell);\n refCell = cell;\n }\n }\n else {\n delta = -delta;\n for (var i = 0; i < delta; i++) {\n this._presenter.onRemoveCell(this._allocatedCells[i]);\n }\n this._allocatedCells.splice(0, delta);\n }\n };\n TablixRow.prototype.getRealizedCellCount = function () {\n return this._realizedCellsCount;\n };\n TablixRow.prototype.getRealizedHeadersCount = function () {\n return this._realizedRowHeaders.length;\n };\n TablixRow.prototype.getRealizedHeaderAt = function (index) {\n return this._realizedRowHeaders[index];\n };\n TablixRow.prototype.getTablixCell = function () {\n var realizedCells;\n if (this._realizedRowHeaders.length > 0) {\n realizedCells = this._realizedRowHeaders;\n }\n else if (this._realizedCornerCells.length > 0) {\n realizedCells = this._realizedCornerCells;\n }\n else {\n realizedCells = this._realizedColumnHeaders;\n }\n //Debug.assert(realizedCells.length !== 0, \"At least on header should have been realized\");\n return realizedCells[realizedCells.length - 1];\n };\n TablixRow.prototype.getOrCreateEmptySpaceCell = function () {\n var cell = this._allocatedCells[this._realizedCellsCount];\n if (cell === undefined) {\n cell = this.createCell(this);\n this._allocatedCells[this._realizedCellsCount] = cell;\n this._presenter.onAppendCell(cell);\n }\n return cell;\n };\n TablixRow.prototype.createCell = function (row) {\n var presenter = this._presenter.createCellPresenter(this._owner.owner.layoutManager.getLayoutKind());\n return new TablixCell(presenter, presenter, this);\n };\n TablixRow.prototype.getOrCreateCell = function () {\n var cell = this._allocatedCells[this._realizedCellsCount];\n if (cell === undefined) {\n cell = this.createCell(this);\n this._allocatedCells[this._realizedCellsCount] = cell;\n this._presenter.onAppendCell(cell);\n }\n else {\n cell.colSpan = 1;\n cell.rowSpan = 1;\n }\n this._realizedCellsCount = this._realizedCellsCount + 1;\n return cell;\n };\n TablixRow.prototype.onResize = function (height) {\n if (height === this.getContentContextualWidth())\n return;\n this._containerHeight = height;\n this.setContentHeight();\n this._heightFixed = true;\n this.setAligningContextualWidth(-1);\n };\n TablixRow.prototype.onResizeEnd = function (height) { };\n TablixRow.prototype.fixSize = function () {\n if (this.sizeFixed())\n return;\n this.setContentHeight();\n this._heightFixed = true;\n };\n TablixRow.prototype.unfixSize = function () {\n this._heightFixed = false;\n this._height = -1;\n };\n TablixRow.prototype.getContentContextualWidth = function () {\n return this._containerHeight;\n };\n TablixRow.prototype.getCellIContentContextualWidth = function (cell) {\n return this.presenter.getCellContentHeight(cell);\n };\n TablixRow.prototype.getCellSpanningHeight = function (cell) {\n var height = this.getContextualWidth();\n if (cell.rowSpan > 1) {\n var index = this.getIndex(this.owner);\n var rows = this.owner.realizedRows;\n for (var i = 1; i < cell.rowSpan; i++)\n height += rows[i + index].getContextualWidth();\n }\n return height;\n };\n TablixRow.prototype.getContextualWidth = function () {\n if (this._height === -1 || this._containerHeight === -1)\n this._height = this._presenter.getHeight();\n return this._height;\n };\n TablixRow.prototype.sizeFixed = function () {\n return this._heightFixed;\n };\n TablixRow.prototype.calculateSize = function () {\n if (this._heightFixed)\n return this._containerHeight;\n var contentHeight = 0;\n var count = this._realizedRowHeaders.length;\n for (var i = 0; i < count; i++) {\n var cell = this._realizedRowHeaders[i];\n if (cell.rowSpan === 1)\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(cell));\n }\n count = this._realizedCornerCells.length;\n for (var i = 0; i < count; i++) {\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(this._realizedCornerCells[i]));\n }\n count = this._realizedColumnHeaders.length;\n for (var i = 0; i < count; i++) {\n var cell = this._realizedColumnHeaders[i];\n if (cell.rowSpan === 1)\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(cell));\n }\n count = this._realizedBodyCells.length;\n for (var i = 0; i < count; i++) {\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(this._realizedBodyCells[i]));\n }\n return this._containerHeight = contentHeight;\n };\n TablixRow.prototype.setAligningContextualWidth = function (size) {\n // TODO should be implemented when we support variable row heights\n };\n TablixRow.prototype.getAligningContextualWidth = function () {\n // TODO should be implemented when we support variable row heights\n return -1;\n };\n TablixRow.prototype.setContentHeight = function () {\n var count = this._realizedRowHeaders.length;\n // Need to do them in reverse order so that leaf headers are set first\n for (var i = count - 1; i >= 0; i--) {\n var cell = this._realizedRowHeaders[i];\n cell.setContainerHeight(this._containerHeight);\n if (cell.rowSpan > 1)\n cell.setContainerHeight(this.getCellSpanningHeight(cell));\n }\n count = this._realizedCornerCells.length;\n for (var i = 0; i < count; i++) {\n this._realizedCornerCells[i].setContainerHeight(this._containerHeight);\n }\n count = this._realizedColumnHeaders.length;\n for (var i = 0; i < count; i++) {\n var cell = this._realizedColumnHeaders[i];\n cell.setContainerHeight(this._containerHeight);\n if (cell.rowSpan > 1)\n cell.setContainerHeight(this.getCellSpanningHeight(cell));\n }\n count = this._realizedBodyCells.length;\n for (var i = 0; i < count; i++) {\n this._realizedBodyCells[i].setContainerHeight(this._containerHeight);\n }\n this._height = -1;\n };\n TablixRow.prototype.getIndex = function (grid) {\n return grid.realizedRows.indexOf(this);\n };\n TablixRow.prototype.getHeaders = function () {\n return this._realizedRowHeaders;\n };\n TablixRow.prototype.getOtherDimensionHeaders = function () {\n return this._realizedColumnHeaders;\n };\n TablixRow.prototype.getCellContextualSpan = function (cell) {\n return cell.rowSpan;\n };\n TablixRow.prototype.getOtherDimensionOwner = function (cell) {\n return cell._column;\n };\n return TablixRow;\n }());\n internal.TablixRow = TablixRow;\n var TablixGrid = (function () {\n function TablixGrid(presenter) {\n this._presenter = presenter;\n this._footerRow = null;\n }\n TablixGrid.prototype.initialize = function (owner, gridHost, footerHost) {\n this._owner = owner;\n this._presenter.initialize(this, gridHost, footerHost, owner);\n this.fillColumnsProportionally = false;\n this._realizedRows = [];\n this._realizedColumns = [];\n this._emptySpaceHeaderCell = null;\n this._emptyFooterSpaceCell = null;\n };\n Object.defineProperty(TablixGrid.prototype, \"owner\", {\n get: function () {\n return this._owner;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixGrid.prototype, \"fillColumnsProportionally\", {\n get: function () {\n return this._fillColumnsProportionally;\n },\n set: function (value) {\n if (this._fillColumnsProportionally === value)\n return;\n this._fillColumnsProportionally = value;\n this._presenter.onFillColumnsProportionallyChanged(value);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixGrid.prototype, \"realizedColumns\", {\n get: function () {\n return this._realizedColumns;\n },\n set: function (columns) {\n this._realizedColumns = columns;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixGrid.prototype, \"realizedRows\", {\n get: function () {\n return this._realizedRows;\n },\n set: function (rows) {\n this._realizedRows = rows;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixGrid.prototype, \"footerRow\", {\n get: function () {\n return this._footerRow;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixGrid.prototype, \"emptySpaceHeaderCell\", {\n get: function () {\n return this._emptySpaceHeaderCell;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixGrid.prototype, \"emptySpaceFooterCell\", {\n get: function () {\n return this._emptyFooterSpaceCell;\n },\n enumerable: true,\n configurable: true\n });\n TablixGrid.prototype.ShowEmptySpaceCells = function (rowSpan, width) {\n if (this._realizedRows.length === 0)\n return;\n if (this._realizedRows.length !== 0 && !this._emptySpaceHeaderCell) {\n this._emptySpaceHeaderCell = this._realizedRows[0].getOrCreateEmptySpaceCell();\n this._emptySpaceHeaderCell.rowSpan = rowSpan;\n this._emptySpaceHeaderCell.colSpan = 1;\n this._emptySpaceHeaderCell.setContainerWidth(width);\n }\n if (this._footerRow && (this._emptyFooterSpaceCell === null)) {\n this._emptyFooterSpaceCell = this._footerRow.getOrCreateEmptySpaceCell();\n this._emptyFooterSpaceCell.rowSpan = 1;\n this._emptyFooterSpaceCell.colSpan = 1;\n this._emptyFooterSpaceCell.setContainerWidth(width);\n }\n };\n TablixGrid.prototype.HideEmptySpaceCells = function () {\n if (this._emptySpaceHeaderCell) {\n this._emptySpaceHeaderCell.clear();\n this._emptySpaceHeaderCell = null;\n }\n if (this._emptyFooterSpaceCell) {\n this._emptyFooterSpaceCell.clear();\n this._emptyFooterSpaceCell = null;\n }\n };\n TablixGrid.prototype.onStartRenderingSession = function (clear) {\n if (clear) {\n this.clearRows();\n this.clearColumns();\n }\n };\n TablixGrid.prototype.onStartRenderingIteration = function () {\n this.initializeRows();\n this.initializeColumns();\n };\n TablixGrid.prototype.onEndRenderingIteration = function () {\n var rows = this._rows;\n if (rows !== undefined) {\n var rowCount = rows.length;\n for (var i = 0; i < rowCount; i++) {\n rows[i].releaseUnusedCells(this._owner);\n }\n }\n if (this._footerRow) {\n this._footerRow.releaseUnusedCells(this._owner);\n }\n };\n TablixGrid.prototype.getOrCreateRow = function (rowIndex) {\n var currentRow = this._rows[rowIndex];\n if (currentRow === undefined) {\n currentRow = new TablixRow(this._presenter.createRowPresenter());\n currentRow.initialize(this);\n this._presenter.onAppendRow(currentRow);\n this._rows[rowIndex] = currentRow;\n }\n if (this._realizedRows[rowIndex] === undefined) {\n this._realizedRows[rowIndex] = currentRow;\n }\n return currentRow;\n };\n TablixGrid.prototype.getOrCreateFootersRow = function () {\n if (this._footerRow === null) {\n this._footerRow = new TablixRow(this._presenter.createRowPresenter());\n this._footerRow.initialize(this);\n this._presenter.onAddFooterRow(this._footerRow);\n }\n return this._footerRow;\n };\n TablixGrid.prototype.moveRowsToEnd = function (moveFromIndex, count) {\n for (var i = 0; i < count; i++) {\n var row = this._rows[i + moveFromIndex];\n debug.assertValue(row, \"Invalid Row Index\");\n row.unfixSize();\n this._presenter.onRemoveRow(row);\n this._presenter.onAppendRow(row);\n this._rows.push(row);\n }\n this._rows.splice(moveFromIndex, count);\n };\n TablixGrid.prototype.moveRowsToStart = function (moveToIndex, count) {\n var refRow = this._rows[moveToIndex];\n debug.assertValue(refRow, \"Invalid Row Index\");\n for (var i = 0; i < count; i++) {\n var row = this._rows.pop();\n row.unfixSize();\n this._presenter.onRemoveRow(row);\n this._presenter.onInsertRowBefore(row, refRow);\n this._rows.splice(moveToIndex + i, 0, row);\n }\n };\n TablixGrid.prototype.moveColumnsToEnd = function (moveFromIndex, count) {\n var firstCol = this._rows[0]._realizedCornerCells.length;\n var leafStartDepth = Math.max(this._columns[firstCol]._realizedColumnHeaders.length - 1, 0);\n for (var i = leafStartDepth; i < this._rows.length; i++) {\n this._rows[i].moveScrollableCellsToEnd(count);\n }\n for (var i = 0; i < count; i++) {\n var column = this._columns[i + moveFromIndex];\n //Debug.assertValue(column, \"Invalid Column Index\");\n this._columns.push(column);\n }\n this._columns.splice(moveFromIndex, count);\n };\n TablixGrid.prototype.moveColumnsToStart = function (moveToIndex, count) {\n var firstCol = this._rows[0]._realizedCornerCells.length;\n var leafStartDepth = Math.max(this._columns[firstCol]._realizedColumnHeaders.length - 1, 0);\n for (var i = leafStartDepth; i < this._rows.length; i++) {\n this._rows[i].moveScrollableCellsToStart(count);\n }\n for (var i = 0; i < count; i++) {\n var column = this._columns.pop();\n this._columns.splice(moveToIndex + i, 0, column);\n }\n };\n TablixGrid.prototype.getOrCreateColumn = function (columnIndex) {\n var currentColumn = this._columns[columnIndex];\n if (currentColumn === undefined) {\n currentColumn = new TablixColumn(this._presenter.createColumnPresenter(columnIndex), columnIndex);\n currentColumn.initialize(this);\n this._columns[columnIndex] = currentColumn;\n }\n if (this._realizedColumns[columnIndex] === undefined) {\n this._realizedColumns[columnIndex] = currentColumn;\n }\n return currentColumn;\n };\n TablixGrid.prototype.initializeColumns = function () {\n if (!this._columns)\n this._columns = [];\n var length = this._columns.length;\n for (var i = 0; i < length; i++) {\n this._columns[i].initialize(this);\n }\n this._realizedColumns = [];\n };\n TablixGrid.prototype.clearColumns = function () {\n this._columns = null;\n this._realizedColumns = null;\n };\n TablixGrid.prototype.initializeRows = function () {\n // make sure rowDimension confirms it and it's not null in the grid\n var hasFooter = this._owner.rowDimension.hasFooter() && (this._footerRow !== null);\n this._realizedRows = [];\n if (!this._rows) {\n this._rows = [];\n }\n var rows = this._rows;\n var length = rows.length;\n for (var i = 0; i < length; i++) {\n rows[i].initialize(this);\n }\n if (hasFooter) {\n if (!this._footerRow) {\n this.getOrCreateFootersRow();\n }\n this._footerRow.initialize(this);\n }\n };\n TablixGrid.prototype.clearRows = function () {\n var rows = this._rows;\n if (rows) {\n var length_1 = rows.length;\n for (var i = 0; i < length_1; i++) {\n rows[i].releaseAllCells(this._owner);\n }\n if (this._footerRow)\n this._footerRow.releaseAllCells(this._owner);\n this._presenter.onClear();\n this._footerRow = null;\n this._rows = null;\n this._realizedRows = null;\n }\n };\n TablixGrid.prototype.getWidth = function () {\n return this._presenter.getWidth();\n };\n TablixGrid.prototype.getHeight = function () {\n return this._presenter.getHeight();\n };\n return TablixGrid;\n }());\n internal.TablixGrid = TablixGrid;\n })(internal = controls.internal || (controls.internal = {}));\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var internal;\n (function (internal) {\n var PixelConverter = jsCommon.PixelConverter;\n /**\n * This class is used for layouts that don't or cannot\n * rely on DOM measurements. Instead they compute all required\n * widths and heights and store it in this structure.\n */\n var SizeComputationManager = (function () {\n function SizeComputationManager() {\n }\n Object.defineProperty(SizeComputationManager.prototype, \"visibleWidth\", {\n get: function () {\n return this._viewport ? this._viewport.width : 0;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"visibleHeight\", {\n get: function () {\n return this._viewport ? this._viewport.height : 0;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"gridWidth\", {\n get: function () {\n return this.visibleWidth;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"gridHeight\", {\n get: function () {\n return this.visibleHeight;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"rowHeight\", {\n get: function () {\n return this._cellHeight;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"cellWidth\", {\n get: function () {\n return this._cellWidth;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"cellHeight\", {\n get: function () {\n return this._cellHeight;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"contentWidth\", {\n get: function () {\n return this._cellWidth;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SizeComputationManager.prototype, \"contentHeight\", {\n get: function () {\n return this._cellHeight;\n },\n enumerable: true,\n configurable: true\n });\n SizeComputationManager.prototype.updateColumnCount = function (columnCount) {\n this._columnCount = columnCount;\n };\n SizeComputationManager.prototype.updateRowHeight = function (rowHeight) {\n this._cellHeight = rowHeight;\n };\n SizeComputationManager.prototype.updateScalingFactor = function (scalingFactor) {\n this._scalingFactor = scalingFactor;\n this._cellWidth = this.computeColumnWidth(this._columnCount);\n };\n SizeComputationManager.prototype.updateViewport = function (viewport) {\n this._viewport = viewport;\n this._cellWidth = this.computeColumnWidth(this._columnCount);\n this._cellHeight = this.computeColumnHeight();\n };\n SizeComputationManager.prototype.computeColumnWidth = function (totalColumnCount) {\n var scalingFactor = this._scalingFactor;\n if (!scalingFactor)\n scalingFactor = 1;\n var minimumColumnWidth = scalingFactor * SizeComputationManager.TablixMinimumColumnWidth;\n var maxAllowedColumns = Math.floor(this._viewport.width / minimumColumnWidth);\n return this.fitToColumnCount(maxAllowedColumns, totalColumnCount);\n };\n SizeComputationManager.prototype.computeColumnHeight = function () {\n if (!this.hasImageContent)\n return this._cellHeight;\n var width = this._viewport.width;\n if (width <= 250) {\n // Small\n return 20;\n }\n else if (width <= 510) {\n // Medium\n return 51;\n }\n else if (width <= 770) {\n // Large\n return 52;\n }\n debug.assertFail(\"Fixed size is only for viewport up to 770px width.\");\n };\n SizeComputationManager.prototype.fitToColumnCount = function (maxAllowedColumnCount, totalColumnCount) {\n var columnsToFit = Math.min(maxAllowedColumnCount, totalColumnCount);\n return Math.floor(this._viewport.width / columnsToFit);\n };\n // Minimum size for a column, used to calculate layout\n SizeComputationManager.TablixMinimumColumnWidth = 75;\n return SizeComputationManager;\n }());\n internal.SizeComputationManager = SizeComputationManager;\n var DimensionLayoutManager = (function () {\n function DimensionLayoutManager(owner, grid, realizationManager) {\n //debug.assertValue(realizationManager, \"Realization Manager must be defined\");\n this._owner = owner;\n this._grid = grid;\n this._lastScrollOffset = null;\n this._isScrolling = false;\n this._fixedSizeEnabled = true;\n this._done = false;\n this._realizationManager = realizationManager;\n }\n Object.defineProperty(DimensionLayoutManager.prototype, \"owner\", {\n get: function () {\n return this._owner;\n },\n set: function (owner) {\n this._owner = owner;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DimensionLayoutManager.prototype, \"realizationManager\", {\n get: function () {\n return this._realizationManager;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DimensionLayoutManager.prototype, \"fixedSizeEnabled\", {\n get: function () {\n return this._fixedSizeEnabled;\n },\n set: function (enable) {\n this._fixedSizeEnabled = enable;\n },\n enumerable: true,\n configurable: true\n });\n DimensionLayoutManager.prototype.onCornerCellRealized = function (item, cell, leaf) {\n this._realizationManager.onCornerCellRealized(item, cell);\n };\n DimensionLayoutManager.prototype.onHeaderRealized = function (item, cell, leaf) {\n this._realizationManager.onHeaderRealized(item, cell, leaf);\n };\n Object.defineProperty(DimensionLayoutManager.prototype, \"needsToRealize\", {\n get: function () {\n return this._realizationManager.needsToRealize;\n },\n enumerable: true,\n configurable: true\n });\n DimensionLayoutManager.prototype.getVisibleSizeRatio = function () {\n return 1 - this.dimension.getFractionScrollOffset();\n };\n Object.defineProperty(DimensionLayoutManager.prototype, \"alignToEnd\", {\n get: function () {\n return this._alignToEnd;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DimensionLayoutManager.prototype, \"done\", {\n get: function () {\n return this._done;\n },\n enumerable: true,\n configurable: true\n });\n DimensionLayoutManager.prototype._requiresMeasure = function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._requiresMeasure\");\n return true;\n };\n DimensionLayoutManager.prototype.startScrollingSession = function () {\n this._isScrolling = true;\n };\n DimensionLayoutManager.prototype.endScrollingSession = function () {\n this._isScrolling = false;\n };\n DimensionLayoutManager.prototype.isScrolling = function () {\n return this._isScrolling;\n };\n DimensionLayoutManager.prototype.isResizing = function () {\n return false;\n };\n DimensionLayoutManager.prototype.getOtherHierarchyContextualHeight = function () {\n var otherDimension = this.dimension.otherDimension;\n var count = otherDimension.getDepth();\n var contextualHeight = 0;\n var items = this._getRealizedItems();\n if (items.length > 0) {\n for (var i = 0; i < count; i++) {\n contextualHeight += items[i].getContextualWidth();\n }\n }\n return contextualHeight;\n };\n DimensionLayoutManager.prototype._isAutoSized = function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._isAutoSized\");\n return false;\n };\n DimensionLayoutManager.prototype.onStartRenderingSession = function () {\n this._measureEnabled = this._requiresMeasure();\n this._gridOffset = this.dimension.otherDimension.getDepth();\n };\n DimensionLayoutManager.prototype.onEndRenderingSession = function () {\n this._realizationManager.onEndRenderingSession();\n this._alignToEnd = false;\n this._done = false;\n this._measureEnabled = true;\n this._sendDimensionsToControl();\n };\n /**\n * Implementing classes must override this to send dimentions to TablixControl.\n */\n DimensionLayoutManager.prototype._sendDimensionsToControl = function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._sendDimensionsToControl\");\n };\n Object.defineProperty(DimensionLayoutManager.prototype, \"measureEnabled\", {\n get: function () {\n return this._measureEnabled;\n },\n enumerable: true,\n configurable: true\n });\n DimensionLayoutManager.prototype.getFooterContextualWidth = function () {\n return 0;\n };\n DimensionLayoutManager.prototype.onStartRenderingIteration = function (clear, contextualWidth) {\n if (this._measureEnabled && !this._done) {\n this._contextualWidthToFill = (contextualWidth - this.otherScrollbarContextualWidth) * this.getGridScale() - this.getFooterContextualWidth();\n }\n this._realizationManager.onStartRenderingIteration();\n if (clear) {\n this._lastScrollOffset = null;\n }\n else if (this._lastScrollOffset !== null) {\n this.swapElements();\n }\n };\n Object.defineProperty(DimensionLayoutManager.prototype, \"allItemsRealized\", {\n get: function () {\n return this.getRealizedItemsCount() - this._gridOffset === this.dimension.getItemsCount() || this.dimension.getItemsCount() === 0;\n },\n enumerable: true,\n configurable: true\n });\n DimensionLayoutManager.prototype.onEndRenderingIteration = function () {\n if (this._done) {\n return;\n }\n if (!this._measureEnabled) {\n this._lastScrollOffset = this.dimension.scrollOffset;\n this._done = true;\n return;\n }\n var gridContextualWidth = this.getGridContextualWidth();\n var filled = powerbi.Double.greaterOrEqualWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\n var allRealized = this.allItemsRealized;\n var newScrollOffset;\n if (filled) {\n newScrollOffset = this.scrollForwardToAlignEnd(gridContextualWidth);\n }\n else {\n newScrollOffset = this.scrollBackwardToFill(gridContextualWidth);\n }\n this._realizationManager.onEndRenderingIteration(gridContextualWidth, filled);\n var originalScrollbarVisible = this.dimension.scrollbar.visible;\n this.updateScrollbar(gridContextualWidth);\n this._done = (filled || allRealized) &&\n this.dimension.scrollbar.visible === originalScrollbarVisible &&\n powerbi.Double.equalWithPrecision(newScrollOffset, this.dimension.scrollOffset, DimensionLayoutManager._scrollOffsetPrecision);\n this.dimension.scrollOffset = newScrollOffset;\n this._lastScrollOffset = this.dimension.scrollOffset;\n };\n DimensionLayoutManager.prototype.getScrollDeltaWithinPage = function () {\n if (this._lastScrollOffset !== null) {\n var delta = this.dimension.getIntegerScrollOffset() - Math.floor(this._lastScrollOffset);\n if (Math.abs(delta) < this.getRealizedItemsCount() - this.dimension.otherDimension.getDepth()) {\n return delta;\n }\n }\n return null;\n };\n DimensionLayoutManager.prototype.swapElements = function () {\n var delta = this.getScrollDeltaWithinPage();\n if (delta !== null) {\n var otherHierarchyDepth = this.dimension.otherDimension.getDepth();\n if (Math.abs(delta) < this.getRealizedItemsCount() - otherHierarchyDepth) {\n if (delta > 0) {\n this._moveElementsToBottom(otherHierarchyDepth, delta);\n }\n else if (delta < 0) {\n this._moveElementsToTop(otherHierarchyDepth, -delta);\n }\n }\n }\n };\n DimensionLayoutManager.prototype._getRealizedItems = function () {\n // abstract\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._getRealizedItems\");\n return null;\n };\n DimensionLayoutManager.prototype.getRealizedItemsCount = function () {\n var realizedItems = this._getRealizedItems();\n return realizedItems.length;\n };\n DimensionLayoutManager.prototype._moveElementsToBottom = function (moveFromIndex, count) {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._moveElementsToBottom\");\n };\n DimensionLayoutManager.prototype._moveElementsToTop = function (moveToIndex, count) {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._moveElementsToTop\");\n };\n DimensionLayoutManager.prototype.isScrollingWithinPage = function () {\n return this.getScrollDeltaWithinPage() !== null;\n };\n DimensionLayoutManager.prototype.getGridContextualWidth = function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.getGridContextualWidth\");\n return 0;\n };\n DimensionLayoutManager.prototype.updateScrollbar = function (gridContextualWidth) {\n var scrollbar = this.dimension.scrollbar;\n scrollbar.viewMin = this.dimension.scrollOffset;\n scrollbar.min = 0;\n scrollbar.max = this.dimension.getItemsCount();\n scrollbar.viewSize = this.getViewSize(gridContextualWidth);\n this.dimension.scrollbar.show(this.canScroll(gridContextualWidth));\n };\n DimensionLayoutManager.prototype.getViewSize = function (gridContextualWidth) {\n var count = this.getRealizedItemsCount();\n if (count === 0)\n return 0;\n var startIndex = this._gridOffset;\n var sizeInItems = 0;\n var sizeInPixels = 0;\n var widthToFill = this._contextualWidthToFill;\n var scrollableArea = widthToFill - this.getOtherHierarchyContextualHeight();\n var error = this.getMeaurementError(gridContextualWidth);\n for (var i = startIndex; i < count; i++) {\n var visibleRatio = void 0;\n if (i === startIndex) {\n visibleRatio = this.getVisibleSizeRatio();\n }\n else\n visibleRatio = 1;\n var itemContextualWidth = this.getItemContextualWidthWithScrolling(i) * error;\n sizeInPixels += itemContextualWidth;\n sizeInItems += visibleRatio;\n if (powerbi.Double.greaterWithPrecision(sizeInPixels, scrollableArea, DimensionLayoutManager._pixelPrecision)) {\n sizeInItems -= ((sizeInPixels - scrollableArea) / itemContextualWidth) * visibleRatio;\n break;\n }\n }\n return sizeInItems;\n };\n DimensionLayoutManager.prototype.isScrollableHeader = function (item, items, index) {\n if (index !== 0 || this.dimension.getFractionScrollOffset() === 0) {\n return false;\n }\n var hierarchyNavigator = this.dimension._hierarchyNavigator;\n if (hierarchyNavigator.isLeaf(item)) {\n return true;\n }\n var currentItem = item;\n var currentItems = items;\n do {\n currentItems = hierarchyNavigator.getChildren(currentItem);\n currentItem = this.dimension.getFirstVisibleItem(hierarchyNavigator.getLevel(currentItem) + 1);\n if (currentItem === undefined) {\n break;\n }\n if (!hierarchyNavigator.isLastItem(currentItem, currentItems)) {\n return false;\n }\n } while (!hierarchyNavigator.isLeaf(currentItem));\n return true;\n };\n DimensionLayoutManager.prototype.reachedEnd = function () {\n return this.dimension.getIntegerScrollOffset() + (this.getRealizedItemsCount() - this._gridOffset) >= this.dimension.getItemsCount();\n };\n DimensionLayoutManager.prototype.scrollBackwardToFill = function (gridContextualWidth) {\n var newScrollOffset = this.dimension.scrollOffset;\n if (this.reachedEnd()) {\n var widthToFill = this._contextualWidthToFill - gridContextualWidth;\n if (this.dimension.getItemsCount() > 0) {\n var averageColumnwidth = gridContextualWidth / (this.getRealizedItemsCount() - this.dimension.getFractionScrollOffset());\n newScrollOffset = this.dimension.getValidScrollOffset(Math.floor(this.dimension.scrollOffset - (widthToFill / averageColumnwidth)));\n }\n this._alignToEnd = !powerbi.Double.equalWithPrecision(newScrollOffset, this.dimension.scrollOffset, DimensionLayoutManager._scrollOffsetPrecision); // this is an aproximate scrolling back, we have to ensure it is aligned to the end of the control\n }\n return newScrollOffset;\n };\n DimensionLayoutManager.prototype.getItemContextualWidth = function (index) {\n var realizedItems = this._getRealizedItems();\n if (index >= realizedItems.length)\n return null;\n return realizedItems[index].getContextualWidth();\n };\n DimensionLayoutManager.prototype.getItemContextualWidthWithScrolling = function (index) {\n return this.getSizeWithScrolling(this.getItemContextualWidth(index), index);\n };\n DimensionLayoutManager.prototype.getSizeWithScrolling = function (size, index) {\n var ratio;\n if (this._gridOffset === index) {\n ratio = this.getVisibleSizeRatio();\n }\n else {\n ratio = 1;\n }\n return size * ratio;\n };\n DimensionLayoutManager.prototype.getGridContextualWidthFromItems = function () {\n var count = this.getRealizedItemsCount();\n var contextualWidth = 0;\n for (var i = 0; i < count; i++) {\n contextualWidth += this.getItemContextualWidthWithScrolling(i);\n }\n return contextualWidth;\n };\n DimensionLayoutManager.prototype.getMeaurementError = function (gridContextualWidth) {\n return gridContextualWidth / this.getGridContextualWidthFromItems();\n };\n DimensionLayoutManager.prototype.scrollForwardToAlignEnd = function (gridContextualWidth) {\n var newScrollOffset = this.dimension.scrollOffset;\n if (this._alignToEnd) {\n var withinThreshold = powerbi.Double.equalWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\n if (!withinThreshold) {\n var count = this.getRealizedItemsCount();\n var startIndex = this._gridOffset;\n var widthToScroll = gridContextualWidth - this._contextualWidthToFill;\n var error = this.getMeaurementError(gridContextualWidth);\n for (var i = startIndex; i < count; i++) {\n var itemContextualWidth = this.getItemContextualWidth(i) * error;\n if (powerbi.Double.lessWithPrecision(itemContextualWidth, widthToScroll, DimensionLayoutManager._pixelPrecision)) {\n widthToScroll -= itemContextualWidth;\n }\n else {\n var visibleRatio = startIndex === i ? 1 - this.dimension.getFractionScrollOffset() : 1;\n newScrollOffset = this.dimension.getValidScrollOffset(this.dimension.scrollOffset + (i - startIndex) + (widthToScroll * visibleRatio / itemContextualWidth));\n break;\n }\n }\n }\n this._alignToEnd = !withinThreshold;\n }\n return newScrollOffset;\n };\n Object.defineProperty(DimensionLayoutManager.prototype, \"dimension\", {\n get: function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.dimension\");\n return null;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DimensionLayoutManager.prototype, \"otherLayoutManager\", {\n get: function () {\n return this.dimension.otherDimension.layoutManager;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DimensionLayoutManager.prototype, \"contextualWidthToFill\", {\n get: function () {\n return this._contextualWidthToFill;\n },\n enumerable: true,\n configurable: true\n });\n DimensionLayoutManager.prototype.getGridScale = function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.getGridScale\");\n return 0;\n };\n Object.defineProperty(DimensionLayoutManager.prototype, \"otherScrollbarContextualWidth\", {\n get: function () {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.otherScrollbarContextualWidth\");\n return 0;\n },\n enumerable: true,\n configurable: true\n });\n DimensionLayoutManager.prototype.getActualContextualWidth = function (gridContextualWidth) {\n if (this._isAutoSized() && !this.canScroll(gridContextualWidth))\n return gridContextualWidth;\n return this._contextualWidthToFill;\n };\n DimensionLayoutManager.prototype.canScroll = function (gridContextualWidth) {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.canScroll\");\n return false;\n };\n DimensionLayoutManager.prototype.calculateSizes = function () {\n if (this.fixedSizeEnabled) {\n this.calculateContextualWidths();\n this.calculateSpans();\n }\n };\n DimensionLayoutManager.prototype._calculateSize = function (item) {\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._calculateSize\");\n return null;\n };\n DimensionLayoutManager.prototype.calculateContextualWidths = function () {\n var items = this._getRealizedItems();\n var count = items.length;\n for (var i = 0; i < count; i++) {\n var item = items[i];\n if (this.measureEnabled)\n item.setAligningContextualWidth(-1);\n this._calculateSize(item);\n }\n };\n DimensionLayoutManager.prototype.calculateSpans = function () {\n if (this.measureEnabled) {\n this.updateNonScrollableItemsSpans();\n this.updateScrollableItemsSpans();\n }\n // TODO override in row layout manager to add footer to calculation, this is required for Matrix\n };\n DimensionLayoutManager.prototype.updateNonScrollableItemsSpans = function () {\n var otherDimensionItems = this.otherLayoutManager._getRealizedItems();\n var otherDimensionItemsCount = otherDimensionItems.length;\n var startIndex = this.dimension.getDepth();\n for (var i = startIndex; i < otherDimensionItemsCount; i++) {\n var otherDimensionItem = otherDimensionItems[i];\n this.updateSpans(otherDimensionItem, otherDimensionItem.getHeaders());\n }\n };\n DimensionLayoutManager.prototype.updateScrollableItemsSpans = function () {\n var otherRealizedItems = this.otherLayoutManager._getRealizedItems();\n var otherRealizedItemsCount = Math.min(this.dimension.getDepth(), otherRealizedItems.length);\n for (var i = 0; i < otherRealizedItemsCount; i++) {\n var otherRealizedItem = otherRealizedItems[i];\n this.updateSpans(otherRealizedItem, otherRealizedItem.getOtherDimensionHeaders());\n }\n };\n DimensionLayoutManager.prototype.fixSizes = function () {\n if (this.fixedSizeEnabled) {\n var items = this._getRealizedItems();\n var count = items.length;\n for (var i = count - 1; i >= 0; i--) {\n items[i].fixSize();\n }\n }\n };\n DimensionLayoutManager.prototype.updateSpans = function (otherRealizedItem, cells) {\n var realizedItems = this._getRealizedItems();\n var cellCount = cells.length;\n for (var j = 0; j < cellCount; j++) {\n var cell = cells[j];\n var owner = otherRealizedItem.getOtherDimensionOwner(cell);\n var span = owner.getCellContextualSpan(cell);\n if (span > 1) {\n var totalSizeInSpan = 0;\n var startIndex = owner.getIndex(this._grid);\n for (var k = 0; k < span; k++) {\n var item = realizedItems[k + startIndex];\n totalSizeInSpan += item.getContentContextualWidth();\n if (k === span - 1)\n this.updateLastChildSize(cell, item, totalSizeInSpan);\n }\n }\n }\n };\n DimensionLayoutManager.prototype.updateLastChildSize = function (spanningCell, item, totalSpanSize) {\n var delta = item.getCellIContentContextualWidth(spanningCell) - totalSpanSize;\n if (delta > 0)\n item.setAligningContextualWidth(Math.max(item.getAligningContextualWidth(), delta + item.getContentContextualWidth()));\n };\n DimensionLayoutManager._pixelPrecision = 1.0001;\n DimensionLayoutManager._scrollOffsetPrecision = 0.01;\n return DimensionLayoutManager;\n }());\n internal.DimensionLayoutManager = DimensionLayoutManager;\n var ResizeState = (function () {\n function ResizeState(column, width, scale) {\n this.column = column;\n this.item = column.getLeafItem();\n this.itemType = column.itemType;\n this.startColumnWidth = width;\n this.resizingDelta = 0;\n this.animationFrame = null;\n this.scale = scale;\n }\n ResizeState.prototype.getNewSize = function () {\n return this.startColumnWidth + this.resizingDelta;\n };\n return ResizeState;\n }());\n internal.ResizeState = ResizeState;\n var ColumnLayoutManager = (function (_super) {\n __extends(ColumnLayoutManager, _super);\n function ColumnLayoutManager(owner, grid, realizationManager) {\n _super.call(this, owner, grid, realizationManager);\n realizationManager.owner = this;\n this.fillProportionally = false;\n this._resizeState = null;\n }\n Object.defineProperty(ColumnLayoutManager.prototype, \"dimension\", {\n get: function () {\n return this.owner.owner.columnDimension;\n },\n enumerable: true,\n configurable: true\n });\n ColumnLayoutManager.prototype.isResizing = function () {\n return this._resizeState !== null;\n };\n Object.defineProperty(ColumnLayoutManager.prototype, \"fillProportionally\", {\n get: function () {\n return this._grid.fillColumnsProportionally;\n },\n set: function (value) {\n this._grid.fillColumnsProportionally = value;\n },\n enumerable: true,\n configurable: true\n });\n ColumnLayoutManager.prototype.getGridScale = function () {\n return this._grid._presenter.getScreenToCssRatioX();\n };\n Object.defineProperty(ColumnLayoutManager.prototype, \"otherScrollbarContextualWidth\", {\n get: function () {\n if (this.dimension.otherDimension.scrollbar.visible) {\n return controls.HTMLElementUtils.getElementWidth(this.dimension.otherDimension.scrollbar.element);\n }\n return 0;\n },\n enumerable: true,\n configurable: true\n });\n ColumnLayoutManager.prototype._getRealizedItems = function () {\n if (!this._grid.realizedColumns) {\n this._grid.realizedColumns = [];\n }\n return this._grid.realizedColumns;\n };\n ColumnLayoutManager.prototype._moveElementsToBottom = function (moveFromIndex, count) {\n this._grid.moveColumnsToEnd(moveFromIndex, count);\n };\n ColumnLayoutManager.prototype._moveElementsToTop = function (moveToIndex, count) {\n this._grid.moveColumnsToStart(moveToIndex, count);\n };\n ColumnLayoutManager.prototype._requiresMeasure = function () {\n // if the control is not scrolling in either dimension or is scrolling or is resizing\n return (!this.isScrolling() && !this.otherLayoutManager.isScrolling()) || this.isScrolling() || this.isResizing();\n };\n ColumnLayoutManager.prototype.getGridContextualWidth = function () {\n return this._grid.getWidth();\n };\n ColumnLayoutManager.prototype.getFirstVisibleColumn = function () {\n return this._grid.realizedColumns[this._gridOffset];\n };\n ColumnLayoutManager.prototype._isAutoSized = function () {\n return this.owner.owner.autoSizeWidth;\n };\n ColumnLayoutManager.prototype.applyScrolling = function () {\n var columnOffset = this.dimension.getFractionScrollOffset();\n var firstVisibleColumnWidth = 0;\n if (columnOffset !== 0) {\n var firstVisibleColumn = this.getFirstVisibleColumn();\n if (firstVisibleColumn !== undefined) {\n firstVisibleColumnWidth = firstVisibleColumn.getContextualWidth();\n this.scroll(firstVisibleColumn, firstVisibleColumnWidth, columnOffset);\n }\n }\n };\n ColumnLayoutManager.prototype.scroll = function (firstVisibleColumn, width, offset) {\n this.scrollCells(firstVisibleColumn._realizedColumnHeaders, width, offset);\n this.scrollBodyCells(this._grid.realizedRows, width, offset);\n if (firstVisibleColumn.footer !== null) {\n firstVisibleColumn.footer.scrollHorizontally(width, offset);\n }\n };\n ColumnLayoutManager.prototype.scrollCells = function (cells, width, offset) {\n var length = cells.length;\n for (var i = 0; i < length; i++) {\n cells[i].scrollHorizontally(width, offset);\n }\n };\n ColumnLayoutManager.prototype.scrollBodyCells = function (rows, width, offset) {\n var length = rows.length;\n var cells;\n var cell;\n for (var i = 0; i < length; i++) {\n cells = rows[i]._realizedBodyCells;\n if (cells !== undefined) {\n cell = cells[0];\n if (cell !== undefined) {\n cell.scrollHorizontally(width, offset);\n }\n }\n }\n };\n ColumnLayoutManager.prototype.onStartResize = function (cell, currentX, currentY) {\n this._resizeState = new ResizeState(cell._column, cell._column.getContentContextualWidth(), controls.HTMLElementUtils.getAccumulatedScale(this.owner.owner.container));\n };\n ColumnLayoutManager.prototype.onResize = function (cell, deltaX, deltaY) {\n var _this = this;\n if (this.isResizing()) {\n this._resizeState.resizingDelta = Math.round(Math.max(deltaX / this._resizeState.scale, ColumnLayoutManager.minColumnWidth - this._resizeState.startColumnWidth));\n if (this._resizeState.animationFrame === null)\n this._resizeState.animationFrame = requestAnimationFrame(function () { return _this.performResizing(); });\n }\n };\n ColumnLayoutManager.prototype.onEndResize = function (cell) {\n if (this.isResizing() && this._resizeState.animationFrame !== null) {\n this.performResizing(); // if we reached the end and we are still waiting for the last animation frame, perform the pending resizing and clear the state \n }\n this.endResizing();\n this._resizeState = null;\n };\n ColumnLayoutManager.prototype.onReset = function (cell) {\n this._resizeState = new ResizeState(cell._column, -1, 1);\n cell._column.clearSize();\n this.endResizing();\n this.owner.owner.refresh(false);\n this._resizeState = null;\n };\n ColumnLayoutManager.prototype.updateItemToResizeState = function (realizedColumns) {\n if (this._resizeState === null)\n return;\n var columnCount = realizedColumns.length;\n var hierarchyNavigator = this.owner.owner.hierarchyNavigator;\n // Only iterate over the columns that belong to column hierachy (i.e. skip the row hierarchy rows)\n // as this post-rendering adjustment only applies to them.\n var startIndex = this.otherLayoutManager.dimension.getDepth();\n for (var i = startIndex; i < columnCount; i++) {\n var column = realizedColumns[i];\n if (!column.columnHeaderOrCornerEquals(this._resizeState.itemType, this._resizeState.item, column.itemType, column.getLeafItem(), hierarchyNavigator))\n continue;\n if (column !== this._resizeState.column) {\n this._resizeState.column = column;\n column.onResize(this._resizeState.getNewSize());\n break;\n }\n }\n };\n ColumnLayoutManager.prototype.performResizing = function () {\n if (this._resizeState === null)\n return;\n this._resizeState.animationFrame = null;\n var newSize = this._resizeState.getNewSize();\n this._resizeState.column.onResize(newSize);\n this.owner.owner.refresh(false);\n };\n ColumnLayoutManager.prototype.endResizing = function () {\n if (this._resizeState === null)\n return;\n var newSize = this._resizeState.getNewSize();\n this._resizeState.column.onResizeEnd(newSize);\n };\n /**\n * Sends column related data (pixel size, column count, etc) to TablixControl.\n */\n ColumnLayoutManager.prototype._sendDimensionsToControl = function () {\n var gridContextualWidth = this.getGridContextualWidth();\n var widthToFill = this.getActualContextualWidth(gridContextualWidth);\n var otherContextualHeight = this.getOtherHierarchyContextualHeight();\n var scale = this.getGridScale(); // in case of canvas we have to convert the size from device pixel to css pixel\n this.owner.owner.updateColumnDimensions(otherContextualHeight / scale, (widthToFill - otherContextualHeight) / scale, this.getViewSize(gridContextualWidth));\n };\n ColumnLayoutManager.prototype.getEstimatedHeaderWidth = function (label, headerIndex) {\n debug.assertFail(\"PureVirtualMethod: ColumnLayoutManager.getEstimatedHeaderWidth\");\n return -1;\n };\n ColumnLayoutManager.prototype.getEstimatedBodyCellWidth = function (content) {\n debug.assertFail(\"PureVirtualMethod: ColumnLayoutManager.getEstimatedBodyCellWidth\");\n return -1;\n };\n ColumnLayoutManager.minColumnWidth = 10;\n return ColumnLayoutManager;\n }(DimensionLayoutManager));\n internal.ColumnLayoutManager = ColumnLayoutManager;\n var DashboardColumnLayoutManager = (function (_super) {\n __extends(DashboardColumnLayoutManager, _super);\n function DashboardColumnLayoutManager() {\n _super.apply(this, arguments);\n }\n DashboardColumnLayoutManager.prototype.getEstimatedHeaderWidth = function (label, headerIndex) {\n if (this.ignoreColumn(headerIndex))\n return 0;\n // for dashboard layout it does not matter whether we pass an actual cell or not\n return this.owner.getCellWidth(undefined);\n };\n DashboardColumnLayoutManager.prototype.getEstimatedBodyCellWidth = function (content) {\n // for dashboard layout it does not matter whether we pass an actual cell or not\n return this.owner.getCellWidth(undefined);\n };\n DashboardColumnLayoutManager.prototype.canScroll = function (gridContextualWidth) {\n return false;\n };\n DashboardColumnLayoutManager.prototype._calculateSize = function (item) {\n var headerIndex = item.getIndex(this._grid);\n var computedSize = 0;\n if (!this.ignoreColumn(headerIndex)) {\n // for dashboard layout it does not matter whether we pass an actual cell or not\n computedSize = this.owner.getContentWidth(undefined);\n }\n item.onResize(computedSize);\n item.onResizeEnd(computedSize);\n return computedSize;\n };\n DashboardColumnLayoutManager.prototype.ignoreColumn = function (headerIndex) {\n // On the dashboard, we need to return 0 if the row header is static\n // (a table or a matrix without row groups)\n return headerIndex === 0 && !this.owner.binder.hasRowGroups();\n };\n return DashboardColumnLayoutManager;\n }(ColumnLayoutManager));\n internal.DashboardColumnLayoutManager = DashboardColumnLayoutManager;\n var CanvasColumnLayoutManager = (function (_super) {\n __extends(CanvasColumnLayoutManager, _super);\n function CanvasColumnLayoutManager() {\n _super.apply(this, arguments);\n }\n CanvasColumnLayoutManager.prototype.getEstimatedHeaderWidth = function (label, headerIndex) {\n // On the canvas the header width depends on the size of the content\n return this.owner.getEstimatedTextWidth(label);\n };\n CanvasColumnLayoutManager.prototype.getEstimatedBodyCellWidth = function (content) {\n return this.owner.getEstimatedTextWidth(content);\n };\n CanvasColumnLayoutManager.prototype.calculateContextualWidths = function () {\n var items = this._getRealizedItems();\n var columnWidths = [];\n for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {\n var item = items_1[_i];\n if (this.measureEnabled)\n item.setAligningContextualWidth(-1);\n columnWidths.push(this._calculateSize(item));\n }\n // Save all column widths. Needed when user turns off auto-sizing for column widths.\n this.owner.columnWidthsToPersist = columnWidths;\n };\n CanvasColumnLayoutManager.prototype.canScroll = function (gridContextualWidth) {\n return !powerbi.Double.equalWithPrecision(this.dimension.scrollOffset, 0, DimensionLayoutManager._scrollOffsetPrecision) ||\n (((this.getRealizedItemsCount() - this._gridOffset) < this.dimension.getItemsCount()) && this._contextualWidthToFill > 0) ||\n powerbi.Double.greaterWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\n };\n CanvasColumnLayoutManager.prototype._calculateSize = function (item) {\n return item.calculateSize();\n };\n return CanvasColumnLayoutManager;\n }(ColumnLayoutManager));\n internal.CanvasColumnLayoutManager = CanvasColumnLayoutManager;\n var RowLayoutManager = (function (_super) {\n __extends(RowLayoutManager, _super);\n function RowLayoutManager(owner, grid, realizationManager) {\n _super.call(this, owner, grid, realizationManager);\n realizationManager.owner = this;\n }\n Object.defineProperty(RowLayoutManager.prototype, \"dimension\", {\n get: function () {\n return this.owner.owner.rowDimension;\n },\n enumerable: true,\n configurable: true\n });\n RowLayoutManager.prototype.getGridScale = function () {\n return this._grid._presenter.getScreenToCssRatioY();\n };\n Object.defineProperty(RowLayoutManager.prototype, \"otherScrollbarContextualWidth\", {\n get: function () {\n if (this.dimension.otherDimension.scrollbar.visible) {\n return controls.HTMLElementUtils.getElementHeight(this.dimension.otherDimension.scrollbar.element);\n }\n return 0;\n },\n enumerable: true,\n configurable: true\n });\n RowLayoutManager.prototype.startScrollingSession = function () {\n _super.prototype.startScrollingSession.call(this);\n };\n RowLayoutManager.prototype._getRealizedItems = function () {\n if (!this._grid.realizedRows) {\n this._grid.realizedRows = [];\n }\n return this._grid.realizedRows;\n };\n RowLayoutManager.prototype._moveElementsToBottom = function (moveFromIndex, count) {\n this._grid.moveRowsToEnd(moveFromIndex, count);\n };\n RowLayoutManager.prototype._moveElementsToTop = function (moveToIndex, count) {\n this._grid.moveRowsToStart(moveToIndex, count);\n };\n RowLayoutManager.prototype._requiresMeasure = function () {\n // if the control is not scrolling in either dimension and the column dimension is not resizing or row dimension is scrolling and reaching the end while scrolling \n return (!this.isScrolling() && !this.otherLayoutManager.isScrolling() && !this.otherLayoutManager.isResizing())\n || (this.isScrolling() && (this.dimension.getIntegerScrollOffset() + (this.getRealizedItemsCount() - this._gridOffset) >= this.dimension.getItemsCount()));\n };\n RowLayoutManager.prototype.getGridContextualWidth = function () {\n return this._grid.getHeight();\n };\n RowLayoutManager.prototype.getFirstVisibleRow = function () {\n return this._grid.realizedRows[this._gridOffset];\n };\n RowLayoutManager.prototype._isAutoSized = function () {\n return this.owner.owner.autoSizeHeight;\n };\n RowLayoutManager.prototype.applyScrolling = function () {\n var rowOffset = this.dimension.getFractionScrollOffset();\n var firstVisibleRowHeight = 0;\n if (rowOffset !== 0) {\n var firstVisibleRow = this.getFirstVisibleRow();\n if (firstVisibleRow) {\n firstVisibleRowHeight = firstVisibleRow.getContextualWidth();\n this.scroll(firstVisibleRow, firstVisibleRowHeight, rowOffset);\n }\n }\n };\n RowLayoutManager.prototype.scroll = function (firstVisibleRow, height, offset) {\n this.scrollCells(firstVisibleRow._realizedRowHeaders, height, offset);\n this.scrollCells(firstVisibleRow._realizedBodyCells, height, offset);\n };\n RowLayoutManager.prototype.scrollCells = function (cells, height, offset) {\n var length = cells.length;\n for (var i = 0; i < length; i++) {\n cells[i].scrollVertically(height, offset);\n }\n };\n RowLayoutManager.prototype.getFooterContextualWidth = function () {\n if (this.owner.owner.rowDimension.hasFooter()) {\n if (this.owner.grid.footerRow) {\n return this.owner.grid.footerRow.getContextualWidth();\n }\n }\n return 0;\n };\n RowLayoutManager.prototype.calculateContextualWidths = function () {\n _super.prototype.calculateContextualWidths.call(this);\n if (this.fixedSizeEnabled) {\n var footerRow = this._grid.footerRow;\n if (footerRow) {\n this._calculateSize(footerRow);\n }\n }\n };\n RowLayoutManager.prototype.fixSizes = function () {\n _super.prototype.fixSizes.call(this);\n if (this.fixedSizeEnabled) {\n if (this._grid.footerRow) {\n this._grid.footerRow.fixSize();\n }\n }\n };\n /**\n * Sends row related data (pixel size, column count, etc) to TablixControl.\n */\n RowLayoutManager.prototype._sendDimensionsToControl = function () {\n var gridContextualWidth = this.getGridContextualWidth();\n var widthToFill = this.getActualContextualWidth(gridContextualWidth);\n var otherContextualHeight = this.getOtherHierarchyContextualHeight();\n var scale = this.getGridScale();\n this.owner.owner.updateRowDimensions(otherContextualHeight / scale, (widthToFill - otherContextualHeight) / scale, gridContextualWidth / scale, this.getViewSize(gridContextualWidth), (this._grid.footerRow ? this._grid.footerRow.getContextualWidth() / scale : 0));\n };\n RowLayoutManager.prototype.getEstimatedHeaderWidth = function (label, headerIndex) {\n debug.assertFail(\"PureVirtualMethod: RowLayoutManager.getEstimatedHeaderWidth\");\n return -1;\n };\n return RowLayoutManager;\n }(DimensionLayoutManager));\n internal.RowLayoutManager = RowLayoutManager;\n var DashboardRowLayoutManager = (function (_super) {\n __extends(DashboardRowLayoutManager, _super);\n function DashboardRowLayoutManager() {\n _super.apply(this, arguments);\n }\n DashboardRowLayoutManager.prototype.getEstimatedHeaderWidth = function (label, headerIndex) {\n return this.getHeaderWidth(headerIndex);\n };\n DashboardRowLayoutManager.prototype.canScroll = function (gridContextualWidth) {\n return false;\n };\n DashboardRowLayoutManager.prototype._calculateSize = function (item) {\n return item.calculateSize();\n };\n DashboardRowLayoutManager.prototype.getHeaderWidth = function (headerIndex) {\n // On the dashboard, we need to return 0 if the row header is static\n // (a table or a matrix without row groups)\n if (headerIndex === 0 && !this.owner.binder.hasRowGroups())\n return 0;\n // for dashboard layout it does not matter whether we pass an actual text or not\n return this.owner.getEstimatedTextWidth(undefined);\n };\n return DashboardRowLayoutManager;\n }(RowLayoutManager));\n internal.DashboardRowLayoutManager = DashboardRowLayoutManager;\n var CanvasRowLayoutManager = (function (_super) {\n __extends(CanvasRowLayoutManager, _super);\n function CanvasRowLayoutManager() {\n _super.apply(this, arguments);\n }\n CanvasRowLayoutManager.prototype.getEstimatedHeaderWidth = function (label, headerIndex) {\n // On the canvas the header width depends on the size of the content\n return this.owner.getEstimatedTextWidth(label);\n };\n CanvasRowLayoutManager.prototype.canScroll = function (gridContextualWidth) {\n return !powerbi.Double.equalWithPrecision(this.dimension.scrollOffset, 0, DimensionLayoutManager._scrollOffsetPrecision) ||\n (((this.getRealizedItemsCount() - this._gridOffset) < this.dimension.getItemsCount()) && this._contextualWidthToFill > 0) ||\n powerbi.Double.greaterWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\n };\n CanvasRowLayoutManager.prototype._calculateSize = function (item) {\n return item.calculateSize();\n };\n return CanvasRowLayoutManager;\n }(RowLayoutManager));\n internal.CanvasRowLayoutManager = CanvasRowLayoutManager;\n var TablixLayoutManager = (function () {\n function TablixLayoutManager(binder, grid, columnLayoutManager, rowLayoutManager) {\n this._allowHeaderResize = true;\n this._binder = binder;\n this._grid = grid;\n this._columnLayoutManager = columnLayoutManager;\n this._rowLayoutManager = rowLayoutManager;\n this._columnWidthsToPersist = [];\n }\n TablixLayoutManager.prototype.initialize = function (owner) {\n this._owner = owner;\n this._container = owner.container;\n this._gridHost = owner.contentHost;\n this._footersHost = owner.footerHost;\n this._grid.initialize(owner, this._gridHost, this._footersHost);\n };\n Object.defineProperty(TablixLayoutManager.prototype, \"owner\", {\n get: function () {\n return this._owner;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixLayoutManager.prototype, \"binder\", {\n get: function () {\n return this._binder;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixLayoutManager.prototype, \"columnWidthsToPersist\", {\n get: function () {\n return this._columnWidthsToPersist;\n },\n set: function (columnWidths) {\n this._columnWidthsToPersist = columnWidths;\n },\n enumerable: true,\n configurable: true\n });\n TablixLayoutManager.prototype.getTablixClassName = function () {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getTablixClassName\");\n return null;\n };\n TablixLayoutManager.prototype.getLayoutKind = function () {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getLayoutKind\");\n // TODO ckerer: this method should not be necessary when we are done refactoring!\n return null;\n };\n TablixLayoutManager.prototype.getOrCreateColumnHeader = function (item, items, rowIndex, columnIndex) {\n var hierarchyNav = this.owner.hierarchyNavigator;\n var row = this._grid.getOrCreateRow(rowIndex);\n var column = this._grid.getOrCreateColumn(columnIndex + this._columnLayoutManager._gridOffset);\n var isLeaf = hierarchyNav.isLeaf(item);\n var cell = row.getOrCreateColumnHeader(column, this._columnLayoutManager.isScrollableHeader(item, items, columnIndex), isLeaf);\n var rowIdx = hierarchyNav.getLevel(item);\n cell.position.row.index = cell.position.row.indexInSiblings = rowIdx;\n cell.position.row.isFirst = rowIdx === 0;\n cell.position.row.isLast = isLeaf;\n var colIdx = hierarchyNav.getIndex(item);\n cell.position.column.index = cell.position.row.indexInSiblings = colIdx;\n cell.position.column.isFirst = hierarchyNav.areAllParentsFirst(item, items);\n cell.position.column.isLast = hierarchyNav.areAllParentsLast(item, items);\n this.enableCellHorizontalResize(isLeaf, cell);\n return cell;\n };\n TablixLayoutManager.prototype.getOrCreateRowHeader = function (item, items, rowIndex, columnIndex) {\n var hierarchyNav = this.owner.hierarchyNavigator;\n var row = this._grid.getOrCreateRow(rowIndex + this._rowLayoutManager._gridOffset);\n var column = this._grid.getOrCreateColumn(columnIndex);\n var isLeaf = hierarchyNav.isLeaf(item);\n var scrollable = this._rowLayoutManager.isScrollableHeader(item, items, rowIndex);\n if (row.getRealizedCellCount() === 0) {\n this.alignRowHeaderCells(item, row);\n }\n var cell = row.getOrCreateRowHeader(column, scrollable, hierarchyNav.isLeaf(item));\n var rowIdx = hierarchyNav.getIndex(item);\n cell.position.row.index = cell.position.row.indexInSiblings = rowIdx;\n cell.position.row.isFirst = hierarchyNav.areAllParentsFirst(item, items);\n cell.position.row.isLast = hierarchyNav.areAllParentsLast(item, items);\n var colIdx = hierarchyNav.getLevel(item);\n cell.position.column.index = cell.position.column.indexInSiblings = colIdx;\n cell.position.column.isFirst = colIdx === 0;\n cell.position.column.isLast = isLeaf;\n cell.enableHorizontalResize(false, this._columnLayoutManager);\n return cell;\n };\n TablixLayoutManager.prototype.getOrCreateCornerCell = function (item, rowLevel, columnLevel) {\n var row = this._grid.getOrCreateRow(columnLevel);\n var column = this._grid.getOrCreateColumn(rowLevel);\n var columnDepth = this._columnLayoutManager.dimension.getDepth();\n var isLeaf = columnLevel === (columnDepth - 1);\n var cell = row.getOrCreateCornerCell(column);\n var rowIdx = columnLevel;\n cell.position.row.index = cell.position.row.indexInSiblings = rowIdx;\n cell.position.row.isFirst = rowIdx === 0;\n cell.position.row.isLast = isLeaf;\n var colIdx = rowLevel;\n cell.position.column.index = cell.position.column.indexInSiblings = colIdx;\n cell.position.column.isFirst = colIdx === 0;\n cell.position.column.isLast = colIdx === this._rowLayoutManager.dimension.getDepth() - 1;\n this.enableCellHorizontalResize(isLeaf, cell);\n return cell;\n };\n TablixLayoutManager.prototype.getOrCreateBodyCell = function (cellItem, rowItem, rowItems, rowIndex, columnIndex) {\n var scrollable;\n var row = this._grid.getOrCreateRow(rowIndex + this._rowLayoutManager._gridOffset);\n var column = this._grid.getOrCreateColumn(columnIndex + this._columnLayoutManager._gridOffset);\n if (row._realizedBodyCells.length === 0 && this._owner.columnDimension.getFractionScrollOffset() !== 0) {\n scrollable = true;\n }\n else {\n scrollable = this._rowLayoutManager.isScrollableHeader(rowItem, rowItems, rowIndex);\n }\n var cell = row.getOrCreateBodyCell(column, scrollable);\n cell.position = cellItem.position;\n cell.enableHorizontalResize(false, this._columnLayoutManager);\n return cell;\n };\n TablixLayoutManager.prototype.getOrCreateFooterBodyCell = function (cellItem, columnIndex) {\n var scrollable;\n var row = this._grid.getOrCreateFootersRow();\n var column = this._grid.getOrCreateColumn(columnIndex + this._columnLayoutManager._gridOffset);\n scrollable = (row._realizedBodyCells.length === 0 && this._owner.columnDimension.getFractionScrollOffset() !== 0);\n var cell = row.getOrCreateFooterBodyCell(column, scrollable);\n cell.position = cellItem.position;\n cell.enableHorizontalResize(false, this._columnLayoutManager);\n return cell;\n };\n TablixLayoutManager.prototype.getOrCreateFooterRowHeader = function (item, items) {\n var row = this._grid.getOrCreateFootersRow();\n var column = this._grid.getOrCreateColumn(0);\n //debug.assert(this.owner.hierarchyNavigator.isLeaf(item), \"Leaf item expected\");\n var cell = row.getOrCreateFooterRowHeader(column);\n cell.position = undefined;\n cell.enableHorizontalResize(false, this._columnLayoutManager);\n return cell;\n };\n TablixLayoutManager.prototype.getVisibleWidth = function () {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getVisibleWidth\");\n return -1;\n };\n TablixLayoutManager.prototype.getVisibleHeight = function () {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getVisibleHeight\");\n return -1;\n };\n TablixLayoutManager.prototype.updateColumnCount = function (rowDimension, columnDimension) {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.updateColumnCount\");\n };\n TablixLayoutManager.prototype.updateViewport = function (viewport) {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.updateViewport\");\n };\n TablixLayoutManager.prototype.getEstimatedRowHeight = function () {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getEstimatedRowHeight\");\n return -1;\n };\n TablixLayoutManager.prototype.getCellWidth = function (cell) {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getCellWidth\");\n return -1;\n };\n TablixLayoutManager.prototype.getContentWidth = function (cell) {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getContentWidth\");\n return -1;\n };\n TablixLayoutManager.prototype.adjustContentSize = function (hasImage) {\n // default implementation has no adjustment\n };\n /**\n * This call makes room for parent header cells where neccessary.\n * Since HTML cells that span vertically displace other rows,\n * room has to be made for spanning headers that leave an exiting\n * row to enter the new row that it starts from and removed when\n * returning to an entering row.\n */\n TablixLayoutManager.prototype.alignRowHeaderCells = function (item, currentRow) {\n var index = currentRow.getRowHeaderLeafIndex();\n if (index === -1) {\n return;\n }\n var rowDimension = this._owner.rowDimension;\n var leaf = rowDimension.getFirstVisibleChildLeaf(item);\n if (!this.owner.hierarchyNavigator.headerItemEquals(leaf, currentRow.getAllocatedCellAt(index).item)) {\n return;\n }\n currentRow.moveCellsBy(this.owner.hierarchyNavigator.getLevel(leaf) - this.owner.hierarchyNavigator.getLevel(item) - index);\n };\n Object.defineProperty(TablixLayoutManager.prototype, \"grid\", {\n get: function () {\n return this._grid;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixLayoutManager.prototype, \"rowLayoutManager\", {\n get: function () {\n return this._rowLayoutManager;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixLayoutManager.prototype, \"columnLayoutManager\", {\n get: function () {\n return this._columnLayoutManager;\n },\n enumerable: true,\n configurable: true\n });\n TablixLayoutManager.prototype.showEmptySpaceHeader = function () {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.showEmptySpaceHeader\");\n return false;\n };\n TablixLayoutManager.prototype.onStartRenderingSession = function (scrollingDimension, parentElement, clear) {\n if (this.showEmptySpaceHeader()) {\n var cell = this._grid.emptySpaceHeaderCell;\n if (cell) {\n this._binder.unbindEmptySpaceHeaderCell(cell);\n }\n cell = this._grid.emptySpaceFooterCell;\n if (cell) {\n this._binder.unbindEmptySpaceFooterCell(cell);\n }\n this._grid.HideEmptySpaceCells();\n }\n this._scrollingDimension = scrollingDimension;\n if (this._scrollingDimension) {\n this._scrollingDimension.layoutManager.startScrollingSession();\n }\n this._rowLayoutManager.onStartRenderingSession();\n this._columnLayoutManager.onStartRenderingSession();\n this._grid.onStartRenderingSession(clear);\n var measureEnabled = this._columnLayoutManager.measureEnabled || this._rowLayoutManager.measureEnabled;\n if (measureEnabled)\n this.measureSampleText(parentElement);\n };\n TablixLayoutManager.prototype.onEndRenderingSession = function () {\n this._rowLayoutManager.onEndRenderingSession();\n this._columnLayoutManager.onEndRenderingSession();\n if (this._scrollingDimension) {\n this._scrollingDimension.layoutManager.endScrollingSession();\n }\n this._scrollingDimension = null;\n if (this.showEmptySpaceHeader()) {\n var emptySpace = this._columnLayoutManager.contextualWidthToFill - this._columnLayoutManager.getGridContextualWidth();\n if (emptySpace > 0) {\n this._grid.ShowEmptySpaceCells(this._owner.columnDimension.getDepth(), emptySpace);\n var cell = this._grid.emptySpaceHeaderCell;\n if (cell) {\n this._binder.bindEmptySpaceHeaderCell(cell);\n }\n cell = this._grid.emptySpaceFooterCell;\n if (cell) {\n this._binder.bindEmptySpaceFooterCell(cell);\n }\n }\n }\n };\n TablixLayoutManager.prototype.onStartRenderingIteration = function (clear) {\n this._rowLayoutManager.onStartRenderingIteration(clear, this.getVisibleHeight());\n this._columnLayoutManager.onStartRenderingIteration(clear, this.getVisibleWidth());\n this._grid.onStartRenderingIteration();\n };\n TablixLayoutManager.prototype.onEndRenderingIteration = function () {\n this._grid.onEndRenderingIteration();\n // ANDREMI: Comment out for static tablix\n this._columnLayoutManager.calculateSizes(); // calculate the entire grid first without altering the tree to avoid multiple measure pass invoking\n this._rowLayoutManager.calculateSizes();\n this._columnLayoutManager.fixSizes(); // now assign the sizes\n this._rowLayoutManager.fixSizes();\n this._columnLayoutManager.updateItemToResizeState(this._grid.realizedColumns); // if we are in a middle of a resize, the column to resize might have been swaped during the render, restore its resize state\n this._columnLayoutManager.applyScrolling();\n this._rowLayoutManager.applyScrolling();\n this._columnLayoutManager.onEndRenderingIteration();\n this._rowLayoutManager.onEndRenderingIteration();\n return this._columnLayoutManager.done && this._rowLayoutManager.done;\n };\n TablixLayoutManager.prototype.onCornerCellRealized = function (item, cell) {\n var columnLeaf = this.owner.hierarchyNavigator.isColumnHierarchyLeaf(item);\n var rowLeaf = this.owner.hierarchyNavigator.isRowHierarchyLeaf(item);\n if (columnLeaf)\n cell._column.OnLeafRealized(this._owner.hierarchyNavigator);\n this._columnLayoutManager.onCornerCellRealized(item, cell, columnLeaf);\n this._rowLayoutManager.onCornerCellRealized(item, cell, rowLeaf);\n };\n TablixLayoutManager.prototype.onRowHeaderRealized = function (item, cell) {\n var hierarchyNavigator = this._owner.hierarchyNavigator;\n var leaf = hierarchyNavigator.isLeaf(item);\n var tablixCell = cell;\n if (tablixCell.colSpan > 1)\n tablixCell.setContainerWidth(-1);\n this._rowLayoutManager.onHeaderRealized(item, cell, leaf);\n };\n TablixLayoutManager.prototype.onRowHeaderFooterRealized = function (item, cell) {\n };\n TablixLayoutManager.prototype.onColumnHeaderRealized = function (item, cell) {\n var hierarchyNavigator = this._owner.hierarchyNavigator;\n var leaf = hierarchyNavigator.isLeaf(item);\n if (leaf)\n cell._column.OnLeafRealized(this._owner.hierarchyNavigator);\n this._columnLayoutManager.onHeaderRealized(item, cell, leaf);\n };\n TablixLayoutManager.prototype.onBodyCellRealized = function (item, cell) {\n };\n TablixLayoutManager.prototype.onBodyCellFooterRealized = function (item, cell) {\n };\n TablixLayoutManager.prototype.setAllowHeaderResize = function (value) {\n this._allowHeaderResize = value;\n };\n TablixLayoutManager.prototype.enableCellHorizontalResize = function (isLeaf, cell) {\n var enableCellHorizontalResize = isLeaf && this._allowHeaderResize;\n cell.enableHorizontalResize(enableCellHorizontalResize, this._columnLayoutManager);\n };\n TablixLayoutManager.prototype.getEstimatedTextWidth = function (label) {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getEstimatedTextWidth\");\n return -1;\n };\n TablixLayoutManager.prototype.measureSampleText = function (parentElement) {\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.measureSampleText\");\n };\n return TablixLayoutManager;\n }());\n internal.TablixLayoutManager = TablixLayoutManager;\n var DashboardTablixLayoutManager = (function (_super) {\n __extends(DashboardTablixLayoutManager, _super);\n function DashboardTablixLayoutManager(binder, sizeComputationManager, grid, rowRealizationManager, columnRealizationManager) {\n var dashboardColumnLayoutManager = new DashboardColumnLayoutManager(null, grid, columnRealizationManager);\n var dashboardRowLayoutManager = new DashboardRowLayoutManager(null, grid, rowRealizationManager);\n _super.call(this, binder, grid, dashboardColumnLayoutManager, dashboardRowLayoutManager);\n dashboardColumnLayoutManager.owner = this;\n dashboardRowLayoutManager.owner = this;\n this._sizeComputationManager = sizeComputationManager;\n }\n DashboardTablixLayoutManager.createLayoutManager = function (binder) {\n // computed sizes are shared between layout manager and grid presenter\n var sizeComputationManager = new SizeComputationManager();\n return new DashboardTablixLayoutManager(binder, sizeComputationManager, new internal.TablixGrid(new internal.DashboardTablixGridPresenter(sizeComputationManager)), new internal.RowRealizationManager(binder), new internal.ColumnRealizationManager(binder));\n };\n DashboardTablixLayoutManager.prototype.getTablixClassName = function () {\n return \"tablixDashboard\";\n };\n DashboardTablixLayoutManager.prototype.getLayoutKind = function () {\n return 1 /* DashboardTile */;\n };\n DashboardTablixLayoutManager.prototype.showEmptySpaceHeader = function () {\n return false;\n };\n DashboardTablixLayoutManager.prototype.measureSampleText = function (parentElement) {\n var textProperties = powerbi.TextMeasurementService.getSvgMeasurementProperties(parentElement);\n this._characterHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(textProperties);\n this._sizeComputationManager.updateRowHeight(this._characterHeight);\n var actualTextSize = PixelConverter.toPoint(parseFloat(textProperties.fontSize));\n var scalingFactor = actualTextSize / controls.TablixDefaultTextSize;\n this._sizeComputationManager.updateScalingFactor(powerbi.Double.toIncrement(scalingFactor, 0.05));\n };\n DashboardTablixLayoutManager.prototype.getVisibleWidth = function () {\n return this._sizeComputationManager.visibleWidth;\n };\n DashboardTablixLayoutManager.prototype.getVisibleHeight = function () {\n return this._sizeComputationManager.visibleHeight;\n };\n DashboardTablixLayoutManager.prototype.getCellWidth = function (cell) {\n return this._sizeComputationManager.cellWidth;\n };\n DashboardTablixLayoutManager.prototype.getContentWidth = function (cell) {\n return this._sizeComputationManager.contentWidth;\n };\n DashboardTablixLayoutManager.prototype.getEstimatedTextWidth = function (label) {\n // On the dashboard it does not matter what text we render, \n // we always use the same content width\n return this._sizeComputationManager.contentWidth;\n };\n DashboardTablixLayoutManager.prototype.adjustContentSize = function (hasImage) {\n this._sizeComputationManager.hasImageContent = hasImage;\n };\n DashboardTablixLayoutManager.prototype.updateColumnCount = function (rowDimension, columnDimension) {\n // The total number of columns is the number (depth) of row groups + the number of (leaf) column group instances\n var rowDimensionDepth = rowDimension ? rowDimension.getDepth() : 0;\n var columnInstances = columnDimension ? columnDimension.getItemsCount() : 0;\n var totalColumnCount = rowDimensionDepth + columnInstances;\n // Adjust the column count by the static row header (if any)\n if (!this.binder.hasRowGroups())\n totalColumnCount--;\n this._sizeComputationManager.updateColumnCount(totalColumnCount);\n };\n DashboardTablixLayoutManager.prototype.updateViewport = function (viewport) {\n this._sizeComputationManager.updateViewport(viewport);\n };\n DashboardTablixLayoutManager.prototype.getEstimatedRowHeight = function () {\n return this._characterHeight;\n };\n return DashboardTablixLayoutManager;\n }(TablixLayoutManager));\n internal.DashboardTablixLayoutManager = DashboardTablixLayoutManager;\n var CanvasTablixLayoutManager = (function (_super) {\n __extends(CanvasTablixLayoutManager, _super);\n function CanvasTablixLayoutManager(binder, grid, rowRealizationManager, columnRealizationManager) {\n var canvasColumnLayoutManager = new CanvasColumnLayoutManager(null, grid, columnRealizationManager);\n var canvasRowLayoutManager = new CanvasRowLayoutManager(null, grid, rowRealizationManager);\n _super.call(this, binder, grid, canvasColumnLayoutManager, canvasRowLayoutManager);\n canvasColumnLayoutManager.owner = this;\n canvasRowLayoutManager.owner = this;\n }\n CanvasTablixLayoutManager.createLayoutManager = function (binder, columnWidthManager) {\n return new CanvasTablixLayoutManager(binder, new internal.TablixGrid(new controls.internal.CanvasTablixGridPresenter(columnWidthManager)), new internal.RowRealizationManager(binder), new internal.ColumnRealizationManager(binder));\n };\n CanvasTablixLayoutManager.prototype.getTablixClassName = function () {\n return \"tablixCanvas\";\n };\n CanvasTablixLayoutManager.prototype.getLayoutKind = function () {\n return 0 /* Canvas */;\n };\n CanvasTablixLayoutManager.prototype.measureSampleText = function (parentElement) {\n // TODO: Use TextMeasurementService once the DOM methods are fixed (they are not working right now)\n var textDiv = controls.internal.TablixUtils.createDiv();\n textDiv.style.cssFloat = 'left';\n textDiv.style.whiteSpace = 'nowrap';\n textDiv.style.overflow = 'hidden';\n textDiv.style.lineHeight = 'normal';\n parentElement.appendChild(textDiv);\n var textNode = document.createTextNode(\"a\");\n textDiv.appendChild(textNode);\n this.characterWidth = controls.HTMLElementUtils.getElementWidth(textDiv);\n this.characterHeight = controls.HTMLElementUtils.getElementHeight(textDiv);\n textDiv.removeChild(textNode);\n parentElement.removeChild(textDiv);\n };\n CanvasTablixLayoutManager.prototype.showEmptySpaceHeader = function () {\n return !this._columnLayoutManager.fillProportionally;\n };\n CanvasTablixLayoutManager.prototype.getVisibleWidth = function () {\n if (this._columnLayoutManager.measureEnabled) {\n if (this._owner.autoSizeWidth && this._owner.maxWidth) {\n return this._owner.maxWidth;\n }\n else {\n return controls.HTMLElementUtils.getElementWidth(this._container);\n }\n }\n return -1;\n };\n CanvasTablixLayoutManager.prototype.getVisibleHeight = function () {\n if (this._rowLayoutManager.measureEnabled) {\n if (this._owner.autoSizeHeight && this._owner.maxHeight) {\n return this._owner.maxHeight;\n }\n else {\n return controls.HTMLElementUtils.getElementHeight(this._container);\n }\n }\n return -1;\n };\n CanvasTablixLayoutManager.prototype.getCellWidth = function (cell) {\n return controls.HTMLElementUtils.getElementWidth(cell._presenter.tableCell);\n };\n CanvasTablixLayoutManager.prototype.getContentWidth = function (cell) {\n return controls.HTMLElementUtils.getElementWidth(cell._presenter.contentElement);\n };\n CanvasTablixLayoutManager.prototype.getEstimatedTextWidth = function (text) {\n return text ? text.length * this.characterWidth : 0;\n };\n CanvasTablixLayoutManager.prototype.updateColumnCount = function (rowDimension, columnDimension) {\n // We currently only need to update model information when using dashboard layouts\n };\n CanvasTablixLayoutManager.prototype.updateViewport = function (viewport) {\n // We currently only need to update model information when using dashboard layouts\n };\n CanvasTablixLayoutManager.prototype.getEstimatedRowHeight = function () {\n return this.characterHeight;\n };\n return CanvasTablixLayoutManager;\n }(TablixLayoutManager));\n internal.CanvasTablixLayoutManager = CanvasTablixLayoutManager;\n })(internal = controls.internal || (controls.internal = {}));\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var HTMLElementUtils;\n (function (HTMLElementUtils) {\n function clearChildren(element) {\n if (!element) {\n return;\n }\n while (element.hasChildNodes()) {\n element.removeChild(element.firstChild);\n }\n }\n HTMLElementUtils.clearChildren = clearChildren;\n function setElementTop(element, top) {\n element.style.top = top + \"px\";\n }\n HTMLElementUtils.setElementTop = setElementTop;\n function setElementLeft(element, left) {\n element.style.left = left + \"px\";\n }\n HTMLElementUtils.setElementLeft = setElementLeft;\n function setElementHeight(element, height) {\n if (HTMLElementUtils.isAutoSize(height))\n element.style.height = \"\";\n else\n element.style.height = height + \"px\";\n }\n HTMLElementUtils.setElementHeight = setElementHeight;\n function setElementWidth(element, width) {\n if (HTMLElementUtils.isAutoSize(width))\n element.style.width = \"\";\n else\n element.style.width = width + \"px\";\n }\n HTMLElementUtils.setElementWidth = setElementWidth;\n function getElementWidth(element) {\n return element.offsetWidth;\n }\n HTMLElementUtils.getElementWidth = getElementWidth;\n function getElementHeight(element) {\n return element.offsetHeight;\n }\n HTMLElementUtils.getElementHeight = getElementHeight;\n function isAutoSize(size) {\n return size === -1;\n }\n HTMLElementUtils.isAutoSize = isAutoSize;\n function getAccumulatedScale(element) {\n var scale = 1;\n while (element) {\n scale *= HTMLElementUtils.getScale(element);\n element = element.parentElement;\n }\n return scale;\n }\n HTMLElementUtils.getAccumulatedScale = getAccumulatedScale;\n /**\n * Get scale of element, return 1 when not scaled.\n */\n function getScale(element) {\n element = $(element);\n var str = element.css('-webkit-transform') ||\n element.css('-moz-transform') ||\n element.css('-ms-transform') ||\n element.css('-o-transform') ||\n element.css('transform');\n return (str && (str.match(/\\d*\\.\\d*/) && Number(str.match(/\\d*\\.\\d*/)[0]) ||\n str.match(/\\d+/) && Number(str.match(/\\d+/)[0]))) || 1;\n }\n HTMLElementUtils.getScale = getScale;\n })(HTMLElementUtils = controls.HTMLElementUtils || (controls.HTMLElementUtils = {}));\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var internal;\n (function (internal) {\n var DomFactory = InJs.DomFactory;\n var DataViewObjectDefinitions = powerbi.data.DataViewObjectDefinitions;\n var DataViewRoleWildCard = powerbi.data.DataViewRoleWildcard;\n var TablixObjects;\n (function (TablixObjects) {\n TablixObjects.ObjectGeneral = \"general\";\n TablixObjects.ObjectGrid = \"grid\";\n TablixObjects.ObjectColumnHeaders = \"columnHeaders\";\n TablixObjects.ObjectRowHeaders = \"rowHeaders\";\n TablixObjects.ObjectValues = \"values\";\n TablixObjects.ObjectTotal = \"total\";\n TablixObjects.ObjectSubTotals = \"subTotals\";\n /**\n * Represents a DataViewObjects property related to the Tablix\n */\n var TablixProperty = (function () {\n /**\n * Creates a new TablixProperty\n * @param {string} objectName Object Name\n * @param {string} propertyName Property Name\n * @param {any} defaultValue Default value of the Property\n * @param {ObjectValueGetterFunction} getterFuntion Function used to get the Property value from the Objects\n */\n function TablixProperty(objectName, propertyName, defaultValue, getterFuntion) {\n this.objectName = objectName;\n this.propertyName = propertyName;\n this.defaultValue = defaultValue;\n this.getterFuntion = getterFuntion;\n }\n /**\n * Gets the PropertyIdentifier for the Property\n * @returns PropertyIdentifier for the Property\n */\n TablixProperty.prototype.getPropertyID = function () {\n return { objectName: this.objectName, propertyName: this.propertyName };\n };\n /**\n * Gets the value of the Property from the Objects\n * @param {DataViewObjects} objects DataView Objects to get the value from\n * @param {boolean} useDefault True to fall back to the Default value if the Property is missing from the objects. False to return undefined\n * @returns Value of the property\n */\n TablixProperty.prototype.getValue = function (objects) {\n // We use this when we intend to have undefined for missing properties. Useful in letting styles fallback to CSS if not defined\n return this.getterFuntion(objects, this.getPropertyID(), this.defaultValue);\n };\n return TablixProperty;\n }());\n TablixObjects.TablixProperty = TablixProperty;\n // Per Column\n TablixObjects.PropColumnFormatString = new TablixProperty(TablixObjects.ObjectGeneral, 'formatString', undefined, powerbi.DataViewObjects.getValue);\n // General\n TablixObjects.PropGeneralAutoSizeColumns = new TablixProperty(TablixObjects.ObjectGeneral, 'autoSizeColumnWidth', true, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGeneralTextSize = new TablixProperty(TablixObjects.ObjectGeneral, 'textSize', 8, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGeneralTableTotals = new TablixProperty(TablixObjects.ObjectGeneral, 'totals', true, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGeneralMatrixRowSubtotals = new TablixProperty(TablixObjects.ObjectGeneral, 'rowSubtotals', true, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGeneralMatrixColumnSubtotals = new TablixProperty(TablixObjects.ObjectGeneral, 'columnSubtotals', true, powerbi.DataViewObjects.getValue);\n //Grid\n TablixObjects.PropGridVertical = new TablixProperty(TablixObjects.ObjectGrid, 'gridVertical', false, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGridVerticalColor = new TablixProperty(TablixObjects.ObjectGrid, 'gridVerticalColor', \"#E8E8E8\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropGridVerticalWeight = new TablixProperty(TablixObjects.ObjectGrid, 'gridVerticalWeight', 1, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGridHorizontalTable = new TablixProperty(TablixObjects.ObjectGrid, 'gridHorizontal', true, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGridHorizontalMatrix = new TablixProperty(TablixObjects.ObjectGrid, 'gridHorizontal', false, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGridHorizontalColor = new TablixProperty(TablixObjects.ObjectGrid, 'gridHorizontalColor', \"#E8E8E8\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropGridHorizontalWeight = new TablixProperty(TablixObjects.ObjectGrid, 'gridHorizontalWeight', 1, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGridRowPadding = new TablixProperty(TablixObjects.ObjectGrid, 'rowPadding', 0, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGridOutlineColor = new TablixProperty(TablixObjects.ObjectGrid, 'outlineColor', \"#CCC\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropGridOutlineWeight = new TablixProperty(TablixObjects.ObjectGrid, 'outlineWeight', 1, powerbi.DataViewObjects.getValue);\n TablixObjects.PropGridImageHeight = new TablixProperty(TablixObjects.ObjectGrid, 'imageHeight', 75, powerbi.DataViewObjects.getValue);\n // Column Headers\n TablixObjects.PropColumnsFontColor = new TablixProperty(TablixObjects.ObjectColumnHeaders, 'fontColor', \"#666\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropColumnsBackColor = new TablixProperty(TablixObjects.ObjectColumnHeaders, 'backColor', undefined, powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropColumnsOutline = new TablixProperty(TablixObjects.ObjectColumnHeaders, 'outline', \"BottomOnly\", powerbi.DataViewObjects.getValue);\n // Row Headers\n TablixObjects.PropRowsFontColor = new TablixProperty(TablixObjects.ObjectRowHeaders, 'fontColor', \"#666\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropRowsBackColor = new TablixProperty(TablixObjects.ObjectRowHeaders, 'backColor', undefined, powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropRowsOutline = new TablixProperty(TablixObjects.ObjectRowHeaders, 'outline', \"RightOnly\", powerbi.DataViewObjects.getValue);\n // Values\n TablixObjects.PropValuesBackColor = new TablixProperty(TablixObjects.ObjectValues, 'backColor', undefined, powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropValuesFontColorPrimary = new TablixProperty(TablixObjects.ObjectValues, 'fontColorPrimary', \"#333\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropValuesBackColorPrimary = new TablixProperty(TablixObjects.ObjectValues, 'backColorPrimary', undefined, powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropValuesFontColorSecondary = new TablixProperty(TablixObjects.ObjectValues, 'fontColorSecondary', \"#333\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropValuesBackColorSecondary = new TablixProperty(TablixObjects.ObjectValues, 'backColorSecondary', undefined, powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropValuesOutline = new TablixProperty(TablixObjects.ObjectValues, 'outline', \"None\", powerbi.DataViewObjects.getValue);\n TablixObjects.PropValuesUrlIconProp = new TablixProperty(TablixObjects.ObjectValues, 'urlIcon', false, powerbi.DataViewObjects.getValue);\n // Total\n TablixObjects.PropTotalFontColor = new TablixProperty(TablixObjects.ObjectTotal, 'fontColor', \"#333\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropTotalBackColor = new TablixProperty(TablixObjects.ObjectTotal, 'backColor', undefined, powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropTotalOutline = new TablixProperty(TablixObjects.ObjectTotal, 'outline', \"TopOnly\", powerbi.DataViewObjects.getValue);\n // SubTotals\n TablixObjects.PropSubTotalsFontColor = new TablixProperty(TablixObjects.ObjectSubTotals, 'fontColor', \"#333\", powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropSubTotalsBackColor = new TablixProperty(TablixObjects.ObjectSubTotals, 'backColor', undefined, powerbi.DataViewObjects.getFillColor);\n TablixObjects.PropSubTotalsOutline = new TablixProperty(TablixObjects.ObjectSubTotals, 'outline', \"TopOnly\", powerbi.DataViewObjects.getValue);\n /**\n * Get the DataViewObject from the DataView\n * @param {DataView} dataview The DataView\n * @returns DataViewObjects (dataView.metadata.objects)\n */\n function getMetadadataObjects(dataview) {\n if (dataview && dataview.metadata)\n return dataview.metadata.objects;\n return null;\n }\n TablixObjects.getMetadadataObjects = getMetadadataObjects;\n function enumerateObjectRepetition(enumeration, dataView, tablixType) {\n debug.assertValue(enumeration, 'enumeration should be defined');\n debug.assertValue(dataView, \"dataView can't be undefined\");\n // We currently only support Table\n if (tablixType !== controls.TablixType.Table)\n return;\n var columns = getTableColumnMetadata(dataView);\n for (var _i = 0, columns_1 = columns; _i < columns_1.length; _i++) {\n var column = columns_1[_i];\n var repetition = {\n selector: {\n data: [DataViewRoleWildCard.fromRoles(['Values'])],\n metadata: column.queryName,\n },\n objects: (_a = {},\n _a[TablixObjects.ObjectValues] = {\n formattingProperties: [TablixObjects.PropValuesBackColor.propertyName]\n },\n _a\n )\n };\n enumeration.push(repetition);\n }\n var _a;\n }\n TablixObjects.enumerateObjectRepetition = enumerateObjectRepetition;\n function enumerateObjectInstances(options, enumeration, dataView, tablixType) {\n debug.assertValue(dataView, \"dataView can't be undefined\");\n var objects = getMetadadataObjects(dataView);\n var totalsShown = true;\n if (tablixType === controls.TablixType.Table) {\n totalsShown = shouldShowTableTotalsOption(dataView) && shouldShowTableTotals(objects);\n }\n else {\n totalsShown =\n (shouldShowColumnSubtotalsOption(dataView) && shouldShowColumnSubtotals(objects)) ||\n (shouldShowRowSubtotalsOption(dataView) && shouldShowRowSubtotals(objects));\n }\n switch (options.objectName) {\n case TablixObjects.ObjectGeneral:\n enumerateGeneralOptions(enumeration, objects, tablixType, dataView);\n break;\n case TablixObjects.ObjectGrid:\n enumerateGridOptions(enumeration, objects, tablixType);\n break;\n case TablixObjects.ObjectColumnHeaders:\n enumerateColumnHeadersOptions(enumeration, objects);\n break;\n case TablixObjects.ObjectRowHeaders:\n enumerateRowHeadersOptions(enumeration, objects);\n break;\n case TablixObjects.ObjectValues:\n enumerateValuesOptions(enumeration, objects, tablixType);\n break;\n case TablixObjects.ObjectTotal:\n if (totalsShown)\n enumerateTotalOptions(enumeration, objects);\n break;\n case TablixObjects.ObjectSubTotals:\n if (totalsShown)\n enumerateSubTotalsOptions(enumeration, objects);\n break;\n default:\n break;\n }\n }\n TablixObjects.enumerateObjectInstances = enumerateObjectInstances;\n function enumerateGeneralOptions(enumeration, objects, tablixType, dataView) {\n var visualObjectinstance = {\n selector: null,\n objectName: TablixObjects.ObjectGeneral,\n properties: {\n autoSizeColumnWidth: TablixObjects.PropGeneralAutoSizeColumns.getValue(objects),\n textSize: TablixObjects.PropGeneralTextSize.getValue(objects),\n }\n };\n var properties = visualObjectinstance.properties;\n // Total and SubTotals\n switch (tablixType) {\n case controls.TablixType.Table:\n if (shouldShowTableTotalsOption(dataView))\n properties[TablixObjects.PropGeneralTableTotals.propertyName] = shouldShowTableTotals(objects);\n break;\n case controls.TablixType.Matrix:\n if (shouldShowRowSubtotalsOption(dataView))\n properties[TablixObjects.PropGeneralMatrixRowSubtotals.propertyName] = shouldShowRowSubtotals(objects);\n if (shouldShowColumnSubtotalsOption(dataView))\n properties[TablixObjects.PropGeneralMatrixColumnSubtotals.propertyName] = shouldShowColumnSubtotals(objects);\n break;\n }\n enumeration.pushInstance(visualObjectinstance);\n }\n TablixObjects.enumerateGeneralOptions = enumerateGeneralOptions;\n function enumerateGridOptions(enumeration, objects, tablixType) {\n var visualObjectinstance = {\n selector: null,\n objectName: TablixObjects.ObjectGeneral,\n properties: {}\n };\n var properties = visualObjectinstance.properties;\n // Vertical Grid\n var verticalGridEnabled = TablixObjects.PropGridVertical.getValue(objects);\n properties[TablixObjects.PropGridVertical.propertyName] = verticalGridEnabled;\n if (verticalGridEnabled) {\n properties[TablixObjects.PropGridVerticalColor.propertyName] = TablixObjects.PropGridVerticalColor.getValue(objects);\n properties[TablixObjects.PropGridVerticalWeight.propertyName] = TablixObjects.PropGridVerticalWeight.getValue(objects);\n }\n // Horizontal Grid\n var horizontalGridEnabled = (tablixType === controls.TablixType.Table ? TablixObjects.PropGridHorizontalTable : TablixObjects.PropGridHorizontalMatrix).getValue(objects);\n properties[(tablixType === controls.TablixType.Table ? TablixObjects.PropGridHorizontalTable : TablixObjects.PropGridHorizontalMatrix).propertyName] = horizontalGridEnabled;\n if (horizontalGridEnabled) {\n properties[TablixObjects.PropGridHorizontalColor.propertyName] = TablixObjects.PropGridHorizontalColor.getValue(objects);\n properties[TablixObjects.PropGridHorizontalWeight.propertyName] = TablixObjects.PropGridHorizontalWeight.getValue(objects);\n }\n // Row Padding\n properties[TablixObjects.PropGridRowPadding.propertyName] = TablixObjects.PropGridRowPadding.getValue(objects);\n // Outline\n properties[TablixObjects.PropGridOutlineColor.propertyName] = TablixObjects.PropGridOutlineColor.getValue(objects);\n properties[TablixObjects.PropGridOutlineWeight.propertyName] = TablixObjects.PropGridOutlineWeight.getValue(objects);\n // Image Height\n properties[TablixObjects.PropGridImageHeight.propertyName] = TablixObjects.PropGridImageHeight.getValue(objects);\n enumeration.pushInstance(visualObjectinstance);\n }\n TablixObjects.enumerateGridOptions = enumerateGridOptions;\n function enumerateColumnHeadersOptions(enumeration, objects) {\n enumeration.pushInstance({\n selector: null,\n objectName: TablixObjects.ObjectColumnHeaders,\n properties: {\n fontColor: TablixObjects.PropColumnsFontColor.getValue(objects),\n backColor: TablixObjects.PropColumnsBackColor.getValue(objects),\n outline: TablixObjects.PropColumnsOutline.getValue(objects),\n }\n });\n }\n TablixObjects.enumerateColumnHeadersOptions = enumerateColumnHeadersOptions;\n function enumerateRowHeadersOptions(enumeration, objects) {\n enumeration.pushInstance({\n selector: null,\n objectName: TablixObjects.ObjectRowHeaders,\n properties: {\n fontColor: TablixObjects.PropRowsFontColor.getValue(objects),\n backColor: TablixObjects.PropRowsBackColor.getValue(objects),\n outline: TablixObjects.PropRowsOutline.getValue(objects),\n }\n });\n }\n TablixObjects.enumerateRowHeadersOptions = enumerateRowHeadersOptions;\n function enumerateValuesOptions(enumeration, objects, tablixType) {\n var instance = {\n selector: null,\n objectName: TablixObjects.ObjectValues,\n properties: {\n fontColorPrimary: TablixObjects.PropValuesFontColorPrimary.getValue(objects),\n backColorPrimary: TablixObjects.PropValuesBackColorPrimary.getValue(objects),\n fontColorSecondary: TablixObjects.PropValuesFontColorSecondary.getValue(objects),\n backColorSecondary: TablixObjects.PropValuesBackColorSecondary.getValue(objects),\n outline: TablixObjects.PropValuesOutline.getValue(objects),\n }\n };\n if (tablixType === controls.TablixType.Table)\n instance.properties[TablixObjects.PropValuesUrlIconProp.propertyName] = TablixObjects.PropValuesUrlIconProp.getValue(objects);\n enumeration.pushInstance(instance);\n }\n TablixObjects.enumerateValuesOptions = enumerateValuesOptions;\n function enumerateTotalOptions(enumeration, objects) {\n enumeration.pushInstance({\n selector: null,\n objectName: TablixObjects.ObjectTotal,\n properties: {\n fontColor: TablixObjects.PropTotalFontColor.getValue(objects),\n backColor: TablixObjects.PropTotalBackColor.getValue(objects),\n outline: TablixObjects.PropTotalOutline.getValue(objects),\n }\n });\n }\n TablixObjects.enumerateTotalOptions = enumerateTotalOptions;\n function enumerateSubTotalsOptions(enumeration, objects) {\n enumeration.pushInstance({\n selector: null,\n objectName: TablixObjects.ObjectSubTotals,\n properties: {\n fontColor: TablixObjects.PropSubTotalsFontColor.getValue(objects),\n backColor: TablixObjects.PropSubTotalsBackColor.getValue(objects),\n }\n });\n }\n TablixObjects.enumerateSubTotalsOptions = enumerateSubTotalsOptions;\n function getTableObjects(dataView) {\n var objects = getMetadadataObjects(dataView);\n var formattingProperties = {\n general: {\n autoSizeColumnWidth: TablixObjects.PropGeneralAutoSizeColumns.getValue(objects),\n textSize: TablixObjects.PropGeneralTextSize.getValue(objects),\n totals: shouldShowTableTotals(objects),\n },\n };\n formattingProperties.grid = {\n gridVertical: TablixObjects.PropGridVertical.getValue(objects),\n gridVerticalColor: TablixObjects.PropGridVerticalColor.getValue(objects),\n gridVerticalWeight: TablixObjects.PropGridVerticalWeight.getValue(objects),\n gridHorizontal: TablixObjects.PropGridHorizontalTable.getValue(objects),\n gridHorizontalColor: TablixObjects.PropGridHorizontalColor.getValue(objects),\n gridHorizontalWeight: TablixObjects.PropGridHorizontalWeight.getValue(objects),\n outlineColor: TablixObjects.PropGridOutlineColor.getValue(objects),\n outlineWeight: TablixObjects.PropGridOutlineWeight.getValue(objects),\n rowPadding: TablixObjects.PropGridRowPadding.getValue(objects),\n imageHeight: TablixObjects.PropGridImageHeight.getValue(objects),\n };\n formattingProperties.columnHeaders = {\n fontColor: TablixObjects.PropColumnsFontColor.getValue(objects),\n backColor: TablixObjects.PropColumnsBackColor.getValue(objects),\n outline: TablixObjects.PropColumnsOutline.getValue(objects),\n };\n formattingProperties.values = {\n fontColorPrimary: TablixObjects.PropValuesFontColorPrimary.getValue(objects),\n backColorPrimary: TablixObjects.PropValuesBackColorPrimary.getValue(objects),\n fontColorSecondary: TablixObjects.PropValuesFontColorSecondary.getValue(objects),\n backColorSecondary: TablixObjects.PropValuesBackColorSecondary.getValue(objects),\n outline: TablixObjects.PropValuesOutline.getValue(objects),\n urlIcon: TablixObjects.PropValuesUrlIconProp.getValue(objects),\n };\n formattingProperties.total = {\n fontColor: TablixObjects.PropTotalFontColor.getValue(objects),\n backColor: TablixObjects.PropTotalBackColor.getValue(objects),\n outline: TablixObjects.PropTotalOutline.getValue(objects),\n };\n return formattingProperties;\n }\n TablixObjects.getTableObjects = getTableObjects;\n function getMatrixObjects(dataView) {\n var objects = getMetadadataObjects(dataView);\n var formattingProperties = {\n general: {\n autoSizeColumnWidth: TablixObjects.PropGeneralAutoSizeColumns.getValue(objects),\n textSize: TablixObjects.PropGeneralTextSize.getValue(objects),\n rowSubtotals: shouldShowRowSubtotals(objects),\n columnSubtotals: shouldShowColumnSubtotals(objects),\n },\n };\n formattingProperties.grid = {\n gridVertical: TablixObjects.PropGridVertical.getValue(objects),\n gridVerticalColor: TablixObjects.PropGridVerticalColor.getValue(objects),\n gridVerticalWeight: TablixObjects.PropGridVerticalWeight.getValue(objects),\n gridHorizontal: TablixObjects.PropGridHorizontalMatrix.getValue(objects),\n gridHorizontalColor: TablixObjects.PropGridHorizontalColor.getValue(objects),\n gridHorizontalWeight: TablixObjects.PropGridHorizontalWeight.getValue(objects),\n outlineColor: TablixObjects.PropGridOutlineColor.getValue(objects),\n outlineWeight: TablixObjects.PropGridOutlineWeight.getValue(objects),\n rowPadding: TablixObjects.PropGridRowPadding.getValue(objects),\n imageHeight: TablixObjects.PropGridImageHeight.getValue(objects),\n };\n formattingProperties.columnHeaders = {\n fontColor: TablixObjects.PropColumnsFontColor.getValue(objects),\n backColor: TablixObjects.PropColumnsBackColor.getValue(objects),\n outline: TablixObjects.PropColumnsOutline.getValue(objects),\n };\n formattingProperties.rowHeaders = {\n fontColor: TablixObjects.PropRowsFontColor.getValue(objects),\n backColor: TablixObjects.PropRowsBackColor.getValue(objects),\n outline: TablixObjects.PropRowsOutline.getValue(objects),\n };\n formattingProperties.values = {\n fontColorPrimary: TablixObjects.PropValuesFontColorPrimary.getValue(objects),\n backColorPrimary: TablixObjects.PropValuesBackColorPrimary.getValue(objects),\n fontColorSecondary: TablixObjects.PropValuesFontColorSecondary.getValue(objects),\n backColorSecondary: TablixObjects.PropValuesBackColorSecondary.getValue(objects),\n outline: TablixObjects.PropValuesOutline.getValue(objects),\n };\n formattingProperties.subtotals = {\n fontColor: TablixObjects.PropSubTotalsFontColor.getValue(objects),\n backColor: TablixObjects.PropSubTotalsBackColor.getValue(objects),\n outline: TablixObjects.PropSubTotalsOutline.getValue(objects),\n };\n return formattingProperties;\n }\n TablixObjects.getMatrixObjects = getMatrixObjects;\n /**\n * Generate default objects for the Table/Matrix to set default styling\n * @param {TablixType} tablixType Tablix Type: table | matrix\n * @returns DataViewObjects that can be attached to the DataViewMetadata\n */\n function generateTablixDefaultObjects(tablixType) {\n return {\n general: [{\n selector: null,\n properties: {\n textSize: DataViewObjectDefinitions.encodePropertyValue(12, { numeric: true }),\n totals: DataViewObjectDefinitions.encodePropertyValue(false, { bool: true }),\n }\n }],\n };\n }\n TablixObjects.generateTablixDefaultObjects = generateTablixDefaultObjects;\n function getTextSizeInPx(textSize) {\n return jsCommon.PixelConverter.fromPoint(textSize);\n }\n TablixObjects.getTextSizeInPx = getTextSizeInPx;\n function shouldShowTableTotals(objects) {\n return TablixObjects.PropGeneralTableTotals.getValue(objects);\n }\n TablixObjects.shouldShowTableTotals = shouldShowTableTotals;\n function shouldShowTableTotalsOption(dataView) {\n if (dataView && dataView.table && !_.isEmpty(dataView.table.columns)) {\n var columns = dataView.table.columns;\n if (_.some(columns, function (column) { return column.discourageAggregationAcrossGroups; }))\n return false;\n }\n return true;\n }\n function getTableColumnMetadata(dataView) {\n if (!dataView || !dataView.table || _.isEmpty(dataView.table.columns))\n return;\n return dataView.table.columns;\n }\n function shouldShowRowSubtotals(objects) {\n return TablixObjects.PropGeneralMatrixRowSubtotals.getValue(objects);\n }\n TablixObjects.shouldShowRowSubtotals = shouldShowRowSubtotals;\n function shouldShowRowSubtotalsOption(dataView) {\n return !(dataView &&\n dataView.matrix &&\n dataView.matrix.rows &&\n isDiscourageAggregationAcrossGroups(dataView.matrix.rows.levels));\n }\n function shouldShowColumnSubtotals(objects) {\n return TablixObjects.PropGeneralMatrixColumnSubtotals.getValue(objects);\n }\n TablixObjects.shouldShowColumnSubtotals = shouldShowColumnSubtotals;\n function shouldShowColumnSubtotalsOption(dataView) {\n return !(dataView &&\n dataView.matrix &&\n dataView.matrix.columns &&\n isDiscourageAggregationAcrossGroups(dataView.matrix.columns.levels));\n }\n TablixObjects.shouldShowColumnSubtotalsOption = shouldShowColumnSubtotalsOption;\n function isDiscourageAggregationAcrossGroups(levels) {\n var lastLevel = _.last(levels);\n // If the last item is not Aggregatable, disable totals option since there will be no totals at all to display\n // However, if the non-aggregatable filed is in the middle, there are totals showing up in matrix.\n // Therefore, we still allow users to turn it off\n return lastLevel && _.some(lastLevel.sources, function (source) { return source.discourageAggregationAcrossGroups; });\n }\n TablixObjects.isDiscourageAggregationAcrossGroups = isDiscourageAggregationAcrossGroups;\n })(TablixObjects = internal.TablixObjects || (internal.TablixObjects = {}));\n var TablixUtils;\n (function (TablixUtils) {\n TablixUtils.CssClassTablixDiv = \"tablixDiv\"; // Any DIV inside the table (outer and inner)\n TablixUtils.CssClassContentElement = \"tablixCellContentElement\"; // Outer DIV\n TablixUtils.CssClassContentHost = \"tablixCellContentHost\"; // Inner DIV\n TablixUtils.CssClassTablixHeader = \"tablixHeader\"; // Any Header in the Table/Matrix\n TablixUtils.CssClassTablixColumnHeaderLeaf = \"tablixColumnHeaderLeaf\"; // Leaf Column Headers\n TablixUtils.CssClassTablixValueNumeric = \"tablixValueNumeric\"; // Numeric cells, will also be applied to all Matrix body cells\n TablixUtils.CssClassTablixValueTotal = \"tablixValueTotal\"; // Total cells, will also be applied to subtotal Matrix body cells\n TablixUtils.CssClassValueURLIcon = \"powervisuals-glyph url-icon tablixUrlIconGlyph\"; // Any <a> Tag\n TablixUtils.CssClassValueURLIconContainer = \"tablixValueUrlIcon\"; // Container for the <a> tag\n TablixUtils.CssClassMatrixRowHeaderLeaf = \"matrixRowHeaderLeaf\"; // Matrix Leaf Row Headers\n TablixUtils.CssClassMatrixRowHeaderSubTotal = \"matrixRowHeaderSubTotal\"; // Matrix SubTotal Row Headers\n TablixUtils.CssClassTableFooter = 'tableFooterCell'; // Any cell in the Footer area\n TablixUtils.CssClassTableBodyCell = 'tableBodyCell'; // Any cell in the Table Body\n TablixUtils.CssClassTableBodyCellBottom = 'tableBodyCellBottom'; // Bottom-Most Body cell\n TablixUtils.StringNonBreakingSpace = '&nbsp;';\n TablixUtils.UnitOfMeasurement = 'px';\n var SortIconContainerClassName = \"tablixSortIconContainer\";\n TablixUtils.CellPaddingLeft = 10;\n TablixUtils.CellPaddingRight = 5;\n TablixUtils.CellPaddingLeftMatrixTotal = 5;\n TablixUtils.FontFamilyCell = \"'Segoe UI','wf_segoe-ui_normal', helvetica, arial, sans-serif\";\n TablixUtils.FontFamilyHeader = \"'Segoe UI','wf_segoe-ui_normal', helvetica, arial, sans-serif\";\n TablixUtils.FontFamilyTotal = \"'Segoe UI Bold','wf_segoe-ui_bold', helvetica, arial, sans-serif\";\n TablixUtils.FontColorCells = \"#333\";\n TablixUtils.FontColorHeaders = \"#666\";\n var EdgeSettings = (function () {\n function EdgeSettings(weight, color) {\n this.applyParams(true, weight, color);\n }\n EdgeSettings.prototype.applyParams = function (shown, weight, color) {\n if (shown) {\n this.weight = weight == null ? 0 : weight;\n this.color = color == null ? 'black' : color;\n }\n else {\n this.weight = 0;\n this.color = 'black';\n }\n };\n EdgeSettings.prototype.getCSS = function () {\n var css = [];\n if (_.isNumber(this.weight)) {\n css.push(this.weight + TablixUtils.UnitOfMeasurement);\n if (this.color)\n css.push(this.color);\n css.push('solid');\n }\n return css.join(' ');\n };\n return EdgeSettings;\n }());\n TablixUtils.EdgeSettings = EdgeSettings;\n /**\n * Style parameters for each Cell\n */\n var CellStyle = (function () {\n function CellStyle() {\n this.borders = {};\n this.paddings = { top: 0, left: TablixUtils.CellPaddingLeft, bottom: 0, right: TablixUtils.CellPaddingRight };\n // Initializing values with empty string would cause CSS attributes to not be set if they are undefined\n this.fontFamily = \"\";\n this.fontColor = \"\";\n this.backColor = \"\";\n this.hasImage = false;\n }\n /**\n * Sets the Inline style for the Cell\n * @param {ITablixCell} cell Cell to set style to\n */\n CellStyle.prototype.applyStyle = function (cell) {\n var div = cell.extension.contentHost;\n var style = div.style;\n style.fontFamily = this.fontFamily;\n style.color = this.fontColor;\n style.backgroundColor = this.backColor;\n /**\n * We are setting the borders as inset shadow\n * This way we can control how intersecting borders would look like when they have different colors\n */\n var borderShadow = [];\n style.border = \"none\";\n if (this.borders.left) {\n borderShadow.push(\"inset \" + this.borders.left.weight + TablixUtils.UnitOfMeasurement + \" 0 0 0 \" + this.borders.left.color);\n }\n if (this.borders.right) {\n borderShadow.push(\"inset -\" + this.borders.right.weight + TablixUtils.UnitOfMeasurement + \" 0 0 0 \" + this.borders.right.color);\n }\n if (this.borders.top) {\n borderShadow.push(\"inset 0 \" + this.borders.top.weight + TablixUtils.UnitOfMeasurement + \" 0 0 \" + this.borders.top.color);\n }\n if (this.borders.bottom) {\n borderShadow.push(\"inset 0 -\" + this.borders.bottom.weight + TablixUtils.UnitOfMeasurement + \" 0 0 \" + this.borders.bottom.color);\n }\n style.boxShadow = borderShadow.join(', ');\n style.paddingTop = ((this.paddings.top == null ? 0 : this.paddings.top) + (this.borders.top == null ? 0 : this.borders.top.weight)) + TablixUtils.UnitOfMeasurement;\n style.paddingRight = ((this.paddings.right == null ? TablixUtils.CellPaddingRight : this.paddings.right) + (this.borders.right == null ? 0 : this.borders.right.weight)) + TablixUtils.UnitOfMeasurement;\n style.paddingBottom = ((this.paddings.bottom == null ? 0 : this.paddings.bottom) + (this.borders.bottom == null ? 0 : this.borders.bottom.weight)) + TablixUtils.UnitOfMeasurement;\n style.paddingLeft = ((this.paddings.left == null ? TablixUtils.CellPaddingLeft : this.paddings.left) + (this.borders.left == null ? 0 : this.borders.left.weight)) + TablixUtils.UnitOfMeasurement;\n };\n CellStyle.prototype.getExtraTop = function () {\n var extra = 0;\n if (this.paddings.top)\n extra += this.paddings.top;\n if (this.borders.top)\n extra += this.borders.top.weight;\n return extra;\n };\n CellStyle.prototype.getExtraBottom = function () {\n var extra = 0;\n if (this.paddings.bottom)\n extra += this.paddings.bottom;\n if (this.borders.bottom)\n extra += this.borders.bottom.weight;\n return extra;\n };\n CellStyle.prototype.getExtraRight = function () {\n var extra = 0;\n if (this.paddings.right)\n extra += this.paddings.right;\n if (this.borders.right)\n extra += this.borders.right.weight;\n return extra;\n };\n CellStyle.prototype.getExtraLeft = function () {\n var extra = 0;\n if (this.paddings.left)\n extra += this.paddings.left;\n if (this.borders.left)\n extra += this.borders.left.weight;\n return extra;\n };\n return CellStyle;\n }());\n TablixUtils.CellStyle = CellStyle;\n /**\n * Index within a dimension (row/column)\n */\n var DimensionPosition = (function () {\n function DimensionPosition() {\n }\n return DimensionPosition;\n }());\n TablixUtils.DimensionPosition = DimensionPosition;\n /**\n * Poistion information about the cell\n */\n var CellPosition = (function () {\n function CellPosition() {\n this.row = new DimensionPosition();\n this.column = new DimensionPosition();\n }\n CellPosition.prototype.isMatch = function (position) {\n return this.column.index === position.column.index &&\n this.row.index === position.row.index;\n };\n return CellPosition;\n }());\n TablixUtils.CellPosition = CellPosition;\n var TablixVisualCell = (function () {\n function TablixVisualCell(dataPoint, isTotal, columnMetadata, formatter) {\n this.dataPoint = dataPoint;\n this.columnMetadata = columnMetadata;\n this.formatter = formatter;\n this.isTotal = isTotal;\n this.position = new TablixUtils.CellPosition();\n }\n Object.defineProperty(TablixVisualCell.prototype, \"textContent\", {\n get: function () {\n if (this.dataPoint == null)\n return '';\n if (this.formatter)\n return this.formatter(this.dataPoint, this.columnMetadata, TablixObjects.PropColumnFormatString.getPropertyID());\n else\n return this.dataPoint;\n },\n enumerable: true,\n configurable: true\n });\n ;\n Object.defineProperty(TablixVisualCell.prototype, \"domContent\", {\n get: function () {\n if (this.columnMetadata && isValidStatusGraphic(this.columnMetadata.kpi, this.textContent))\n return createKpiDom(this.columnMetadata.kpi, this.textContent);\n },\n enumerable: true,\n configurable: true\n });\n ;\n Object.defineProperty(TablixVisualCell.prototype, \"isNumeric\", {\n get: function () {\n if (this.columnMetadata)\n return this.columnMetadata.type.numeric && !this.columnMetadata.kpi;\n },\n enumerable: true,\n configurable: true\n });\n ;\n Object.defineProperty(TablixVisualCell.prototype, \"isUrl\", {\n get: function () {\n if (this.columnMetadata)\n return visuals.converterHelper.isWebUrlColumn(this.columnMetadata);\n },\n enumerable: true,\n configurable: true\n });\n ;\n Object.defineProperty(TablixVisualCell.prototype, \"isImage\", {\n get: function () {\n if (this.columnMetadata)\n return visuals.converterHelper.isImageUrlColumn(this.columnMetadata);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixVisualCell.prototype, \"isValidUrl\", {\n get: function () {\n return jsCommon.UrlUtils.isValidImageUrl(this.textContent);\n },\n enumerable: true,\n configurable: true\n });\n ;\n TablixVisualCell.prototype.isMatch = function (item) {\n return this.position.isMatch(item.position) && this.backColor === item.backColor;\n };\n return TablixVisualCell;\n }());\n TablixUtils.TablixVisualCell = TablixVisualCell;\n function createTable() {\n return document.createElement(\"table\");\n }\n TablixUtils.createTable = createTable;\n function createDiv() {\n var div = document.createElement(\"div\");\n div.className = \"tablixDiv\";\n return div;\n }\n TablixUtils.createDiv = createDiv;\n function resetCellCssClass(cell) {\n cell.extension.contentElement.className = TablixUtils.CssClassTablixDiv + \" \" + TablixUtils.CssClassContentElement;\n cell.extension.contentHost.className = TablixUtils.CssClassTablixDiv + \" \" + TablixUtils.CssClassContentHost;\n }\n TablixUtils.resetCellCssClass = resetCellCssClass;\n function addCellCssClass(cell, style) {\n cell.extension.contentHost.className += \" \" + style;\n }\n TablixUtils.addCellCssClass = addCellCssClass;\n /**\n * Clears all inline styles (border, fontColor, background) and resets CSS classes\n * Performed with unbind-<Cell>\n */\n function clearCellStyle(cell) {\n cell.extension.contentHost.className = \"\";\n cell.extension.contentHost.style.cssText = \"\";\n }\n TablixUtils.clearCellStyle = clearCellStyle;\n function clearCellTextAndTooltip(cell) {\n cell.extension.contentHost.textContent = '';\n cell.extension.contentHost.removeAttribute('title');\n cell.contentHeight = cell.contentWidth = 0;\n controls.HTMLElementUtils.clearChildren(cell.extension.contentHost);\n }\n TablixUtils.clearCellTextAndTooltip = clearCellTextAndTooltip;\n function setCellTextAndTooltip(cell, text) {\n var val = visuals.TextUtil.replaceSpaceWithNBSP(text);\n cell.extension.contentHost.textContent = val;\n cell.extension.contentHost.title = val;\n }\n TablixUtils.setCellTextAndTooltip = setCellTextAndTooltip;\n function isValidSortClick(e) {\n var colHeader = e.target;\n var x = e.offsetX;\n return x >= 0 && x < colHeader.offsetWidth - internal.TablixResizer.resizeHandleSize;\n }\n TablixUtils.isValidSortClick = isValidSortClick;\n function appendATagToBodyCell(value, cell, urlIcon) {\n var element = cell.extension.contentHost;\n var atag = null;\n if (element.childElementCount === 0) {\n atag = document.createElement('a');\n element.appendChild(atag);\n }\n else {\n atag = element.children[0];\n }\n atag.href = value;\n atag.target = '_blank';\n atag.title = value;\n if (urlIcon === true) {\n atag.className = TablixUtils.CssClassValueURLIcon;\n element.className = TablixUtils.CssClassValueURLIconContainer;\n }\n else {\n atag.innerText = value;\n }\n }\n TablixUtils.appendATagToBodyCell = appendATagToBodyCell;\n function appendImgTagToBodyCell(value, cell, imageHeight) {\n var element = cell.extension.contentHost;\n var imgContainer = TablixUtils.createDiv();\n var imgTag = document.createElement('img');\n imgContainer.style.height = imageHeight + \"px\";\n imgContainer.style.width = \"100%\";\n imgContainer.style.textAlign = \"center\";\n imgTag.src = value;\n imgTag.style.maxHeight = \"100%\";\n imgTag.style.maxWidth = \"100%\";\n imgContainer.appendChild(imgTag);\n element.appendChild(imgContainer);\n }\n TablixUtils.appendImgTagToBodyCell = appendImgTagToBodyCell;\n function createKpiDom(kpi, kpiValue) {\n debug.assertValue(kpi, 'kpi');\n debug.assertValue(kpiValue, 'kpiValue');\n var className = visuals.KpiUtil.getClassForKpi(kpi, kpiValue) || '';\n return DomFactory.div()\n .addClass(className)\n .css({\n 'display': 'inline-block',\n 'vertical-align': 'bottom',\n 'margin': '0',\n });\n }\n TablixUtils.createKpiDom = createKpiDom;\n function isValidStatusGraphic(kpi, kpiValue) {\n if (!kpi || kpiValue === undefined) {\n return false;\n }\n return !!visuals.KpiUtil.getClassForKpi(kpi, kpiValue);\n }\n TablixUtils.isValidStatusGraphic = isValidStatusGraphic;\n function getCustomSortEventArgs(queryName, sortDirection) {\n var sortDescriptors = [{\n queryName: queryName,\n sortDirection: sortDirection\n }];\n return { sortDescriptors: sortDescriptors };\n }\n TablixUtils.getCustomSortEventArgs = getCustomSortEventArgs;\n function reverseSort(sortDirection) {\n return sortDirection === 2 /* Descending */ ? 1 /* Ascending */ : 2 /* Descending */;\n }\n TablixUtils.reverseSort = reverseSort;\n function createColumnHeaderWithSortIcon(item, cell) {\n var colHeaderContainer = TablixUtils.createDiv();\n if (item.sort) {\n var itemSort = item.sort;\n colHeaderContainer.appendChild(createSortIcon(itemSort, true));\n colHeaderContainer.appendChild(createSortIcon(reverseSort(itemSort), false));\n }\n else {\n colHeaderContainer.appendChild(createSortIcon(2 /* Descending */, false));\n }\n var colHeaderTitle = TablixUtils.createDiv();\n // Preserving trailing and leading spaces\n var title = item ? visuals.TextUtil.replaceSpaceWithNBSP(item.displayName) : '';\n colHeaderTitle.textContent = title;\n colHeaderContainer.appendChild(colHeaderTitle);\n cell.extension.contentHost.title = title;\n cell.extension.contentHost.appendChild(colHeaderContainer);\n }\n TablixUtils.createColumnHeaderWithSortIcon = createColumnHeaderWithSortIcon;\n function createSortIcon(sort, isSorted) {\n var imgSort = document.createElement('i');\n imgSort.className = SortIconContainerClassName +\n \" \" + (isSorted ? \"sorted\" : \"future\") +\n \" \" + (sort === 1 /* Ascending */ ? \"powervisuals-glyph caret-up\" : \"powervisuals-glyph caret-down\");\n return imgSort;\n }\n function checkSortIconExists(cell) {\n for (var i = 0, len = cell.extension.contentElement.childElementCount; i < len; i++) {\n var element = cell.extension.contentElement.children.item(i);\n if (element.classList.contains(SortIconContainerClassName))\n return true;\n }\n return false;\n }\n function removeSortIcons(cell) {\n if (!checkSortIconExists(cell))\n return;\n $(cell.extension.contentElement).find('.' + SortIconContainerClassName).remove();\n }\n TablixUtils.removeSortIcons = removeSortIcons;\n })(TablixUtils = internal.TablixUtils || (internal.TablixUtils = {}));\n })(internal = controls.internal || (controls.internal = {}));\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n controls.TablixDefaultTextSize = jsCommon.TextSizeDefaults.TextSizeMin;\n var TablixControl = (function () {\n function TablixControl(hierarchyNavigator, layoutManager, binder, parentDomElement, options) {\n var _this = this;\n this.scrollBarElementWidth = 9;\n // Options (fontSize set after container initialized)\n this.options = options;\n var isInteractive = options.interactive;\n this.isTouchEnabled = isInteractive && options.enableTouchSupport;\n // Main Div\n this.mainDiv = controls.internal.TablixUtils.createDiv();\n this.mainDiv.classList.add(TablixControl.TablixTableAreaClassName);\n // Footer Div\n this.footerDiv = controls.internal.TablixUtils.createDiv();\n this.footerDiv.classList.add(TablixControl.TablixFooterClassName);\n if (this.isTouchEnabled)\n this.InitializeTouchSupport();\n this.gridDimensions = {};\n this.containerElement = controls.internal.TablixUtils.createDiv();\n this.className = layoutManager.getTablixClassName();\n this.autoSizeWidth = false;\n this.autoSizeHeight = false;\n this.fontFamily = controls.internal.TablixUtils.FontFamilyCell;\n this.fontColor = controls.internal.TablixUtils.FontColorCells;\n this.fontSize = options.fontSize;\n parentDomElement.className = TablixControl.TablixContainerClassName;\n parentDomElement.appendChild(this.containerElement);\n this.containerElement.addEventListener(\"mousewheel\", function (e) { _this.onMouseWheel(e); });\n this.containerElement.addEventListener(\"DOMMouseScroll\", function (e) { _this.onFireFoxMouseWheel(e); });\n this.containerElement.appendChild(this.mainDiv);\n this.containerElement.appendChild(this.footerDiv);\n if (this.isTouchEnabled) {\n this.touchInterpreter.initTouch(this.mainDiv, null, false);\n this.footerTouchInterpreter.initTouch(this.footerDiv, this.mainDiv, false);\n }\n this.controlLayoutManager = layoutManager;\n this.controlLayoutManager.initialize(this);\n this.hierarchyTablixNavigator = hierarchyNavigator;\n this.binder = binder;\n this.columnDim = new controls.TablixColumnDimension(this);\n this.rowDim = new controls.TablixRowDimension(this);\n this.columnDim._otherDimension = this.rowDimension;\n this.rowDim._otherDimension = this.columnDimension;\n this.InitializeScrollbars();\n if (!isInteractive) {\n this.scrollbarWidth = 0;\n }\n this.updateHorizontalPosition();\n this.updateVerticalPosition();\n this.updateFooterVisibility();\n this.lastRenderingArgs = {};\n }\n TablixControl.prototype.InitializeTouchSupport = function () {\n this.touchManager = new controls.TouchUtils.TouchManager();\n this.touchInterpreter = new controls.TouchUtils.TouchEventInterpreter(this.touchManager);\n this.footerTouchInterpreter = new controls.TouchUtils.TouchEventInterpreter(this.touchManager);\n this.columnTouchDelegate = new controls.ColumnTouchDelegate(new controls.TouchUtils.Rectangle());\n this.rowTouchDelegate = new controls.RowTouchDelegate(new controls.TouchUtils.Rectangle());\n this.bodyTouchDelegate = new controls.BodyTouchDelegate(new controls.TouchUtils.Rectangle());\n this.footerTouchDelegate = new controls.ColumnTouchDelegate(new controls.TouchUtils.Rectangle());\n this.columnTouchDelegate.setHandler(this, this.onTouchEvent);\n this.rowTouchDelegate.setHandler(this, this.onTouchEvent);\n this.bodyTouchDelegate.setHandler(this, this.onTouchEvent);\n this.footerTouchDelegate.setHandler(this, this.onTouchEvent);\n this.touchManager.addTouchRegion(this.columnTouchDelegate.dimension, this.columnTouchDelegate, this.columnTouchDelegate);\n this.touchManager.addTouchRegion(this.rowTouchDelegate.dimension, this.rowTouchDelegate, this.rowTouchDelegate);\n this.touchManager.addTouchRegion(this.bodyTouchDelegate.dimension, this.bodyTouchDelegate, this.bodyTouchDelegate);\n this.touchManager.addTouchRegion(this.footerTouchDelegate.dimension, this.footerTouchDelegate, this.footerTouchDelegate);\n };\n TablixControl.prototype.InitializeScrollbars = function () {\n // Row Dimension\n this.rowDim._initializeScrollbar(this.containerElement, null, this.options.layoutKind);\n var rowDimensionScrollbarStyle = this.rowDim.scrollbar.element.style;\n rowDimensionScrollbarStyle.position = \"absolute\";\n rowDimensionScrollbarStyle.top = \"0\" + TablixControl.UnitOfMeasurement;\n rowDimensionScrollbarStyle.right = \"0\" + TablixControl.UnitOfMeasurement;\n this.rowDim.scrollbar.width = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\n // Default to true which is the more common case to avoid an extra rendering iteration\n // when first rendering the visual\n this.rowDim.scrollbar.show(true);\n // Column Dimension\n this.columnDim._initializeScrollbar(this.containerElement, null, this.options.layoutKind);\n var columnDimensionScrollbarStyle = this.columnDim.scrollbar.element.style;\n columnDimensionScrollbarStyle.position = \"absolute\";\n columnDimensionScrollbarStyle.left = \"0\" + TablixControl.UnitOfMeasurement;\n columnDimensionScrollbarStyle.bottom = \"0\" + TablixControl.UnitOfMeasurement;\n this.columnDim.scrollbar.height = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\n this.columnDim.scrollbar.show(false);\n };\n Object.defineProperty(TablixControl.prototype, \"container\", {\n get: function () {\n return this.containerElement;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"contentHost\", {\n get: function () {\n return this.mainDiv;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"footerHost\", {\n get: function () {\n return this.footerDiv;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"className\", {\n set: function (value) {\n this.containerElement.className = value;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"hierarchyNavigator\", {\n get: function () {\n return this.hierarchyTablixNavigator;\n },\n enumerable: true,\n configurable: true\n });\n TablixControl.prototype.getBinder = function () {\n return this.binder;\n };\n Object.defineProperty(TablixControl.prototype, \"autoSizeWidth\", {\n get: function () {\n return this._autoSizeWidth;\n },\n set: function (value) {\n this._autoSizeWidth = value;\n if (!value) {\n this.containerElement.style.minWidth = this.containerElement.style.maxWidth = \"none\";\n }\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"autoSizeHeight\", {\n get: function () {\n return this._autoSizeHeight;\n },\n set: function (value) {\n if (!value) {\n this.containerElement.style.minHeight = this.containerElement.style.maxHeight = \"none\";\n }\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"maxWidth\", {\n get: function () {\n return this.maximumWidth;\n },\n set: function (value) {\n this.maximumWidth = value;\n this.containerElement.style.maxWidth = this.maximumWidth + TablixControl.UnitOfMeasurement;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"viewport\", {\n get: function () {\n return this.viewPort;\n },\n set: function (value) {\n this.viewPort = value;\n this.containerElement.style.width = this.viewPort.width + TablixControl.UnitOfMeasurement;\n this.containerElement.style.height = this.viewPort.height + TablixControl.UnitOfMeasurement;\n this.rowDim.scrollbar.invalidateArrange();\n this.columnDim.scrollbar.invalidateArrange();\n this.controlLayoutManager.updateViewport(this.viewPort);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"maxHeight\", {\n get: function () {\n return this.maximumHeight;\n },\n set: function (value) {\n this.maximumHeight = value;\n this.containerElement.style.maxHeight = this.maximumHeight + TablixControl.UnitOfMeasurement;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"minWidth\", {\n get: function () {\n return this.minimumWidth;\n },\n set: function (value) {\n this.minimumWidth = value;\n this.containerElement.style.minWidth = this.minimumWidth + TablixControl.UnitOfMeasurement;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"minHeight\", {\n get: function () {\n return this.minimumHeight;\n },\n set: function (value) {\n this.minimumHeight = value;\n this.containerElement.style.minHeight = this.minimumHeight + TablixControl.UnitOfMeasurement;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"fontSize\", {\n get: function () {\n return this.textFontSize;\n },\n set: function (value) {\n this.textFontSize = !value ? TablixControl.DefaultFontSize : value;\n this.containerElement.style.fontSize = this.textFontSize;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"fontFamily\", {\n get: function () {\n return this.textFontFamily;\n },\n set: function (value) {\n this.textFontFamily = value;\n this.containerElement.style.fontFamily = value;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"fontColor\", {\n get: function () {\n return this.textFontColor;\n },\n set: function (value) {\n this.textFontColor = value;\n this.containerElement.style.color = value;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"scrollbarWidth\", {\n set: function (value) {\n this.scrollBarElementWidth = value;\n this.rowDim.scrollbar.width = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\n this.columnDim.scrollbar.height = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\n },\n enumerable: true,\n configurable: true\n });\n TablixControl.prototype.updateModels = function (resetScrollOffsets, rowModel, columnModel) {\n this.rowDim.model = rowModel;\n this.rowDim.modelDepth = this.hierarchyNavigator.getRowHierarchyDepth();\n this.columnDim.model = columnModel;\n this.columnDim.modelDepth = this.hierarchyNavigator.getColumnHierarchyDepth();\n if (resetScrollOffsets) {\n this.rowDim.scrollOffset = 0;\n this.columnDim.scrollOffset = 0;\n }\n this.layoutManager.updateColumnCount(this.rowDim, this.columnDim);\n };\n TablixControl.prototype.updateColumnDimensions = function (rowHierarchyWidth, columnHierarchyWidth, count) {\n var gridDimensions = this.gridDimensions;\n gridDimensions.columnCount = count;\n gridDimensions.rowHierarchyWidth = rowHierarchyWidth;\n gridDimensions.columnHierarchyWidth = columnHierarchyWidth;\n };\n TablixControl.prototype.updateRowDimensions = function (columnHierarchyHeight, rowHierarchyHeight, rowHierarchyContentHeight, count, footerHeight) {\n var gridDimensions = this.gridDimensions;\n gridDimensions.rowCount = count;\n gridDimensions.rowHierarchyHeight = rowHierarchyHeight;\n gridDimensions.rowHierarchyContentHeight = rowHierarchyContentHeight;\n gridDimensions.columnHierarchyHeight = columnHierarchyHeight;\n gridDimensions.footerHeight = footerHeight;\n };\n TablixControl.prototype.updateTouchDimensions = function () {\n var gridDimensions = this.gridDimensions;\n this.columnTouchDelegate.resize(gridDimensions.rowHierarchyWidth, 0, gridDimensions.columnHierarchyWidth, gridDimensions.columnHierarchyHeight);\n this.columnTouchDelegate.setScrollDensity(gridDimensions.columnCount / gridDimensions.columnHierarchyWidth);\n this.rowTouchDelegate.resize(0, gridDimensions.columnHierarchyHeight, gridDimensions.rowHierarchyWidth, gridDimensions.rowHierarchyHeight);\n this.rowTouchDelegate.setScrollDensity(gridDimensions.rowCount / gridDimensions.rowHierarchyHeight);\n this.bodyTouchDelegate.resize(gridDimensions.rowHierarchyWidth, gridDimensions.columnHierarchyHeight, gridDimensions.columnHierarchyWidth, gridDimensions.rowHierarchyHeight);\n this.bodyTouchDelegate.setScrollDensity(gridDimensions.columnCount / gridDimensions.columnHierarchyWidth, gridDimensions.rowCount / gridDimensions.rowHierarchyHeight);\n this.footerTouchDelegate.resize(gridDimensions.rowHierarchyWidth, gridDimensions.columnHierarchyHeight + gridDimensions.rowHierarchyHeight, gridDimensions.columnHierarchyWidth, gridDimensions.footerHeight);\n this.footerTouchDelegate.setScrollDensity(gridDimensions.columnCount / gridDimensions.columnHierarchyWidth);\n };\n TablixControl.prototype.onMouseWheel = function (e) {\n var dimension = this.determineDimensionToScroll();\n if (dimension)\n dimension.scrollbar.onMouseWheel(e);\n };\n TablixControl.prototype.onFireFoxMouseWheel = function (e) {\n var dimension = this.determineDimensionToScroll();\n if (dimension)\n dimension.scrollbar.onFireFoxMouseWheel(e);\n };\n TablixControl.prototype.determineDimensionToScroll = function () {\n if (this.rowDim.scrollbar.visible)\n return this.rowDim;\n // In the absence of the vertical scrollbar, we scroll the\n // horizontal scrollbar.\n if (this.columnDim.scrollbar.visible)\n return this.columnDim;\n return null;\n };\n Object.defineProperty(TablixControl.prototype, \"layoutManager\", {\n get: function () {\n return this.controlLayoutManager;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"columnDimension\", {\n get: function () {\n return this.columnDim;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixControl.prototype, \"rowDimension\", {\n get: function () {\n return this.rowDim;\n },\n enumerable: true,\n configurable: true\n });\n TablixControl.prototype.refresh = function (clear) {\n this.render(clear, null);\n };\n TablixControl.prototype._onScrollAsync = function (dimension) {\n var _this = this;\n requestAnimationFrame(function () { _this.performPendingScroll(dimension); });\n };\n TablixControl.prototype.performPendingScroll = function (dimension) {\n this.render(false, dimension);\n };\n TablixControl.prototype.updateHorizontalPosition = function () {\n if (this.rowDim.scrollbar.visible) {\n this.columnDim.scrollbar.element.style.right = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\n this.footerDiv.style.right = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\n this.mainDiv.style.right = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\n }\n else {\n this.columnDim.scrollbar.element.style.right = \"0\" + TablixControl.UnitOfMeasurement;\n this.mainDiv.style.right = \"0\" + TablixControl.UnitOfMeasurement;\n this.footerDiv.style.right = \"0\" + TablixControl.UnitOfMeasurement;\n }\n };\n TablixControl.prototype.updateFooterVisibility = function () {\n if (this.rowDim.hasFooter() ? (this.footerDiv.style.display !== \"block\") : (this.footerDiv.style.display !== \"none\")) {\n if (this.rowDim.hasFooter()) {\n this.footerDiv.style.display = \"block\";\n }\n else {\n this.footerDiv.style.display = \"none\";\n }\n }\n };\n TablixControl.prototype.updateVerticalPosition = function () {\n var hasVerticalScrollbar = this.rowDim.scrollbar.visible;\n // TODO: ideally the tablix control would not know about where it is rendered but the layout manager\n // would provider that information; we should refactor the layout manager so that getLayoutKind is not needed anymore.\n var isDashboardTile = this.controlLayoutManager.getLayoutKind() === 1 /* DashboardTile */;\n var showFooter = hasVerticalScrollbar || isDashboardTile;\n if (showFooter) {\n var mainBottom = this.footerDiv.offsetHeight;\n var footerBottom = 0;\n var verticalScrollbarBottom = 0;\n // If we have a horizontal scrollbar, we need to adjust the bottom\n // value by the scrollbar width\n var hasHorizontalScrollbar = this.columnDim.scrollbar.visible;\n if (hasHorizontalScrollbar) {\n mainBottom += this.scrollBarElementWidth;\n footerBottom += this.scrollBarElementWidth;\n verticalScrollbarBottom = this.scrollBarElementWidth;\n }\n this.mainDiv.style.bottom = mainBottom + TablixControl.UnitOfMeasurement;\n this.rowDim.scrollbar.element.style.bottom = verticalScrollbarBottom + TablixControl.UnitOfMeasurement;\n this.footerDiv.style.bottom = footerBottom + TablixControl.UnitOfMeasurement;\n // With a vertical scrollbar, the footer is always rendered at the bottom\n this.footerDiv.style.removeProperty(\"top\");\n }\n else {\n // Without a vertical scrollbar, the footer is rendered below the last row;\n // this is controlled by the top value only\n this.footerDiv.style.top = this.gridDimensions.rowHierarchyContentHeight + TablixControl.UnitOfMeasurement;\n this.footerDiv.style.removeProperty(\"bottom\");\n this.mainDiv.style.removeProperty(\"bottom\");\n }\n };\n TablixControl.prototype.alreadyRendered = function (scrollingDimension) {\n if (scrollingDimension !== this.lastRenderingArgs.scrollingDimension ||\n this.rowDimension.scrollOffset !== this.lastRenderingArgs.rowScrollOffset ||\n this.columnDimension.scrollOffset !== this.lastRenderingArgs.columnScrollOffset) {\n return false;\n }\n return true;\n };\n TablixControl.prototype.render = function (clear, scrollingDimension) {\n // at time of rendering always ensure the scroll offset is valid\n this.columnDim.makeScrollOffsetValid();\n this.rowDim.makeScrollOffsetValid();\n if (clear || scrollingDimension === null) {\n this.lastRenderingArgs = {};\n }\n else if (this.alreadyRendered(scrollingDimension)) {\n return;\n }\n var done = false;\n this.renderIterationCount = 0;\n this.controlLayoutManager.onStartRenderingSession(scrollingDimension, this.mainDiv, clear);\n var binder = this.binder;\n binder.onStartRenderingSession();\n var priorFooterHeight = this.gridDimensions.footerHeight;\n var priorRowHierarchyHeight = this.gridDimensions.rowHierarchyHeight;\n var priorRowHierarchyContentHeight = this.gridDimensions.rowHierarchyContentHeight;\n while (!done && this.renderIterationCount < TablixControl.MaxRenderIterationCount) {\n var hScrollbarVisibility = this.columnDim.scrollbar.visible;\n var vScrollbarVisibility = this.rowDim.scrollbar.visible;\n this.columnDim._onStartRenderingIteration();\n this.rowDim._onStartRenderingIteration();\n this.controlLayoutManager.onStartRenderingIteration(clear);\n // These calls add cells to the table.\n // Column needs to be rendered before rows as the row call will pair up with columns to produce the body cells.\n this.renderCorner();\n this.columnDim._render();\n this.rowDim._render();\n done = this.controlLayoutManager.onEndRenderingIteration();\n this.columnDim._onEndRenderingIteration();\n this.rowDim._onEndRenderingIteration();\n if ((hScrollbarVisibility !== this.columnDim.scrollbar.visible)) {\n this.updateVerticalPosition();\n }\n if (vScrollbarVisibility !== this.rowDim.scrollbar.visible) {\n this.updateHorizontalPosition();\n }\n this.renderIterationCount++;\n }\n this.controlLayoutManager.onEndRenderingSession();\n binder.onEndRenderingSession();\n if (this.isTouchEnabled)\n this.updateTouchDimensions();\n this.lastRenderingArgs.rowScrollOffset = this.rowDimension.scrollOffset;\n this.lastRenderingArgs.columnScrollOffset = this.columnDimension.scrollOffset;\n this.updateContainerDimensions();\n var lastRenderingArgs = this.lastRenderingArgs;\n lastRenderingArgs.rowScrollOffset = this.rowDimension.scrollOffset;\n lastRenderingArgs.columnScrollOffset = this.columnDimension.scrollOffset;\n lastRenderingArgs.scrollingDimension = scrollingDimension;\n if (priorFooterHeight !== this.gridDimensions.footerHeight ||\n priorRowHierarchyHeight !== this.gridDimensions.rowHierarchyHeight ||\n priorRowHierarchyContentHeight !== this.gridDimensions.rowHierarchyContentHeight) {\n this.updateVerticalPosition();\n }\n // NOTE: it is critical that we refresh the scrollbars only after the vertical\n // position was updated above; otherwise the measurements can be incorrect.\n if (this.options.interactive) {\n this.columnDim.scrollbar.refresh();\n this.rowDim.scrollbar.refresh();\n }\n };\n TablixControl.prototype.updateContainerDimensions = function () {\n var gridDimensions = this.gridDimensions;\n if (this._autoSizeWidth) {\n var vScrollBarWidth = this.rowDim.scrollbar.visible ? this.scrollBarElementWidth : 0;\n this.containerElement.style.width =\n gridDimensions.rowHierarchyWidth +\n gridDimensions.columnHierarchyWidth +\n vScrollBarWidth +\n TablixControl.UnitOfMeasurement;\n }\n if (this._autoSizeHeight) {\n var hScrollBarHeight = this.columnDim.scrollbar.visible ? this.scrollBarElementWidth : 0;\n this.containerElement.style.height =\n gridDimensions.columnHierarchyHeight +\n gridDimensions.rowHierarchyHeight +\n gridDimensions.footerHeight +\n hScrollBarHeight +\n TablixControl.UnitOfMeasurement;\n }\n };\n TablixControl.prototype.cornerCellMatch = function (item, cell) {\n var previousItem = cell.item;\n return cell.type === 0 /* CornerCell */ && previousItem && this.hierarchyTablixNavigator.cornerCellItemEquals(item, previousItem);\n };\n TablixControl.prototype.renderCorner = function () {\n var columnDepth = this.columnDim.getDepth();\n var rowDepth = this.rowDim.getDepth();\n for (var i = 0; i < columnDepth; i++) {\n for (var j = 0; j < rowDepth; j++) {\n var item = this.hierarchyTablixNavigator.getCorner(j, i);\n var cell = this.controlLayoutManager.getOrCreateCornerCell(item, j, i);\n var match = this.cornerCellMatch(item, cell);\n if (!match) {\n this._unbindCell(cell);\n cell.type = 0 /* CornerCell */;\n cell.item = item;\n this.binder.bindCornerCell(item, cell);\n }\n this.controlLayoutManager.onCornerCellRealized(item, cell);\n }\n }\n };\n TablixControl.prototype._unbindCell = function (cell) {\n switch (cell.type) {\n case 3 /* BodyCell */:\n this.binder.unbindBodyCell(cell.item, cell);\n break;\n case 2 /* ColumnHeader */:\n this.binder.unbindColumnHeader(cell.item, cell);\n break;\n case 1 /* RowHeader */:\n this.binder.unbindRowHeader(cell.item, cell);\n break;\n case 0 /* CornerCell */:\n this.binder.unbindCornerCell(cell.item, cell);\n }\n cell.item = null;\n cell.type = null;\n };\n TablixControl.prototype.onTouchEvent = function (args) {\n var colShift;\n var rowShift;\n var that;\n if ((args) && (args.length > 0)) {\n if ((\"columnDim\" in args[0]) && (\"rowDim\" in args[0])) {\n that = args[0];\n colShift = that.columnDim.scrollbar.visible ? args[1] : 0;\n rowShift = that.rowDim.scrollbar.visible ? args[2] : 0;\n that.columnDim.scrollbar.viewMin = Math.max(0, that.columnDim.scrollbar.viewMin + colShift);\n that.columnDim.scrollOffset = Math.max(0, that.columnDim.scrollOffset + colShift);\n that.rowDim.scrollbar.viewMin = Math.max(0, that.rowDim.scrollbar.viewMin + rowShift);\n that.rowDim.scrollOffset = Math.max(0, that.rowDim.scrollOffset + rowShift);\n if (colShift === 0) {\n that._onScrollAsync(that.rowDim);\n }\n else if (rowShift === 0) {\n that._onScrollAsync(that.columnDim);\n }\n else {\n that._onScrollAsync(null);\n }\n }\n }\n };\n TablixControl.UnitOfMeasurement = 'px';\n TablixControl.TablixContainerClassName = 'tablixContainer';\n TablixControl.TablixTableAreaClassName = \"tablixTableArea\";\n TablixControl.TablixFooterClassName = \"tableFooterArea\";\n TablixControl.DefaultFontSize = jsCommon.PixelConverter.fromPoint(controls.TablixDefaultTextSize);\n /*\n * This is workaround for the infinite loop in rendering\n * BugID: 6518621\n * ToDo: Investigate the underlying cause for rendering to never report completion\n * Rendering typically require 3-5 iterations to complete, so 10 is enough\n */\n TablixControl.MaxRenderIterationCount = 10;\n return TablixControl;\n }());\n controls.TablixControl = TablixControl;\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var TablixDimension = (function () {\n function TablixDimension(tablixControl) {\n this._scrollStep = 0.1;\n this._owner = tablixControl;\n this._hierarchyNavigator = tablixControl.hierarchyNavigator;\n this._binder = tablixControl.getBinder();\n this._tablixLayoutManager = tablixControl.layoutManager;\n this.scrollOffset = 0;\n }\n TablixDimension.prototype._onStartRenderingIteration = function () {\n this.updateScrollPosition();\n };\n TablixDimension.prototype._onEndRenderingIteration = function () {\n };\n TablixDimension.prototype.getValidScrollOffset = function (scrollOffset) {\n return Math.min(Math.max(scrollOffset, 0), Math.max(this.getItemsCount() - this._scrollStep, 0));\n };\n TablixDimension.prototype.makeScrollOffsetValid = function () {\n this.scrollOffset = this.getValidScrollOffset(this.scrollOffset);\n };\n TablixDimension.prototype.getIntegerScrollOffset = function () {\n return Math.floor(this.scrollOffset);\n };\n TablixDimension.prototype.getFractionScrollOffset = function () {\n return this.scrollOffset - this.getIntegerScrollOffset();\n };\n Object.defineProperty(TablixDimension.prototype, \"scrollbar\", {\n get: function () {\n return this._scrollbar;\n },\n enumerable: true,\n configurable: true\n });\n TablixDimension.prototype.getFirstVisibleItem = function (level) {\n return this._scrollItems[level];\n };\n TablixDimension.prototype.getFirstVisibleChild = function (item) {\n return this._hierarchyNavigator.getAt(this._hierarchyNavigator.getChildren(item), this.getFirstVisibleChildIndex(item));\n };\n TablixDimension.prototype.getFirstVisibleChildIndex = function (item) {\n var startItem = this.getFirstVisibleItem(this._hierarchyNavigator.getLevel(item) + 1);\n var firstVisibleIndex;\n if (startItem === undefined || (startItem !== undefined && this._hierarchyNavigator.getParent(startItem) !== item)) {\n firstVisibleIndex = 0;\n }\n else {\n firstVisibleIndex = this._hierarchyNavigator.getIndex(startItem);\n }\n return firstVisibleIndex;\n };\n TablixDimension.prototype._initializeScrollbar = function (parentElement, touchDiv, layoutKind) {\n var _this = this;\n this._scrollbar = this._createScrollbar(parentElement, layoutKind);\n this._scrollbar._onscroll.push(function (e) { return _this.onScroll(); });\n if (touchDiv) {\n this.scrollbar.initTouch(touchDiv, true);\n touchDiv.style.setProperty(\"-ms-touch-action\", \"pinch-zoom\");\n }\n };\n TablixDimension.prototype.getItemsCount = function () {\n return this.model ? this._hierarchyNavigator.getLeafCount(this.model) : 0;\n };\n TablixDimension.prototype.getDepth = function () {\n return this.modelDepth;\n };\n TablixDimension.prototype.onScroll = function () {\n this.scrollOffset = this._scrollbar.viewMin;\n this._owner._onScrollAsync(this);\n };\n Object.defineProperty(TablixDimension.prototype, \"otherDimension\", {\n get: function () {\n return this._otherDimension;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TablixDimension.prototype, \"layoutManager\", {\n get: function () {\n return this._layoutManager;\n },\n enumerable: true,\n configurable: true\n });\n TablixDimension.prototype._createScrollbar = function (parentElement, layoutKind) {\n // abstract\n debug.assertFail(\"PureVirtualMethod: TablixDimension._createScrollbar\");\n return null;\n };\n TablixDimension.prototype.updateScrollPosition = function () {\n this._scrollItems = [];\n if (!this.model) {\n return;\n }\n var firstVisibleScrollIndex = this.getIntegerScrollOffset();\n var firstVisible = this._hierarchyNavigator.getLeafAt(this.model, firstVisibleScrollIndex);\n if (!firstVisible) {\n return;\n }\n this._firstVisibleScrollIndex = firstVisibleScrollIndex;\n do {\n this._scrollItems[this._hierarchyNavigator.getLevel(firstVisible)] = firstVisible;\n firstVisible = this._hierarchyNavigator.getParent(firstVisible);\n } while (firstVisible !== null);\n };\n return TablixDimension;\n }());\n controls.TablixDimension = TablixDimension;\n var TablixRowDimension = (function (_super) {\n __extends(TablixRowDimension, _super);\n function TablixRowDimension(tablixControl) {\n _super.call(this, tablixControl);\n this._layoutManager = this._tablixLayoutManager.rowLayoutManager;\n this._footer = null;\n }\n TablixRowDimension.prototype.setFooter = function (footerHeader) {\n this._footer = footerHeader;\n this._owner.updateFooterVisibility();\n };\n TablixRowDimension.prototype.hasFooter = function () {\n return (this._footer !== null);\n };\n /**\n * This method first populates the footer followed by each row and their correlating body cells from top to bottom.\n */\n TablixRowDimension.prototype._render = function () {\n var firstVisibleRowItem = this.getFirstVisibleItem(0);\n if (this.hasFooter()) {\n this.addFooterRowHeader(this._footer);\n this.addFooterBodyCells(this._footer);\n }\n if (firstVisibleRowItem !== undefined) {\n this.addNodes(this.model, 0, this.getDepth(), this._hierarchyNavigator.getIndex(firstVisibleRowItem));\n }\n };\n TablixRowDimension.prototype._createScrollbar = function (parentElement, layoutKind) {\n return new controls.VerticalScrollbar(parentElement, layoutKind);\n };\n /**\n * This function is a recursive call (with its recursive behavior in addNode()) that will navigate\n * through the row hierarchy in DFS (Depth First Search) order and continue into a single row\n * upto its estimated edge.\n */\n TablixRowDimension.prototype.addNodes = function (items, rowIndex, depth, firstVisibleIndex) {\n var count = this._hierarchyNavigator.getCount(items);\n //for loop explores children of current \"items\"\n for (var i = firstVisibleIndex; i < count; i++) {\n if (!this._layoutManager.needsToRealize) {\n return;\n }\n var item = this._hierarchyNavigator.getAt(items, i);\n var cell = this.addNode(item, items, rowIndex, depth);\n rowIndex += cell.rowSpan; //next node is bumped down according cells vertical span\n }\n };\n TablixRowDimension.prototype.getFirstVisibleChildLeaf = function (item) {\n var leaf = item;\n while (!this._hierarchyNavigator.isLeaf(leaf)) {\n leaf = this.getFirstVisibleChild(leaf);\n }\n return leaf;\n };\n TablixRowDimension.prototype.bindRowHeader = function (item, cell) {\n this._binder.bindRowHeader(item, cell);\n };\n /**\n * This method can be thought of as the continuation of addNodes() as it continues the DFS (Depth First Search)\n * started from addNodes(). This function also handles ending the recursion with \"_needsToRealize\" being set to\n * false.\n *\n * Once the body cells are reached, populating is done linearly with addBodyCells().\n */\n TablixRowDimension.prototype.addNode = function (item, items, rowIndex, depth) {\n var previousCount;\n var rowHeaderCell = this._tablixLayoutManager.getOrCreateRowHeader(item, items, rowIndex, this._hierarchyNavigator.getLevel(item));\n var match = this.rowHeaderMatch(item, rowHeaderCell);\n if (!match) {\n this._owner._unbindCell(rowHeaderCell);\n rowHeaderCell.type = 1 /* RowHeader */;\n rowHeaderCell.item = item;\n rowHeaderCell.unfixRowHeight();\n }\n if (this._hierarchyNavigator.isLeaf(item)) {\n rowHeaderCell.colSpan = depth - this._hierarchyNavigator.getLevel(item);\n rowHeaderCell.rowSpan = 1;\n if (!match)\n this.bindRowHeader(item, rowHeaderCell);\n this._tablixLayoutManager.onRowHeaderRealized(item, rowHeaderCell);\n this.addBodyCells(item, items, rowIndex);\n }\n else {\n previousCount = this._layoutManager.getRealizedItemsCount();\n this.addNodes(this._hierarchyNavigator.getChildren(item), rowIndex, depth, this.getFirstVisibleChildIndex(item));\n rowHeaderCell.colSpan = 1;\n rowHeaderCell.rowSpan = this._layoutManager.getRealizedItemsCount() - previousCount + 1;\n if (!match)\n this.bindRowHeader(item, rowHeaderCell);\n this._tablixLayoutManager.onRowHeaderRealized(item, rowHeaderCell);\n }\n return rowHeaderCell;\n };\n TablixRowDimension.prototype.rowHeaderMatch = function (item, cell) {\n var previousItem = cell.item;\n return cell.type === 1 /* RowHeader */ && previousItem && this._hierarchyNavigator.headerItemEquals(item, previousItem);\n };\n TablixRowDimension.prototype.addBodyCells = function (item, items, rowIndex) {\n var firstVisibleColumnIndex = this._otherDimension.getIntegerScrollOffset();\n var columnCount = this._otherDimension._layoutManager.getRealizedItemsCount() - this.getDepth();\n var hierarchyNavigator = this._hierarchyNavigator;\n var otherModel = this._otherDimension.model;\n var layoutManager = this._tablixLayoutManager;\n for (var i = 0; i < columnCount; i++) {\n //get column header \"item\" by index to pair up with row header to find corelating body cell\n var cellItem = hierarchyNavigator.getIntersection(item, hierarchyNavigator.getLeafAt(otherModel, firstVisibleColumnIndex + i));\n var cell = layoutManager.getOrCreateBodyCell(cellItem, item, items, rowIndex, i);\n this.bindBodyCell(cellItem, cell);\n layoutManager.onBodyCellRealized(cellItem, cell);\n }\n };\n TablixRowDimension.prototype.bindBodyCell = function (item, cell) {\n var match = this.bodyCelMatch(item, cell);\n if (!match) {\n this._owner._unbindCell(cell);\n cell.type = 3 /* BodyCell */;\n cell.item = item;\n cell.unfixRowHeight();\n this._binder.bindBodyCell(item, cell);\n }\n };\n TablixRowDimension.prototype.addFooterRowHeader = function (item) {\n var cell = this._tablixLayoutManager.getOrCreateFooterRowHeader(item, this.model);\n cell.colSpan = this.getDepth();\n var match = this.rowHeaderMatch(item, cell);\n if (!match) {\n this._owner._unbindCell(cell);\n cell.type = 1 /* RowHeader */;\n cell.item = item;\n cell.unfixRowHeight();\n this.bindRowHeader(item, cell);\n this._tablixLayoutManager.onRowHeaderFooterRealized(item, cell);\n }\n };\n TablixRowDimension.prototype.addFooterBodyCells = function (rowItem) {\n var firstVisibleColumnIndex = this._otherDimension.getIntegerScrollOffset();\n var columnCount = this._otherDimension.layoutManager.getRealizedItemsCount() - this.getDepth();\n var layoutManager = this._tablixLayoutManager;\n for (var i = 0; i < columnCount; i++) {\n //get column header \"item\" by index to pair up with row header to find corelating body cell\n var columnItem = this._hierarchyNavigator.getLeafAt(this._otherDimension.model, firstVisibleColumnIndex + i);\n //get corelating body cell and bind it\n var item = this._hierarchyNavigator.getIntersection(rowItem, columnItem);\n var cell = layoutManager.getOrCreateFooterBodyCell(item, i);\n this.bindBodyCell(item, cell);\n layoutManager.onBodyCellFooterRealized(item, cell);\n }\n };\n TablixRowDimension.prototype.bodyCelMatch = function (item, cell) {\n var previousItem = cell.item;\n return cell.type === 3 /* BodyCell */ && previousItem && this._hierarchyNavigator.bodyCellItemEquals(item, previousItem);\n };\n return TablixRowDimension;\n }(TablixDimension));\n controls.TablixRowDimension = TablixRowDimension;\n var TablixColumnDimension = (function (_super) {\n __extends(TablixColumnDimension, _super);\n function TablixColumnDimension(tablixControl) {\n _super.call(this, tablixControl);\n this._layoutManager = this._tablixLayoutManager.columnLayoutManager;\n }\n TablixColumnDimension.prototype._render = function () {\n var firstVisibleColumnItem = this.getFirstVisibleItem(0);\n if (firstVisibleColumnItem !== undefined) {\n this.addNodes(this.model, 0, this.getDepth(), this._hierarchyNavigator.getIndex(firstVisibleColumnItem));\n }\n };\n TablixColumnDimension.prototype._createScrollbar = function (parentElement, layoutKind) {\n var scrollbar = new controls.HorizontalScrollbar(parentElement, layoutKind);\n // Set smallest increment of the scrollbar to 0.2 rows\n scrollbar.smallIncrement = 0.2;\n return scrollbar;\n };\n TablixColumnDimension.prototype.addNodes = function (items, columnIndex, depth, firstVisibleIndex) {\n var count = this._hierarchyNavigator.getCount(items);\n for (var i = firstVisibleIndex; i < count; i++) {\n if (!this._layoutManager.needsToRealize) {\n return;\n }\n var cell = this.addNode(this._hierarchyNavigator.getAt(items, i), items, columnIndex, depth);\n columnIndex += cell.colSpan;\n }\n };\n TablixColumnDimension.prototype.addNode = function (item, items, columnIndex, depth) {\n var cell = this._tablixLayoutManager.getOrCreateColumnHeader(item, items, this._hierarchyNavigator.getLevel(item), columnIndex);\n var match = this.columnHeaderMatch(item, cell);\n if (!match) {\n this._owner._unbindCell(cell);\n cell.type = 2 /* ColumnHeader */;\n cell.item = item;\n cell.unfixRowHeight();\n }\n if (this._hierarchyNavigator.isLeaf(item)) {\n cell.rowSpan = depth - this._hierarchyNavigator.getLevel(item);\n }\n else {\n var previousCount = this._layoutManager.getRealizedItemsCount();\n this.addNodes(this._hierarchyNavigator.getChildren(item), columnIndex, depth, this.getFirstVisibleChildIndex(item));\n // In case we have a grand total with multiple measures, the multi-measures will be direct children\n // There can be difference in level > 1. In this case, we want the Total cell to have rowspan = the difference\n var childrenLevelDifference = this._hierarchyNavigator.getChildrenLevelDifference(item);\n if (childrenLevelDifference === Infinity)\n cell.rowSpan = 1;\n else\n cell.rowSpan = childrenLevelDifference;\n cell.colSpan = this._layoutManager.getRealizedItemsCount() - previousCount + 1;\n }\n if (!match)\n this._binder.bindColumnHeader(item, cell);\n this._tablixLayoutManager.onColumnHeaderRealized(item, cell);\n return cell;\n };\n TablixColumnDimension.prototype.columnHeaderMatch = function (item, cell) {\n var previousItem = cell.item;\n return cell.type === 2 /* ColumnHeader */ && previousItem && this._hierarchyNavigator.headerItemEquals(item, previousItem);\n };\n return TablixColumnDimension;\n }(TablixDimension));\n controls.TablixColumnDimension = TablixColumnDimension;\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n /**\n * This class represents the touch region of the column headers (this can also apply to footer/total).\n * This class is reponsible for interpreting gestures in terms of pixels to changes in column position.\n *\n * Unlike the table body, this can only scroll in one direction.\n */\n var ColumnTouchDelegate = (function () {\n /**\n * @constructor\n * @param region Location and area of the touch region in respect to its HTML element.\n */\n function ColumnTouchDelegate(region) {\n this.dim = region;\n this.averageSize = 1; //default\n this.handlers = null;\n this.tablixControl = null;\n }\n Object.defineProperty(ColumnTouchDelegate.prototype, \"dimension\", {\n get: function () {\n return this.dim;\n },\n enumerable: true,\n configurable: true\n });\n /**\n * Sets the amount of columns to be shifted per delta in pixels.\n *\n * @param xRatio Column to pixel ratio (# columns / # pixels).\n */\n ColumnTouchDelegate.prototype.setScrollDensity = function (xRatio) {\n this.averageSize = xRatio;\n };\n /**\n * Resize element.\n *\n * @param x X location from upper left of listened HTML element.\n * @param y Y location from upper left of listened HTML element.\n * @param width Width of area to listen for events.\n * @param height Height of area to listen for events.\n */\n ColumnTouchDelegate.prototype.resize = function (x, y, width, height) {\n this.dim.x = x;\n this.dim.y = y;\n this.dim.width = width;\n this.dim.height = height;\n };\n /**\n * @see IPixelToItem.\n */\n ColumnTouchDelegate.prototype.getPixelToItem = function (x, y, dx, dy, down) {\n return new controls.TouchUtils.TouchEvent(x * this.averageSize, 0, down, -dx * this.averageSize, 0);\n };\n /**\n * Fires event to Tablix Control to scroll with the event passed from the TouchManager.\n *\n * @param e Event recieved from touch manager.\n */\n ColumnTouchDelegate.prototype.touchEvent = function (e) {\n var args = [];\n args[0] = this.tablixControl;\n args[1] = e.dx;\n args[2] = e.dy;\n if (this.handlers) {\n controls.fire([this.handlers], args);\n }\n };\n /**\n * Asigns handler for scrolling when scroll event is fired.\n *\n * @param tablixObj TablixControl that's handling the fired event.\n * @param handlerCall The call to be made (EXAMPLE: handlerCall = object.method;).\n */\n ColumnTouchDelegate.prototype.setHandler = function (tablixObj, handlerCall) {\n this.handlers = handlerCall;\n this.tablixControl = tablixObj;\n };\n return ColumnTouchDelegate;\n }());\n controls.ColumnTouchDelegate = ColumnTouchDelegate;\n /**\n * This class represents the touch region of the row headers (left or right side aligned).\n * This class is reponsible for interpreting gestures in terms of pixels to changes in row position.\n *\n * Unlike the table body, this can only scroll in one direction.\n */\n var RowTouchDelegate = (function () {\n /**\n * @constructor\n * @param region Location and area of the touch region in respect to its HTML element.\n */\n function RowTouchDelegate(region) {\n this.dim = region;\n this.averageSize = 30; //default\n this.handlers = null;\n this.tablixControl = null;\n }\n Object.defineProperty(RowTouchDelegate.prototype, \"dimension\", {\n get: function () {\n return this.dim;\n },\n enumerable: true,\n configurable: true\n });\n /**\n * Sets the amount of rows to be shifted per delta in pixels.\n *\n * @param yRatio Row to pixel ratio (# rows / # pixels).\n */\n RowTouchDelegate.prototype.setScrollDensity = function (yRatio) {\n this.averageSize = yRatio;\n };\n /**\n * Resize element.\n * @param x X location from upper left of listened HTML element.\n * @param y Y location from upper left of listened HTML element.\n * @param width Width of area to listen for events.\n * @param height Height of area to listen for events.\n */\n RowTouchDelegate.prototype.resize = function (x, y, width, height) {\n this.dim.x = x;\n this.dim.y = y;\n this.dim.width = width;\n this.dim.height = height;\n };\n /**\n * @see: IPixelToItem\n */\n RowTouchDelegate.prototype.getPixelToItem = function (x, y, dx, dy, down) {\n var event = new controls.TouchUtils.TouchEvent(0, y * this.averageSize, down, 0, -dy * this.averageSize);\n return event;\n };\n /**\n * Fires event to Tablix Control to scroll with the event passed from the TouchManager.\n *\n * @param e Event recieved from touch manager.\n */\n RowTouchDelegate.prototype.touchEvent = function (e) {\n var args = [];\n args[0] = this.tablixControl;\n args[1] = e.dx;\n args[2] = e.dy;\n if (this.handlers) {\n controls.fire([this.handlers], args);\n }\n };\n /**\n * Asigns handler for scrolling when scroll event is fired.\n *\n * @param tablixObj TablixControl that's handling the fired event.\n * @param handlerCall The call to be made (EXAMPLE: handlerCall = object.method;).\n */\n RowTouchDelegate.prototype.setHandler = function (tablixObj, handlerCall) {\n this.handlers = handlerCall;\n this.tablixControl = tablixObj;\n };\n return RowTouchDelegate;\n }());\n controls.RowTouchDelegate = RowTouchDelegate;\n /**\n * This class represents the touch region covering the body of the table.\n * This class is reponsible for interpreting gestures in terms of pixels to\n * changes in row and column position.\n */\n var BodyTouchDelegate = (function () {\n /**\n * @constructor\n * @param region Location and area of the touch region in respect to its HTML element.\n */\n function BodyTouchDelegate(region) {\n this.dim = region;\n this.averageSizeX = BodyTouchDelegate.DefaultAverageSizeX;\n this.averageSizeY = BodyTouchDelegate.DefaultAverageSizeY;\n this.handlers = null;\n this.tablixControl = null;\n }\n Object.defineProperty(BodyTouchDelegate.prototype, \"dimension\", {\n /**\n * Returns dimension.\n *\n * @return The dimentions of the region this delegate listens to.\n */\n get: function () {\n return this.dim;\n },\n enumerable: true,\n configurable: true\n });\n /**\n * Sets the amount of rows and columns to be shifted per delta in pixels.\n *\n * @param xRatio Column to pixel ratio (# columns / # pixels)\n * @param yRatio Row to pixel ratio (# rows / # pixels)\n */\n BodyTouchDelegate.prototype.setScrollDensity = function (xRatio, yRatio) {\n this.averageSizeX = xRatio;\n this.averageSizeY = yRatio;\n };\n /**\n * Resize element.\n *\n * @param x X location from upper left of listened HTML element.\n * @param y Y location from upper left of listened HTML element.\n * @param width Width of area to listen for events.\n * @param height Height of area to listen for events.\n */\n BodyTouchDelegate.prototype.resize = function (x, y, width, height) {\n var dimension = this.dim;\n dimension.x = x;\n dimension.y = y;\n dimension.width = width;\n dimension.height = height;\n };\n /**\n * @see: IPixelToItem.\n */\n BodyTouchDelegate.prototype.getPixelToItem = function (x, y, dx, dy, down) {\n return new controls.TouchUtils.TouchEvent(x * this.averageSizeX, y * this.averageSizeY, down, -dx * this.averageSizeX, -dy * this.averageSizeY);\n };\n /**\n * Fires event to Tablix Control to scroll with the event passed from the TouchManager.\n *\n * @param e Event recieved from touch manager.\n */\n BodyTouchDelegate.prototype.touchEvent = function (e) {\n var args = [this.tablixControl, e.dx, e.dy];\n if (this.handlers) {\n controls.fire([this.handlers], args);\n }\n };\n /**\n * Asigns handler for scrolling when scroll event is fired.\n *\n * @param tablixObj TablixControl that's handling the fired event.\n * @param handlerCall The call to be made (EXAMPLE: handlerCall = object.method;).\n */\n BodyTouchDelegate.prototype.setHandler = function (tablixObj, handlerCall) {\n this.handlers = handlerCall;\n this.tablixControl = tablixObj;\n };\n BodyTouchDelegate.DefaultAverageSizeX = 30;\n BodyTouchDelegate.DefaultAverageSizeY = 30;\n return BodyTouchDelegate;\n }());\n controls.BodyTouchDelegate = BodyTouchDelegate;\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var TouchUtils;\n (function (TouchUtils) {\n var Point = (function () {\n function Point(x, y) {\n this.x = x || 0;\n this.y = y || 0;\n }\n Point.prototype.offset = function (offsetX, offsetY) {\n this.x += offsetX;\n this.y += offsetY;\n };\n return Point;\n }());\n TouchUtils.Point = Point;\n var Rectangle = (function (_super) {\n __extends(Rectangle, _super);\n function Rectangle(x, y, width, height) {\n _super.call(this, x, y);\n this.width = width || 0;\n this.height = height || 0;\n }\n Object.defineProperty(Rectangle.prototype, \"point\", {\n get: function () {\n return new Point(this.x, this.y);\n },\n enumerable: true,\n configurable: true\n });\n Rectangle.prototype.contains = function (p) {\n return Rectangle.contains(this, p);\n };\n Rectangle.contains = function (rect, p) {\n if (p && !Rectangle.isEmpty(rect)) {\n return rect.x <= p.x && p.x < rect.x + rect.width && rect.y <= p.y && p.y < rect.y + rect.height;\n }\n return false;\n };\n Rectangle.isEmpty = function (rect) {\n return !(rect !== undefined && rect.width >= 0 && rect.height >= 0);\n };\n return Rectangle;\n }(Point));\n TouchUtils.Rectangle = Rectangle;\n (function (MouseButton) {\n MouseButton[MouseButton[\"NoClick\"] = 0] = \"NoClick\";\n MouseButton[MouseButton[\"LeftClick\"] = 1] = \"LeftClick\";\n MouseButton[MouseButton[\"RightClick\"] = 2] = \"RightClick\";\n MouseButton[MouseButton[\"CenterClick\"] = 3] = \"CenterClick\";\n })(TouchUtils.MouseButton || (TouchUtils.MouseButton = {}));\n var MouseButton = TouchUtils.MouseButton;\n /**\n * A simple touch event class that's abstracted away from any platform specific traits.\n */\n var TouchEvent = (function () {\n /**\n * @constructor\n * @param x X Location of mouse.\n * @param y Y Location of mouse.\n * @param isMouseDown Indicates if the mouse button is held down or a finger press on screen.\n * @param dx (optional) The change in x of the gesture.\n * @param dy (optional) The change in y of the gesture.\n */\n function TouchEvent(x, y, isMouseDown, dx, dy) {\n this._x = x;\n this._y = y;\n this.isMouseButtonDown = isMouseDown;\n this._dx = dx || 0;\n this._dy = dy || 0;\n }\n Object.defineProperty(TouchEvent.prototype, \"x\", {\n get: function () {\n return this._x;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TouchEvent.prototype, \"y\", {\n get: function () {\n return this._y;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TouchEvent.prototype, \"dx\", {\n get: function () {\n return this._dx;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TouchEvent.prototype, \"dy\", {\n get: function () {\n return this._dy;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TouchEvent.prototype, \"isMouseDown\", {\n /**\n * Returns a boolean indicating if the mouse button is held down.\n *\n * @return: True if the the mouse button is held down,\n * otherwise false.\n */\n get: function () {\n return this.isMouseButtonDown;\n },\n enumerable: true,\n configurable: true\n });\n return TouchEvent;\n }());\n TouchUtils.TouchEvent = TouchEvent;\n /**\n * This class \"listens\" to the TouchEventInterpreter to recieve touch events and sends it to all\n * \"Touch Delegates\" with TouchRegions that contain the mouse event. Prior to sending off the\n * event, its position is put in respect to the delegate's TouchRegion and converted to the appropriate\n * unit (see IPixelToItem).\n */\n var TouchManager = (function () {\n /**\n * Default constructor.\n *\n * The default behavior is to enable thresholds and lock to axis.\n */\n function TouchManager() {\n this.touchList = [];\n this.swipeDirection = 2 /* FreeForm */;\n this.matchingDirectionCount = 0;\n this.lockThreshold = true;\n this.scrollThreshold = true;\n this.lastTouchEvent = new TouchEvent(0, 0, false);\n }\n Object.defineProperty(TouchManager.prototype, \"lastEvent\", {\n get: function () {\n return this.lastTouchEvent;\n },\n enumerable: true,\n configurable: true\n });\n /**\n * @param region Rectangle indicating the locations of the touch region.\n * @param handler Handler for recieved touch events.\n * @param converter Converts from pixels to the wanted item of measure (rows, columns, etc).\n *\n * EXAMPLE: dx -> from # of pixels to the right to # of columns moved to the right.\n */\n TouchManager.prototype.addTouchRegion = function (region, handler, converter) {\n var item = {\n lastPoint: new TouchEvent(0, 0, false),\n handler: handler,\n region: region,\n converter: converter\n };\n this.touchList = this.touchList.concat([item]);\n };\n /**\n * Sends a mouse up event to all regions with their last event as a mouse down event.\n */\n TouchManager.prototype.upAllTouches = function () {\n var eventPoint;\n var length;\n length = this.touchList.length;\n for (var i = 0; i < length; i++) {\n if (this.touchList[i].lastPoint.isMouseDown) {\n eventPoint = this.touchList[i].converter.getPixelToItem(this.touchList[i].lastPoint.x, this.touchList[i].lastPoint.y, 0, 0, false);\n this.touchList[i].handler.touchEvent(eventPoint);\n }\n this.touchList[i].lastPoint = new TouchEvent(this.touchList[i].lastPoint.x, this.touchList[i].lastPoint.y, false);\n }\n this.lastTouchEvent = new TouchEvent(0, 0, false);\n };\n TouchManager.prototype.touchEvent = function (e) {\n var list;\n var length;\n var x = 0;\n var y = 0;\n var dx = 0;\n var dy = 0;\n var angle = 0;\n var eventPoint = null;\n //assume there are already regions in the middle of a drag event and get those regions\n list = this._getActive();\n //if this is the start of a mouse drag event, repopulate the list with touched regions\n if (!this.lastTouchEvent.isMouseDown && e.isMouseDown) {\n list = this._findRegions(e);\n }\n //determine the delta values and update last event (delta ignored on first mouse down event)\n dx = this.lastTouchEvent.x - e.x;\n dy = this.lastTouchEvent.y - e.y;\n this.lastTouchEvent = new TouchEvent(e.x, e.y, e.isMouseDown, dx, dy);\n //go through the list\n length = list.length;\n for (var i = 0; i < length; i++) {\n x = e.x - list[i].region.point.x;\n y = e.y - list[i].region.point.y;\n //is this in the middle of a drag?\n if (list[i].lastPoint.isMouseDown && e.isMouseDown) {\n dx = x - list[i].lastPoint.x;\n dy = y - list[i].lastPoint.y;\n //calculate the absolute angle from the horizontal axis\n angle = Math.abs(180 / Math.PI * Math.atan(dy / dx));\n if (this.scrollThreshold) {\n //is the gesture already locked? (6 prior events within the threshold)\n if (this.lockThreshold && (this.matchingDirectionCount > 5)) {\n if (this.swipeDirection === 1 /* Horizontal */) {\n dy = 0;\n }\n else if (this.swipeDirection === 0 /* Vertical */) {\n dx = 0;\n }\n }\n else {\n //is it within the horizontal threshold?\n if (angle < 20) {\n dy = 0;\n if (this.swipeDirection === 1 /* Horizontal */) {\n this.matchingDirectionCount++;\n }\n else {\n this.matchingDirectionCount = 1;\n this.swipeDirection = 1 /* Horizontal */;\n }\n }\n else {\n //calculate the absolute angle from the vertical axis\n angle = Math.abs(180 / Math.PI * Math.atan(dx / dy));\n //is it within the horizontal threshold?\n if (angle < 20) {\n dx = 0;\n if (this.swipeDirection === 0 /* Vertical */) {\n this.matchingDirectionCount++;\n }\n else {\n this.matchingDirectionCount = 1;\n this.swipeDirection = 0 /* Vertical */;\n }\n }\n else {\n if (this.swipeDirection === 2 /* FreeForm */) {\n this.matchingDirectionCount++;\n }\n else {\n this.swipeDirection = 2 /* FreeForm */;\n this.matchingDirectionCount = 1;\n }\n }\n }\n }\n }\n }\n else {\n dx = 0;\n dy = 0;\n this.swipeDirection = 2 /* FreeForm */;\n this.matchingDirectionCount = 0;\n }\n list[i].lastPoint = new TouchEvent(x, y, e.isMouseDown, dx, dy);\n eventPoint = list[i].converter.getPixelToItem(x, y, dx, dy, e.isMouseDown);\n list[i].handler.touchEvent(eventPoint);\n }\n };\n /**\n * @param e Position of event used to find touched regions\n * @return Array of regions that contain the event point.\n */\n TouchManager.prototype._findRegions = function (e) {\n var list = [];\n var length;\n length = this.touchList.length;\n for (var i = 0; i < length; i++) {\n if (this.touchList[i].region.contains(new Point(e.x, e.y))) {\n list = list.concat([this.touchList[i]]);\n }\n }\n return list;\n };\n /**\n * @return Array of regions that contain a mouse down event. (see ITouchHandlerSet.lastPoint).\n */\n TouchManager.prototype._getActive = function () {\n var list = [];\n var length;\n length = this.touchList.length;\n for (var i = 0; i < length; i++) {\n if (this.touchList[i].lastPoint.isMouseDown) {\n list = list.concat([this.touchList[i]]);\n }\n }\n return list;\n };\n return TouchManager;\n }());\n TouchUtils.TouchManager = TouchManager;\n var MinDistanceForSwipe = 80;\n var MaxTimeForSwipe = 600;\n /**\n * This class is responsible for establishing connections to handle touch events\n * and to interpret those events so they're compatible with the touch abstractions.\n *\n * Touch events with platform specific handles should be done here.\n */\n var TouchEventInterpreter = (function () {\n function TouchEventInterpreter(manager) {\n this.manager = manager;\n this.allowMouseDrag = true;\n this.touchPanel = null;\n this.scale = 1;\n this.documentMouseMoveWrapper = null;\n this.documentMouseUpWrapper = null;\n this.sliding = false;\n }\n TouchEventInterpreter.prototype.initTouch = function (panel, touchReferencePoint, allowMouseDrag) {\n var _this = this;\n panel.style.setProperty(\"-ms-touch-action\", \"pinch-zoom\");\n this.touchReferencePoint = touchReferencePoint;\n this.touchPanel = panel;\n this.allowMouseDrag = allowMouseDrag === undefined ? true : allowMouseDrag;\n if (\"ontouchmove\" in panel) {\n panel.addEventListener(\"touchstart\", function (e) { return _this.onTouchStart(e); });\n panel.addEventListener(\"touchend\", function (e) { return _this.onTouchEnd(e); });\n }\n else {\n panel.addEventListener(\"mousedown\", function (e) { return _this.onTouchMouseDown(e); });\n panel.addEventListener(\"mouseup\", function (e) { return _this.onTouchMouseUp(e); });\n }\n };\n TouchEventInterpreter.prototype.getXYByClient = function (pageX, pageY, rect) {\n var x = rect.left;\n var y = rect.top;\n // Fix for Safari\n if (window[\"scrollX\"] !== undefined) {\n x += window[\"scrollX\"];\n y += window[\"scrollY\"];\n }\n var point = new Point(0, 0);\n point.offset(pageX - x, pageY - y);\n return point;\n };\n TouchEventInterpreter.prototype.onTouchStart = function (e) {\n if (e.touches.length === 1) {\n e.cancelBubble = true;\n var mouchEvent = e.touches[0];\n this.touchStartTime = new Date().getTime();\n this.touchStartPageY = mouchEvent.pageY;\n this.onTouchMouseDown(mouchEvent);\n }\n };\n TouchEventInterpreter.prototype.onTouchMove = function (e) {\n if (e.touches.length === 1) {\n if (e.preventDefault) {\n e.preventDefault();\n }\n var mouchEvent = e.touches[0];\n this.touchLastPageY = mouchEvent.pageY;\n this.touchLastPageX = mouchEvent.pageX;\n // while sliding ignore the touch move event \n if (!this.sliding) {\n this.onTouchMouseMove(mouchEvent);\n }\n }\n };\n TouchEventInterpreter.prototype.onTouchEnd = function (e) {\n this.clearTouchEvents();\n var swipeInfo = this.getSwipeInfo();\n if (this.didUserSwipe(swipeInfo)) {\n this.startSlideAffect(swipeInfo);\n }\n else if (!this.sliding) {\n this.upAllTouches();\n }\n };\n TouchEventInterpreter.prototype.onTouchMouseDown = function (e) {\n var _this = this;\n this.scale = controls.HTMLElementUtils.getAccumulatedScale(this.touchPanel);\n //any prior touch scrolling that produced a selection outside Tablix will prevent the next touch scroll (1262519)\n document.getSelection().removeAllRanges();\n this.rect = (this.touchReferencePoint ? this.touchReferencePoint : this.touchPanel).getBoundingClientRect();\n if (\"ontouchmove\" in this.touchPanel) {\n this.documentMouseMoveWrapper = function (e) { return _this.onTouchMove(e); };\n document.addEventListener(\"touchmove\", this.documentMouseMoveWrapper);\n this.documentMouseUpWrapper = function (e) { return _this.onTouchEnd(e); };\n document.addEventListener(\"touchend\", this.documentMouseUpWrapper);\n }\n else {\n this.documentMouseMoveWrapper = function (e) { return _this.onTouchMouseMove(e); };\n document.addEventListener(\"mousemove\", this.documentMouseMoveWrapper);\n this.documentMouseUpWrapper = function (e) { return _this.onTouchMouseUp(e); };\n document.addEventListener(\"mouseup\", this.documentMouseUpWrapper);\n }\n if (\"setCapture\" in this.touchPanel) {\n this.touchPanel.setCapture();\n }\n };\n TouchEventInterpreter.prototype.onTouchMouseMove = function (e) {\n var event;\n var point;\n var rect = this.rect;\n var validMouseDragEvent = (rect !== null) && (e.which !== MouseButton.NoClick);\n // Ignore events that are not part of a drag event\n if (!validMouseDragEvent || this.sliding)\n return;\n point = this.getXYByClient(e.pageX, e.pageY, rect);\n event = new TouchEvent(point.x / this.scale, point.y / this.scale, validMouseDragEvent);\n this.manager.touchEvent(event);\n if (e.preventDefault)\n e.preventDefault();\n else if (\"returnValue\" in e)\n e[\"returnValue\"] = false;\n };\n TouchEventInterpreter.prototype.onTouchMouseUp = function (e, bubble) {\n this.upAllTouches();\n this.clearTouchEvents();\n };\n TouchEventInterpreter.prototype.getSwipeInfo = function () {\n var touchEndTime = new Date().getTime();\n var touchTime = touchEndTime - this.touchStartTime;\n var touchDist = this.touchLastPageY - this.touchStartPageY;\n var touchDirection = touchDist < 0 ? -1 : 1;\n return {\n direction: touchDirection,\n distance: touchDist,\n endTime: touchEndTime,\n time: touchTime,\n };\n };\n TouchEventInterpreter.prototype.didUserSwipe = function (swipeInfo) {\n return swipeInfo.time < MaxTimeForSwipe && swipeInfo.distance * swipeInfo.direction > MinDistanceForSwipe;\n };\n /**\n * In case of swipe - auto advance to the swipe direction in 2 steps.\n */\n TouchEventInterpreter.prototype.startSlideAffect = function (swipeInfo) {\n var _this = this;\n if (this.sliding) {\n return;\n }\n this.sliding = true;\n var point = this.getXYByClient(this.touchLastPageX, this.touchLastPageY, this.rect);\n this.slide(point, 300, swipeInfo);\n // second step\n requestAnimationFrame(function () {\n // in case the user is now scrolling in the opposite direction stop the slide\n if (!_this.didUserChangeDirection(swipeInfo)) {\n _this.slide(point, 200, swipeInfo);\n }\n _this.clearSlide();\n });\n };\n TouchEventInterpreter.prototype.didUserChangeDirection = function (swipeInfo) {\n if (this.touchStartTime <= swipeInfo.endTime) {\n return false;\n }\n var updatedDist = this.touchLastPageY - this.touchStartPageY;\n var updatedDirection = updatedDist < 0 ? -1 : 1;\n return updatedDirection !== swipeInfo.direction;\n };\n TouchEventInterpreter.prototype.slide = function (point, slideDist, swipeInfo) {\n var updatedDist = this.touchStartTime > swipeInfo.endTime ? this.touchLastPageY - this.touchStartPageY : 0;\n point.y += slideDist * swipeInfo.direction + updatedDist;\n var event = new TouchEvent(point.x / this.scale, point.y / this.scale, true);\n this.manager.touchEvent(event);\n };\n TouchEventInterpreter.prototype.clearSlide = function () {\n this.sliding = false;\n this.upAllTouches();\n };\n TouchEventInterpreter.prototype.upAllTouches = function () {\n if (this.documentMouseMoveWrapper !== null)\n return;\n this.rect = null;\n this.manager.upAllTouches();\n };\n TouchEventInterpreter.prototype.clearTouchEvents = function () {\n if (\"releaseCapture\" in this.touchPanel) {\n this.touchPanel.releaseCapture();\n }\n if (this.documentMouseMoveWrapper === null)\n return;\n if (\"ontouchmove\" in this.touchPanel) {\n document.removeEventListener(\"touchmove\", this.documentMouseMoveWrapper);\n document.removeEventListener(\"touchend\", this.documentMouseUpWrapper);\n }\n else {\n document.removeEventListener(\"mousemove\", this.documentMouseMoveWrapper);\n document.removeEventListener(\"mouseup\", this.documentMouseUpWrapper);\n }\n this.documentMouseMoveWrapper = null;\n this.documentMouseUpWrapper = null;\n };\n return TouchEventInterpreter;\n }());\n TouchUtils.TouchEventInterpreter = TouchEventInterpreter;\n })(TouchUtils = controls.TouchUtils || (controls.TouchUtils = {}));\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n (function (TablixType) {\n TablixType[TablixType[\"Matrix\"] = 0] = \"Matrix\";\n TablixType[TablixType[\"Table\"] = 1] = \"Table\";\n })(controls.TablixType || (controls.TablixType = {}));\n var TablixType = controls.TablixType;\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var controls;\n (function (controls) {\n var PropAutoSizeWidth = controls.internal.TablixObjects.PropGeneralAutoSizeColumns;\n var getMetadataObjects = controls.internal.TablixObjects.getMetadadataObjects;\n var TablixColumnWidthManager = (function () {\n function TablixColumnWidthManager(dataView, isMatrix, hostPersistCallBack, matrixLeafNodes) {\n this.columnWidthObjects = [];\n this.isMatrix = isMatrix;\n this.updateDataView(dataView, matrixLeafNodes);\n this.hostPersistCallBack = hostPersistCallBack;\n }\n /**\n * Update the current DataView\n * @param {dataView} DataView new DataView\n * @param {MatrixVisualNode[]} matrixLeafNodes? (Optional)Matrix Leaf Nodes\n */\n TablixColumnWidthManager.prototype.updateDataView = function (dataView, matrixLeafNodes) {\n this.previousDataView = this.currentDataView;\n if (this.previousDataView)\n this.previousAutoColumnSizePropertyValue = PropAutoSizeWidth.getValue(getMetadataObjects(this.previousDataView));\n else\n this.previousAutoColumnSizePropertyValue = undefined;\n this.currentDataView = dataView;\n if (this.currentDataView)\n this.currentAutoColumnSizePropertyValue = PropAutoSizeWidth.getValue(getMetadataObjects(this.currentDataView));\n else\n this.currentAutoColumnSizePropertyValue = undefined;\n this.matrixLeafNodes = matrixLeafNodes;\n this.updateColumnWidthObjects();\n this.updateTablixColumnWidths();\n };\n /**\n * Destroy columnWidthObjects and construct it again from the currently displayed Columns\n */\n TablixColumnWidthManager.prototype.updateColumnWidthObjects = function () {\n this.columnWidthObjects.length = 0;\n if (this.isMatrix)\n this.updateMatrixColumnWidthObjects();\n else\n this.updateTableColumnWidthObjects();\n };\n TablixColumnWidthManager.prototype.updateTableColumnWidthObjects = function () {\n if (this.currentDataView && this.currentDataView.table) {\n var columnMetaData = this.currentDataView.table.columns;\n for (var i = 0, len = columnMetaData.length; i < len; i++) {\n var query = columnMetaData[i].queryName;\n this.columnWidthObjects.push({\n queryName: query,\n width: undefined\n });\n }\n }\n };\n TablixColumnWidthManager.prototype.updateMatrixColumnWidthObjects = function () {\n // Matrix visual columns are row headers and column hierarchy leaves\n if (this.currentDataView && this.currentDataView.matrix && this.currentDataView.matrix.rows) {\n // Get query names of row groups (row headers)\n for (var i = 0, len = this.currentDataView.matrix.rows.levels.length; i < len; i++) {\n var rowGroup = this.currentDataView.matrix.rows.levels[i]; // TODO: Investigate multi-source groups\n if (!_.isEmpty(rowGroup.sources))\n this.columnWidthObjects.push({\n queryName: rowGroup.sources[0].queryName,\n width: undefined\n });\n }\n }\n // Get query names of columns leaves or values\n if (this.matrixLeafNodes) {\n for (var i = 0, len = this.matrixLeafNodes.length; i < len; i++) {\n var query = this.matrixLeafNodes[i].queryName;\n this.columnWidthObjects.push({\n queryName: query,\n width: undefined\n });\n }\n }\n };\n /**\n * Update the column widths after a dataViewChange\n */\n TablixColumnWidthManager.prototype.updateTablixColumnWidths = function () {\n var columnMetaData = this.currentDataView && this.currentDataView.metadata && this.currentDataView.metadata.columns;\n if (columnMetaData) {\n // Auto-Size false to true.\n // Blow away any saved widths and revert back to default of calculating column sizes\n if (this.shouldClearAllColumnWidths()) {\n this.autoSizeAllColumns();\n }\n else {\n this.deserializeColumnWidths(columnMetaData);\n }\n }\n };\n /**\n * Read the Column Widths from the Columns metadata\n * @param {DataViewMetadataColumn[]} columnMetaData Columns metadata\n */\n TablixColumnWidthManager.prototype.deserializeColumnWidths = function (columnMetaData) {\n // Clear existing widths\n this.columnWidthObjects.forEach(function (obj) {\n obj.width = undefined;\n });\n for (var _i = 0, columnMetaData_1 = columnMetaData; _i < columnMetaData_1.length; _i++) {\n var column = columnMetaData_1[_i];\n var columnWidthPropValue = powerbi.DataViewObjects.getValue(column.objects, TablixColumnWidthManager.columnWidthProp);\n if (!_.isNumber(columnWidthPropValue)) {\n continue;\n }\n for (var _a = 0, _b = this.columnWidthObjects; _a < _b.length; _a++) {\n var obj = _b[_a];\n if (obj.queryName === column.queryName) {\n obj.width = columnWidthPropValue;\n }\n }\n }\n };\n /**\n * Returns a value indicating that autoSizeColumns was flipped from true to false\n */\n TablixColumnWidthManager.prototype.shouldPersistAllColumnWidths = function () {\n // We don't have a previous DataView -> Don't persist\n if (!this.previousDataView)\n // TODO: 6928446\n // Once 6927388 gets fixed, we need to persist the DataView is first loaded with AutoSize off to count for missing set widths\n return false;\n else\n return !this.currentAutoColumnSizePropertyValue && this.previousAutoColumnSizePropertyValue;\n };\n /**\n * Returns a value indicating that autoSizeColumns was flipped from false to true\n */\n TablixColumnWidthManager.prototype.shouldClearAllColumnWidths = function () {\n return this.previousDataView != null && this.previousAutoColumnSizePropertyValue === false\n && this.currentDataView != null && this.currentAutoColumnSizePropertyValue === true;\n };\n /**\n * Returns the current columnWidthObjects\n * @returns current columnWidthObjects including undefined widths for autosized columns\n */\n TablixColumnWidthManager.prototype.getColumnWidthObjects = function () {\n return this.columnWidthObjects;\n };\n /**\n * Returns the current columnWidthObjects for only the fixed-size columns\n * @returns Returns the current columnWidthObjects excluding auto-sized columns\n */\n TablixColumnWidthManager.prototype.getFixedColumnWidthObjects = function () {\n return this.columnWidthObjects.filter(function (obj) {\n return obj.width != null;\n });\n };\n /**\n * Get the persisted width of a certain column in px, or undefined if the columns is set to autosize or index is out of range\n * @param {number} index index of the Column\n * @returns Column persisted width in pixel\n */\n TablixColumnWidthManager.prototype.getPersistedColumnWidth = function (index) {\n var colIndex = this.isMatrix ? index : index - 1;\n var item = this.columnWidthObjects[colIndex];\n if (item)\n return item.width;\n else\n return undefined;\n };\n /**\n * Call the host to persist the data\n * @param {boolean} generateInstances\n */\n TablixColumnWidthManager.prototype.callHostToPersist = function (generateInstances) {\n if (generateInstances)\n this.generateVisualObjectInstancesToPersist();\n if (this.hostPersistCallBack) {\n this.hostPersistCallBack(this.visualObjectInstancesToPersist);\n }\n };\n /**\n * Remove all persisted columns widths and Update visualObjectInstancesToPersist\n */\n TablixColumnWidthManager.prototype.autoSizeAllColumns = function () {\n this.visualObjectInstancesToPersist = {\n merge: [this.getAutoSizeColumnWidthObject()],\n remove: [],\n };\n for (var _i = 0, _a = this.columnWidthObjects; _i < _a.length; _i++) {\n var columnWidthObject = _a[_i];\n this.visualObjectInstancesToPersist.remove.push({\n selector: { metadata: columnWidthObject.queryName },\n objectName: 'general',\n properties: {\n columnWidth: undefined\n }\n });\n }\n this.callHostToPersist(false);\n };\n /**\n * Remove persisted column width for a specific column and Update visualObjectInstancesToPersist\n */\n TablixColumnWidthManager.prototype.onColumnAutosized = function (queryName) {\n // If AutoSize option is ON, remove the persisted value\n // Else, update the persisted value\n var width = this.currentAutoColumnSizePropertyValue ? undefined : -1;\n for (var _i = 0, _a = this.columnWidthObjects; _i < _a.length; _i++) {\n var obj = _a[_i];\n if (obj.queryName === queryName) {\n obj.width = width;\n }\n }\n ;\n // If AutoSize option is ON, remove the persisted value\n if (this.currentAutoColumnSizePropertyValue) {\n this.visualObjectInstancesToPersist = {\n remove: [{\n selector: { metadata: queryName },\n objectName: 'general',\n properties: { columnWidth: undefined }\n }],\n };\n this.callHostToPersist(false);\n }\n // Else, do nothing. A Column Resize will be triggered soon\n };\n /**\n * Handler for a column width change by the user\n * @param {number} index zero-based index of the column, including hidden row header for table\n * @param {number} width new width\n */\n TablixColumnWidthManager.prototype.onColumnWidthChanged = function (index, width) {\n // Table has a hidden row headers column\n var colIndex = this.isMatrix ? index : index - 1;\n if (_.isEmpty(this.columnWidthObjects) || colIndex < 0 || colIndex >= this.columnWidthObjects.length)\n return;\n var queryName = this.columnWidthObjects[colIndex].queryName;\n // Column Autosize\n if (width === -1) {\n this.onColumnAutosized(queryName);\n }\n else {\n for (var _i = 0, _a = this.columnWidthObjects; _i < _a.length; _i++) {\n var obj = _a[_i];\n if (obj.queryName === queryName) {\n obj.width = width;\n }\n }\n ;\n this.callHostToPersist(true);\n }\n };\n /**\n * Persist all column widths, called when autoSizeColumns flipped to false\n * @param {number[]} widthsToPersist Widths to persist, including an empty row header for table\n */\n TablixColumnWidthManager.prototype.persistAllColumnWidths = function (widthsToPersist) {\n var _this = this;\n // Table indices are offset with an empty header. \n var widths = this.isMatrix ? widthsToPersist : widthsToPersist.slice(1, widthsToPersist.length);\n // ToDo: Handle this properly\n // This happens when autosizing turns OFF before knowing all widths (lots of columns outside of ViewPort)\n if (this.columnWidthObjects.length !== widths.length) {\n return;\n }\n // Pick the maximum for each queryName\n // This will ensure going from autoSize ON to OFF will not show any ellipsis\n var dictionary = new Array();\n widths.forEach(function (w, i) {\n var query = _this.columnWidthObjects[i].queryName;\n if (dictionary[query] == null)\n dictionary[query] = w;\n else\n dictionary[query] = Math.max(w, dictionary[query]);\n });\n for (var _i = 0, _a = this.columnWidthObjects; _i < _a.length; _i++) {\n var obj = _a[_i];\n var width = dictionary[obj.queryName];\n if (width != null)\n obj.width = width;\n }\n this.callHostToPersist(true);\n };\n /**\n * Construct a ColumnAutoSize object\n * @returns ColumnAutoSize object\n */\n TablixColumnWidthManager.prototype.getAutoSizeColumnWidthObject = function () {\n return {\n selector: null,\n objectName: 'general',\n properties: {\n autoSizeColumnWidth: this.currentAutoColumnSizePropertyValue\n }\n };\n };\n /**\n * Generate visualObjectInstances with autoSizeColumns and Column Widths\n */\n TablixColumnWidthManager.prototype.generateVisualObjectInstancesToPersist = function () {\n // ToDo: Ensure lists need to be reset after call to persist\n // AutoSize Property\n this.visualObjectInstancesToPersist = {\n merge: [this.getAutoSizeColumnWidthObject()]\n };\n // Column Widths\n var added = new Array();\n for (var _i = 0, _a = this.columnWidthObjects; _i < _a.length; _i++) {\n var obj = _a[_i];\n // Only persist width if we have a valid queryName to use as selector\n // ToDo: Not sure how we can have an item without a queryName\n if (obj.queryName && _.isNumber(obj.width) && !added[obj.queryName]) {\n this.visualObjectInstancesToPersist.merge.push({\n selector: { metadata: obj.queryName },\n objectName: 'general',\n properties: {\n columnWidth: obj.width\n }\n });\n added[obj.queryName] = true;\n }\n }\n };\n /**\n * PropertyID for Column Widths (General > columnWidth)\n */\n TablixColumnWidthManager.columnWidthProp = { objectName: 'general', propertyName: 'columnWidth' };\n return TablixColumnWidthManager;\n }());\n controls.TablixColumnWidthManager = TablixColumnWidthManager;\n })(controls = visuals.controls || (visuals.controls = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * Base class for values that are animated when resized.\n */\n var AnimatedText = (function () {\n function AnimatedText(name) {\n this.mainText = jsCommon.CssConstants.createClassAndSelector('mainText');\n this.name = name;\n this.visualConfiguration = { maxFontSize: 60 };\n }\n AnimatedText.prototype.getMetaDataColumn = function (dataView) {\n if (dataView && dataView.metadata && dataView.metadata.columns) {\n for (var i = 0, ilen = dataView.metadata.columns.length; i < ilen; i++) {\n var column = dataView.metadata.columns[i];\n if (column.isMeasure) {\n this.metaDataColumn = column;\n break;\n }\n }\n }\n };\n AnimatedText.prototype.getAdjustedFontHeight = function (availableWidth, textToMeasure, seedFontHeight) {\n var textProperties = {\n fontFamily: null,\n fontSize: null,\n text: textToMeasure\n };\n var fontHeight = this.getAdjustedFontHeightCore(textProperties, availableWidth, seedFontHeight, 0);\n return fontHeight;\n };\n AnimatedText.prototype.getAdjustedFontHeightCore = function (textProperties, availableWidth, seedFontHeight, iteration) {\n // Too many attempts - just return what we have so we don't sacrifice perf\n if (iteration > 10) {\n return seedFontHeight;\n }\n textProperties.fontSize = jsCommon.PixelConverter.toString(seedFontHeight);\n var candidateLength = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n if (candidateLength < availableWidth)\n return seedFontHeight;\n return this.getAdjustedFontHeightCore(textProperties, availableWidth, seedFontHeight * 0.9, iteration + 1);\n };\n AnimatedText.prototype.clear = function () {\n this.svg.select(this.mainText.selector).text('');\n };\n AnimatedText.prototype.doValueTransition = function (startValue, endValue, displayUnitSystemType, animationOptions, duration, forceUpdate, formatter) {\n if (!forceUpdate && startValue === endValue && endValue != null)\n return;\n if (!startValue)\n startValue = 0;\n var svg = this.svg, viewport = this.currentViewport, height = viewport.height, width = viewport.width, endValueArr = [endValue], seedFontHeight = this.getSeedFontHeight(width, height), translateX = this.getTranslateX(width), translateY = this.getTranslateY(seedFontHeight), metaDataColumn = this.metaDataColumn;\n // Respect the formatter default value\n if (!formatter) {\n formatter = visuals.valueFormatter.create({\n format: this.getFormatString(metaDataColumn),\n value: endValue,\n displayUnitSystemType: displayUnitSystemType,\n formatSingleValues: true,\n allowFormatBeautification: true,\n columnType: metaDataColumn ? metaDataColumn.type : undefined\n });\n }\n var startText = formatter.format(startValue), endText = formatter.format(endValue);\n svg.attr('class', this.name);\n var textElement = svg\n .selectAll('text')\n .data(endValueArr);\n textElement\n .enter()\n .append('text')\n .attr('class', this.mainText.class);\n var fontHeight = this.getAdjustedFontHeight(width, endText, seedFontHeight);\n translateY = this.getTranslateY(fontHeight + (height - fontHeight) / 2);\n var textElementUpdate = textElement\n .text(startText)\n .attr({\n 'text-anchor': this.getTextAnchor(),\n 'font-size': fontHeight,\n 'transform': visuals.SVGUtil.translate(translateX, translateY),\n })\n .style({\n 'fill': this.style.titleText.color.value,\n })\n .call(visuals.tooltipUtils.tooltipUpdate, [startText]);\n if (endValue == null) {\n textElementUpdate.text(endText).call(visuals.tooltipUtils.tooltipUpdate, [endText]);\n }\n else if (metaDataColumn && visuals.AxisHelper.isDateTime(metaDataColumn.type)) {\n textElementUpdate.text(endText).call(visuals.tooltipUtils.tooltipUpdate, [endText]);\n }\n else {\n var interpolatedValue_1 = startValue;\n textElementUpdate\n .transition()\n .duration(duration)\n .tween('text', function (d) {\n var i = d3.interpolate(interpolatedValue_1, d);\n return function (t) {\n var num = i(t);\n this.textContent = formatter.format(num);\n };\n });\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(animationOptions);\n };\n AnimatedText.prototype.setTextColor = function (color) {\n this.style.titleText.color.value = color;\n };\n AnimatedText.prototype.getSeedFontHeight = function (boundingWidth, boundingHeight) {\n // Simply an estimate - it should eventually be modified based on the actual text length\n var estimatedSize = Math.floor(Math.min(boundingWidth, boundingHeight) * 0.75);\n var maxFontSize = this.visualConfiguration.maxFontSize;\n if (maxFontSize)\n return Math.min(maxFontSize, estimatedSize);\n return estimatedSize;\n };\n AnimatedText.prototype.getTranslateX = function (width) {\n if (this.visualConfiguration) {\n switch (this.visualConfiguration.align) {\n case 'left':\n return 0;\n case 'right':\n return width;\n }\n }\n return width / 2;\n };\n AnimatedText.prototype.getTranslateY = function (height) {\n return height;\n };\n AnimatedText.prototype.getTextAnchor = function () {\n if (this.visualConfiguration) {\n switch (this.visualConfiguration.align) {\n case 'left':\n return 'start';\n case 'right':\n return 'end';\n }\n }\n return 'middle';\n };\n AnimatedText.prototype.getFormatString = function (column) {\n debug.assertAnyValue(column, 'column');\n return visuals.valueFormatter.getFormatString(column, AnimatedText.formatStringProp);\n };\n /** Note: Public for testability */\n AnimatedText.formatStringProp = {\n objectName: 'general',\n propertyName: 'formatString',\n };\n return AnimatedText;\n }());\n visuals.AnimatedText = AnimatedText;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * Renders a number that can be animate change in value.\n */\n var AnimatedNumber = (function (_super) {\n __extends(AnimatedNumber, _super);\n function AnimatedNumber(svg, animator) {\n _super.call(this, 'animatedNumber');\n if (svg)\n this.svg = svg;\n if (animator)\n this.animator = animator;\n }\n AnimatedNumber.prototype.init = function (options) {\n this.options = options;\n var element = options.element;\n if (!this.svg)\n this.svg = d3.select(element.get(0)).append('svg');\n this.currentViewport = options.viewport;\n this.hostServices = options.host;\n this.style = options.style;\n this.updateViewportDependantProperties();\n };\n AnimatedNumber.prototype.updateViewportDependantProperties = function () {\n var viewport = this.currentViewport;\n this.svg.attr('width', viewport.width)\n .attr('height', viewport.height);\n };\n AnimatedNumber.prototype.update = function (options) {\n debug.assertValue(options, 'options');\n this.currentViewport = options.viewport;\n var dataViews = this.dataViews = options.dataViews;\n if (!dataViews || !dataViews[0]) {\n return;\n }\n var dataView = dataViews[0];\n this.updateViewportDependantProperties();\n this.getMetaDataColumn(dataView);\n var newValue = dataView && dataView.single ? dataView.single.value : 0;\n if (newValue != null) {\n this.updateInternal(newValue, options.suppressAnimations, true, this.formatter);\n }\n };\n AnimatedNumber.prototype.setFormatter = function (formatter) {\n this.formatter = formatter;\n };\n AnimatedNumber.prototype.onDataChanged = function (options) {\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\n this.update({\n dataViews: options.dataViews,\n suppressAnimations: options.suppressAnimations,\n viewport: this.currentViewport\n });\n };\n AnimatedNumber.prototype.onResizing = function (viewport) {\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\n this.update({\n dataViews: this.dataViews,\n suppressAnimations: true,\n viewport: viewport\n });\n };\n AnimatedNumber.prototype.canResizeTo = function (viewport) {\n // Temporarily disabling resize restriction.\n return true;\n };\n AnimatedNumber.prototype.updateInternal = function (target, suppressAnimations, forceUpdate, formatter) {\n if (forceUpdate === void 0) { forceUpdate = false; }\n var start = this.value || 0;\n var duration = visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n this.doValueTransition(start, target, \n /*displayUnitSystemType*/ null, this.options.animation, duration, forceUpdate, formatter);\n this.value = target;\n };\n return AnimatedNumber;\n }(visuals.AnimatedText));\n visuals.AnimatedNumber = AnimatedNumber;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var BasicShapeVisual = (function () {\n function BasicShapeVisual(options) {\n }\n Object.defineProperty(BasicShapeVisual.prototype, \"shapeType\", {\n /**property for the shape line color */\n get: function () {\n return this.data ? this.data.shapeType : BasicShapeVisual.DefaultShape;\n },\n set: function (shapeType) {\n this.data.shapeType = shapeType;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"lineColor\", {\n /**property for the shape line color */\n get: function () {\n return this.data ? this.data.lineColor : BasicShapeVisual.DefaultStrokeColor;\n },\n set: function (color) {\n this.data.lineColor = color;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"lineTransparency\", {\n /**property for the shape line transparency */\n get: function () {\n return this.data ? this.data.lineTransparency : BasicShapeVisual.DefaultLineTransValue;\n },\n set: function (trans) {\n this.data.lineTransparency = trans;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"lineWeight\", {\n /**property for the shape line weight */\n get: function () {\n return this.data ? this.data.lineWeight : BasicShapeVisual.DefaultWeightValue;\n },\n set: function (weight) {\n this.data.lineWeight = weight;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"roundEdge\", {\n /**property for the shape round edge */\n get: function () {\n return this.data ? this.data.roundEdge : BasicShapeVisual.DefaultRoundEdgeValue;\n },\n set: function (roundEdge) {\n this.data.roundEdge = roundEdge;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"showFill\", {\n /**property for showing the fill properties */\n get: function () {\n return this.data ? this.data.showFill : BasicShapeVisual.DefaultFillShowValue;\n },\n set: function (show) {\n this.data.showFill = show;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"fillColor\", {\n /**property for the shape line color */\n get: function () {\n return this.data ? this.data.fillColor : BasicShapeVisual.DefaultFillColor;\n },\n set: function (color) {\n this.data.fillColor = color;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"shapeTransparency\", {\n /**property for the shape fill transparency */\n get: function () {\n return this.data ? this.data.shapeTransparency : BasicShapeVisual.DefaultFillTransValue;\n },\n set: function (trans) {\n this.data.shapeTransparency = trans;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(BasicShapeVisual.prototype, \"angle\", {\n /**property for the shape angle */\n get: function () {\n return this.data ? this.data.angle : BasicShapeVisual.DefaultAngle;\n },\n set: function (angle) {\n this.data.angle = this.scaleTo360Deg(angle);\n },\n enumerable: true,\n configurable: true\n });\n BasicShapeVisual.prototype.init = function (options) {\n this.element = options.element;\n this.selection = d3.select(this.element.context);\n this.currentViewport = options.viewport;\n };\n BasicShapeVisual.prototype.update = function (options) {\n debug.assertValue(options, 'options');\n this.currentViewport = options.viewport;\n var dataViews = options.dataViews;\n if (!_.isEmpty(dataViews)) {\n var dataView = options.dataViews[0];\n if (dataView.metadata && dataView.metadata.objects) {\n var dataViewObject = options.dataViews[0].metadata.objects;\n this.data = this.getDataFromDataView(dataViewObject);\n }\n }\n this.render();\n };\n BasicShapeVisual.prototype.getDataFromDataView = function (dataViewObject) {\n if (dataViewObject) {\n return {\n shapeType: powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.general.shapeType, BasicShapeVisual.DefaultShape),\n lineColor: this.getValueFromColor(powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.line.lineColor, BasicShapeVisual.DefaultStrokeColor)),\n lineTransparency: powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.line.transparency, BasicShapeVisual.DefaultLineTransValue),\n lineWeight: powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.line.weight, BasicShapeVisual.DefaultWeightValue),\n roundEdge: powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.line.roundEdge, BasicShapeVisual.DefaultRoundEdgeValue),\n shapeTransparency: powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.fill.transparency, BasicShapeVisual.DefaultFillTransValue),\n fillColor: this.getValueFromColor(powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.fill.fillColor, BasicShapeVisual.DefaultFillColor)),\n showFill: powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.fill.show, BasicShapeVisual.DefaultFillShowValue),\n angle: this.scaleTo360Deg(powerbi.DataViewObjects.getValue(dataViewObject, visuals.basicShapeProps.rotation.angle, BasicShapeVisual.DefaultAngle))\n };\n }\n return null;\n };\n BasicShapeVisual.prototype.scaleTo360Deg = function (angle) {\n if (angle !== 0 && (Math.abs(angle) % 360) === 0)\n return angle;\n angle = angle % 360;\n angle = (angle + 360) % 360;\n return angle;\n };\n BasicShapeVisual.prototype.getValueFromColor = function (color) {\n return color.solid ? color.solid.color : color;\n };\n BasicShapeVisual.prototype.enumerateObjectInstances = function (options) {\n var objectInstances = [];\n switch (options.objectName) {\n case 'line':\n var instance = {\n selector: null,\n properties: {\n lineColor: this.lineColor,\n transparency: this.lineTransparency,\n weight: this.lineWeight\n },\n objectName: options.objectName\n };\n if (this.data.shapeType === visuals.basicShapeType.rectangle) {\n instance.properties['roundEdge'] = this.roundEdge;\n }\n objectInstances.push(instance);\n return objectInstances;\n case 'fill':\n if (this.shapeType !== visuals.basicShapeType.line) {\n objectInstances.push({\n selector: null,\n properties: {\n show: this.showFill,\n fillColor: this.fillColor,\n transparency: this.shapeTransparency\n },\n objectName: options.objectName\n });\n }\n return objectInstances;\n case 'rotation':\n objectInstances.push({\n selector: null,\n properties: {\n angle: this.angle\n },\n objectName: options.objectName\n });\n return objectInstances;\n }\n return null;\n };\n BasicShapeVisual.prototype.render = function () {\n this.selection.html('');\n switch (this.shapeType) {\n case visuals.basicShapeType.rectangle:\n visuals.ShapeFactory.createRectangle(this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\n break;\n case visuals.basicShapeType.oval:\n visuals.ShapeFactory.createOval(this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\n break;\n case visuals.basicShapeType.line:\n visuals.ShapeFactory.createLine(this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\n break;\n case visuals.basicShapeType.arrow:\n visuals.ShapeFactory.createUpArrow(this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\n break;\n case visuals.basicShapeType.triangle:\n visuals.ShapeFactory.createTriangle(this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\n break;\n default:\n break;\n }\n };\n BasicShapeVisual.DefaultShape = visuals.basicShapeType.rectangle;\n BasicShapeVisual.DefaultStrokeColor = '#00B8AA';\n BasicShapeVisual.DefaultFillColor = '#E6E6E6';\n BasicShapeVisual.DefaultFillShowValue = true;\n BasicShapeVisual.DefaultFillTransValue = 0;\n BasicShapeVisual.DefaultWeightValue = 3;\n BasicShapeVisual.DefaultLineTransValue = 0;\n BasicShapeVisual.DefaultRoundEdgeValue = 0;\n BasicShapeVisual.DefaultAngle = 0;\n return BasicShapeVisual;\n }());\n visuals.BasicShapeVisual = BasicShapeVisual;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var EnumExtensions = jsCommon.EnumExtensions;\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var DEFAULT_AXIS_SCALE_TYPE = visuals.axisScale.linear;\n var COMBOCHART_DOMAIN_OVERLAP_TRESHOLD_PERCENTAGE = 0.1;\n // the interactive right margin is set to be the circle selection radius of the hover line\n var INTERACTIVITY_RIGHT_MARGIN = 6;\n visuals.DEFAULT_AXIS_COLOR = '#777';\n /**\n * Renders a data series as a cartestian visual.\n */\n var CartesianChart = (function () {\n function CartesianChart(options) {\n this.xRefLine = createClassAndSelector('x-ref-line');\n this.y1RefLine = createClassAndSelector('y1-ref-line');\n var isScrollable = false;\n this.trimOrdinalDataOnOverflow = true;\n if (options) {\n this.tooltipsEnabled = options.tooltipsEnabled;\n this.type = options.chartType;\n this.isLabelInteractivityEnabled = options.isLabelInteractivityEnabled;\n this.lineChartLabelDensityEnabled = options.lineChartLabelDensityEnabled;\n if (options.trimOrdinalDataOnOverflow !== undefined)\n this.trimOrdinalDataOnOverflow = options.trimOrdinalDataOnOverflow;\n if (options.isScrollable)\n isScrollable = options.isScrollable;\n this.animator = options.animator;\n if (options.cartesianSmallViewPortProperties) {\n this.cartesianSmallViewPortProperties = options.cartesianSmallViewPortProperties;\n }\n if (options.behavior) {\n this.behavior = options.behavior;\n }\n }\n this.axes = new CartesianAxes(isScrollable, ScrollableAxes.ScrollbarWidth, this.trimOrdinalDataOnOverflow);\n this.svgAxes = new SvgCartesianAxes(this.axes);\n this.svgBrush = new SvgBrush(ScrollableAxes.ScrollbarWidth);\n this.scrollableAxes = new ScrollableAxes(this.axes, this.svgBrush);\n }\n CartesianChart.getAxisVisibility = function (type) {\n switch (type) {\n case 6 /* StackedBar */:\n case 5 /* ClusteredBar */:\n case 7 /* HundredPercentStackedBar */:\n return 1 /* ShowLinesOnXAxis */;\n case 9 /* Scatter */:\n return 3 /* ShowLinesOnBothAxis */;\n default:\n return 2 /* ShowLinesOnYAxis */;\n }\n };\n CartesianChart.prototype.init = function (options) {\n this.visualInitOptions = options;\n this.layers = [];\n var element = this.element = options.element;\n this.currentViewport = options.viewport;\n this.hostServices = options.host;\n var chartAreaSvg = this.chartAreaSvg = d3.select(element.get(0)).append('svg');\n chartAreaSvg.classed(CartesianChart.ClassName, true);\n chartAreaSvg.style('position', 'absolute');\n if (this.behavior) {\n this.clearCatcher = visuals.appendClearCatcher(chartAreaSvg);\n this.interactivityService = visuals.createInteractivityService(this.hostServices);\n }\n if (options.style.maxMarginFactor != null)\n this.axes.setMaxMarginFactor(options.style.maxMarginFactor);\n var axisLinesVisibility = CartesianChart.getAxisVisibility(this.type);\n this.axes.setAxisLinesVisibility(axisLinesVisibility);\n this.svgAxes.init(chartAreaSvg);\n this.svgBrush.init(chartAreaSvg);\n this.sharedColorPalette = new SharedColorPalette(options.style.colorPalette.dataColors);\n this.legend = visuals.createLegend(element, options.interactivity && options.interactivity.isInteractiveLegend, this.type !== 12 /* Waterfall */ ? this.interactivityService : undefined, this.axes.isScrollable);\n this.isMobileChart = options.interactivity && options.interactivity.isInteractiveLegend;\n };\n CartesianChart.prototype.isPlayAxis = function () {\n if (!this.dataViews || !this.dataViews[0])\n return false;\n var dataView = this.dataViews[0];\n var categoryRoleIsPlay = dataView.categorical\n && dataView.categorical.categories\n && dataView.categorical.categories[0]\n && dataView.categorical.categories[0].source\n && dataView.categorical.categories[0].source.roles\n && dataView.categorical.categories[0].source.roles['Play'];\n return this.type === 9 /* Scatter */\n && (this.animator || this.isMobileChart)\n && dataView.matrix != null\n && (!dataView.categorical || categoryRoleIsPlay);\n };\n CartesianChart.getIsScalar = function (objects, propertyId, type) {\n var axisTypeValue = powerbi.DataViewObjects.getValue(objects, propertyId);\n if (!objects || axisTypeValue === undefined) {\n // If we don't have anything set (Auto), show charts as Scalar if the category type is numeric or time. \n // If we have the property, it will override the type.\n return !visuals.AxisHelper.isOrdinal(type);\n }\n // also checking type here to be in sync with AxisHelper, which ignores scalar if the type is non-numeric.\n return (axisTypeValue === visuals.axisType.scalar) && !visuals.AxisHelper.isOrdinal(type);\n };\n CartesianChart.getAdditionalTelemetry = function (dataView) {\n var telemetry = {};\n var categoryColumn = dataView && dataView.categorical && _.first(dataView.categorical.categories);\n if (categoryColumn) {\n telemetry.axisType = visuals.CartesianChart.getIsScalar(dataView.metadata.objects, visuals.columnChartProps.categoryAxis.axisType, categoryColumn.source.type)\n ? 'scalar'\n : 'categorical';\n }\n return telemetry;\n };\n CartesianChart.detectScalarMapping = function (dataViewMapping) {\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\n return false;\n var dataViewCategories = dataViewMapping.categorical.categories;\n var categoryItems = dataViewCategories.for.in.items;\n if (_.isEmpty(categoryItems))\n return false;\n var categoryType = categoryItems[0].type;\n if (!dataViewMapping.metadata)\n return false;\n var objects = dataViewMapping.metadata.objects;\n return CartesianChart.getIsScalar(objects, visuals.columnChartProps.categoryAxis.axisType, categoryType);\n };\n CartesianChart.prototype.populateObjectProperties = function (dataViews) {\n if (dataViews && dataViews.length > 0) {\n var dataViewMetadata = dataViews[0].metadata;\n if (dataViewMetadata) {\n this.legendObjectProperties = powerbi.DataViewObjects.getObject(dataViewMetadata.objects, 'legend', {});\n this.xAxisReferenceLines = powerbi.DataViewObjects.getUserDefinedObjects(dataViewMetadata.objects, 'xAxisReferenceLine');\n this.y1AxisReferenceLines = powerbi.DataViewObjects.getUserDefinedObjects(dataViewMetadata.objects, 'y1AxisReferenceLine');\n }\n else {\n this.legendObjectProperties = {};\n }\n this.categoryAxisProperties = visuals.CartesianHelper.getCategoryAxisProperties(dataViewMetadata);\n this.valueAxisProperties = visuals.CartesianHelper.getValueAxisProperties(dataViewMetadata);\n }\n };\n CartesianChart.prototype.updateInternal = function (options, dataChanged) {\n var dataViews = this.dataViews = options.dataViews;\n this.currentViewport = options.viewport;\n if (!dataViews)\n return;\n if (this.layers.length === 0) {\n // Lazily instantiate the chart layers on the first data load.\n var objects = this.extractMetadataObjects(dataViews);\n this.layers = this.createAndInitLayers(objects);\n debug.assert(this.layers.length > 0, 'createAndInitLayers should update the layers.');\n }\n var layers = this.layers;\n if (dataChanged) {\n if (!_.isEmpty(dataViews)) {\n this.populateObjectProperties(dataViews);\n this.axes.update(dataViews);\n this.svgAxes.update(this.categoryAxisProperties, this.valueAxisProperties);\n var dataView = dataViews[0];\n if (dataView.metadata) {\n // flatten background data\n this.background = {\n image: powerbi.DataViewObjects.getValue(dataView.metadata.objects, visuals.scatterChartProps.plotArea.image),\n transparency: powerbi.DataViewObjects.getValue(dataView.metadata.objects, visuals.scatterChartProps.plotArea.transparency, visuals.visualBackgroundHelper.getDefaultTransparency()),\n };\n }\n }\n this.sharedColorPalette.clearPreferredScale();\n var layerDataViews = getLayerDataViews(dataViews);\n var trendLineDataViews = _.filter(dataViews, function (dataView) { return visuals.TrendLineHelper.isDataViewForRegression(dataView); });\n this.trendLines = [];\n for (var i = 0, layerCount = layers.length; i < layerCount; i++) {\n var layerDataView = layerDataViews[i];\n layers[i].setData(layerDataView ? [layerDataView] : []);\n if (this.supportsTrendLines(i)) {\n var trendLineDataView = trendLineDataViews[i];\n if (trendLineDataView) {\n var y2 = (i > 0);\n var trendLines = visuals.TrendLineHelper.readDataView(trendLineDataView, layerDataView, y2, this.sharedColorPalette);\n (_a = this.trendLines).push.apply(_a, trendLines);\n }\n }\n if (layerCount > 1)\n this.sharedColorPalette.rotateScale();\n }\n }\n this.render(!this.hasSetData || options.suppressAnimations, options.resizeMode);\n this.hasSetData = this.hasSetData || (dataViews && dataViews.length > 0);\n if (dataViews && dataViews.length > 0) {\n var warnings = visuals.getInvalidValueWarnings(dataViews, false /*supportsNaN*/, false /*supportsNegativeInfinity*/, false /*supportsPositiveInfinity*/);\n this.axes.addWarnings(warnings);\n if (warnings && warnings.length > 0)\n this.hostServices.setWarnings(warnings);\n }\n var _a;\n };\n // TODO: Remove onDataChanged & onResizing once we have a flag to distinguish between resize and data changed events.\n CartesianChart.prototype.onDataChanged = function (options) {\n this.updateInternal({\n dataViews: options.dataViews,\n suppressAnimations: options.suppressAnimations,\n viewport: this.currentViewport\n }, true);\n };\n // TODO: Remove onDataChanged & onResizing once we have a flag to distinguish between resize and data changed events.\n CartesianChart.prototype.onResizing = function (viewport, resizeMode) {\n this.updateInternal({\n dataViews: this.dataViews,\n suppressAnimations: true,\n viewport: viewport,\n resizeMode: resizeMode,\n }, false);\n };\n CartesianChart.prototype.scrollTo = function (position) {\n this.scrollableAxes.scrollTo(position);\n };\n CartesianChart.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n var layersLength = this.layers ? this.layers.length : 0;\n if (options.objectName === 'legend') {\n if (!this.shouldShowLegendCard())\n return;\n var show = powerbi.DataViewObject.getValue(this.legendObjectProperties, visuals.legendProps.show, this.legend.isVisible());\n var showTitle = powerbi.DataViewObject.getValue(this.legendObjectProperties, visuals.legendProps.showTitle, true);\n var titleText = powerbi.DataViewObject.getValue(this.legendObjectProperties, visuals.legendProps.titleText, this.layerLegendData ? this.layerLegendData.title : '');\n var labelColor = powerbi.DataViewObject.getValue(this.legendObjectProperties, visuals.legendProps.labelColor, visuals.LegendData.DefaultLegendLabelFillColor);\n var fontSize = powerbi.DataViewObject.getValue(this.legendObjectProperties, visuals.legendProps.fontSize, this.layerLegendData && this.layerLegendData.fontSize ? this.layerLegendData.fontSize : visuals.SVGLegend.DefaultFontSizeInPt);\n enumeration.pushInstance({\n selector: null,\n properties: {\n show: show,\n position: visuals.LegendPosition[this.legend.getOrientation()],\n showTitle: showTitle,\n titleText: titleText,\n labelColor: labelColor,\n fontSize: fontSize,\n },\n objectName: options.objectName\n });\n }\n else if (options.objectName === 'categoryAxis' && this.axes.hasCategoryAxis()) {\n this.getCategoryAxisValues(enumeration);\n }\n else if (options.objectName === 'valueAxis') {\n this.getValueAxisValues(enumeration);\n }\n else if (options.objectName === 'y1AxisReferenceLine') {\n var refLinedefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\n visuals.ReferenceLineHelper.enumerateObjectInstances(enumeration, this.y1AxisReferenceLines, refLinedefaultColor, options.objectName);\n }\n else if (options.objectName === 'xAxisReferenceLine') {\n var refLinedefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\n visuals.ReferenceLineHelper.enumerateObjectInstances(enumeration, this.xAxisReferenceLines, refLinedefaultColor, options.objectName);\n }\n else if (options.objectName === 'trend') {\n if (this.supportsTrendLines()) {\n visuals.TrendLineHelper.enumerateObjectInstances(enumeration, this.trendLines);\n }\n }\n else if (options.objectName === 'plotArea') {\n visuals.visualBackgroundHelper.enumeratePlot(enumeration, this.background);\n }\n if (options.objectName === 'dataPoint' &&\n visuals.ComboChart.isComboChart(this.type)) {\n visuals.ComboChart.enumerateDataPoints(enumeration, options, this.layers);\n }\n else {\n for (var i = 0, len = layersLength; i < len; i++) {\n var layer = this.layers[i];\n if (layer.enumerateObjectInstances) {\n layer.enumerateObjectInstances(enumeration, options);\n }\n }\n }\n return enumeration.complete();\n };\n CartesianChart.prototype.supportsTrendLines = function (layerIndex) {\n var layerDataViews = getLayerDataViews(this.dataViews);\n if (_.isEmpty(this.layers))\n return false;\n // If layerIndex was not given then check all layers.\n var layers = layerIndex == null ? this.layers : [this.layers[layerIndex]];\n return _.all(layers, function (layer, index) {\n if (!layerDataViews[index])\n return true;\n return layer.supportsTrendLine && layer.supportsTrendLine();\n });\n };\n CartesianChart.prototype.shouldShowLegendCard = function () {\n var layers = this.layers;\n var dataViews = this.dataViews;\n if (layers && dataViews) {\n var layersLength = layers.length;\n var layersWithValuesCtr = 0;\n for (var i = 0; i < layersLength; i++) {\n if (layers[i].hasLegend()) {\n return true;\n }\n // if there are at least two layers with values legend card should be shown (even if each of the individual layers don't have legend)\n var dataView = dataViews[i];\n if (dataView && dataView.categorical && dataView.categorical.values && dataView.categorical.values.length > 0) {\n layersWithValuesCtr++;\n if (layersWithValuesCtr > 1) {\n return true;\n }\n }\n }\n }\n return false;\n };\n CartesianChart.prototype.getAxisScaleOptions = function (axisType) {\n var scaleOptions = [DEFAULT_AXIS_SCALE_TYPE];\n if (this.axes.isLogScaleAllowed(axisType))\n scaleOptions.push(visuals.axisScale.log);\n return scaleOptions;\n };\n CartesianChart.prototype.getCategoryAxisValues = function (enumeration) {\n if (!this.categoryAxisProperties) {\n return;\n }\n var supportedType = visuals.axisType.both;\n var isScalar = false;\n var scaleOptions = this.getAxisScaleOptions(0 /* X */);\n if (this.layers && this.layers[0].getSupportedCategoryAxisType) {\n supportedType = this.layers[0].getSupportedCategoryAxisType();\n if (supportedType === visuals.axisType.scalar) {\n isScalar = true;\n }\n else {\n isScalar = visuals.CartesianHelper.isScalar(supportedType === visuals.axisType.both, this.categoryAxisProperties);\n }\n }\n if (!isScalar) {\n this.categoryAxisProperties['start'] = null;\n this.categoryAxisProperties['end'] = null;\n }\n var instance = {\n selector: null,\n properties: {},\n objectName: 'categoryAxis',\n validValues: {\n axisScale: scaleOptions,\n axisStyle: this.axes.categoryAxisHasUnitType ? [visuals.axisStyle.showTitleOnly, visuals.axisStyle.showUnitOnly, visuals.axisStyle.showBoth] : [visuals.axisStyle.showTitleOnly]\n }\n };\n instance.properties['show'] = this.categoryAxisProperties['show'] != null ? this.categoryAxisProperties['show'] : true;\n if (this.axes.isYAxisCategorical())\n instance.properties['position'] = this.valueAxisProperties && this.valueAxisProperties['position'] != null ? this.valueAxisProperties['position'] : visuals.yAxisPosition.left;\n if (supportedType === visuals.axisType.both) {\n instance.properties['axisType'] = isScalar ? visuals.axisType.scalar : visuals.axisType.categorical;\n }\n if (isScalar) {\n instance.properties['axisScale'] = this.categoryAxisProperties['axisScale'] || DEFAULT_AXIS_SCALE_TYPE;\n instance.properties['start'] = this.categoryAxisProperties['start'];\n instance.properties['end'] = this.categoryAxisProperties['end'];\n }\n instance.properties['showAxisTitle'] = this.categoryAxisProperties['showAxisTitle'] != null ? this.categoryAxisProperties['showAxisTitle'] : false;\n instance.properties['axisStyle'] = this.categoryAxisProperties['axisStyle'] ? this.categoryAxisProperties['axisStyle'] : visuals.axisStyle.showTitleOnly;\n instance.properties['labelColor'] = this.categoryAxisProperties['labelColor'] || visuals.DEFAULT_AXIS_COLOR;\n if (isScalar) {\n instance.properties['labelDisplayUnits'] = this.categoryAxisProperties['labelDisplayUnits'] ? this.categoryAxisProperties['labelDisplayUnits'] : 0;\n var labelPrecision = this.categoryAxisProperties['labelPrecision'];\n instance.properties['labelPrecision'] = (labelPrecision === undefined || labelPrecision < 0)\n ? visuals.dataLabelUtils.defaultLabelPrecision\n : labelPrecision;\n }\n enumeration.pushInstance(instance);\n };\n //todo: wrap all these object getters and other related stuff into an interface\n CartesianChart.prototype.getValueAxisValues = function (enumeration) {\n if (!this.valueAxisProperties) {\n return;\n }\n var scaleOptions = this.getAxisScaleOptions(1 /* Y1 */);\n var secScaleOption = this.getAxisScaleOptions(2 /* Y2 */);\n var instance = {\n selector: null,\n properties: {},\n objectName: 'valueAxis',\n validValues: {\n axisScale: scaleOptions,\n secAxisScale: secScaleOption,\n axisStyle: this.axes.valueAxisHasUnitType ? [visuals.axisStyle.showTitleOnly, visuals.axisStyle.showUnitOnly, visuals.axisStyle.showBoth] : [visuals.axisStyle.showTitleOnly]\n }\n };\n instance.properties['show'] = this.valueAxisProperties['show'] != null ? this.valueAxisProperties['show'] : true;\n if (!this.axes.isYAxisCategorical()) {\n instance.properties['position'] = this.valueAxisProperties['position'] != null ? this.valueAxisProperties['position'] : visuals.yAxisPosition.left;\n }\n instance.properties['axisScale'] = this.valueAxisProperties['axisScale'] || DEFAULT_AXIS_SCALE_TYPE;\n instance.properties['start'] = this.valueAxisProperties['start'];\n instance.properties['end'] = this.valueAxisProperties['end'];\n instance.properties['showAxisTitle'] = this.valueAxisProperties['showAxisTitle'] != null ? this.valueAxisProperties['showAxisTitle'] : false;\n instance.properties['axisStyle'] = this.valueAxisProperties['axisStyle'] != null ? this.valueAxisProperties['axisStyle'] : visuals.axisStyle.showTitleOnly;\n instance.properties['labelColor'] = this.valueAxisProperties['labelColor'] || visuals.DEFAULT_AXIS_COLOR;\n if (this.type !== 7 /* HundredPercentStackedBar */ && this.type !== 8 /* HundredPercentStackedColumn */) {\n instance.properties['labelDisplayUnits'] = this.valueAxisProperties['labelDisplayUnits'] ? this.valueAxisProperties['labelDisplayUnits'] : 0;\n var labelPrecision = this.valueAxisProperties['labelPrecision'];\n instance.properties['labelPrecision'] = (labelPrecision === undefined || labelPrecision < 0)\n ? visuals.dataLabelUtils.defaultLabelPrecision\n : labelPrecision;\n }\n enumeration.pushInstance(instance);\n if (this.layers.length === 2) {\n instance.properties['secShow'] = this.valueAxisProperties['secShow'] != null ? this.valueAxisProperties['secShow'] : this.axes.hasY2Axis();\n if (instance.properties['secShow']) {\n instance.properties['axisLabel'] = '';\n }\n }\n if (this.axes.hasY2Axis() && instance.properties['secShow']) {\n enumeration.pushContainer({\n displayName: powerbi.data.createDisplayNameGetter('Visual_YAxis_ShowSecondary'),\n });\n var secInstance = {\n selector: null,\n properties: {},\n objectName: 'valueAxis'\n };\n secInstance.properties['secAxisLabel'] = '';\n secInstance.properties['secPosition'] = this.valueAxisProperties['secPosition'] != null ? this.valueAxisProperties['secPosition'] : visuals.yAxisPosition.right;\n secInstance.properties['secAxisScale'] = this.valueAxisProperties['secAxisScale'] || DEFAULT_AXIS_SCALE_TYPE;\n secInstance.properties['secStart'] = this.valueAxisProperties['secStart'];\n secInstance.properties['secEnd'] = this.valueAxisProperties['secEnd'];\n secInstance.properties['secShowAxisTitle'] = this.valueAxisProperties['secShowAxisTitle'] != null ? this.valueAxisProperties['secShowAxisTitle'] : false;\n enumeration\n .pushInstance(secInstance)\n .pushInstance({\n selector: null,\n properties: {\n secAxisStyle: this.valueAxisProperties['secAxisStyle'] ? this.valueAxisProperties['secAxisStyle'] : visuals.axisStyle.showTitleOnly,\n labelColor: this.valueAxisProperties['secLabelColor'],\n secLabelDisplayUnits: this.valueAxisProperties['secLabelDisplayUnits'] ? this.valueAxisProperties['secLabelDisplayUnits'] : 0,\n secLabelPrecision: this.valueAxisProperties['secLabelPrecision'] < 0 ? 0 : this.valueAxisProperties['secLabelPrecision']\n },\n objectName: 'valueAxis',\n validValues: {\n secAxisStyle: this.axes.secondaryValueAxisHasUnitType ? [visuals.axisStyle.showTitleOnly, visuals.axisStyle.showUnitOnly, visuals.axisStyle.showBoth] : [visuals.axisStyle.showTitleOnly],\n axisScale: scaleOptions\n },\n });\n enumeration.popContainer();\n }\n };\n CartesianChart.prototype.onClearSelection = function () {\n if (this.hasSetData) {\n for (var i = 0, len = this.layers.length; i < len; i++) {\n var layer = this.layers[i];\n layer.onClearSelection();\n layer.render(true /* suppressAnimations */);\n }\n }\n };\n CartesianChart.prototype.extractMetadataObjects = function (dataViews) {\n var objects;\n if (dataViews && dataViews.length > 0) {\n var dataViewMetadata = dataViews[0].metadata;\n if (dataViewMetadata)\n objects = dataViewMetadata.objects;\n }\n return objects;\n };\n CartesianChart.prototype.createAndInitLayers = function (objects) {\n var _this = this;\n // Create the layers\n var layers = CartesianLayerFactory.createLayers(this.type, objects, this.interactivityService, this.animator, this.axes.isScrollable, this.tooltipsEnabled, this.lineChartLabelDensityEnabled);\n // Initialize the layers\n var cartesianOptions = powerbi.Prototype.inherit(this.visualInitOptions);\n cartesianOptions.svg = this.svgAxes.getScrollableRegion();\n cartesianOptions.labelsContext = this.svgAxes.getLabelsRegion();\n cartesianOptions.cartesianHost = {\n updateLegend: function (data) { return _this.legend.drawLegend(data, _this.currentViewport); },\n getSharedColors: function () { return _this.sharedColorPalette; },\n triggerRender: function (suppressAnimations) { return _this.render(suppressAnimations); },\n };\n cartesianOptions.chartType = this.type;\n for (var i = 0, len = layers.length; i < len; i++)\n layers[i].init(cartesianOptions);\n return layers;\n };\n CartesianChart.prototype.renderLegend = function () {\n var layers = this.layers;\n var legendData = { title: \"\", dataPoints: [] };\n var _loop_1 = function(i, len) {\n this_1.layerLegendData = layers[i].calculateLegend();\n if (this_1.layerLegendData) {\n legendData.title = i === 0 ? this_1.layerLegendData.title || \"\"\n : legendData.title;\n legendData.labelColor = this_1.layerLegendData.labelColor;\n // Data points have have duplicate identities (ex. Combo Chart uses a measure in both line and column).\n // Add the layer number (if it's set) so the D3 keys are different.\n if (!_.isEmpty(this_1.layerLegendData.dataPoints)) {\n this_1.layerLegendData.dataPoints.forEach(function (dataPoint) { return dataPoint.layerNumber = i; });\n }\n legendData.dataPoints = legendData.dataPoints.concat(this_1.layerLegendData.dataPoints || []);\n legendData.fontSize = this_1.layerLegendData.fontSize || visuals.SVGLegend.DefaultFontSizeInPt;\n if (this_1.layerLegendData.grouped) {\n legendData.grouped = true;\n }\n }\n };\n var this_1 = this;\n for (var i = 0, len = layers.length; i < len; i++) {\n _loop_1(i, len);\n }\n var legendProperties = this.legendObjectProperties;\n if (legendProperties) {\n visuals.LegendData.update(legendData, legendProperties);\n var position = legendProperties[visuals.legendProps.position];\n if (position)\n this.legend.changeOrientation(visuals.LegendPosition[position]);\n }\n else {\n this.legend.changeOrientation(visuals.LegendPosition.Top);\n }\n if ((legendData.dataPoints.length === 1 && !legendData.grouped) || this.hideLegends()) {\n legendData.dataPoints = [];\n }\n this.legend.drawLegend(legendData, this.currentViewport);\n };\n CartesianChart.prototype.hideLegends = function () {\n if (this.cartesianSmallViewPortProperties) {\n if (this.cartesianSmallViewPortProperties.hideLegendOnSmallViewPort && (this.currentViewport.height < this.cartesianSmallViewPortProperties.MinHeightLegendVisible)) {\n return true;\n }\n }\n return false;\n };\n CartesianChart.prototype.render = function (suppressAnimations, resizeMode) {\n var _this = this;\n // Note: interactive legend shouldn't be rendered explicitly here\n // The interactive legend is being rendered in the render method of ICartesianVisual\n if (!(this.visualInitOptions.interactivity && this.visualInitOptions.interactivity.isInteractiveLegend)) {\n this.renderLegend();\n }\n var legendMargins = this.legendMargins = this.legend.getMargins();\n var legendOrientation = this.legend.getOrientation();\n var hideAxisLabels = this.hideAxisLabels(legendMargins);\n var plotAreaViewport = {\n height: this.currentViewport.height - legendMargins.height,\n width: this.currentViewport.width - legendMargins.width\n };\n var padding = powerbi.Prototype.inherit(SvgCartesianAxes.AxisPadding);\n var playAxisControlLayout;\n if (this.isPlayAxis()) {\n plotAreaViewport.height -= CartesianChart.PlayAxisBottomMargin;\n playAxisControlLayout = {\n left: visuals.Legend.isLeft(legendOrientation) ? legendMargins.width : 0,\n top: visuals.Legend.isTop(legendOrientation) ? legendMargins.height + plotAreaViewport.height : plotAreaViewport.height,\n height: CartesianChart.PlayAxisBottomMargin,\n width: plotAreaViewport.width\n };\n }\n this.chartAreaSvg.attr({\n 'width': plotAreaViewport.width,\n 'height': plotAreaViewport.height,\n });\n visuals.Legend.positionChartArea(this.chartAreaSvg, this.legend);\n var interactivityRightMargin = this.calculateInteractivityRightMargin();\n var _a = this.getMinimumDomainExtents(), ensureXDomain = _a[0], ensureYDomain = _a[1];\n var axesLayout = this.axes.negotiateAxes(this.layers, plotAreaViewport, padding, playAxisControlLayout, hideAxisLabels, CartesianChart.AxisTextProperties, interactivityRightMargin, ensureXDomain, ensureYDomain);\n // Even if the caller thinks animations are ok, now that we've laid out the axes and legend we should disable animations\n // if the plot area changed. Animations for property changes like legend on/off are not desired.\n var plotAreaHasChanged = !this.renderedPlotArea\n || (this.renderedPlotArea.height !== axesLayout.plotArea.height ||\n this.renderedPlotArea.width !== axesLayout.plotArea.width);\n suppressAnimations = suppressAnimations || plotAreaHasChanged;\n this.scrollableAxes.render(axesLayout, this.layers, suppressAnimations, function (layers, axesLayout, suppressAnimations) { return _this.renderPlotArea(layers, axesLayout, suppressAnimations, legendMargins, resizeMode); });\n // attach scroll event\n this.chartAreaSvg.on('wheel', function () {\n if (!(_this.axes.isXScrollBarVisible || _this.axes.isYScrollBarVisible))\n return;\n visuals.TooltipManager.ToolTipInstance.hide();\n var wheelEvent = d3.event;\n var dy = wheelEvent.deltaY;\n _this.scrollableAxes.scrollDelta(dy);\n });\n this.renderedPlotArea = axesLayout.plotArea;\n };\n /**\n * Gets any minimum domain extents.\n * Reference lines and trend lines may enforce minimum extents on X and/or Y domains.\n */\n CartesianChart.prototype.getMinimumDomainExtents = function () {\n var xs = [];\n var ys = [];\n if (!_.isEmpty(this.xAxisReferenceLines)) {\n var xAxisReferenceLineProperties = this.xAxisReferenceLines[0].object;\n var value = visuals.ReferenceLineHelper.extractReferenceLineValue(xAxisReferenceLineProperties);\n xs.push(value);\n }\n if (!_.isEmpty(this.y1AxisReferenceLines)) {\n var y1AxisReferenceLineProperties = this.y1AxisReferenceLines[0].object;\n var value = visuals.ReferenceLineHelper.extractReferenceLineValue(y1AxisReferenceLineProperties);\n ys.push(value);\n }\n var ensureXDomain = {\n min: d3.min(xs),\n max: d3.max(xs)\n };\n var ensureYDomain = {\n min: d3.min(ys),\n max: d3.max(ys)\n };\n return [ensureXDomain, ensureYDomain];\n };\n CartesianChart.prototype.getPlotAreaRect = function (axesLayout, legendMargins) {\n var rect = {\n left: axesLayout.margin.left,\n top: axesLayout.margin.top,\n width: axesLayout.plotArea.width,\n height: axesLayout.plotArea.height,\n };\n // Adjust the margins to the legend position \n if (this.legend) {\n var legendPosition_1 = this.legend.getOrientation();\n if (visuals.Legend.isTop(legendPosition_1)) {\n rect.top += legendMargins.height;\n }\n else if (visuals.Legend.isLeft(legendPosition_1)) {\n rect.left += legendMargins.width;\n }\n }\n return rect;\n };\n CartesianChart.prototype.renderBackgroundImage = function (layout) {\n visuals.visualBackgroundHelper.renderBackgroundImage(this.background, this.element, layout);\n };\n CartesianChart.prototype.hideAxisLabels = function (legendMargins) {\n if (this.cartesianSmallViewPortProperties) {\n if (this.cartesianSmallViewPortProperties.hideAxesOnSmallViewPort && (this.currentViewport.height < this.cartesianSmallViewPortProperties.MinHeightAxesVisible) && !this.visualInitOptions.interactivity.isInteractiveLegend) {\n return true;\n }\n }\n return false;\n };\n CartesianChart.prototype.calculateInteractivityRightMargin = function () {\n // add right margin in order not to cut the circle selection of the hover line \n if (this.visualInitOptions.interactivity && this.visualInitOptions.interactivity.isInteractiveLegend && !this.trimOrdinalDataOnOverflow) {\n return INTERACTIVITY_RIGHT_MARGIN;\n }\n else {\n return 0;\n }\n };\n CartesianChart.prototype.renderPlotArea = function (layers, axesLayout, suppressAnimations, legendMargins, resizeMode) {\n debug.assertValue(layers, 'layers');\n var axes = axesLayout.axes;\n var plotArea = axesLayout.plotArea;\n var plotAreaRect = this.getPlotAreaRect(axesLayout, legendMargins);\n var duration = visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n var easing = this.animator && this.animator.getEasing();\n this.renderBackgroundImage(plotAreaRect);\n if (!_.isEmpty(easing))\n this.svgAxes.renderAxes(axesLayout, duration, easing);\n else\n this.svgAxes.renderAxes(axesLayout, duration);\n this.renderReferenceLines(axesLayout);\n this.renderLayers(layers, plotArea, axes, suppressAnimations, resizeMode);\n this.renderTrendLines(axesLayout);\n };\n CartesianChart.prototype.renderTrendLines = function (axesLayout) {\n var scrollableRegion = this.svgAxes.getScrollableRegion();\n visuals.TrendLineHelper.render(this.trendLines, scrollableRegion, axesLayout.axes, axesLayout.plotArea);\n };\n CartesianChart.prototype.renderReferenceLines = function (axesLayout) {\n var axes = axesLayout.axes;\n var plotArea = axesLayout.plotArea;\n var scrollableRegion = this.svgAxes.getScrollableRegion();\n var refLineDefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\n var showY1ReferenceLines = false;\n if (this.y1AxisReferenceLines) {\n for (var _i = 0, _a = this.y1AxisReferenceLines; _i < _a.length; _i++) {\n var referenceLineProperties = _a[_i];\n var object = referenceLineProperties.object;\n if (object[visuals.ReferenceLineHelper.referenceLineProps.show]) {\n var isHorizontal = !axes.y1.isCategoryAxis;\n var y1RefLineOptions = {\n graphicContext: scrollableRegion,\n referenceLineProperties: object,\n axes: axes,\n viewport: plotArea,\n classAndSelector: this.y1RefLine,\n defaultColor: refLineDefaultColor,\n isHorizontal: isHorizontal\n };\n visuals.ReferenceLineHelper.render(y1RefLineOptions);\n showY1ReferenceLines = true;\n }\n }\n }\n if (!showY1ReferenceLines) {\n scrollableRegion.selectAll(this.y1RefLine.selector).remove();\n }\n var showXReferenceLines = false;\n if (this.xAxisReferenceLines) {\n for (var _b = 0, _c = this.xAxisReferenceLines; _b < _c.length; _b++) {\n var referenceLineProperties = _c[_b];\n var object = referenceLineProperties.object;\n if (object[visuals.ReferenceLineHelper.referenceLineProps.show]) {\n var isHorizontal = false;\n var xRefLineOptions = {\n graphicContext: scrollableRegion,\n referenceLineProperties: object,\n axes: axes,\n viewport: plotArea,\n classAndSelector: this.xRefLine,\n defaultColor: refLineDefaultColor,\n isHorizontal: isHorizontal\n };\n visuals.ReferenceLineHelper.render(xRefLineOptions);\n showXReferenceLines = true;\n }\n }\n }\n if (!showXReferenceLines) {\n scrollableRegion.selectAll(this.xRefLine.selector).remove();\n }\n };\n CartesianChart.prototype.getReferenceLineLabels = function (axes, plotArea) {\n var refLineDefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\n var referenceLineLabels = [];\n if (this.y1AxisReferenceLines) {\n for (var _i = 0, _a = this.y1AxisReferenceLines; _i < _a.length; _i++) {\n var referenceLineProperties = _a[_i];\n var object = referenceLineProperties.object;\n if (object[visuals.ReferenceLineHelper.referenceLineProps.show] && object[visuals.ReferenceLineHelper.referenceLineProps.dataLabelShow]) {\n var isHorizontal = !axes.y1.isCategoryAxis;\n var y1RefLineLabelOptions = {\n referenceLineProperties: object,\n axes: axes,\n viewport: plotArea,\n defaultColor: refLineDefaultColor,\n isHorizontal: isHorizontal,\n key: JSON.stringify({\n type: 'y1AxisReferenceLine',\n id: referenceLineProperties.id,\n }),\n };\n referenceLineLabels.push(visuals.ReferenceLineHelper.createLabelDataPoint(y1RefLineLabelOptions));\n }\n }\n }\n if (this.xAxisReferenceLines) {\n for (var _b = 0, _c = this.xAxisReferenceLines; _b < _c.length; _b++) {\n var referenceLineProperties = _c[_b];\n var object = referenceLineProperties.object;\n if (object[visuals.ReferenceLineHelper.referenceLineProps.show] && object[visuals.ReferenceLineHelper.referenceLineProps.dataLabelShow]) {\n var isHorizontal = false;\n var xRefLineLabelOptions = {\n referenceLineProperties: object,\n axes: axes,\n viewport: plotArea,\n defaultColor: refLineDefaultColor,\n isHorizontal: isHorizontal,\n key: JSON.stringify({\n type: 'xAxisReferenceLine',\n id: referenceLineProperties.id,\n }),\n };\n referenceLineLabels.push(visuals.ReferenceLineHelper.createLabelDataPoint(xRefLineLabelOptions));\n }\n }\n }\n return referenceLineLabels;\n };\n CartesianChart.prototype.renderDataLabels = function (labelDataPointGroups, labelsAreNumeric, plotArea, suppressAnimations, isCombo) {\n var labelBackgroundRegion = this.svgAxes.getLabelBackground();\n var labelRegion = this.svgAxes.getLabelsRegion();\n if (this.behavior) {\n var labelLayoutOptions = visuals.NewDataLabelUtils.getDataLabelLayoutOptions(this.type);\n var labelLayout = new powerbi.LabelLayout(labelLayoutOptions);\n var dataLabels = labelLayout.layout(labelDataPointGroups, plotArea);\n if (isCombo) {\n visuals.NewDataLabelUtils.drawLabelBackground(labelBackgroundRegion, dataLabels, \"#FFFFFF\", 0.7);\n }\n var svgLabels = void 0;\n var animator = this.animator;\n if (animator && !suppressAnimations) {\n var isPlayAxis = this.isPlayAxis();\n var duration = isPlayAxis ? visuals.PlayChart.FrameAnimationDuration : animator.getDuration();\n svgLabels = visuals.NewDataLabelUtils.animateDefaultLabels(labelRegion, dataLabels, duration, labelsAreNumeric, isPlayAxis ? 'linear' : animator.getEasing());\n }\n else {\n svgLabels = visuals.NewDataLabelUtils.drawDefaultLabels(labelRegion, dataLabels, labelsAreNumeric);\n }\n if (labelLayoutOptions.allowLeaderLines) {\n var filteredLabels = _.filter(dataLabels, function (d) { return d.leaderLinePoints != null && !_.isEmpty(d.leaderLinePoints) && d.identity != null; });\n visuals.NewDataLabelUtils.drawLabelLeaderLines(labelRegion, filteredLabels, function (d) { return d.identity.getKey(); });\n }\n if (this.interactivityService && this.isLabelInteractivityEnabled) {\n var labelsBehaviorOptions = {\n labelItems: svgLabels,\n };\n this.interactivityService.bind(dataLabels, new visuals.LabelsBehavior(), labelsBehaviorOptions, { isLabels: true });\n }\n }\n else {\n var labelLayout = new powerbi.LabelLayout({\n maximumOffset: visuals.NewDataLabelUtils.maxLabelOffset,\n startingOffset: visuals.NewDataLabelUtils.startingLabelOffset,\n attemptToMoveLabelsIntoViewport: true,\n });\n var dataLabels = labelLayout.layout(labelDataPointGroups, plotArea);\n if (isCombo) {\n visuals.NewDataLabelUtils.drawLabelBackground(labelBackgroundRegion, dataLabels, \"#FFFFFF\", 0.7);\n }\n visuals.NewDataLabelUtils.drawDefaultLabels(labelRegion, dataLabels, labelsAreNumeric);\n }\n };\n CartesianChart.prototype.renderLayers = function (layers, plotArea, axes, suppressAnimations, resizeMode) {\n var labelDataPointGroups = [];\n var dataPoints = [];\n var layerBehaviorOptions = [];\n var labelsAreNumeric = true;\n for (var i = 0, len = layers.length; i < len; i++) {\n var result = layers[i].render(suppressAnimations, resizeMode);\n if (result) {\n if (this.behavior) {\n // NOTE: these are not needed if we don't have interactivity\n dataPoints = dataPoints.concat(result.dataPoints);\n layerBehaviorOptions.push(result.behaviorOptions);\n }\n if (result.labelDataPointGroups) {\n var resultLabelDataPointsGroups = result.labelDataPointGroups;\n for (var _i = 0, resultLabelDataPointsGroups_1 = resultLabelDataPointsGroups; _i < resultLabelDataPointsGroups_1.length; _i++) {\n var resultLabelDataPointsGroup = resultLabelDataPointsGroups_1[_i];\n if (!resultLabelDataPointsGroup)\n continue;\n labelDataPointGroups.push({\n labelDataPoints: visuals.NewDataLabelUtils.removeDuplicates(resultLabelDataPointsGroup.labelDataPoints || []),\n maxNumberOfLabels: resultLabelDataPointsGroup.maxNumberOfLabels,\n });\n }\n }\n else {\n var resultsLabelDataPoints = result.labelDataPoints || [];\n labelDataPointGroups.push({\n labelDataPoints: visuals.NewDataLabelUtils.removeDuplicates(resultsLabelDataPoints),\n maxNumberOfLabels: resultsLabelDataPoints.length,\n });\n }\n labelsAreNumeric = labelsAreNumeric && result.labelsAreNumeric;\n }\n }\n var referenceLineLabels = this.getReferenceLineLabels(axes, plotArea);\n if (!_.isEmpty(referenceLineLabels)) {\n labelDataPointGroups.unshift({\n labelDataPoints: referenceLineLabels,\n maxNumberOfLabels: referenceLineLabels.length,\n });\n }\n this.renderDataLabels(labelDataPointGroups, labelsAreNumeric, plotArea, suppressAnimations, visuals.ComboChart.isComboChart(this.type));\n if (this.interactivityService) {\n var behaviorOptions = {\n layerOptions: layerBehaviorOptions,\n clearCatcher: this.clearCatcher,\n };\n this.interactivityService.bind(dataPoints, this.behavior, behaviorOptions);\n }\n };\n /**\n * Returns the actual viewportWidth if visual is not scrollable.\n * @return If visual is scrollable, returns the plot area needed to draw all the datapoints.\n */\n CartesianChart.getPreferredPlotArea = function (categoryCount, categoryThickness, viewport, isScrollable, isScalar, margin, noOuterPadding) {\n if (!margin)\n margin = { top: 0, right: 0, bottom: 0, left: 0 };\n var plotArea = {\n height: viewport.height - margin.top - margin.bottom,\n width: viewport.width - margin.left - margin.right\n };\n if (!isScalar && isScrollable) {\n var preferredCategorySpan = CartesianChart.getPreferredCategorySpan(categoryCount, categoryThickness, noOuterPadding);\n plotArea.width = Math.max(preferredCategorySpan, plotArea.width);\n }\n return plotArea;\n };\n /**\n * Returns preferred Category span if the visual is scrollable.\n */\n CartesianChart.getPreferredCategorySpan = function (categoryCount, categoryThickness, noOuterPadding) {\n var span = (categoryThickness * categoryCount);\n if (noOuterPadding)\n return span;\n return span + (categoryThickness * CartesianChart.OuterPaddingRatio * 2);\n };\n /**\n * Note: Public for testing access.\n */\n CartesianChart.getLayout = function (data, options) {\n var categoryCount = options.categoryCount, availableWidth = options.availableWidth, domain = options.domain, trimOrdinalDataOnOverflow = options.trimOrdinalDataOnOverflow, isScalar = !!options.isScalar, isScrollable = !!options.isScrollable;\n var categoryThickness = CartesianChart.getCategoryThickness(data ? data.series : null, categoryCount, availableWidth, domain, isScalar, trimOrdinalDataOnOverflow);\n // Total width of the outer padding, the padding that exist on the far right and far left of the chart.\n var totalOuterPadding = categoryThickness * CartesianChart.OuterPaddingRatio * 2;\n // visibleCategoryCount will be used to discard data that overflows on ordinal-axis charts.\n // Needed for dashboard visuals \n var calculatedBarCount = powerbi.Double.floorWithPrecision((availableWidth - totalOuterPadding) / categoryThickness);\n var visibleCategoryCount = Math.min(calculatedBarCount, categoryCount);\n var willScroll = visibleCategoryCount < categoryCount && isScrollable;\n var outerPaddingRatio = CartesianChart.OuterPaddingRatio;\n if (!isScalar && !willScroll) {\n // use dynamic outer padding to improve spacing when we have few categories\n var oneOuterPadding = (availableWidth - (categoryThickness * visibleCategoryCount)) / 2;\n outerPaddingRatio = oneOuterPadding / categoryThickness;\n }\n // If scrollable, visibleCategoryCount will be total categories\n if (!isScalar && isScrollable)\n visibleCategoryCount = categoryCount;\n return {\n categoryCount: visibleCategoryCount,\n categoryThickness: categoryThickness,\n outerPaddingRatio: outerPaddingRatio,\n isScalar: isScalar\n };\n };\n /**\n * Returns the thickness for each category.\n * For clustered charts, you still need to divide by\n * the number of series to get column width after calling this method.\n * For linear or time scales, category thickness accomodates for\n * the minimum interval between consequtive points.\n * For all types, return value has accounted for outer padding,\n * but not inner padding.\n */\n CartesianChart.getCategoryThickness = function (seriesList, numCategories, plotLength, domain, isScalar, trimOrdinalDataOnOverflow) {\n var thickness;\n if (numCategories < 2)\n thickness = plotLength * (1 - CartesianChart.OuterPaddingRatio);\n else if (isScalar && domain && domain.length > 1) {\n // the smallest interval defines the column width.\n var minInterval = CartesianChart.getMinInterval(seriesList);\n var domainSpan = domain[domain.length - 1] - domain[0];\n // account for outside padding\n var ratio = minInterval / (domainSpan + (minInterval * CartesianChart.OuterPaddingRatio * 2));\n thickness = plotLength * ratio;\n thickness = Math.max(thickness, CartesianChart.MinScalarRectThickness);\n }\n else {\n // Divide the available width up including outer padding (in terms of category thickness) on\n // both sides of the chart, and categoryCount categories. Reverse math:\n // availableWidth = (categoryThickness * categoryCount) + (categoryThickness * (outerPadding * 2)),\n // availableWidth = categoryThickness * (categoryCount + (outerPadding * 2)),\n // categoryThickness = availableWidth / (categoryCount + (outerpadding * 2))\n thickness = plotLength / (numCategories + (CartesianChart.OuterPaddingRatio * 2));\n if (trimOrdinalDataOnOverflow) {\n thickness = Math.max(thickness, CartesianChart.MinOrdinalRectThickness);\n }\n }\n // spec calls for using the whole plot area, but the max rectangle thickness is \"as if there were three categories\"\n // (outerPaddingRatio has the same units as '# of categories' so they can be added)\n var maxRectThickness = plotLength / (3 + (CartesianChart.OuterPaddingRatio * 2));\n thickness = Math.min(thickness, maxRectThickness);\n if (!isScalar && numCategories >= 3 && trimOrdinalDataOnOverflow) {\n return Math.max(thickness, CartesianChart.MinOrdinalRectThickness);\n }\n return thickness;\n };\n CartesianChart.getMinInterval = function (seriesList) {\n var minInterval = Number.MAX_VALUE;\n if (seriesList.length > 0) {\n var series0data = seriesList[0].data.filter(function (d) { return !d.highlight; });\n for (var i = 0, ilen = series0data.length - 1; i < ilen; i++) {\n minInterval = Math.min(minInterval, Math.abs(series0data[i + 1].categoryValue - series0data[i].categoryValue));\n }\n }\n return minInterval;\n };\n CartesianChart.MinOrdinalRectThickness = 20;\n CartesianChart.MinScalarRectThickness = 2;\n CartesianChart.OuterPaddingRatio = 0.4;\n CartesianChart.InnerPaddingRatio = 0.2;\n CartesianChart.TickLabelPadding = 2; // between text labels, used by AxisHelper\n CartesianChart.ClassName = 'cartesianChart';\n CartesianChart.PlayAxisBottomMargin = 80; //do not change unless we add dynamic label measurements for play slider\n CartesianChart.FontSize = 11;\n CartesianChart.FontSizeString = jsCommon.PixelConverter.toString(CartesianChart.FontSize);\n CartesianChart.AxisTextProperties = {\n fontFamily: 'wf_segoe-ui_normal',\n fontSize: CartesianChart.FontSizeString,\n };\n return CartesianChart;\n }());\n visuals.CartesianChart = CartesianChart;\n function getLayerDataViews(dataViews) {\n if (_.isEmpty(dataViews))\n return [];\n // TODO: figure out a more general way to correlate between layers and input data views.\n return _.filter(dataViews, function (dataView) { return !visuals.TrendLineHelper.isDataViewForRegression(dataView); });\n }\n function hasMultipleYAxes(layers) {\n debug.assertValue(layers, 'layers');\n return layers.length > 1;\n }\n /**\n * Returns a boolean, that indicates if y axis title should be displayed.\n * @return True if y axis title should be displayed,\n * otherwise false.\n */\n function shouldShowYAxisLabel(layerNumber, valueAxisProperties, yAxisWillMerge) {\n return ((layerNumber === 0 && !!valueAxisProperties && !!valueAxisProperties['showAxisTitle']) ||\n (layerNumber === 1 && !yAxisWillMerge && !!valueAxisProperties && !!valueAxisProperties['secShowAxisTitle']));\n }\n function tryMergeYDomains(layers, visualOptions) {\n debug.assert(layers.length < 3, 'merging of more than 2 layers is not supported');\n var noMerge = {\n domain: undefined,\n merged: false,\n tickCount: undefined\n };\n if (layers.length < 2)\n return noMerge;\n var min;\n var max;\n var minOfMax;\n var maxOfMin;\n // TODO: replace full calculateAxesProperties with just a data domain calc\n // we need to be aware of which chart require zero (column/bar) and which don't (line)\n var y1props = layers[0].calculateAxesProperties(visualOptions)[1];\n var y2props = layers[1].calculateAxesProperties(visualOptions)[1];\n var firstYDomain = y1props.scale.domain();\n var secondYDomain = y2props.scale.domain();\n if (y1props.values && y1props.values.length > 0 && y2props.values && y2props.values.length > 0) {\n noMerge.tickCount = Math.max(y1props.values.length, y2props.values.length);\n }\n min = Math.min(firstYDomain[0], secondYDomain[0]);\n max = Math.max(firstYDomain[1], secondYDomain[1]);\n if (visualOptions.forceMerge) {\n return {\n domain: [min, max],\n merged: true,\n tickCount: noMerge.tickCount\n };\n }\n // If domains don't intersect don't merge axis.\n if (firstYDomain[0] > secondYDomain[1] || firstYDomain[1] < secondYDomain[0])\n return noMerge;\n maxOfMin = Math.max(firstYDomain[0], secondYDomain[0]);\n minOfMax = Math.min(firstYDomain[1], secondYDomain[1]);\n var range = (max - min);\n if (range === 0) {\n return noMerge;\n }\n var intersection = Math.abs((minOfMax - maxOfMin) / range);\n // Only merge if intersection of domains greater than 10% of total range.\n if (intersection < COMBOCHART_DOMAIN_OVERLAP_TRESHOLD_PERCENTAGE)\n return noMerge;\n else\n return {\n domain: [min, max],\n merged: true,\n tickCount: noMerge.tickCount\n };\n }\n var SvgBrush = (function () {\n function SvgBrush(brushWidth) {\n this.brush = d3.svg.brush();\n this.brushWidth = brushWidth;\n }\n SvgBrush.prototype.init = function (element) {\n this.element = element;\n };\n SvgBrush.prototype.remove = function () {\n this.element.selectAll(SvgBrush.Brush.selector).remove();\n this.brushGraphicsContext = undefined;\n };\n SvgBrush.prototype.getExtent = function () {\n return this.brush.extent();\n };\n SvgBrush.prototype.setExtent = function (extent) {\n this.brush.extent(extent);\n };\n SvgBrush.prototype.setScale = function (scale) {\n if (this.isHorizontal)\n this.brush.x(scale);\n else\n this.brush.y(scale);\n };\n SvgBrush.prototype.setOrientation = function (isHorizontal) {\n this.isHorizontal = isHorizontal;\n };\n SvgBrush.prototype.renderBrush = function (extentLength, brushX, brushY, scrollCallback) {\n var _this = this;\n // create graphics context if it doesn't exist\n if (!this.brushGraphicsContext) {\n this.brushGraphicsContext = this.element.append(\"g\")\n .classed(SvgBrush.Brush.class, true);\n }\n this.scrollCallback = scrollCallback;\n // events\n this.brush\n .on(\"brushstart\", function () { return _this.brushStartExtent = _this.brush.extent(); })\n .on(\"brush\", function () {\n window.requestAnimationFrame(scrollCallback);\n })\n .on(\"brushend\", function () {\n _this.resizeExtent(extentLength);\n _this.updateExtentPosition(extentLength);\n _this.brushStartExtent = null;\n });\n // position the graphics context\n var brushContext = this.brushGraphicsContext\n .attr({\n \"transform\": visuals.SVGUtil.translate(brushX, brushY),\n \"drag-resize-disabled\": \"true\" /* Disables resizing of the visual when dragging the scrollbar in edit mode */\n })\n .call(this.brush);\n // Disable the zooming feature by removing the resize elements\n brushContext.selectAll(\".resize\")\n .remove();\n if (this.isHorizontal)\n brushContext.selectAll(\"rect\").attr(\"height\", this.brushWidth);\n else\n brushContext.selectAll(\"rect\").attr(\"width\", this.brushWidth);\n };\n SvgBrush.prototype.scroll = function (scrollBarLength) {\n this.updateExtentPosition(scrollBarLength);\n this.scrollCallback();\n };\n SvgBrush.prototype.updateExtentPosition = function (scrollBarLength) {\n var extent = this.brush.extent();\n debug.assertNonEmpty(extent, 'updateExtentPosition, extent');\n var newStartPos = extent[0];\n var halfScrollBarLen = scrollBarLength / 2;\n if (extent[0] === extent[1]) {\n // user clicked on the brush background, width will be zero, offset x by half width\n newStartPos = newStartPos - halfScrollBarLen;\n }\n if (extent[1] - extent[0] > scrollBarLength) {\n // user is dragging one edge after mousedown in the background, figure out which side is moving\n // also, center up on the new extent center\n var halfDragLength = (extent[1] - extent[0]) / 2;\n if (extent[0] < this.brushStartExtent[0])\n newStartPos = extent[0] + halfDragLength - halfScrollBarLen;\n else\n newStartPos = extent[1] - halfDragLength - halfScrollBarLen;\n }\n if (this.isHorizontal)\n this.brushGraphicsContext.select(\".extent\").attr('x', newStartPos);\n else\n this.brushGraphicsContext.select(\".extent\").attr('y', newStartPos);\n };\n SvgBrush.prototype.resizeExtent = function (extentLength) {\n if (this.isHorizontal)\n this.brushGraphicsContext.select(\".extent\").attr(\"width\", extentLength);\n else\n this.brushGraphicsContext.select(\".extent\").attr(\"height\", extentLength);\n };\n SvgBrush.Brush = createClassAndSelector('brush');\n return SvgBrush;\n }());\n var ScrollableAxes = (function () {\n function ScrollableAxes(axes, svgBrush) {\n this.axes = axes;\n this.brush = svgBrush;\n }\n ScrollableAxes.prototype.filterDataToViewport = function (mainAxisScale, layers, axes, scrollScale, extent, visibleCategoryCount) {\n if (scrollScale) {\n var selected = void 0;\n var data_1 = [];\n // NOTE: using start + numVisibleCategories to make sure we don't have issues with exactness related to extent start/end\n // (don't use extent[1])\n /*\n When extent[0] and extent[1] are very close to the boundary of a new index, due to floating point err,\n the \"start\" might move to the next index but the \"end\" might not change until you slide one more pixel.\n It makes things really jittery during scrolling, sometimes you see N columns and sometimes you briefly see N+1.\n */\n var startIndex = visuals.AxisHelper.lookupOrdinalIndex(scrollScale, extent[0]);\n var endIndex = startIndex + visibleCategoryCount; // NOTE: intentionally 1 past end index\n var domain = scrollScale.domain();\n selected = domain.slice(startIndex, endIndex); // NOTE: Up to but not including 'end'\n if (selected && selected.length > 0) {\n for (var i = 0; i < layers.length; i++) {\n data_1[i] = layers[i].setFilteredData(selected[0], selected[selected.length - 1] + 1);\n }\n mainAxisScale.domain(selected);\n var axisPropsToUpdate = void 0;\n if (this.axes.isXScrollBarVisible) {\n axisPropsToUpdate = axes.x;\n }\n else {\n axisPropsToUpdate = axes.y1;\n }\n axisPropsToUpdate.axis.scale(mainAxisScale);\n axisPropsToUpdate.scale(mainAxisScale);\n // tick values are indices for ordinal axes\n axisPropsToUpdate.axis.ticks(selected.length);\n axisPropsToUpdate.axis.tickValues(selected);\n // use the original tick format to format the tick values\n var tickFormat_1 = axisPropsToUpdate.axis.tickFormat();\n axisPropsToUpdate.values = _.map(selected, function (d) { return tickFormat_1(d); });\n }\n }\n };\n ScrollableAxes.prototype.render = function (axesLayout, layers, suppressAnimations, renderDelegate) {\n var _this = this;\n var plotArea = axesLayout.plotArea;\n if (plotArea.width < 1 || plotArea.height < 1)\n return; //do nothing - too small\n this.axisScale = null;\n var brushX;\n var brushY;\n var scrollbarLength;\n var numVisibleCategories;\n var categoryThickness;\n var newAxisLength;\n if (this.axes.isXScrollBarVisible) {\n this.axisScale = axesLayout.axes.x.scale;\n brushX = axesLayout.margin.left;\n brushY = axesLayout.viewport.height;\n categoryThickness = axesLayout.axes.x.categoryThickness;\n var outerPadding = axesLayout.axes.x.outerPadding;\n numVisibleCategories = powerbi.Double.floorWithPrecision((plotArea.width - outerPadding * 2) / categoryThickness);\n scrollbarLength = (numVisibleCategories + 1) * categoryThickness;\n newAxisLength = plotArea.width;\n }\n else if (this.axes.isYScrollBarVisible) {\n this.axisScale = axesLayout.axes.y1.scale;\n brushX = axesLayout.viewport.width;\n brushY = axesLayout.margin.top;\n categoryThickness = axesLayout.axes.y1.categoryThickness;\n var outerPadding = axesLayout.axes.y1.outerPadding;\n numVisibleCategories = powerbi.Double.floorWithPrecision((plotArea.height - outerPadding * 2) / categoryThickness);\n scrollbarLength = (numVisibleCategories + 1) * categoryThickness;\n newAxisLength = plotArea.height;\n }\n else {\n // No scrollbars, render the chart normally.\n this.brush.remove();\n renderDelegate(layers, axesLayout, suppressAnimations);\n return;\n }\n // viewport is REALLY small\n if (numVisibleCategories < 1)\n return; // don't do anything\n this.scrollScale = this.axisScale.copy();\n this.scrollScale.rangeBands([0, scrollbarLength]); //no inner/outer padding, keep the math simple\n this.brushMinExtent = this.scrollScale(numVisibleCategories - 1);\n // Options: use newAxisLength to squeeze-pop and keep the chart balanced, \n // or use scrollbarLength to keep rects still - but it leaves unbalanced right edge\n // 1. newAxisLength ex: As you resize smaller we constantly adjust the inner/outer padding to keep things balanced with the same # of rects, \n // when we need to drop a rect we pop out the rectangle and the padding seems to jump (to keep things cenetered and balanced). \n // 2. scrollbarLenghth ex: As you resize smaller we can leave all rectangles in the exact same place, no squeezing inner/outer padding,\n // when we need to drop a rect we just remove it - but this leaves the right side with lots of empty room (bad for dashboard tiles)\n // we are using option 1 to squeeze pop and show balanced layout at all sizes, but this is the less ideal experience during resize.\n // we should consider using option 2 during resize, then switch to option 1 when resize ends.\n this.axisScale.rangeBands([0, newAxisLength], CartesianChart.InnerPaddingRatio, CartesianChart.OuterPaddingRatio);\n this.brush.setOrientation(this.axes.isXScrollBarVisible);\n this.brush.setScale(this.scrollScale);\n this.brush.setExtent([0, this.brushMinExtent]);\n // This function will be called whenever we scroll.\n var renderOnScroll = function (extent, suppressAnimations) {\n _this.filterDataToViewport(_this.axisScale, layers, axesLayout.axes, _this.scrollScale, extent, numVisibleCategories);\n renderDelegate(layers, axesLayout, suppressAnimations);\n };\n var scrollCallback = function () { return _this.onBrushed(scrollbarLength, renderOnScroll); };\n this.brush.renderBrush(this.brushMinExtent, brushX, brushY, scrollCallback);\n renderOnScroll(this.brush.getExtent(), suppressAnimations);\n };\n ScrollableAxes.prototype.scrollDelta = function (delta) {\n if (this.axisScale && !_.isEmpty(this.axisScale.domain())) {\n var currentStartIndex = this.axisScale.domain()[0];\n var newStartIndex = currentStartIndex + Math.round(delta / CartesianChart.MinOrdinalRectThickness);\n this.scrollTo(newStartIndex);\n }\n };\n // PUBLIC FOR UNIT TESTING ONLY\n ScrollableAxes.prototype.scrollTo = function (startIndex) {\n debug.assert(this.axes.isXScrollBarVisible || this.axes.isYScrollBarVisible, 'scrolling is not available');\n debug.assertValue(this.scrollScale, 'scrollScale');\n var lastIndex = _.last(this.scrollScale.domain());\n startIndex = Math.max(0, Math.min(startIndex, lastIndex));\n var extent = this.brush.getExtent();\n var extentLength = extent[1] - extent[0];\n var halfCategoryThickness = (this.scrollScale(1) - this.scrollScale(0)) / 2;\n extent[0] = this.scrollScale(startIndex) + halfCategoryThickness;\n extent[1] = extent[0] + extentLength + halfCategoryThickness;\n this.brush.setExtent(extent);\n var scrollbarLength = this.scrollScale.rangeExtent()[1];\n ScrollableAxes.clampBrushExtent(this.brush, scrollbarLength, this.brushMinExtent);\n this.brush.scroll(scrollbarLength);\n };\n ScrollableAxes.prototype.onBrushed = function (scrollbarLength, render) {\n var brush = this.brush;\n ScrollableAxes.clampBrushExtent(this.brush, scrollbarLength, this.brushMinExtent);\n var extent = brush.getExtent();\n render(extent, /*suppressAnimations*/ true);\n };\n ScrollableAxes.clampBrushExtent = function (brush, scrollbarLength, minExtent) {\n var extent = brush.getExtent();\n var width = extent[1] - extent[0];\n if (width === minExtent && extent[1] <= scrollbarLength && extent[0] >= 0)\n return;\n if (width > minExtent) {\n var padding = (width - minExtent) / 2;\n extent[0] += padding;\n extent[1] -= padding;\n }\n else if (width < minExtent) {\n var padding = (minExtent - width) / 2;\n extent[0] -= padding;\n extent[1] += padding;\n }\n if (extent[0] < 0) {\n extent[0] = 0;\n extent[1] = minExtent;\n }\n else if (extent[0] > scrollbarLength - minExtent) {\n extent[0] = scrollbarLength - minExtent;\n extent[1] = scrollbarLength;\n }\n brush.setExtent(extent);\n };\n ScrollableAxes.ScrollbarWidth = 10;\n return ScrollableAxes;\n }());\n var SvgCartesianAxes = (function () {\n function SvgCartesianAxes(axes) {\n this.axes = axes;\n }\n SvgCartesianAxes.prototype.getScrollableRegion = function () {\n return this.axisGraphicsContextScrollable;\n };\n SvgCartesianAxes.prototype.getLabelsRegion = function () {\n return this.labelRegion;\n };\n SvgCartesianAxes.prototype.getLabelBackground = function () {\n return this.labelBackgroundRegion;\n };\n SvgCartesianAxes.prototype.getXAxis = function () {\n return this.xAxisGraphicsContext;\n };\n SvgCartesianAxes.prototype.getY1Axis = function () {\n return this.y1AxisGraphicsContext;\n };\n SvgCartesianAxes.prototype.getY2Axis = function () {\n return this.y2AxisGraphicsContext;\n };\n SvgCartesianAxes.prototype.update = function (categoryAxisProperties, valueAxisProperties) {\n this.categoryAxisProperties = categoryAxisProperties;\n this.valueAxisProperties = valueAxisProperties;\n };\n SvgCartesianAxes.prototype.init = function (svg) {\n /*\n The layout of the visual will look like:\n <svg>\n <g>\n <nonscrollable axis/>\n </g>\n <svgScrollable>\n <g>\n <scrollable axis/>\n </g>\n </svgScrollable>\n <g xbrush/>\n </svg>\n \n */\n var axisGraphicsContext = this.axisGraphicsContext = svg.append('g')\n .classed(SvgCartesianAxes.AxisGraphicsContext.class, true);\n this.svgScrollable = svg.append('svg')\n .classed('svgScrollable', true)\n .style('overflow', 'hidden');\n var axisGraphicsContextScrollable = this.axisGraphicsContextScrollable = this.svgScrollable.append('g')\n .classed(SvgCartesianAxes.AxisGraphicsContext.class, true);\n this.labelBackgroundRegion = this.svgScrollable.append('g')\n .classed(visuals.NewDataLabelUtils.labelBackgroundGraphicsContextClass.class, true);\n this.labelRegion = this.svgScrollable.append('g')\n .classed(visuals.NewDataLabelUtils.labelGraphicsContextClass.class, true);\n var showLinesOnX = this.axes.showLinesOnX;\n var showLinesOnY = this.axes.showLinesOnY;\n // NOTE: We infer the axis which should scroll based on whether or not we draw grid lines for the other axis, and\n // only allow one axis to scroll.\n var scrollX = showLinesOnY;\n var scrollY = !scrollX;\n if (scrollY) {\n this.y1AxisGraphicsContext = axisGraphicsContextScrollable.append('g').attr('class', 'y axis');\n this.y2AxisGraphicsContext = axisGraphicsContextScrollable.append('g').attr('class', 'y axis');\n }\n else {\n this.y1AxisGraphicsContext = axisGraphicsContext.append('g').attr('class', 'y axis');\n this.y2AxisGraphicsContext = axisGraphicsContext.append('g').attr('class', 'y axis');\n }\n if (scrollX) {\n this.xAxisGraphicsContext = axisGraphicsContextScrollable.append('g').attr('class', 'x axis');\n }\n else {\n this.xAxisGraphicsContext = axisGraphicsContext.append('g').attr('class', 'x axis');\n }\n this.xAxisGraphicsContext.classed('showLinesOnAxis', showLinesOnX);\n this.y1AxisGraphicsContext.classed('showLinesOnAxis', showLinesOnY);\n this.y2AxisGraphicsContext.classed('showLinesOnAxis', showLinesOnY);\n this.xAxisGraphicsContext.classed('hideLinesOnAxis', !showLinesOnX);\n this.y1AxisGraphicsContext.classed('hideLinesOnAxis', !showLinesOnY);\n this.y2AxisGraphicsContext.classed('hideLinesOnAxis', !showLinesOnY);\n };\n SvgCartesianAxes.updateAnimatedTickTooltips = function (axisSelection, values) {\n axisSelection.each('end', function () {\n d3.select(this)\n .selectAll('text')\n .append('title')\n .text(function (d, i) { return values[i]; });\n });\n };\n SvgCartesianAxes.updateTickTooltips = function (axisSelection, values) {\n axisSelection.selectAll('text').append('title').text(function (d, i) { return values[i]; });\n };\n SvgCartesianAxes.prototype.renderAxes = function (axesLayout, duration, easing) {\n if (easing === void 0) { easing = 'cubic-in-out'; }\n var marginLimits = axesLayout.marginLimits;\n var plotArea = axesLayout.plotArea;\n var viewport = axesLayout.viewport;\n var margin = axesLayout.margin;\n var axes = axesLayout.axes;\n var tickLabelMargins = axesLayout.tickLabelMargins;\n var bottomMarginLimit = marginLimits.bottom;\n var leftRightMarginLimit = marginLimits.left;\n var xLabelColor;\n var yLabelColor;\n var y2LabelColor;\n if (this.axes.shouldRenderAxis(axes.x)) {\n if (axes.x.isCategoryAxis) {\n xLabelColor = this.categoryAxisProperties && this.categoryAxisProperties['labelColor'] ? this.categoryAxisProperties['labelColor'] : null;\n }\n else {\n xLabelColor = this.valueAxisProperties && this.valueAxisProperties['labelColor'] ? this.valueAxisProperties['labelColor'] : null;\n }\n axes.x.axis.orient(\"bottom\");\n // we only rotate ordinal tick labels\n if (!axes.x.willLabelsFit && visuals.AxisHelper.isOrdinalScale(axes.x.scale))\n axes.x.axis.tickPadding(SvgCartesianAxes.TickPaddingRotatedX);\n var xAxisGraphicsElement = this.xAxisGraphicsContext;\n if (duration) {\n xAxisGraphicsElement\n .transition()\n .duration(duration)\n .ease(easing)\n .call(axes.x.axis)\n .call(SvgCartesianAxes.updateAnimatedTickTooltips, axes.x.values);\n }\n else {\n xAxisGraphicsElement\n .call(axes.x.axis);\n }\n xAxisGraphicsElement\n .call(SvgCartesianAxes.darkenZeroLine)\n .call(SvgCartesianAxes.setAxisLabelColor, xLabelColor);\n var xAxisTextNodes = xAxisGraphicsElement.selectAll('text');\n if (axes.x.willLabelsWordBreak) {\n xAxisTextNodes\n .call(visuals.AxisHelper.LabelLayoutStrategy.wordBreak, axes.x, bottomMarginLimit);\n }\n else {\n xAxisTextNodes\n .call(visuals.AxisHelper.LabelLayoutStrategy.rotate, bottomMarginLimit, powerbi.TextMeasurementService.getTailoredTextOrDefault, CartesianChart.AxisTextProperties, !axes.x.willLabelsFit && visuals.AxisHelper.isOrdinalScale(axes.x.scale), bottomMarginLimit === tickLabelMargins.xMax, axes.x, margin, this.axes.isXScrollBarVisible || this.axes.isYScrollBarVisible);\n }\n if (!duration) {\n SvgCartesianAxes.updateTickTooltips(xAxisGraphicsElement, axes.x.values);\n }\n }\n else {\n this.xAxisGraphicsContext.selectAll('*').remove();\n }\n if (this.axes.shouldRenderAxis(axes.y1)) {\n if (axes.y1.isCategoryAxis) {\n yLabelColor = this.categoryAxisProperties && this.categoryAxisProperties['labelColor'] ? this.categoryAxisProperties['labelColor'] : null;\n }\n else {\n yLabelColor = this.valueAxisProperties && this.valueAxisProperties['labelColor'] ? this.valueAxisProperties['labelColor'] : null;\n }\n var showY1OnRight = this.axes.shouldShowY1OnRight();\n var y1TickPadding = showY1OnRight ? axesLayout.tickPadding.right : axesLayout.tickPadding.left;\n axes.y1.axis\n .tickSize(-plotArea.width)\n .tickPadding(y1TickPadding)\n .orient(this.axes.getYAxisOrientation().toLowerCase());\n var y1AxisGraphicsElement = this.y1AxisGraphicsContext;\n if (duration) {\n y1AxisGraphicsElement\n .transition()\n .duration(duration)\n .ease(easing)\n .call(axes.y1.axis)\n .call(SvgCartesianAxes.updateAnimatedTickTooltips, axes.y1.values);\n }\n else {\n y1AxisGraphicsElement\n .call(axes.y1.axis);\n }\n y1AxisGraphicsElement\n .call(SvgCartesianAxes.darkenZeroLine)\n .call(SvgCartesianAxes.setAxisLabelColor, yLabelColor);\n if (tickLabelMargins.yLeft >= leftRightMarginLimit) {\n y1AxisGraphicsElement.selectAll('text')\n .call(visuals.AxisHelper.LabelLayoutStrategy.clip, \n // Can't use padding space to render text, so subtract that from available space for ellipses calculations\n leftRightMarginLimit - y1TickPadding, powerbi.TextMeasurementService.svgEllipsis);\n }\n if (!duration) {\n SvgCartesianAxes.updateTickTooltips(y1AxisGraphicsElement, axes.y1.values);\n }\n if (axes.y2 && (!this.valueAxisProperties || this.valueAxisProperties['secShow'] == null || this.valueAxisProperties['secShow'])) {\n y2LabelColor = this.valueAxisProperties && this.valueAxisProperties['secLabelColor'] ? this.valueAxisProperties['secLabelColor'] : null;\n var y2TickPadding = showY1OnRight ? axesLayout.tickPadding.left : axesLayout.tickPadding.right;\n axes.y2.axis\n .tickSize(SvgCartesianAxes.Y2TickSize)\n .tickPadding(y2TickPadding)\n .orient(showY1OnRight ? visuals.yAxisPosition.left.toLowerCase() : visuals.yAxisPosition.right.toLowerCase());\n var y2AxisGraphicsElement = this.y2AxisGraphicsContext;\n if (duration) {\n y2AxisGraphicsElement\n .transition()\n .duration(duration)\n .ease(easing)\n .call(axes.y2.axis)\n .call(SvgCartesianAxes.updateAnimatedTickTooltips, axes.y2.values);\n }\n else {\n y2AxisGraphicsElement\n .call(axes.y2.axis);\n }\n y2AxisGraphicsElement\n .call(SvgCartesianAxes.darkenZeroLine)\n .call(SvgCartesianAxes.setAxisLabelColor, y2LabelColor);\n if (tickLabelMargins.yRight >= leftRightMarginLimit) {\n y2AxisGraphicsElement.selectAll('text')\n .call(visuals.AxisHelper.LabelLayoutStrategy.clip, \n // Can't use padding space to render text, so subtract that from available space for ellipses calculations\n leftRightMarginLimit - y2TickPadding, powerbi.TextMeasurementService.svgEllipsis);\n }\n if (!duration) {\n SvgCartesianAxes.updateTickTooltips(y2AxisGraphicsElement, axes.y2.values);\n }\n }\n else {\n this.y2AxisGraphicsContext.selectAll('*').remove();\n }\n }\n else {\n this.y1AxisGraphicsContext.selectAll('*').remove();\n this.y2AxisGraphicsContext.selectAll('*').remove();\n }\n // Axis labels\n //TODO: Add label for second Y axis for combo chart\n var axisLabels = axesLayout.axisLabels;\n var chartHasAxisLabels = (axisLabels.x != null) || (axisLabels.y != null || axisLabels.y2 != null);\n if (chartHasAxisLabels) {\n var hideXAxisTitle = !this.axes.shouldRenderAxisTitle(axes.x, /* defaultValue */ true, /* secondary */ false);\n var hideYAxisTitle = !this.axes.shouldRenderAxisTitle(axes.y1, /* defaultValue */ true, /* secondary */ false);\n var hideY2AxisTitle = !this.axes.shouldRenderAxisTitle(axes.y2, /* defaultValue */ false, /* secondary */ true);\n var renderAxisOptions = {\n axisLabels: axisLabels,\n viewport: viewport,\n margin: margin,\n hideXAxisTitle: hideXAxisTitle,\n hideYAxisTitle: hideYAxisTitle,\n hideY2AxisTitle: hideY2AxisTitle,\n xLabelColor: xLabelColor,\n yLabelColor: yLabelColor,\n y2LabelColor: y2LabelColor,\n fontSize: SvgCartesianAxes.AxisLabelFontSize,\n };\n this.renderAxesLabels(renderAxisOptions);\n }\n else {\n this.axisGraphicsContext.selectAll('.xAxisLabel').remove();\n this.axisGraphicsContext.selectAll('.yAxisLabel').remove();\n }\n this.translateAxes(viewport, margin);\n };\n SvgCartesianAxes.prototype.renderAxesLabels = function (options) {\n debug.assertValue(options, 'options');\n debug.assertValue(options.viewport, 'options.viewport');\n debug.assertValue(options.axisLabels, 'options.axisLabels');\n this.axisGraphicsContext.selectAll('.xAxisLabel').remove();\n this.axisGraphicsContext.selectAll('.yAxisLabel').remove();\n var margin = options.margin;\n var width = options.viewport.width - (margin.left + margin.right);\n var height = options.viewport.height;\n var fontSize = options.fontSize;\n var heightOffset = fontSize;\n var showOnRight = this.axes.shouldShowY1OnRight();\n if (!options.hideXAxisTitle) {\n var xAxisLabel = this.axisGraphicsContext.append(\"text\")\n .style(\"text-anchor\", \"middle\")\n .text(options.axisLabels.x)\n .call(function (text) {\n text.each(function () {\n var text = d3.select(this);\n text.attr({\n \"class\": \"xAxisLabel\",\n \"transform\": visuals.SVGUtil.translate(width / 2, height - heightOffset)\n });\n });\n });\n xAxisLabel.style(\"fill\", options.xLabelColor ? options.xLabelColor.solid.color : null);\n xAxisLabel.call(visuals.AxisHelper.LabelLayoutStrategy.clip, width, powerbi.TextMeasurementService.svgEllipsis)\n .call(visuals.tooltipUtils.tooltipUpdate, [options.axisLabels.x]);\n }\n if (!options.hideYAxisTitle) {\n var yAxisLabel = this.axisGraphicsContext.append(\"text\")\n .style(\"text-anchor\", \"middle\")\n .text(options.axisLabels.y)\n .call(function (text) {\n text.each(function () {\n var text = d3.select(this);\n text.attr({\n \"class\": \"yAxisLabel\",\n \"transform\": \"rotate(-90)\",\n \"y\": showOnRight ? width + margin.right - fontSize : -margin.left,\n \"x\": -((height - margin.top - margin.bottom) / 2),\n \"dy\": \"1em\",\n });\n });\n });\n yAxisLabel.style(\"fill\", options.yLabelColor ? options.yLabelColor.solid.color : null);\n yAxisLabel.call(visuals.AxisHelper.LabelLayoutStrategy.clip, height - (margin.bottom + margin.top), powerbi.TextMeasurementService.svgEllipsis)\n .call(visuals.tooltipUtils.tooltipUpdate, [options.axisLabels.y]);\n }\n if (!options.hideY2AxisTitle && options.axisLabels.y2) {\n var y2AxisLabel = this.axisGraphicsContext.append(\"text\")\n .style(\"text-anchor\", \"middle\")\n .text(options.axisLabels.y2)\n .call(function (text) {\n text.each(function () {\n var text = d3.select(this);\n text.attr({\n \"class\": \"yAxisLabel\",\n \"transform\": \"rotate(-90)\",\n \"y\": showOnRight ? -margin.left : width + margin.right - fontSize,\n \"x\": -((height - margin.top - margin.bottom) / 2),\n \"dy\": \"1em\",\n });\n });\n });\n y2AxisLabel.style(\"fill\", options.y2LabelColor ? options.y2LabelColor.solid.color : null);\n y2AxisLabel.call(visuals.AxisHelper.LabelLayoutStrategy.clip, height - (margin.bottom + margin.top), powerbi.TextMeasurementService.svgEllipsis)\n .call(visuals.tooltipUtils.tooltipUpdate, [options.axisLabels.y2]);\n }\n };\n // Margin convention: http://bl.ocks.org/mbostock/3019563\n SvgCartesianAxes.prototype.translateAxes = function (viewport, margin) {\n var width = viewport.width - (margin.left + margin.right);\n var height = viewport.height - (margin.top + margin.bottom);\n var showY1OnRight = this.axes.shouldShowY1OnRight();\n this.xAxisGraphicsContext\n .attr('transform', visuals.SVGUtil.translate(0, height));\n this.y1AxisGraphicsContext\n .attr('transform', visuals.SVGUtil.translate(showY1OnRight ? width : 0, 0));\n this.y2AxisGraphicsContext\n .attr('transform', visuals.SVGUtil.translate(showY1OnRight ? 0 : width, 0));\n this.svgScrollable.attr({\n 'x': 0,\n 'width': viewport.width,\n 'height': viewport.height\n });\n this.axisGraphicsContext.attr('transform', visuals.SVGUtil.translate(margin.left, margin.top));\n this.axisGraphicsContextScrollable.attr('transform', visuals.SVGUtil.translate(margin.left, margin.top));\n this.labelRegion.attr('transform', visuals.SVGUtil.translate(margin.left, margin.top));\n this.labelBackgroundRegion.attr('transform', visuals.SVGUtil.translate(margin.left, margin.top));\n if (this.axes.isXScrollBarVisible) {\n this.svgScrollable.attr({\n 'x': margin.left\n });\n this.axisGraphicsContextScrollable.attr('transform', visuals.SVGUtil.translate(0, margin.top));\n this.labelRegion.attr('transform', visuals.SVGUtil.translate(0, margin.top));\n this.labelBackgroundRegion.attr('transform', visuals.SVGUtil.translate(0, margin.top));\n this.svgScrollable.attr('width', width);\n }\n else if (this.axes.isYScrollBarVisible) {\n this.svgScrollable.attr('height', height + margin.top);\n }\n };\n /**\n * Within the context of the given selection (g), find the offset of\n * the zero tick using the d3 attached datum of g.tick elements.\n * 'Classed' is undefined for transition selections\n */\n SvgCartesianAxes.darkenZeroLine = function (g) {\n // remove zero-line class from all first, filtering can cause lines that are no longer zero to still be dark (since the key is index based)\n g.selectAll('g.tick line').classed('zero-line', false);\n var zeroTick = g.selectAll('g.tick').filter(function (data) { return data === 0; }).node();\n if (zeroTick) {\n d3.select(zeroTick).select('line').classed('zero-line', true);\n }\n };\n SvgCartesianAxes.setAxisLabelColor = function (g, fill) {\n g.selectAll('g.tick text').style('fill', fill ? fill.solid.color : null);\n };\n // These match D3's internal axis padding values\n SvgCartesianAxes.AxisPadding = {\n left: 10,\n right: 10,\n top: 0,\n bottom: 13,\n };\n SvgCartesianAxes.AxisGraphicsContext = createClassAndSelector('axisGraphicsContext');\n SvgCartesianAxes.TickPaddingRotatedX = 5;\n SvgCartesianAxes.AxisLabelFontSize = 11;\n SvgCartesianAxes.Y2TickSize = -6;\n return SvgCartesianAxes;\n }());\n visuals.SvgCartesianAxes = SvgCartesianAxes;\n var CartesianAxes = (function () {\n function CartesianAxes(isScrollable, scrollbarWidth, trimOrdinalDataOnOverflow) {\n this.scrollbarWidth = scrollbarWidth;\n this.isScrollable = isScrollable;\n this.maxMarginFactor = CartesianAxes.MaxMarginFactor;\n this.yAxisOrientation = visuals.yAxisPosition.left;\n this.trimOrdinalDataOnOverflow = trimOrdinalDataOnOverflow;\n }\n CartesianAxes.prototype.shouldShowY1OnRight = function () {\n return this.yAxisOrientation === visuals.yAxisPosition.right;\n };\n CartesianAxes.prototype.isYAxisCategorical = function () {\n return this.layout && this.layout.axes.y1.isCategoryAxis;\n };\n CartesianAxes.prototype.hasCategoryAxis = function () {\n var axes = this.layout && this.layout.axes;\n if (!axes)\n return false;\n return this.isYAxisCategorical()\n ? axes.y1 && axes.y1.axis != null\n : axes.x && axes.x.axis != null;\n };\n CartesianAxes.prototype.hasY2Axis = function () {\n return this.layout && this.layout.axes.y2 != null;\n };\n CartesianAxes.prototype.getYAxisOrientation = function () {\n return this.yAxisOrientation;\n };\n CartesianAxes.prototype.setAxisLinesVisibility = function (axisLinesVisibility) {\n this.showLinesOnX = EnumExtensions.hasFlag(axisLinesVisibility, 3 /* ShowLinesOnBothAxis */) ||\n EnumExtensions.hasFlag(axisLinesVisibility, 1 /* ShowLinesOnXAxis */);\n this.showLinesOnY = EnumExtensions.hasFlag(axisLinesVisibility, 3 /* ShowLinesOnBothAxis */) ||\n EnumExtensions.hasFlag(axisLinesVisibility, 2 /* ShowLinesOnYAxis */);\n };\n CartesianAxes.prototype.setMaxMarginFactor = function (factor) {\n this.maxMarginFactor = factor;\n };\n CartesianAxes.prototype.update = function (dataViews) {\n if (dataViews && dataViews.length > 0) {\n var dataViewMetadata = dataViews[0].metadata;\n this.categoryAxisProperties = visuals.CartesianHelper.getCategoryAxisProperties(dataViewMetadata);\n this.valueAxisProperties = visuals.CartesianHelper.getValueAxisProperties(dataViewMetadata);\n }\n var axisPosition = this.valueAxisProperties['position'];\n this.yAxisOrientation = axisPosition ? axisPosition.toString() : visuals.yAxisPosition.left;\n };\n CartesianAxes.prototype.addWarnings = function (warnings) {\n var axes = this.layout && this.layout.axes;\n if (axes && axes.x && axes.x.hasDisallowedZeroInDomain\n || axes.y1 && axes.y1.hasDisallowedZeroInDomain\n || axes.y2 && axes.y2.hasDisallowedZeroInDomain) {\n warnings.unshift(new visuals.ZeroValueWarning());\n }\n };\n /**\n * Computes the Cartesian Chart axes from the set of layers.\n */\n CartesianAxes.prototype.calculateAxes = function (layers, viewport, margin, playAxisControlLayout, textProperties, scrollbarVisible, existingAxisProperties, hideAxisTitles, ensureXDomain, ensureYDomain) {\n debug.assertValue(layers, 'layers');\n var visualOptions = {\n viewport: viewport,\n margin: margin,\n forcedXDomain: [this.categoryAxisProperties ? this.categoryAxisProperties['start'] : null, this.categoryAxisProperties ? this.categoryAxisProperties['end'] : null],\n forceMerge: this.valueAxisProperties && this.valueAxisProperties['secShow'] === false,\n showCategoryAxisLabel: false,\n showValueAxisLabel: false,\n trimOrdinalDataOnOverflow: this.trimOrdinalDataOnOverflow,\n categoryAxisScaleType: this.categoryAxisProperties && this.categoryAxisProperties['axisScale'] != null ? this.categoryAxisProperties['axisScale'] : DEFAULT_AXIS_SCALE_TYPE,\n valueAxisScaleType: this.valueAxisProperties && this.valueAxisProperties['axisScale'] != null ? this.valueAxisProperties['axisScale'] : DEFAULT_AXIS_SCALE_TYPE,\n categoryAxisDisplayUnits: this.categoryAxisProperties && this.categoryAxisProperties['labelDisplayUnits'] != null ? this.categoryAxisProperties['labelDisplayUnits'] : 0,\n valueAxisDisplayUnits: this.valueAxisProperties && this.valueAxisProperties['labelDisplayUnits'] != null ? this.valueAxisProperties['labelDisplayUnits'] : 0,\n categoryAxisPrecision: this.categoryAxisProperties ? visuals.CartesianHelper.getPrecision(this.categoryAxisProperties['labelPrecision']) : null,\n valueAxisPrecision: this.valueAxisProperties ? visuals.CartesianHelper.getPrecision(this.valueAxisProperties['labelPrecision']) : null,\n playAxisControlLayout: playAxisControlLayout,\n ensureXDomain: ensureXDomain,\n ensureYDomain: ensureYDomain,\n };\n var skipMerge = this.valueAxisProperties && this.valueAxisProperties['secShow'] === true;\n var yAxisWillMerge = false;\n var mergeResult;\n if (hasMultipleYAxes(layers) && !skipMerge) {\n mergeResult = tryMergeYDomains(layers, visualOptions);\n yAxisWillMerge = mergeResult.merged;\n if (yAxisWillMerge) {\n visualOptions.forcedYDomain = mergeResult.domain;\n }\n else {\n visualOptions.forcedTickCount = mergeResult.tickCount;\n }\n }\n if (this.valueAxisProperties) {\n visualOptions.forcedYDomain = visuals.AxisHelper.applyCustomizedDomain([this.valueAxisProperties['start'], this.valueAxisProperties['end']], visualOptions.forcedYDomain);\n }\n var result;\n for (var layerNumber = 0, len = layers.length; layerNumber < len; layerNumber++) {\n var currentlayer = layers[layerNumber];\n if (layerNumber === 1 && !yAxisWillMerge) {\n visualOptions.forcedYDomain = this.valueAxisProperties ? [this.valueAxisProperties['secStart'], this.valueAxisProperties['secEnd']] : null;\n visualOptions.valueAxisScaleType = this.valueAxisProperties && this.valueAxisProperties['secAxisScale'] != null ? this.valueAxisProperties['secAxisScale'] : DEFAULT_AXIS_SCALE_TYPE;\n visualOptions.valueAxisDisplayUnits = this.valueAxisProperties && this.valueAxisProperties['secLabelDisplayUnits'] != null ? this.valueAxisProperties['secLabelDisplayUnits'] : 0;\n visualOptions.valueAxisPrecision = this.valueAxisProperties ? visuals.CartesianHelper.getPrecision(this.valueAxisProperties['secLabelPrecision']) : null;\n }\n visualOptions.showCategoryAxisLabel = (!!this.categoryAxisProperties && !!this.categoryAxisProperties['showAxisTitle']); //here\n visualOptions.showValueAxisLabel = shouldShowYAxisLabel(layerNumber, this.valueAxisProperties, yAxisWillMerge);\n var axes = currentlayer.calculateAxesProperties(visualOptions);\n if (layerNumber === 0) {\n result = {\n x: axes[0],\n y1: axes[1]\n };\n }\n else if (axes && !result.y2) {\n if (result.x.usingDefaultDomain || _.isEmpty(result.x.dataDomain)) {\n visualOptions.showValueAxisLabel = (!!this.valueAxisProperties && !!this.valueAxisProperties['showAxisTitle']);\n var axes_1 = currentlayer.calculateAxesProperties(visualOptions);\n // no categories returned for the first layer, use second layer x-axis properties\n result.x = axes_1[0];\n // and 2nd value axis to be the primary\n result.y1 = axes_1[1];\n }\n else {\n // make sure all layers use the same x-axis/scale for drawing\n currentlayer.overrideXScale(result.x);\n if (!yAxisWillMerge && !axes[1].usingDefaultDomain)\n result.y2 = axes[1];\n }\n }\n if (existingAxisProperties && existingAxisProperties.x) {\n result.x.willLabelsFit = existingAxisProperties.x.willLabelsFit;\n result.x.willLabelsWordBreak = existingAxisProperties.x.willLabelsWordBreak;\n }\n else {\n var width = viewport.width - (margin.left + margin.right);\n result.x.willLabelsFit = visuals.AxisHelper.LabelLayoutStrategy.willLabelsFit(result.x, width, powerbi.TextMeasurementService.measureSvgTextWidth, textProperties);\n // If labels do not fit and we are not scrolling, try word breaking\n result.x.willLabelsWordBreak = (!result.x.willLabelsFit && !scrollbarVisible) && visuals.AxisHelper.LabelLayoutStrategy.willLabelsWordBreak(result.x, margin, width, powerbi.TextMeasurementService.measureSvgTextWidth, powerbi.TextMeasurementService.estimateSvgTextHeight, powerbi.TextMeasurementService.getTailoredTextOrDefault, textProperties);\n }\n }\n // Adjust for axis titles\n if (hideAxisTitles) {\n result.x.axisLabel = null;\n result.y1.axisLabel = null;\n if (result.y2) {\n result.y2.axisLabel = null;\n }\n }\n this.addUnitTypeToAxisLabels(result);\n return result;\n };\n /**\n * Negotiate the axes regions, the plot area, and determine if we need a scrollbar for ordinal categories.\n * @param layers an array of Cartesian layout layers (column, line, etc.)\n * @param parentViewport the full viewport for the visual\n * @param padding the D3 axis padding values\n * @param playAxisControlLayout if this is a playable Cartesian chart, includes the layout for the play controls (start/stop, time slider)\n * @param hideAxisLabels forces axis titles to be hidden\n * @param textProperties text properties to be used by text measurement\n * @param interactivityRightMargin extra right margin for the interactivity\n * @param ensureXDomain if non null, includes values that must be part of the axis domain\n * @param ensureYDomain if non null, includes values that must be part of the axis domain\n */\n CartesianAxes.prototype.negotiateAxes = function (layers, parentViewport, padding, playAxisControlLayout, hideAxisLabels, textProperties, interactivityRightMargin, ensureXDomain, ensureYDomain) {\n // 1> MinMargins -> some initial axis properties / text\n // 2> Get axis margins for the initial text, no rotateXTickLabels90. margins grown? -> axis properties / text again (possibly more tick labels now)\n // ?> do we have more labels? do we need rotate? are we done?\n // 3> margins again (rotate? margins grow?) -> text again (less tick labls now?)\n // FREEZE PROPERTIES THAT CAN CHANGE\n // 4> margins (final), axes (final)\n // 1.a) initialize margins\n var margin = powerbi.Prototype.inherit(CartesianAxes.MinimumMargin);\n var viewport = powerbi.Prototype.inherit(parentViewport);\n var leftRightMarginLimit = viewport.width * this.maxMarginFactor;\n var bottomMarginLimit = Math.max(CartesianAxes.MinimumMargin.bottom, Math.ceil(viewport.height * this.maxMarginFactor));\n var marginLimits = {\n left: leftRightMarginLimit,\n right: leftRightMarginLimit,\n top: 0,\n bottom: bottomMarginLimit,\n };\n // 1.b) Calculate axis properties using initial margins\n var axes = this.calculateAxes(layers, viewport, margin, playAxisControlLayout, textProperties, \n /*scrollbarVisible*/ false, \n /*previousAxisProperties*/ null, hideAxisLabels, ensureXDomain, ensureYDomain);\n // these are used by getTickLabelMargins\n var renderXAxis = this.shouldRenderAxis(axes.x);\n var renderY1Axis = this.shouldRenderAxis(axes.y1);\n var renderY2Axis = this.shouldRenderAxis(axes.y2, true);\n var showY1OnRight = this.shouldShowY1OnRight();\n var plotArea = {\n width: viewport.width - (margin.left + margin.right),\n height: viewport.height - (margin.top + margin.bottom)\n };\n var isScalar = false;\n if (!_.isEmpty(layers)) {\n if (layers[0].getVisualCategoryAxisIsScalar)\n isScalar = layers[0].getVisualCategoryAxisIsScalar();\n }\n // 2.a) calculate axis tick margins\n var tickLabelMargins = undefined;\n tickLabelMargins = visuals.AxisHelper.getTickLabelMargins(plotArea, marginLimits.left, powerbi.TextMeasurementService.measureSvgTextWidth, powerbi.TextMeasurementService.estimateSvgTextHeight, axes, marginLimits.bottom, textProperties, \n /*scrolling*/ false, showY1OnRight, renderXAxis, renderY1Axis, renderY2Axis);\n margin = this.updateAxisMargins(axes, tickLabelMargins, padding, showY1OnRight, renderY1Axis, renderY2Axis, isScalar ? 0 : interactivityRightMargin);\n // if any of these change, we need to calculate margins again\n var previousTickCountY1 = axes.y1 && axes.y1.values.length;\n var previousTickCountY2 = axes.y2 && axes.y2.values.length;\n var previousWillFitX = axes.x && axes.x.willLabelsFit;\n var previousWillBreakX = axes.x && axes.x.willLabelsWordBreak;\n // 2.b) Re-calculate the axes with the new margins.\n axes = this.calculateAxes(layers, viewport, margin, playAxisControlLayout, textProperties, \n /*scrollbarVisible*/ false, \n /*previousAxes*/ null, hideAxisLabels, ensureXDomain, ensureYDomain);\n plotArea.width = viewport.width - (margin.left + margin.right);\n plotArea.height = viewport.height - (margin.top + margin.bottom);\n // check properties that affect getTickLabelMargin - if these are the same, we don't need to calculate axis margins again\n var preferredPlotArea = this.getPreferredPlotArea(axes, layers, isScalar);\n var rotateXTickLabels90 = !this.willAllCategoriesFitInPlotArea(plotArea, preferredPlotArea);\n var allDone = ((!axes.y1 || axes.y1.values.length === previousTickCountY1)\n && (!axes.y2 || axes.y2.values.length === previousTickCountY2)\n && (!axes.x || axes.x.willLabelsFit === previousWillFitX)\n && (!axes.x || axes.x.willLabelsWordBreak === previousWillBreakX)\n && !rotateXTickLabels90);\n this.isXScrollBarVisible = false;\n this.isYScrollBarVisible = false;\n if (!allDone) {\n // 3.a) calculate axis tick margins\n tickLabelMargins = visuals.AxisHelper.getTickLabelMargins(plotArea, marginLimits.left, powerbi.TextMeasurementService.measureSvgTextWidth, powerbi.TextMeasurementService.estimateSvgTextHeight, axes, marginLimits.bottom, textProperties, rotateXTickLabels90, showY1OnRight, renderXAxis, renderY1Axis, renderY2Axis);\n margin = this.updateAxisMargins(axes, tickLabelMargins, padding, showY1OnRight, renderY1Axis, renderY2Axis, isScalar ? 0 : interactivityRightMargin);\n // 3.b) Re-calculate the axes with the new final margins\n axes = this.calculateAxes(layers, viewport, margin, playAxisControlLayout, textProperties, \n /*scrollbarVisible*/ rotateXTickLabels90, axes, hideAxisLabels, ensureXDomain, ensureYDomain);\n // now we can determine if we need actual scrolling\n // rotateXTickLabels90 will give more plotArea to categories since the left-overflow of a rotated category label doesn't exist anymore\n plotArea.width = viewport.width - (margin.left + margin.right);\n plotArea.height = viewport.height - (margin.top + margin.bottom);\n preferredPlotArea = this.getPreferredPlotArea(axes, layers, isScalar);\n var willScroll = !this.willAllCategoriesFitInPlotArea(plotArea, preferredPlotArea);\n if (willScroll) {\n if (this.showLinesOnY) {\n this.isXScrollBarVisible = true;\n plotArea.height -= this.scrollbarWidth;\n viewport.height -= this.scrollbarWidth;\n }\n if (this.showLinesOnX) {\n this.isYScrollBarVisible = true;\n plotArea.width -= this.scrollbarWidth;\n viewport.width -= this.scrollbarWidth;\n }\n // 3.c) Re-calculate the axes with the final margins (and the updated viewport - scrollbarWidth)\n axes = this.calculateAxes(layers, viewport, margin, playAxisControlLayout, textProperties, \n /*scrollbarVisible*/ true, axes, hideAxisLabels, ensureXDomain, ensureYDomain);\n }\n }\n ///////DONE\n var axisLabels = hideAxisLabels ?\n { x: null, y: null, y2: null } :\n { x: axes.x.axisLabel, y: axes.y1.axisLabel, y2: axes.y2 ? axes.y2.axisLabel : null };\n this.layout = {\n axes: axes,\n axisLabels: axisLabels,\n margin: margin,\n marginLimits: marginLimits,\n viewport: viewport,\n plotArea: plotArea,\n preferredPlotArea: preferredPlotArea,\n tickLabelMargins: tickLabelMargins,\n tickPadding: padding,\n rotateXTickLabels90: rotateXTickLabels90,\n };\n return this.layout;\n };\n CartesianAxes.prototype.getPreferredPlotArea = function (axes, layers, isScalar) {\n var preferredPlotArea;\n if (!isScalar && this.isScrollable && !_.isEmpty(layers) && layers[0].getPreferredPlotArea) {\n var categoryThickness = this.showLinesOnY ? axes.x.categoryThickness : axes.y1.categoryThickness;\n var categoryCount = this.showLinesOnY ? axes.x.dataDomain.length : axes.y1.dataDomain.length;\n preferredPlotArea = layers[0].getPreferredPlotArea(isScalar, categoryCount, categoryThickness);\n }\n return preferredPlotArea;\n };\n CartesianAxes.prototype.willAllCategoriesFitInPlotArea = function (plotArea, preferredPlotArea) {\n if (this.showLinesOnY && preferredPlotArea && powerbi.Double.greaterWithPrecision(preferredPlotArea.width, plotArea.width)) {\n return false;\n }\n if (this.showLinesOnX && preferredPlotArea && powerbi.Double.greaterWithPrecision(preferredPlotArea.height, plotArea.height)) {\n return false;\n }\n return true;\n };\n CartesianAxes.prototype.updateAxisMargins = function (axes, tickLabelMargins, padding, showY1OnRight, renderY1Axis, renderY2Axis, interactivityRightMargin) {\n // We look at the y axes as main and second sides, if the y axis orientation is right then the main side represents the right side.\n var maxY1Padding = showY1OnRight ? tickLabelMargins.yRight : tickLabelMargins.yLeft, maxY2Padding = showY1OnRight ? tickLabelMargins.yLeft : tickLabelMargins.yRight, maxXAxisBottom = tickLabelMargins.xMax;\n maxY1Padding += padding.left;\n if ((renderY2Axis && !showY1OnRight) || (showY1OnRight && renderY1Axis))\n maxY2Padding += padding.right;\n maxXAxisBottom += padding.bottom;\n var axisLabels = { x: axes.x.axisLabel, y: axes.y1.axisLabel, y2: axes.y2 ? axes.y2.axisLabel : null };\n if (axisLabels.x != null)\n maxXAxisBottom += CartesianAxes.XAxisLabelPadding;\n if (axisLabels.y != null)\n maxY1Padding += CartesianAxes.YAxisLabelPadding;\n if (axisLabels.y2 != null)\n maxY2Padding += CartesianAxes.YAxisLabelPadding;\n var margin = powerbi.Prototype.inherit(CartesianAxes.MinimumMargin);\n margin.left = showY1OnRight ? maxY2Padding : maxY1Padding;\n margin.right = showY1OnRight ? maxY1Padding : maxY2Padding;\n margin.right += interactivityRightMargin; // for mobile interactive legend\n margin.bottom = maxXAxisBottom;\n return margin;\n };\n CartesianAxes.prototype.isLogScaleAllowed = function (axisType) {\n var axes = this.layout && this.layout.axes;\n if (!axes)\n return false;\n switch (axisType) {\n case 0 /* X */:\n return axes.x.isLogScaleAllowed;\n case 1 /* Y1 */:\n return axes.y1.isLogScaleAllowed;\n case 2 /* Y2 */:\n return axes.y2 && axes.y2.isLogScaleAllowed;\n }\n };\n CartesianAxes.prototype.axesHaveTicks = function (viewport) {\n if (!this.layout)\n return false;\n var margin = this.layout.margin;\n var width = viewport.width - (margin.left + margin.right);\n var height = viewport.height - (margin.top + margin.bottom);\n // TODO: this is never the case, remove.\n if (visuals.AxisHelper.getRecommendedNumberOfTicksForXAxis(width) === 0\n && visuals.AxisHelper.getRecommendedNumberOfTicksForYAxis(height) === 0) {\n return false;\n }\n return true;\n };\n CartesianAxes.prototype.shouldRenderAxisTitle = function (axisProperties, defaultValue, secondary) {\n var propertyName = secondary ? 'secShowAxisTitle' : 'showAxisTitle';\n return !!this.getAxisProperty(axisProperties, propertyName, defaultValue);\n };\n CartesianAxes.prototype.shouldRenderAxis = function (axisProperties, secondary) {\n if (secondary === void 0) { secondary = false; }\n if (!axisProperties)\n return false;\n var propertyName = secondary ? 'secShow' : 'show';\n return this.getAxisProperty(axisProperties, propertyName, true)\n && axisProperties.values\n && axisProperties.values.length > 0;\n };\n CartesianAxes.prototype.getAxisProperty = function (axisProperties, propertyName, defaultValue) {\n if (!axisProperties)\n return defaultValue;\n var properties = axisProperties.isCategoryAxis\n ? this.categoryAxisProperties\n : this.valueAxisProperties;\n if (properties && properties[propertyName] != null)\n return properties[propertyName];\n else\n return defaultValue;\n };\n // TODO: clean this up\n CartesianAxes.prototype.addUnitTypeToAxisLabels = function (axes) {\n var unitType = CartesianAxes.getUnitType(axes.x.formatter);\n if (axes.x.isCategoryAxis) {\n this.categoryAxisHasUnitType = unitType != null;\n }\n else {\n this.valueAxisHasUnitType = unitType != null;\n }\n if (axes.x.axisLabel && unitType) {\n if (axes.x.isCategoryAxis) {\n axes.x.axisLabel = visuals.AxisHelper.createAxisLabel(this.categoryAxisProperties, axes.x.axisLabel, unitType);\n }\n else {\n axes.x.axisLabel = visuals.AxisHelper.createAxisLabel(this.valueAxisProperties, axes.x.axisLabel, unitType);\n }\n }\n unitType = CartesianAxes.getUnitType(axes.y1.formatter);\n if (!axes.y1.isCategoryAxis) {\n this.valueAxisHasUnitType = unitType != null;\n }\n else {\n this.categoryAxisHasUnitType = unitType != null;\n }\n if (axes.y1.axisLabel && unitType) {\n if (!axes.y1.isCategoryAxis) {\n axes.y1.axisLabel = visuals.AxisHelper.createAxisLabel(this.valueAxisProperties, axes.y1.axisLabel, unitType);\n }\n else {\n axes.y1.axisLabel = visuals.AxisHelper.createAxisLabel(this.categoryAxisProperties, axes.y1.axisLabel, unitType);\n }\n }\n if (axes.y2) {\n var unitType_1 = CartesianAxes.getUnitType(axes.y2.formatter);\n this.secondaryValueAxisHasUnitType = unitType_1 != null;\n if (axes.y2.axisLabel && unitType_1) {\n axes.y2.axisLabel = visuals.AxisHelper.createAxisLabel(this.valueAxisProperties, axes.y2.axisLabel, unitType_1, true);\n }\n }\n };\n CartesianAxes.getUnitType = function (formatter) {\n if (formatter &&\n formatter.displayUnit &&\n formatter.displayUnit.value > 1)\n return formatter.displayUnit.title;\n };\n CartesianAxes.YAxisLabelPadding = 20;\n CartesianAxes.XAxisLabelPadding = 18;\n CartesianAxes.MaxMarginFactor = 0.25;\n CartesianAxes.MinimumMargin = {\n left: 1,\n right: 1,\n top: 8,\n bottom: 25,\n };\n return CartesianAxes;\n }());\n visuals.CartesianAxes = CartesianAxes;\n var CartesianLayerFactory;\n (function (CartesianLayerFactory) {\n function createLayers(type, objects, interactivityService, animator, isScrollable, tooltipsEnabled, lineChartLabelDensityEnabled) {\n if (isScrollable === void 0) { isScrollable = false; }\n var layers = [];\n var cartesianOptions = {\n isScrollable: isScrollable,\n animator: animator,\n interactivityService: interactivityService,\n tooltipsEnabled: tooltipsEnabled,\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\n };\n switch (type) {\n case 1 /* Area */:\n layers.push(createLineChartLayer(2 /* area */, /* inComboChart */ false, cartesianOptions));\n //layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ false, cartesianOptions, true));\n break;\n case 0 /* Line */:\n layers.push(createLineChartLayer(1 /* default */, /* inComboChart */ false, cartesianOptions));\n //layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ false, cartesianOptions, true));\n break;\n case 2 /* StackedArea */:\n layers.push(createLineChartLayer(16 /* stackedArea */, /* inComboChart */ false, cartesianOptions));\n break;\n case 9 /* Scatter */:\n layers.push(createScatterChartLayer(cartesianOptions));\n //layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ false, cartesianOptions, true));\n break;\n case 12 /* Waterfall */:\n layers.push(createWaterfallChartLayer(cartesianOptions));\n break;\n case 11 /* DataDot */:\n layers.push(createDataDotChartLayer(cartesianOptions));\n break;\n case 4 /* StackedColumn */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.stackedColumn, cartesianOptions));\n break;\n case 3 /* ClusteredColumn */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.clusteredColumn, cartesianOptions));\n break;\n case 8 /* HundredPercentStackedColumn */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.hundredPercentStackedColumn, cartesianOptions));\n break;\n case 6 /* StackedBar */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.stackedBar, cartesianOptions));\n break;\n case 5 /* ClusteredBar */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.clusteredBar, cartesianOptions));\n break;\n case 7 /* HundredPercentStackedBar */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.hundredPercentStackedBar, cartesianOptions));\n break;\n case 10 /* ComboChart */:\n var columnType = getComboColumnType();\n layers.push(createColumnChartLayer(columnType, cartesianOptions));\n layers.push(createLineChartLayer(1 /* default */, /* inComboChart */ true, cartesianOptions));\n break;\n case 13 /* LineClusteredColumnCombo */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.clusteredColumn, cartesianOptions));\n layers.push(createLineChartLayer(1 /* default */, /* inComboChart */ true, cartesianOptions));\n break;\n case 14 /* LineStackedColumnCombo */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.stackedColumn, cartesianOptions));\n layers.push(createLineChartLayer(1 /* default */, /* inComboChart */ true, cartesianOptions));\n break;\n case 15 /* DataDotClusteredColumnCombo */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.clusteredColumn, cartesianOptions));\n layers.push(createDataDotChartLayer(cartesianOptions));\n break;\n case 16 /* DataDotStackedColumnCombo */:\n layers.push(createColumnChartLayer(visuals.ColumnChartType.stackedColumn, cartesianOptions));\n layers.push(createDataDotChartLayer(cartesianOptions));\n break;\n }\n return layers;\n }\n CartesianLayerFactory.createLayers = createLayers;\n function createLineChartLayer(type, inComboChart, defaultOptions, isTrendLayer) {\n var options = {\n animator: defaultOptions.animator,\n interactivityService: defaultOptions.interactivityService,\n isScrollable: defaultOptions.isScrollable,\n tooltipsEnabled: !isTrendLayer && defaultOptions.tooltipsEnabled,\n chartType: type,\n lineChartLabelDensityEnabled: defaultOptions.lineChartLabelDensityEnabled,\n isTrendLayer: isTrendLayer,\n };\n if (inComboChart) {\n options.chartType = options.chartType | 8 /* lineShadow */;\n }\n return new visuals.LineChart(options);\n }\n function createScatterChartLayer(defaultOptions) {\n defaultOptions.isScrollable = false;\n return new visuals.ScatterChart(defaultOptions);\n }\n function createWaterfallChartLayer(defaultOptions) {\n return new visuals.WaterfallChart(defaultOptions);\n }\n function createDataDotChartLayer(defaultOptions) {\n return new visuals.DataDotChart(defaultOptions);\n }\n function createColumnChartLayer(type, defaultOptions) {\n var options = {\n animator: defaultOptions.animator,\n interactivityService: defaultOptions.interactivityService,\n isScrollable: defaultOptions.isScrollable,\n tooltipsEnabled: defaultOptions.tooltipsEnabled,\n chartType: type\n };\n return new visuals.ColumnChart(options);\n }\n function getComboColumnType(objects) {\n // This supports existing serialized forms of pinned combo-chart visuals\n var columnType = visuals.ColumnChartType.clusteredColumn;\n if (objects) {\n var comboChartTypes = objects.general;\n if (comboChartTypes) {\n switch (comboChartTypes.visualType1) {\n case 'Column':\n columnType = visuals.ColumnChartType.clusteredColumn;\n break;\n case 'ColumnStacked':\n columnType = visuals.ColumnChartType.stackedColumn;\n break;\n default:\n debug.assertFail('Unsupported cartesian chart type ' + comboChartTypes.visualType1);\n }\n // second visual is always LineChart (for now)\n if (comboChartTypes.visualType2) {\n debug.assert(comboChartTypes.visualType2 === 'Line', 'expecting a LineChart for VisualType2');\n }\n }\n }\n return columnType;\n }\n })(CartesianLayerFactory || (CartesianLayerFactory = {}));\n var SharedColorPalette = (function () {\n function SharedColorPalette(palette) {\n this.palette = palette;\n this.clearPreferredScale();\n }\n SharedColorPalette.prototype.getColorScaleByKey = function (scaleKey) {\n this.setPreferredScale(scaleKey);\n return this.preferredScale;\n };\n SharedColorPalette.prototype.getNewColorScale = function () {\n return this.preferredScale;\n };\n SharedColorPalette.prototype.getColorByIndex = function (index) {\n return this.palette.getColorByIndex(index);\n };\n SharedColorPalette.prototype.getSentimentColors = function () {\n return this.palette.getSentimentColors();\n };\n SharedColorPalette.prototype.getBasePickerColors = function () {\n return this.palette.getBasePickerColors();\n };\n SharedColorPalette.prototype.clearPreferredScale = function () {\n this.preferredScale = this.palette.getNewColorScale();\n this.rotated = false;\n };\n SharedColorPalette.prototype.rotateScale = function () {\n // We create a new rotated the scale such that the first color of the new scale is the first\n // free color of the previous scale. Note that the new scale does not have any colors allocated\n // to particular keys.\n this.preferredScale = this.preferredScale.clone();\n this.preferredScale.clearAndRotateScale();\n this.rotated = true;\n };\n SharedColorPalette.prototype.setPreferredScale = function (scaleKey) {\n if (!this.rotated) {\n // The first layer to express a preference sets the preferred scale.\n this.preferredScale = this.palette.getColorScaleByKey(scaleKey);\n }\n };\n return SharedColorPalette;\n }());\n visuals.SharedColorPalette = SharedColorPalette;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var EnumExtensions = jsCommon.EnumExtensions;\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n var flagBar = 1 << 1;\n var flagColumn = 1 << 2;\n var flagClustered = 1 << 3;\n var flagStacked = 1 << 4;\n var flagStacked100 = flagStacked | (1 << 5);\n (function (ColumnChartType) {\n ColumnChartType[ColumnChartType[\"clusteredBar\"] = flagBar | flagClustered] = \"clusteredBar\";\n ColumnChartType[ColumnChartType[\"clusteredColumn\"] = flagColumn | flagClustered] = \"clusteredColumn\";\n ColumnChartType[ColumnChartType[\"hundredPercentStackedBar\"] = flagBar | flagStacked100] = \"hundredPercentStackedBar\";\n ColumnChartType[ColumnChartType[\"hundredPercentStackedColumn\"] = flagColumn | flagStacked100] = \"hundredPercentStackedColumn\";\n ColumnChartType[ColumnChartType[\"stackedBar\"] = flagBar | flagStacked] = \"stackedBar\";\n ColumnChartType[ColumnChartType[\"stackedColumn\"] = flagColumn | flagStacked] = \"stackedColumn\";\n })(visuals.ColumnChartType || (visuals.ColumnChartType = {}));\n var ColumnChartType = visuals.ColumnChartType;\n var RoleNames = {\n category: 'Category',\n series: 'Series',\n y: 'Y',\n };\n /**\n * Renders a stacked and clustered column chart.\n */\n var ColumnChart = (function () {\n function ColumnChart(options) {\n debug.assertValue(options, 'options');\n var chartType = options.chartType;\n debug.assertValue(chartType, 'chartType');\n this.chartType = chartType;\n this.categoryAxisType = null;\n this.animator = options.animator;\n this.isScrollable = options.isScrollable;\n this.tooltipsEnabled = options.tooltipsEnabled;\n this.interactivityService = options.interactivityService;\n }\n ColumnChart.customizeQuery = function (options) {\n var dataViewMapping = options.dataViewMappings[0];\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\n return;\n dataViewMapping.categorical.dataVolume = 4;\n if (visuals.CartesianChart.detectScalarMapping(dataViewMapping)) {\n var dataViewCategories = dataViewMapping.categorical.categories;\n dataViewCategories.dataReductionAlgorithm = { sample: {} };\n }\n };\n ColumnChart.getSortableRoles = function (options) {\n var dataViewMapping = options.dataViewMappings[0];\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\n return null;\n var dataViewCategories = dataViewMapping.categorical.categories;\n var categoryItems = dataViewCategories.for.in.items;\n if (!_.isEmpty(categoryItems)) {\n var categoryType = categoryItems[0].type;\n var objects = void 0;\n if (dataViewMapping.metadata)\n objects = dataViewMapping.metadata.objects;\n //TODO: column chart should be sortable by X if it has scalar axis\n // But currenly it doesn't support this. Return 'category' once\n // it is supported.\n if (!visuals.CartesianChart.getIsScalar(objects, visuals.columnChartProps.categoryAxis.axisType, categoryType)) {\n return ['Category', 'Y'];\n }\n }\n return null;\n };\n ColumnChart.prototype.updateVisualMetadata = function (x, y, margin) {\n this.xAxisProperties = x;\n this.yAxisProperties = y;\n this.margin = margin;\n };\n ColumnChart.prototype.init = function (options) {\n this.svg = options.svg;\n this.svg.classed(ColumnChart.ColumnChartClassName, true);\n this.unclippedGraphicsContext = this.svg.append('g').classed('columnChartUnclippedGraphicsContext', true);\n this.mainGraphicsContext = this.unclippedGraphicsContext.append('svg').classed('columnChartMainGraphicsContext', true);\n this.style = options.style;\n this.currentViewport = options.viewport;\n this.hostService = options.host;\n this.interactivity = options.interactivity;\n this.colors = this.style.colorPalette.dataColors;\n this.cartesianVisualHost = options.cartesianHost;\n this.options = options;\n this.isComboChart = visuals.ComboChart.isComboChart(options.chartType);\n this.element = options.element;\n };\n ColumnChart.prototype.getCategoryLayout = function (numCategoryValues, options) {\n var availableWidth;\n if (ColumnChart.isBar(this.chartType)) {\n availableWidth = this.currentViewport.height - (this.margin.top + this.margin.bottom);\n }\n else {\n availableWidth = this.currentViewport.width - (this.margin.left + this.margin.right);\n }\n var metaDataColumn = this.data ? this.data.categoryMetadata : undefined;\n var categoryDataType = visuals.AxisHelper.getCategoryValueType(metaDataColumn);\n var isScalar = this.data ? this.data.scalarCategoryAxis : false;\n var domain = visuals.AxisHelper.createDomain(this.data.series, categoryDataType, isScalar, options.forcedXDomain, options.ensureXDomain);\n return visuals.CartesianChart.getLayout(this.data, {\n availableWidth: availableWidth,\n categoryCount: numCategoryValues,\n domain: domain,\n isScalar: isScalar,\n isScrollable: this.isScrollable,\n trimOrdinalDataOnOverflow: options.trimOrdinalDataOnOverflow\n });\n };\n ColumnChart.converter = function (dataView, colors, is100PercentStacked, isScalar, dataViewMetadata, chartType, interactivityService, tooltipsEnabled) {\n if (is100PercentStacked === void 0) { is100PercentStacked = false; }\n if (isScalar === void 0) { isScalar = false; }\n if (dataViewMetadata === void 0) { dataViewMetadata = null; }\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n debug.assertValue(dataView, 'dataView');\n debug.assertValue(colors, 'colors');\n var xAxisCardProperties = visuals.CartesianHelper.getCategoryAxisProperties(dataViewMetadata);\n var valueAxisProperties = visuals.CartesianHelper.getValueAxisProperties(dataViewMetadata);\n isScalar = visuals.CartesianHelper.isScalar(isScalar, xAxisCardProperties);\n var dataViewCat = visuals.ColumnUtil.applyUserMinMax(isScalar, dataView.categorical, xAxisCardProperties);\n var converterStrategy = new ColumnChartConverterHelper(dataView);\n var categoryInfo = visuals.converterHelper.getPivotedCategories(dataViewCat, visuals.columnChartProps.general.formatString);\n var categories = categoryInfo.categories, categoryFormatter = categoryInfo.categoryFormatter, categoryIdentities = categoryInfo.categoryIdentities, categoryMetadata = dataViewCat && dataViewCat.categories && dataViewCat.categories.length > 0 ? dataViewCat.categories[0].source : undefined;\n var labelSettings = visuals.dataLabelUtils.getDefaultColumnLabelSettings(is100PercentStacked || ColumnChart.isStacked(chartType));\n var defaultLegendLabelColor = visuals.LegendData.DefaultLegendLabelFillColor;\n var defaultDataPointColor = undefined;\n var showAllDataPoints = undefined;\n if (dataViewMetadata && dataViewMetadata.objects) {\n var objects = dataViewMetadata.objects;\n defaultDataPointColor = powerbi.DataViewObjects.getFillColor(objects, visuals.columnChartProps.dataPoint.defaultColor);\n showAllDataPoints = powerbi.DataViewObjects.getValue(objects, visuals.columnChartProps.dataPoint.showAllDataPoints);\n defaultLegendLabelColor = powerbi.DataViewObjects.getFillColor(objects, visuals.columnChartProps.legend.labelColor, visuals.LegendData.DefaultLegendLabelFillColor);\n var labelsObj = objects['labels'];\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, labelSettings);\n }\n // Allocate colors\n var legendAndSeriesInfo = converterStrategy.getLegend(colors, defaultLegendLabelColor, defaultDataPointColor);\n var legend = legendAndSeriesInfo.legend.dataPoints;\n var seriesSources = legendAndSeriesInfo.seriesSources;\n // Determine data points\n var result = ColumnChart.createDataPoints(dataView, categories, categoryIdentities, legend, legendAndSeriesInfo.seriesObjects, converterStrategy, labelSettings, is100PercentStacked, isScalar, visuals.converterHelper.categoryIsAlsoSeriesRole(dataView, RoleNames.series, RoleNames.category), categoryInfo.categoryObjects, defaultDataPointColor, chartType, categoryMetadata, tooltipsEnabled);\n var columnSeries = result.series;\n var valuesMetadata = [];\n for (var j = 0, jlen = legend.length; j < jlen; j++) {\n valuesMetadata.push(seriesSources[j]);\n }\n var labels = visuals.converterHelper.createAxesLabels(xAxisCardProperties, valueAxisProperties, categoryMetadata, valuesMetadata);\n if (!ColumnChart.isColumn(chartType)) {\n // Replace between x and y axes\n var temp = labels.xAxisLabel;\n labels.xAxisLabel = labels.yAxisLabel;\n labels.yAxisLabel = temp;\n }\n if (interactivityService) {\n for (var _i = 0, columnSeries_1 = columnSeries; _i < columnSeries_1.length; _i++) {\n var series = columnSeries_1[_i];\n interactivityService.applySelectionStateToData(series.data);\n }\n interactivityService.applySelectionStateToData(legendAndSeriesInfo.legend.dataPoints);\n }\n return {\n categories: categories,\n categoryFormatter: categoryFormatter,\n series: columnSeries,\n valuesMetadata: valuesMetadata,\n legendData: legendAndSeriesInfo.legend,\n hasHighlights: result.hasHighlights,\n categoryMetadata: categoryMetadata,\n scalarCategoryAxis: isScalar,\n labelSettings: labelSettings,\n axesLabels: { x: labels.xAxisLabel, y: labels.yAxisLabel },\n hasDynamicSeries: result.hasDynamicSeries,\n isMultiMeasure: result.isMultiMeasure,\n defaultDataPointColor: defaultDataPointColor,\n showAllDataPoints: showAllDataPoints,\n };\n };\n ColumnChart.canSupportOverflow = function (chartType, seriesCount) {\n return !ColumnChart.isStacked(chartType) || seriesCount === 1;\n };\n ColumnChart.createDataPoints = function (dataView, categories, categoryIdentities, legend, seriesObjectsList, converterStrategy, defaultLabelSettings, is100PercentStacked, isScalar, isCategoryAlsoSeries, categoryObjectsList, defaultDataPointColor, chartType, categoryMetadata, tooltipsEnabled) {\n if (is100PercentStacked === void 0) { is100PercentStacked = false; }\n if (isScalar === void 0) { isScalar = false; }\n var dataViewCat = dataView.categorical;\n var grouped = dataViewCat && dataViewCat.values ? dataViewCat.values.grouped() : undefined;\n var categoryCount = categories.length;\n var seriesCount = legend.length;\n var columnSeries = [];\n if (seriesCount < 1 || categoryCount < 1)\n return { series: columnSeries, hasHighlights: false, hasDynamicSeries: false, isMultiMeasure: false };\n var dvCategories = dataViewCat.categories;\n categoryMetadata = !_.isEmpty(dvCategories) ? dvCategories[0].source : null;\n var categoryType = visuals.AxisHelper.getCategoryValueType(categoryMetadata);\n var isDateTime = visuals.AxisHelper.isDateTime(categoryType);\n var baseValuesPos = [], baseValuesNeg = [];\n var rawValues = [];\n var rawHighlightValues = [];\n var hasDynamicSeries = !!(dataViewCat.values && dataViewCat.values.source);\n var isMultiMeasure = !hasDynamicSeries && seriesCount > 1;\n var highlightsOverflow = false; // Overflow means the highlight larger than value or the signs being different\n var hasHighlights = converterStrategy.hasHighlightValues(0);\n for (var seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\n var seriesValues = [];\n var seriesHighlightValues = [];\n for (var categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {\n var value = converterStrategy.getValueBySeriesAndCategory(seriesIndex, categoryIndex);\n seriesValues[categoryIndex] = value;\n if (hasHighlights) {\n var highlightValue = converterStrategy.getHighlightBySeriesAndCategory(seriesIndex, categoryIndex);\n seriesHighlightValues[categoryIndex] = highlightValue;\n // There are two cases where we don't use overflow logic; if all are false, use overflow logic appropriate for the chart.\n if (!((value >= 0 && highlightValue >= 0 && value >= highlightValue) ||\n (value <= 0 && highlightValue <= 0 && value <= highlightValue))) {\n highlightsOverflow = true;\n }\n }\n }\n rawValues.push(seriesValues);\n if (hasHighlights) {\n rawHighlightValues.push(seriesHighlightValues);\n }\n }\n if (highlightsOverflow && !ColumnChart.canSupportOverflow(chartType, seriesCount)) {\n highlightsOverflow = false;\n hasHighlights = false;\n rawValues = rawHighlightValues;\n }\n var dataPointObjects = categoryObjectsList, formatStringProp = visuals.columnChartProps.general.formatString;\n for (var seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\n var seriesDataPoints = [], legendItem = legend[seriesIndex], seriesLabelSettings = void 0;\n if (!hasDynamicSeries) {\n var labelsSeriesGroup = !_.isEmpty(grouped) && grouped[0].values ? grouped[0].values[seriesIndex] : null;\n var labelObjects = (labelsSeriesGroup && labelsSeriesGroup.source && labelsSeriesGroup.source.objects) ? labelsSeriesGroup.source.objects['labels'] : null;\n if (labelObjects) {\n seriesLabelSettings = powerbi.Prototype.inherit(defaultLabelSettings);\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(labelObjects, seriesLabelSettings);\n }\n }\n columnSeries.push({\n displayName: legendItem.label,\n key: 'series' + seriesIndex,\n index: seriesIndex,\n data: seriesDataPoints,\n identity: legendItem.identity,\n color: legendItem.color,\n labelSettings: seriesLabelSettings,\n });\n if (seriesCount > 1)\n dataPointObjects = seriesObjectsList[seriesIndex];\n var valueColumnMetadata = dataViewCat.values[seriesIndex].source;\n var gradientMeasureIndex = visuals.GradientUtils.getGradientMeasureIndex(dataViewCat);\n var gradientValueColumn = visuals.GradientUtils.getGradientValueColumn(dataViewCat);\n var valueMeasureIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, \"Y\");\n var pctFormatString = visuals.valueFormatter.getLocalizedString('Percentage');\n for (var categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {\n if (seriesIndex === 0) {\n baseValuesPos.push(0);\n baseValuesNeg.push(0);\n }\n var value = visuals.AxisHelper.normalizeNonFiniteNumber(rawValues[seriesIndex][categoryIndex]);\n if (value == null) {\n // Optimization: Ignore null dataPoints from the fabricated category/series combination in the self cross-join.\n // However, we must retain the first series because it is used to compute things like axis scales, and value lookups.\n if (seriesIndex > 0)\n continue;\n }\n var originalValue = value;\n var categoryValue = categories[categoryIndex];\n // ignore variant measures\n if (isDateTime && categoryValue != null && !(categoryValue instanceof Date))\n continue;\n if (isDateTime && categoryValue)\n categoryValue = categoryValue.getTime();\n if (isScalar && (categoryValue == null || isNaN(categoryValue)))\n continue;\n var multipliers = void 0;\n if (is100PercentStacked)\n multipliers = visuals.StackedUtil.getStackedMultiplier(dataViewCat, categoryIndex, seriesCount, categoryCount, converterStrategy);\n var unadjustedValue = value, isNegative = value < 0;\n if (multipliers) {\n if (isNegative)\n value *= multipliers.neg;\n else\n value *= multipliers.pos;\n }\n var valueAbsolute = Math.abs(value);\n var position = void 0;\n if (isNegative) {\n position = baseValuesNeg[categoryIndex];\n if (!isNaN(valueAbsolute))\n baseValuesNeg[categoryIndex] -= valueAbsolute;\n }\n else {\n if (!isNaN(valueAbsolute))\n baseValuesPos[categoryIndex] += valueAbsolute;\n position = baseValuesPos[categoryIndex];\n }\n var seriesGroup = grouped && grouped.length > seriesIndex && grouped[seriesIndex].values ? grouped[seriesIndex].values[valueMeasureIndex] : null;\n var category = !_.isEmpty(dataViewCat.categories) ? dataViewCat.categories[0] : null;\n var identity = visuals.SelectionIdBuilder.builder()\n .withCategory(category, categoryIndex)\n .withSeries(dataViewCat.values, seriesGroup)\n .withMeasure(converterStrategy.getMeasureNameByIndex(seriesIndex))\n .createSelectionId();\n var rawCategoryValue = categories[categoryIndex];\n var color = ColumnChart.getDataPointColor(legendItem, categoryIndex, dataPointObjects);\n var gradientColumnForTooltip = gradientMeasureIndex === 0 ? null : gradientValueColumn;\n var tooltipInfo = void 0;\n if (tooltipsEnabled) {\n tooltipInfo = [];\n if (category) {\n tooltipInfo.push({\n displayName: category.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(rawCategoryValue, category.source, formatStringProp),\n });\n }\n if (hasDynamicSeries) {\n if (!category || category.source !== dataViewCat.values.source) {\n // Category/series on the same column -- don't repeat its value in the tooltip.\n tooltipInfo.push({\n displayName: dataViewCat.values.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(grouped[seriesIndex].name, dataViewCat.values.source, formatStringProp),\n });\n }\n }\n if (originalValue != null) {\n var valueString = void 0;\n var formattedOriginalValue = visuals.converterHelper.formatFromMetadataColumn(originalValue, valueColumnMetadata, formatStringProp);\n if (is100PercentStacked) {\n var originalPct = visuals.valueFormatter.format(valueAbsolute, pctFormatString);\n valueString = formattedOriginalValue + ' (' + originalPct + ')';\n }\n else {\n valueString = formattedOriginalValue;\n }\n tooltipInfo.push({\n displayName: valueColumnMetadata.displayName,\n value: valueString,\n });\n }\n if (gradientColumnForTooltip && gradientColumnForTooltip.values[categoryIndex] != null) {\n tooltipInfo.push({\n displayName: gradientColumnForTooltip.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(gradientColumnForTooltip.values[categoryIndex], gradientColumnForTooltip.source, formatStringProp),\n });\n }\n }\n var series = columnSeries[seriesIndex];\n var dataPointLabelSettings = (series.labelSettings) ? series.labelSettings : defaultLabelSettings;\n var labelColor = dataPointLabelSettings.labelColor;\n var lastValue = undefined;\n //Stacked column/bar label color is white by default (except last series)\n if ((ColumnChart.isStacked(chartType))) {\n lastValue = this.getStackedLabelColor(isNegative, seriesIndex, seriesCount, categoryIndex, rawValues);\n labelColor = (lastValue || (seriesIndex === seriesCount - 1 && !isNegative)) ? labelColor : visuals.dataLabelUtils.defaultInsideLabelColor;\n }\n var dataPoint = {\n categoryValue: categoryValue,\n value: value,\n position: position,\n valueAbsolute: valueAbsolute,\n valueOriginal: unadjustedValue,\n seriesIndex: seriesIndex,\n labelSettings: dataPointLabelSettings,\n categoryIndex: categoryIndex,\n color: color,\n selected: false,\n originalValue: value,\n originalPosition: position,\n originalValueAbsolute: valueAbsolute,\n identity: identity,\n key: identity.getKey(),\n tooltipInfo: tooltipInfo,\n labelFill: labelColor,\n labelFormatString: valueColumnMetadata.format,\n lastSeries: lastValue,\n chartType: chartType\n };\n seriesDataPoints.push(dataPoint);\n if (hasHighlights) {\n var valueHighlight = rawHighlightValues[seriesIndex][categoryIndex];\n var unadjustedValueHighlight = valueHighlight;\n var highlightedTooltip = true;\n if (valueHighlight === null) {\n valueHighlight = 0;\n highlightedTooltip = false;\n }\n if (is100PercentStacked) {\n valueHighlight *= multipliers.pos;\n }\n var absoluteValueHighlight = Math.abs(valueHighlight);\n var highlightPosition = position;\n if (valueHighlight > 0) {\n highlightPosition -= valueAbsolute - absoluteValueHighlight;\n }\n else if (valueHighlight === 0 && value > 0) {\n highlightPosition -= valueAbsolute;\n }\n var highlightIdentity = visuals.SelectionId.createWithHighlight(identity);\n var highlightedValueAndPct = void 0;\n var highlightedValueFormat = void 0;\n if (highlightedTooltip && unadjustedValueHighlight != null && valueHighlight != null) {\n var highlightedPct = visuals.valueFormatter.format(valueHighlight, pctFormatString);\n highlightedValueFormat = visuals.converterHelper.formatFromMetadataColumn(unadjustedValueHighlight, valueColumnMetadata, formatStringProp);\n highlightedValueAndPct = highlightedValueFormat + ' (' + highlightedPct + ')';\n }\n if (tooltipsEnabled) {\n var highlightValue = void 0;\n if (is100PercentStacked) {\n highlightValue = highlightedValueAndPct;\n }\n else {\n highlightValue = highlightedValueFormat;\n }\n if (highlightValue != null) {\n tooltipInfo.push({\n displayName: visuals.ToolTipComponent.localizationOptions.highlightedValueDisplayName,\n value: highlightValue,\n });\n }\n }\n if (highlightedTooltip) {\n // Override non highlighted data point\n dataPoint.tooltipInfo = tooltipInfo;\n }\n var highlightDataPoint = {\n categoryValue: categoryValue,\n value: valueHighlight,\n position: highlightPosition,\n valueAbsolute: absoluteValueHighlight,\n valueOriginal: unadjustedValueHighlight,\n seriesIndex: seriesIndex,\n labelSettings: dataPointLabelSettings,\n categoryIndex: categoryIndex,\n color: color,\n selected: false,\n highlight: true,\n originalValue: value,\n originalPosition: position,\n originalValueAbsolute: valueAbsolute,\n drawThinner: highlightsOverflow,\n identity: highlightIdentity,\n key: highlightIdentity.getKey(),\n tooltipInfo: tooltipInfo,\n labelFormatString: valueColumnMetadata.format,\n labelFill: labelColor,\n lastSeries: lastValue,\n chartType: chartType\n };\n seriesDataPoints.push(highlightDataPoint);\n }\n }\n }\n return {\n series: columnSeries,\n hasHighlights: hasHighlights,\n hasDynamicSeries: hasDynamicSeries,\n isMultiMeasure: isMultiMeasure,\n };\n };\n ColumnChart.getDataPointColor = function (legendItem, categoryIndex, dataPointObjects) {\n debug.assertValue(legendItem, 'legendItem');\n debug.assertValue(categoryIndex, 'categoryIndex');\n debug.assertAnyValue(dataPointObjects, 'dataPointObjects');\n if (dataPointObjects) {\n var colorOverride = powerbi.DataViewObjects.getFillColor(dataPointObjects[categoryIndex], visuals.columnChartProps.dataPoint.fill);\n if (colorOverride)\n return colorOverride;\n }\n return legendItem.color;\n };\n ColumnChart.getStackedLabelColor = function (isNegative, seriesIndex, seriesCount, categoryIndex, rawValues) {\n var lastValue = !(isNegative && seriesIndex === seriesCount - 1 && seriesCount !== 1);\n //run for the next series and check if current series is last\n for (var i = seriesIndex + 1; i < seriesCount; i++) {\n var nextValues = visuals.AxisHelper.normalizeNonFiniteNumber(rawValues[i][categoryIndex]);\n if ((nextValues !== null) && (((!isNegative || (isNegative && seriesIndex === 0)) && nextValues > 0) || (isNegative && seriesIndex !== 0))) {\n lastValue = false;\n break;\n }\n }\n return lastValue;\n };\n ColumnChart.sliceSeries = function (series, endIndex, startIndex) {\n if (startIndex === void 0) { startIndex = 0; }\n var newSeries = [];\n if (series && series.length > 0) {\n for (var i = 0, len = series.length; i < len; i++) {\n var iNewSeries = newSeries[i] = powerbi.Prototype.inherit(series[i]);\n // TODO: [investigate] possible perf improvement.\n // if data[n].categoryIndex > endIndex implies data[n+1].categoryIndex > endIndex\n // then we could short circuit the filter loop.\n iNewSeries.data = series[i].data.filter(function (d) { return d.categoryIndex >= startIndex && d.categoryIndex < endIndex; });\n }\n }\n return newSeries;\n };\n ColumnChart.getInteractiveColumnChartDomElement = function (element) {\n return element.children(\"svg\").get(0);\n };\n ColumnChart.prototype.setData = function (dataViews) {\n debug.assertValue(dataViews, \"dataViews\");\n var is100PctStacked = ColumnChart.isStacked100(this.chartType);\n this.data = {\n categories: [],\n categoryFormatter: null,\n series: [],\n valuesMetadata: [],\n legendData: null,\n hasHighlights: false,\n categoryMetadata: null,\n scalarCategoryAxis: false,\n labelSettings: visuals.dataLabelUtils.getDefaultColumnLabelSettings(is100PctStacked || ColumnChart.isStacked(this.chartType)),\n axesLabels: { x: null, y: null },\n hasDynamicSeries: false,\n defaultDataPointColor: null,\n isMultiMeasure: false,\n };\n if (dataViews.length > 0) {\n var dataView = this.dataView = dataViews[0];\n if (dataView && dataView.categorical) {\n var dvCategories = dataView.categorical.categories;\n var categoryMetadata = (dvCategories && dvCategories.length > 0)\n ? dvCategories[0].source\n : null;\n var categoryType = visuals.AxisHelper.getCategoryValueType(categoryMetadata);\n this.data = ColumnChart.converter(dataView, this.cartesianVisualHost.getSharedColors(), is100PctStacked, visuals.CartesianChart.getIsScalar(dataView.metadata ? dataView.metadata.objects : null, visuals.columnChartProps.categoryAxis.axisType, categoryType), dataView.metadata, this.chartType, this.interactivityService, this.tooltipsEnabled);\n }\n }\n this.setChartStrategy();\n };\n ColumnChart.prototype.setChartStrategy = function () {\n switch (this.chartType) {\n case ColumnChartType.clusteredBar:\n this.columnChart = new visuals.ClusteredBarChartStrategy();\n break;\n case ColumnChartType.clusteredColumn:\n this.columnChart = new visuals.ClusteredColumnChartStrategy();\n break;\n case ColumnChartType.stackedBar:\n case ColumnChartType.hundredPercentStackedBar:\n this.columnChart = new visuals.StackedBarChartStrategy();\n break;\n case ColumnChartType.stackedColumn:\n case ColumnChartType.hundredPercentStackedColumn:\n default:\n this.columnChart = new visuals.StackedColumnChartStrategy();\n break;\n }\n // For single series, render stacked as a clustered\n if (ColumnChart.isStacked(this.chartType) && this.data.series.length === 1) {\n switch (this.chartType) {\n case (ColumnChartType.stackedBar):\n this.columnChart = new visuals.ClusteredBarChartStrategy();\n break;\n case (ColumnChartType.stackedColumn):\n this.columnChart = new visuals.ClusteredColumnChartStrategy();\n break;\n }\n }\n };\n ColumnChart.prototype.calculateLegend = function () {\n // if we're in interactive mode, return the interactive legend\n if (this.interactivity && this.interactivity.isInteractiveLegend) {\n return this.createInteractiveLegendDataPoints(0);\n }\n var legendData = this.data ? this.data.legendData : null;\n var legendDataPoints = legendData ? legendData.dataPoints : [];\n if (_.isEmpty(legendDataPoints))\n return null;\n return legendData;\n };\n ColumnChart.prototype.hasLegend = function () {\n return this.data && (this.data.hasDynamicSeries || (this.data.series && this.data.series.length > 1));\n };\n ColumnChart.prototype.enumerateObjectInstances = function (enumeration, options) {\n switch (options.objectName) {\n case 'dataPoint':\n if (this.dataView && !visuals.GradientUtils.hasGradientRole(this.dataView.categorical))\n this.enumerateDataPoints(enumeration);\n break;\n case 'labels':\n this.enumerateDataLabels(enumeration);\n break;\n }\n };\n ColumnChart.prototype.enumerateDataLabels = function (enumeration) {\n var data = this.data, labelSettings = this.data.labelSettings, seriesCount = data.series.length, showLabelPerSeries = !data.hasDynamicSeries && (seriesCount > 1 || !data.categoryMetadata);\n //Draw default settings\n visuals.dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings, null, showLabelPerSeries));\n if (seriesCount === 0)\n return;\n //Draw series settings\n if (showLabelPerSeries && labelSettings.showLabelPerSeries) {\n for (var i = 0; i < seriesCount; i++) {\n var series = data.series[i], labelSettings_1 = (series.labelSettings) ? series.labelSettings : this.data.labelSettings;\n enumeration.pushContainer({ displayName: series.displayName });\n visuals.dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings_1, series));\n enumeration.popContainer();\n }\n }\n };\n ColumnChart.prototype.getLabelSettingsOptions = function (enumeration, labelSettings, series, showAll) {\n return {\n enumeration: enumeration,\n dataLabelsSettings: labelSettings,\n show: true,\n displayUnits: !ColumnChart.isStacked100(this.chartType),\n precision: true,\n selector: series && series.identity ? series.identity.getSelector() : null,\n showAll: showAll,\n fontSize: true,\n };\n };\n ColumnChart.prototype.enumerateDataPoints = function (enumeration) {\n var data = this.data;\n if (!data)\n return;\n var seriesCount = data.series.length;\n if (seriesCount === 0)\n return;\n if (data.hasDynamicSeries || seriesCount > 1 || !data.categoryMetadata) {\n for (var i = 0; i < seriesCount; i++) {\n var series = data.series[i];\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: series.displayName,\n selector: visuals.ColorHelper.normalizeSelector(series.identity.getSelector()),\n properties: {\n fill: { solid: { color: series.color } }\n },\n });\n }\n }\n else {\n // For single-category, single-measure column charts, the user can color the individual bars.\n var singleSeriesData = data.series[0].data;\n var categoryFormatter = data.categoryFormatter;\n // Add default color and show all slices\n enumeration.pushInstance({\n objectName: 'dataPoint',\n selector: null,\n properties: {\n defaultColor: { solid: { color: data.defaultDataPointColor || this.colors.getColorByIndex(0).value } }\n }\n }).pushInstance({\n objectName: 'dataPoint',\n selector: null,\n properties: {\n showAllDataPoints: !!data.showAllDataPoints\n }\n });\n if (data.showAllDataPoints) {\n for (var i = 0; i < singleSeriesData.length; i++) {\n var singleSeriesDataPoints = singleSeriesData[i], categoryValue = data.categories[i];\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: categoryFormatter ? categoryFormatter.format(categoryValue) : categoryValue,\n selector: visuals.ColorHelper.normalizeSelector(singleSeriesDataPoints.identity.getSelector(), /*isSingleSeries*/ true),\n properties: {\n fill: { solid: { color: singleSeriesDataPoints.color } }\n },\n });\n }\n }\n }\n };\n ColumnChart.prototype.calculateAxesProperties = function (options) {\n var data = this.data;\n this.currentViewport = options.viewport;\n var margin = this.margin = options.margin;\n var origCatgSize = (data && data.categories) ? data.categories.length : 0;\n var chartLayout = data ? this.getCategoryLayout(origCatgSize, options) : {\n categoryCount: 0,\n categoryThickness: visuals.CartesianChart.MinOrdinalRectThickness,\n outerPaddingRatio: visuals.CartesianChart.OuterPaddingRatio,\n isScalar: false\n };\n this.categoryAxisType = chartLayout.isScalar ? visuals.axisType.scalar : null;\n if (data && !chartLayout.isScalar && !this.isScrollable && options.trimOrdinalDataOnOverflow) {\n // trim data that doesn't fit on dashboard\n var catgSize = Math.min(origCatgSize, chartLayout.categoryCount);\n if (catgSize !== origCatgSize) {\n data = powerbi.Prototype.inherit(data);\n data.series = ColumnChart.sliceSeries(data.series, catgSize);\n data.categories = data.categories.slice(0, catgSize);\n }\n }\n this.columnChart.setData(data);\n var preferredPlotArea = this.getPreferredPlotArea(chartLayout.isScalar, chartLayout.categoryCount, chartLayout.categoryThickness);\n var is100Pct = ColumnChart.isStacked100(this.chartType);\n var chartContext = {\n height: preferredPlotArea.height,\n width: preferredPlotArea.width,\n duration: 0,\n hostService: this.hostService,\n unclippedGraphicsContext: this.unclippedGraphicsContext,\n mainGraphicsContext: this.mainGraphicsContext,\n margin: this.margin,\n layout: chartLayout,\n animator: this.animator,\n interactivityService: this.interactivityService,\n viewportHeight: this.currentViewport.height - (margin.top + margin.bottom),\n viewportWidth: this.currentViewport.width - (margin.left + margin.right),\n is100Pct: is100Pct,\n isComboChart: this.isComboChart,\n };\n this.ApplyInteractivity(chartContext);\n this.columnChart.setupVisualProps(chartContext);\n var ensureXDomain;\n var ensureYDomain;\n var isBarChart = ColumnChart.isBar(this.chartType);\n if (isBarChart) {\n var temp = options.forcedXDomain;\n options.forcedXDomain = options.forcedYDomain;\n options.forcedYDomain = temp;\n // In the case of clustered and stacked bar charts, the y1 reference line is a vertical line\n ensureXDomain = options.ensureYDomain;\n }\n else {\n ensureYDomain = options.ensureYDomain;\n }\n this.xAxisProperties = this.columnChart.setXScale(is100Pct, options.forcedTickCount, options.forcedXDomain, isBarChart ? options.valueAxisScaleType : options.categoryAxisScaleType, isBarChart ? options.valueAxisDisplayUnits : options.categoryAxisDisplayUnits, isBarChart ? options.valueAxisPrecision : options.categoryAxisPrecision, ensureXDomain);\n this.yAxisProperties = this.columnChart.setYScale(is100Pct, options.forcedTickCount, options.forcedYDomain, isBarChart ? options.categoryAxisScaleType : options.valueAxisScaleType, isBarChart ? options.categoryAxisDisplayUnits : options.valueAxisDisplayUnits, isBarChart ? options.categoryAxisPrecision : options.valueAxisPrecision, ensureYDomain);\n if (options.showCategoryAxisLabel && this.xAxisProperties.isCategoryAxis || options.showValueAxisLabel && !this.xAxisProperties.isCategoryAxis) {\n this.xAxisProperties.axisLabel = data.axesLabels.x;\n }\n else {\n this.xAxisProperties.axisLabel = null;\n }\n if (options.showValueAxisLabel && !this.yAxisProperties.isCategoryAxis || options.showCategoryAxisLabel && this.yAxisProperties.isCategoryAxis) {\n this.yAxisProperties.axisLabel = data.axesLabels.y;\n }\n else {\n this.yAxisProperties.axisLabel = null;\n }\n return [this.xAxisProperties, this.yAxisProperties];\n };\n ColumnChart.prototype.getPreferredPlotArea = function (isScalar, categoryCount, categoryThickness) {\n var plotArea = {\n height: this.currentViewport.height - this.margin.top - this.margin.bottom,\n width: this.currentViewport.width - this.margin.left - this.margin.right\n };\n if (this.isScrollable && !isScalar) {\n var preferredCategorySpan = visuals.CartesianChart.getPreferredCategorySpan(categoryCount, categoryThickness);\n if (ColumnChart.isBar(this.chartType)) {\n plotArea.height = Math.max(preferredCategorySpan, plotArea.height);\n }\n else\n plotArea.width = Math.max(preferredCategorySpan, plotArea.width);\n }\n return plotArea;\n };\n ColumnChart.prototype.ApplyInteractivity = function (chartContext) {\n var _this = this;\n var interactivity = this.interactivity;\n if (interactivity) {\n if (interactivity.dragDataPoint) {\n chartContext.onDragStart = function (datum) {\n if (!datum.identity)\n return;\n _this.hostService.onDragStart({\n event: d3.event,\n data: {\n data: datum.identity.getSelector()\n }\n });\n };\n }\n if (interactivity.isInteractiveLegend) {\n var dragMove = function () {\n var mousePoint = d3.mouse(_this.mainGraphicsContext[0][0]); // get the x and y for the column area itself\n var x = mousePoint[0];\n var y = mousePoint[1];\n var index = _this.columnChart.getClosestColumnIndex(x, y);\n _this.selectColumn(index);\n };\n var ColumnChartSvg = ColumnChart.getInteractiveColumnChartDomElement(this.element);\n //set click interaction on the visual\n this.svg.on('click', dragMove);\n //set click interaction on the background\n d3.select(ColumnChartSvg)\n .on('click', dragMove)\n .style('touch-action', 'none');\n var drag = d3.behavior.drag()\n .origin(Object)\n .on(\"drag\", dragMove);\n //set drag interaction on the visual\n this.svg.call(drag);\n //set drag interaction on the background\n d3.select(ColumnChartSvg).call(drag);\n }\n }\n };\n ColumnChart.prototype.selectColumn = function (indexOfColumnSelected, force) {\n if (force === void 0) { force = false; }\n if (!force && this.lastInteractiveSelectedColumnIndex === indexOfColumnSelected)\n return; // same column, nothing to do here\n var legendData = this.createInteractiveLegendDataPoints(indexOfColumnSelected);\n var legendDataPoints = legendData.dataPoints;\n this.cartesianVisualHost.updateLegend(legendData);\n if (legendDataPoints.length > 0) {\n this.columnChart.selectColumn(indexOfColumnSelected, this.lastInteractiveSelectedColumnIndex);\n }\n this.lastInteractiveSelectedColumnIndex = indexOfColumnSelected;\n };\n ColumnChart.prototype.createInteractiveLegendDataPoints = function (columnIndex) {\n var data = this.data;\n if (!data || _.isEmpty(data.series))\n return { dataPoints: [] };\n var formatStringProp = visuals.columnChartProps.general.formatString;\n var legendDataPoints = [];\n var category = data.categories && data.categories[columnIndex];\n var allSeries = data.series;\n var dataPoints = data.legendData && data.legendData.dataPoints;\n var converterStrategy = new ColumnChartConverterHelper(this.dataView);\n for (var i = 0, len = allSeries.length; i < len; i++) {\n var measure = converterStrategy.getValueBySeriesAndCategory(i, columnIndex);\n var valueMetadata = data.valuesMetadata[i];\n var formattedLabel = visuals.converterHelper.getFormattedLegendLabel(valueMetadata, this.dataView.categorical.values, formatStringProp);\n var dataPointColor = void 0;\n if (allSeries.length === 1) {\n var series = allSeries[0];\n dataPointColor = series.data.length > columnIndex && series.data[columnIndex].color;\n }\n else {\n dataPointColor = dataPoints.length > i && dataPoints[i].color;\n }\n legendDataPoints.push({\n color: dataPointColor,\n icon: visuals.LegendIcon.Box,\n label: formattedLabel,\n category: data.categoryFormatter ? data.categoryFormatter.format(category) : category,\n measure: visuals.valueFormatter.format(measure, visuals.valueFormatter.getFormatString(valueMetadata, formatStringProp)),\n identity: visuals.SelectionId.createNull(),\n selected: false\n });\n }\n return { dataPoints: legendDataPoints };\n };\n ColumnChart.prototype.overrideXScale = function (xProperties) {\n this.xAxisProperties = xProperties;\n };\n ColumnChart.prototype.render = function (suppressAnimations) {\n var columnChartDrawInfo = this.columnChart.drawColumns(!suppressAnimations /* useAnimations */);\n var data = this.data;\n var margin = this.margin;\n var viewport = this.currentViewport;\n var height = viewport.height - (margin.top + margin.bottom);\n var width = viewport.width - (margin.left + margin.right);\n this.mainGraphicsContext\n .attr('height', height)\n .attr('width', width);\n if (this.tooltipsEnabled)\n visuals.TooltipManager.addTooltip(columnChartDrawInfo.eventGroup, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n var allDataPoints = [];\n var behaviorOptions = undefined;\n if (this.interactivityService) {\n for (var i = 0, ilen = data.series.length; i < ilen; i++) {\n allDataPoints = allDataPoints.concat(data.series[i].data);\n }\n behaviorOptions = {\n datapoints: allDataPoints,\n eventGroup: columnChartDrawInfo.eventGroup,\n bars: columnChartDrawInfo.shapesSelection,\n hasHighlights: data.hasHighlights,\n mainGraphicsContext: this.mainGraphicsContext,\n viewport: columnChartDrawInfo.viewport,\n axisOptions: columnChartDrawInfo.axisOptions,\n showLabel: data.labelSettings.show\n };\n }\n if (this.interactivity && this.interactivity.isInteractiveLegend) {\n if (this.data.series.length > 0) {\n this.selectColumn(visuals.CartesianHelper.findMaxCategoryIndex(this.data.series), true); // start with the last column\n }\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n return { dataPoints: allDataPoints, behaviorOptions: behaviorOptions, labelDataPoints: columnChartDrawInfo.labelDataPoints, labelsAreNumeric: true };\n };\n ColumnChart.prototype.onClearSelection = function () {\n if (this.interactivityService) {\n this.interactivityService.clearSelection();\n }\n };\n ColumnChart.prototype.getVisualCategoryAxisIsScalar = function () {\n return this.data ? this.data.scalarCategoryAxis : false;\n };\n ColumnChart.prototype.getSupportedCategoryAxisType = function () {\n var metaDataColumn = this.data ? this.data.categoryMetadata : undefined;\n var valueType = visuals.AxisHelper.getCategoryValueType(metaDataColumn);\n var isOrdinal = visuals.AxisHelper.isOrdinal(valueType);\n return isOrdinal ? visuals.axisType.categorical : visuals.axisType.both;\n };\n ColumnChart.prototype.setFilteredData = function (startIndex, endIndex) {\n var data = powerbi.Prototype.inherit(this.data);\n data.series = ColumnChart.sliceSeries(data.series, endIndex, startIndex);\n data.categories = data.categories.slice(startIndex, endIndex);\n this.columnChart.setData(data);\n return data;\n };\n ColumnChart.getLabelFill = function (labelColor, isInside, isCombo) {\n if (labelColor) {\n return labelColor;\n }\n if (isInside && !isCombo) {\n return visuals.NewDataLabelUtils.defaultInsideLabelColor;\n }\n return visuals.NewDataLabelUtils.defaultLabelColor;\n };\n ColumnChart.prototype.supportsTrendLine = function () {\n var isScalar = this.data ? this.data.scalarCategoryAxis : false;\n return this.chartType === ColumnChartType.clusteredColumn && isScalar;\n };\n ColumnChart.isBar = function (chartType) {\n return EnumExtensions.hasFlag(chartType, flagBar);\n };\n ColumnChart.isColumn = function (chartType) {\n return EnumExtensions.hasFlag(chartType, flagColumn);\n };\n ColumnChart.isClustered = function (chartType) {\n return EnumExtensions.hasFlag(chartType, flagClustered);\n };\n ColumnChart.isStacked = function (chartType) {\n return EnumExtensions.hasFlag(chartType, flagStacked);\n };\n ColumnChart.isStacked100 = function (chartType) {\n return EnumExtensions.hasFlag(chartType, flagStacked100);\n };\n ColumnChart.ColumnChartClassName = 'columnChart';\n ColumnChart.clusteredValidLabelPositions = [16 /* OutsideEnd */, 4 /* InsideEnd */, 1 /* InsideCenter */, 2 /* InsideBase */];\n ColumnChart.stackedValidLabelPositions = [1 /* InsideCenter */, 4 /* InsideEnd */, 2 /* InsideBase */];\n ColumnChart.SeriesClasses = jsCommon.CssConstants.createClassAndSelector('series');\n return ColumnChart;\n }());\n visuals.ColumnChart = ColumnChart;\n var ColumnChartConverterHelper = (function () {\n function ColumnChartConverterHelper(dataView) {\n this.dataView = dataView && dataView.categorical;\n this.reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n }\n ColumnChartConverterHelper.prototype.getLegend = function (colors, defaultLegendLabelColor, defaultColor) {\n var legend = [];\n var seriesSources = [];\n var seriesObjects = [];\n var grouped = false;\n var colorHelper = new visuals.ColorHelper(colors, visuals.columnChartProps.dataPoint.fill, defaultColor);\n var legendTitle = undefined;\n if (this.dataView && this.dataView.values) {\n var allValues = this.dataView.values;\n var valueGroups = allValues.grouped();\n var hasDynamicSeries = !!(allValues && allValues.source);\n var formatStringProp = visuals.columnChartProps.general.formatString;\n for (var valueGroupsIndex = 0, valueGroupsLen = valueGroups.length; valueGroupsIndex < valueGroupsLen; valueGroupsIndex++) {\n var valueGroup = valueGroups[valueGroupsIndex], valueGroupObjects = valueGroup.objects, values = valueGroup.values;\n for (var valueIndex = 0, valuesLen = values.length; valueIndex < valuesLen; valueIndex++) {\n var series = values[valueIndex];\n var source = series.source;\n // Gradient measures do not create series.\n if (DataRoleHelper.hasRole(source, 'Gradient') && !DataRoleHelper.hasRole(source, 'Y'))\n continue;\n seriesSources.push(source);\n seriesObjects.push(series.objects);\n var selectionId = series.identity ?\n visuals.SelectionId.createWithIdAndMeasure(series.identity, source.queryName) :\n visuals.SelectionId.createWithMeasure(this.getMeasureNameByIndex(valueIndex));\n var label = visuals.converterHelper.getFormattedLegendLabel(source, allValues, formatStringProp);\n var color = hasDynamicSeries\n ? colorHelper.getColorForSeriesValue(valueGroupObjects, allValues.identityFields, source.groupName)\n : colorHelper.getColorForMeasure(source.objects, source.queryName);\n legend.push({\n icon: visuals.LegendIcon.Box,\n color: color,\n label: label,\n identity: selectionId,\n selected: false,\n });\n if (series.identity && source.groupName !== undefined) {\n grouped = true;\n }\n }\n }\n var dvValues = this.dataView.values;\n legendTitle = dvValues && dvValues.source ? dvValues.source.displayName : \"\";\n }\n var legendData = {\n title: legendTitle,\n dataPoints: legend,\n grouped: grouped,\n labelColor: defaultLegendLabelColor,\n };\n return {\n legend: legendData,\n seriesSources: seriesSources,\n seriesObjects: seriesObjects,\n };\n };\n ColumnChartConverterHelper.prototype.getValueBySeriesAndCategory = function (series, category) {\n if (this.reader.hasDynamicSeries()) {\n // Combo chart dynamic series is broken when line and column have the same measure, so for now,\n // work around this by using the grouped directly instead of relying on the reader and roles\n var grouped = this.dataView.values.grouped();\n return grouped[series].values[0].values[category];\n }\n return this.reader.getValue('Y', category, series);\n };\n ColumnChartConverterHelper.prototype.getMeasureNameByIndex = function (index) {\n return this.dataView.values[index].source.queryName;\n };\n ColumnChartConverterHelper.prototype.hasHighlightValues = function (series) {\n var column = this.dataView && this.dataView.values ? this.dataView.values[series] : undefined;\n return column && !!column.highlights;\n };\n ColumnChartConverterHelper.prototype.getHighlightBySeriesAndCategory = function (series, category) {\n return this.dataView.values[series].highlights[category];\n };\n return ColumnChartConverterHelper;\n }());\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var PixelConverter = jsCommon.PixelConverter;\n var ClusteredColumnChartStrategy = (function () {\n function ClusteredColumnChartStrategy() {\n }\n ClusteredColumnChartStrategy.prototype.setupVisualProps = function (columnChartProps) {\n this.graphicsContext = columnChartProps;\n this.margin = columnChartProps.margin;\n this.width = this.graphicsContext.width;\n this.height = this.graphicsContext.height;\n this.categoryLayout = columnChartProps.layout;\n this.animator = columnChartProps.animator;\n this.interactivityService = columnChartProps.interactivityService;\n this.viewportHeight = columnChartProps.viewportHeight;\n this.viewportWidth = columnChartProps.viewportWidth;\n this.isComboChart = columnChartProps.isComboChart;\n };\n ClusteredColumnChartStrategy.prototype.setData = function (data) {\n this.data = data;\n };\n ClusteredColumnChartStrategy.prototype.setXScale = function (is100Pct, forcedTickCount, forcedXDomain, axisScaleType, axisDisplayUnits, axisPrecision, ensureXDomain) {\n var width = this.width;\n var forcedXMin, forcedXMax;\n if (forcedXDomain && forcedXDomain.length === 2) {\n forcedXMin = forcedXDomain[0];\n forcedXMax = forcedXDomain[1];\n }\n var props = this.xProps = visuals.ColumnUtil.getCategoryAxis(this.data, width, this.categoryLayout, false, forcedXMin, forcedXMax, axisScaleType, axisDisplayUnits, axisPrecision, ensureXDomain);\n // create clustered offset scale\n var seriesLength = this.data.series.length;\n var columnWidth = (this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio)) / seriesLength;\n this.seriesOffsetScale = d3.scale.ordinal()\n .domain(this.data.series.map(function (s) { return s.index; }))\n .rangeBands([0, seriesLength * columnWidth]);\n return props;\n };\n ClusteredColumnChartStrategy.prototype.setYScale = function (is100Pct, forcedTickCount, forcedYDomain, axisScaleType, axisDisplayUnits, axisPrecision, ensureYDomain) {\n debug.assert(!is100Pct, 'Cannot have 100% clustered chart.');\n var height = this.viewportHeight;\n var valueDomain = visuals.AxisHelper.createValueDomain(this.data.series, true) || visuals.emptyDomain;\n var combinedDomain = visuals.AxisHelper.combineDomain(forcedYDomain, valueDomain, ensureYDomain);\n var shouldClamp = visuals.AxisHelper.scaleShouldClamp(combinedDomain, valueDomain);\n this.yProps = visuals.AxisHelper.createAxis({\n pixelSpan: height,\n dataDomain: combinedDomain,\n metaDataColumn: this.data.valuesMetadata[0],\n formatString: visuals.valueFormatter.getFormatString(this.data.valuesMetadata[0], visuals.columnChartProps.general.formatString),\n outerPadding: 0,\n isScalar: true,\n isVertical: true,\n forcedTickCount: forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false,\n scaleType: axisScaleType,\n axisDisplayUnits: axisDisplayUnits,\n axisPrecision: axisPrecision,\n shouldClamp: shouldClamp,\n });\n return this.yProps;\n };\n ClusteredColumnChartStrategy.prototype.drawColumns = function (useAnimation) {\n var data = this.data;\n debug.assertValue(data, 'data could not be null or undefined');\n this.columnsCenters = null; // invalidate the columnsCenters so that will be calculated again\n var categoryWidth = (this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio));\n var columnWidth = categoryWidth / data.series.length;\n var axisOptions = {\n columnWidth: columnWidth,\n categoryWidth: categoryWidth,\n xScale: this.xProps.scale,\n yScale: this.yProps.scale,\n seriesOffsetScale: this.seriesOffsetScale,\n isScalar: this.categoryLayout.isScalar,\n margin: this.margin,\n };\n var clusteredColumnLayout = this.layout = ClusteredColumnChartStrategy.getLayout(data, axisOptions);\n var dataLabelSettings = data.labelSettings;\n var labelDataPoints = [];\n if (dataLabelSettings && dataLabelSettings.show) {\n labelDataPoints = this.createLabelDataPoints();\n }\n var result;\n var shapes;\n var series = visuals.ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\n if (this.animator && useAnimation) {\n result = this.animator.animate({\n viewModel: data,\n series: series,\n layout: clusteredColumnLayout,\n itemCS: ClusteredColumnChartStrategy.classes.item,\n interactivityService: this.interactivityService,\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\n viewPort: { height: this.height, width: this.width }\n });\n shapes = result.shapes;\n }\n if (!this.animator || !useAnimation || result.failed) {\n shapes = visuals.ColumnUtil.drawDefaultShapes(data, series, clusteredColumnLayout, ClusteredColumnChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\n }\n visuals.ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\n return {\n eventGroup: this.graphicsContext.mainGraphicsContext,\n shapesSelection: shapes,\n viewport: { height: this.height, width: this.width },\n axisOptions: axisOptions,\n labelDataPoints: labelDataPoints,\n };\n };\n ClusteredColumnChartStrategy.prototype.selectColumn = function (selectedColumnIndex, lastSelectedColumnIndex) {\n visuals.ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, ClusteredColumnChartStrategy.classes.item.selector, selectedColumnIndex, lastSelectedColumnIndex);\n this.moveHandle(selectedColumnIndex);\n };\n ClusteredColumnChartStrategy.prototype.getClosestColumnIndex = function (x, y) {\n return visuals.ColumnUtil.getClosestColumnIndex(x, this.getColumnsCenters());\n };\n /**\n * Get the chart's columns centers (x value).\n */\n ClusteredColumnChartStrategy.prototype.getColumnsCenters = function () {\n var _this = this;\n if (!this.columnsCenters) {\n var categoryWidth = this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio);\n // use the axis scale and first series data to get category centers\n if (this.data.series.length > 0) {\n var xScaleOffset_1 = 0;\n if (!this.categoryLayout.isScalar)\n xScaleOffset_1 = categoryWidth / 2;\n var firstSeries = this.data.series[0];\n this.columnsCenters = firstSeries.data.map(function (d) { return _this.xProps.scale(_this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + xScaleOffset_1; });\n }\n }\n return this.columnsCenters;\n };\n ClusteredColumnChartStrategy.prototype.moveHandle = function (selectedColumnIndex) {\n var columnCenters = this.getColumnsCenters();\n var x = columnCenters[selectedColumnIndex];\n var hoverLine = d3.select('.interactive-hover-line');\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\n }\n if (!this.columnSelectionLineHandle) {\n var handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\n handle.append('line')\n .classed('interactive-hover-line', true)\n .attr({\n x1: x,\n x2: x,\n y1: 0,\n y2: this.height,\n });\n handle.append('circle')\n .attr({\n cx: x,\n cy: this.height,\n r: '6px',\n })\n .classed('drag-handle', true);\n }\n else {\n var handle = this.columnSelectionLineHandle;\n handle.select('line').attr({ x1: x, x2: x });\n handle.select('circle').attr({ cx: x });\n }\n };\n ClusteredColumnChartStrategy.getLayout = function (data, axisOptions) {\n var columnWidth = axisOptions.columnWidth;\n var halfColumnWidth = 0.5 * columnWidth;\n var quarterColumnWidth = halfColumnWidth / 2;\n var isScalar = axisOptions.isScalar;\n var xScale = axisOptions.xScale;\n var yScale = axisOptions.yScale;\n var seriesOffsetScale = axisOptions.seriesOffsetScale;\n var scaledY0 = yScale(0);\n var xScaleOffset = 0;\n if (isScalar)\n xScaleOffset = axisOptions.categoryWidth / 2;\n return {\n shapeLayout: {\n width: function (d) { return d.drawThinner ? halfColumnWidth : columnWidth; },\n x: function (d) { return xScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - xScaleOffset + (d.drawThinner ? quarterColumnWidth : 0); },\n y: function (d) { return scaledY0 + visuals.AxisHelper.diffScaled(yScale, Math.max(0, d.value), 0); },\n height: function (d) { return Math.abs(visuals.AxisHelper.diffScaled(yScale, 0, d.value)); },\n },\n shapeLayoutWithoutHighlights: {\n width: function (d) { return columnWidth; },\n x: function (d) { return xScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - xScaleOffset; },\n y: function (d) { return scaledY0 + visuals.AxisHelper.diffScaled(yScale, Math.max(0, d.originalValue), 0); },\n height: function (d) { return Math.abs(visuals.AxisHelper.diffScaled(yScale, 0, d.originalValue)); },\n },\n zeroShapeLayout: {\n width: function (d) { return d.drawThinner ? halfColumnWidth : columnWidth; },\n x: function (d) { return xScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - xScaleOffset + (d.drawThinner ? quarterColumnWidth : 0); },\n y: function (d) { return scaledY0; },\n height: function (d) { return 0; },\n },\n };\n };\n ClusteredColumnChartStrategy.prototype.createLabelDataPoints = function () {\n var labelDataPoints = [];\n var data = this.data;\n var series = data.series;\n var formattersCache = visuals.NewDataLabelUtils.createColumnFormatterCacheManager();\n var shapeLayout = this.layout.shapeLayout;\n for (var _i = 0, series_2 = series; _i < series_2.length; _i++) {\n var currentSeries = series_2[_i];\n var labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\n if (!labelSettings.show)\n continue;\n var axisFormatter = visuals.NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\n for (var _a = 0, _b = currentSeries.data; _a < _b.length; _a++) {\n var dataPoint = _b[_a];\n if ((data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\n continue;\n }\n // Calculate parent rectangle\n var parentRect = {\n left: shapeLayout.x(dataPoint),\n top: shapeLayout.y(dataPoint),\n width: shapeLayout.width(dataPoint),\n height: shapeLayout.height(dataPoint),\n };\n // Calculate label text\n var formatString = dataPoint.labelFormatString;\n var formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\n var text = visuals.NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\n // Calculate text size\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\n labelDataPoints.push({\n isPreferred: true,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\n insideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\n parentType: 1 /* Rectangle */,\n parentShape: {\n rect: parentRect,\n orientation: dataPoint.value >= 0 ? 1 /* VerticalBottomBased */ : 2 /* VerticalTopBased */,\n validPositions: visuals.ColumnChart.clusteredValidLabelPositions,\n },\n identity: dataPoint.identity,\n fontSize: labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt,\n });\n }\n }\n return labelDataPoints;\n };\n ClusteredColumnChartStrategy.classes = {\n item: {\n class: 'column',\n selector: '.column',\n },\n };\n return ClusteredColumnChartStrategy;\n }());\n visuals.ClusteredColumnChartStrategy = ClusteredColumnChartStrategy;\n var ClusteredBarChartStrategy = (function () {\n function ClusteredBarChartStrategy() {\n }\n ClusteredBarChartStrategy.prototype.setupVisualProps = function (barChartProps) {\n this.graphicsContext = barChartProps;\n this.margin = barChartProps.margin;\n this.width = this.graphicsContext.width;\n this.height = this.graphicsContext.height;\n this.categoryLayout = barChartProps.layout;\n this.animator = barChartProps.animator;\n this.interactivityService = barChartProps.interactivityService;\n this.viewportHeight = barChartProps.viewportHeight;\n this.viewportWidth = barChartProps.viewportWidth;\n this.isComboChart = barChartProps.isComboChart;\n };\n ClusteredBarChartStrategy.prototype.setData = function (data) {\n this.data = data;\n };\n ClusteredBarChartStrategy.prototype.setYScale = function (is100Pct, forcedTickCount, forcedYDomain, axisScaleType, axisDisplayUnits, axisPrecision, ensureYDomain) {\n var height = this.height;\n var forcedYMin, forcedYMax;\n if (forcedYDomain && forcedYDomain.length === 2) {\n forcedYMin = forcedYDomain[0];\n forcedYMax = forcedYDomain[1];\n }\n var props = this.yProps = visuals.ColumnUtil.getCategoryAxis(this.data, height, this.categoryLayout, true, forcedYMin, forcedYMax, axisScaleType, axisDisplayUnits, axisPrecision, ensureYDomain);\n // create clustered offset scale\n var seriesLength = this.data.series.length;\n var columnWidth = (this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio)) / seriesLength;\n this.seriesOffsetScale = d3.scale.ordinal()\n .domain(this.data.series.map(function (s) { return s.index; }))\n .rangeBands([0, seriesLength * columnWidth]);\n return props;\n };\n ClusteredBarChartStrategy.prototype.setXScale = function (is100Pct, forcedTickCount, forcedXDomain, axisScaleType, axisDisplayUnits, axisPrecision, ensureXDomain) {\n debug.assert(!is100Pct, 'Cannot have 100% clustered chart.');\n debug.assert(forcedTickCount === undefined, 'Cannot have clustered bar chart as combo chart.');\n var width = this.width;\n var valueDomain = visuals.AxisHelper.createValueDomain(this.data.series, true) || visuals.emptyDomain;\n var combinedDomain = visuals.AxisHelper.combineDomain(forcedXDomain, valueDomain, ensureXDomain);\n var shouldClamp = visuals.AxisHelper.scaleShouldClamp(combinedDomain, valueDomain);\n this.xProps = visuals.AxisHelper.createAxis({\n pixelSpan: width,\n dataDomain: combinedDomain,\n metaDataColumn: this.data.valuesMetadata[0],\n formatString: visuals.valueFormatter.getFormatString(this.data.valuesMetadata[0], visuals.columnChartProps.general.formatString),\n outerPadding: 0,\n isScalar: true,\n isVertical: false,\n forcedTickCount: forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false,\n scaleType: axisScaleType,\n axisDisplayUnits: axisDisplayUnits,\n axisPrecision: axisPrecision,\n shouldClamp: shouldClamp,\n });\n this.xProps.axis.tickSize(-this.viewportHeight, 0);\n return this.xProps;\n };\n ClusteredBarChartStrategy.prototype.drawColumns = function (useAnimation) {\n var data = this.data;\n debug.assertValue(data, 'data could not be null or undefined');\n this.barsCenters = null; // invalidate the columnsCenters so that will be calculated again\n var categoryWidth = (this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio));\n var columnWidth = categoryWidth / data.series.length;\n var axisOptions = {\n columnWidth: columnWidth,\n categoryWidth: categoryWidth,\n xScale: this.xProps.scale,\n yScale: this.yProps.scale,\n seriesOffsetScale: this.seriesOffsetScale,\n isScalar: this.categoryLayout.isScalar,\n margin: this.margin,\n };\n var clusteredBarLayout = this.layout = ClusteredBarChartStrategy.getLayout(data, axisOptions);\n var dataLabelSettings = data.labelSettings;\n var labelDataPoints = [];\n if (dataLabelSettings && dataLabelSettings.show) {\n labelDataPoints = this.createLabelDataPoints();\n }\n var result;\n var shapes;\n var series = visuals.ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\n if (this.animator && useAnimation) {\n result = this.animator.animate({\n viewModel: data,\n series: series,\n layout: clusteredBarLayout,\n itemCS: ClusteredBarChartStrategy.classes.item,\n interactivityService: this.interactivityService,\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\n viewPort: { height: this.height, width: this.width }\n });\n shapes = result.shapes;\n }\n if (!this.animator || !useAnimation || result.failed) {\n shapes = visuals.ColumnUtil.drawDefaultShapes(data, series, clusteredBarLayout, ClusteredBarChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\n }\n visuals.ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\n return {\n eventGroup: this.graphicsContext.mainGraphicsContext,\n shapesSelection: shapes,\n viewport: { height: this.height, width: this.width },\n axisOptions: axisOptions,\n labelDataPoints: labelDataPoints,\n };\n };\n ClusteredBarChartStrategy.prototype.selectColumn = function (selectedColumnIndex, lastSelectedColumnIndex) {\n visuals.ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, ClusteredBarChartStrategy.classes.item.selector, selectedColumnIndex, lastSelectedColumnIndex);\n this.moveHandle(selectedColumnIndex);\n };\n ClusteredBarChartStrategy.prototype.getClosestColumnIndex = function (x, y) {\n return visuals.ColumnUtil.getClosestColumnIndex(y, this.getBarsCenters());\n };\n /**\n * Get the chart's columns centers (y value).\n */\n ClusteredBarChartStrategy.prototype.getBarsCenters = function () {\n var _this = this;\n if (!this.barsCenters) {\n var barWidth = this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio);\n // use the axis scale and first series data to get category centers\n if (this.data.series.length > 0) {\n var yScaleOffset_1 = 0;\n if (!this.categoryLayout.isScalar)\n yScaleOffset_1 = barWidth / 2;\n var firstSeries = this.data.series[0];\n this.barsCenters = firstSeries.data.map(function (d) { return _this.yProps.scale(_this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + yScaleOffset_1; });\n }\n }\n return this.barsCenters;\n };\n ClusteredBarChartStrategy.prototype.moveHandle = function (selectedColumnIndex) {\n var barCenters = this.getBarsCenters();\n var y = barCenters[selectedColumnIndex];\n var hoverLine = d3.select('.interactive-hover-line');\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\n }\n if (!this.columnSelectionLineHandle) {\n var handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\n handle.append('line')\n .classed('interactive-hover-line', true)\n .attr({\n x1: 0,\n x2: this.width,\n y1: y,\n y2: y,\n });\n handle.append('circle')\n .attr({\n cx: 0,\n cy: y,\n r: '6px',\n })\n .classed('drag-handle', true);\n }\n else {\n var handle = this.columnSelectionLineHandle;\n handle.select('line').attr({ y1: y, y2: y });\n handle.select('circle').attr({ cy: y });\n }\n };\n ClusteredBarChartStrategy.getLayout = function (data, axisOptions) {\n var columnWidth = axisOptions.columnWidth;\n var halfColumnWidth = 0.5 * columnWidth;\n var quarterColumnWidth = halfColumnWidth / 2;\n var isScalar = axisOptions.isScalar;\n var xScale = axisOptions.xScale;\n var yScale = axisOptions.yScale;\n var seriesOffsetScale = axisOptions.seriesOffsetScale;\n var scaledX0 = xScale(0);\n var yScaleOffset = 0;\n if (isScalar)\n yScaleOffset = axisOptions.categoryWidth / 2;\n return {\n shapeLayout: {\n width: function (d) { return Math.abs(visuals.AxisHelper.diffScaled(xScale, 0, d.value)); },\n x: function (d) { return scaledX0 + visuals.AxisHelper.diffScaled(xScale, Math.min(0, d.value), 0); },\n y: function (d) { return yScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - yScaleOffset + (d.drawThinner ? quarterColumnWidth : 0); },\n height: function (d) { return d.drawThinner ? halfColumnWidth : columnWidth; },\n },\n shapeLayoutWithoutHighlights: {\n width: function (d) { return Math.abs(visuals.AxisHelper.diffScaled(xScale, 0, d.originalValue)); },\n x: function (d) { return scaledX0 + visuals.AxisHelper.diffScaled(xScale, Math.min(0, d.originalValue), 0); },\n y: function (d) { return yScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - yScaleOffset; },\n height: function (d) { return columnWidth; },\n },\n zeroShapeLayout: {\n width: function (d) { return 0; },\n x: function (d) { return scaledX0 + visuals.AxisHelper.diffScaled(xScale, Math.min(0, d.value), 0); },\n y: function (d) { return yScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - yScaleOffset + (d.drawThinner ? quarterColumnWidth : 0); },\n height: function (d) { return d.drawThinner ? halfColumnWidth : columnWidth; },\n },\n };\n };\n ClusteredBarChartStrategy.prototype.createLabelDataPoints = function () {\n var labelDataPoints = [];\n var data = this.data;\n var series = data.series;\n var formattersCache = visuals.NewDataLabelUtils.createColumnFormatterCacheManager();\n var shapeLayout = this.layout.shapeLayout;\n for (var _i = 0, series_3 = series; _i < series_3.length; _i++) {\n var currentSeries = series_3[_i];\n var labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\n if (!labelSettings.show)\n continue;\n var axisFormatter = visuals.NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\n for (var _a = 0, _b = currentSeries.data; _a < _b.length; _a++) {\n var dataPoint = _b[_a];\n if ((this.interactivityService && this.interactivityService.hasSelection() && !dataPoint.selected) || (data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\n continue;\n }\n // Calculate label text\n var formatString = dataPoint.labelFormatString;\n var formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\n var text = visuals.NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\n // Calculate text size\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\n // Calculate parent rectangle\n var parentRect = {\n left: shapeLayout.x(dataPoint),\n top: shapeLayout.y(dataPoint),\n width: shapeLayout.width(dataPoint),\n height: shapeLayout.height(dataPoint),\n };\n labelDataPoints.push({\n isPreferred: true,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\n insideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\n parentType: 1 /* Rectangle */,\n parentShape: {\n rect: parentRect,\n orientation: dataPoint.value >= 0 ? 3 /* HorizontalLeftBased */ : 4 /* HorizontalRightBased */,\n validPositions: visuals.ColumnChart.clusteredValidLabelPositions,\n },\n identity: dataPoint.identity,\n fontSize: labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt,\n });\n }\n }\n return labelDataPoints;\n };\n ClusteredBarChartStrategy.classes = {\n item: {\n class: 'bar',\n selector: '.bar'\n },\n };\n return ClusteredBarChartStrategy;\n }());\n visuals.ClusteredBarChartStrategy = ClusteredBarChartStrategy;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var PixelConverter = jsCommon.PixelConverter;\n var StackedColumnChartStrategy = (function () {\n function StackedColumnChartStrategy() {\n }\n StackedColumnChartStrategy.prototype.setupVisualProps = function (columnChartProps) {\n this.graphicsContext = columnChartProps;\n this.margin = columnChartProps.margin;\n this.width = this.graphicsContext.width;\n this.height = this.graphicsContext.height;\n this.categoryLayout = columnChartProps.layout;\n this.animator = columnChartProps.animator;\n this.interactivityService = columnChartProps.interactivityService;\n this.viewportHeight = columnChartProps.viewportHeight;\n this.viewportWidth = columnChartProps.viewportWidth;\n this.isComboChart = columnChartProps.isComboChart;\n };\n StackedColumnChartStrategy.prototype.setData = function (data) {\n this.data = data;\n };\n StackedColumnChartStrategy.prototype.setXScale = function (is100Pct, forcedTickCount, forcedXDomain, axisScaleType, axisDisplayUnits, axisPrecision, xReferenceLineValue) {\n var width = this.width;\n var forcedXMin, forcedXMax;\n if (forcedXDomain && forcedXDomain.length === 2) {\n forcedXMin = forcedXDomain[0];\n forcedXMax = forcedXDomain[1];\n }\n var props = this.xProps = visuals.ColumnUtil.getCategoryAxis(this.data, width, this.categoryLayout, false, forcedXMin, forcedXMax, axisScaleType, axisDisplayUnits, axisPrecision, xReferenceLineValue);\n return props;\n };\n StackedColumnChartStrategy.prototype.setYScale = function (is100Pct, forcedTickCount, forcedYDomain, axisScaleType, axisDisplayUnits, axisPrecision, y1ReferenceLineValue) {\n var height = this.viewportHeight;\n var valueDomain = visuals.StackedUtil.calcValueDomain(this.data.series, is100Pct);\n var valueDomainArr = [valueDomain.min, valueDomain.max];\n var combinedDomain = visuals.AxisHelper.combineDomain(forcedYDomain, valueDomainArr, y1ReferenceLineValue);\n var shouldClamp = visuals.AxisHelper.scaleShouldClamp(combinedDomain, valueDomainArr);\n var metadataColumn = this.data.valuesMetadata[0];\n var formatString = is100Pct ?\n this.graphicsContext.hostService.getLocalizedString('Percentage')\n : visuals.valueFormatter.getFormatString(metadataColumn, visuals.columnChartProps.general.formatString);\n this.yProps = visuals.AxisHelper.createAxis({\n pixelSpan: height,\n dataDomain: combinedDomain,\n metaDataColumn: metadataColumn,\n formatString: formatString,\n outerPadding: 0,\n isScalar: true,\n isVertical: true,\n forcedTickCount: forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false,\n scaleType: axisScaleType,\n axisDisplayUnits: axisDisplayUnits,\n axisPrecision: axisPrecision,\n is100Pct: is100Pct,\n shouldClamp: shouldClamp,\n });\n return this.yProps;\n };\n StackedColumnChartStrategy.prototype.drawColumns = function (useAnimation) {\n var data = this.data;\n debug.assertValue(data, 'data should not be null or undefined');\n this.columnsCenters = null; // invalidate the columnsCenters so that will be calculated again\n var axisOptions = {\n columnWidth: this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio),\n xScale: this.xProps.scale,\n yScale: this.yProps.scale,\n isScalar: this.categoryLayout.isScalar,\n margin: this.margin,\n };\n var stackedColumnLayout = this.layout = StackedColumnChartStrategy.getLayout(data, axisOptions);\n var dataLabelSettings = data.labelSettings;\n var labelDataPoints = [];\n if (dataLabelSettings && dataLabelSettings.show) {\n labelDataPoints = this.createLabelDataPoints();\n }\n var result;\n var shapes;\n var series = visuals.ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\n if (this.animator && useAnimation) {\n result = this.animator.animate({\n viewModel: data,\n series: series,\n layout: stackedColumnLayout,\n itemCS: StackedColumnChartStrategy.classes.item,\n interactivityService: this.interactivityService,\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\n viewPort: { height: this.height, width: this.width },\n });\n shapes = result.shapes;\n }\n if (!this.animator || !useAnimation || result.failed) {\n shapes = visuals.ColumnUtil.drawDefaultShapes(data, series, stackedColumnLayout, StackedColumnChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\n }\n visuals.ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\n return {\n eventGroup: this.graphicsContext.mainGraphicsContext,\n shapesSelection: shapes,\n viewport: { height: this.height, width: this.width },\n axisOptions: axisOptions,\n labelDataPoints: labelDataPoints,\n };\n };\n StackedColumnChartStrategy.prototype.selectColumn = function (selectedColumnIndex, lastSelectedColumnIndex) {\n visuals.ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, StackedColumnChartStrategy.classes.item.selector, selectedColumnIndex, lastSelectedColumnIndex);\n this.moveHandle(selectedColumnIndex);\n };\n StackedColumnChartStrategy.prototype.getClosestColumnIndex = function (x, y) {\n return visuals.ColumnUtil.getClosestColumnIndex(x, this.getColumnsCenters());\n };\n /**\n * Get the chart's columns centers (x value).\n */\n StackedColumnChartStrategy.prototype.getColumnsCenters = function () {\n var _this = this;\n if (!this.columnsCenters) {\n var categoryWidth = this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio);\n // use the axis scale and first series data to get category centers\n if (this.data.series.length > 0) {\n var xScaleOffset_2 = 0;\n if (!this.categoryLayout.isScalar)\n xScaleOffset_2 = categoryWidth / 2;\n var firstSeries = this.data.series[0];\n this.columnsCenters = firstSeries.data.map(function (d) { return _this.xProps.scale(_this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + xScaleOffset_2; });\n }\n }\n return this.columnsCenters;\n };\n StackedColumnChartStrategy.prototype.moveHandle = function (selectedColumnIndex) {\n var columnCenters = this.getColumnsCenters();\n var x = columnCenters[selectedColumnIndex];\n var hoverLine = d3.select('.interactive-hover-line');\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\n }\n if (!this.columnSelectionLineHandle) {\n var handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\n handle.append('line')\n .classed('interactive-hover-line', true)\n .attr({\n x1: x,\n x2: x,\n y1: 0,\n y2: this.height,\n });\n handle.append('circle')\n .attr({\n cx: x,\n cy: this.height,\n r: '6px',\n })\n .classed('drag-handle', true);\n }\n else {\n var handle = this.columnSelectionLineHandle;\n handle.select('line').attr({ x1: x, x2: x });\n handle.select('circle').attr({ cx: x });\n }\n };\n StackedColumnChartStrategy.getLayout = function (data, axisOptions) {\n var columnWidth = axisOptions.columnWidth;\n var isScalar = axisOptions.isScalar;\n var xScale = axisOptions.xScale;\n var yScale = axisOptions.yScale;\n var xScaleOffset = 0;\n if (isScalar)\n xScaleOffset = columnWidth / 2;\n // d.position is the top left corner (for drawing) - set in columnChart.converter\n // for positive values, this is the previous stack position + the new value,\n // for negative values it is just the previous stack position\n return {\n shapeLayout: {\n width: function (d) { return columnWidth; },\n x: function (d) { return xScale(isScalar ? d.categoryValue : d.categoryIndex) - xScaleOffset; },\n y: function (d) { return yScale(d.position); },\n height: function (d) { return yScale(d.position - d.valueAbsolute) - yScale(d.position); },\n },\n shapeLayoutWithoutHighlights: {\n width: function (d) { return columnWidth; },\n x: function (d) { return xScale(isScalar ? d.categoryValue : d.categoryIndex) - xScaleOffset; },\n y: function (d) { return yScale(d.originalPosition); },\n height: function (d) { return yScale(d.originalPosition - d.originalValueAbsolute) - yScale(d.originalPosition); },\n },\n zeroShapeLayout: {\n width: function (d) { return columnWidth; },\n x: function (d) { return xScale(isScalar ? d.categoryValue : d.categoryIndex) - xScaleOffset; },\n y: function (d) { return d.value >= 0 ? yScale(d.position - d.valueAbsolute) : yScale(d.position); },\n height: function (d) { return 0; }\n },\n };\n };\n StackedColumnChartStrategy.prototype.createLabelDataPoints = function () {\n var labelDataPoints = [];\n var data = this.data;\n var series = data.series;\n var formattersCache = visuals.NewDataLabelUtils.createColumnFormatterCacheManager();\n var shapeLayout = this.layout.shapeLayout;\n for (var _i = 0, series_4 = series; _i < series_4.length; _i++) {\n var currentSeries = series_4[_i];\n var labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\n if (!labelSettings.show)\n continue;\n var axisFormatter = visuals.NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\n for (var _a = 0, _b = currentSeries.data; _a < _b.length; _a++) {\n var dataPoint = _b[_a];\n if ((data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\n continue;\n }\n // Calculate parent rectangle\n var parentRect = {\n left: shapeLayout.x(dataPoint),\n top: shapeLayout.y(dataPoint),\n width: shapeLayout.width(dataPoint),\n height: shapeLayout.height(dataPoint),\n };\n // Calculate label text\n var formatString = \"\";\n if (this.graphicsContext.is100Pct) {\n formatString = visuals.NewDataLabelUtils.hundredPercentFormat;\n }\n else {\n formatString = dataPoint.labelFormatString;\n }\n var formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\n var text = visuals.NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\n // Calculate text size\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\n labelDataPoints.push({\n isPreferred: true,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\n insideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\n parentType: 1 /* Rectangle */,\n parentShape: {\n rect: parentRect,\n orientation: dataPoint.value >= 0 ? 1 /* VerticalBottomBased */ : 2 /* VerticalTopBased */,\n validPositions: visuals.ColumnChart.stackedValidLabelPositions,\n },\n identity: dataPoint.identity,\n fontSize: labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt,\n });\n }\n }\n return labelDataPoints;\n };\n StackedColumnChartStrategy.classes = {\n item: {\n class: 'column',\n selector: '.column'\n },\n highlightItem: {\n class: 'highlightColumn',\n selector: '.highlightColumn'\n },\n };\n return StackedColumnChartStrategy;\n }());\n visuals.StackedColumnChartStrategy = StackedColumnChartStrategy;\n var StackedBarChartStrategy = (function () {\n function StackedBarChartStrategy() {\n }\n StackedBarChartStrategy.prototype.setupVisualProps = function (barChartProps) {\n this.graphicsContext = barChartProps;\n this.margin = barChartProps.margin;\n this.width = this.graphicsContext.width;\n this.height = this.graphicsContext.height;\n this.categoryLayout = barChartProps.layout;\n this.animator = barChartProps.animator;\n this.interactivityService = barChartProps.interactivityService;\n this.viewportHeight = barChartProps.viewportHeight;\n this.viewportWidth = barChartProps.viewportWidth;\n this.isComboChart = barChartProps.isComboChart;\n };\n StackedBarChartStrategy.prototype.setData = function (data) {\n this.data = data;\n };\n StackedBarChartStrategy.prototype.setYScale = function (is100Pct, forcedTickCount, forcedYDomain, axisScaleType, axisDisplayUnits, axisPrecision, ensureYDomain) {\n var height = this.height;\n var forcedYMin, forcedYMax;\n if (forcedYDomain && forcedYDomain.length === 2) {\n forcedYMin = forcedYDomain[0];\n forcedYMax = forcedYDomain[1];\n }\n var props = this.yProps = visuals.ColumnUtil.getCategoryAxis(this.data, height, this.categoryLayout, true, forcedYMin, forcedYMax, axisScaleType, axisDisplayUnits, axisPrecision, ensureYDomain);\n return props;\n };\n StackedBarChartStrategy.prototype.setXScale = function (is100Pct, forcedTickCount, forcedXDomain, axisScaleType, axisDisplayUnits, axisPrecision, ensureXDomain) {\n debug.assert(forcedTickCount === undefined, 'Cannot have stacked bar chart as combo chart.');\n var width = this.width;\n var valueDomain = visuals.StackedUtil.calcValueDomain(this.data.series, is100Pct);\n var valueDomainArr = [valueDomain.min, valueDomain.max];\n var combinedDomain = visuals.AxisHelper.combineDomain(forcedXDomain, valueDomainArr, ensureXDomain);\n var shouldClamp = visuals.AxisHelper.scaleShouldClamp(combinedDomain, valueDomainArr);\n var metadataColumn = this.data.valuesMetadata[0];\n var formatString = is100Pct ?\n this.graphicsContext.hostService.getLocalizedString('Percentage')\n : visuals.valueFormatter.getFormatString(metadataColumn, visuals.columnChartProps.general.formatString);\n this.xProps = visuals.AxisHelper.createAxis({\n pixelSpan: width,\n dataDomain: combinedDomain,\n metaDataColumn: metadataColumn,\n formatString: formatString,\n outerPadding: 0,\n isScalar: true,\n isVertical: false,\n forcedTickCount: forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false,\n scaleType: axisScaleType,\n axisDisplayUnits: axisDisplayUnits,\n axisPrecision: axisPrecision,\n is100Pct: is100Pct,\n shouldClamp: shouldClamp,\n });\n this.xProps.axis.tickSize(-this.viewportHeight, 0);\n return this.xProps;\n };\n StackedBarChartStrategy.prototype.drawColumns = function (useAnimation) {\n var data = this.data;\n debug.assertValue(data, 'data should not be null or undefined');\n this.barsCenters = null; // invalidate the barsCenters so that will be calculated again\n var axisOptions = {\n columnWidth: this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio),\n xScale: this.xProps.scale,\n yScale: this.yProps.scale,\n isScalar: this.categoryLayout.isScalar,\n margin: this.margin,\n };\n var stackedBarLayout = this.layout = StackedBarChartStrategy.getLayout(data, axisOptions);\n var dataLabelSettings = data.labelSettings;\n var labelDataPoints = [];\n if (dataLabelSettings && dataLabelSettings.show) {\n labelDataPoints = this.createLabelDataPoints();\n }\n var result;\n var shapes;\n var series = visuals.ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\n if (this.animator && useAnimation) {\n result = this.animator.animate({\n viewModel: data,\n series: series,\n layout: stackedBarLayout,\n itemCS: StackedBarChartStrategy.classes.item,\n interactivityService: this.interactivityService,\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\n viewPort: { height: this.height, width: this.width },\n });\n shapes = result.shapes;\n }\n if (!this.animator || !useAnimation || result.failed) {\n shapes = visuals.ColumnUtil.drawDefaultShapes(data, series, stackedBarLayout, StackedBarChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\n }\n visuals.ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\n return {\n eventGroup: this.graphicsContext.mainGraphicsContext,\n shapesSelection: shapes,\n viewport: { height: this.height, width: this.width },\n axisOptions: axisOptions,\n labelDataPoints: labelDataPoints,\n };\n };\n StackedBarChartStrategy.prototype.selectColumn = function (selectedColumnIndex, lastInteractiveSelectedColumnIndex) {\n visuals.ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, StackedBarChartStrategy.classes.item.selector, selectedColumnIndex, lastInteractiveSelectedColumnIndex);\n this.moveHandle(selectedColumnIndex);\n };\n StackedBarChartStrategy.prototype.getClosestColumnIndex = function (x, y) {\n return visuals.ColumnUtil.getClosestColumnIndex(y, this.getBarsCenters());\n };\n /**\n * Get the chart's columns centers (y value).\n */\n StackedBarChartStrategy.prototype.getBarsCenters = function () {\n var _this = this;\n if (!this.barsCenters) {\n var barWidth = this.categoryLayout.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio);\n // use the axis scale and first series data to get category centers\n if (this.data.series.length > 0) {\n var yScaleOffset_2 = 0;\n if (!this.categoryLayout.isScalar)\n yScaleOffset_2 = barWidth / 2;\n var firstSeries = this.data.series[0];\n this.barsCenters = firstSeries.data.map(function (d) { return _this.yProps.scale(_this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + yScaleOffset_2; });\n }\n }\n return this.barsCenters;\n };\n StackedBarChartStrategy.prototype.moveHandle = function (selectedColumnIndex) {\n var barCenters = this.getBarsCenters();\n var y = barCenters[selectedColumnIndex];\n var hoverLine = d3.select('.interactive-hover-line');\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\n }\n if (!this.columnSelectionLineHandle) {\n var handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\n handle.append('line')\n .classed('interactive-hover-line', true)\n .attr({\n x1: 0,\n x2: this.width,\n y1: y,\n y2: y\n });\n handle.append('circle')\n .classed('drag-handle', true)\n .attr({\n cx: 0,\n cy: y,\n r: '6px',\n });\n }\n else {\n var handle = this.columnSelectionLineHandle;\n handle.select('line').attr({ y1: y, y2: y });\n handle.select('circle').attr({ cy: y });\n }\n };\n StackedBarChartStrategy.getLayout = function (data, axisOptions) {\n var columnWidth = axisOptions.columnWidth;\n var isScalar = axisOptions.isScalar;\n var xScale = axisOptions.xScale;\n var yScale = axisOptions.yScale;\n var yScaleOffset = 0;\n if (isScalar)\n yScaleOffset = columnWidth / 2;\n // d.position is the top right corner for bars - set in columnChart.converter\n // for positive values, this is the previous stack position + the new value,\n // for negative values it is just the previous stack position\n return {\n shapeLayout: {\n width: function (d) { return xScale(d.position) - xScale(d.position - d.valueAbsolute); },\n x: function (d) { return xScale(d.position - d.valueAbsolute); },\n y: function (d) { return yScale(isScalar ? d.categoryValue : d.categoryIndex) - yScaleOffset; },\n height: function (d) { return columnWidth; },\n },\n shapeLayoutWithoutHighlights: {\n width: function (d) { return xScale(d.originalPosition) - xScale(d.originalPosition - d.originalValueAbsolute); },\n x: function (d) { return xScale(d.originalPosition - d.originalValueAbsolute); },\n y: function (d) { return yScale(isScalar ? d.categoryValue : d.categoryIndex) - yScaleOffset; },\n height: function (d) { return columnWidth; },\n },\n zeroShapeLayout: {\n width: function (d) { return 0; },\n x: function (d) { return d.value >= 0 ? xScale(d.position - d.valueAbsolute) : xScale(d.position); },\n y: function (d) { return yScale(isScalar ? d.categoryValue : d.categoryIndex) - yScaleOffset; },\n height: function (d) { return columnWidth; },\n },\n };\n };\n StackedBarChartStrategy.prototype.createLabelDataPoints = function () {\n var labelDataPoints = [];\n var data = this.data;\n var series = data.series;\n var formattersCache = visuals.NewDataLabelUtils.createColumnFormatterCacheManager();\n var shapeLayout = this.layout.shapeLayout;\n for (var _i = 0, series_5 = series; _i < series_5.length; _i++) {\n var currentSeries = series_5[_i];\n var labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\n if (!labelSettings.show)\n continue;\n var axisFormatter = visuals.NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\n for (var _a = 0, _b = currentSeries.data; _a < _b.length; _a++) {\n var dataPoint = _b[_a];\n if ((this.interactivityService && this.interactivityService.hasSelection() && !dataPoint.selected) || (data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\n continue;\n }\n // Calculate label text\n var formatString = undefined;\n if (this.graphicsContext.is100Pct) {\n formatString = visuals.NewDataLabelUtils.hundredPercentFormat;\n }\n else {\n formatString = dataPoint.labelFormatString;\n }\n var formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\n var text = visuals.NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\n // Calculate text size\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\n // Calculate parent rectangle\n var parentRect = {\n left: shapeLayout.x(dataPoint),\n top: shapeLayout.y(dataPoint),\n width: shapeLayout.width(dataPoint),\n height: shapeLayout.height(dataPoint),\n };\n labelDataPoints.push({\n isPreferred: true,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\n insideFill: visuals.ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\n parentType: 1 /* Rectangle */,\n parentShape: {\n rect: parentRect,\n orientation: dataPoint.value >= 0 ? 3 /* HorizontalLeftBased */ : 4 /* HorizontalRightBased */,\n validPositions: visuals.ColumnChart.stackedValidLabelPositions,\n },\n identity: dataPoint.identity,\n fontSize: labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt,\n });\n }\n }\n return labelDataPoints;\n };\n StackedBarChartStrategy.classes = {\n item: {\n class: 'bar',\n selector: '.bar'\n },\n highlightItem: {\n class: 'highlightBar',\n selector: '.highlightBar'\n },\n };\n return StackedBarChartStrategy;\n }());\n visuals.StackedBarChartStrategy = StackedBarChartStrategy;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var samples;\n (function (samples) {\n var SelectionManager = visuals.utility.SelectionManager;\n var HelloIVisual = (function () {\n function HelloIVisual() {\n }\n HelloIVisual.converter = function (dataView) {\n var viewModel = {\n size: HelloIVisual.getSize(dataView),\n color: HelloIVisual.getFill(dataView).solid.color,\n text: HelloIVisual.DefaultText,\n toolTipInfo: [{\n displayName: 'Test',\n value: '1...2....3... can you see me? I am sending random strings to the tooltip',\n }],\n selector: visuals.SelectionId.createNull()\n };\n var table = dataView.table;\n if (!table)\n return viewModel;\n viewModel.text = table.rows[0][0];\n if (dataView.categorical) {\n viewModel.selector = dataView.categorical.categories[0].identity\n ? visuals.SelectionId.createWithId(dataView.categorical.categories[0].identity[0])\n : visuals.SelectionId.createNull();\n }\n return viewModel;\n };\n HelloIVisual.prototype.init = function (options) {\n this.root = d3.select(options.element.get(0))\n .append('svg')\n .classed('hello', true);\n this.svgText = this.root\n .append('text')\n .style('cursor', 'pointer')\n .style('stroke', 'green')\n .style('stroke-width', '0px')\n .attr('text-anchor', 'middle');\n this.selectiionManager = new SelectionManager({ hostServices: options.host });\n };\n HelloIVisual.prototype.update = function (options) {\n if (!options.dataViews && !options.dataViews[0])\n return;\n var dataView = this.dataView = options.dataViews[0];\n var viewport = options.viewport;\n var viewModel = HelloIVisual.converter(dataView);\n this.root.attr({\n 'height': viewport.height,\n 'width': viewport.width\n });\n var textProperties = {\n fontFamily: 'tahoma',\n fontSize: viewModel.size + 'px',\n text: viewModel.text\n };\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(textProperties);\n var selectionManager = this.selectiionManager;\n this.svgText.style({\n 'fill': viewModel.color,\n 'font-size': textProperties.fontSize,\n 'font-family': textProperties.fontFamily,\n }).attr({\n 'y': viewport.height / 2 + textHeight / 3 + 'px',\n 'x': viewport.width / 2,\n }).text(viewModel.text)\n .on('click', function () {\n var _this = this;\n selectionManager\n .select(viewModel.selector)\n .then(function (ids) { return d3.select(_this).style('stroke-width', ids.length > 0 ? '2px' : '0px'); });\n })\n .data([viewModel]);\n visuals.TooltipManager.addTooltip(this.svgText, function (tooltipEvent) { return tooltipEvent.data.toolTipInfo; });\n };\n HelloIVisual.getFill = function (dataView) {\n if (dataView) {\n var objects = dataView.metadata.objects;\n if (objects) {\n var general = objects['general'];\n if (general) {\n var fill = general['fill'];\n if (fill)\n return fill;\n }\n }\n }\n return { solid: { color: 'red' } };\n };\n HelloIVisual.getSize = function (dataView) {\n if (dataView) {\n var objects = dataView.metadata.objects;\n if (objects) {\n var general = objects['general'];\n if (general) {\n var size = general['size'];\n if (size)\n return size;\n }\n }\n }\n return 100;\n };\n HelloIVisual.prototype.enumerateObjectInstances = function (options) {\n var instances = [];\n var dataView = this.dataView;\n switch (options.objectName) {\n case 'general':\n var general = {\n objectName: 'general',\n displayName: 'General',\n selector: null,\n properties: {\n fill: HelloIVisual.getFill(dataView),\n size: HelloIVisual.getSize(dataView)\n }\n };\n instances.push(general);\n break;\n }\n return instances;\n };\n HelloIVisual.prototype.destroy = function () {\n this.root = null;\n };\n HelloIVisual.capabilities = {\n dataRoles: [{\n displayName: 'Values',\n name: 'Values',\n kind: powerbi.VisualDataRoleKind.GroupingOrMeasure\n }],\n dataViewMappings: [{\n table: {\n rows: {\n for: { in: 'Values' },\n dataReductionAlgorithm: { window: { count: 100 } }\n },\n rowCount: { preferred: { min: 1 } }\n },\n }],\n objects: {\n general: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_General'),\n properties: {\n fill: {\n type: { fill: { solid: { color: true } } },\n displayName: 'Fill'\n },\n size: {\n type: { numeric: true },\n displayName: 'Size'\n }\n },\n }\n },\n };\n HelloIVisual.DefaultText = 'Invalid DV';\n return HelloIVisual;\n }());\n samples.HelloIVisual = HelloIVisual;\n })(samples = visuals.samples || (visuals.samples = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * This module only supplies the capabilities for comboCharts.\n * Implementation is in cartesianChart and the various ICartesianVisual implementations.\n */\n var ComboChart;\n (function (ComboChart) {\n ComboChart.capabilities = visuals.comboChartCapabilities;\n /**\n * Handles the case of a column layer in a combo chart. In this case, the column layer is enumearated last.\n */\n function enumerateDataPoints(enumeration, options, layers) {\n if (!layers)\n return;\n var columnChartLayerIndex;\n var layersLength = layers.length;\n for (var layerIndex = 0; layerIndex < layersLength; layerIndex++) {\n var layer = layers[layerIndex];\n if (layer.enumerateObjectInstances) {\n if (layer instanceof visuals.ColumnChart) {\n columnChartLayerIndex = layerIndex;\n continue;\n }\n layer.enumerateObjectInstances(enumeration, options);\n }\n }\n if (columnChartLayerIndex !== undefined)\n layers[columnChartLayerIndex].enumerateObjectInstances(enumeration, options);\n }\n ComboChart.enumerateDataPoints = enumerateDataPoints;\n function customizeQuery(options) {\n // If there is a dynamic series but no values on the column data view mapping, remove the dynamic series\n var columnMapping = !_.isEmpty(options.dataViewMappings) && options.dataViewMappings[0];\n if (columnMapping) {\n var columnValuesMapping = columnMapping.categorical && columnMapping.categorical.values;\n var seriesSelect = columnValuesMapping.group && !_.isEmpty(columnValuesMapping.group.select) && columnValuesMapping.group.select[0];\n if (_.isEmpty(seriesSelect.for.in.items))\n columnValuesMapping.group.by.items = undefined;\n }\n if (columnMapping && columnMapping.categorical) {\n columnMapping.categorical.dataVolume = 4;\n }\n var lineMapping = options.dataViewMappings.length > 1 && options.dataViewMappings[1];\n if (lineMapping && lineMapping.categorical) {\n lineMapping.categorical.dataVolume = 4;\n }\n }\n ComboChart.customizeQuery = customizeQuery;\n function getSortableRoles(options) {\n if (options && options.dataViewMappings.length > 0) {\n var dataViewMapping = options.dataViewMappings[0];\n //TODO: column chart should be sortable by X if it has scalar axis\n // But currenly it doesn't support this. Return 'category' once\n // it is supported.\n if (!visuals.CartesianChart.detectScalarMapping(dataViewMapping))\n return ['Category', 'Y', 'Y2'];\n }\n return null;\n }\n ComboChart.getSortableRoles = getSortableRoles;\n function isComboChart(chartType) {\n return chartType === 10 /* ComboChart */\n || chartType === 13 /* LineClusteredColumnCombo */\n || chartType === 14 /* LineStackedColumnCombo */\n || chartType === 15 /* DataDotClusteredColumnCombo */\n || chartType === 16 /* DataDotStackedColumnCombo */;\n }\n ComboChart.isComboChart = isComboChart;\n })(ComboChart = visuals.ComboChart || (visuals.ComboChart = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var ArrayExtensions = jsCommon.ArrayExtensions;\n var DataColorPalette = (function () {\n /**\n * Creates a DataColorPalette using the given theme, or the default theme.\n */\n function DataColorPalette(colors, sentimentcolors) {\n // Hardcoded values for Color Picker.\n this.basePickerColors = [\n { value: '#FFFFFF' },\n { value: '#000000' },\n { value: '#00B8AA' },\n { value: '#374649' },\n { value: '#FD625E' },\n { value: '#F2C811' },\n { value: '#5F6B6D' },\n { value: '#8AD4EB' },\n { value: '#FE9666' },\n { value: '#A66999' }\n ];\n // TODO: Default theme is currently hardcoded. Theme should eventually come from PV and be added as a parameter in the ctor. \n this.colors = colors || ThemeManager.getDefaultTheme();\n this.sentimentColors = sentimentcolors || ThemeManager.defaultSentimentColors;\n this.scales = {};\n }\n DataColorPalette.prototype.getColorScaleByKey = function (key) {\n var scale = this.scales[key];\n if (scale === undefined) {\n scale = this.createScale();\n this.scales[key] = scale;\n }\n return scale;\n };\n DataColorPalette.prototype.getNewColorScale = function () {\n return this.createScale();\n };\n DataColorPalette.prototype.getColorByIndex = function (index) {\n debug.assert(index >= 0 && index < this.colors.length, 'index is out of bounds');\n return this.colors[index];\n };\n DataColorPalette.prototype.getSentimentColors = function () {\n return this.sentimentColors;\n };\n DataColorPalette.prototype.getBasePickerColors = function () {\n return this.basePickerColors;\n };\n DataColorPalette.prototype.getAllColors = function () {\n return this.colors;\n };\n DataColorPalette.prototype.createScale = function () {\n return D3ColorScale.createFromColors(this.colors);\n };\n return DataColorPalette;\n }());\n visuals.DataColorPalette = DataColorPalette;\n var D3ColorScale = (function () {\n function D3ColorScale(scale) {\n this.scale = scale;\n }\n D3ColorScale.prototype.getColor = function (key) {\n return this.scale(key);\n };\n D3ColorScale.prototype.clearAndRotateScale = function () {\n var offset = this.scale.domain().length;\n var rotatedColors = ArrayExtensions.rotate(this.scale.range(), offset);\n this.scale = d3.scale.ordinal().range(rotatedColors);\n };\n D3ColorScale.prototype.clone = function () {\n return new D3ColorScale(this.scale.copy());\n };\n D3ColorScale.prototype.getDomain = function () {\n return this.scale.domain();\n };\n D3ColorScale.createFromColors = function (colors) {\n return new D3ColorScale(d3.scale.ordinal().range(colors));\n };\n return D3ColorScale;\n }());\n visuals.D3ColorScale = D3ColorScale;\n // TODO: When theming support is added, this should be changed into a fully fledged service. For now though we will\n var ThemeManager = (function () {\n function ThemeManager() {\n }\n ThemeManager.getDefaultTheme = function () {\n if (!ThemeManager.defaultTheme) {\n // Extend the list of available colors by cycling the base colors\n ThemeManager.defaultTheme = [];\n var baseColors = ThemeManager.defaultBaseColors;\n for (var i = 0; i < ThemeManager.colorSectorCount; ++i) {\n for (var j = 0, jlen = baseColors.length; j < jlen; ++j) {\n ThemeManager.defaultTheme.push({\n value: jsCommon.Color.rotate(baseColors[j].value, i / ThemeManager.colorSectorCount)\n });\n }\n }\n }\n return ThemeManager.defaultTheme;\n };\n ThemeManager.colorSectorCount = 12;\n // declare the Theme code as a private implementation detail inside the DataColorPalette so that the code stays hidden\n // until it's ready for wider use.\n ThemeManager.defaultBaseColors = [\n // First loop\n { value: '#01B8AA' },\n { value: '#374649' },\n { value: '#FD625E' },\n { value: '#F2C80F' },\n { value: '#5F6B6D' },\n { value: '#8AD4EB' },\n { value: '#FE9666' },\n { value: '#A66999' },\n { value: '#3599B8' },\n { value: '#DFBFBF' },\n // Second loop\n { value: '#4AC5BB' },\n { value: '#5F6B6D' },\n { value: '#FB8281' },\n { value: '#F4D25A' },\n { value: '#7F898A' },\n { value: '#A4DDEE' },\n { value: '#FDAB89' },\n { value: '#B687AC' },\n { value: '#28738A' },\n { value: '#A78F8F' },\n // Third loop\n { value: '#168980' },\n { value: '#293537' },\n { value: '#BB4A4A' },\n { value: '#B59525' },\n { value: '#475052' },\n { value: '#6A9FB0' },\n { value: '#BD7150' },\n { value: '#7B4F71' },\n { value: '#1B4D5C' },\n { value: '#706060' },\n // Fourth loop\n { value: '#0F5C55' },\n { value: '#1C2325' },\n { value: '#7D3231' },\n { value: '#796419' },\n { value: '#303637' },\n { value: '#476A75' },\n { value: '#7E4B36' },\n { value: '#52354C' },\n { value: '#0D262E' },\n { value: '#544848' },\n ];\n ThemeManager.defaultSentimentColors = [\n { value: '#C0433A' },\n { value: '#E8D62E' },\n { value: '#79C75B' },\n ];\n return ThemeManager;\n }());\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/**\n * IMPORTANT: This chart is not currently enabled in the PBI system and is under development.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n /**\n * The data dot chart shows a set of circles with the data value inside them.\n * The circles are regularly spaced similar to column charts.\n * The radius of all dots is the same across the chart.\n * This is most often combined with a column chart to create the 'chicken pox' chart.\n * If any of the data values do not fit within the circles, then the data values are hidden\n * and the y axis for the dots is displayed instead.\n * This chart only supports a single series of data.\n * This chart does not display a legend.\n */\n var DataDotChart = (function () {\n function DataDotChart(options) {\n this.isScrollable = options.isScrollable;\n this.interactivityService = options.interactivityService;\n }\n DataDotChart.prototype.init = function (options) {\n this.options = options;\n // Common properties\n this.svg = options.svg;\n this.svg.classed(DataDotChart.ClassName, true);\n this.mainGraphicsG = this.svg.append('g')\n .classed('dataDotChartMainGraphicsContext', true);\n this.mainGraphicsContext = this.mainGraphicsG.append('svg');\n this.currentViewport = options.viewport;\n this.hostService = options.host;\n this.cartesianVisualHost = options.cartesianHost;\n this.style = options.style;\n this.colors = this.style.colorPalette.dataColors;\n // Interactivity properties\n this.interactivity = options.interactivity;\n this.element = options.element;\n };\n DataDotChart.prototype.setData = function (dataViews) {\n this.data = {\n series: {\n data: []\n },\n hasHighlights: false,\n hasDynamicSeries: false,\n };\n if (dataViews.length > 0) {\n // I only handle a single data view\n var dataView = dataViews[0];\n if (dataView && dataView.categorical) {\n var dataViewCategorical = this.dataViewCategorical = dataView.categorical;\n var dvCategories = dataViewCategorical.categories;\n // I default to text unless there is a category type\n var categoryType = powerbi.ValueType.fromDescriptor({ text: true });\n if (dvCategories && dvCategories.length > 0 && dvCategories[0].source && dvCategories[0].source.type)\n categoryType = dvCategories[0].source.type;\n this.data = DataDotChart.converter(dataView, visuals.valueFormatter.format(null), this.interactivityService);\n }\n }\n };\n DataDotChart.prototype.setFilteredData = function (startIndex, endIndex) {\n var data = this.clippedData = powerbi.Prototype.inherit(this.data);\n if (data && data.series && data.series.data)\n data.series = { data: data.series.data.slice(startIndex, endIndex), xCol: data.series.xCol, yCol: data.series.yCol };\n return data;\n };\n DataDotChart.prototype.calculateAxesProperties = function (options) {\n var _this = this;\n this.currentViewport = options.viewport;\n this.margin = options.margin;\n var data = this.clippedData = this.data;\n var viewport = this.currentViewport;\n var margin = this.margin;\n var series = data ? data.series : null;\n var seriesArray = series && series.data && series.data.length > 0 ? [series] : [];\n var categoryCount = series && series.data ? series.data.length : 0;\n // If there are highlights, then the series is 2x in length and highlights are interwoven.\n if (data.hasHighlights) {\n categoryCount = categoryCount / 2;\n }\n var width = viewport.width - (margin.left + margin.right);\n var height = viewport.height - (margin.top + margin.bottom);\n var xMetaDataColumn;\n var yMetaDataColumn;\n if (DataDotChart.hasDataPoint(series)) {\n xMetaDataColumn = series.xCol;\n yMetaDataColumn = series.yCol;\n }\n var layout = visuals.CartesianChart.getLayout(null, {\n availableWidth: width,\n categoryCount: categoryCount,\n domain: null,\n isScalar: false,\n isScrollable: this.isScrollable,\n trimOrdinalDataOnOverflow: options.trimOrdinalDataOnOverflow\n });\n var outerPadding = layout.categoryThickness * visuals.CartesianChart.OuterPaddingRatio;\n // clip data that won't fit\n if (!this.isScrollable) {\n this.clippedData = DataDotChart.createClippedDataIfOverflowed(data, layout.categoryCount);\n }\n var yDomain = visuals.AxisHelper.createValueDomain(seriesArray, /*includeZero:*/ true) || visuals.emptyDomain;\n var combinedDomain = visuals.AxisHelper.combineDomain(options.forcedYDomain, yDomain, options.ensureYDomain);\n this.yAxisProperties = visuals.AxisHelper.createAxis({\n pixelSpan: height,\n dataDomain: combinedDomain,\n metaDataColumn: yMetaDataColumn,\n formatString: visuals.valueFormatter.getFormatString(yMetaDataColumn, DataDotChart.formatStringProp),\n outerPadding: 0,\n isScalar: true,\n isVertical: true,\n forcedTickCount: options.forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false\n });\n var axisType = this.xAxisProperties ? this.xAxisProperties.axisType : powerbi.ValueType.fromDescriptor({ text: true });\n var xDomain = visuals.AxisHelper.createDomain(seriesArray, axisType, /*isScalar:*/ false, options.forcedXDomain, options.ensureXDomain);\n this.xAxisProperties = visuals.AxisHelper.createAxis({\n pixelSpan: width,\n dataDomain: xDomain,\n metaDataColumn: xMetaDataColumn,\n formatString: visuals.valueFormatter.getFormatString(xMetaDataColumn, DataDotChart.formatStringProp),\n outerPadding: outerPadding,\n isScalar: false,\n isVertical: false,\n forcedTickCount: options.forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n categoryThickness: layout.categoryThickness,\n getValueFn: function (index, type) { return _this.lookupXValue(index, type); },\n isCategoryAxis: true\n });\n return [this.xAxisProperties, this.yAxisProperties];\n };\n DataDotChart.createClippedDataIfOverflowed = function (data, categoryCount) {\n // If there are highlights, then the series is 2x in length and highlights are interwoven.\n var requiredLength = data.hasHighlights ? Math.min(data.series.data.length, categoryCount * 2) : Math.min(data.series.data.length, categoryCount);\n if (requiredLength >= data.series.data.length) {\n return data;\n }\n var clipped = powerbi.Prototype.inherit(data);\n clipped.series = powerbi.Prototype.inherit(data.series); // This prevents clipped and data from sharing the series object\n clipped.series.data = clipped.series.data.slice(0, requiredLength);\n return clipped;\n };\n DataDotChart.hasDataPoint = function (series) {\n return (series && series.data && series.data.length > 0);\n };\n DataDotChart.prototype.lookupXValue = function (index, type) {\n var data = this.data;\n var isDateTime = visuals.AxisHelper.isDateTime(type);\n if (isDateTime)\n return new Date(index);\n if (data && data.series) {\n var seriesData = data.series.data;\n if (seriesData) {\n var dataAtIndex = seriesData[index];\n if (dataAtIndex) {\n return dataAtIndex.categoryValue;\n }\n }\n }\n return index;\n };\n DataDotChart.prototype.overrideXScale = function (xProperties) {\n this.xAxisProperties = xProperties;\n };\n DataDotChart.prototype.render = function (suppressAnimations) {\n var _this = this;\n if (!this.clippedData)\n return;\n var data = this.clippedData;\n var dataPoints = data.series.data;\n var hasHighlights = data.hasHighlights;\n var margin = this.margin;\n var viewport = this.currentViewport;\n var width = viewport.width - (margin.left + margin.right);\n var height = viewport.height - (margin.top + margin.bottom);\n var xScale = this.xAxisProperties.scale;\n var yScale = this.yAxisProperties.scale;\n var dotWidth = this.xAxisProperties.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio);\n var dotRadius = dotWidth / 2;\n var dotColor = this.cartesianVisualHost.getSharedColors().getNewColorScale().getColor(DataDotChart.DotColorKey);\n var hasSelection = this.interactivityService ? this.interactivityService.hasSelection() : false;\n this.mainGraphicsContext.attr('width', width)\n .attr('height', height);\n var dots = this.mainGraphicsContext.selectAll(DataDotChart.DotClassSelector).data(dataPoints, function (d) { return d.identity.getKey(); });\n dots.enter()\n .append('circle')\n .classed(DataDotChart.DotClassName, true);\n dots\n .style({ 'fill': dotColor.value })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights); })\n .classed('null-value', function (d) { return d.value === null; })\n .attr({\n r: function (d) { return dotRadius; },\n cx: function (d) { return xScale(d.categoryIndex) + dotRadius; },\n cy: function (d) { return yScale(d.value); }\n });\n dots.exit().remove();\n var dotLabels = this.mainGraphicsContext.selectAll(DataDotChart.DotLabelClassSelector).data(dataPoints, function (d) { return d.identity.getKey(); });\n dotLabels.enter()\n .append('text')\n .classed(DataDotChart.DotLabelClassName, true)\n .attr({\n 'text-anchor': DataDotChart.DotLabelTextAnchor,\n dy: DataDotChart.DotLabelVerticalOffset\n });\n dotLabels\n .classed('null-value', function (d) { return d.value === null; })\n .classed('overflowed', false)\n .attr({\n x: function (d) { return xScale(d.categoryIndex) + dotRadius; },\n y: function (d) { return yScale(d.value); }\n })\n .text(function (d) { return _this.yAxisProperties.formatter.format(d.value); });\n var overflowed = false;\n dotLabels\n .each(function () {\n // jQuery fails to properly inspect SVG class elements, the $('<div>') notation works around it.\n if (!overflowed && !$(\"<div>\").addClass($(this).attr(\"class\")).hasClass(\"null-value\")) {\n var width_1 = powerbi.TextMeasurementService.measureSvgTextElementWidth(this);\n if (width_1 > dotWidth) {\n dotLabels.classed('overflowed', true);\n overflowed = true;\n }\n }\n });\n dotLabels.exit().remove();\n var behaviorOptions = undefined;\n if (this.interactivityService) {\n behaviorOptions = {\n dots: dots,\n dotLabels: dotLabels,\n datapoints: dataPoints\n };\n }\n // This should always be the last line in the render code.\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n return { dataPoints: dataPoints, behaviorOptions: behaviorOptions, labelDataPoints: [], labelsAreNumeric: true };\n };\n DataDotChart.prototype.calculateLegend = function () {\n return this.createLegendDataPoints(0); // start with index 0\n };\n DataDotChart.prototype.hasLegend = function () {\n return this.data && this.data.hasDynamicSeries;\n };\n DataDotChart.prototype.createLegendDataPoints = function (columnIndex) {\n var data = this.data;\n if (!data)\n return null;\n var series = data.series;\n var seriesData = series.data;\n var legendDataPoints = [];\n var category;\n var axisType = this.xAxisProperties ? this.xAxisProperties.axisType : powerbi.ValueType.fromDescriptor({ text: true });\n // Category will be the same for all series. This is an optimization.\n if (data.series && data.series.data) {\n var firstDataPoint = data.series.data[0];\n category = firstDataPoint && this.lookupXValue(firstDataPoint.categoryValue, axisType);\n }\n // Create a legend data point for the specified column \n if (series.yCol) {\n var formatStringProp = DataDotChart.formatStringProp;\n var lineDataPoint = seriesData[columnIndex];\n var measure = lineDataPoint && lineDataPoint.value;\n var label = visuals.converterHelper.getFormattedLegendLabel(series.yCol, this.dataViewCategorical.values, formatStringProp);\n var dotColor = this.cartesianVisualHost.getSharedColors().getNewColorScale().getColor(DataDotChart.DotColorKey);\n var dataViewCategoricalValues = this.dataViewCategorical.values;\n var identity = dataViewCategoricalValues && dataViewCategoricalValues.length > columnIndex ?\n visuals.SelectionId.createWithIdAndMeasure(dataViewCategoricalValues[columnIndex].identity, dataViewCategoricalValues[columnIndex].source.queryName) :\n visuals.SelectionId.createWithMeasure(dataViewCategoricalValues.source.queryName);\n legendDataPoints.push({\n color: dotColor.value,\n icon: visuals.LegendIcon.Line,\n label: label,\n category: visuals.valueFormatter.format(category, visuals.valueFormatter.getFormatString(series.xCol, formatStringProp)),\n measure: visuals.valueFormatter.format(measure, visuals.valueFormatter.getFormatString(series.yCol, formatStringProp)),\n identity: identity,\n selected: false\n });\n }\n return { dataPoints: legendDataPoints };\n };\n DataDotChart.prototype.onClearSelection = function () {\n if (this.interactivityService)\n this.interactivityService.clearSelection();\n // cartesianChart handles calling render again.\n };\n DataDotChart.converter = function (dataView, blankCategoryValue, interactivityService) {\n var categorical = dataView.categorical;\n var category = categorical.categories && categorical.categories.length > 0\n ? categorical.categories[0]\n : {\n source: undefined,\n values: [blankCategoryValue],\n identity: undefined\n };\n var categoryType = visuals.AxisHelper.getCategoryValueType(category.source);\n var isDateTime = visuals.AxisHelper.isDateTime(categoryType);\n var categoryValues = category.values;\n // I only handle a single series\n if (!_.isEmpty(categorical.values)) {\n var measure = categorical.values[0];\n var hasHighlights = !!measure.highlights;\n var dataPoints = [];\n for (var categoryIndex = 0, len = measure.values.length; categoryIndex < len; categoryIndex++) {\n debug.assert(!category.identity || categoryIndex < category.identity.length, 'Category identities is smaller than category values.');\n // I create the identity from the category. If there is no category, then I use the measure name to create identity\n var identity = category.identity ?\n visuals.SelectionId.createWithIdAndMeasure(category.identity[categoryIndex], measure.source.queryName) :\n visuals.SelectionId.createWithMeasure(measure.source.queryName);\n var categoryValue = categoryValues[categoryIndex];\n // ignore variant measures\n if (isDateTime && categoryValue != null && !(categoryValue instanceof Date))\n continue;\n dataPoints.push({\n categoryValue: isDateTime && categoryValue ? categoryValue.getTime() : categoryValue,\n value: measure.values[categoryIndex],\n categoryIndex: categoryIndex,\n seriesIndex: 0,\n selected: false,\n identity: identity,\n highlight: false\n });\n if (hasHighlights) {\n var highlightIdentity = visuals.SelectionId.createWithHighlight(identity);\n var highlightValue = measure.highlights[categoryIndex];\n dataPoints.push({\n categoryValue: isDateTime && categoryValue ? categoryValue.getTime() : categoryValue,\n value: highlightValue,\n categoryIndex: categoryIndex,\n seriesIndex: 0,\n selected: false,\n identity: highlightIdentity,\n highlight: true\n });\n }\n }\n if (interactivityService)\n interactivityService.applySelectionStateToData(dataPoints);\n return {\n series: {\n xCol: category.source,\n yCol: measure.source,\n data: dataPoints\n },\n hasHighlights: hasHighlights,\n hasDynamicSeries: true,\n };\n }\n return {\n series: {\n data: []\n },\n hasHighlights: false,\n hasDynamicSeries: false,\n };\n };\n DataDotChart.formatStringProp = { objectName: 'general', propertyName: 'formatString' };\n DataDotChart.ClassName = 'dataDotChart';\n DataDotChart.DotClassName = 'dot';\n DataDotChart.DotClassSelector = '.dot';\n DataDotChart.DotColorKey = 'dataDot';\n DataDotChart.DotLabelClassName = 'label';\n DataDotChart.DotLabelClassSelector = '.label';\n DataDotChart.DotLabelVerticalOffset = '0.4em';\n DataDotChart.DotLabelTextAnchor = 'middle';\n return DataDotChart;\n }());\n visuals.DataDotChart = DataDotChart;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n /**\n * Renders a funnel chart.\n */\n var FunnelChart = (function () {\n function FunnelChart(options) {\n this.labelPositionObjects = [visuals.labelPosition.outsideEnd, visuals.labelPosition.insideCenter];\n if (options) {\n this.tooltipsEnabled = options.tooltipsEnabled;\n if (options.funnelSmallViewPortProperties) {\n this.funnelSmallViewPortProperties = options.funnelSmallViewPortProperties;\n }\n if (options.animator) {\n this.animator = options.animator;\n }\n if (options.behavior) {\n this.behavior = options.behavior;\n }\n }\n }\n FunnelChart.isValidValueColumn = function (valueColumn) {\n debug.assertValue(valueColumn, 'valueColumn');\n return DataRoleHelper.hasRole(valueColumn.source, 'Y');\n };\n FunnelChart.getFirstValidValueColumn = function (values) {\n for (var _i = 0, values_1 = values; _i < values_1.length; _i++) {\n var valueColumn = values_1[_i];\n if (!FunnelChart.isValidValueColumn(valueColumn))\n continue;\n return valueColumn;\n }\n return undefined;\n };\n FunnelChart.converter = function (dataView, colors, hostServices, defaultDataPointColor, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var slices = [];\n var formatStringProp = visuals.funnelChartProps.general.formatString;\n var categorical = dataView.categorical;\n var categories = categorical.categories || [];\n var values = categorical.values;\n var valueMetaData = [];\n if (values) {\n valueMetaData = _.map(values, function (v) { return v.source; });\n }\n var hasHighlights = values && values.length > 0 && values[0] && !!values[0].highlights;\n var highlightsOverflow = false;\n var hasNegativeValues = false;\n var allValuesAreNegative = false;\n var categoryLabels = [];\n var dataLabelsSettings = visuals.dataLabelUtils.getDefaultFunnelLabelSettings();\n var percentBarLabelSettings = visuals.dataLabelUtils.getDefaultLabelSettings(true);\n var colorHelper = new visuals.ColorHelper(colors, visuals.funnelChartProps.dataPoint.fill, defaultDataPointColor);\n var firstValue;\n var firstHighlight;\n var previousValue;\n var previousHighlight;\n var gradientValueColumn = visuals.GradientUtils.getGradientValueColumn(categorical);\n if (dataView && dataView.metadata && dataView.metadata.objects) {\n var labelsObj = dataView.metadata.objects['labels'];\n if (labelsObj)\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\n var percentLabelsObj = dataView.metadata.objects['percentBarLabel'];\n if (percentLabelsObj)\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(percentLabelsObj, percentBarLabelSettings);\n }\n // Always take the first valid value field\n var firstValueColumn = !_.isEmpty(values) && FunnelChart.getFirstValidValueColumn(values);\n // If we don't have a valid value column, just return\n if (!firstValueColumn)\n return {\n slices: slices,\n categoryLabels: categoryLabels,\n valuesMetadata: valueMetaData,\n hasHighlights: hasHighlights,\n highlightsOverflow: highlightsOverflow,\n canShowDataLabels: true,\n dataLabelsSettings: dataLabelsSettings,\n hasNegativeValues: hasNegativeValues,\n allValuesAreNegative: allValuesAreNegative,\n percentBarLabelSettings: percentBarLabelSettings,\n };\n // Calculate the first value for percent tooltip values\n firstValue = firstValueColumn.values[0];\n if (hasHighlights) {\n firstHighlight = firstValueColumn.highlights[0];\n }\n var pctFormatString = visuals.valueFormatter.getLocalizedString('Percentage');\n if (categories.length === 1) {\n // Single Category, Value and (optional) Gradient\n var category = categories[0];\n var categoryValues = category.values;\n for (var i = 0, ilen = categoryValues.length; i < ilen; i++) {\n var measureName = firstValueColumn.source.queryName;\n var identity = visuals.SelectionIdBuilder.builder()\n .withCategory(category, i)\n .withMeasure(measureName)\n .createSelectionId();\n var value = firstValueColumn.values[i];\n var formattedCategoryValue = visuals.converterHelper.formatFromMetadataColumn(categoryValues[i], category.source, formatStringProp);\n var tooltipInfo = void 0;\n if (tooltipsEnabled) {\n tooltipInfo = [];\n tooltipInfo.push({\n displayName: category.source.displayName,\n value: formattedCategoryValue,\n });\n if (value != null) {\n tooltipInfo.push({\n displayName: firstValueColumn.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(value, firstValueColumn.source, formatStringProp),\n });\n }\n var highlightValue = void 0;\n if (hasHighlights) {\n highlightValue = firstValueColumn.highlights[i];\n if (highlightValue != null) {\n tooltipInfo.push({\n displayName: visuals.ToolTipComponent.localizationOptions.highlightedValueDisplayName,\n value: visuals.converterHelper.formatFromMetadataColumn(highlightValue, firstValueColumn.source, formatStringProp),\n });\n }\n }\n var gradientColumnMetadata = gradientValueColumn ? gradientValueColumn.source : undefined;\n if (gradientColumnMetadata && gradientColumnMetadata !== firstValueColumn.source && gradientValueColumn.values[i] != null) {\n tooltipInfo.push({\n displayName: gradientColumnMetadata.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(gradientValueColumn.values[i], gradientColumnMetadata, formatStringProp),\n });\n }\n if (hasHighlights) {\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstHighlight ? highlightValue / firstHighlight : null, previousHighlight ? highlightValue / previousHighlight : null, true);\n }\n else {\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstValue ? value / firstValue : null, previousValue ? value / previousValue : null);\n }\n }\n // Same color for all bars\n var color = colorHelper.getColorForMeasure(category.objects && category.objects[i], '');\n slices.push({\n label: formattedCategoryValue,\n value: value,\n originalValue: value,\n categoryOrMeasureIndex: i,\n identity: identity,\n selected: false,\n key: identity.getKey(),\n tooltipInfo: tooltipInfo,\n color: color,\n labelFill: dataLabelsSettings.labelColor,\n });\n if (hasHighlights) {\n var highlightIdentity = visuals.SelectionId.createWithHighlight(identity);\n var highlightValue = firstValueColumn.highlights[i];\n slices.push({\n label: formattedCategoryValue,\n value: value,\n originalValue: value,\n categoryOrMeasureIndex: i,\n identity: highlightIdentity,\n selected: false,\n key: highlightIdentity.getKey(),\n highlight: true,\n highlightValue: highlightValue,\n originalHighlightValue: highlightValue,\n tooltipInfo: tooltipInfo,\n color: color,\n });\n previousHighlight = highlightValue;\n }\n previousValue = value;\n }\n }\n else if (valueMetaData.length > 0 && values && values.length > 0) {\n // Multi-measures\n for (var i = 0, len = values.length; i < len; i++) {\n var valueColumn = values[i];\n if (!FunnelChart.isValidValueColumn(valueColumn))\n continue;\n var value = valueColumn.values[0];\n var identity = visuals.SelectionId.createWithMeasure(valueColumn.source.queryName);\n var tooltipInfo = void 0;\n // Same color for all bars\n var color = colorHelper.getColorForMeasure(valueColumn.source.objects, '');\n if (tooltipsEnabled) {\n tooltipInfo = [];\n if (value != null) {\n tooltipInfo.push({\n displayName: valueColumn.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(value, valueColumn.source, formatStringProp),\n });\n }\n if (hasHighlights) {\n var highlightValue = valueColumn.highlights[0];\n if (highlightValue != null) {\n tooltipInfo.push({\n displayName: visuals.ToolTipComponent.localizationOptions.highlightedValueDisplayName,\n value: visuals.converterHelper.formatFromMetadataColumn(highlightValue, valueColumn.source, formatStringProp),\n });\n }\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstHighlight ? highlightValue / firstHighlight : null, previousHighlight ? highlightValue / previousHighlight : null, true);\n }\n else {\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstValue ? value / firstValue : null, previousValue ? value / previousValue : null);\n }\n }\n slices.push({\n label: valueMetaData[i].displayName,\n value: value,\n originalValue: value,\n categoryOrMeasureIndex: i,\n identity: identity,\n selected: false,\n key: identity.getKey(),\n tooltipInfo: tooltipInfo,\n color: color,\n labelFill: dataLabelsSettings.labelColor,\n });\n if (hasHighlights) {\n var highlightIdentity = visuals.SelectionId.createWithHighlight(identity);\n var highlight = valueColumn.highlights[0];\n slices.push({\n label: valueMetaData[i].displayName,\n value: value,\n originalValue: value,\n categoryOrMeasureIndex: i,\n identity: highlightIdentity,\n key: highlightIdentity.getKey(),\n selected: false,\n highlight: true,\n originalHighlightValue: highlight,\n highlightValue: highlight,\n tooltipInfo: tooltipInfo,\n color: color,\n });\n previousHighlight = highlight;\n }\n previousValue = value;\n }\n }\n for (var i = 0; i < slices.length; i += hasHighlights ? 2 : 1) {\n var slice = slices[i];\n categoryLabels.push(slice.label);\n }\n // Calculate negative value warning flags\n allValuesAreNegative = slices.length > 0 && _.every(slices, function (slice) { return (slice.highlight ? slice.highlightValue <= 0 : true) && slice.value < 0; });\n for (var _i = 0, slices_1 = slices; _i < slices_1.length; _i++) {\n var slice = slices_1[_i];\n if (allValuesAreNegative) {\n slice.value = Math.abs(slice.value);\n if (slice.highlight)\n slice.highlightValue = Math.abs(slice.highlightValue);\n }\n else {\n var value = slice.value;\n var isValueNegative = value < 0;\n if (isValueNegative)\n slice.value = 0;\n var isHighlightValueNegative = false;\n if (slice.highlight) {\n var highlightValue = slice.highlightValue;\n isHighlightValueNegative = highlightValue < 0;\n slice.highlightValue = isHighlightValueNegative ? 0 : highlightValue;\n }\n if (!hasNegativeValues)\n hasNegativeValues = isValueNegative || isHighlightValueNegative;\n }\n if (slice.highlightValue > slice.value) {\n highlightsOverflow = true;\n }\n }\n return {\n slices: slices,\n categoryLabels: categoryLabels,\n valuesMetadata: valueMetaData,\n hasHighlights: hasHighlights,\n highlightsOverflow: highlightsOverflow,\n canShowDataLabels: true,\n dataLabelsSettings: dataLabelsSettings,\n hasNegativeValues: hasNegativeValues,\n allValuesAreNegative: allValuesAreNegative,\n percentBarLabelSettings: percentBarLabelSettings,\n };\n };\n FunnelChart.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n switch (options.objectName) {\n case 'dataPoint':\n var dataViewCat = this.dataViews && this.dataViews.length > 0 && this.dataViews[0] && this.dataViews[0].categorical;\n var hasGradientRole = visuals.GradientUtils.hasGradientRole(dataViewCat);\n if (!hasGradientRole) {\n this.enumerateDataPoints(enumeration);\n }\n break;\n case 'labels':\n var labelSettingsOptions = FunnelChart.getLabelSettingsOptions(enumeration, this.data.dataLabelsSettings, true, this.labelPositionObjects);\n visuals.dataLabelUtils.enumerateDataLabels(labelSettingsOptions);\n break;\n case 'percentBarLabel':\n var percentLabelSettingOptions = FunnelChart.getLabelSettingsOptions(enumeration, this.data.percentBarLabelSettings, false);\n visuals.dataLabelUtils.enumerateDataLabels(percentLabelSettingOptions);\n break;\n }\n return enumeration.complete();\n };\n FunnelChart.getLabelSettingsOptions = function (enumeration, labelSettings, isDataLabels, positionObject) {\n return {\n enumeration: enumeration,\n dataLabelsSettings: labelSettings,\n show: true,\n displayUnits: isDataLabels,\n precision: isDataLabels,\n position: isDataLabels,\n positionObject: positionObject,\n fontSize: true,\n };\n };\n FunnelChart.prototype.enumerateDataPoints = function (enumeration) {\n var data = this.data;\n if (!data)\n return;\n var slices = data.slices;\n enumeration.pushInstance({\n objectName: 'dataPoint',\n selector: null,\n properties: {\n defaultColor: { solid: { color: this.defaultDataPointColor || this.colors.getColorByIndex(0).value } }\n },\n });\n for (var i = 0; i < slices.length; i++) {\n var slice = slices[i];\n if (slice.highlight)\n continue;\n var color = slice.color;\n var selector = slice.identity.getSelector();\n var isSingleSeries = !!selector.data;\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: slice.label,\n selector: visuals.ColorHelper.normalizeSelector(selector, isSingleSeries),\n properties: {\n fill: { solid: { color: color } }\n },\n });\n }\n };\n FunnelChart.prototype.init = function (options) {\n this.options = options;\n var element = options.element;\n var svg = this.svg = d3.select(element.get(0))\n .append('svg')\n .classed(FunnelChart.VisualClassName, true);\n if (this.behavior)\n this.clearCatcher = visuals.appendClearCatcher(this.svg);\n this.currentViewport = options.viewport;\n this.margin = {\n left: 5,\n right: 5,\n top: 0,\n bottom: 0\n };\n var style = options.style;\n this.colors = style.colorPalette.dataColors;\n this.hostServices = options.host;\n if (this.behavior) {\n this.interactivityService = visuals.createInteractivityService(this.hostServices);\n }\n this.percentGraphicsContext = svg.append('g').classed(FunnelChart.Selectors.percentBar.root.class, true);\n this.funnelGraphicsContext = svg.append('g');\n this.axisGraphicsContext = svg.append('g');\n this.updateViewportProperties();\n };\n FunnelChart.prototype.updateViewportProperties = function () {\n var viewport = this.currentViewport;\n this.svg.attr('width', viewport.width)\n .attr('height', viewport.height);\n };\n FunnelChart.prototype.update = function (options) {\n debug.assertValue(options, 'options');\n this.data = {\n slices: [],\n categoryLabels: [],\n valuesMetadata: [],\n hasHighlights: false,\n highlightsOverflow: false,\n canShowDataLabels: true,\n dataLabelsSettings: visuals.dataLabelUtils.getDefaultFunnelLabelSettings(),\n hasNegativeValues: false,\n allValuesAreNegative: false,\n percentBarLabelSettings: visuals.dataLabelUtils.getDefaultLabelSettings(true),\n };\n var dataViews = this.dataViews = options.dataViews;\n this.currentViewport = options.viewport;\n if (dataViews && dataViews.length > 0) {\n var dataView = dataViews[0];\n if (dataView.metadata && dataView.metadata.objects) {\n var defaultColor = powerbi.DataViewObjects.getFillColor(dataView.metadata.objects, visuals.funnelChartProps.dataPoint.defaultColor);\n if (defaultColor)\n this.defaultDataPointColor = defaultColor;\n }\n if (dataView.categorical) {\n this.data = FunnelChart.converter(dataView, this.colors, this.hostServices, this.defaultDataPointColor, this.tooltipsEnabled);\n if (this.interactivityService) {\n this.interactivityService.applySelectionStateToData(this.data.slices);\n }\n }\n var warnings = visuals.getInvalidValueWarnings(dataViews, false /*supportsNaN*/, false /*supportsNegativeInfinity*/, false /*supportsPositiveInfinity*/);\n if (this.data.allValuesAreNegative) {\n warnings.unshift(new visuals.AllNegativeValuesWarning());\n }\n else if (this.data.hasNegativeValues) {\n warnings.unshift(new visuals.NegativeValuesNotSupportedWarning());\n }\n this.hostServices.setWarnings(warnings);\n }\n this.updateViewportProperties();\n this.updateInternal(options.suppressAnimations);\n };\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\n FunnelChart.prototype.onDataChanged = function (options) {\n this.update({\n dataViews: options.dataViews,\n suppressAnimations: options.suppressAnimations,\n viewport: this.currentViewport\n });\n };\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\n FunnelChart.prototype.onResizing = function (viewport) {\n this.currentViewport = viewport;\n this.update({\n dataViews: this.dataViews,\n suppressAnimations: true,\n viewport: this.currentViewport\n });\n };\n FunnelChart.prototype.getMaxLabelLength = function (labels, properties) {\n var max = 0;\n var textMeasurer = powerbi.TextMeasurementService.measureSvgTextWidth;\n for (var i = 0, len = labels.length; i < len; i++) {\n properties.text = labels[i];\n max = Math.max(max, textMeasurer(properties));\n }\n return max + FunnelChart.LabelFunnelPadding;\n };\n FunnelChart.prototype.updateInternal = function (suppressAnimations) {\n if (this.data == null)\n return;\n var data = this.data;\n var slices = data.slices;\n var slicesWithoutHighlights = slices.filter(function (d) { return !d.highlight; });\n var isHidingPercentBars = this.isHidingPercentBars();\n var axisOptions = this.setUpAxis();\n var margin = axisOptions.margin;\n var funnelContext = this.funnelGraphicsContext.attr('transform', visuals.SVGUtil.translate(margin.left, margin.top));\n this.percentGraphicsContext.attr('transform', visuals.SVGUtil.translate(margin.left, margin.top));\n this.svg.style('font-family', visuals.dataLabelUtils.StandardFontFamily);\n var layout = FunnelChart.getLayout(data, axisOptions);\n var labelLayout = visuals.dataLabelUtils.getFunnelChartLabelLayout(data, axisOptions, FunnelChart.InnerTextMinimumPadding, data.dataLabelsSettings, this.currentViewport);\n var result;\n var shapes;\n var dataLabels;\n if (this.animator && !suppressAnimations) {\n var animationOptions = {\n viewModel: data,\n interactivityService: this.interactivityService,\n layout: layout,\n axisGraphicsContext: this.axisGraphicsContext,\n shapeGraphicsContext: funnelContext,\n percentGraphicsContext: this.percentGraphicsContext,\n labelGraphicsContext: this.svg,\n axisOptions: axisOptions,\n slicesWithoutHighlights: slicesWithoutHighlights,\n labelLayout: labelLayout,\n isHidingPercentBars: isHidingPercentBars,\n visualInitOptions: this.options,\n };\n result = this.animator.animate(animationOptions);\n shapes = result.shapes;\n dataLabels = result.dataLabels;\n }\n if (!this.animator || suppressAnimations || result.failed) {\n FunnelChart.drawDefaultAxis(this.axisGraphicsContext, axisOptions, isHidingPercentBars);\n shapes = FunnelChart.drawDefaultShapes(data, slices, funnelContext, layout, this.interactivityService && this.interactivityService.hasSelection());\n FunnelChart.drawPercentBars(data, this.percentGraphicsContext, layout, isHidingPercentBars);\n if (data.dataLabelsSettings.show && data.canShowDataLabels) {\n dataLabels = visuals.dataLabelUtils.drawDefaultLabelsForFunnelChart(data.slices, this.svg, labelLayout);\n }\n else {\n visuals.dataLabelUtils.cleanDataLabels(this.svg);\n }\n }\n if (this.interactivityService) {\n var interactors = FunnelChart.drawInteractorShapes(slices, funnelContext, layout);\n var behaviorOptions = {\n bars: shapes,\n interactors: interactors,\n clearCatcher: this.clearCatcher,\n hasHighlights: data.hasHighlights,\n };\n this.interactivityService.bind(slices, this.behavior, behaviorOptions);\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(interactors, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n }\n }\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(shapes, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n };\n FunnelChart.prototype.getUsableVerticalSpace = function () {\n var categoryLabels = this.data.categoryLabels;\n var margin = this.margin;\n var verticalSpace = this.currentViewport.height - (margin.top + margin.bottom);\n return verticalSpace - (FunnelChart.MinBarThickness * categoryLabels.length);\n };\n FunnelChart.prototype.isHidingPercentBars = function () {\n var data = this.data;\n if (data.percentBarLabelSettings.show) {\n var percentBarTextHeight = this.getPercentBarTextHeight();\n var verticalSpace = this.getUsableVerticalSpace() - (2 * FunnelChart.MinBarThickness * FunnelChart.PercentBarToBarRatio) - (2 * percentBarTextHeight);\n return verticalSpace <= 0;\n }\n return true;\n };\n FunnelChart.prototype.isSparklines = function () {\n return this.getUsableVerticalSpace() <= 0;\n };\n FunnelChart.prototype.setUpAxis = function () {\n var data = this.data;\n var slices = data.slices;\n var categoryLabels = data.categoryLabels;\n var viewport = this.currentViewport;\n var margin = this.margin;\n var isSparklines = this.isSparklines();\n var isHidingPercentBars = this.isHidingPercentBars();\n var percentBarTextHeight = isHidingPercentBars ? 0 : this.getPercentBarTextHeight();\n var verticalRange = viewport.height - (margin.top + margin.bottom) - (2 * percentBarTextHeight);\n var maxMarginFactor = FunnelChart.MaxMarginFactor;\n if (categoryLabels.length > 0 && isSparklines) {\n categoryLabels = [];\n data.canShowDataLabels = false;\n }\n else if (this.showCategoryLabels()) {\n var textProperties = FunnelChart.getTextProperties();\n // Get the amount of space needed for the labels, then add the minimum level of padding for the axis.\n var longestLabelLength = this.getMaxLabelLength(categoryLabels, textProperties);\n var maxLabelLength = viewport.width * maxMarginFactor;\n var labelLength = Math.min(longestLabelLength, maxLabelLength);\n margin.left = labelLength + FunnelChart.YAxisPadding;\n }\n else {\n categoryLabels = [];\n }\n var horizontalRange = viewport.width - (margin.left + margin.right);\n var barToSpaceRatio = FunnelChart.BarToSpaceRatio;\n var maxScore = d3.max(slices.map(function (d) { return d.value; }));\n if (data.hasHighlights) {\n var maxHighlight = d3.max(slices.map(function (d) { return d.highlightValue; }));\n maxScore = d3.max([maxScore, maxHighlight]);\n }\n var minScore = 0;\n var rangeStart = 0;\n var rangeEnd = verticalRange;\n var delta;\n if (isHidingPercentBars)\n delta = verticalRange - (categoryLabels.length * FunnelChart.MaxBarHeight);\n else\n delta = verticalRange - (categoryLabels.length * FunnelChart.MaxBarHeight) - (2 * FunnelChart.MaxBarHeight * FunnelChart.PercentBarToBarRatio);\n if (categoryLabels.length > 0 && delta > 0) {\n rangeStart = Math.ceil(delta / 2);\n rangeEnd = Math.ceil(verticalRange - delta / 2);\n }\n // Offset funnel axis start and end by percent bar text height\n if (!isHidingPercentBars) {\n rangeStart += percentBarTextHeight;\n rangeEnd += percentBarTextHeight;\n }\n var valueScale = d3.scale.linear()\n .domain([minScore, maxScore])\n .range([horizontalRange, 0]);\n var categoryScale = d3.scale.ordinal()\n .domain(d3.range(0, data.categoryLabels.length))\n .rangeBands([rangeStart, rangeEnd], barToSpaceRatio, isHidingPercentBars ? barToSpaceRatio : FunnelChart.PercentBarToBarRatio);\n return {\n margin: margin,\n valueScale: valueScale,\n categoryScale: categoryScale,\n maxScore: maxScore,\n maxWidth: horizontalRange,\n rangeStart: rangeStart,\n rangeEnd: rangeEnd,\n barToSpaceRatio: barToSpaceRatio,\n categoryLabels: categoryLabels,\n };\n };\n FunnelChart.prototype.getPercentBarTextHeight = function () {\n var percentBarTextProperties = FunnelChart.getTextProperties(this.data.percentBarLabelSettings.fontSize);\n return powerbi.TextMeasurementService.estimateSvgTextHeight(percentBarTextProperties);\n };\n FunnelChart.prototype.onClearSelection = function () {\n if (this.interactivityService)\n this.interactivityService.clearSelection();\n };\n FunnelChart.getLayout = function (data, axisOptions) {\n var highlightsOverflow = data.highlightsOverflow;\n var categoryScale = axisOptions.categoryScale;\n var valueScale = axisOptions.valueScale;\n var maxScore = axisOptions.maxScore;\n var columnHeight = categoryScale.rangeBand();\n var percentBarTickHeight = Math.ceil(columnHeight / 2);\n var overFlowHighlightColumnWidth = columnHeight * FunnelChart.OverflowingHighlightWidthRatio;\n var overFlowHighlightOffset = overFlowHighlightColumnWidth / 2;\n var lastCategoryIndex = axisOptions.categoryLabels.length - 1;\n var horizontalDistance = Math.abs(valueScale(maxScore) - valueScale(0));\n var emptyHorizontalSpace = function (value) { return (horizontalDistance - Math.abs(valueScale(value) - valueScale(0))) / 2; };\n var getMinimumShapeSize = function (value) { return Math.max(FunnelChart.MinimumInteractorSize, Math.abs(valueScale(value) - valueScale(0))); };\n var percentBarFontSize = PixelConverter.fromPoint(data.percentBarLabelSettings.fontSize);\n var percentBarTextProperties = FunnelChart.getTextProperties(data.percentBarLabelSettings.fontSize);\n var baselineDelta = powerbi.TextMeasurementService.estimateSvgTextBaselineDelta(percentBarTextProperties);\n var percentBarYOffset = powerbi.TextMeasurementService.estimateSvgTextHeight(percentBarTextProperties) - baselineDelta;\n return {\n percentBarLayout: {\n mainLine: {\n x2: function (d) { return Math.abs(valueScale(d.value) - valueScale(0)); },\n transform: function (d) {\n var xOffset = valueScale(d.value) - emptyHorizontalSpace(d.value);\n var yOffset = d.isTop\n ? categoryScale(0) - percentBarTickHeight\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight;\n return visuals.SVGUtil.translate(xOffset, yOffset);\n },\n },\n leftTick: {\n y2: function (d) { return percentBarTickHeight; },\n transform: function (d) {\n var xOffset = valueScale(d.value) - emptyHorizontalSpace(d.value);\n var yOffset = d.isTop\n ? categoryScale(0) - percentBarTickHeight - (percentBarTickHeight / 2)\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight - (percentBarTickHeight / 2);\n return visuals.SVGUtil.translate(xOffset, yOffset);\n },\n },\n rightTick: {\n y2: function (d) { return percentBarTickHeight; },\n transform: function (d) {\n var columnOffset = valueScale(d.value) - emptyHorizontalSpace(d.value);\n var columnWidth = Math.abs(valueScale(d.value) - valueScale(0));\n var xOffset = columnOffset + columnWidth;\n var yOffset = d.isTop\n ? categoryScale(0) - percentBarTickHeight - (percentBarTickHeight / 2)\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight - (percentBarTickHeight / 2);\n return visuals.SVGUtil.translate(xOffset, yOffset);\n },\n },\n text: {\n x: function (d) { return Math.ceil((Math.abs(valueScale(maxScore) - valueScale(0)) / 2)); },\n y: function (d) {\n return d.isTop\n ? -percentBarTickHeight / 2 - baselineDelta\n : percentBarYOffset + (percentBarTickHeight / 2);\n },\n style: function () { return (\"font-size: \" + percentBarFontSize + \";\"); },\n transform: function (d) {\n var xOffset = d.isTop\n ? categoryScale(0) - percentBarTickHeight\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight;\n return visuals.SVGUtil.translate(0, xOffset);\n },\n fill: data.percentBarLabelSettings.labelColor,\n maxWidth: horizontalDistance,\n },\n },\n shapeLayout: {\n height: (function (d) { return d.highlight && highlightsOverflow ? overFlowHighlightColumnWidth : columnHeight; }),\n width: function (d) {\n return Math.abs(valueScale(FunnelChart.getFunnelSliceValue(d)) - valueScale(0));\n },\n y: function (d) {\n return categoryScale(d.categoryOrMeasureIndex) + (d.highlight && highlightsOverflow ? overFlowHighlightOffset : 0);\n },\n x: function (d) {\n var value = FunnelChart.getFunnelSliceValue(d);\n return valueScale(value) - emptyHorizontalSpace(value);\n },\n },\n shapeLayoutWithoutHighlights: {\n height: (function (d) { return columnHeight; }),\n width: function (d) {\n return Math.abs(valueScale(d.value) - valueScale(0));\n },\n y: function (d) {\n return categoryScale(d.categoryOrMeasureIndex) + (0);\n },\n x: function (d) {\n return valueScale(d.value) - emptyHorizontalSpace(d.value);\n },\n },\n zeroShapeLayout: {\n height: (function (d) { return d.highlight && highlightsOverflow ? overFlowHighlightColumnWidth : columnHeight; }),\n width: function (d) { return 0; },\n y: function (d) {\n return categoryScale(d.categoryOrMeasureIndex) + (d.highlight && highlightsOverflow ? overFlowHighlightOffset : 0);\n },\n x: function (d) {\n return valueScale((valueScale.domain()[0] + valueScale.domain()[1]) / 2);\n },\n },\n interactorLayout: {\n height: (function (d) { return d.highlight && highlightsOverflow ? overFlowHighlightColumnWidth : columnHeight; }),\n width: function (d) { return getMinimumShapeSize(FunnelChart.getFunnelSliceValue(d)); },\n y: function (d) {\n return categoryScale(d.categoryOrMeasureIndex) + (d.highlight && highlightsOverflow ? overFlowHighlightOffset : 0);\n },\n x: function (d) {\n var size = getMinimumShapeSize(FunnelChart.getFunnelSliceValue(d));\n return (horizontalDistance - size) / 2;\n },\n },\n };\n };\n FunnelChart.drawDefaultAxis = function (graphicsContext, axisOptions, isHidingPercentBars) {\n //Generate ordinal domain\n var indices = d3.range(0, axisOptions.categoryLabels.length);\n var xScaleForAxis = d3.scale.ordinal()\n .domain(indices)\n .rangeBands([axisOptions.rangeStart, axisOptions.rangeEnd], axisOptions.barToSpaceRatio, isHidingPercentBars ? axisOptions.barToSpaceRatio : FunnelChart.PercentBarToBarRatio);\n var xAxis = d3.svg.axis()\n .scale(xScaleForAxis)\n .orient(\"right\")\n .tickPadding(FunnelChart.TickPadding)\n .innerTickSize(FunnelChart.InnerTickSize)\n .ticks(indices.length)\n .tickValues(indices)\n .tickFormat(function (i) { return axisOptions.categoryLabels[i]; }); //To output the category label\n graphicsContext.attr('class', 'axis hideLinesOnAxis')\n .attr('transform', visuals.SVGUtil.translate(0, axisOptions.margin.top))\n .call(xAxis);\n graphicsContext.selectAll('.tick')\n .call(visuals.tooltipUtils.tooltipUpdate, axisOptions.categoryLabels);\n // Subtract the padding from the margin since we can't have text there. Then shorten the labels if necessary.\n var leftRightMarginLimit = axisOptions.margin.left - FunnelChart.LabelFunnelPadding;\n graphicsContext.selectAll('.tick text')\n .call(visuals.AxisHelper.LabelLayoutStrategy.clip, leftRightMarginLimit, powerbi.TextMeasurementService.svgEllipsis);\n };\n FunnelChart.drawDefaultShapes = function (data, slices, graphicsContext, layout, hasSelection) {\n var hasHighlights = data.hasHighlights;\n var columns = graphicsContext.selectAll(FunnelChart.Selectors.funnel.bars.selector).data(slices, function (d) { return d.key; });\n columns.enter()\n .append('rect')\n .attr(\"class\", function (d) { return d.highlight ? FunnelChart.FunnelBarHighlightClass : FunnelChart.Selectors.funnel.bars.class; });\n columns\n .style(\"fill\", function (d) {\n return d.color;\n })\n .style(\"fill-opacity\", function (d) { return function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights); }; })\n .attr(layout.shapeLayout);\n columns.exit().remove();\n return columns;\n };\n FunnelChart.getFunnelSliceValue = function (slice, asOriginal) {\n if (asOriginal === void 0) { asOriginal = false; }\n if (asOriginal)\n return slice.highlight ? slice.originalHighlightValue : slice.originalValue;\n else\n return slice.highlight ? slice.highlightValue : slice.value;\n };\n FunnelChart.drawInteractorShapes = function (slices, graphicsContext, layout) {\n // Draw invsible ineractors for just data points which are below threshold\n var interactorsData = slices.filter(function (d) {\n return !d.highlight && layout.interactorLayout.width(d) === FunnelChart.MinimumInteractorSize;\n });\n var columns = graphicsContext.selectAll(FunnelChart.Selectors.funnel.interactors.selector).data(interactorsData, function (d) { return d.key; });\n columns.enter()\n .append('rect')\n .attr(\"class\", FunnelChart.Selectors.funnel.interactors.class);\n columns\n .style(\"fill-opacity\", 0)\n .attr(layout.interactorLayout);\n columns.exit().remove();\n return columns;\n };\n FunnelChart.drawPercentBarComponents = function (graphicsContext, data, layout, percentLabelSettings) {\n // Main line\n var mainLine = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.mainLine.selector).data(data);\n mainLine.exit().remove();\n mainLine.enter()\n .append('line')\n .classed(FunnelChart.Selectors.percentBar.mainLine.class, true);\n mainLine\n .attr(layout.percentBarLayout.mainLine);\n // Left tick\n var leftTick = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.leftTick.selector).data(data);\n leftTick.exit().remove();\n leftTick.enter()\n .append('line')\n .classed(FunnelChart.Selectors.percentBar.leftTick.class, true);\n leftTick\n .attr(layout.percentBarLayout.leftTick);\n // Right tick\n var rightTick = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.rightTick.selector).data(data);\n rightTick.exit().remove();\n rightTick.enter()\n .append('line')\n .classed(FunnelChart.Selectors.percentBar.rightTick.class, true);\n rightTick\n .attr(layout.percentBarLayout.rightTick);\n // Text\n var text = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.text.selector).data(data);\n var localizedString = visuals.valueFormatter.getLocalizedString(\"Percentage1\");\n text.exit().remove();\n text.enter().append('text').classed(FunnelChart.Selectors.percentBar.text.class, true);\n text\n .attr(layout.percentBarLayout.text)\n .text(function (fp) {\n return visuals.dataLabelUtils.getLabelFormattedText({\n label: fp.percent,\n format: localizedString,\n fontSize: percentLabelSettings.fontSize,\n maxWidth: layout.percentBarLayout.text.maxWidth,\n });\n })\n .append('title').text(function (d) { return powerbi.formattingService.formatValue(d.percent, localizedString); });\n };\n FunnelChart.drawPercentBars = function (data, graphicsContext, layout, isHidingPercentBars) {\n if (isHidingPercentBars || !data.slices || (data.hasHighlights ? data.slices.length / 2 : data.slices.length) < 2) {\n FunnelChart.drawPercentBarComponents(graphicsContext, [], layout, data.percentBarLabelSettings);\n return;\n }\n var slices = [data.slices[data.hasHighlights ? 1 : 0], data.slices[data.slices.length - 1]];\n var baseline = FunnelChart.getFunnelSliceValue(slices[0]);\n if (baseline <= 0) {\n FunnelChart.drawPercentBarComponents(graphicsContext, [], layout, data.percentBarLabelSettings);\n return;\n }\n var percentData = [\n {\n value: FunnelChart.getFunnelSliceValue(slices[0]),\n percent: 1,\n isTop: true,\n },\n {\n value: FunnelChart.getFunnelSliceValue(slices[1]),\n percent: FunnelChart.getFunnelSliceValue(slices[1]) / baseline,\n isTop: false,\n },\n ];\n FunnelChart.drawPercentBarComponents(graphicsContext, percentData, layout, data.percentBarLabelSettings);\n };\n FunnelChart.prototype.showCategoryLabels = function () {\n if (this.funnelSmallViewPortProperties) {\n if ((this.funnelSmallViewPortProperties.hideFunnelCategoryLabelsOnSmallViewPort) && (this.currentViewport.height < this.funnelSmallViewPortProperties.minHeightFunnelCategoryLabelsVisible)) {\n return false;\n }\n }\n return true;\n };\n FunnelChart.addFunnelPercentsToTooltip = function (pctFormatString, tooltipInfo, hostServices, percentOfFirst, percentOfPrevious, highlight) {\n if (percentOfFirst != null) {\n tooltipInfo.push({\n displayName: hostServices.getLocalizedString(\"Funnel_PercentOfFirst\" + (highlight ? \"_Highlight\" : \"\")),\n value: visuals.valueFormatter.format(percentOfFirst, pctFormatString),\n });\n }\n if (percentOfPrevious != null) {\n tooltipInfo.push({\n displayName: hostServices.getLocalizedString(\"Funnel_PercentOfPrevious\" + (highlight ? \"_Highlight\" : \"\")),\n value: visuals.valueFormatter.format(percentOfPrevious, pctFormatString),\n });\n }\n };\n FunnelChart.getTextProperties = function (fontSize) {\n return {\n fontSize: PixelConverter.fromPoint(fontSize || visuals.dataLabelUtils.DefaultFontSizeInPt),\n fontFamily: FunnelChart.DefaultFontFamily,\n };\n };\n FunnelChart.DefaultBarOpacity = 1;\n FunnelChart.DimmedBarOpacity = 0.4;\n FunnelChart.PercentBarToBarRatio = 0.75;\n FunnelChart.TickPadding = 0;\n FunnelChart.InnerTickSize = 0;\n FunnelChart.MinimumInteractorSize = 15;\n FunnelChart.InnerTextClassName = 'labelSeries';\n FunnelChart.Selectors = {\n funnel: {\n bars: createClassAndSelector('funnelBar'),\n highlights: createClassAndSelector('highlight'),\n interactors: createClassAndSelector('funnelBarInteractor'),\n },\n percentBar: {\n root: createClassAndSelector('percentBars'),\n mainLine: createClassAndSelector('mainLine'),\n leftTick: createClassAndSelector('leftTick'),\n rightTick: createClassAndSelector('rightTick'),\n text: createClassAndSelector('value'),\n },\n };\n FunnelChart.FunnelBarHighlightClass = [FunnelChart.Selectors.funnel.bars.class, FunnelChart.Selectors.funnel.highlights.class].join(' ');\n FunnelChart.YAxisPadding = 10;\n FunnelChart.VisualClassName = 'funnelChart';\n FunnelChart.DefaultFontFamily = 'wf_standard-font';\n FunnelChart.BarToSpaceRatio = 0.1;\n FunnelChart.MaxBarHeight = 40;\n FunnelChart.MinBarThickness = 12;\n FunnelChart.LabelFunnelPadding = 6;\n FunnelChart.InnerTextMinimumPadding = 10;\n FunnelChart.OverflowingHighlightWidthRatio = 0.5;\n FunnelChart.MaxMarginFactor = 0.25;\n return FunnelChart;\n }());\n visuals.FunnelChart = FunnelChart;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n /**\n * Renders a number that can be animate change in value.\n */\n var Gauge = (function () {\n function Gauge(options) {\n this.lastAngle = -Math.PI / 2;\n if (options) {\n if (options.gaugeSmallViewPortProperties) {\n this.gaugeSmallViewPortProperties = options.gaugeSmallViewPortProperties;\n }\n this.animator = options.animator;\n this.tooltipsEnabled = options.tooltipsEnabled;\n }\n }\n Gauge.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n switch (options.objectName) {\n case 'axis':\n this.enumerateAxis(enumeration);\n break;\n case 'labels': {\n var labelSettings = this.data ? this.data.dataLabelsSettings : visuals.dataLabelUtils.getDefaultGaugeLabelSettings();\n visuals.dataLabelUtils.enumerateDataLabels(this.getDataLabelSettingsOptions(enumeration, labelSettings));\n break;\n }\n case 'calloutValue': {\n var labelSettings = this.data ? this.data.calloutValueLabelsSettings : visuals.dataLabelUtils.getDefaultGaugeLabelSettings();\n visuals.dataLabelUtils.enumerateDataLabels(this.getDataLabelSettingsOptions(enumeration, labelSettings));\n break;\n }\n case 'dataPoint': {\n this.enumerateDataPoint(enumeration);\n break;\n }\n }\n return enumeration.complete();\n };\n Gauge.prototype.getDataLabelSettingsOptions = function (enumeration, labelSettings) {\n return {\n dataLabelsSettings: labelSettings,\n show: true,\n precision: true,\n displayUnits: true,\n fontSize: true,\n enumeration: enumeration,\n };\n };\n Gauge.prototype.enumerateAxis = function (enumeration) {\n var dataView = this.dataViews[0];\n if (dataView && dataView.metadata) {\n var properties = Gauge.getGaugeObjectsProperties(dataView);\n enumeration.pushInstance({\n selector: null,\n objectName: 'axis',\n properties: properties,\n });\n }\n };\n Gauge.prototype.enumerateDataPoint = function (enumeration) {\n var dataPointSettings = this.data ? this.data.dataPointSettings : Gauge.DefaultDataPointSettings;\n var properties = {};\n properties.fill = { solid: { color: dataPointSettings.fillColor } };\n if (dataPointSettings.targetColor != null) {\n properties.target = { solid: { color: dataPointSettings.targetColor } };\n }\n enumeration.pushInstance({\n selector: null,\n objectName: visuals.gaugeProps.dataPoint.target.objectName,\n properties: properties\n });\n };\n Gauge.getGaugeObjectsProperties = function (dataView) {\n var properties = {};\n var objects = dataView.metadata.objects;\n var hasAxisObject = !!objects && !!objects.axis;\n if (!DataRoleHelper.hasRoleInDataView(dataView, visuals.gaugeRoleNames.minValue))\n properties.min = hasAxisObject ? objects.axis.min : undefined;\n if (!DataRoleHelper.hasRoleInDataView(dataView, visuals.gaugeRoleNames.maxValue))\n properties.max = hasAxisObject ? objects.axis.max : undefined;\n if (!DataRoleHelper.hasRoleInDataView(dataView, visuals.gaugeRoleNames.targetValue))\n properties.target = hasAxisObject ? objects.axis.target : undefined;\n return properties;\n };\n Gauge.prototype.init = function (options) {\n this.element = options.element;\n this.currentViewport = options.viewport;\n this.style = options.style;\n this.options = options;\n this.settings = Gauge.DefaultStyleProperties;\n this.targetSettings = Gauge.DefaultTargetSettings;\n this.setMargins();\n this.color = d3.scale.ordinal().range(this.style.colorPalette.dataColors.getSentimentColors().map(function (color) { return color.value; }));\n this.hostService = options.host;\n var svg = this.svg = d3.select(this.element.get(0)).append('svg');\n svg.classed(Gauge.VisualClassName, true);\n var mainGraphicsContext = this.mainGraphicsContext = svg.append('g');\n mainGraphicsContext.attr('class', Gauge.MainGaugeGroupClassName);\n this.initKpiBands();\n var backgroundArc = this.backgroundArc = d3.svg.arc()\n .innerRadius(0)\n .outerRadius(0)\n .startAngle(-Math.PI / 2)\n .endAngle(Math.PI / 2);\n var foregroundArc = this.foregroundArc = d3.svg.arc()\n .innerRadius(0)\n .outerRadius(0)\n .startAngle(-Math.PI / 2);\n this.backgroundArcPath = mainGraphicsContext.append('path')\n .classed('backgroundArc', true)\n .attr('d', backgroundArc);\n this.foregroundArcPath = mainGraphicsContext.append('path')\n .datum({ endAngle: -Math.PI / 2 })\n .classed('foregroundArc', true)\n .attr('d', foregroundArc);\n var g = this.animatedNumberGrapicsContext = svg.append('g');\n this.animatedNumber = new visuals.AnimatedNumber(g);\n this.animatedNumber.init(options);\n var gaugeDrawingOptions = this.gaugeVisualProperties = this.getGaugeVisualProperties();\n var animatedNumberProperties = this.getAnimatedNumberProperties(gaugeDrawingOptions.radius, gaugeDrawingOptions.innerRadiusFactor, gaugeDrawingOptions.top, gaugeDrawingOptions.left);\n this.animatedNumberGrapicsContext.attr('transform', animatedNumberProperties.transformString);\n this.animatedNumber.onResizing(animatedNumberProperties.viewport);\n };\n Gauge.prototype.update = function (options) {\n debug.assertValue(options, 'options');\n this.currentViewport = options.viewport;\n var dataViews = this.dataViews = options.dataViews;\n if (!dataViews || !dataViews[0]) {\n return;\n }\n this.data = Gauge.converter(dataViews[0], this.tooltipsEnabled);\n this.targetSettings = this.data.targetSettings;\n if (dataViews[0])\n dataViews[0].single = { value: this.data.total };\n // Only show the target label if:\n // 1. There is a target\n // 2. The viewport width is big enough for a target\n // 3. We're showing label text for side numbers\n // 4. Data label settings specify to show\n this.showTargetLabel = this.targetSettings.target != null\n && (this.currentViewport.width > Gauge.MinWidthForTargetLabel || !this.showMinMaxLabelsOnBottom())\n && this.showSideNumbersLabelText()\n && this.data.dataLabelsSettings.show;\n this.setMargins();\n this.gaugeVisualProperties = this.getGaugeVisualProperties();\n this.drawViewPort(this.gaugeVisualProperties);\n this.updateInternal(options.suppressAnimations);\n this.updateCalloutValue(options.suppressAnimations);\n var warnings = visuals.getInvalidValueWarnings(dataViews, false /*supportsNaN*/, false /*supportsNegativeInfinity*/, false /*supportsPositiveInfinity*/);\n this.hostService.setWarnings(warnings);\n };\n Gauge.prototype.updateCalloutValue = function (suppressAnimations) {\n if (this.data.calloutValueLabelsSettings.show) {\n var animatedNumberProperties = this.getAnimatedNumberProperties(this.gaugeVisualProperties.radius, this.gaugeVisualProperties.innerRadiusFactor, this.gaugeVisualProperties.top, this.gaugeVisualProperties.left);\n this.animatedNumberGrapicsContext.attr('transform', animatedNumberProperties.transformString);\n this.animatedNumber.setTextColor(this.data.calloutValueLabelsSettings.labelColor);\n var calloutValue = this.data ? this.data.total : null;\n var formatter = this.getFormatter(this.data.calloutValueLabelsSettings, calloutValue);\n this.animatedNumber.setFormatter(formatter);\n this.animatedNumber.update({\n viewport: animatedNumberProperties.viewport,\n dataViews: this.dataViews,\n suppressAnimations: suppressAnimations,\n });\n this.animatedNumberGrapicsContext.selectAll('title').remove();\n this.animatedNumberGrapicsContext.append('title').text([formatter.format(calloutValue)]);\n }\n else {\n this.animatedNumber.clear();\n this.animatedNumberGrapicsContext.selectAll('title').remove();\n }\n };\n Gauge.prototype.onDataChanged = function (options) {\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\n this.update({\n dataViews: options.dataViews,\n suppressAnimations: options.suppressAnimations,\n viewport: this.currentViewport\n });\n };\n Gauge.prototype.onResizing = function (viewport) {\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\n this.update({\n dataViews: this.dataViews,\n suppressAnimations: true,\n viewMode: 0 /* View */,\n viewport: viewport\n });\n };\n Gauge.getValidSettings = function (targetData) {\n var maxVal = (targetData.max === Gauge.MAX_VALUE) ? Gauge.DEFAULT_MAX : targetData.max;\n var minVal = (targetData.min === Gauge.MIN_VALUE) ? Gauge.DEFAULT_MIN : targetData.min;\n var targetVal = targetData.target;\n return {\n min: minVal,\n max: maxVal,\n target: targetVal\n };\n };\n Gauge.getGaugeData = function (dataView) {\n var settings = {\n max: Gauge.MAX_VALUE,\n min: Gauge.MIN_VALUE,\n target: undefined,\n total: 0,\n tooltipItems: []\n };\n if (dataView && dataView.categorical && dataView.categorical.values && dataView.metadata && dataView.metadata.columns) {\n var values = dataView.categorical.values;\n var metadataColumns = dataView.metadata.columns;\n debug.assert(metadataColumns.length >= values.length, 'length');\n for (var i = 0; i < values.length; i++) {\n var col = metadataColumns[i], value = values[i].values[0] || 0;\n if (col && col.roles) {\n if (col.roles[visuals.gaugeRoleNames.y]) {\n settings.total = value;\n if (value)\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: visuals.converterHelper.formatFromMetadataColumn(value, values[i].source, Gauge.formatStringProp) });\n }\n else if (col.roles[visuals.gaugeRoleNames.minValue]) {\n settings.min = value;\n }\n else if (col.roles[visuals.gaugeRoleNames.maxValue]) {\n settings.max = value;\n }\n else if (col.roles[visuals.gaugeRoleNames.targetValue]) {\n settings.target = value;\n if (value)\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: visuals.converterHelper.formatFromMetadataColumn(value, values[i].source, Gauge.formatStringProp) });\n }\n }\n }\n // Override settings according to property pane axis values\n var gaugeObjectsSettings = Gauge.getGaugeObjectsProperties(dataView);\n if (gaugeObjectsSettings && !$.isEmptyObject(gaugeObjectsSettings))\n Gauge.overrideGaugeSettings(settings, gaugeObjectsSettings);\n }\n else {\n settings.tooltipItems = undefined;\n }\n return settings;\n };\n Gauge.overrideGaugeSettings = function (settings, gaugeObjectsSettings) {\n if ($.isNumeric(gaugeObjectsSettings.min))\n settings.min = gaugeObjectsSettings.min;\n if ($.isNumeric(gaugeObjectsSettings.max))\n settings.max = gaugeObjectsSettings.max;\n if ($.isNumeric(gaugeObjectsSettings.target))\n settings.target = gaugeObjectsSettings.target;\n };\n /** Note: Made public for testability */\n Gauge.converter = function (dataView, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var gaugeData = Gauge.getGaugeData(dataView), total = gaugeData.total, formatString = null, hasPercent = false;\n if (dataView.metadata && !_.isEmpty(dataView.metadata.columns)) {\n formatString = visuals.valueFormatter.getFormatString(dataView.metadata.columns[0], Gauge.formatStringProp, true);\n if (formatString != null)\n hasPercent = visuals.valueFormatter.getFormatMetadata(formatString).hasPercent;\n }\n if (total > 0 && gaugeData.max === Gauge.MAX_VALUE) {\n gaugeData.max = hasPercent ? Gauge.DEFAULT_MAX : total * 2;\n }\n var settings = Gauge.getValidSettings(gaugeData);\n //Checking that the value is plotted inside the gauge boundaries\n var adjustedTotal = Math.max(total, settings.min);\n adjustedTotal = Math.min(adjustedTotal, settings.max);\n var percent = (settings.min !== settings.max)\n ? (adjustedTotal - settings.min) / (settings.max - settings.min)\n : 0;\n var tooltipInfo;\n if (tooltipsEnabled && dataView && gaugeData.tooltipItems != null) {\n tooltipInfo = gaugeData.tooltipItems;\n }\n return {\n percent: percent,\n adjustedTotal: adjustedTotal,\n total: total,\n metadataColumn: Gauge.getMetaDataColumn(dataView),\n targetSettings: settings,\n tooltipInfo: tooltipInfo,\n dataLabelsSettings: Gauge.convertDataLabelSettings(dataView, \"labels\"),\n calloutValueLabelsSettings: Gauge.convertDataLabelSettings(dataView, \"calloutValue\"),\n dataPointSettings: Gauge.convertDataPointSettings(dataView, settings)\n };\n };\n Gauge.convertDataLabelSettings = function (dataview, objectName) {\n var dataViewMetadata = dataview.metadata;\n var dataLabelsSettings = visuals.dataLabelUtils.getDefaultGaugeLabelSettings();\n if (dataViewMetadata) {\n var objects = dataViewMetadata.objects;\n if (objects) {\n // Handle label settings\n var labelsObj = objects[objectName];\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\n }\n }\n return dataLabelsSettings;\n };\n Gauge.convertDataPointSettings = function (dataView, targetSettings) {\n // Default the fill color the the default fill color. Default the target to undefined as it's only used if there's a target.\n var fillColor = Gauge.DefaultDataPointSettings.fillColor;\n var targetColor;\n if (dataView && dataView.metadata && dataView.metadata.objects) {\n // If there is saved metadata, use it for the colors\n var objects = dataView.metadata.objects;\n fillColor = powerbi.DataViewObjects.getFillColor(objects, visuals.gaugeProps.dataPoint.fill, Gauge.DefaultDataPointSettings.fillColor);\n if (targetSettings && (targetSettings.target != null)) {\n targetColor = powerbi.DataViewObjects.getFillColor(objects, visuals.gaugeProps.dataPoint.target, Gauge.DefaultDataPointSettings.targetColor);\n }\n }\n else if (targetSettings && (targetSettings.target != null)) {\n // If there isn't metadata, but a target is set, default to the default target color\n targetColor = Gauge.DefaultDataPointSettings.targetColor;\n }\n return {\n fillColor: fillColor,\n targetColor: targetColor\n };\n };\n Gauge.getMetaDataColumn = function (dataView) {\n if (dataView && dataView.metadata && dataView.metadata.columns) {\n for (var i = 0, ilen = dataView.metadata.columns.length; i < ilen; i++) {\n var column = dataView.metadata.columns[i];\n if (column.isMeasure) {\n return column;\n }\n }\n }\n return null;\n };\n Gauge.prototype.initKpiBands = function () {\n if (!this.settings.kpiBands.show)\n return;\n var kpiArcs = this.kpiArcs = [];\n var kpiArcPaths = this.kpiArcPaths = [];\n var mainGraphicsContext = this.mainGraphicsContext;\n for (var i = 0; i < 3; i++) {\n var arc = d3.svg.arc()\n .innerRadius(0)\n .outerRadius(0)\n .startAngle(0)\n .endAngle(0);\n kpiArcs.push(arc);\n var arcPath = mainGraphicsContext.append('path')\n .attr(\"d\", arc);\n kpiArcPaths.push(arcPath);\n }\n };\n Gauge.prototype.updateKpiBands = function (radius, innerRadiusFactor, tString, kpiAngleAttr) {\n if (!this.settings.kpiBands.show)\n return;\n for (var i = 0; i < kpiAngleAttr.length; i++) {\n this.kpiArcs[i]\n .innerRadius(radius * innerRadiusFactor - (Gauge.KpiBandDistanceFromMainArc + this.settings.kpiBands.thickness))\n .outerRadius(radius * innerRadiusFactor - Gauge.KpiBandDistanceFromMainArc)\n .startAngle(kpiAngleAttr[i].start)\n .endAngle(kpiAngleAttr[i].end);\n this.kpiArcPaths[i]\n .attr('fill', kpiAngleAttr[i].fill)\n .attr('d', this.kpiArcs[i])\n .attr('transform', tString);\n }\n };\n Gauge.prototype.removeTargetElements = function () {\n if (this.targetLine) {\n this.targetLine.remove();\n this.targetText.remove();\n this.targetConnector.remove();\n this.targetLine = this.targetConnector = this.targetText = null;\n }\n };\n Gauge.prototype.getTargetRatio = function () {\n var targetSettings = this.targetSettings;\n var range = targetSettings.max - targetSettings.min;\n if (range !== 0)\n return (targetSettings.target - targetSettings.min) / range;\n return 0;\n };\n Gauge.prototype.updateTargetLine = function (radius, innerRadius, left, top) {\n if (!this.targetLine) {\n this.targetLine = this.mainGraphicsContext.append('line');\n }\n var angle = this.getTargetRatio() * Math.PI;\n var outY = top - radius * Math.sin(angle);\n var outX = left - radius * Math.cos(angle);\n var inY = top - innerRadius * Math.sin(angle);\n var inX = left - innerRadius * Math.cos(angle);\n this.targetLine.attr({\n x1: inX,\n y1: inY,\n x2: outX,\n y2: outY\n });\n };\n /** Note: public for testability */\n Gauge.prototype.getAnimatedNumberProperties = function (radius, innerRadiusFactor, top, left) {\n var boxAngle = Math.PI / 4;\n var scale = 1;\n var innerRadiusOfArc = radius * innerRadiusFactor;\n var innerRadiusForTextBoundingBox = innerRadiusOfArc - (this.settings.kpiBands.show\n ? (Gauge.KpiBandDistanceFromMainArc + this.settings.kpiBands.thickness)\n : 0);\n var innerRCos = innerRadiusForTextBoundingBox * Math.cos(boxAngle);\n var innerRSin = innerRadiusForTextBoundingBox * Math.sin(boxAngle);\n var innerY = top - innerRSin;\n var innerX = left - innerRCos;\n innerY = innerY * scale;\n innerX = innerX * scale;\n var animatedNumberWidth = innerRCos * 2;\n var properties = {\n transformString: visuals.SVGUtil.translate(innerX, innerY),\n viewport: { height: innerRSin, width: animatedNumberWidth }\n };\n return properties;\n };\n /** Note: public for testability */\n Gauge.prototype.getGaugeVisualProperties = function () {\n var viewport = this.currentViewport;\n var margin = this.margin;\n var width = viewport.width - margin.right - margin.left;\n var halfWidth = width / 2;\n var height = viewport.height - margin.top - margin.bottom;\n var radius = Math.min(halfWidth, height);\n var innerRadiusFactor = Gauge.InnerRadiusFactor;\n var left = margin.left + halfWidth;\n var top = radius + (height - radius) / 2 + margin.top;\n var tString = visuals.SVGUtil.translate(left, top);\n var innerRadiusOfArc = radius * innerRadiusFactor;\n var gaugeData = {\n radius: radius,\n innerRadiusOfArc: innerRadiusOfArc,\n left: left,\n top: top,\n height: height,\n width: width,\n margin: margin,\n transformString: tString,\n innerRadiusFactor: innerRadiusFactor\n };\n return gaugeData;\n };\n /** Note: public for testability */\n Gauge.prototype.drawViewPort = function (drawOptions) {\n debug.assertAnyValue(drawOptions, \"Gauge options\");\n var separation = this.settings.kpiBands.separationRadians;\n var innerRadiusFactor = Gauge.InnerRadiusFactor;\n var backgroudArc = this.backgroundArc;\n var color = this.color;\n var attrs = [{\n fill: color(0),\n start: -Math.PI / 2,\n end: -Math.PI / 2 + Math.PI / 4 - separation\n }, {\n fill: color(1),\n start: -Math.PI / 2 + Math.PI * 1 / 4 + separation,\n end: -Math.PI / 2 + Math.PI * 3 / 4 - separation\n }, {\n fill: color(2),\n start: -Math.PI / 2 + Math.PI * 3 / 4 + separation,\n end: Math.PI / 2\n }];\n var radius = drawOptions.radius;\n var transformString = drawOptions.transformString;\n this.updateKpiBands(radius, innerRadiusFactor, transformString, attrs);\n backgroudArc\n .innerRadius(radius * innerRadiusFactor)\n .outerRadius(radius)\n .startAngle(-Math.PI / 2)\n .endAngle(Math.PI / 2);\n this.backgroundArcPath\n .attr(\"d\", backgroudArc)\n .attr(\"transform\", transformString);\n var foregroundArc = this.foregroundArc;\n foregroundArc\n .innerRadius(radius * innerRadiusFactor)\n .outerRadius(radius)\n .startAngle(-Math.PI / 2);\n this.foregroundArcPath\n .datum({ endAngle: this.lastAngle })\n .attr(\"transform\", transformString)\n .attr(\"d\", foregroundArc);\n var innerRadiusOfArc = drawOptions.innerRadiusOfArc;\n var left = drawOptions.left;\n var top = drawOptions.top;\n var margin = drawOptions.margin;\n var height = drawOptions.height;\n var targetSettings = this.targetSettings;\n if (!this.settings.targetLine.show || targetSettings.target == null) {\n this.removeTargetElements();\n }\n else {\n if (targetSettings.min > targetSettings.target || targetSettings.max < targetSettings.target) {\n this.removeTargetElements();\n }\n else {\n this.updateTargetLine(radius, innerRadiusOfArc, left, top);\n this.appendTargetTextAlongArc(radius, height, drawOptions.width, margin);\n }\n }\n this.svg.attr('height', this.currentViewport.height).attr('width', this.currentViewport.width);\n };\n Gauge.prototype.createTicks = function () {\n var settings = this.settings;\n var targetSettings = this.targetSettings;\n var total = targetSettings.max - targetSettings.min;\n var numberOfLabels = settings.labels.count;\n var step = total / numberOfLabels;\n var arr = [];\n var formatter = this.getFormatter(this.data.dataLabelsSettings, targetSettings.max);\n for (var i = 0; i < numberOfLabels + 1; i++) {\n arr.push(formatter.format(targetSettings.min + (i * step)));\n }\n return arr;\n };\n Gauge.prototype.updateInternal = function (suppressAnimations) {\n var height = this.gaugeVisualProperties.height;\n var width = this.gaugeVisualProperties.width;\n var radius = this.gaugeVisualProperties.radius;\n var margin = this.margin;\n var duration = visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n var data = this.data;\n var lastAngle = this.lastAngle = -Math.PI / 2 + Math.PI * data.percent;\n var ticks = this.createTicks();\n this.foregroundArcPath\n .transition()\n .ease(this.settings.transition.ease)\n .duration(duration)\n .call(this.arcTween, [lastAngle, this.foregroundArc]);\n this.appendTextAlongArc(ticks, radius, height, width, margin);\n this.updateVisualConfigurations();\n this.updateVisualStyles();\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(this.foregroundArcPath, function (tooltipEvent) { return data.tooltipInfo; });\n visuals.TooltipManager.addTooltip(this.backgroundArcPath, function (tooltipEvent) { return data.tooltipInfo; });\n }\n };\n Gauge.prototype.updateVisualStyles = function () {\n var fillColor = this.data.dataLabelsSettings.labelColor || this.style.labelText.color.value;\n this.mainGraphicsContext.selectAll('text')\n .style({\n 'fill': fillColor,\n });\n };\n Gauge.prototype.updateVisualConfigurations = function () {\n var configOptions = this.settings;\n var dataPointSettings = this.data.dataPointSettings;\n this.mainGraphicsContext\n .select('line')\n .attr({\n stroke: dataPointSettings.targetColor,\n 'stroke-width': configOptions.targetLine.thickness,\n });\n this.backgroundArcPath.style('fill', configOptions.arcColors.background);\n this.foregroundArcPath.style('fill', dataPointSettings.fillColor);\n };\n Gauge.prototype.appendTextAlongArc = function (ticks, radius, height, width, margin) {\n this.svg.selectAll(Gauge.LabelText.selector).remove();\n if (!this.data.dataLabelsSettings.show)\n return;\n var total = ticks.length;\n var divisor = total - 1;\n var top = (radius + (height - radius) / 2 + margin.top);\n var showMinMaxLabelsOnBottom = this.showMinMaxLabelsOnBottom();\n var fontSize = PixelConverter.fromPoint(this.data.dataLabelsSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt);\n var padding = this.settings.labels.padding;\n for (var count = 0; count < total; count++) {\n var textProperties = {\n text: ticks[count],\n fontFamily: visuals.dataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: visuals.dataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: visuals.dataLabelUtils.LabelTextProperties.fontWeight,\n };\n if (Math.floor(total / 2) === count)\n continue; // Skip Middle label, by design\n if (this.showSideNumbersLabelText()) {\n var x = (margin.left + width / 2) - (radius * Math.cos(Math.PI * count / divisor));\n var y = top - (radius * Math.sin(Math.PI * count / divisor));\n var anchor = void 0;\n var onRight = count * 2 > total;\n var onBottom = false;\n if (showMinMaxLabelsOnBottom && (count === 0 || count === total - 1)) {\n // If this is a min or max label and we're showing them on the bottom rather than the sides\n // Adjust the label display properties to appear under the arc\n onBottom = true;\n y += padding / 2;\n // Align the labels with the outer edge of the arc\n anchor = onRight ? 'end' : 'start';\n textProperties.text = powerbi.TextMeasurementService.getTailoredTextOrDefault(textProperties, radius);\n }\n else {\n // For all other labels, display around the arc\n anchor = onRight ? 'start' : 'end';\n x += padding * (onRight ? 1 : -1);\n }\n var text = this.mainGraphicsContext\n .append('text')\n .attr({\n 'x': x,\n 'y': y,\n 'dy': onBottom ? fontSize : 0,\n 'class': Gauge.LabelText.class\n })\n .style({\n 'text-anchor': anchor,\n 'font-size': fontSize\n })\n .text(textProperties.text)\n .append('title').text(textProperties.text);\n if (!onBottom)\n this.truncateTextIfNeeded(text, x, onRight);\n }\n }\n };\n Gauge.prototype.truncateTextIfNeeded = function (text, positionX, onRight) {\n var availableSpace = (onRight ? this.currentViewport.width - positionX : positionX);\n text.call(visuals.AxisHelper.LabelLayoutStrategy.clip, availableSpace, powerbi.TextMeasurementService.svgEllipsis);\n };\n Gauge.prototype.getFormatter = function (dataLabelSettings, value2) {\n var realValue2 = dataLabelSettings.displayUnits === 0 ? value2 : null;\n var formatString = visuals.valueFormatter.getFormatString(this.data.metadataColumn, Gauge.formatStringProp);\n var precision = visuals.dataLabelUtils.getLabelPrecision(dataLabelSettings.precision, formatString);\n var valueFormatterOptions = visuals.dataLabelUtils.getOptionsForLabelFormatter(dataLabelSettings, formatString, realValue2, precision);\n valueFormatterOptions.formatSingleValues = dataLabelSettings.displayUnits > 0 ? false : true;\n return visuals.valueFormatter.create(valueFormatterOptions);\n };\n Gauge.prototype.appendTargetTextAlongArc = function (radius, height, width, margin) {\n var targetSettings = this.targetSettings;\n var target = targetSettings.target;\n var tRatio = this.getTargetRatio();\n var top = (radius + (height - radius) / 2 + margin.top);\n var flag = tRatio > 0.5;\n var padding = this.settings.labels.padding;\n var anchor = flag ? 'start' : 'end';\n var formatter = this.getFormatter(this.data.dataLabelsSettings, targetSettings.max);\n var maxRatio = Math.asin(Gauge.MinDistanceFromBottom / radius) / Math.PI;\n var finalRatio = tRatio < maxRatio || tRatio > (1 - maxRatio)\n ? flag\n ? 1 - maxRatio\n : maxRatio\n : tRatio;\n var targetX = (margin.left + width / 2) - ((radius + padding) * Math.cos(Math.PI * finalRatio));\n var targetY = top - ((radius + padding) * Math.sin(Math.PI * finalRatio));\n if (!this.targetText) {\n this.targetText = this.mainGraphicsContext\n .append('text')\n .classed(Gauge.TargetText.class, true);\n }\n this.targetText\n .attr({\n 'x': targetX,\n 'y': targetY,\n })\n .style({\n 'text-anchor': anchor,\n 'display': this.showTargetLabel ? '' : 'none',\n 'font-size': this.style.labelText.fontSize\n })\n .text(formatter.format(target));\n this.truncateTextIfNeeded(this.targetText, targetX, flag);\n this.targetText.call(visuals.tooltipUtils.tooltipUpdate, [formatter.format(target)]);\n if (!this.targetConnector) {\n this.targetConnector = this.mainGraphicsContext\n .append('line')\n .classed(Gauge.TargetConnector.class, true);\n }\n // Hide the target connector if the text is going to align with the target line in the arc\n // It should only be shown if the target text is displaced (ex. when the target is very close to min/max)\n if (tRatio === finalRatio) {\n this.targetConnector.style('display', 'none');\n }\n else {\n this.targetConnector\n .attr({\n 'x1': (margin.left + width / 2) - (radius * Math.cos(Math.PI * tRatio)),\n 'y1': top - (radius * Math.sin(Math.PI * tRatio)),\n 'x2': targetX,\n 'y2': targetY\n })\n .style({\n 'stroke-width': this.settings.targetLine.thickness,\n 'stroke': this.settings.targetLine.color,\n 'display': ''\n });\n }\n };\n Gauge.prototype.arcTween = function (transition, arr) {\n transition.attrTween('d', function (d) {\n var interpolate = d3.interpolate(d.endAngle, arr[0]);\n return function (t) {\n d.endAngle = interpolate(t);\n return arr[1](d);\n };\n });\n };\n Gauge.prototype.showMinMaxLabelsOnBottom = function () {\n // More vertical space, put labels on bottom\n if (this.currentViewport.height > this.currentViewport.width)\n return true;\n // We want to show the start/end ticks on the bottom when there\n // is insufficient space for the left and right label text\n if (this.data && this.gaugeVisualProperties) {\n var ticks = this.createTicks();\n var visualWhitespace = (this.currentViewport.width - (this.gaugeVisualProperties.radius * 2)) / 2;\n var maxLabelWidth = visualWhitespace - this.settings.labels.padding;\n var textProperties = powerbi.TextMeasurementService.getMeasurementProperties($(this.svg.node()));\n textProperties.fontSize = PixelConverter.fromPoint(this.data.dataLabelsSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt);\n var width = void 0;\n for (var _i = 0, _a = [ticks[0], ticks[ticks.length - 1]]; _i < _a.length; _i++) {\n var tickValue = _a[_i];\n textProperties.text = tickValue;\n width = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n if (width > maxLabelWidth)\n return true;\n }\n }\n return false;\n };\n Gauge.prototype.setMargins = function () {\n if (this.gaugeSmallViewPortProperties) {\n if (this.gaugeSmallViewPortProperties.smallGaugeMarginsOnSmallViewPort && (this.currentViewport.height < this.gaugeSmallViewPortProperties.MinHeightGaugeSideNumbersVisible)) {\n var margins = this.gaugeSmallViewPortProperties.GaugeMarginsOnSmallViewPort;\n this.margin = { top: margins, bottom: margins, left: margins, right: margins };\n return;\n }\n }\n this.margin = {\n top: Gauge.DefaultTopBottomMargin,\n bottom: Gauge.DefaultTopBottomMargin,\n left: Gauge.DefaultLeftRightMargin,\n right: Gauge.DefaultLeftRightMargin\n };\n // If we're not showing side labels, reduce the margin so that the gauge has more room to display\n if (!this.showSideNumbersLabelText() || this.showMinMaxLabelsOnBottom()) {\n var targetSettings = this.targetSettings;\n if (this.showTargetLabel) {\n // If we're showing the target label, only reduce the margin on the side that doesn't have a target label\n var tRatio = (targetSettings.target - targetSettings.min) / (targetSettings.max - targetSettings.min);\n if (tRatio > 0.5)\n this.margin.left = Gauge.ReducedLeftRightMargin;\n else\n this.margin.right = Gauge.ReducedLeftRightMargin;\n }\n else {\n // Otherwise, reduce both margins\n this.margin.left = this.margin.right = Gauge.ReducedLeftRightMargin;\n }\n }\n var fontSize = 0;\n if (this.data && this.data.dataLabelsSettings && this.data.dataLabelsSettings.fontSize && this.data.dataLabelsSettings.fontSize >= visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt) {\n fontSize = PixelConverter.fromPointToPixel(this.data.dataLabelsSettings.fontSize - visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt);\n }\n if (fontSize !== 0) {\n this.margin.bottom += fontSize;\n this.margin.left += fontSize;\n this.margin.right += fontSize;\n }\n };\n Gauge.prototype.showSideNumbersLabelText = function () {\n if (this.gaugeSmallViewPortProperties) {\n if (this.gaugeSmallViewPortProperties.hideGaugeSideNumbersOnSmallViewPort) {\n if (this.currentViewport.height < this.gaugeSmallViewPortProperties.MinHeightGaugeSideNumbersVisible) {\n return false;\n }\n }\n }\n return true;\n };\n Gauge.MIN_VALUE = -Infinity;\n Gauge.MAX_VALUE = +Infinity;\n Gauge.MinDistanceFromBottom = 10;\n Gauge.MinWidthForTargetLabel = 150;\n Gauge.DefaultTopBottomMargin = 20;\n Gauge.DefaultLeftRightMargin = 45;\n Gauge.ReducedLeftRightMargin = 15;\n Gauge.DEFAULT_MAX = 1;\n Gauge.DEFAULT_MIN = 0;\n Gauge.VisualClassName = 'gauge';\n Gauge.DefaultStyleProperties = {\n transition: {\n ease: 'bounce'\n },\n arcColors: {\n background: '#e9e9e9',\n foreground: '#00B8AA'\n },\n targetLine: {\n show: true,\n color: '#666666',\n thickness: 2\n },\n labels: {\n count: 2,\n padding: 5,\n fontSize: visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt,\n },\n kpiBands: {\n show: false,\n separationRadians: Math.PI / 128,\n thickness: 5\n },\n };\n Gauge.DefaultTargetSettings = {\n min: 0,\n max: 1,\n target: undefined\n };\n Gauge.DefaultDataPointSettings = {\n fillColor: Gauge.DefaultStyleProperties.arcColors.foreground,\n targetColor: Gauge.DefaultStyleProperties.targetLine.color\n };\n Gauge.InnerRadiusFactor = 0.7;\n Gauge.KpiBandDistanceFromMainArc = 2;\n Gauge.MainGaugeGroupClassName = 'mainGroup';\n Gauge.LabelText = createClassAndSelector('labelText');\n Gauge.TargetConnector = createClassAndSelector('targetConnector');\n Gauge.TargetText = createClassAndSelector('targetText');\n /** Note: Public for testability */\n Gauge.formatStringProp = {\n objectName: 'general',\n propertyName: 'formatString',\n };\n return Gauge;\n }());\n visuals.Gauge = Gauge;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Utility = jsCommon.Utility;\n var ImageVisual = (function () {\n function ImageVisual() {\n this.scalingType = visuals.imageScalingType.normal;\n }\n ImageVisual.prototype.init = function (options) {\n this.element = options.element;\n };\n ImageVisual.prototype.enumerateObjectInstances = function (options) {\n switch (options.objectName) {\n case 'imageScaling':\n return this.enumerateImageScaling();\n }\n return null;\n };\n ImageVisual.prototype.enumerateImageScaling = function () {\n return [{\n selector: null,\n objectName: 'imageScaling',\n properties: {\n imageScalingType: this.scalingType,\n }\n }];\n };\n ImageVisual.prototype.update = function (options) {\n var dataViews = options.dataViews;\n if (!dataViews || dataViews.length === 0)\n return;\n var objects = dataViews[0].metadata.objects;\n if (!objects || !objects.general)\n return;\n var div = this.imageBackgroundElement;\n if (!div) {\n div = $(\"<div class='imageBackground' />\");\n this.imageBackgroundElement = div;\n this.imageBackgroundElement.appendTo(this.element);\n }\n var viewport = options.viewport;\n div.css('height', viewport.height);\n if (objects.imageScaling)\n this.scalingType = objects.imageScaling.imageScalingType.toString();\n else\n this.scalingType = visuals.imageScalingType.normal;\n var imageUrl = objects.general.imageUrl;\n if (Utility.isLocalUrl(imageUrl))\n div.css(\"backgroundImage\", \"url(\" + imageUrl + \")\");\n if (this.scalingType === visuals.imageScalingType.fit)\n div.css(\"background-size\", \"100% 100%\");\n else if (this.scalingType === visuals.imageScalingType.fill)\n div.css(\"background-size\", \"cover\");\n else\n div.css(\"background-size\", \"contain\");\n };\n return ImageVisual;\n }());\n visuals.ImageVisual = ImageVisual;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n var KPIStatusWithHistory = (function () {\n function KPIStatusWithHistory() {\n }\n KPIStatusWithHistory.prototype.init = function (options) {\n KPIStatusWithHistory.getLocalizedString = options.host.getLocalizedString;\n this.rootElement = d3.select(options.element.get(0)).append('div').attr('text-align', 'center').classed('kpiVisual', true);\n this.svg = this.rootElement.append('svg');\n var mainGroupElement = this.mainGroupElement = this.svg.append('g');\n this.areaFill = mainGroupElement.append(\"path\");\n this.textContainer = this.rootElement.append(\"div\").classed('textContainer', true);\n this.indicatorTextContainer = this.textContainer.append(\"div\").classed('indicatorText', true);\n this.absoluteGoalDistanceText = this.textContainer.append(\"div\").classed('goalText', true);\n this.kpiActualText = this.indicatorTextContainer.append(\"div\").attr('id', 'indicatorText');\n this.initIcons();\n this.host = options.host;\n };\n KPIStatusWithHistory.prototype.update = function (options) {\n if (!options.dataViews || !options.dataViews[0])\n return;\n var dataView = this.dataView = options.dataViews[0];\n var viewport = options.viewport;\n // We must have at least one measure\n if ((!dataView.categorical || !dataView.categorical.values || dataView.categorical.values.length < 1) &&\n (!dataView.categorical || !dataView.categorical.categories || dataView.categorical.categories.length < 1)) {\n this.svg.attr(\"visibility\", \"hidden\");\n this.textContainer.attr(\"style\", \"display:none\");\n return;\n }\n this.svg.attr(\"visibility\", \"visible\");\n var kpiViewModel = KPIStatusWithHistory.converter(dataView, viewport, KPIStatusWithHistory.getProp_KPIDirection(dataView));\n this.render(kpiViewModel, viewport);\n };\n KPIStatusWithHistory.prototype.initIcons = function () {\n this.successMarkIcon = this.indicatorTextContainer.append(\"div\").classed('powervisuals-glyph checkmark kpi-visual-green', true);\n this.betweenIcon = this.indicatorTextContainer.append('div').classed('powervisuals-glyph circle-small kpi-visual-yellow', true);\n this.exclamationMarkIcon = this.indicatorTextContainer.append(\"div\").classed('powervisuals-glyph exclamation kpi-visual-red', true);\n this.successMarkIcon.attr('style', 'display:none');\n this.betweenIcon.attr('style', 'display:none');\n this.exclamationMarkIcon.attr('style', 'display:none');\n };\n KPIStatusWithHistory.prototype.render = function (kpiViewModel, viewport) {\n this.setShowDataMissingWarning(!(kpiViewModel.indicatorExists && kpiViewModel.trendExists));\n if (kpiViewModel.dataPoints.length === 0 || !kpiViewModel.indicatorExists || !kpiViewModel.trendExists) {\n this.areaFill.attr(\"visibility\", \"hidden\");\n this.svg.attr(\"visibility\", \"hidden\");\n this.textContainer.attr(\"style\", \"display:none\");\n return;\n }\n this.svg.attr({\n 'height': viewport.height,\n 'width': viewport.width,\n });\n var status = KPIStatusWithHistory.status.NOGOAL;\n if (kpiViewModel.targetExists && kpiViewModel.indicatorExists && kpiViewModel.trendExists) {\n status = GetStatus(kpiViewModel.actual, kpiViewModel.goals, kpiViewModel.directionType);\n }\n var actualText = kpiViewModel.formattedValue;\n var calculatedHeight = KPIStatusWithHistory.indicatorTextSizeInPx;\n this.textContainer\n .attr('style', \"width:\" + viewport.width + \"px;\" +\n \"top:\" + ((viewport.height - calculatedHeight) / 2) + \"px\");\n this.kpiActualText\n .classed(KPIStatusWithHistory.allColorClasses, false)\n .classed(GetTextColorClassByStatus(status), true)\n .attr(\"text-anchor\", \"middle\")\n .text(actualText);\n var icon = null;\n switch (status) {\n case KPIStatusWithHistory.status.INCREASE:\n icon = this.successMarkIcon;\n this.exclamationMarkIcon.attr(\"style\", \"display:none\");\n this.betweenIcon.attr(\"style\", \"display:none\");\n break;\n case KPIStatusWithHistory.status.IN_BETWEEN:\n icon = this.betweenIcon;\n this.exclamationMarkIcon.attr(\"style\", \"display:none\");\n this.successMarkIcon.attr(\"style\", \"display:none\");\n break;\n case KPIStatusWithHistory.status.DROP:\n icon = this.exclamationMarkIcon;\n this.successMarkIcon.attr(\"style\", \"display:none\");\n this.betweenIcon.attr(\"style\", \"display:none\");\n break;\n default:\n this.exclamationMarkIcon.attr(\"style\", \"display:none\");\n this.successMarkIcon.attr(\"style\", \"display:none\");\n this.betweenIcon.attr(\"style\", \"display:none\");\n }\n if (icon) {\n icon.attr('style', 'font-size:12px');\n }\n var shownGoalString = kpiViewModel.showGoal ? kpiViewModel.formattedGoalString + \" \" : \"\";\n var shownDistanceFromGoalString = kpiViewModel.showDistanceFromGoal ? getDistanceFromGoalInPercentageString(kpiViewModel.actual, kpiViewModel.goals, kpiViewModel.directionType) : \"\";\n this.absoluteGoalDistanceText\n .attr(\"text-anchor\", \"middle\")\n .text(shownGoalString + shownDistanceFromGoalString);\n if (kpiViewModel.showTrendLine && kpiViewModel.historyExists) {\n var area = d3.svg.area()\n .x(function (d) { return d.x; })\n .y0(viewport.height)\n .y1(function (d) { return d.y; });\n this.areaFill\n .classed(KPIStatusWithHistory.allColorClasses, false)\n .classed(GetGraphColorClassByStatus(status), true)\n .attr(\"d\", area(kpiViewModel.dataPoints))\n .attr(\"stroke\", \"none\")\n .attr(\"visibility\", \"visible\")\n .attr('fill-opacity', 0.2);\n }\n else {\n this.areaFill.attr(\"visibility\", \"hidden\");\n }\n };\n KPIStatusWithHistory.prototype.setShowDataMissingWarning = function (show) {\n this.host.setWarnings(show ? [new visuals.VisualKPIDataMissingWarning()] : []);\n };\n KPIStatusWithHistory.getDefaultFormatSettings = function () {\n return {\n labelSettings: visuals.dataLabelUtils.getDefaultLabelSettings(true, visuals.Card.DefaultStyle.value.color),\n textSize: 27,\n wordWrap: false\n };\n };\n KPIStatusWithHistory.getFormatString = function (column) {\n debug.assertAnyValue(column, 'column');\n return visuals.valueFormatter.getFormatString(column, visuals.AnimatedText.formatStringProp);\n };\n KPIStatusWithHistory.getProp_Show_KPIGoal = function (dataView) {\n if (dataView && dataView.metadata) {\n return powerbi.DataViewObjects.getValue(dataView.metadata.objects, KPIStatusWithHistory.showKPIGoal, true);\n }\n return true;\n };\n KPIStatusWithHistory.getProp_Show_KPITrendLine = function (dataView) {\n if (dataView && dataView.metadata) {\n return powerbi.DataViewObjects.getValue(dataView.metadata.objects, KPIStatusWithHistory.showKPITrendLine, true);\n }\n return true;\n };\n KPIStatusWithHistory.getProp_Show_KPIDistance = function (dataView) {\n if (dataView && dataView.metadata) {\n return powerbi.DataViewObjects.getValue(dataView.metadata.objects, KPIStatusWithHistory.showKPIDistance, true);\n }\n return true;\n };\n KPIStatusWithHistory.getProp_KPIDirection = function (dataView) {\n if (dataView && dataView.metadata) {\n return powerbi.DataViewObjects.getValue(dataView.metadata.objects, KPIStatusWithHistory.directionTypeStringProp, visuals.kpiDirection.positive);\n }\n return visuals.kpiDirection.positive;\n };\n KPIStatusWithHistory.getProp_Indicator_DisplayUnits = function (dataView) {\n KPIStatusWithHistory.initDefaultLabelSettings();\n if (dataView && dataView.metadata) {\n return powerbi.DataViewObjects.getValue(dataView.metadata.objects, KPIStatusWithHistory.indicatorDisplayUnitsProp, KPIStatusWithHistory.defaultLabelSettings.displayUnits);\n }\n return KPIStatusWithHistory.defaultLabelSettings.displayUnits;\n };\n KPIStatusWithHistory.getProp_Indicator_Precision = function (dataView) {\n KPIStatusWithHistory.initDefaultLabelSettings();\n if (dataView && dataView.metadata) {\n return powerbi.DataViewObjects.getValue(dataView.metadata.objects, KPIStatusWithHistory.indicatorPrecisionProp, KPIStatusWithHistory.defaultLabelSettings.precision);\n }\n return KPIStatusWithHistory.defaultLabelSettings.precision;\n };\n KPIStatusWithHistory.initDefaultLabelSettings = function () {\n if (!KPIStatusWithHistory.defaultCardFormatSetting) {\n KPIStatusWithHistory.defaultCardFormatSetting = KPIStatusWithHistory.getDefaultFormatSettings();\n KPIStatusWithHistory.defaultLabelSettings = KPIStatusWithHistory.defaultCardFormatSetting.labelSettings;\n }\n };\n KPIStatusWithHistory.getFormattedValue = function (metaDataColumn, theValue, precision, displayUnits, displayUnitSystemType) {\n if (displayUnitSystemType === void 0) { displayUnitSystemType = powerbi.DisplayUnitSystemType.WholeUnits; }\n var isDefaultDisplayUnit = displayUnits === 0;\n var formatter = visuals.valueFormatter.create({\n format: KPIStatusWithHistory.getFormatString(metaDataColumn),\n value: displayUnits,\n precision: precision,\n displayUnitSystemType: displayUnitSystemType,\n formatSingleValues: isDefaultDisplayUnit ? true : false,\n allowFormatBeautification: true,\n columnType: metaDataColumn ? metaDataColumn.type : undefined\n });\n return formatter.format(theValue);\n };\n KPIStatusWithHistory.getFormattedGoalString = function (metaDataColumn, goals, precision, displayUnits) {\n if (!goals || goals.length === 0) {\n return \"\";\n }\n var goalsString = KPIStatusWithHistory.getLocalizedString('Visual_KPI_Goal_Title') + \": \" + KPIStatusWithHistory.getFormattedValue(metaDataColumn, goals[0], precision, displayUnits);\n if (goals.length === 2) {\n goalsString += \", \" + KPIStatusWithHistory.getFormattedValue(metaDataColumn, goals[1], precision, displayUnits);\n }\n return goalsString;\n };\n KPIStatusWithHistory.converter = function (dataView, viewPort, directionType) {\n var dataPoints = [];\n var catDv = dataView.categorical;\n var indicatorMetadataColumn = null;\n var goalMetadataColumn = null;\n var formattedGoalString = \"\";\n var formattedValue = \"\";\n var targetExists = false;\n var indicatorExists = false;\n var trendExists = false;\n var historyExists = true;\n if (!dataView.categorical.categories) {\n historyExists = false;\n }\n var values = catDv.values;\n var columns = dataView.metadata.columns;\n for (var _i = 0, columns_2 = columns; _i < columns_2.length; _i++) {\n var column = columns_2[_i];\n if (DataRoleHelper.hasRole(column, 'Indicator')) {\n indicatorExists = true;\n indicatorMetadataColumn = column;\n }\n if (DataRoleHelper.hasRole(column, 'TrendLine')) {\n trendExists = true;\n }\n if (DataRoleHelper.hasRole(column, 'Goal')) {\n targetExists = true;\n goalMetadataColumn = column;\n }\n }\n if (!indicatorExists || !trendExists || !values || values.length === 0 || !values[0].values || !dataView.categorical.values) {\n return {\n dataPoints: dataPoints,\n directionType: directionType,\n actual: 0,\n goals: [],\n formattedGoalString: formattedGoalString,\n targetExists: targetExists,\n historyExists: historyExists,\n indicatorExists: indicatorExists,\n trendExists: trendExists,\n formattedValue: formattedValue,\n showGoal: false,\n showDistanceFromGoal: false,\n showTrendLine: false\n };\n }\n var category, categoryValues;\n if (historyExists) {\n category = catDv.categories[0]; // This only works if we have a category axis\n categoryValues = category.values;\n }\n var historyActualData = [];\n var historyGoalData = [];\n var indicatorColumns = KPIStatusWithHistory.getColumnsByRole(values, \"Indicator\");\n var goalColumns = KPIStatusWithHistory.getColumnsByRole(values, \"Goal\");\n var actualValue;\n for (var i = 0, len = values[0].values.length; i < len; i++) {\n actualValue = indicatorColumns[0].values[i];\n var goals_1 = [];\n for (var goalCnt = 0; goalCnt < goalColumns.length; goalCnt++) {\n goals_1.push(goalColumns[goalCnt].values[i]);\n }\n historyGoalData.push(goals_1);\n historyActualData.push(actualValue);\n }\n var maxActualData = Math.max.apply(Math, historyActualData);\n var minActualData = Math.min.apply(Math, historyActualData);\n var areaMaxHight = viewPort.height * KPIStatusWithHistory.trendAreaFilePercentage;\n var precision = KPIStatusWithHistory.getProp_Indicator_Precision(dataView);\n var displayUnits = KPIStatusWithHistory.getProp_Indicator_DisplayUnits(dataView);\n for (var i = 0; i < historyActualData.length; i++) {\n var yPos = areaMaxHight * (historyActualData[i] - minActualData) / (maxActualData - minActualData);\n var selectorId = null;\n if (historyExists) {\n selectorId = visuals.SelectionId.createWithId(category.identity[i]).getSelector();\n }\n dataPoints.push({\n x: i * viewPort.width / (historyActualData.length - 1),\n y: viewPort.height - yPos,\n actual: historyActualData[i],\n goals: historyGoalData[i],\n });\n }\n var actual, goals;\n if (dataPoints.length > 0) {\n actual = dataPoints[dataPoints.length - 1].actual;\n goals = dataPoints[dataPoints.length - 1].goals;\n }\n if (dataPoints.length === 1) {\n historyExists = false;\n }\n formattedValue = KPIStatusWithHistory.getFormattedValue(indicatorMetadataColumn, actual, precision, displayUnits, powerbi.DisplayUnitSystemType.DataLabels);\n formattedGoalString = KPIStatusWithHistory.getFormattedGoalString(goalMetadataColumn, goals, precision, displayUnits);\n var showGoal = KPIStatusWithHistory.getProp_Show_KPIGoal(dataView);\n var showDistanceFromGoal = KPIStatusWithHistory.getProp_Show_KPIDistance(dataView);\n var showTrendLine = KPIStatusWithHistory.getProp_Show_KPITrendLine(dataView);\n return {\n dataPoints: dataPoints,\n directionType: directionType,\n actual: actual,\n goals: goals,\n formattedGoalString: formattedGoalString,\n targetExists: targetExists,\n historyExists: historyExists,\n indicatorExists: indicatorExists,\n trendExists: trendExists,\n formattedValue: formattedValue,\n showGoal: showGoal,\n showDistanceFromGoal: showDistanceFromGoal,\n showTrendLine: showTrendLine\n };\n };\n KPIStatusWithHistory.getColumnsByRole = function (values, roleString) {\n var retval = [];\n for (var i = 0; i < values.length; i++) {\n if (DataRoleHelper.hasRole(values[i].source, roleString)) {\n retval.push(values[i]);\n }\n }\n return retval;\n };\n KPIStatusWithHistory.prototype.enumerateObjectInstances = function (options) {\n var instances = [];\n var dataView = this.dataView;\n switch (options.objectName) {\n case 'indicator':\n instances.push({\n selector: null,\n objectName: 'indicator',\n properties: {\n indicatorDisplayUnits: KPIStatusWithHistory.getProp_Indicator_DisplayUnits(dataView),\n indicatorPrecision: KPIStatusWithHistory.getProp_Indicator_Precision(dataView)\n }\n });\n case 'trendline':\n instances.push({\n selector: null,\n objectName: 'trendline',\n properties: {\n show: KPIStatusWithHistory.getProp_Show_KPITrendLine(dataView)\n }\n });\n case 'goals':\n instances.push({\n selector: null,\n objectName: 'goals',\n properties: {\n showGoal: KPIStatusWithHistory.getProp_Show_KPIGoal(dataView),\n showDistance: KPIStatusWithHistory.getProp_Show_KPIDistance(dataView)\n }\n });\n case 'status':\n instances.push({\n selector: null,\n objectName: 'status',\n properties: {\n direction: KPIStatusWithHistory.getProp_KPIDirection(dataView)\n }\n });\n }\n return instances;\n };\n KPIStatusWithHistory.prototype.destroy = function () {\n this.svg = null;\n };\n KPIStatusWithHistory.directionTypeStringProp = { objectName: 'status', propertyName: 'direction' };\n KPIStatusWithHistory.showKPIGoal = { objectName: 'goals', propertyName: 'showGoal' };\n KPIStatusWithHistory.showKPIDistance = { objectName: 'goals', propertyName: 'showDistance' };\n KPIStatusWithHistory.showKPITrendLine = { objectName: 'trendline', propertyName: 'show' };\n KPIStatusWithHistory.indicatorDisplayUnitsProp = { objectName: 'indicator', propertyName: 'indicatorDisplayUnits' };\n KPIStatusWithHistory.indicatorPrecisionProp = { objectName: 'indicator', propertyName: 'indicatorPrecision' };\n KPIStatusWithHistory.status = { INCREASE: \"increase\", DROP: \"drop\", IN_BETWEEN: \"in-between\", NOGOAL: \"no-goal\" };\n KPIStatusWithHistory.statusBandingType = { Below: \"BELOW\", Above: \"ABOVE\" };\n KPIStatusWithHistory.actualTextConsts = { VERTICAL_OFFSET_FROM_HALF_HEIGHT: 20, FONT_WIDTH_FACTOR: 14, RIGHT_MARGIN: 10 };\n KPIStatusWithHistory.kpiRedClass = 'kpi-visual-red';\n KPIStatusWithHistory.kpiYellowClass = 'kpi-visual-yellow';\n KPIStatusWithHistory.kpiGreenClass = 'kpi-visual-green';\n KPIStatusWithHistory.kpiTextGreyClass = 'kpi-visual-text-grey';\n KPIStatusWithHistory.kpiGraphGreyClass = 'kpi-visual-graph-grey';\n KPIStatusWithHistory.allColorClasses = KPIStatusWithHistory.kpiRedClass + ' ' + KPIStatusWithHistory.kpiYellowClass + ' ' + KPIStatusWithHistory.kpiGreenClass + ' ' + KPIStatusWithHistory.kpiTextGreyClass + ' ' + KPIStatusWithHistory.kpiGraphGreyClass;\n KPIStatusWithHistory.trendAreaFilePercentage = 1;\n KPIStatusWithHistory.estimatedIconHeightInPx = 9;\n KPIStatusWithHistory.indicatorTextSizeInPx = 60;\n return KPIStatusWithHistory;\n }());\n visuals.KPIStatusWithHistory = KPIStatusWithHistory;\n function GetStatus(actual, goals, directionType) {\n if (!goals || goals.length === 0) {\n return KPIStatusWithHistory.status.NOGOAL;\n }\n var maxGoal, minGoal;\n if (goals.length === 2) {\n maxGoal = Math.max.apply(Math, goals);\n minGoal = Math.min.apply(Math, goals);\n if (actual >= minGoal && actual <= maxGoal) {\n return KPIStatusWithHistory.status.IN_BETWEEN;\n }\n }\n else {\n maxGoal = goals[0];\n minGoal = goals[0];\n }\n switch (directionType) {\n case visuals.kpiDirection.positive:\n if (actual < minGoal) {\n return KPIStatusWithHistory.status.DROP;\n }\n break;\n case visuals.kpiDirection.negative:\n if (actual > maxGoal) {\n return KPIStatusWithHistory.status.DROP;\n }\n break;\n default:\n break;\n }\n return KPIStatusWithHistory.status.INCREASE;\n }\n function getDistanceFromGoalInPercentageString(actual, goals, directionType) {\n if (!goals || goals.length !== 1 || goals[0] === 0) {\n return \"\";\n }\n var sign = \"+\";\n var distance;\n var goal = goals[0];\n distance = Math.abs(actual - goal);\n switch (directionType) {\n case visuals.kpiDirection.positive:\n if (actual < goal) {\n sign = \"-\";\n }\n break;\n case visuals.kpiDirection.negative:\n if (actual > goal) {\n sign = \"-\";\n }\n break;\n }\n var percent = Number((100 * distance / goal).toFixed(2));\n return \"(\" + sign + percent + \"%)\";\n }\n function GetTextColorClassByStatus(status) {\n switch (status) {\n case KPIStatusWithHistory.status.NOGOAL:\n return KPIStatusWithHistory.kpiTextGreyClass;\n case KPIStatusWithHistory.status.INCREASE:\n return KPIStatusWithHistory.kpiGreenClass;\n case KPIStatusWithHistory.status.IN_BETWEEN:\n return KPIStatusWithHistory.kpiYellowClass;\n case KPIStatusWithHistory.status.DROP:\n return KPIStatusWithHistory.kpiRedClass;\n }\n }\n function GetGraphColorClassByStatus(status) {\n switch (status) {\n case KPIStatusWithHistory.status.NOGOAL:\n return KPIStatusWithHistory.kpiGraphGreyClass;\n case KPIStatusWithHistory.status.INCREASE:\n return KPIStatusWithHistory.kpiGreenClass;\n case KPIStatusWithHistory.status.IN_BETWEEN:\n return KPIStatusWithHistory.kpiYellowClass;\n case KPIStatusWithHistory.status.DROP:\n return KPIStatusWithHistory.kpiRedClass;\n }\n }\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var EnumExtensions = jsCommon.EnumExtensions;\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n ;\n /**\n * Renders a data series as a line visual.\n */\n var LineChart = (function () {\n function LineChart(options) {\n var _this = this;\n this.deferDragMoveOperation = jsCommon.DeferUtility.deferUntilNextFrame(function () {\n if (_this.lastDragMoveXPosition) {\n var index = _this.findIndex(_this.lastDragMoveXPosition - _this.margin.left);\n _this.selectColumn(index);\n _this.lastDragMoveXPosition = undefined;\n }\n });\n this.isScrollable = options.isScrollable ? options.isScrollable : false;\n this.tooltipsEnabled = options.tooltipsEnabled;\n this.lineType = options.chartType ? options.chartType : 1 /* default */;\n this.interactivityService = options.interactivityService;\n this.animator = options.animator;\n this.lineChartLabelDensityEnabled = options.lineChartLabelDensityEnabled;\n this.lineClassAndSelector = LineChart.LineClassSelector;\n }\n LineChart.customizeQuery = function (options) {\n var dataViewMapping = options.dataViewMappings[0];\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\n return;\n dataViewMapping.categorical.dataVolume = 4;\n if (visuals.CartesianChart.detectScalarMapping(dataViewMapping)) {\n var dataViewCategories = dataViewMapping.categorical.categories;\n dataViewCategories.dataReductionAlgorithm = { sample: {} };\n }\n };\n LineChart.getSortableRoles = function (options) {\n var dataViewMapping = options.dataViewMappings[0];\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\n return null;\n var dataViewCategories = dataViewMapping.categorical.categories;\n var categoryItems = dataViewCategories.for.in.items;\n if (!_.isEmpty(categoryItems)) {\n var categoryType = categoryItems[0].type;\n var objects = void 0;\n if (dataViewMapping.metadata)\n objects = dataViewMapping.metadata.objects;\n //TODO: line chart should be sortable by X if it has scalar axis\n // But currently it doesn't support this. Always return 'category'\n // once it is supported.\n if (!visuals.CartesianChart.getIsScalar(objects, visuals.lineChartProps.categoryAxis.axisType, categoryType))\n return ['Category', 'Y'];\n }\n return null;\n };\n LineChart.converter = function (dataView, blankCategoryValue, colors, isScalar, interactivityService, shouldCalculateStacked, isComboChart, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n var valueRoleName = isComboChart ? \"Y2\" : \"Y\";\n var categorical = dataView.categorical;\n var category = categorical.categories && categorical.categories.length > 0\n ? categorical.categories[0]\n : {\n source: undefined,\n values: [blankCategoryValue],\n identity: undefined,\n };\n var xAxisCardProperties = visuals.CartesianHelper.getCategoryAxisProperties(dataView.metadata);\n isScalar = visuals.CartesianHelper.isScalar(isScalar, xAxisCardProperties);\n categorical = visuals.ColumnUtil.applyUserMinMax(isScalar, categorical, xAxisCardProperties);\n var formatStringProp = visuals.lineChartProps.general.formatString;\n var categoryType = visuals.AxisHelper.getCategoryValueType(category.source, isScalar);\n var isDateTime = visuals.AxisHelper.isDateTime(categoryType);\n var categoryValues = category.values;\n var categoryData = [];\n var series = [];\n var seriesLen = categorical.values ? categorical.values.length : 0;\n var hasDynamicSeries = !!(categorical.values && categorical.values.source);\n var values = categorical.values;\n var defaultLabelSettings = visuals.dataLabelUtils.getDefaultLineChartLabelSettings(isComboChart);\n var defaultSeriesColor;\n if (dataView.metadata && dataView.metadata.objects) {\n var objects = dataView.metadata.objects;\n // If the line layer is in a combo chart, the \"Default Column Color\" slice's value (lineChartProps.dataPoint.defaultColor) will not affect the line series as well\n defaultSeriesColor = isComboChart ? undefined : powerbi.DataViewObjects.getFillColor(objects, visuals.lineChartProps.dataPoint.defaultColor);\n var labelsObj = objects['labels'];\n visuals.dataLabelUtils.updateLineChartLabelSettingsFromLabelsObject(labelsObj, defaultLabelSettings);\n }\n var colorHelper = new visuals.ColorHelper(colors, visuals.lineChartProps.dataPoint.fill, defaultSeriesColor);\n var grouped;\n if (dataView.categorical.values)\n grouped = dataView.categorical.values.grouped();\n var stackedValues;\n if (shouldCalculateStacked) {\n //initialize array with zeros\n stackedValues = categorical.values && categorical.values.length > 0 ? _.times(categorical.values[0].values.length, function () { return 0; }) : [];\n }\n for (var seriesIndex = 0; seriesIndex < seriesLen; seriesIndex++) {\n var column = categorical.values[seriesIndex];\n var valuesMetadata = column.source;\n var dataPoints = [];\n var groupedIdentity = grouped[seriesIndex];\n var identity = hasDynamicSeries && groupedIdentity\n ? visuals.SelectionId.createWithIdAndMeasure(groupedIdentity.identity, column.source.queryName)\n : visuals.SelectionId.createWithMeasure(column.source.queryName);\n var key = identity.getKey();\n var color = this.getColor(colorHelper, hasDynamicSeries, values, grouped, seriesIndex, groupedIdentity);\n var seriesLabelSettings = void 0;\n if (!hasDynamicSeries) {\n var labelsSeriesGroup = grouped && grouped.length > 0 && grouped[0].values ? grouped[0].values[seriesIndex] : null;\n var labelObjects = (labelsSeriesGroup && labelsSeriesGroup.source && labelsSeriesGroup.source.objects) ? labelsSeriesGroup.source.objects['labels'] : null;\n if (labelObjects) {\n seriesLabelSettings = powerbi.Prototype.inherit(defaultLabelSettings);\n visuals.dataLabelUtils.updateLineChartLabelSettingsFromLabelsObject(labelObjects, seriesLabelSettings);\n }\n }\n var dataPointLabelSettings = (seriesLabelSettings) ? seriesLabelSettings : defaultLabelSettings;\n var useHighlightValues = column.highlights && column.highlights.length > 0;\n var categoryCount = reader.hasCategories() ? reader.getCategoryCount() : 1;\n // NOTE: line capabilities don't allow highlights, but comboChart does - so only use highlight values if we are in \"combo\" mode\n for (var categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {\n var categoryValue = categoryValues[categoryIndex];\n var value = visuals.AxisHelper.normalizeNonFiniteNumber(useHighlightValues ? reader.getHighlight(valueRoleName, categoryIndex, seriesIndex) : reader.getValue(valueRoleName, categoryIndex, seriesIndex));\n // When Scalar, skip null categories and null values so we draw connected lines and never draw isolated dots.\n if (isScalar && (categoryValue == null || value == null))\n continue;\n // ignore variant measures\n if (isDateTime && categoryValue != null && !(categoryValue instanceof Date))\n continue;\n var categorical_1 = dataView.categorical;\n var tooltipInfo = void 0;\n if (tooltipsEnabled) {\n // This tooltip is using in combo chart and mobile tooltip.\n tooltipInfo = [];\n if (category.source) {\n tooltipInfo.push({\n displayName: category.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(categoryValue, category.source, formatStringProp),\n });\n }\n // This dynamicSeries tooltip is only using in mobile tooltip.\n if (hasDynamicSeries) {\n if (!category.source || category.source !== categorical_1.values.source) {\n // Category/series on the same column -- don't repeat its value in the tooltip.\n tooltipInfo.push({\n displayName: categorical_1.values.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(grouped[seriesIndex].name, categorical_1.values.source, formatStringProp),\n });\n }\n }\n if (value != null) {\n tooltipInfo.push({\n displayName: valuesMetadata.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(value, valuesMetadata, formatStringProp),\n });\n }\n }\n var categoryKey = category && !_.isEmpty(category.identity) && category.identity[categoryIndex] ? category.identity[categoryIndex].key : categoryIndex;\n var dataPoint = {\n categoryValue: isDateTime && categoryValue ? categoryValue.getTime() : categoryValue,\n value: value,\n categoryIndex: categoryIndex,\n seriesIndex: seriesIndex,\n tooltipInfo: tooltipInfo,\n selected: false,\n identity: identity,\n key: JSON.stringify({ series: key, category: categoryKey }),\n labelFill: dataPointLabelSettings.labelColor,\n labelFormatString: valuesMetadata.format,\n labelSettings: dataPointLabelSettings\n };\n if (shouldCalculateStacked) {\n stackedValues[categoryIndex] += value;\n dataPoint.stackedValue = stackedValues[categoryIndex];\n }\n if (category.objects && category.objects[categoryIndex]) {\n dataPoint['pointColor'] = powerbi.DataViewObjects.getFillColor(category.objects[categoryIndex], visuals.lineChartProps.dataPoint.fill);\n }\n dataPoints.push(dataPoint);\n if (!categoryData[categoryIndex]) {\n categoryData[categoryIndex] = dataPoint;\n }\n }\n if (interactivityService) {\n interactivityService.applySelectionStateToData(dataPoints);\n }\n if (dataPoints.length > 0) {\n series.push({\n displayName: valuesMetadata.displayName,\n key: key,\n lineIndex: seriesIndex,\n color: color,\n xCol: category.source,\n yCol: column.source,\n data: dataPoints,\n identity: identity,\n selected: false,\n labelSettings: seriesLabelSettings,\n });\n }\n }\n xAxisCardProperties = visuals.CartesianHelper.getCategoryAxisProperties(dataView.metadata);\n var valueAxisProperties = visuals.CartesianHelper.getValueAxisProperties(dataView.metadata);\n // Convert to DataViewMetadataColumn\n var valuesMetadataArray = [];\n if (values) {\n for (var i = 0; i < values.length; i++) {\n if (values[i] && values[i].source && values[i].source.displayName) {\n valuesMetadataArray.push({ displayName: values[i].source.displayName });\n }\n }\n }\n var axesLabels = visuals.converterHelper.createAxesLabels(xAxisCardProperties, valueAxisProperties, category.source, valuesMetadataArray);\n if (interactivityService) {\n interactivityService.applySelectionStateToData(series);\n }\n return {\n series: series,\n isScalar: isScalar,\n dataLabelsSettings: defaultLabelSettings,\n axesLabels: { x: axesLabels.xAxisLabel, y: axesLabels.yAxisLabel },\n hasDynamicSeries: hasDynamicSeries,\n categoryMetadata: category.source,\n categories: categoryValues,\n categoryData: categoryData,\n };\n };\n LineChart.getInteractiveLineChartDomElement = function (element) {\n return element.children(\"svg\").get(0);\n };\n LineChart.getColor = function (colorHelper, hasDynamicSeries, values, grouped, seriesIndex, groupedIdentity) {\n var objects;\n if (hasDynamicSeries) {\n if (grouped && grouped[seriesIndex])\n objects = grouped[seriesIndex].objects;\n }\n else if (values[seriesIndex]) {\n objects = values[seriesIndex].source.objects;\n }\n return hasDynamicSeries && groupedIdentity\n ? colorHelper.getColorForSeriesValue(objects, values.identityFields, groupedIdentity.name)\n : colorHelper.getColorForMeasure(objects, values[seriesIndex].source.queryName);\n };\n LineChart.createStackedValueDomain = function (data) {\n debug.assertValue(data, 'data');\n if (data.length === 0)\n return null;\n var minY = d3.min(data, function (kv) { return d3.min(kv.data, function (d) { return d.stackedValue; }); });\n var maxY = d3.max(data, function (kv) { return d3.max(kv.data, function (d) { return d.stackedValue; }); });\n return [minY, maxY];\n };\n LineChart.prototype.init = function (options) {\n var _this = this;\n this.options = options;\n this.element = options.element;\n this.cartesainSVG = options.svg;\n this.host = options.host;\n this.currentViewport = options.viewport;\n this.colors = options.style.colorPalette.dataColors;\n this.isInteractiveChart = options.interactivity && options.interactivity.isInteractiveLegend;\n this.cartesianVisualHost = options.cartesianHost;\n this.scaleDetector = new visuals.SVGScaleDetector(this.cartesainSVG);\n var chartType = options.chartType;\n this.isComboChart = chartType === 10 /* ComboChart */ || chartType === 13 /* LineClusteredColumnCombo */ || chartType === 14 /* LineStackedColumnCombo */;\n var svg = options.svg;\n svg.classed(LineChart.ClassName, true);\n var graphicsContextParent = this.mainGraphicsSVG = svg.append('svg')\n .classed('lineChartSVG', true);\n if (!this.isComboChart && !this.isInteractiveChart) {\n this.overlayRect = graphicsContextParent\n .append(LineChart.RectOverlayName)\n .style(\"opacity\", visuals.SVGUtil.AlmostZero);\n }\n this.mainGraphicsContext = graphicsContextParent\n .append('g')\n .classed(LineChart.MainGraphicsContextClassName, true);\n this.hoverLineContext = svg.append('g')\n .classed('hover-line', true);\n this.hoverLineContext.append(LineChart.LineElementName)\n .attr(\"x1\", 0).attr(\"x2\", 0)\n .attr(\"y1\", 0).attr(\"y2\", 0);\n var hoverLine = this.hoverLine = this.hoverLineContext.select(LineChart.LineElementName);\n if (this.isInteractiveChart) {\n hoverLine.classed('interactive', true);\n }\n hoverLine.style('opacity', visuals.SVGUtil.AlmostZero);\n // define circles object - which will hold the handle circles.\n // this object will be populated on render() function, with number of circles which matches the nubmer of lines.\n this.selectionCircles = [];\n this.xAxisProperties = {\n axis: null,\n scale: null,\n isScalar: null,\n axisType: null,\n formatter: null,\n graphicsContext: null,\n values: null,\n axisLabel: null,\n isCategoryAxis: true\n };\n if (this.isInteractiveChart) {\n var rootSvg_1 = LineChart.getInteractiveLineChartDomElement(this.element);\n var dragMove = function () {\n _this.lastDragMoveXPosition = d3.mouse(rootSvg_1)[0];\n _this.deferDragMoveOperation();\n };\n // assign drag and onClick events\n var drag = d3.behavior.drag()\n .origin(Object)\n .on(\"drag\", dragMove);\n d3.select(rootSvg_1)\n .style('touch-action', 'none')\n .call(drag)\n .on('click', dragMove);\n }\n // Internet Explorer and Edge use the stroke edge, not the path edge for the mouse coordinate's origin.\n // We need to adjust mouse events on the interactivity lines to account for this.\n this.shouldAdjustMouseCoordsOnPathsForStroke = !jsCommon.BrowserUtils.isChrome();\n };\n LineChart.prototype.setData = function (dataViews) {\n this.data = {\n series: [],\n dataLabelsSettings: visuals.dataLabelUtils.getDefaultLineChartLabelSettings(this.isComboChart),\n axesLabels: { x: null, y: null },\n hasDynamicSeries: false,\n categories: [],\n categoryMetadata: undefined,\n categoryData: [],\n };\n if (dataViews.length > 0) {\n var dataView = dataViews[0];\n if (dataView) {\n if (dataView.categorical) {\n var dataViewCat = this.dataViewCat = dataView.categorical;\n var dvCategories = dataViewCat.categories;\n var categoryType = powerbi.ValueType.fromDescriptor({ text: true });\n if (dvCategories && dvCategories.length > 0 && dvCategories[0].source && dvCategories[0].source.type)\n categoryType = dvCategories[0].source.type;\n var convertedData = LineChart.converter(dataView, visuals.valueFormatter.format(null), this.cartesianVisualHost.getSharedColors(), visuals.CartesianChart.getIsScalar(dataView.metadata ? dataView.metadata.objects : null, visuals.lineChartProps.categoryAxis.axisType, categoryType), this.interactivityService, EnumExtensions.hasFlag(this.lineType, 16 /* stackedArea */), this.isComboChart);\n this.data = convertedData;\n }\n }\n }\n };\n LineChart.prototype.calculateLegend = function () {\n return this.createLegendDataPoints(0); // start with index 0\n };\n LineChart.prototype.hasLegend = function () {\n return this.data && (this.data.hasDynamicSeries || (this.data.series && this.data.series.length > 1));\n };\n LineChart.prototype.setFilteredData = function (startIndex, endIndex) {\n var catgSize = endIndex - startIndex;\n var data = this.clippedData = powerbi.Prototype.inherit(this.data);\n data.series = LineChart.sliceSeries(data.series, catgSize, startIndex);\n data.categories = data.categories.slice(startIndex, endIndex);\n return data;\n };\n LineChart.prototype.calculateAxesProperties = function (options) {\n var _this = this;\n var data = this.data;\n var viewport = options.viewport;\n var margin = options.margin;\n this.currentViewport = viewport;\n this.margin = margin;\n var origCatgSize = data.series && data.series.length > 0 ? data.series[0].data.length : 0;\n var categoryWidth = visuals.CartesianChart.MinOrdinalRectThickness;\n var isScalar = this.data.isScalar;\n var trimOrdinalDataOnOverflow = options.trimOrdinalDataOnOverflow;\n var preferredPlotArea = this.getPreferredPlotArea(isScalar, origCatgSize, categoryWidth);\n this.clippedData = undefined;\n if (data && !isScalar && !this.isScrollable && trimOrdinalDataOnOverflow) {\n // trim data that doesn't fit on dashboard\n var categoryCount = this.getCategoryCount(origCatgSize);\n var catgSize = Math.min(origCatgSize, categoryCount);\n if (catgSize !== origCatgSize) {\n data = this.clippedData = powerbi.Prototype.inherit(data);\n this.clippedData.series = LineChart.sliceSeries(data.series, catgSize);\n }\n }\n var xMetaDataColumn;\n var yMetaDataColumn;\n if (data.series && data.series.length > 0) {\n xMetaDataColumn = data.series[0].xCol;\n yMetaDataColumn = data.series[0].yCol;\n }\n var valueDomain = EnumExtensions.hasFlag(this.lineType, 16 /* stackedArea */) ? LineChart.createStackedValueDomain(data.series) : visuals.AxisHelper.createValueDomain(data.series, false);\n var hasZeroValueInYDomain = options.valueAxisScaleType === visuals.axisScale.log && !visuals.AxisHelper.isLogScalePossible(valueDomain);\n var combinedDomain = visuals.AxisHelper.combineDomain(options.forcedYDomain, valueDomain, options.ensureYDomain);\n this.yAxisProperties = visuals.AxisHelper.createAxis({\n pixelSpan: preferredPlotArea.height,\n dataDomain: combinedDomain,\n metaDataColumn: yMetaDataColumn,\n formatString: visuals.valueFormatter.getFormatString(yMetaDataColumn, visuals.lineChartProps.general.formatString),\n outerPadding: 0,\n isScalar: true,\n isVertical: true,\n forcedTickCount: options.forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false,\n scaleType: options.valueAxisScaleType,\n axisDisplayUnits: options.valueAxisDisplayUnits,\n axisPrecision: options.valueAxisPrecision,\n shouldClamp: false,\n });\n var metaDataColumn = this.data ? this.data.categoryMetadata : undefined;\n var categoryDataType = visuals.AxisHelper.getCategoryValueType(metaDataColumn);\n var xDomain = visuals.AxisHelper.createDomain(data.series, categoryDataType, this.data.isScalar, options.forcedXDomain, options.ensureXDomain);\n var hasZeroValueInXDomain = options.categoryAxisScaleType === visuals.axisScale.log && !visuals.AxisHelper.isLogScalePossible(xDomain);\n this.xAxisProperties = visuals.AxisHelper.createAxis({\n pixelSpan: preferredPlotArea.width,\n dataDomain: xDomain,\n metaDataColumn: xMetaDataColumn,\n formatString: visuals.valueFormatter.getFormatString(xMetaDataColumn, visuals.lineChartProps.general.formatString),\n outerPadding: this.data.isScalar ? LineChart.ScalarOuterPadding : 0,\n isScalar: this.data.isScalar,\n isVertical: false,\n forcedTickCount: options.forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n getValueFn: function (index, type) { return visuals.CartesianHelper.lookupXValue(_this.data, index, type, _this.data.isScalar); },\n categoryThickness: visuals.CartesianChart.getCategoryThickness(data.series, origCatgSize, this.getAvailableWidth(), xDomain, isScalar, trimOrdinalDataOnOverflow),\n isCategoryAxis: true,\n scaleType: options.categoryAxisScaleType,\n axisDisplayUnits: options.categoryAxisDisplayUnits,\n axisPrecision: options.categoryAxisPrecision\n });\n this.xAxisProperties.axisLabel = options.showCategoryAxisLabel ? data.axesLabels.x : null;\n this.yAxisProperties.axisLabel = options.showValueAxisLabel ? data.axesLabels.y : null;\n this.xAxisProperties.hasDisallowedZeroInDomain = hasZeroValueInXDomain;\n this.yAxisProperties.hasDisallowedZeroInDomain = hasZeroValueInYDomain;\n return [this.xAxisProperties, this.yAxisProperties];\n };\n LineChart.prototype.enumerateObjectInstances = function (enumeration, options) {\n switch (options.objectName) {\n case 'dataPoint':\n this.enumerateDataPoints(enumeration);\n break;\n case 'labels':\n this.enumerateDataLabels(enumeration);\n break;\n }\n };\n LineChart.prototype.enumerateDataPoints = function (enumeration) {\n var data = this.data;\n if (!data || !data.series || data.series.length === 0)\n return;\n var formatStringProp = visuals.lineChartProps.general.formatString;\n var singleSeriesData = data.series;\n var seriesLength = singleSeriesData.length;\n for (var i = 0; i < seriesLength; i++) {\n var selector = visuals.ColorHelper.normalizeSelector(singleSeriesData[i].identity.getSelector());\n var label = visuals.converterHelper.getFormattedLegendLabel(singleSeriesData[i].yCol, this.dataViewCat.values, formatStringProp);\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: label,\n selector: selector,\n properties: {\n fill: { solid: { color: data.defaultSeriesColor || singleSeriesData[i].color } }\n },\n });\n }\n };\n LineChart.prototype.enumerateDataLabels = function (enumeration) {\n var data = this.data, labelSettings = this.data.dataLabelsSettings, seriesCount = data.series.length, showLabelPerSeries = this.showLabelPerSeries();\n //Draw default settings\n visuals.dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings, null, showLabelPerSeries));\n if (seriesCount === 0)\n return;\n //Draw series settings\n if (showLabelPerSeries && labelSettings.showLabelPerSeries) {\n for (var i = 0; i < seriesCount; i++) {\n var series = data.series[i], labelSettings_2 = (series.labelSettings) ? series.labelSettings : this.data.dataLabelsSettings;\n enumeration.pushContainer({ displayName: series.displayName });\n visuals.dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings_2, series));\n enumeration.popContainer();\n }\n }\n };\n LineChart.prototype.supportsTrendLine = function () {\n var isScalar = this.data ? this.data.isScalar : false;\n return !EnumExtensions.hasFlag(this.lineType, 16 /* stackedArea */) && isScalar;\n };\n LineChart.prototype.getLabelSettingsOptions = function (enumeration, labelSettings, series, showAll) {\n return {\n enumeration: enumeration,\n dataLabelsSettings: labelSettings,\n show: true,\n displayUnits: true,\n precision: true,\n selector: series && series.identity ? series.identity.getSelector() : null,\n showAll: showAll,\n fontSize: true,\n labelDensity: this.lineChartLabelDensityEnabled,\n };\n };\n LineChart.prototype.overrideXScale = function (xProperties) {\n this.xAxisProperties = xProperties;\n };\n LineChart.prototype.onClearSelection = function () {\n if (this.interactivityService)\n this.interactivityService.clearSelection();\n };\n LineChart.prototype.render = function (suppressAnimations) {\n var duration = visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n if (this.data.categoryData.length !== this.previousCategoryCount) {\n duration = 0;\n }\n this.previousCategoryCount = this.data.categoryData.length;\n var result;\n if (!this.isInteractiveChart)\n result = this.renderNew(duration);\n else\n result = this.renderOld(duration);\n // This should always be the last line in the render code.\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n return result;\n };\n LineChart.prototype.renderNew = function (duration) {\n var _this = this;\n var data = this.clippedData ? this.clippedData : this.data;\n if (!data)\n return;\n var dataPointCount = data.categories.length * data.series.length;\n if (dataPointCount > visuals.AnimatorCommon.MaxDataPointsToAnimate) {\n // Too many data points to animate.\n duration = 0;\n }\n var isStackedArea = EnumExtensions.hasFlag(this.lineType, 16 /* stackedArea */);\n var margin = this.margin;\n var viewport = this.currentViewport;\n var height = viewport.height - (margin.top + margin.bottom);\n var width = viewport.width - (margin.left + margin.right);\n var xScale = this.xAxisProperties.scale;\n var yScale = this.yAxisProperties.scale;\n var horizontalOffset = this.getXOfFirstCategory();\n var hasSelection = this.interactivityService && this.interactivityService.hasSelection();\n var renderAreas = EnumExtensions.hasFlag(this.lineType, 2 /* area */) || EnumExtensions.hasFlag(this.lineType, 16 /* stackedArea */);\n var xPosition = function (d) { return xScale(_this.getXValue(d)) + horizontalOffset; };\n var y0Position, yPosition;\n if (isStackedArea) {\n y0Position = function (d) { return yScale(d.stackedValue - d.value); };\n yPosition = function (d) { return yScale(d.stackedValue); };\n }\n else {\n y0Position = yScale(0);\n yPosition = function (d) { return yScale(d.value); };\n }\n var area;\n if (renderAreas) {\n area = d3.svg.area()\n .x(xPosition)\n .y0(y0Position)\n .y1(yPosition)\n .defined(function (d) { return d.value !== null; });\n }\n var line = d3.svg.line()\n .x(xPosition)\n .y(yPosition)\n .defined(function (d) {\n return d.value !== null;\n });\n if (EnumExtensions.hasFlag(this.lineType, 4 /* smooth */)) {\n line.interpolate('basis');\n if (area) {\n area.interpolate('basis');\n }\n }\n this.mainGraphicsSVG\n .attr('height', height)\n .attr('width', width);\n var areas = undefined;\n // Render Areas\n if (renderAreas) {\n areas = this.mainGraphicsContext.selectAll(LineChart.CategoryAreaSelector.selector).data(data.series, function (d) { return d.identity.getKey(); });\n areas.enter()\n .append(LineChart.PathElementName)\n .classed(LineChart.CategoryAreaSelector.class, true);\n areas\n .style('fill', function (d) { return d.color; })\n .style('fill-opacity', function (d) { return (hasSelection && !d.selected) ? LineChart.DimmedAreaFillOpacity : LineChart.AreaFillOpacity; })\n .transition()\n .ease('linear')\n .duration(duration)\n .attr('d', function (d) { return area(d.data); });\n areas.exit()\n .remove();\n }\n // Render Lines\n var lines = this.mainGraphicsContext.selectAll(this.lineClassAndSelector.selector).data(data.series, function (d) { return d.identity.getKey(); });\n lines.enter()\n .append(LineChart.PathElementName)\n .classed(this.lineClassAndSelector.class, true);\n lines\n .style('stroke', function (d) { return d.color; })\n .style('stroke-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); })\n .transition()\n .ease('linear')\n .duration(duration)\n .attr('d', function (d) {\n return line(d.data);\n });\n lines.exit()\n .remove();\n // Render extra lines that are wider and invisible used for better interactivity\n var interactivityLines;\n if (this.interactivityService) {\n interactivityLines = this.mainGraphicsContext.selectAll(\".interactivity-line\").data(data.series, function (d) { return d.identity.getKey(); });\n interactivityLines.enter()\n .append(LineChart.PathElementName)\n .classed('interactivity-line', true)\n .style('stroke-width', LineChart.interactivityStrokeWidth);\n interactivityLines\n .attr('d', function (d) {\n return line(d.data);\n });\n interactivityLines.exit()\n .remove();\n }\n // Prepare grouping for dots\n var dotGroups = this.mainGraphicsContext.selectAll(LineChart.CategorySelector.selector)\n .data(data.series, function (d) { return d.identity.getKey(); });\n dotGroups.enter()\n .append('g')\n .classed(LineChart.CategorySelector.class, true);\n dotGroups.exit()\n .remove();\n // Render dots\n var dots = dotGroups.selectAll(LineChart.CategoryValuePoint.selector)\n .data(function (series) {\n return series.data.filter(function (value, i) {\n return _this.shouldDrawCircle(series, i);\n });\n }, function (d) { return d.key; });\n dots.enter()\n .append(LineChart.CircleElementName)\n .classed(LineChart.CategoryValuePoint.class, true);\n dots\n .style('fill', function () {\n var lineSeries = d3.select(this.parentNode).datum();\n return lineSeries.color;\n })\n .style('fill-opacity', function () {\n var lineSeries = d3.select(this.parentNode).datum();\n return visuals.ColumnUtil.getFillOpacity(lineSeries.selected, false, hasSelection, false);\n })\n .transition()\n .duration(duration)\n .attr({\n cx: function (d, i) { return xScale(_this.getXValue(d)) + horizontalOffset; },\n cy: function (d, i) { return yScale(isStackedArea ? d.stackedValue : d.value); },\n r: LineChart.CircleRadius\n });\n dots.exit()\n .remove();\n // Render explicit dots\n var explicitDots;\n if (!this.isComboChart) {\n explicitDots = dotGroups.selectAll(LineChart.CategoryPointSelector.selector)\n .data(function (series) {\n return _.filter(series.data, function (value) { return value.pointColor != null; });\n }, function (d) { return d.key; });\n explicitDots.enter()\n .append(LineChart.CircleElementName)\n .classed(LineChart.CategoryPointSelector.class, true);\n explicitDots\n .style('fill', function (d) { return d.pointColor; })\n .transition()\n .duration(duration)\n .attr({\n cx: function (d) { return xScale(_this.getXValue(d)); },\n cy: function (d) { return yScale(isStackedArea ? d.stackedValue : d.value); },\n r: LineChart.PointRadius\n });\n explicitDots.exit()\n .remove();\n }\n // Add data labels\n var labelDataPointsGroups;\n if (data.dataLabelsSettings.show)\n labelDataPointsGroups = this.createLabelDataPoints();\n if (this.tooltipsEnabled) {\n if (!this.isComboChart) {\n this.overlayRect\n .attr({\n x: 0,\n width: width,\n height: height\n });\n var seriesTooltipApplier = function (tooltipEvent) {\n var pointX = tooltipEvent.elementCoordinates[0];\n var index = _this.getCategoryIndexFromTooltipEvent(tooltipEvent, pointX);\n var categoryData = _this.selectColumnForTooltip(index);\n return _this.getSeriesTooltipInfo(categoryData);\n };\n var clearHoverLine = function () {\n _this.hoverLine.style('opacity', visuals.SVGUtil.AlmostZero);\n _this.hoverLineContext.selectAll(LineChart.HoverLineCircleDot.selector).remove();\n };\n visuals.TooltipManager.addTooltip(this.mainGraphicsSVG, seriesTooltipApplier, true, clearHoverLine);\n }\n else {\n var seriesTooltipApplier = function (tooltipEvent) {\n var pointX = tooltipEvent.elementCoordinates[0];\n return _this.getTooltipInfoForCombo(tooltipEvent, pointX);\n };\n if (interactivityLines)\n visuals.TooltipManager.addTooltip(interactivityLines, seriesTooltipApplier, true);\n visuals.TooltipManager.addTooltip(dots, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; }, true);\n if (explicitDots)\n visuals.TooltipManager.addTooltip(explicitDots, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; }, true);\n }\n }\n var dataPointsToBind = undefined;\n var behaviorOptions = undefined;\n if (this.interactivityService) {\n // Register interactivity\n dataPointsToBind = data.series.slice();\n for (var i = 0, ilen = data.series.length; i < ilen; i++) {\n dataPointsToBind = dataPointsToBind.concat(data.series[i].data);\n }\n behaviorOptions = {\n lines: lines,\n interactivityLines: interactivityLines,\n dots: dots,\n areas: areas,\n tooltipOverlay: this.overlayRect,\n };\n }\n return {\n dataPoints: dataPointsToBind,\n behaviorOptions: behaviorOptions,\n labelDataPoints: [],\n labelsAreNumeric: true,\n labelDataPointGroups: labelDataPointsGroups,\n };\n };\n LineChart.prototype.renderOld = function (duration) {\n var _this = this;\n var data = this.clippedData ? this.clippedData : this.data;\n if (!data)\n return;\n var margin = this.margin;\n var viewport = this.currentViewport;\n var height = viewport.height - (margin.top + margin.bottom);\n var xScale = this.xAxisProperties.scale;\n var yScale = this.yAxisProperties.scale;\n var hasSelection = this.interactivityService && this.interactivityService.hasSelection();\n var area;\n if (EnumExtensions.hasFlag(this.lineType, 2 /* area */)) {\n area = d3.svg.area()\n .x(function (d) { return xScale(_this.getXValue(d)); })\n .y0(height)\n .y1(function (d) { return yScale(d.value); })\n .defined(function (d) { return d.value !== null; });\n }\n var line = d3.svg.line()\n .x(function (d) {\n return xScale(_this.getXValue(d));\n })\n .y(function (d) {\n return yScale(d.value);\n })\n .defined(function (d) {\n return d.value !== null;\n });\n if (EnumExtensions.hasFlag(this.lineType, 4 /* smooth */)) {\n line.interpolate('basis');\n if (area) {\n area.interpolate('basis');\n }\n }\n var firstCategoryOffset = this.getXOfFirstCategory();\n this.mainGraphicsContext.attr('transform', visuals.SVGUtil.translate(firstCategoryOffset, 0));\n this.mainGraphicsSVG.attr('height', this.getAvailableHeight())\n .attr('width', this.getAvailableWidth());\n this.hoverLineContext.attr('transform', visuals.SVGUtil.translate(firstCategoryOffset, 0));\n if (EnumExtensions.hasFlag(this.lineType, 2 /* area */)) {\n var catAreaSelect = this.mainGraphicsContext.selectAll(LineChart.CategoryAreaSelector.selector)\n .data(data.series, function (d) { return d.identity.getKey(); });\n var catAreaEnter = catAreaSelect\n .enter().append('g')\n .classed(LineChart.CategoryAreaSelector.class, true);\n catAreaEnter.append(LineChart.PathElementName);\n var catAreaUpdate = this.mainGraphicsContext.selectAll(LineChart.CategoryAreaSelector.selector);\n catAreaUpdate.select(LineChart.PathElementName)\n .transition()\n .ease('linear')\n .duration(duration)\n .attr('d', function (d) { return area(d.data); })\n .style('fill', function (d) { return d.color; })\n .style('fill-opacity', function (d) { return (hasSelection && !d.selected) ? LineChart.DimmedAreaFillOpacity : LineChart.AreaFillOpacity; });\n catAreaSelect.exit().remove();\n }\n var catSelect = this.mainGraphicsContext.selectAll(LineChart.CategorySelector.selector)\n .data(data.series, function (d) { return d.identity.getKey(); });\n var catEnter = catSelect\n .enter()\n .append('g')\n .classed(LineChart.CategorySelector.class, true);\n catEnter.append(LineChart.PathElementName);\n catEnter.selectAll(LineChart.CategoryValuePoint.selector)\n .data(function (d) { return d.data; })\n .enter()\n .append(LineChart.CircleElementName)\n .classed(LineChart.CategoryValuePoint.class, true);\n // moving this up to avoid using the svg path generator with NaN values\n // do not move this without validating that no errors are thrown in the browser console\n catSelect.exit().remove();\n // add the drag handle, if needed\n if (this.isInteractiveChart && !this.dragHandle) {\n var handleTop = this.getAvailableHeight();\n this.dragHandle = this.hoverLineContext.append('circle')\n .attr('cx', 0)\n .attr('cy', handleTop)\n .attr('r', '6px')\n .classed('drag-handle', true);\n }\n // Create the selection circles\n var linesCount = catSelect.data().length; // number of lines plotted\n while (this.selectionCircles.length < linesCount) {\n var addedCircle = this.hoverLineContext.append(LineChart.CircleElementName)\n .classed(LineChart.CircleClassName, true)\n .attr('r', LineChart.CircleRadius).style('opacity', 0);\n this.selectionCircles.push(addedCircle);\n }\n while (this.selectionCircles.length > linesCount) {\n this.selectionCircles.pop().remove();\n }\n var catUpdate = this.mainGraphicsContext.selectAll(LineChart.CategorySelector.selector);\n var lineSelection = catUpdate.select(LineChart.PathElementName)\n .classed(this.lineClassAndSelector.class, true)\n .style('stroke', function (d) { return d.color; })\n .style('stroke-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); });\n lineSelection\n .transition()\n .ease('linear')\n .duration(duration)\n .attr('d', function (d) {\n return line(d.data);\n });\n var that = this;\n var updateSelection = catUpdate.selectAll(LineChart.CategoryValuePoint.selector);\n var transitions = updateSelection\n .style('fill', function () {\n var lineSeries = d3.select(this.parentNode).datum();\n return lineSeries.color;\n })\n .style('fill-opacity', function () {\n var lineSeries = d3.select(this.parentNode).datum();\n return visuals.ColumnUtil.getFillOpacity(lineSeries.selected, false, hasSelection, false);\n })\n .transition()\n .duration(duration)\n .attr({\n 'cx': function (d, i) {\n var lineSeries = d3.select(this.parentNode).datum();\n var circleIndex = that.shouldDrawCircle(lineSeries, i);\n return circleIndex ? xScale(that.getXValue(d)) : 0;\n },\n 'cy': function (d, i) {\n var lineSeries = d3.select(this.parentNode).datum();\n var circleIndex = that.shouldDrawCircle(lineSeries, i);\n return circleIndex ? yScale(d.value) : 0;\n },\n 'r': function (d, i) {\n var lineSeries = d3.select(this.parentNode).datum();\n var circleIndex = that.shouldDrawCircle(lineSeries, i);\n return circleIndex ? LineChart.CircleRadius : 0;\n }\n });\n if (this.isInteractiveChart && this.hasDataPoint(data.series)) {\n var selectionSize_1 = updateSelection.size();\n var endedTransitionCount_1 = 0;\n transitions.each('end', function () {\n // When transitions finish, and it's an interactive chart - select the last column (draw the legend and the handle)\n endedTransitionCount_1++;\n if (endedTransitionCount_1 === selectionSize_1) {\n _this.selectColumn(visuals.CartesianHelper.findMaxCategoryIndex(data.series), true);\n }\n });\n }\n var dataPoints = null;\n if (data.dataLabelsSettings.show) {\n dataPoints = [];\n for (var i = 0, ilen = data.series.length; i < ilen; i++) {\n Array.prototype.push.apply(dataPoints, data.series[i].data);\n }\n }\n catSelect.exit().remove();\n // # Code from here is taken from renderNew:\n // Add data labels\n var labelDataPointsGroups;\n if (data.dataLabelsSettings.show)\n labelDataPointsGroups = this.createLabelDataPoints();\n return dataPoints == null ? null : {\n dataPoints: dataPoints,\n behaviorOptions: null,\n labelDataPoints: null,\n labelsAreNumeric: null,\n labelDataPointGroups: labelDataPointsGroups\n };\n };\n /**\n * Note: Public for tests.\n */\n LineChart.prototype.getSeriesTooltipInfo = function (pointData) {\n var tooltipinfo = [];\n var maxNumberOfItems = 10; // to limit the number of rows we display\n // count to the maximum number of rows we can display\n var count = 0;\n for (var _i = 0, pointData_1 = pointData; _i < pointData_1.length; _i++) {\n var point = pointData_1[_i];\n if (count >= maxNumberOfItems)\n break;\n if (point.value != null) {\n tooltipinfo.push({\n header: point.category,\n color: point.color,\n displayName: point.label,\n value: point.measure\n });\n count++;\n }\n }\n if (tooltipinfo.length === 0)\n return null; //don't draw an empty tooltip container\n return tooltipinfo;\n };\n /**\n * Note: Public for tests.\n */\n LineChart.prototype.getTooltipInfoForCombo = function (tooltipEvent, pointX) {\n // update pointX, the mouse coordinate, with the left-offset of the SVGRect from the x-scale space so we can use the d3.scale to get the index.\n var categoryIndex = this.getCategoryIndexFromTooltipEvent(tooltipEvent, pointX);\n var seriesData = tooltipEvent.data;\n var dataPoint;\n if (seriesData && seriesData.data && seriesData.data.length) {\n dataPoint = _.find(seriesData.data, function (dp) { return dp.categoryIndex === categoryIndex; });\n }\n if (dataPoint)\n return dataPoint.tooltipInfo;\n // return undefined so we don't show an empty tooltip\n };\n /**\n * Note: Public for tests.\n */\n LineChart.prototype.getCategoryIndexFromTooltipEvent = function (tooltipEvent, pointX) {\n if (tooltipEvent.data && tooltipEvent.data.categoryIndex != null) {\n // Tooltip originated with a dot; simply return the categoryIndex from the dot's bound data\n return tooltipEvent.data.categoryIndex;\n }\n var seriesData = tooltipEvent.data;\n var offsetX = 0; // Offset based on the firstCategoryOffset (since lines don't start at x = 0) as well as the offset due to lines that may not start at the first category\n if (seriesData && !_.isEmpty(seriesData.data) && this.xAxisProperties) {\n // Tooltip originated from a path; determine series offset from the first point that is part of a path\n pointX = this.adjustPathXCoordinate(pointX);\n var firstPathPoint = _.find(seriesData.data, function (dataPoint, index, dataPoints) {\n var nextDataPoint = dataPoints[index + 1];\n return dataPoint.value != null && nextDataPoint && nextDataPoint.value != null;\n });\n debug.assertValue(firstPathPoint, \"If there is data on the tooltipEvent but no categoryIndex, there should always be two consecutive non-null values\");\n offsetX = this.xAxisProperties.scale(this.getXValue(firstPathPoint)) + this.getXOfFirstCategory();\n }\n // else: Tooltip originated from the background; no offsetX is needed\n return this.findIndex(pointX, offsetX);\n };\n LineChart.prototype.getVisualCategoryAxisIsScalar = function () {\n return this.data ? this.data.isScalar : false;\n };\n LineChart.prototype.getSupportedCategoryAxisType = function () {\n var dvCategories = this.dataViewCat ? this.dataViewCat.categories : undefined;\n var categoryType = powerbi.ValueType.fromDescriptor({ text: true });\n if (dvCategories && dvCategories.length > 0 && dvCategories[0].source && dvCategories[0].source.type)\n categoryType = dvCategories[0].source.type;\n var isOrdinal = visuals.AxisHelper.isOrdinal(categoryType);\n return isOrdinal ? visuals.axisType.categorical : visuals.axisType.both;\n };\n LineChart.prototype.getPreferredPlotArea = function (isScalar, categoryCount, categoryThickness) {\n return visuals.CartesianChart.getPreferredPlotArea(categoryCount, categoryThickness, this.currentViewport, this.isScrollable, isScalar, this.margin, true);\n };\n LineChart.prototype.getCategoryCount = function (origCatgSize) {\n var availableWidth = this.getAvailableWidth();\n var categoryThickness = visuals.CartesianChart.MinOrdinalRectThickness;\n return Math.min(Math.round((availableWidth - categoryThickness * visuals.CartesianChart.OuterPaddingRatio * 2) / categoryThickness), origCatgSize);\n };\n LineChart.prototype.getAvailableWidth = function () {\n return this.currentViewport.width - (this.margin.left + this.margin.right);\n };\n LineChart.prototype.getAvailableHeight = function () {\n return this.currentViewport.height - (this.margin.top + this.margin.bottom);\n };\n LineChart.sliceSeries = function (series, newLength, startIndex) {\n if (startIndex === void 0) { startIndex = 0; }\n var newSeries = [];\n if (series && series.length > 0) {\n debug.assert(series[0].data.length >= newLength, \"invalid newLength\");\n for (var i = 0, len = series.length; i < len; i++) {\n newSeries[i] = powerbi.Prototype.inherit(series[i]);\n newSeries[i].data = series[i].data.slice(startIndex, startIndex + newLength);\n }\n }\n return newSeries;\n };\n LineChart.prototype.getXOfFirstCategory = function () {\n if (!this.data.isScalar) {\n // This will place the line points in the middle of the bands\n // So they center with Labels when scale is ordinal.\n var xScale = this.xAxisProperties.scale;\n if (xScale.rangeBand) {\n return xScale.rangeBand() / 2;\n }\n }\n return 0;\n };\n LineChart.prototype.hasDataPoint = function (series) {\n if (series.length === 0)\n return false;\n for (var i = 0, len = series.length; i < len; i++) {\n if (series[i].data.length > 0)\n return true;\n }\n return false;\n };\n LineChart.prototype.getXValue = function (d) {\n return this.data.isScalar ? d.categoryValue : d.categoryIndex;\n };\n /**\n * This checks to see if a data point is isolated, which means\n * the previous and next data point are both null.\n */\n LineChart.prototype.shouldDrawCircle = function (d, i) {\n var dataLength = d.data.length;\n var isLastPoint = i === (dataLength - 1);\n var isFirstPoint = i === 0;\n if (i > dataLength - 1 || d.data[i] === null || d.data[i].value === null)\n return false;\n if (isFirstPoint && isLastPoint)\n return true;\n if (isFirstPoint && dataLength > 1 && d.data[i + 1].value === null)\n return true;\n if (!isFirstPoint && isLastPoint && d.data[i - 1].value === null)\n return true;\n if (!isFirstPoint && !isLastPoint && d.data[i - 1].value === null && d.data[i + 1].value === null)\n return true;\n return false;\n };\n LineChart.prototype.selectColumnForTooltip = function (columnIndex, force) {\n if (force === void 0) { force = false; }\n var x = this.getChartX(columnIndex) + this.getXOfFirstCategory();\n var dataPoints = this.createTooltipDataPoints(columnIndex);\n if (dataPoints.length > 0) {\n this.setHoverLineForTooltip(x);\n }\n this.setDotsForTooltip(x, dataPoints);\n return dataPoints;\n };\n LineChart.prototype.setHoverLineForTooltip = function (chartX) {\n chartX = chartX || 0;\n this.hoverLine\n .attr('x1', chartX)\n .attr('x2', chartX)\n .attr(\"y1\", 0)\n .attr(\"y2\", this.getAvailableHeight())\n .style('opacity', 1);\n };\n LineChart.prototype.setDotsForTooltip = function (chartX, dataPoints) {\n var _this = this;\n var isStackedArea = EnumExtensions.hasFlag(this.lineType, 16 /* stackedArea */);\n var dotYPosition = isStackedArea ? function (d) { return _this.yAxisProperties.scale(d.stackedValue); } : function (d) { return _this.yAxisProperties.scale(d.value); };\n var tooltipDots = this.hoverLineContext.selectAll(LineChart.HoverLineCircleDot.selector).data(dataPoints);\n tooltipDots\n .enter()\n .append(LineChart.CircleElementName)\n .classed(LineChart.HoverLineCircleDot.class, true);\n tooltipDots\n .filter(function (d) { return d.value; })\n .attr('fill', function (d) { return d.color; })\n .attr(\"r\", 3)\n .attr(\"cx\", chartX)\n .attr(\"cy\", dotYPosition);\n tooltipDots.exit().remove();\n };\n /**\n * Updates the hover line and the legend with the selected colums (given by columnIndex).\n * This is for the Mobile renderer with InteractiveLegend\n */\n LineChart.prototype.selectColumn = function (columnIndex, force) {\n if (force === void 0) { force = false; }\n if (!force && this.lastInteractiveSelectedColumnIndex === columnIndex)\n return; // same column, nothing to do here\n this.lastInteractiveSelectedColumnIndex = columnIndex;\n var x = this.getChartX(columnIndex);\n this.setHoverLine(x, columnIndex);\n var legendItems = this.createLegendDataPoints(columnIndex);\n if (legendItems)\n this.options.cartesianHost.updateLegend(legendItems);\n };\n LineChart.prototype.setHoverLine = function (chartX, columnIndex) {\n this.hoverLine\n .attr('x1', chartX)\n .attr('x2', chartX)\n .attr(\"y1\", 0).attr(\"y2\", this.getAvailableHeight())\n .style('opacity', 1);\n var that = this;\n this.mainGraphicsContext\n .selectAll(LineChart.CategorySelector.selector)\n .selectAll(LineChart.PathElementName)\n .each(function (series) {\n var _this = this;\n // Get the item color for the handle dots\n var color = series.color;\n var circleToChange = that.selectionCircles[series.lineIndex];\n circleToChange\n .attr({\n 'cx': chartX,\n 'cy': function () {\n var pathElement = d3.select(_this).node();\n var pos = that.getPosition(chartX, pathElement);\n return pos.y;\n }\n })\n .style({\n 'opacity': function () { return _.some(series.data, function (value) { return value.categoryIndex === columnIndex; }) ? 1 : 0; },\n 'fill': color\n });\n if (that.dragHandle)\n that.dragHandle.attr('cx', chartX);\n });\n };\n LineChart.prototype.getChartX = function (columnIndex) {\n var x = 0;\n if (this.data.isScalar) {\n if (columnIndex >= 0 && columnIndex < this.data.categoryData.length)\n x = Math.max(0, this.xAxisProperties.scale(this.data.categoryData[columnIndex].categoryValue));\n }\n else {\n x = Math.max(0, this.xAxisProperties.scale(columnIndex));\n }\n var rangeEnd = powerbi.visuals.AxisHelper.extent(this.xAxisProperties.scale)[1];\n x = Math.min(x, rangeEnd);\n if (!isNaN(x))\n return x;\n return 0;\n };\n /**\n * Finds the index of the category of the given x coordinate given.\n * pointX is in non-scaled screen-space, and offsetX is in render-space.\n * offsetX does not need any scaling adjustment.\n * @param {number} pointX The mouse coordinate in screen-space, without scaling applied\n * @param {number} offsetX Any left offset in d3.scale render-space\n * @return {number}\n */\n LineChart.prototype.findIndex = function (pointX, offsetX) {\n // we are using mouse coordinates that do not know about any potential CSS transform scale\n var xScale = this.scaleDetector.getScale().x;\n if (!powerbi.Double.equalWithPrecision(xScale, 1.0, 0.00001)) {\n pointX = pointX / xScale;\n }\n if (offsetX) {\n pointX += offsetX;\n }\n var index = powerbi.visuals.AxisHelper.invertScale(this.xAxisProperties.scale, pointX);\n if (this.data.isScalar) {\n // When we have scalar data the inverted scale produces a category value, so we need to search for the closest index.\n index = visuals.AxisHelper.findClosestXAxisIndex(index, this.data.categoryData);\n }\n return index;\n };\n LineChart.prototype.getPosition = function (x, pathElement) {\n var pathLength = pathElement.getTotalLength();\n var pos;\n var beginning = 0, end = pathLength, target;\n while (true) {\n target = Math.floor((beginning + end) / 2);\n pos = pathElement.getPointAtLength(target);\n visuals.SVGUtil.ensureValidSVGPoint(pos);\n if ((target === end || target === beginning) && pos.x !== x)\n break;\n if (pos.x > x)\n end = target;\n else if (pos.x < x)\n beginning = target;\n else\n break;\n }\n return pos;\n };\n LineChart.prototype.createTooltipDataPoints = function (columnIndex) {\n var data = this.data;\n if (!data || data.series.length === 0 || !data.categoryData)\n return [];\n var dataPoints = [];\n var category;\n debug.assert(columnIndex < data.categoryData.length, 'category index out of range');\n var categoryDataPoint = data.categoryData[columnIndex];\n if (this.data.isScalar) {\n if (categoryDataPoint) {\n if (visuals.AxisHelper.isDateTime(this.xAxisProperties.axisType)) {\n category = visuals.CartesianHelper.lookupXValue(this.data, categoryDataPoint.categoryValue, this.xAxisProperties.axisType, this.data.isScalar);\n }\n else {\n category = categoryDataPoint.categoryValue;\n }\n }\n }\n else {\n category = visuals.CartesianHelper.lookupXValue(this.data, columnIndex, this.xAxisProperties.axisType, this.data.isScalar);\n }\n var formatStringProp = visuals.lineChartProps.general.formatString;\n for (var _i = 0, _a = data.series; _i < _a.length; _i++) {\n var series = _a[_i];\n var lineData = series.data;\n var lineDataPoint = void 0;\n if (this.data.isScalar) {\n if (categoryDataPoint) {\n lineDataPoint = lineData.filter(function (data) {\n return data.categoryValue === categoryDataPoint.categoryValue;\n })[0];\n }\n }\n else {\n lineDataPoint = lineData[columnIndex];\n }\n var value = lineDataPoint && lineDataPoint.value;\n if (value != null) {\n var label = visuals.converterHelper.getFormattedLegendLabel(series.yCol, this.dataViewCat.values, formatStringProp);\n dataPoints.push({\n color: series.color,\n label: label,\n category: visuals.valueFormatter.format(category, visuals.valueFormatter.getFormatString(series.xCol, formatStringProp)),\n measure: visuals.valueFormatter.format(value, visuals.valueFormatter.getFormatString(series.yCol, formatStringProp)),\n value: value,\n stackedValue: lineDataPoint.stackedValue\n });\n }\n }\n return dataPoints;\n };\n LineChart.prototype.createLegendDataPoints = function (columnIndex) {\n var data = this.data;\n if (!data || !data.series || data.series.length < 1)\n return;\n var legendDataPoints = [];\n var category;\n // 'category' and 'measure' are only for Mobile interactive legend, Minerva legend does not need them\n var categoryDataPoint = data.categoryData[columnIndex];\n if (this.isInteractiveChart && categoryDataPoint) {\n if (this.data.isScalar) {\n category = categoryDataPoint.categoryValue;\n if (visuals.AxisHelper.isDateTime(this.xAxisProperties.axisType))\n category = new Date(category);\n }\n else {\n category = visuals.CartesianHelper.lookupXValue(this.data, columnIndex, this.xAxisProperties.axisType, this.data.isScalar);\n }\n }\n var formatStringProp = visuals.lineChartProps.general.formatString;\n var seriesYCol = null;\n // iterating over the line data (i is for a line)\n for (var i = 0, len = data.series.length; i < len; i++) {\n var series = data.series[i];\n var lineData = series.data;\n // 'category' and 'measure' are only for Mobile interactive legend, Minerva legend does not need them\n var measure = void 0;\n if (this.isInteractiveChart) {\n var lineDataPoint = void 0;\n if (this.data.isScalar) {\n // Scalar series skip null values, and therefore do not share the same category index\n // Search this series for the categoryValue - it may not exist\n if (categoryDataPoint) {\n var targetCategoryValue = categoryDataPoint.categoryValue;\n for (var i_1 = 0; i_1 < lineData.length; i_1++) {\n if (lineData[i_1].categoryValue === targetCategoryValue) {\n lineDataPoint = lineData[i_1];\n break;\n }\n }\n }\n }\n else {\n // ordinal series all share the same x-indicies\n lineDataPoint = lineData[columnIndex];\n }\n measure = lineDataPoint && lineDataPoint.value;\n }\n var label = visuals.converterHelper.getFormattedLegendLabel(series.yCol, this.dataViewCat.values, formatStringProp);\n seriesYCol = series.yCol;\n legendDataPoints.push({\n color: series.color,\n icon: visuals.LegendIcon.Line,\n label: label,\n // TODO: category: CartesianChartInteractiveLegend only needs one category value for part of the Title, we don't need to put it on each point.\n category: visuals.valueFormatter.format(category, visuals.valueFormatter.getFormatString(series.xCol, formatStringProp)),\n measure: visuals.valueFormatter.format(measure, visuals.valueFormatter.getFormatString(series.yCol, formatStringProp)),\n identity: series.identity,\n selected: series.selected,\n });\n }\n var dvValues = this.dataViewCat ? this.dataViewCat.values : null;\n var title = dvValues && dvValues.source ? dvValues.source.displayName : \"\";\n return {\n title: title,\n dataPoints: legendDataPoints\n };\n };\n LineChart.prototype.createLabelDataPoints = function () {\n var _this = this;\n var xScale = this.xAxisProperties.scale;\n var yScale = this.yAxisProperties.scale;\n var lineshift = this.getXOfFirstCategory();\n var data = this.data;\n var series = data.series;\n var formattersCache = visuals.NewDataLabelUtils.createColumnFormatterCacheManager();\n var dataLabelsSettings = data.dataLabelsSettings;\n var isStackedArea = EnumExtensions.hasFlag(this.lineType, 16 /* stackedArea */);\n var labelDataPointsGroups = [];\n var labelSettings;\n var axisFormatter;\n var seriesLabelDataPoints;\n var seriesDataPointsCandidates;\n var seriesIndex;\n var seriesCount;\n for (seriesIndex = 0, seriesCount = series.length; seriesIndex < seriesCount; seriesIndex++) {\n var currentSeries = series[seriesIndex];\n labelSettings = (currentSeries.labelSettings) ? currentSeries.labelSettings : dataLabelsSettings;\n if (!labelSettings.show)\n continue;\n axisFormatter = visuals.NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yAxisProperties.formatter, labelSettings);\n var dataPoints = currentSeries.data;\n seriesLabelDataPoints = [];\n seriesDataPointsCandidates = [];\n var createLabelDataPoint = function (dataPoint) {\n if (dataPoint.value == null)\n return null;\n var formatString = \"\";\n formatString = dataPoint.labelFormatString;\n var formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\n var text = visuals.NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties) + visuals.NewDataLabelUtils.LabelDensityPadding;\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\n var parentShape;\n var isParentRect = false;\n if (isStackedArea) {\n var bottomPos = Math.max(dataPoint.stackedValue - dataPoint.value, yScale.domain()[0]); //this is to make sure the bottom position doesn't go below the domain\n var areaWidth = _this.currentViewport.width; // Conceptually, we allow line labels to fill the full plot area, so the width is equal to the plot area\n parentShape = {\n rect: {\n left: xScale(_this.getXValue(dataPoint)) - areaWidth / 2,\n top: yScale(Math.max(dataPoint.stackedValue, dataPoint.stackedValue - dataPoint.value)),\n width: areaWidth,\n height: Math.abs(yScale(dataPoint.stackedValue) - yScale(bottomPos))\n },\n orientation: dataPoint.value >= 0 ? 1 /* VerticalBottomBased */ : 2 /* VerticalTopBased */,\n validPositions: LineChart.validStackedLabelPositions,\n };\n isParentRect = true;\n }\n else {\n parentShape = {\n point: {\n x: xScale(_this.getXValue(dataPoint)) + lineshift,\n y: yScale(dataPoint.value),\n },\n radius: 0,\n validPositions: _this.lineChartLabelDensityEnabled ? LineChart.validLabelPositions : [1 /* Above */],\n };\n }\n var labelDataPoint = {\n isPreferred: false,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : visuals.NewDataLabelUtils.defaultLabelColor,\n insideFill: labelSettings.labelColor && isStackedArea ? labelSettings.labelColor : visuals.NewDataLabelUtils.defaultInsideLabelColor,\n parentType: isParentRect ? 1 /* Rectangle */ : 0 /* Point */,\n parentShape: parentShape,\n fontSize: labelSettings.fontSize,\n identity: dataPoint.identity,\n key: dataPoint.key,\n };\n return labelDataPoint;\n };\n if (!_.isEmpty(dataPoints)) {\n var categoryCount = dataPoints.length;\n var lastDataPoint = dataPoints[categoryCount - 1];\n var lastLabelDataPoint = createLabelDataPoint(lastDataPoint, seriesIndex);\n if (lastLabelDataPoint)\n seriesLabelDataPoints.push(lastLabelDataPoint);\n for (var categoryIndex = 0; categoryIndex < categoryCount - 1; categoryIndex++) {\n var labelDataPoint = createLabelDataPoint(dataPoints[categoryIndex], seriesIndex);\n if (labelDataPoint)\n seriesLabelDataPoints.push(labelDataPoint);\n }\n }\n var maxLabelsToRender = dataPoints.length;\n labelDataPointsGroups[seriesIndex] = {\n labelDataPoints: seriesLabelDataPoints,\n maxNumberOfLabels: maxLabelsToRender,\n };\n }\n return labelDataPointsGroups;\n };\n /**\n * Adjust a mouse coordinate originating from a path; used to fix\n * an inconsistency between Internet Explorer and other browsers.\n *\n * Internet explorer places the origin for the coordinate system of\n * mouse events based on the stroke, so that the very edge of the stroke\n * is zero. Chrome places the 0 on the edge of the path so that the\n * edge of the stroke is -(strokeWidth / 2). We adjust coordinates\n * to match Chrome.\n *\n * TODO: Firefox is similar to IE, but does a very poor job at it, so\n * the edge is inacurate.\n *\n * @param value The x coordinate to be adjusted\n */\n LineChart.prototype.adjustPathXCoordinate = function (x) {\n if (this.shouldAdjustMouseCoordsOnPathsForStroke) {\n var xScale = this.scaleDetector.getScale().x;\n if (!powerbi.Double.equalWithPrecision(xScale, 1.0, 0.00001)) {\n x -= LineChart.pathXAdjustment * xScale;\n }\n else {\n x -= LineChart.pathXAdjustment;\n }\n }\n return x;\n };\n //private isMinMax(index: number, dataPoints: LineChartDataPoint[]): boolean {\n // // Check if the point is the start/end point\n // if (!dataPoints[index - 1] || !dataPoints[index + 1])\n // return true;\n // let currentValue = dataPoints[index].value;\n // let prevValue = dataPoints[index - 1].value;\n // let nextValue = dataPoints[index + 1].value;\n // return (prevValue > currentValue && currentValue < nextValue) // Min point\n // || (prevValue < currentValue && currentValue > nextValue); // Max point\n //}\n //private calculatePointsWeight(labelDataPoints: LabelDataPoint[], dataPointsCandidates: LineChartDataPoint[], minIndex: number, maxIndex: number) {\n // let previousMinMaxIndex = 0;\n // labelDataPoints[0].weight = dataPointsCandidates[0].weight = 0;\n // let previousMinMax: LineChartDataPoint = dataPointsCandidates[0];\n // let dataPointCount = labelDataPoints.length;\n // let yScale = this.yAxisProperties.scale;\n // let totalValueDelta = yScale(dataPointsCandidates[maxIndex].value) - yScale(dataPointsCandidates[minIndex].value);\n // for (let i = 1; i < dataPointCount; i++) {\n // let dataPoint = dataPointsCandidates[i];\n // let weight = (Math.abs(yScale(previousMinMax.value) - yScale(dataPoint.value))) / totalValueDelta + (i - previousMinMaxIndex) / dataPointCount;\n // labelDataPoints[i].weight = weight;\n // if (this.isMinMax(i, dataPointsCandidates)) {\n // previousMinMax.weight += weight;\n // previousMinMax = dataPoint;\n // previousMinMaxIndex = i;\n // }\n // }\n //}\n //private sortByWeightAndPreferrance(a: LabelDataPoint, b: LabelDataPoint): number {\n // // Compare by prederrance first\n // if (!a.isPreferred && b.isPreferred) return 1;\n // if (a.isPreferred && !b.isPreferred) return -1;\n // // Compare by weight\n // if ((!a.weight && b.weight) || (a.weight < b.weight)) return 1;\n // if ((a.weight && !b.weight) || (a.weight > b.weight)) return -1;\n // return 0;\n //}\n LineChart.prototype.showLabelPerSeries = function () {\n var data = this.data;\n return !data.hasDynamicSeries && (data.series.length > 1 || !data.categoryMetadata);\n };\n LineChart.ClassName = 'lineChart';\n LineChart.MainGraphicsContextClassName = 'mainGraphicsContext';\n LineChart.CategorySelector = createClassAndSelector('cat');\n LineChart.CategoryValuePoint = createClassAndSelector('dot');\n LineChart.CategoryPointSelector = createClassAndSelector('point');\n LineChart.CategoryAreaSelector = createClassAndSelector('catArea');\n LineChart.HoverLineCircleDot = createClassAndSelector('circle-item');\n LineChart.LineClassSelector = createClassAndSelector('line');\n LineChart.PointRadius = 5;\n LineChart.CircleRadius = 4;\n LineChart.PathElementName = 'path';\n LineChart.CircleElementName = 'circle';\n LineChart.CircleClassName = 'selection-circle';\n LineChart.LineElementName = 'line';\n LineChart.RectOverlayName = 'rect';\n LineChart.ScalarOuterPadding = 10;\n LineChart.interactivityStrokeWidth = 10;\n LineChart.pathXAdjustment = 5; // Based on half the stroke width for taking stroke into account in coordinate transforms\n LineChart.AreaFillOpacity = 0.4;\n LineChart.DimmedAreaFillOpacity = 0.2;\n LineChart.validLabelPositions = [\n 1 /* Above */,\n 2 /* Below */,\n 8 /* Right */,\n 4 /* Left */,\n 64 /* AboveRight */,\n 128 /* AboveLeft */,\n 16 /* BelowRight */,\n 32 /* BelowLeft */\n ];\n LineChart.validStackedLabelPositions = [1 /* InsideCenter */, 4 /* InsideEnd */, 2 /* InsideBase */];\n return LineChart;\n }());\n visuals.LineChart = LineChart;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Color = jsCommon.Color;\n var PixelConverter = jsCommon.PixelConverter;\n var Polygon = visuals.shapes.Polygon;\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n visuals.MaxLevelOfDetail = 23;\n visuals.MinLevelOfDetail = 1;\n visuals.DefaultFillOpacity = 0.5;\n visuals.DefaultBackgroundColor = \"#000000\";\n visuals.LeaderLineColor = \"#000000\";\n var MapBubbleDataPointRenderer = (function () {\n function MapBubbleDataPointRenderer(tooltipsEnabled) {\n this.tooltipsEnabled = tooltipsEnabled;\n }\n MapBubbleDataPointRenderer.prototype.init = function (mapControl, mapDiv, addClearCatcher) {\n /*\n The layout of the visual would look like :\n <div class=\"visual mapControl\">\n <div class=\"MicrosoftMap\">\n <!-- Bing maps stuff -->\n <svg>\n <rect class=\"clearCatcher\"></rect>\n </svg>\n </div>\n <svg>\n <g class=\"mapBubbles>\n <!-- our geometry -->\n </g>\n <g class=\"mapSlices>\n <!-- our geometry -->\n </g>\n </svg>\n </div>\n \n */\n this.mapControl = mapControl;\n this.root = mapDiv;\n var root = d3.select(mapDiv[0]);\n root.attr(\"drag-resize-disabled\", \"true\"); // Enable panning within the maps in IE\n var svg = this.svg = root\n .append('svg')\n .style(\"position\", \"absolute\") // Absolute position so that the svg will overlap with the canvas.\n .style(\"pointer-events\", \"none\");\n if (addClearCatcher) {\n var clearSvg = this.clearSvg = d3.select(this.mapControl.getRootElement())\n .append('svg')\n .style('position', 'absolute'); // Absolute position so that the svg will overlap with the canvas.\n this.clearCatcher = visuals.appendClearCatcher(clearSvg);\n }\n this.bubbleGraphicsContext = svg\n .append(\"g\")\n .classed(\"mapBubbles\", true);\n this.sliceGraphicsContext = svg\n .append(\"g\")\n .classed(\"mapSlices\", true);\n this.labelBackgroundGraphicsContext = svg\n .append(\"g\")\n .classed(visuals.NewDataLabelUtils.labelBackgroundGraphicsContextClass.class, true);\n this.labelGraphicsContext = svg\n .append(\"g\")\n .classed(visuals.NewDataLabelUtils.labelGraphicsContextClass.class, true);\n this.sliceLayout = d3.layout.pie()\n .sort(null)\n .value(function (d) {\n return d.value;\n });\n this.arc = d3.svg.arc();\n this.clearMaxDataPointRadius();\n this.dataLabelsSettings = visuals.dataLabelUtils.getDefaultMapLabelSettings();\n };\n MapBubbleDataPointRenderer.prototype.setData = function (data) {\n this.mapData = data;\n };\n MapBubbleDataPointRenderer.prototype.clearDataPoints = function () {\n this.mapData = {\n dataPoints: [],\n geocodingCategory: null,\n hasDynamicSeries: false,\n hasSize: false,\n };\n };\n MapBubbleDataPointRenderer.prototype.getDataPointCount = function () {\n if (!this.mapData)\n return 0;\n // Filter out any data points without a location since those aren't actually being drawn\n return _.filter(this.mapData.dataPoints, function (value) { return !!value.location; }).length;\n };\n MapBubbleDataPointRenderer.prototype.getDataPointPadding = function () {\n return this.maxDataPointRadius * 2;\n };\n MapBubbleDataPointRenderer.prototype.clearMaxDataPointRadius = function () {\n this.maxDataPointRadius = 0;\n };\n MapBubbleDataPointRenderer.prototype.setMaxDataPointRadius = function (dataPointRadius) {\n this.maxDataPointRadius = Math.max(dataPointRadius, this.maxDataPointRadius);\n };\n MapBubbleDataPointRenderer.prototype.getDefaultMap = function (geocodingCategory, dataPointCount) {\n this.clearDataPoints();\n };\n MapBubbleDataPointRenderer.prototype.converter = function (viewport, dataView, labelSettings, interactivityService, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var mapControl = this.mapControl;\n var widthOverTwo = viewport.width / 2;\n var heightOverTwo = viewport.height / 2;\n var strokeWidth = 1;\n //update data label settings\n this.dataLabelsSettings = labelSettings;\n // See MapSeriesPresenter::GetDataPointRadius for the PV behavior\n var radiusScale = Math.min(viewport.width, viewport.height) / 384;\n this.clearMaxDataPointRadius();\n var bubbleData = [];\n var sliceData = [];\n var categorical = dataView ? dataView.categorical : null;\n var grouped;\n var sizeIndex = -1;\n var dataValuesSource;\n if (categorical && categorical.values) {\n grouped = categorical.values.grouped();\n sizeIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, \"Size\");\n dataValuesSource = categorical.values.source;\n }\n var dataPoints = this.mapData ? this.mapData.dataPoints : [];\n var hasSize = this.mapData.hasSize;\n for (var categoryIndex = 0, categoryCount = dataPoints.length; categoryIndex < categoryCount; categoryIndex++) {\n var dataPoint = dataPoints[categoryIndex];\n var categoryValue = dataPoint.categoryValue;\n var location_2 = dataPoint.location;\n if (location_2) {\n var xy = mapControl.tryLocationToPixel(new Microsoft.Maps.Location(location_2.latitude, location_2.longitude));\n var x = xy.x + widthOverTwo;\n var y = xy.y + heightOverTwo;\n var radius = dataPoint.radius * radiusScale;\n this.setMaxDataPointRadius(radius);\n var subDataPoints = dataPoint.subDataPoints;\n var seriesCount = subDataPoints.length;\n if (seriesCount === 1) {\n var subDataPoint = subDataPoints[0];\n bubbleData.push({\n x: x,\n y: y,\n labeltext: categoryValue,\n radius: radius,\n fill: subDataPoint.fill,\n stroke: subDataPoint.stroke,\n strokeWidth: strokeWidth,\n tooltipInfo: subDataPoint.tooltipInfo,\n identity: subDataPoint.identity,\n selected: false,\n labelFill: labelSettings.labelColor,\n });\n }\n else {\n var slices = [];\n for (var seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\n var subDataPoint = subDataPoints[seriesIndex];\n var value = hasSize ? subDataPoint.value : 1; // Normalize values if there is no size in the data\n slices.push({\n x: x,\n y: y,\n labeltext: categoryValue,\n radius: radius,\n fill: subDataPoint.fill,\n stroke: subDataPoint.stroke,\n strokeWidth: strokeWidth,\n value: value,\n tooltipInfo: subDataPoint.tooltipInfo,\n identity: subDataPoint.identity,\n selected: false,\n labelFill: labelSettings.labelColor,\n });\n }\n if (interactivityService) {\n interactivityService.applySelectionStateToData(slices);\n }\n sliceData.push(slices);\n }\n }\n }\n if (interactivityService) {\n interactivityService.applySelectionStateToData(bubbleData);\n }\n return { bubbleData: bubbleData, sliceData: sliceData };\n };\n MapBubbleDataPointRenderer.prototype.updateInternal = function (data, viewport, dataChanged, interactivityService, redrawDataLabels) {\n debug.assertValue(viewport, \"viewport\");\n Map.removeTransform3d(this.root);\n this.mapRendererData = data;\n if (this.svg) {\n this.svg\n .style(\"width\", viewport.width.toString() + \"px\")\n .style(\"height\", viewport.height.toString() + \"px\");\n }\n if (this.clearSvg) {\n this.clearSvg\n .style(\"width\", viewport.width.toString() + \"px\")\n .style(\"height\", viewport.height.toString() + \"px\");\n }\n var arc = this.arc;\n var hasSelection = interactivityService && interactivityService.hasSelection();\n var bubbles = this.bubbleGraphicsContext.selectAll(\".bubble\").data(data.bubbleData, function (d) { return d.identity.getKey(); });\n bubbles.enter()\n .append(\"circle\")\n .classed(\"bubble\", true);\n bubbles\n .attr(\"cx\", function (d) { return d.x; })\n .attr(\"cy\", function (d) { return d.y; })\n .attr(\"r\", function (d) { return d.radius; })\n .style(\"fill\", function (d) { return d.fill; })\n .style(\"stroke\", function (d) { return d.stroke; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); })\n .style(\"strokeWidth\", function (d) { return d.strokeWidth; })\n .style(\"stroke-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); })\n .style(\"cursor\", \"default\");\n bubbles.exit().remove();\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(this.bubbleGraphicsContext, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n bubbles.style(\"pointer-events\", \"all\");\n }\n var sliceData = data.sliceData;\n var sliceContainers = this.sliceGraphicsContext.selectAll(\".sliceContainer\").data(sliceData);\n sliceContainers.enter()\n .append(\"g\")\n .classed(\"sliceContainer\", true);\n sliceContainers.exit().remove();\n var sliceLayout = this.sliceLayout;\n var slices = sliceContainers.selectAll(\".slice\")\n .data(function (d) {\n return sliceLayout(d);\n }, function (d) { return d.data.identity.getKey(); });\n slices.enter()\n .append(\"path\")\n .classed(\"slice\", true);\n slices\n .style(\"fill\", function (t) { return t.data.fill; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false); })\n .style(\"stroke\", function (t) { return t.data.stroke; })\n .style(\"strokeWidth\", function (t) { return t.data.strokeWidth; })\n .style(\"stroke-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false); })\n .style(\"cursor\", \"default\")\n .attr(\"transform\", function (t) { return visuals.SVGUtil.translate(t.data.x, t.data.y); })\n .attr('d', function (t) {\n return arc.innerRadius(0).outerRadius(function (t) { return t.data.radius; })(t);\n });\n slices.exit().remove();\n this.updateInternalDataLabels(viewport, redrawDataLabels);\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(this.sliceGraphicsContext, function (tooltipEvent) { return tooltipEvent.data.data.tooltipInfo; });\n slices.style(\"pointer-events\", \"all\");\n }\n var allData = data.bubbleData.slice();\n for (var i = 0, ilen = sliceData.length; i < ilen; i++) {\n allData.push.apply(allData, sliceData[i]);\n }\n var behaviorOptions = {\n bubbleEventGroup: this.bubbleGraphicsContext,\n sliceEventGroup: this.sliceGraphicsContext,\n bubbles: bubbles,\n slices: slices,\n clearCatcher: this.clearCatcher,\n dataPoints: allData,\n };\n return behaviorOptions;\n };\n MapBubbleDataPointRenderer.prototype.updateInternalDataLabels = function (viewport, redrawDataLabels) {\n var labelSettings = this.dataLabelsSettings;\n var dataLabels = [];\n if (labelSettings && (labelSettings.show || labelSettings.showCategory)) {\n var labelDataPoints = this.createLabelDataPoints();\n var labelLayout = new powerbi.LabelLayout({\n maximumOffset: visuals.NewDataLabelUtils.maxLabelOffset,\n startingOffset: visuals.NewDataLabelUtils.startingLabelOffset\n });\n var labelDataPointsGroup = {\n labelDataPoints: labelDataPoints,\n maxNumberOfLabels: labelDataPoints.length\n };\n dataLabels = labelLayout.layout([labelDataPointsGroup], { width: viewport.width, height: viewport.height });\n }\n visuals.NewDataLabelUtils.drawLabelBackground(this.labelGraphicsContext, dataLabels, powerbi.visuals.DefaultBackgroundColor, powerbi.visuals.DefaultFillOpacity);\n visuals.NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, dataLabels, false); // Once we properly split up and handle show and showCategory, the false here should change to !labelSettings.showCategory\n };\n MapBubbleDataPointRenderer.prototype.createLabelDataPoints = function () {\n var data = this.mapRendererData;\n var labelDataPoints = [];\n var dataPoints = data.bubbleData;\n dataPoints = dataPoints.concat(_.map(data.sliceData, function (value) { return value[0]; }));\n var labelSettings = this.dataLabelsSettings;\n for (var _i = 0, dataPoints_4 = dataPoints; _i < dataPoints_4.length; _i++) {\n var dataPoint = dataPoints_4[_i];\n debug.assertValue(dataPoint, 'dataPoint should never be null/undefined');\n var text = dataPoint.labeltext;\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties);\n labelDataPoints.push({\n isPreferred: true,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : visuals.NewDataLabelUtils.defaultInsideLabelColor,\n insideFill: visuals.NewDataLabelUtils.defaultInsideLabelColor,\n parentType: 0 /* Point */,\n parentShape: {\n point: {\n x: dataPoint.x,\n y: dataPoint.y,\n },\n radius: dataPoint.radius,\n validPositions: MapBubbleDataPointRenderer.validLabelPositions,\n },\n fontSize: labelSettings.fontSize,\n identity: undefined,\n hasBackground: true,\n });\n }\n return labelDataPoints;\n };\n MapBubbleDataPointRenderer.validLabelPositions = [1 /* Above */, 2 /* Below */, 4 /* Left */, 8 /* Right */];\n return MapBubbleDataPointRenderer;\n }());\n visuals.MapBubbleDataPointRenderer = MapBubbleDataPointRenderer;\n var MapShapeDataPointRenderer = (function () {\n function MapShapeDataPointRenderer(fillMapDataLabelsEnabled, tooltipsEnabled) {\n this.filledMapDataLabelsEnabled = fillMapDataLabelsEnabled;\n this.tooltipsEnabled = tooltipsEnabled;\n }\n MapShapeDataPointRenderer.getFilledMapParams = function (category, dataCount) {\n switch (category) {\n case visuals.MapUtil.CategoryTypes.Continent:\n case visuals.MapUtil.CategoryTypes.CountryRegion:\n if (dataCount < 10) {\n return { level: 1, maxPolygons: 50, strokeWidth: 0 };\n }\n else if (dataCount < 30) {\n return { level: 1, maxPolygons: 20, strokeWidth: 0 };\n }\n return { level: 1, maxPolygons: 5, strokeWidth: 0 };\n default:\n if (dataCount < 100) {\n return { level: 1, maxPolygons: 5, strokeWidth: 6 };\n }\n if (dataCount < 200) {\n return { level: 0, maxPolygons: 5, strokeWidth: 6 };\n }\n return { level: 0, maxPolygons: 5, strokeWidth: 0 };\n }\n };\n MapShapeDataPointRenderer.buildPaths = function (locations) {\n var paths = [];\n for (var i = 0; i < locations.length; i++) {\n var location_3 = locations[i];\n var polygon = location_3.geographic;\n if (polygon.length > 2) {\n paths.push(location_3);\n }\n }\n return paths;\n };\n MapShapeDataPointRenderer.prototype.init = function (mapControl, mapDiv, addClearCatcher) {\n /*\n The layout of the visual would look like :\n <div class=\"visual mapControl\">\n <div class=\"MicrosoftMap\">\n <!-- Bing maps stuff -->\n <svg>\n <rect class=\"clearCatcher\"></rect>\n </svg>\n </div>\n <svg>\n <g class=\"mapShapes>\n <!-- our geometry -->\n </g>\n </svg>\n </div>\n \n */\n this.mapControl = mapControl;\n this.polygonInfo = new visuals.MapPolygonInfo();\n this.root = mapDiv;\n var root = d3.select(mapDiv[0]);\n root.attr('drag-resize-disabled', 'true'); // Enable panning within the maps in IE\n var svg = this.svg = root\n .append('svg')\n .style('position', 'absolute') // Absolute position so that the svg will overlap with the canvas.\n .style(\"pointer-events\", \"none\");\n if (addClearCatcher) {\n var clearSvg = this.clearSvg = d3.select(this.mapControl.getRootElement())\n .append('svg')\n .style('position', 'absolute'); // Absolute position so that the svg will overlap with the canvas.\n this.clearCatcher = visuals.appendClearCatcher(clearSvg);\n }\n this.shapeGraphicsContext = svg\n .append('g')\n .classed('mapShapes', true);\n this.labelBackgroundGraphicsContext = svg\n .append(\"g\")\n .classed(visuals.NewDataLabelUtils.labelBackgroundGraphicsContextClass.class, true);\n this.labelGraphicsContext = svg\n .append(\"g\")\n .classed(visuals.NewDataLabelUtils.labelGraphicsContextClass.class, true);\n this.clearMaxShapeDimension();\n this.dataLabelsSettings = visuals.dataLabelUtils.getDefaultMapLabelSettings();\n };\n MapShapeDataPointRenderer.prototype.setData = function (data) {\n this.mapData = data;\n };\n MapShapeDataPointRenderer.prototype.clearDataPoints = function () {\n this.mapData = {\n dataPoints: [],\n geocodingCategory: null,\n hasDynamicSeries: false,\n hasSize: false,\n };\n };\n MapShapeDataPointRenderer.prototype.getDataPointCount = function () {\n if (!this.mapData)\n return 0;\n // Filter out any data points without a location since those aren't actually being drawn\n return _.filter(this.mapData.dataPoints, function (value) { return !!value.paths; }).length;\n };\n MapShapeDataPointRenderer.prototype.converter = function (viewport, dataView, labelSettings, interactivityService) {\n this.clearMaxShapeDimension();\n this.dataLabelsSettings = labelSettings;\n var strokeWidth = 1;\n var shapeData = [];\n var dataPoints = this.mapData ? this.mapData.dataPoints : [];\n for (var categoryIndex = 0, categoryCount = dataPoints.length; categoryIndex < categoryCount; categoryIndex++) {\n var categorical = dataView ? dataView.categorical : null;\n var dataPoint = dataPoints[categoryIndex];\n var subDataPoint = dataPoint.subDataPoints[0];\n var paths = dataPoint.paths;\n var grouped = void 0;\n var sizeIndex = -1;\n var dataValuesSource = void 0;\n if (categorical && categorical.values) {\n grouped = categorical.values.grouped();\n sizeIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, \"Size\");\n dataValuesSource = categorical.values.source;\n }\n if (paths) {\n var value = dataPoint.value;\n var categoryValue = dataPoint.categoryValue;\n var identity = subDataPoint.identity;\n var idKey = identity.getKey();\n var formattersCache = visuals.NewDataLabelUtils.createColumnFormatterCacheManager();\n //Determine Largest Shape\n var mainShapeIndex = MapShapeDataPointRenderer.getIndexOfLargestShape(paths);\n for (var pathIndex = 0, pathCount = paths.length; pathIndex < pathCount; pathIndex++) {\n var path = paths[pathIndex];\n var labelFormatString = (dataView && dataView.categorical && !_.isEmpty(dataView.categorical.values)) ? visuals.valueFormatter.getFormatString(dataView.categorical.values[0].source, visuals.filledMapProps.general.formatString) : undefined;\n this.setMaxShapeDimension(path.absoluteBounds.width, path.absoluteBounds.height);\n var formatter = formattersCache.getOrCreate(labelFormatString, labelSettings);\n shapeData.push({\n absolutePointArray: path.absolute,\n path: path.absoluteString,\n fill: subDataPoint.fill,\n stroke: subDataPoint.stroke,\n strokeWidth: strokeWidth,\n tooltipInfo: subDataPoint.tooltipInfo,\n identity: identity,\n selected: false,\n key: JSON.stringify({ id: idKey, pIdx: pathIndex }),\n displayLabel: pathIndex === mainShapeIndex,\n labeltext: categoryValue,\n catagoryLabeltext: (value != null) ? visuals.NewDataLabelUtils.getLabelFormattedText(formatter.format(value)) : undefined,\n labelFormatString: labelFormatString,\n });\n }\n }\n }\n if (interactivityService)\n interactivityService.applySelectionStateToData(shapeData);\n return { shapeData: shapeData };\n };\n MapShapeDataPointRenderer.prototype.updateInternal = function (data, viewport, dataChanged, interactivityService, redrawDataLabels) {\n debug.assertValue(viewport, \"viewport\");\n Map.removeTransform3d(this.root);\n this.mapRendererData = data;\n if (this.svg) {\n this.svg\n .style(\"width\", viewport.width.toString() + \"px\")\n .style(\"height\", viewport.height.toString() + \"px\");\n }\n if (this.clearSvg) {\n this.clearSvg\n .style(\"width\", viewport.width.toString() + \"px\")\n .style(\"height\", viewport.height.toString() + \"px\");\n }\n this.polygonInfo.reCalc(this.mapControl, viewport.width, viewport.height);\n this.shapeGraphicsContext.attr(\"transform\", this.polygonInfo.transformToString(this.polygonInfo.transform));\n var hasSelection = interactivityService && interactivityService.hasSelection();\n var shapes = this.shapeGraphicsContext.selectAll(\"polygon\").data(data.shapeData, function (d) { return d.key; });\n shapes.enter()\n .append(\"polygon\")\n .classed(\"shape\", true)\n .attr(\"points\", function (d) {\n return d.path;\n });\n shapes\n .style(\"fill\", function (d) { return d.fill; })\n .style(\"fill-opacity\", function (d) { return visuals.ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false); })\n .style(\"cursor\", \"default\");\n if (dataChanged) {\n // We only update the paths of existing shapes if we have a change in the data. Updating the lengthy path\n // strings every update during resize or zooming/panning is extremely bad for performance.\n shapes\n .attr(\"points\", function (d) {\n return d.path;\n });\n }\n shapes.exit()\n .remove();\n this.updateInternalDataLabels(viewport, redrawDataLabels);\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(this.shapeGraphicsContext, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n shapes.style(\"pointer-events\", \"all\");\n }\n var behaviorOptions = {\n shapeEventGroup: this.shapeGraphicsContext,\n shapes: shapes,\n clearCatcher: this.clearCatcher,\n dataPoints: data.shapeData,\n };\n return behaviorOptions;\n };\n MapShapeDataPointRenderer.prototype.getDataPointPadding = function () {\n return 12;\n };\n MapShapeDataPointRenderer.getIndexOfLargestShape = function (paths) {\n var largestShapeIndex = 0;\n var largestShapeArea = 0;\n for (var pathIndex = 0, pathCount = paths.length; pathIndex < pathCount; pathIndex++) {\n var path = paths[pathIndex];\n // Using the area of the polygon (and taking the largest)\n var polygon = new Polygon(path.absolute);\n var currentShapeArea = Math.abs(Polygon.calculateAbsolutePolygonArea(polygon.polygonPoints));\n if (currentShapeArea > largestShapeArea) {\n largestShapeIndex = pathIndex;\n largestShapeArea = currentShapeArea;\n }\n }\n return largestShapeIndex;\n };\n MapShapeDataPointRenderer.prototype.updateInternalDataLabels = function (viewport, redrawDataLabels) {\n var labelSettings = this.dataLabelsSettings;\n var labels;\n if (labelSettings && (labelSettings.show || labelSettings.showCategory)) {\n var labelDataPoints = this.createLabelDataPoints();\n if (this.labelLayout === undefined) {\n this.labelLayout = new powerbi.FilledMapLabelLayout();\n }\n labels = this.labelLayout.layout(labelDataPoints, { width: viewport.width, height: viewport.height }, this.polygonInfo.transform, redrawDataLabels);\n }\n this.drawLabelStems(this.labelGraphicsContext, labels, labelSettings.show, labelSettings.showCategory);\n visuals.NewDataLabelUtils.drawLabelBackground(this.labelGraphicsContext, labels, powerbi.visuals.DefaultBackgroundColor, powerbi.visuals.DefaultFillOpacity);\n visuals.NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, labels, false, labelSettings.show && labelSettings.showCategory);\n };\n MapShapeDataPointRenderer.prototype.clearMaxShapeDimension = function () {\n this.maxShapeDimension = 0;\n };\n MapShapeDataPointRenderer.prototype.setMaxShapeDimension = function (width, height) {\n this.maxShapeDimension = Math.max(width, this.maxShapeDimension);\n this.maxShapeDimension = Math.max(height, this.maxShapeDimension);\n };\n MapShapeDataPointRenderer.prototype.createLabelDataPoints = function () {\n var data = this.mapRendererData;\n var labelDataPoints = [];\n if (this.filledMapDataLabelsEnabled) {\n var dataShapes = data.shapeData;\n var labelSettings = this.dataLabelsSettings;\n for (var _i = 0, dataShapes_1 = dataShapes; _i < dataShapes_1.length; _i++) {\n var dataShape = dataShapes_1[_i];\n if (!dataShape.displayLabel) {\n continue;\n }\n var text = void 0, secondRowText = void 0;\n var secondRowTextWidth = 0;\n var hasSecondRow = false;\n if (this.dataLabelsSettings.show && !this.dataLabelsSettings.showCategory) {\n text = dataShape.catagoryLabeltext;\n if (text === undefined)\n continue;\n }\n else if (this.dataLabelsSettings.showCategory && !this.dataLabelsSettings.show) {\n text = dataShape.labeltext;\n if (text === undefined)\n continue;\n }\n else if (this.dataLabelsSettings.showCategory && this.dataLabelsSettings.show) {\n text = dataShape.catagoryLabeltext;\n secondRowText = dataShape.labeltext;\n if (text === undefined && secondRowText === undefined)\n continue;\n hasSecondRow = true;\n }\n if (hasSecondRow) {\n var secondRowProperties = {\n text: secondRowText,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: visuals.NewDataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n secondRowTextWidth = powerbi.TextMeasurementService.measureSvgTextWidth(secondRowProperties);\n }\n var firstRowProperties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: visuals.NewDataLabelUtils.LabelTextProperties.fontSize,\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(firstRowProperties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(firstRowProperties);\n if (secondRowText && dataShape.labeltext !== undefined && dataShape.catagoryLabeltext !== undefined) {\n textHeight = textHeight * 2;\n }\n var labelDataPoint = {\n parentType: 2 /* Polygon */,\n parentShape: {\n polygon: new Polygon(dataShape.absolutePointArray),\n validPositions: MapShapeDataPointRenderer.validLabelPolygonPositions,\n },\n text: text,\n secondRowText: secondRowText,\n textSize: {\n width: Math.max(textWidth, secondRowTextWidth),\n height: textHeight,\n },\n insideFill: labelSettings.labelColor,\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : visuals.NewDataLabelUtils.defaultInsideLabelColor,\n isPreferred: false,\n identity: undefined,\n hasBackground: true,\n };\n labelDataPoints.push(labelDataPoint);\n }\n }\n return labelDataPoints;\n };\n MapShapeDataPointRenderer.prototype.drawLabelStems = function (labelsContext, dataLabels, showText, showCategory) {\n var filteredLabels = _.filter(dataLabels, function (d) { return d.isVisible; });\n var key = function (d, index) { return d.identity ? d.identity.getKeyWithoutHighlight() : index; };\n visuals.NewDataLabelUtils.drawLabelLeaderLines(labelsContext, filteredLabels, key, visuals.LeaderLineColor);\n };\n MapShapeDataPointRenderer.validLabelPolygonPositions = [256 /* Center */, 2 /* Below */, 1 /* Above */, 8 /* Right */, 4 /* Left */, 16 /* BelowRight */, 32 /* BelowLeft */, 64 /* AboveRight */, 128 /* AboveLeft */];\n return MapShapeDataPointRenderer;\n }());\n visuals.MapShapeDataPointRenderer = MapShapeDataPointRenderer;\n var DefaultLocationZoomLevel = 11;\n var Map = (function () {\n function Map(options) {\n if (options.filledMap) {\n this.dataPointRenderer = new MapShapeDataPointRenderer(options.filledMapDataLabelsEnabled, options.tooltipsEnabled);\n this.filledMapDataLabelsEnabled = options.filledMapDataLabelsEnabled;\n this.isFilledMap = true;\n }\n else {\n this.dataPointRenderer = new MapBubbleDataPointRenderer(options.tooltipsEnabled);\n this.isFilledMap = false;\n }\n this.mapControlFactory = options.mapControlFactory ? options.mapControlFactory : this.getDefaultMapControlFactory();\n this.behavior = options.behavior;\n this.tooltipsEnabled = options.tooltipsEnabled;\n this.disableZooming = options.disableZooming;\n this.disablePanning = options.disablePanning;\n this.isLegendScrollable = !!options.behavior;\n this.viewChangeThrottleInterval = options.viewChangeThrottleInterval;\n this.enableCurrentLocation = options.enableCurrentLocation;\n this.boundsHaveBeenUpdated = false;\n }\n Map.prototype.init = function (options) {\n var _this = this;\n debug.assertValue(options, 'options');\n var element = this.element = $(\"<div>\");\n element.appendTo(options.element);\n this.pendingGeocodingRender = false;\n this.currentViewport = options.viewport;\n this.style = options.style;\n this.colors = this.style.colorPalette.dataColors;\n if (this.behavior)\n this.interactivityService = visuals.createInteractivityService(options.host);\n this.dataLabelsSettings = visuals.dataLabelUtils.getDefaultMapLabelSettings();\n this.legend = powerbi.visuals.createLegend(element, options.interactivity && options.interactivity.isInteractiveLegend, this.interactivityService, this.isLegendScrollable);\n this.legendHeight = 0;\n this.legendData = { dataPoints: [] };\n this.geoTaggingAnalyzerService = powerbi.createGeoTaggingAnalyzerService(options.host.getLocalizedString);\n this.host = options.host;\n if (options.host.locale)\n this.locale = options.host.locale();\n this.geocoder = options.host.geocoder();\n this.resetBounds();\n this.mapControlFactory.ensureMap(this.locale, function () {\n Map.removeHillShading();\n Microsoft.Maps.loadModule('Microsoft.Maps.Overlays.Style', {\n callback: function () {\n _this.initialize(element[0]);\n if (_this.enableCurrentLocation) {\n _this.createCurrentLocation(element);\n }\n }\n });\n });\n };\n Map.prototype.createCurrentLocation = function (element) {\n var _this = this;\n var myLocBtn = InJs.DomFactory.div().addClass(\"mapCurrentLocation\").appendTo(element);\n var pushpin;\n myLocBtn.on('click', function () {\n if (_this.isCurrentLocation) {\n // Restore previous map view and remove pushpin\n if (pushpin) {\n _this.mapControl.entities.remove(pushpin);\n }\n _this.updateInternal(false, false);\n _this.isCurrentLocation = false;\n }\n else {\n _this.host.geolocation().getCurrentPosition(function (position) {\n var location = new Microsoft.Maps.Location(position.coords.latitude, position.coords.longitude);\n if (pushpin) {\n _this.mapControl.entities.remove(pushpin);\n }\n pushpin = visuals.MapUtil.CurrentLocation.createPushpin(location);\n _this.mapControl.entities.push(pushpin);\n _this.updateMapView(location, DefaultLocationZoomLevel);\n _this.isCurrentLocation = true;\n });\n }\n });\n };\n Map.prototype.addDataPoint = function (dataPoint) {\n var location = dataPoint.location;\n this.updateBounds(location.latitude, location.longitude);\n this.scheduleRedraw();\n };\n Map.prototype.scheduleRedraw = function () {\n var _this = this;\n if (!this.pendingGeocodingRender && this.mapControl) {\n this.pendingGeocodingRender = true;\n // Maintain a 3 second delay between redraws from geocoded geometry\n setTimeout(function () {\n _this.updateInternal(true, true);\n _this.pendingGeocodingRender = false;\n }, 3000);\n }\n };\n Map.prototype.enqueueGeoCode = function (dataPoint) {\n var _this = this;\n var location = this.geocoder.tryGeocodeImmediate(dataPoint.geocodingQuery, this.geocodingCategory);\n if (location)\n this.completeGeoCode(dataPoint, location);\n else {\n var geocodingContext_1 = this.geocodingContext;\n this.geocoder.geocode(dataPoint.geocodingQuery, this.geocodingCategory).then(function (location) {\n if (location && geocodingContext_1 === _this.geocodingContext) {\n _this.completeGeoCode(dataPoint, location);\n }\n });\n }\n };\n Map.prototype.completeGeoCode = function (dataPoint, location) {\n dataPoint.location = location;\n this.addDataPoint(dataPoint);\n };\n Map.prototype.enqueueGeoCodeAndGeoShape = function (dataPoint, params) {\n var _this = this;\n var location = this.geocoder.tryGeocodeImmediate(dataPoint.geocodingQuery, this.geocodingCategory);\n if (location)\n this.completeGeoCodeAndGeoShape(dataPoint, params, location);\n else {\n var geocodingContext_2 = this.geocodingContext;\n this.geocoder.geocode(dataPoint.geocodingQuery, this.geocodingCategory).then(function (location) {\n if (location && geocodingContext_2 === _this.geocodingContext) {\n _this.completeGeoCodeAndGeoShape(dataPoint, params, location);\n }\n });\n }\n };\n Map.prototype.completeGeoCodeAndGeoShape = function (dataPoint, params, location) {\n dataPoint.location = location;\n this.enqueueGeoShape(dataPoint, params);\n };\n Map.prototype.enqueueGeoShape = function (dataPoint, params) {\n var _this = this;\n debug.assertValue(dataPoint.location, \"cachedLocation\");\n var result = this.geocoder.tryGeocodeBoundaryImmediate(dataPoint.location.latitude, dataPoint.location.longitude, this.geocodingCategory, params.level, params.maxPolygons);\n if (result)\n this.completeGeoShape(dataPoint, params, result);\n else {\n var geocodingContext_3 = this.geocodingContext;\n this.geocoder.geocodeBoundary(dataPoint.location.latitude, dataPoint.location.longitude, this.geocodingCategory, params.level, params.maxPolygons)\n .then(function (result) {\n if (geocodingContext_3 === _this.geocodingContext)\n _this.completeGeoShape(dataPoint, params, result);\n });\n }\n };\n Map.prototype.completeGeoShape = function (dataPoint, params, result) {\n var paths;\n if (result.locations.length === 0 || result.locations[0].geographic) {\n paths = MapShapeDataPointRenderer.buildPaths(result.locations);\n }\n else {\n visuals.MapUtil.calcGeoData(result);\n paths = MapShapeDataPointRenderer.buildPaths(result.locations);\n }\n dataPoint.paths = paths;\n this.addDataPoint(dataPoint);\n };\n Map.prototype.getOptimumLevelOfDetail = function (width, height) {\n var dataPointCount = this.dataPointRenderer.getDataPointCount();\n if (dataPointCount === 0)\n return visuals.MapUtil.MinLevelOfDetail;\n var threshold = this.dataPointRenderer.getDataPointPadding();\n for (var levelOfDetail = visuals.MapUtil.MaxLevelOfDetail; levelOfDetail >= visuals.MapUtil.MinLevelOfDetail; levelOfDetail--) {\n var minXmaxY = visuals.MapUtil.latLongToPixelXY(this.minLatitude, this.minLongitude, levelOfDetail);\n var maxXminY = visuals.MapUtil.latLongToPixelXY(this.maxLatitude, this.maxLongitude, levelOfDetail);\n if (maxXminY.x - minXmaxY.x + threshold <= width && minXmaxY.y - maxXminY.y + threshold <= height) {\n // if we have less than 2 data points we should not zoom in \"too much\"\n if (dataPointCount < 2)\n levelOfDetail = Math.min(visuals.MapUtil.MaxAutoZoomLevel, levelOfDetail);\n return levelOfDetail;\n }\n }\n return visuals.MapUtil.MinLevelOfDetail;\n };\n Map.prototype.getViewCenter = function (levelOfDetail) {\n var minXmaxY = visuals.MapUtil.latLongToPixelXY(this.minLatitude, this.minLongitude, levelOfDetail);\n var maxXminY = visuals.MapUtil.latLongToPixelXY(this.maxLatitude, this.maxLongitude, levelOfDetail);\n return visuals.MapUtil.pixelXYToLocation((minXmaxY.x + maxXminY.x) / 2.0, (maxXminY.y + minXmaxY.y) / 2.0, levelOfDetail);\n };\n Map.prototype.resetBounds = function () {\n this.boundsHaveBeenUpdated = false;\n this.minLongitude = visuals.MapUtil.MaxAllowedLongitude;\n this.maxLongitude = visuals.MapUtil.MinAllowedLongitude;\n this.minLatitude = visuals.MapUtil.MaxAllowedLatitude;\n this.maxLatitude = visuals.MapUtil.MinAllowedLatitude;\n };\n Map.prototype.updateBounds = function (latitude, longitude) {\n this.boundsHaveBeenUpdated = true;\n if (longitude < this.minLongitude) {\n this.minLongitude = longitude;\n }\n if (longitude > this.maxLongitude) {\n this.maxLongitude = longitude;\n }\n if (latitude < this.minLatitude) {\n this.minLatitude = latitude;\n }\n if (latitude > this.maxLatitude) {\n this.maxLatitude = latitude;\n }\n };\n Map.legendObject = function (dataView) {\n return dataView &&\n dataView.metadata &&\n dataView.metadata.objects &&\n dataView.metadata.objects['legend'];\n };\n Map.isLegendHidden = function (dataView) {\n var legendObject = Map.legendObject(dataView);\n return legendObject != null && legendObject[visuals.legendProps.show] === false;\n };\n Map.legendPosition = function (dataView) {\n var legendObject = Map.legendObject(dataView);\n return legendObject && visuals.LegendPosition[legendObject[visuals.legendProps.position]];\n };\n Map.getLegendFontSize = function (dataView) {\n var legendObject = Map.legendObject(dataView);\n return (legendObject && legendObject[visuals.legendProps.fontSize]) || visuals.SVGLegend.DefaultFontSizeInPt;\n };\n Map.isShowLegendTitle = function (dataView) {\n var legendObject = Map.legendObject(dataView);\n return legendObject && legendObject[visuals.legendProps.showTitle];\n };\n Map.prototype.legendTitle = function () {\n var legendObject = Map.legendObject(this.dataView);\n return (legendObject && legendObject[visuals.legendProps.titleText]) || this.legendData.title;\n };\n Map.prototype.renderLegend = function (legendData) {\n var hideLegend = Map.isLegendHidden(this.dataView);\n var showTitle = Map.isShowLegendTitle(this.dataView);\n var title = this.legendTitle();\n // Update the legendData based on the hide flag. Cartesian passes in no-datapoints. OnResize reuses the legendData, so this can't mutate.\n var clonedLegendData = {\n dataPoints: hideLegend ? [] : legendData.dataPoints,\n grouped: legendData.grouped,\n title: showTitle ? title : \"\",\n fontSize: Map.getLegendFontSize(this.dataView)\n };\n // Update the orientation to match what's in the dataView\n var targetOrientation = Map.legendPosition(this.dataView);\n if (targetOrientation !== undefined) {\n this.legend.changeOrientation(targetOrientation);\n }\n else {\n this.legend.changeOrientation(visuals.LegendPosition.Top);\n }\n this.legend.drawLegend(clonedLegendData, this.currentViewport);\n };\n /** Note: public for UnitTest */\n Map.calculateGroupSizes = function (categorical, grouped, groupSizeTotals, sizeMeasureIndex, currentValueScale) {\n var categoryCount = categorical.values[0].values.length;\n var seriesCount = grouped.length;\n for (var i = 0, len = categoryCount; i < len; ++i) {\n var groupTotal = null;\n if (sizeMeasureIndex >= 0) {\n for (var j = 0; j < seriesCount; ++j) {\n var value = grouped[j].values[sizeMeasureIndex].values[i];\n if (value) {\n if (groupTotal === null) {\n groupTotal = value;\n }\n else {\n groupTotal += value;\n }\n }\n }\n }\n groupSizeTotals.push(groupTotal);\n if (groupTotal) {\n if (!currentValueScale) {\n currentValueScale = {\n min: groupTotal,\n max: groupTotal\n };\n }\n else {\n currentValueScale.min = Math.min(currentValueScale.min, groupTotal);\n currentValueScale.max = Math.max(currentValueScale.max, groupTotal);\n }\n }\n }\n return currentValueScale;\n };\n /** Note: public for UnitTest */\n Map.calculateRadius = function (range, value) {\n var rangeDiff = range ? range.max - range.min : 0;\n var radius = 6;\n if (range != null && value != null && rangeDiff !== 0) {\n radius = (14 * ((value - range.min) / rangeDiff)) + 6;\n }\n return radius;\n };\n /** Note: public for UnitTest */\n Map.getGeocodingCategory = function (categorical, geoTaggingAnalyzerService) {\n if (categorical && categorical.categories && categorical.categories.length > 0 && categorical.categories[0].source) {\n // Check categoryString for manually specified information in the model\n var type = categorical.categories[0].source.type;\n if (type && type.categoryString) {\n return geoTaggingAnalyzerService.getFieldType(type.categoryString);\n }\n // Check the category name\n var categoryName = categorical.categories[0].source.displayName;\n var geotaggedResult = geoTaggingAnalyzerService.getFieldType(categoryName);\n if (geotaggedResult)\n return geotaggedResult;\n // Checking roles for VRM backwards compatibility\n var roles = categorical.categories[0].source.roles;\n if (roles) {\n var roleNames = Object.keys(roles);\n for (var i = 0, len = roleNames.length; i < len; ++i) {\n var typeFromRoleName = geoTaggingAnalyzerService.getFieldType(roleNames[i]);\n if (typeFromRoleName)\n return typeFromRoleName;\n }\n }\n }\n return undefined;\n };\n /** Note: public for UnitTest */\n Map.hasSizeField = function (values, defaultIndexIfNoRole) {\n if (_.isEmpty(values))\n return false;\n for (var i = 0, ilen = values.length; i < ilen; i++) {\n var roles = values[i].source.roles;\n // case for Power Q&A since Power Q&A does not assign role to measures.\n if (!roles && i === defaultIndexIfNoRole && values[i].source.type.numeric)\n return true;\n if (roles) {\n var roleNames = Object.keys(roles);\n for (var j = 0, jlen = roleNames.length; j < jlen; j++) {\n var role = roleNames[j];\n if (role === \"Size\")\n return true;\n }\n }\n }\n return false;\n };\n Map.shouldEnumerateDataPoints = function (dataView, usesSizeForGradient) {\n var hasSeries = DataRoleHelper.hasRoleInDataView(dataView, 'Series');\n var gradientRole = usesSizeForGradient ? 'Size' : 'Gradient';\n var hasGradientRole = DataRoleHelper.hasRoleInDataView(dataView, gradientRole);\n return hasSeries || !hasGradientRole;\n };\n Map.shouldEnumerateCategoryLabels = function (isFilledMap, filledMapDataLabelsEnabled) {\n return (!isFilledMap || filledMapDataLabelsEnabled);\n };\n Map.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n switch (options.objectName) {\n case 'dataPoint':\n if (Map.shouldEnumerateDataPoints(this.dataView, this.isFilledMap)) {\n var bubbleData = [];\n //TODO: better way of getting this data\n var hasDynamicSeries = this.hasDynamicSeries;\n if (!hasDynamicSeries) {\n var mapData = this.dataPointRenderer.converter(this.getMapViewPort(), this.dataView, this.dataLabelsSettings, this.interactivityService, this.tooltipsEnabled);\n bubbleData = mapData.bubbleData;\n }\n Map.enumerateDataPoints(enumeration, this.dataPointsToEnumerate, this.colors, hasDynamicSeries, this.defaultDataPointColor, this.showAllDataPoints, bubbleData);\n }\n break;\n case 'categoryLabels':\n if (Map.shouldEnumerateCategoryLabels(this.isFilledMap, this.filledMapDataLabelsEnabled)) {\n visuals.dataLabelUtils.enumerateCategoryLabels(enumeration, this.dataLabelsSettings, true, true);\n }\n break;\n case 'legend':\n if (this.hasDynamicSeries) {\n Map.enumerateLegend(enumeration, this.dataView, this.legend, this.legendTitle());\n }\n break;\n case 'labels':\n if (this.filledMapDataLabelsEnabled) {\n this.dataLabelsSettings = this.dataLabelsSettings ? this.dataLabelsSettings : visuals.dataLabelUtils.getDefaultMapLabelSettings();\n var labelSettingOptions = {\n enumeration: enumeration,\n dataLabelsSettings: this.dataLabelsSettings,\n show: true,\n displayUnits: true,\n precision: true,\n };\n visuals.dataLabelUtils.enumerateDataLabels(labelSettingOptions);\n }\n break;\n }\n return enumeration.complete();\n };\n Map.enumerateDataPoints = function (enumeration, dataPoints, colors, hasDynamicSeries, defaultDataPointColor, showAllDataPoints, bubbleData) {\n var seriesLength = dataPoints && dataPoints.length;\n if (hasDynamicSeries) {\n for (var i = 0; i < seriesLength; i++) {\n var dataPoint = dataPoints[i];\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: dataPoint.label,\n selector: visuals.ColorHelper.normalizeSelector(dataPoint.identity.getSelector()),\n properties: {\n fill: { solid: { color: dataPoint.color } }\n },\n });\n }\n }\n else {\n enumeration.pushInstance({\n objectName: 'dataPoint',\n selector: null,\n properties: {\n defaultColor: { solid: { color: defaultDataPointColor || colors.getColorByIndex(0).value } }\n },\n }).pushInstance({\n objectName: 'dataPoint',\n selector: null,\n properties: {\n showAllDataPoints: !!showAllDataPoints\n },\n });\n if (bubbleData) {\n for (var i = 0; i < bubbleData.length; i++) {\n var bubbleDataPoint = bubbleData[i];\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: bubbleDataPoint.labeltext,\n selector: visuals.ColorHelper.normalizeSelector(bubbleDataPoint.identity.getSelector()),\n properties: {\n fill: { solid: { color: Color.normalizeToHexString(bubbleDataPoint.fill) } }\n },\n });\n }\n }\n }\n };\n Map.enumerateLegend = function (enumeration, dataView, legend, legendTitle) {\n enumeration.pushInstance({\n selector: null,\n properties: {\n show: !Map.isLegendHidden(dataView),\n position: visuals.LegendPosition[legend.getOrientation()],\n showTitle: Map.isShowLegendTitle(dataView),\n titleText: legendTitle,\n fontSize: Map.getLegendFontSize(dataView)\n },\n objectName: 'legend'\n });\n };\n Map.prototype.onDataChanged = function (options) {\n var _this = this;\n debug.assertValue(options, 'options');\n this.resetBounds();\n this.geocodingContext = {};\n if (this.behavior)\n this.behavior.resetZoomPan();\n this.dataLabelsSettings = visuals.dataLabelUtils.getDefaultMapLabelSettings();\n this.defaultDataPointColor = null;\n this.showAllDataPoints = null;\n var dataView = this.dataView = options.dataViews[0];\n var isFilledMap = this.isFilledMap;\n var warnings = [];\n var data = {\n dataPoints: [],\n geocodingCategory: null,\n hasDynamicSeries: false,\n hasSize: false,\n };\n if (dataView) {\n // Handle object-based settings\n if (dataView.metadata && dataView.metadata.objects) {\n var objects = dataView.metadata.objects;\n this.defaultDataPointColor = powerbi.DataViewObjects.getFillColor(objects, visuals.mapProps.dataPoint.defaultColor);\n this.showAllDataPoints = powerbi.DataViewObjects.getValue(objects, visuals.mapProps.dataPoint.showAllDataPoints);\n this.dataLabelsSettings.showCategory = powerbi.DataViewObjects.getValue(objects, visuals.filledMapProps.categoryLabels.show, this.dataLabelsSettings.showCategory);\n if (isFilledMap) {\n this.dataLabelsSettings.precision = powerbi.DataViewObjects.getValue(objects, visuals.filledMapProps.labels.labelPrecision, this.dataLabelsSettings.precision);\n this.dataLabelsSettings.precision = (this.dataLabelsSettings.precision !== visuals.dataLabelUtils.defaultLabelPrecision && this.dataLabelsSettings.precision < 0) ? 0 : this.dataLabelsSettings.precision;\n this.dataLabelsSettings.displayUnits = powerbi.DataViewObjects.getValue(objects, visuals.filledMapProps.labels.labelDisplayUnits, this.dataLabelsSettings.displayUnits);\n var datalabelsObj = objects['labels'];\n if (datalabelsObj) {\n this.dataLabelsSettings.show = (datalabelsObj['show'] !== undefined) ? datalabelsObj['show'] : this.dataLabelsSettings.show;\n if (datalabelsObj['color'] !== undefined) {\n this.dataLabelsSettings.labelColor = datalabelsObj['color'].solid.color;\n }\n }\n }\n else {\n var categoryLabelsObj = objects['categoryLabels'];\n if (categoryLabelsObj)\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(categoryLabelsObj, this.dataLabelsSettings);\n }\n }\n // Convert data\n var colorHelper = new visuals.ColorHelper(this.colors, visuals.mapProps.dataPoint.fill, this.defaultDataPointColor);\n data = Map.converter(dataView, colorHelper, this.geoTaggingAnalyzerService, isFilledMap);\n this.hasDynamicSeries = data.hasDynamicSeries;\n // Create legend\n this.legendData = Map.createLegendData(dataView, colorHelper);\n this.dataPointsToEnumerate = this.legendData.dataPoints;\n this.renderLegend(this.legendData);\n // Start geocoding or geoshaping\n if (data != null) {\n this.geocodingCategory = data.geocodingCategory;\n this.mapControlFactory.ensureMap(this.locale, function () {\n Map.removeHillShading();\n var params;\n if (isFilledMap) {\n params = MapShapeDataPointRenderer.getFilledMapParams(_this.geocodingCategory, data.dataPoints.length);\n }\n for (var _i = 0, _a = data.dataPoints; _i < _a.length; _i++) {\n var dataPoint = _a[_i];\n if (!dataPoint.location) {\n if (!_.isEmpty(dataPoint.categoryValue)) {\n if (isFilledMap)\n _this.enqueueGeoCodeAndGeoShape(dataPoint, params);\n else\n _this.enqueueGeoCode(dataPoint);\n }\n }\n else if (isFilledMap && !dataPoint.paths) {\n _this.enqueueGeoShape(dataPoint, params);\n }\n else {\n _this.addDataPoint(dataPoint);\n }\n }\n });\n }\n else {\n // No data from conversion, so clear data points\n this.clearDataPoints();\n }\n if (isFilledMap) {\n if (!this.geocodingCategory || !this.geoTaggingAnalyzerService.isGeoshapable(this.geocodingCategory)) {\n warnings.push(new visuals.FilledMapWithoutValidGeotagCategoryWarning());\n }\n }\n }\n else {\n this.clearDataPoints();\n this.renderLegend({\n dataPoints: [],\n title: undefined,\n });\n this.dataPointsToEnumerate = [];\n }\n if (!_.isEmpty(warnings))\n this.host.setWarnings(warnings);\n this.dataPointRenderer.setData(data);\n this.updateInternal(true /* dataChanged */, true /* redrawDataLabels */);\n };\n Map.converter = function (dataView, colorHelper, geoTaggingAnalyzerService, isFilledMap) {\n var reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n var dataPoints = [];\n var hasDynamicSeries = reader.hasDynamicSeries();\n var seriesColumnIdentifier = reader.getSeriesColumnIdentityFields();\n var sizeQueryName = reader.getMeasureQueryName('Size');\n if (sizeQueryName == null)\n sizeQueryName = '';\n var hasSize = reader.hasValues('Size');\n var geocodingCategory = null;\n var formatStringProp = visuals.mapProps.general.formatString;\n if (reader.hasCategories()) {\n // Calculate category totals and range for radius calculation\n var categoryTotals = [];\n var categoryTotalRange = void 0;\n if (hasSize) {\n var categoryMin = undefined;\n var categoryMax = undefined;\n for (var categoryIndex = 0, categoryCount = reader.getCategoryCount(); categoryIndex < categoryCount; categoryIndex++) {\n var categoryTotal = void 0;\n for (var seriesIndex = 0, seriesCount = reader.getSeriesCount(); seriesIndex < seriesCount; seriesIndex++) {\n var currentValue = reader.getValue('Size', categoryIndex, seriesIndex);\n // Dont initialze categoryTotal to zero until you find a null value so that it remains undefined for categories that have no non-null values (0 is rendered by filled map while null is not)\n if (categoryTotal == null && currentValue != null)\n categoryTotal = 0;\n if (categoryTotal != null)\n categoryTotal += currentValue;\n }\n categoryTotals.push(categoryTotal);\n if (categoryTotal != null) {\n if (categoryMin === undefined || categoryTotal < categoryMin)\n categoryMin = categoryTotal;\n if (categoryMax === undefined || categoryTotal > categoryMax)\n categoryMax = categoryTotal;\n }\n }\n categoryTotalRange = (categoryMin !== undefined && categoryMax !== undefined) ? {\n max: categoryMax,\n min: categoryMin,\n } : undefined;\n }\n var hasLatLongGroup = reader.hasCompositeCategories() && reader.hasCategoryWithRole('X') && reader.hasCategoryWithRole('Y');\n var hasCategoryGroup = reader.hasCategoryWithRole('Category');\n geocodingCategory = Map.getGeocodingCategory(dataView.categorical, geoTaggingAnalyzerService);\n if (hasLatLongGroup || hasCategoryGroup) {\n // Create data points\n for (var categoryIndex = 0, categoryCount = reader.getCategoryCount(); categoryIndex < categoryCount; categoryIndex++) {\n // Get category information\n var categoryValue = undefined;\n // The category objects should come from whichever category exists; in the case of a composite category, the objects should be the same for\n // both categories, so we only need to obtain them from one role.\n var categoryObjects = hasCategoryGroup ? reader.getCategoryObjects('Category', categoryIndex) : reader.getCategoryObjects('Y', categoryIndex);\n var location_4 = void 0;\n var categoryTooltipItem = void 0;\n var latitudeTooltipItem = void 0;\n var longitudeTooltipItem = void 0;\n var seriesTooltipItem = void 0;\n var sizeTooltipItem = void 0;\n var gradientTooltipItem = void 0;\n if (hasCategoryGroup) {\n // Set category value\n categoryValue = reader.getCategoryValue('Category', categoryIndex);\n categoryTooltipItem = {\n displayName: reader.getCategoryDisplayName('Category'),\n value: visuals.converterHelper.formatFromMetadataColumn(categoryValue, reader.getCategoryMetadataColumn('Category'), formatStringProp),\n };\n // Create location from latitude and longitude if they exist as values\n if (reader.hasValues('Y') && reader.hasValues('X')) {\n var latitude = reader.getFirstNonNullValueForCategory('Y', categoryIndex);\n var longitude = reader.getFirstNonNullValueForCategory('X', categoryIndex);\n if (latitude != null && longitude != null) {\n location_4 = { latitude: latitude, longitude: longitude };\n }\n latitudeTooltipItem = {\n displayName: reader.getValueDisplayName('Y'),\n value: visuals.converterHelper.formatFromMetadataColumn(latitude, reader.getValueMetadataColumn('Y'), formatStringProp),\n };\n longitudeTooltipItem = {\n displayName: reader.getValueDisplayName('X'),\n value: visuals.converterHelper.formatFromMetadataColumn(longitude, reader.getValueMetadataColumn('X'), formatStringProp),\n };\n }\n }\n else {\n var latitude = reader.getCategoryValue('Y', categoryIndex);\n var longitude = reader.getCategoryValue('X', categoryIndex);\n if (latitude != null && longitude != null) {\n // Combine latitude and longitude to create the category value\n categoryValue = latitude + ', ' + longitude;\n // Create location from latitude and longitude\n location_4 = { latitude: latitude, longitude: longitude };\n latitudeTooltipItem = {\n displayName: reader.getCategoryDisplayName('Y'),\n value: visuals.converterHelper.formatFromMetadataColumn(latitude, reader.getCategoryMetadataColumn('Y'), formatStringProp),\n };\n longitudeTooltipItem = {\n displayName: reader.getCategoryDisplayName('X'),\n value: visuals.converterHelper.formatFromMetadataColumn(longitude, reader.getCategoryMetadataColumn('X'), formatStringProp),\n };\n }\n }\n var value = hasSize ? categoryTotals[categoryIndex] : undefined;\n // Calculate sub data points by series\n var subDataPoints = [];\n var seriesCount = reader.getSeriesCount();\n if (!hasSize && !hasDynamicSeries) {\n seriesCount = 1;\n }\n for (var seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\n var color = void 0;\n if (hasDynamicSeries) {\n color = colorHelper.getColorForSeriesValue(reader.getSeriesObjects(seriesIndex), seriesColumnIdentifier, (reader.getSeriesName(seriesIndex)));\n }\n else if (reader.hasCategoryWithRole('Series')) {\n color = colorHelper.getColorForSeriesValue(reader.getCategoryObjects('Series', categoryIndex), reader.getCategoryColumnIdentityFields('Series'), categoryValue);\n }\n else {\n color = colorHelper.getColorForMeasure(categoryObjects, sizeQueryName);\n }\n var colorRgb = Color.parseColorString(color);\n var stroke = Color.hexString(Color.darken(colorRgb, Map.StrokeDarkenColorValue));\n colorRgb.A = 0.6;\n var fill = Color.rgbString(colorRgb);\n var identityBuilder = new visuals.SelectionIdBuilder()\n .withCategory(reader.getCategoryColumn(hasCategoryGroup ? 'Category' : 'Y'), categoryIndex)\n .withMeasure(sizeQueryName);\n if (hasDynamicSeries) {\n identityBuilder = identityBuilder.withSeries(reader.getSeriesValueColumns(), reader.getSeriesValueColumnGroup(seriesIndex));\n }\n if (hasDynamicSeries) {\n seriesTooltipItem = {\n displayName: reader.getSeriesDisplayName(),\n value: visuals.converterHelper.formatFromMetadataColumn(reader.getSeriesName(seriesIndex), reader.getSeriesMetadataColumn(), formatStringProp),\n };\n }\n var subsliceValue = void 0;\n if (hasSize) {\n subsliceValue = reader.getValue('Size', categoryIndex, seriesIndex);\n sizeTooltipItem = {\n displayName: reader.getValueDisplayName('Size'),\n value: visuals.converterHelper.formatFromMetadataColumn(subsliceValue, reader.getValueMetadataColumn('Size', seriesIndex), formatStringProp),\n };\n }\n if (reader.hasValues('Gradient')) {\n gradientTooltipItem = {\n displayName: reader.getValueDisplayName('Gradient'),\n value: visuals.converterHelper.formatFromMetadataColumn(reader.getValue('Gradient', categoryIndex, seriesIndex), reader.getValueMetadataColumn('Gradient', seriesIndex), formatStringProp),\n };\n }\n // Combine any existing tooltip items\n var tooltipInfo = [];\n if (categoryTooltipItem)\n tooltipInfo.push(categoryTooltipItem);\n if (seriesTooltipItem)\n tooltipInfo.push(seriesTooltipItem);\n if (latitudeTooltipItem)\n tooltipInfo.push(latitudeTooltipItem);\n if (longitudeTooltipItem)\n tooltipInfo.push(longitudeTooltipItem);\n if (sizeTooltipItem)\n tooltipInfo.push(sizeTooltipItem);\n if (gradientTooltipItem)\n tooltipInfo.push(gradientTooltipItem);\n // Do not create subslices for data points with null or zero if not filled map\n if (subsliceValue || !hasSize || (subsliceValue === 0 && isFilledMap)) {\n subDataPoints.push({\n value: subsliceValue,\n fill: fill,\n stroke: stroke,\n identity: identityBuilder.createSelectionId(),\n tooltipInfo: tooltipInfo,\n });\n }\n }\n // Skip data points that have a null or zero if not filled map\n if (value || !hasSize || (value === 0 && isFilledMap)) {\n dataPoints.push({\n geocodingQuery: categoryValue,\n value: value,\n categoryValue: categoryValue,\n subDataPoints: subDataPoints,\n radius: Map.calculateRadius(categoryTotalRange, value),\n location: location_4,\n });\n }\n }\n }\n }\n var mapData = {\n dataPoints: dataPoints,\n geocodingCategory: geocodingCategory,\n hasDynamicSeries: hasDynamicSeries,\n hasSize: hasSize,\n };\n return mapData;\n };\n Map.createLegendData = function (dataView, colorHelper) {\n var reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n var legendDataPoints = [];\n var legendTitle;\n if (reader.hasDynamicSeries()) {\n legendTitle = reader.getSeriesDisplayName();\n var seriesColumnIdentifier = reader.getSeriesColumnIdentityFields();\n for (var seriesIndex = 0, seriesCount = reader.getSeriesCount(); seriesIndex < seriesCount; seriesIndex++) {\n var color = colorHelper.getColorForSeriesValue(reader.getSeriesObjects(seriesIndex), seriesColumnIdentifier, reader.getSeriesName(seriesIndex));\n var identity = new visuals.SelectionIdBuilder().withSeries(reader.getSeriesValueColumns(), reader.getSeriesValueColumnGroup(seriesIndex)).createSelectionId();\n legendDataPoints.push({\n color: color,\n label: visuals.valueFormatter.format(reader.getSeriesName(seriesIndex)),\n icon: visuals.LegendIcon.Circle,\n identity: identity,\n selected: false,\n });\n }\n }\n var legendData = {\n dataPoints: legendDataPoints,\n title: legendTitle,\n };\n return legendData;\n };\n Map.prototype.swapLogoContainerChildElement = function () {\n // This is a workaround that allow maps to be printed from the IE and Edge browsers.\n // For some unknown reason, the presence of an <a> child element in the .LogoContainer\n // prevents dashboard map visuals from showing up when printed.\n // The trick is to swap out the <a> element with a <div> container.\n // There are no user impacts or visual changes.\n var logoContainer = this.element.find('.LogoContainer');\n if (logoContainer) {\n var aNode = logoContainer.find('a');\n if (aNode == null)\n return;\n var divNode = $('<div>');\n aNode.children().clone().appendTo(divNode);\n aNode.remove();\n divNode.appendTo(logoContainer);\n }\n };\n Map.prototype.onResizing = function (viewport) {\n if (this.currentViewport.width !== viewport.width || this.currentViewport.height !== viewport.height) {\n this.currentViewport = viewport;\n this.renderLegend(this.legendData);\n this.updateInternal(false /* dataChanged */, false);\n }\n };\n Map.prototype.initialize = function (container) {\n var _this = this;\n var mapOptions = {\n credentials: visuals.MapUtil.Settings.BingKey,\n showMapTypeSelector: false,\n enableClickableLogo: false,\n enableSearchLogo: false,\n mapTypeId: Microsoft.Maps.MapTypeId.road,\n customizeOverlays: true,\n showDashboard: false,\n showScalebar: false,\n disableKeyboardInput: true,\n disableZooming: this.disableZooming,\n disablePanning: this.disablePanning,\n };\n var divQuery = this.root = InJs.DomFactory.div().addClass(Map.MapContainer.cssClass).appendTo(container);\n this.mapControl = this.mapControlFactory.createMapControl(divQuery[0], mapOptions);\n if (this.viewChangeThrottleInterval !== undefined) {\n Microsoft.Maps.Events.addThrottledHandler(this.mapControl, 'viewchange', function () { _this.onViewChanged(); }, this.viewChangeThrottleInterval);\n }\n else {\n Microsoft.Maps.Events.addHandler(this.mapControl, 'viewchange', function () { _this.onViewChanged(); });\n }\n Microsoft.Maps.Events.addHandler(this.mapControl, \"viewchangeend\", function () { _this.onViewChangeEnded(); });\n this.dataPointRenderer.init(this.mapControl, divQuery, !!this.behavior);\n if (!this.pendingGeocodingRender) {\n this.updateInternal(true /* dataChanged */, true);\n }\n };\n Map.prototype.onViewChanged = function () {\n this.updateOffsets(false, false /* dataChanged */);\n if (this.behavior)\n this.behavior.viewChanged();\n this.swapLogoContainerChildElement();\n };\n Map.prototype.onViewChangeEnded = function () {\n this.dataPointRenderer.updateInternalDataLabels(this.currentViewport, true);\n };\n Map.prototype.getMapViewPort = function () {\n var currentViewport = this.currentViewport;\n var legendMargins = this.legend.getMargins();\n var mapViewport = {\n width: currentViewport.width - legendMargins.width,\n height: currentViewport.height - legendMargins.height,\n };\n return mapViewport;\n };\n Map.removeTransform3d = function (mapRoot) {\n // don't remove transform3d from bing maps images in safari (using applewebkit engine)\n var userAgent = window.navigator.userAgent.toLowerCase();\n if (mapRoot && userAgent.indexOf('applewebkit') === -1) {\n var imageTiles = mapRoot.find('img');\n imageTiles.css('transform', '');\n }\n };\n Map.prototype.updateInternal = function (dataChanged, redrawDataLabels) {\n if (this.mapControl) {\n var isLegendVisible = this.legend.isVisible();\n if (!isLegendVisible)\n this.legendData = { dataPoints: [] };\n var mapDiv = this.element.children(Map.MapContainer.selector);\n var mapViewport = this.getMapViewPort();\n mapDiv.height(mapViewport.height);\n mapDiv.width(mapViewport.width);\n // With the risk of double drawing, if the position updates to nearly the same, the map control won't call viewchange, so explicitly update the points\n this.updateOffsets(dataChanged, redrawDataLabels);\n // Set zoom level after we rendered that map as we need the max size of the bubbles/ pie slices to calculate it\n if (this.boundsHaveBeenUpdated && !(this.behavior && this.behavior.hasReceivedZoomOrPanEvent())) {\n var levelOfDetail = this.getOptimumLevelOfDetail(mapViewport.width, mapViewport.height);\n var center = this.getViewCenter(levelOfDetail);\n this.updateMapView(center, levelOfDetail);\n }\n }\n };\n Map.prototype.updateMapView = function (center, levelOfDetail) {\n this.mapControl.setView({ center: center, zoom: levelOfDetail, animate: true });\n };\n Map.prototype.updateOffsets = function (dataChanged, redrawDataLabels) {\n var dataView = this.dataView;\n var data;\n var viewport = this.getMapViewPort();\n if (dataView && dataView.categorical) {\n // currentViewport may not exist in UnitTests\n data = this.dataPointRenderer.converter(viewport, this.dataView, this.dataLabelsSettings, this.interactivityService, this.tooltipsEnabled);\n }\n else {\n data = {\n bubbleData: [],\n shapeData: [],\n sliceData: [],\n };\n }\n var behaviorOptions = this.dataPointRenderer.updateInternal(data, viewport, dataChanged, this.interactivityService, redrawDataLabels);\n visuals.Legend.positionChartArea(d3.select(this.root[0]), this.legend);\n if (this.interactivityService && behaviorOptions) {\n this.interactivityService.bind(behaviorOptions.dataPoints, this.behavior, behaviorOptions);\n }\n };\n Map.prototype.onClearSelection = function () {\n this.interactivityService.clearSelection();\n this.updateOffsets(false, false /* dataChanged */);\n };\n Map.prototype.clearDataPoints = function () {\n this.dataPointRenderer.clearDataPoints();\n this.legend.drawLegend({ dataPoints: [] }, this.currentViewport);\n };\n Map.prototype.getDefaultMapControlFactory = function () {\n return {\n createMapControl: function (element, options) { return new Microsoft.Maps.Map(element, options); },\n ensureMap: jsCommon.ensureMap,\n };\n };\n Map.removeHillShading = function () {\n Microsoft.Maps.Globals.roadUriFormat = Microsoft.Maps.Globals.roadUriFormat.replace('&shading=hill', '');\n };\n Map.MapContainer = {\n cssClass: 'mapControl',\n selector: '.mapControl'\n };\n Map.StrokeDarkenColorValue = 255 * 0.25;\n return Map;\n }());\n visuals.Map = Map;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var getKpiImageMetadata = powerbi.visuals.KpiUtil.getKpiImageMetadata;\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n var UrlUtils = jsCommon.UrlUtils;\n var EdgeSettings = powerbi.visuals.controls.internal.TablixUtils.EdgeSettings;\n var TitleFontFamily = 'wf_segoe-ui_semibold';\n var DefaultFontFamily = 'wf_segoe-ui_normal';\n var DefaultCaptionFontSizeInPt = 10;\n var DefaultTitleFontSizeInPt = 13;\n var DefaultDetailFontSizeInPt = 9;\n var DefaultTitleColor = '#767676';\n var DefaultTextColor = '#333333';\n var DefaultCategoryColor = '#ACACAC';\n var DefaultOutline = visuals.outline.none;\n var DefaultOutlineColor = '#E8E8E8';\n var DefaultOutlineWeight = 1;\n var DefaultBarShow = true;\n var DefaultBarColor = '#A6A6A6';\n var DefaultBarOutline = visuals.outline.leftOnly;\n var DefaultBarWeight = 3;\n var MultiRowCard = (function () {\n function MultiRowCard() {\n this.isInteractivityOverflowHidden = false;\n }\n MultiRowCard.prototype.init = function (options) {\n debug.assertValue(options, 'options');\n this.options = options;\n this.style = options.style;\n var viewport = this.currentViewport = options.viewport;\n var interactivity = this.interactivity = options.interactivity;\n if (interactivity && interactivity.overflow === 'hidden')\n this.isInteractivityOverflowHidden = true;\n var multiRowCardDiv = this.element = $('<div/>')\n .addClass(MultiRowCard.MultiRowCardRoot.class)\n .css({\n 'height': getPixelString(viewport.height),\n });\n options.element.append(multiRowCardDiv);\n this.initializeCardRowSelection();\n };\n MultiRowCard.prototype.onDataChanged = function (options) {\n debug.assertValue(options, 'options');\n var dataViews = options.dataViews;\n if (dataViews && dataViews.length > 0) {\n var dataView = this.dataView = dataViews[0];\n var columnMetadata = dataView.table.columns;\n var tableRows = dataView.table.rows;\n var resetScrollbarPosition = options.operationKind !== powerbi.VisualDataChangeOperationKind.Append;\n var data_2 = this.data = MultiRowCard.converter(dataView, columnMetadata.length, tableRows.length, this.isInteractivityOverflowHidden);\n this.setCardDimensions();\n this.listView.data(data_2.dataModel, function (d) { return data_2.dataModel.indexOf(d); }, resetScrollbarPosition);\n }\n else {\n this.data = {\n dataModel: [],\n dataColumnCount: 0,\n cardTitleSettings: visuals.dataLabelUtils.getDefaultLabelSettings(true, DefaultTitleColor, DefaultTitleFontSizeInPt),\n categoryLabelsSettings: visuals.dataLabelUtils.getDefaultLabelSettings(true, DefaultCategoryColor, DefaultDetailFontSizeInPt),\n dataLabelsSettings: visuals.dataLabelUtils.getDefaultLabelSettings(true, DefaultTextColor, DefaultCaptionFontSizeInPt),\n cardSettings: MultiRowCard.getCardSettings(null)\n };\n }\n this.waitingForData = false;\n };\n MultiRowCard.getCardSettings = function (dataView) {\n var objects = dataView && dataView.metadata && dataView.metadata.objects ? dataView.metadata.objects : null;\n var outlineSettings = {\n outline: powerbi.DataViewObjects.getValue(objects, visuals.multiRowCardProps.card.outline, DefaultOutline),\n color: powerbi.DataViewObjects.getFillColor(objects, visuals.multiRowCardProps.card.outlineColor, DefaultOutlineColor),\n weight: powerbi.DataViewObjects.getValue(objects, visuals.multiRowCardProps.card.outlineWeight, DefaultOutlineWeight),\n };\n var barShow = powerbi.DataViewObjects.getValue(objects, visuals.multiRowCardProps.card.barShow, DefaultBarShow);\n var barSettings = {\n // If the bar is hidden, set the outline to none\n outline: barShow ? DefaultBarOutline : visuals.outline.none,\n color: powerbi.DataViewObjects.getFillColor(objects, visuals.multiRowCardProps.card.barColor, DefaultBarColor),\n weight: powerbi.DataViewObjects.getValue(objects, visuals.multiRowCardProps.card.barWeight, DefaultBarWeight),\n };\n var cardPadding = powerbi.DataViewObjects.getValue(objects, visuals.multiRowCardProps.card.cardPadding, MultiRowCard.DefaultStyle.row.marginBottom);\n var cardBackground = powerbi.DataViewObjects.getFillColor(objects, visuals.multiRowCardProps.card.cardBackground, MultiRowCard.DefaultStyle.row.background);\n return {\n outlineSettings: outlineSettings,\n barSettings: barSettings,\n cardPadding: cardPadding,\n cardBackground: cardBackground\n };\n };\n MultiRowCard.prototype.onResizing = function (viewport) {\n var heightNotChanged = (this.currentViewport.height === viewport.height);\n this.currentViewport = viewport;\n this.element.css('height', getPixelString(viewport.height));\n if (!this.dataView)\n return;\n var previousMaxColPerRow = this.maxColPerRow;\n this.maxColPerRow = this.getMaxColPerRow();\n var widthNotChanged = (previousMaxColPerRow === this.maxColPerRow);\n if (heightNotChanged && widthNotChanged)\n return;\n this.listView.viewport(viewport);\n };\n MultiRowCard.converter = function (dataView, columnCount, maxCards, isDashboardVisual) {\n if (isDashboardVisual === void 0) { isDashboardVisual = false; }\n var details = [];\n var tableDataRows = dataView.table.rows;\n var columnMetadata = dataView.table.columns;\n var cardTitleSettings, dataLabelsSettings, categoryLabelsSettings;\n cardTitleSettings = visuals.dataLabelUtils.getDefaultLabelSettings(true, DefaultTitleColor, DefaultTitleFontSizeInPt);\n dataLabelsSettings = visuals.dataLabelUtils.getDefaultLabelSettings(true, DefaultTextColor, DefaultCaptionFontSizeInPt);\n categoryLabelsSettings = visuals.dataLabelUtils.getDefaultLabelSettings(true, DefaultCategoryColor, DefaultDetailFontSizeInPt);\n if (dataView.metadata && dataView.metadata.objects) {\n var cardTitleLabelObjects = powerbi.DataViewObjects.getObject(dataView.metadata.objects, 'cardTitle');\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(cardTitleLabelObjects, cardTitleSettings);\n var dataLabelObject = powerbi.DataViewObjects.getObject(dataView.metadata.objects, 'dataLabels');\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(dataLabelObject, dataLabelsSettings);\n var categoryLabelObject = powerbi.DataViewObjects.getObject(dataView.metadata.objects, 'categoryLabels');\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(categoryLabelObject, categoryLabelsSettings);\n }\n for (var i = 0, len = maxCards; i < len; i++) {\n var row = tableDataRows[i];\n var isValuePromoted = undefined;\n var title = undefined;\n var showTitleAsURL = false;\n var showTitleAsImage = false;\n var showTitleAsKPI = false;\n var cardData = [];\n for (var j = 0; j < columnCount; j++) {\n var column = columnMetadata[j];\n var statusGraphicInfo = getKpiImageMetadata(column, row[j]);\n var columnCaption = void 0;\n var statusGraphic = void 0;\n if (statusGraphicInfo) {\n columnCaption = statusGraphicInfo.class;\n statusGraphic = statusGraphicInfo.statusGraphic;\n }\n //TODO: seems we are duplicating this logic in many places. Consider putting it in KPIUtil\n if (!columnCaption)\n columnCaption = visuals.valueFormatter.format(row[j], visuals.valueFormatter.getFormatString(column, MultiRowCard.formatStringProp));\n var showKPI = statusGraphicInfo !== undefined && statusGraphicInfo.caption !== undefined;\n // The columnDetail represents column name. In card the column name is shown as details\n var columnDetail = columnMetadata[j].displayName;\n //Title is shown only on Canvas and only if there is one Category field.\n if (!isDashboardVisual && !column.type.numeric) {\n if (isValuePromoted === undefined) {\n isValuePromoted = true;\n title = columnCaption;\n showTitleAsURL = visuals.converterHelper.isWebUrlColumn(column) && UrlUtils.isValidUrl(title);\n showTitleAsImage = visuals.converterHelper.isImageUrlColumn(column) && UrlUtils.isValidImageUrl(columnCaption);\n showTitleAsKPI = showKPI;\n }\n else if (isValuePromoted) {\n isValuePromoted = false;\n }\n }\n cardData.push({\n caption: columnCaption,\n details: columnDetail,\n showURL: visuals.converterHelper.isWebUrlColumn(column) && UrlUtils.isValidUrl(columnCaption),\n showImage: visuals.converterHelper.isImageUrlColumn(column) && UrlUtils.isValidImageUrl(columnCaption),\n showKPI: showKPI,\n columnIndex: j\n });\n }\n details.push({\n title: isValuePromoted ? title : undefined,\n showTitleAsURL: showTitleAsURL,\n showTitleAsImage: showTitleAsImage,\n showTitleAsKPI: showTitleAsKPI,\n cardItemsData: isValuePromoted ? cardData.filter(function (d) { return d.caption !== title; }) : cardData\n });\n }\n return {\n dataModel: details,\n dataColumnCount: details[0] ? details[0].cardItemsData.length : 0,\n cardTitleSettings: cardTitleSettings,\n categoryLabelsSettings: categoryLabelsSettings,\n dataLabelsSettings: dataLabelsSettings,\n cardSettings: MultiRowCard.getCardSettings(dataView)\n };\n };\n MultiRowCard.getSortableRoles = function (options) {\n if (!options || !options.dataViewMappings || _.isEmpty(options.dataViewMappings)) {\n return;\n }\n for (var _i = 0, _a = options.dataViewMappings; _i < _a.length; _i++) {\n var dataViewMapping = _a[_i];\n if (dataViewMapping.table) {\n var rows = dataViewMapping.table.rows;\n if (rows && rows.for && rows.for.in && rows.for.in.items) {\n return [MultiRowCard.ValuesRole];\n }\n }\n }\n return;\n };\n MultiRowCard.prototype.initializeCardRowSelection = function () {\n var _this = this;\n var isDashboardVisual = this.isInteractivityOverflowHidden;\n var rowEnter = function (rowSelection) {\n var cardRow = rowSelection\n .append(\"div\")\n .classed(MultiRowCard.Card.class, true);\n // The card top padding is not needed when card items are wrapped as top padding is added to each carditemcontainer when wrapped\n if (isDashboardVisual) {\n cardRow.classed('mrtile', true);\n }\n else {\n if (_this.cardHasTitle) {\n cardRow.append(\"div\").classed(MultiRowCard.Title.class, true)\n .each(function (d) {\n if (d.showTitleAsImage)\n appendImage(d3.select(this));\n else if (d.showTitleAsURL)\n d3.select(this).append('a');\n else if (d.showTitleAsKPI)\n d3.select(this).append('div')\n .classed(MultiRowCard.KPITitle.class, true)\n .classed(d.title, true)\n .style({\n display: 'inline-block',\n verticalAlign: 'sub'\n });\n });\n }\n }\n var cardItem = cardRow\n .selectAll(MultiRowCard.CardItemContainer.selector)\n .data(function (d) { return d.cardItemsData; })\n .enter()\n .append('div')\n .classed(MultiRowCard.CardItemContainer.class, true);\n cardItem\n .append('div')\n .classed(MultiRowCard.Caption.class, true)\n .each(function (d) {\n if (d.showURL) {\n d3.select(this).append('a');\n }\n else if (d.showImage) {\n appendImage(d3.select(this));\n }\n else if (d.showKPI) {\n d3.select(this).append('div')\n .classed(d.caption, true)\n .style({\n display: 'inline-block',\n verticalAlign: 'sub'\n });\n }\n });\n cardItem\n .append('div')\n .classed(MultiRowCard.Details.class, true);\n };\n /**\n * Row update should:\n * 1. bind Data\n * 2. Manipulate DOM (likely just updating CSS properties) affected by data\n */\n var rowUpdate = function (rowSelection) {\n var style = _this.getStyle();\n var dataLabelHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(MultiRowCard.getTextProperties(false, style.caption.fontSize));\n var categoryLabelHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(MultiRowCard.getTextProperties(false, style.details.fontSize));\n var titleLabelHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(MultiRowCard.getTextProperties(true, style.title.fontSize));\n var rowBorderStyle = _this.getBorderStyles(style.row.border);\n rowSelection\n .style(rowBorderStyle)\n .style({\n 'margin-bottom': isDashboardVisual ? '0px' : (_this.isSingleRowCard ? '0px' : getPixelString(style.row.marginBottom)),\n 'background': style.row.background\n });\n if (!isDashboardVisual && _this.cardHasTitle) {\n rowSelection.selectAll(MultiRowCard.Title.selector)\n .filter(function (d) { return !d.showTitleAsImage && !d.showTitleAsKPI; })\n .style({\n 'font-size': PixelConverter.fromPoint(style.title.fontSize),\n 'line-height': PixelConverter.toString(titleLabelHeight),\n 'color': style.title.color,\n });\n rowSelection.selectAll(MultiRowCard.Title.selector)\n .filter(function (d) { return !d.showTitleAsURL && !d.showTitleAsImage && !d.showTitleAsKPI; })\n .text(function (d) { return d.title; })\n .attr('title', function (d) { return d.title; });\n rowSelection\n .selectAll(MultiRowCard.TitleUrlSelector)\n .text(function (d) { return d.title; })\n .attr({\n 'href': function (d) { return d.title; },\n 'target': '_blank',\n });\n rowSelection\n .selectAll(MultiRowCard.TitleImageSelector)\n .attr('src', function (d) { return d.title; });\n setImageStyle(rowSelection.selectAll(MultiRowCard.Title.selector), style.imageTitle);\n rowSelection\n .selectAll(MultiRowCard.KPITitle.selector)\n .each(function (d) {\n var element = d3.select(this);\n element.classed(d.title);\n });\n }\n var cardSelection = rowSelection.selectAll(MultiRowCard.Card.selector);\n var cardBorderStyle = _this.getBorderStyles(style.card.border);\n cardSelection.style(cardBorderStyle);\n cardSelection\n .selectAll(MultiRowCard.Caption.selector)\n .filter(function (d) { return !d.showImage; })\n .style({\n 'line-height': PixelConverter.toString(dataLabelHeight),\n 'font-size': PixelConverter.fromPoint(style.caption.fontSize),\n })\n .filter(function (d) { return !d.showKPI; })\n .style({\n 'color': style.caption.color,\n })\n .filter(function (d) { return !d.showURL; })\n .text(function (d) { return d.caption; })\n .attr('title', function (d) { return d.caption; });\n cardSelection\n .selectAll(MultiRowCard.CaptionImageSelector)\n .attr('src', function (d) { return d.caption; })\n .style(style.imageCaption);\n cardSelection\n .selectAll(MultiRowCard.CardItemContainer.selector)\n .style({\n 'padding-right': function (d) {\n return _this.isLastRowItem(d.columnIndex, _this.dataView.metadata.columns.length) ? '0px' : getPixelString(style.cardItemContainer.paddingRight);\n },\n 'width': function (d) {\n return _this.getColumnWidth(d.columnIndex, _this.data.dataColumnCount);\n },\n 'display': function (d) {\n return (_this.hideColumn(d.columnIndex) ? 'none' : 'inline-block');\n },\n });\n setImageStyle(cardSelection.selectAll(MultiRowCard.Caption.selector), style.imageCaption);\n cardSelection\n .selectAll(MultiRowCard.CaptionUrlSelector)\n .attr({\n 'href': function (d) { return d.caption; },\n 'target': '_blank',\n })\n .text(function (d) { return d.caption; });\n if (style.details.isVisible) {\n cardSelection\n .selectAll(MultiRowCard.Details.selector)\n .text(function (d) { return d.details; })\n .style({\n 'font-size': PixelConverter.fromPoint(style.details.fontSize),\n 'line-height': PixelConverter.toString(categoryLabelHeight),\n 'color': style.details.color\n })\n .attr('title', function (d) { return d.details; });\n }\n };\n var rowExit = function (rowSelection) {\n rowSelection.remove();\n };\n var listViewOptions = {\n rowHeight: undefined,\n enter: rowEnter,\n exit: rowExit,\n update: rowUpdate,\n loadMoreData: function () { return _this.onLoadMoreData(); },\n viewport: this.currentViewport,\n baseContainer: d3.select(this.element.get(0)),\n scrollEnabled: !this.isInteractivityOverflowHidden,\n isReadMode: function () {\n return (_this.options.host.getViewMode() !== 1 /* Edit */);\n }\n };\n this.listView = visuals.ListViewFactory.createListView(listViewOptions);\n };\n MultiRowCard.prototype.getBorderStyles = function (border) {\n return {\n 'border-top': border && border.top ? border.top.getCSS() : '',\n 'border-right': border && border.right ? border.right.getCSS() : '',\n 'border-bottom': border && border.bottom ? border.bottom.getCSS() : '',\n 'border-left': border && border.left ? border.left.getCSS() : ''\n };\n };\n MultiRowCard.prototype.getMaxColPerRow = function () {\n var rowWidth = this.currentViewport.width;\n var minColumnWidth = this.getStyle().cardItemContainer.minWidth;\n var columnCount = this.data.dataColumnCount;\n //atleast one column fits in a row\n var maxColumnPerRow = Math.floor(rowWidth / minColumnWidth) || 1;\n return Math.min(columnCount, maxColumnPerRow);\n };\n MultiRowCard.prototype.getRowIndex = function (fieldIndex) {\n return Math.floor((fieldIndex * 1.0) / this.getMaxColPerRow());\n };\n MultiRowCard.prototype.getStyle = function () {\n var defaultStyles = MultiRowCard.DefaultStyle;\n var customStyles = this.getCustomStyles();\n if (!this.isInteractivityOverflowHidden)\n return $.extend(true, {}, defaultStyles, customStyles);\n var viewportWidth = this.currentViewport.width;\n var overrideStyle = {};\n for (var _i = 0, _a = MultiRowCard.tileMediaQueries; _i < _a.length; _i++) {\n var currentQuery = _a[_i];\n if (viewportWidth <= currentQuery.maxWidth) {\n overrideStyle = currentQuery.style;\n break;\n }\n }\n return $.extend(true, {}, defaultStyles, customStyles, overrideStyle);\n };\n MultiRowCard.prototype.getSurroundSettings = function (outlineSettings) {\n var edge = new EdgeSettings(outlineSettings.weight, outlineSettings.color);\n var outlineProp = outlineSettings.outline;\n return {\n top: visuals.outline.showTop(outlineProp) ? edge : null,\n right: visuals.outline.showRight(outlineProp) ? edge : null,\n bottom: visuals.outline.showBottom(outlineProp) ? edge : null,\n left: visuals.outline.showLeft(outlineProp) ? edge : null,\n };\n };\n MultiRowCard.prototype.getCustomStyles = function () {\n var dataLabelsSettings = this.data.dataLabelsSettings;\n var categoryLabelSettings = this.data.categoryLabelsSettings;\n var titleLabelSettings = this.data.cardTitleSettings;\n var cardSettings = this.data.cardSettings;\n var customStyle = {\n row: {\n border: this.getSurroundSettings(cardSettings.outlineSettings),\n marginBottom: cardSettings.cardPadding,\n background: cardSettings.cardBackground\n },\n card: {\n border: this.getSurroundSettings(cardSettings.barSettings)\n },\n details: {\n fontSize: categoryLabelSettings.fontSize,\n color: categoryLabelSettings.labelColor,\n isVisible: categoryLabelSettings.show,\n },\n caption: {\n fontSize: dataLabelsSettings.fontSize,\n color: dataLabelsSettings.labelColor,\n },\n title: {\n fontSize: titleLabelSettings.fontSize,\n color: titleLabelSettings.labelColor,\n }\n };\n return customStyle;\n };\n MultiRowCard.getTextProperties = function (isTitle, fontSizeInPt) {\n return {\n fontFamily: isTitle ? TitleFontFamily : DefaultFontFamily,\n fontSize: PixelConverter.fromPoint(fontSizeInPt),\n };\n };\n MultiRowCard.prototype.hideColumn = function (fieldIndex) {\n //calculate the number of items apearing in the same row as the columnIndex\n var rowIndex = this.getRowIndex(fieldIndex);\n // when interactivity is disabled (pinned tile), don't wrap the row\n var maxRows = this.getStyle().card.maxRows;\n return (maxRows && rowIndex >= maxRows);\n };\n MultiRowCard.prototype.getColumnWidth = function (fieldIndex, columnCount) {\n //atleast one column fits in a row\n var maxColumnPerRow = this.getMaxColPerRow();\n if (maxColumnPerRow >= columnCount)\n //all columns fit in the same row, divide the space equaly\n return (100.0 / columnCount) + '%';\n //calculate the number of items apearing in the same row as the columnIndex\n var rowIndex = this.getRowIndex(fieldIndex);\n var totalRows = Math.ceil((columnCount * 1.0) / maxColumnPerRow);\n var lastRowCount = columnCount % maxColumnPerRow;\n if (rowIndex < totalRows || lastRowCount === 0)\n // items is not on the last row or last row contains max columns allowed per row\n return (100.0 / maxColumnPerRow) + '%';\n // items is on the last row\n return (100.0 / lastRowCount) + '%';\n };\n MultiRowCard.prototype.isLastRowItem = function (fieldIndex, columnCount) {\n if (fieldIndex + 1 === columnCount)\n return true;\n var maxColumnPerRow = this.getMaxColPerRow();\n if (maxColumnPerRow - (fieldIndex % maxColumnPerRow) === 1)\n return true;\n return false;\n };\n /**\n * This contains the card column wrapping logic.\n * Determines how many columns can be shown per each row inside a Card.\n * To place the fields evenly along the card,\n * the width of each card item is calculated based on the available viewport width.\n */\n MultiRowCard.prototype.setCardDimensions = function () {\n this.cardHasTitle = false;\n var dataModel = this.data.dataModel;\n if (!this.isInteractivityOverflowHidden && dataModel && dataModel.length > 0) {\n this.cardHasTitle = dataModel[0].title !== undefined;\n this.isSingleRowCard = dataModel.length === 1 ? true : false;\n }\n };\n MultiRowCard.prototype.onLoadMoreData = function () {\n if (!this.waitingForData && this.dataView.metadata && this.dataView.metadata.segment) {\n this.options.host.loadMoreData();\n this.waitingForData = true;\n }\n };\n MultiRowCard.getDataLabelSettingsOptions = function (enumeration, labelSettings, show) {\n if (show === void 0) { show = false; }\n return {\n enumeration: enumeration,\n dataLabelsSettings: labelSettings,\n show: show,\n fontSize: true,\n };\n };\n MultiRowCard.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n var cardTitleSettings = this.data.cardTitleSettings;\n var dataLabelsSettings = this.data.dataLabelsSettings;\n var categoryLabelsSettings = this.data.categoryLabelsSettings;\n switch (options.objectName) {\n case 'cardTitle':\n //display title options only if title visible\n if (!this.isInteractivityOverflowHidden && this.cardHasTitle)\n visuals.dataLabelUtils.enumerateDataLabels(MultiRowCard.getDataLabelSettingsOptions(enumeration, cardTitleSettings));\n break;\n case 'dataLabels':\n visuals.dataLabelUtils.enumerateDataLabels(MultiRowCard.getDataLabelSettingsOptions(enumeration, dataLabelsSettings));\n break;\n case 'categoryLabels':\n visuals.dataLabelUtils.enumerateDataLabels(MultiRowCard.getDataLabelSettingsOptions(enumeration, categoryLabelsSettings, true));\n break;\n case visuals.multiRowCardProps.card.outline.objectName:\n this.enumerateCard(enumeration);\n break;\n }\n return enumeration.complete();\n };\n MultiRowCard.prototype.enumerateCard = function (enumeration) {\n var cardSettings = this.data.cardSettings;\n var propNames = visuals.multiRowCardProps.card;\n var properties = {};\n var outlineSettings = cardSettings.outlineSettings;\n properties[propNames.outline.propertyName] = outlineSettings.outline;\n if (outlineSettings.outline !== visuals.outline.none) {\n properties[propNames.outlineColor.propertyName] = outlineSettings.color;\n properties[propNames.outlineWeight.propertyName] = outlineSettings.weight;\n }\n var barSettings = cardSettings.barSettings;\n // The bar is shown if the outline value is not none\n var barShow = barSettings.outline !== visuals.outline.none;\n properties[propNames.barShow.propertyName] = barShow;\n if (barShow) {\n properties[propNames.barColor.propertyName] = barSettings.color;\n properties[propNames.barWeight.propertyName] = barSettings.weight;\n }\n properties[propNames.cardPadding.propertyName] = cardSettings.cardPadding;\n properties[propNames.cardBackground.propertyName] = cardSettings.cardBackground;\n enumeration.pushInstance({\n selector: null,\n objectName: propNames.outline.objectName,\n properties: properties\n });\n };\n /**\n * Note: Public for testability.\n */\n MultiRowCard.formatStringProp = {\n objectName: 'general',\n propertyName: 'formatString',\n };\n MultiRowCard.MultiRowCardRoot = createClassAndSelector('multiRowCard');\n MultiRowCard.Card = createClassAndSelector('card');\n MultiRowCard.Title = createClassAndSelector('title');\n MultiRowCard.CardItemContainer = createClassAndSelector('cardItemContainer');\n MultiRowCard.Caption = createClassAndSelector('caption');\n MultiRowCard.Details = createClassAndSelector('details');\n MultiRowCard.TitleUrlSelector = MultiRowCard.Title.selector + ' a';\n MultiRowCard.CaptionUrlSelector = MultiRowCard.Caption.selector + ' a';\n MultiRowCard.TitleImageSelector = MultiRowCard.Title.selector + ' img';\n MultiRowCard.CaptionImageSelector = MultiRowCard.Caption.selector + ' img';\n MultiRowCard.KPITitle = createClassAndSelector('kpiTitle');\n MultiRowCard.ValuesRole = 'Values';\n /**\n * Cards have specific styling so defined inline styles and also to support theming and improve performance.\n */\n MultiRowCard.DefaultStyle = {\n row: {\n border: null,\n marginBottom: 20,\n background: undefined\n },\n card: {\n border: null\n },\n cardItemContainer: {\n paddingRight: 20,\n minWidth: 120,\n },\n imageCaption: {\n maxHeight: 75,\n maxWidth: 100,\n },\n imageTitle: {\n maxHeight: 75,\n maxWidth: 100,\n }\n };\n // queries should be ordered by maxWidth in ascending order\n MultiRowCard.tileMediaQueries = [\n {\n maxWidth: 250,\n style: {\n card: {\n maxRows: 2,\n },\n cardItemContainer: {\n minWidth: 110,\n },\n imageCaption: {\n maxHeight: 45,\n }\n }\n },\n {\n maxWidth: 490,\n style: {\n card: {\n maxRows: 2,\n },\n cardItemContainer: {\n minWidth: 130,\n },\n imageCaption: {\n maxHeight: 52,\n }\n }\n },\n {\n maxWidth: 750,\n style: {\n card: {\n maxRows: 1,\n },\n cardItemContainer: {\n minWidth: 120,\n },\n imageCaption: {\n maxHeight: 53,\n }\n }\n }\n ];\n return MultiRowCard;\n }());\n visuals.MultiRowCard = MultiRowCard;\n function appendImage(selection) {\n selection\n .append('div')\n .classed('imgCon', true)\n .append('img');\n }\n function setImageStyle(selection, imageStyle) {\n selection\n .selectAll('.imgCon')\n .style({\n 'height': getPixelString(imageStyle.maxHeight),\n })\n .selectAll('img')\n .style({\n 'max-height': getPixelString(imageStyle.maxHeight),\n 'max-width': getPixelString(imageStyle.maxWidth),\n });\n }\n function getPixelString(value) {\n return value + \"px\";\n }\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var KeyUtils = jsCommon.KeyUtils;\n var StringExtensions = jsCommon.StringExtensions;\n var UrlUtils = jsCommon.UrlUtils;\n /** Represents a rich text box that supports view & edit mode. */\n var Textbox = (function () {\n function Textbox() {\n }\n Textbox.prototype.init = function (options) {\n this.element = options.element;\n this.host = options.host;\n this.viewport = options.viewport;\n this.readOnly = (this.host.getViewMode() === 0 /* View */);\n this.paragraphs = [];\n this.refreshView();\n };\n Textbox.prototype.onResizing = function (viewport) {\n this.viewport = viewport;\n this.updateSize();\n };\n Textbox.prototype.onDataChanged = function (options) {\n debug.assertValue(options, 'options');\n var dataViews = options.dataViews;\n this.paragraphs = [];\n if (dataViews && dataViews.length > 0) {\n var objects = dataViews[0].metadata.objects;\n if (objects && objects.general)\n this.paragraphs = objects.general.paragraphs;\n }\n this.refreshView();\n };\n Textbox.prototype.destroy = function () {\n };\n Textbox.prototype.focus = function () {\n if (!this.editor)\n return;\n this.editor.focus();\n return true;\n };\n Textbox.prototype.onViewModeChanged = function (viewMode) {\n this.readOnly = (viewMode === 0 /* View */);\n this.refreshView();\n };\n Textbox.prototype.setSelection = function (start, end) {\n debug.assertValue(this.editor, 'editor');\n if (this.editor)\n this.editor.setSelection(start, end);\n };\n Textbox.prototype.refreshView = function () {\n var _this = this;\n if (this.readOnly) {\n // Showing just HTML, no editor.\n // If we are in view-mode and we have an editor, we can remove it (after saving).\n if (this.editor) {\n this.saveContents();\n this.editor.destroy();\n this.editor = null;\n }\n this.element.empty();\n var htmlContent = RichTextConversion.convertParagraphsToHtml(this.paragraphs);\n htmlContent.addClass(Textbox.ClassName);\n htmlContent.css({\n 'font-family': RichText.defaultFont,\n 'font-size': RichText.defaultFontSize,\n });\n this.element.append(htmlContent);\n }\n else {\n // Showing the Quill editor.\n // If we are in edit-mode and we don't have an editor we need to create it.\n if (!this.editor) {\n this.editor = new RichText.QuillWrapper(this.readOnly, this.host);\n this.editor.textChanged = function (delta, source) { return _this.saveContents(); };\n this.element.empty();\n var editorElement = this.editor.getElement();\n editorElement.addClass(Textbox.ClassName);\n editorElement.css({\n 'font-family': RichText.defaultFont,\n 'font-size': RichText.defaultFontSize,\n });\n this.element.append(editorElement);\n }\n this.editor.setContents(RichTextConversion.convertParagraphsToOps(this.paragraphs));\n }\n this.updateSize();\n };\n Textbox.prototype.saveContents = function () {\n // It's possible to get here via a throttled text-changed event after a view-mode change has occured and\n // we are now in view mode. Since we save changes on view-mode change it is safe to ignore this call.\n if (!this.editor)\n return;\n var contents = this.editor.getContents();\n this.paragraphs = RichTextConversion.convertDeltaToParagraphs(contents);\n var changes = [{\n objectName: 'general',\n properties: {\n paragraphs: this.paragraphs\n },\n selector: null,\n }];\n this.host.persistProperties(changes);\n };\n Textbox.prototype.updateSize = function () {\n if (this.editor)\n this.editor.resize(this.viewport);\n };\n Textbox.ClassName = 'textbox';\n return Textbox;\n }());\n visuals.Textbox = Textbox;\n var RichTextConversion;\n (function (RichTextConversion) {\n function convertDeltaToParagraphs(contents) {\n var paragraphs = [];\n var paragraph = { textRuns: [] };\n for (var i = 0, len = contents.ops.length; i < len; i++) {\n var insertOp = contents.ops[i];\n debug.assertValue(insertOp, \"operation should be an insert\");\n if (typeof insertOp.insert === \"string\") {\n // string insert values represent text.\n var text = insertOp.insert;\n var attributes = insertOp.attributes;\n if (attributes && attributes.align) {\n // Sometimes horizontal alignment is set after the first \"insert\" of the paragraph, which is likely a bug\n // in Quill. In any case we should never see different horizontal alignments in a single paragraph.\n debug.assert(paragraph.horizontalTextAlignment === undefined || paragraph.horizontalTextAlignment === attributes.align, 'paragraph should not have more than one horizontal alignment');\n paragraph.horizontalTextAlignment = attributes.align;\n }\n // Quill gives us back text runs that may have \\n's in them. We want to create a new paragraph for each \\n we see.\n var start = 0;\n var end = 0;\n var newParagraph = void 0;\n do {\n end = text.indexOf('\\n', start);\n if (end < 0) {\n newParagraph = false;\n end = text.length;\n }\n else {\n newParagraph = true;\n }\n if (end - start > 0) {\n var span = text.substring(start, end);\n var textRun = { value: span };\n if (attributes) {\n if (attributes.link !== undefined && UrlUtils.isValidUrl(attributes.link))\n textRun.url = attributes.link;\n var textStyle = convertFormatAttributesToTextStyle(attributes);\n if (textStyle)\n textRun.textStyle = textStyle;\n }\n paragraph.textRuns.push(textRun);\n }\n // If we actually saw a '\\n' then create a new paragraph\n if (newParagraph) {\n if (paragraph.textRuns.length === 0)\n paragraph.textRuns.push({ value: '' });\n paragraphs.push(paragraph);\n paragraph = { textRuns: [] };\n }\n start = end + 1;\n } while (start < text.length);\n }\n else {\n // numeric insert values represent embeds.\n debug.assertFail(\"embeds not supported\");\n }\n }\n if (paragraph.textRuns.length > 0) {\n // Quill appears to always insert an extra '\\n' at the end of the text, skip it\n if (paragraph.textRuns[0].value.length > 0)\n paragraphs.push(paragraph);\n }\n return paragraphs;\n }\n RichTextConversion.convertDeltaToParagraphs = convertDeltaToParagraphs;\n function convertParagraphsToHtml(paragraphs) {\n var $paragraphs = $();\n for (var paragraphIndex = 0, len = paragraphs.length; paragraphIndex < len; ++paragraphIndex) {\n var paragraphDef = paragraphs[paragraphIndex];\n var isParagraphEmpty = true;\n var $paragraph = $('<div>');\n if (paragraphDef.horizontalTextAlignment)\n $paragraph.css('text-align', paragraphDef.horizontalTextAlignment);\n for (var textRunIndex = 0, jlen = paragraphDef.textRuns.length; textRunIndex < jlen; ++textRunIndex) {\n var textRunDef = paragraphDef.textRuns[textRunIndex];\n var $textRun = $('<span>');\n var styleDef = textRunDef.textStyle;\n if (styleDef) {\n var css = {};\n if (styleDef.fontFamily) {\n css['font-family'] = RichText.getCssFontFamily(removeQuotes(styleDef.fontFamily));\n }\n if (styleDef.fontSize) {\n css['font-size'] = styleDef.fontSize;\n }\n if (styleDef.fontStyle) {\n css['font-style'] = styleDef.fontStyle;\n }\n if (styleDef.fontWeight) {\n css['font-weight'] = styleDef.fontWeight;\n }\n if (styleDef.textDecoration) {\n css['text-decoration'] = styleDef.textDecoration;\n }\n $textRun.css(css);\n }\n var text = textRunDef.value;\n if (!_.isEmpty(text))\n isParagraphEmpty = false;\n if (textRunDef.url !== undefined) {\n var $link = void 0;\n if (UrlUtils.isValidUrl(textRunDef.url)) {\n $link = $('<a>')\n .attr('href', textRunDef.url)\n .attr('target', '_blank')\n .text(text);\n }\n else {\n $link = $('<span>').text(text);\n }\n $textRun.append($link);\n }\n else {\n $textRun.text(text);\n }\n $paragraph.append($textRun);\n }\n // If the entire paragraph is empty we need to make sure we enforce a line-break.\n if (isParagraphEmpty)\n $paragraph.append($('<br>'));\n $paragraphs = $paragraphs.add($paragraph);\n }\n return $paragraphs;\n }\n RichTextConversion.convertParagraphsToHtml = convertParagraphsToHtml;\n function convertParagraphsToOps(paragraphs) {\n var ops = [];\n for (var paragraphIndex = 0, len = paragraphs.length; paragraphIndex < len; ++paragraphIndex) {\n var paragraphDef = paragraphs[paragraphIndex];\n for (var textRunIndex = 0, jlen = paragraphDef.textRuns.length; textRunIndex < jlen; ++textRunIndex) {\n var textRunDef = paragraphDef.textRuns[textRunIndex];\n var formats = {};\n if (paragraphDef.horizontalTextAlignment)\n formats.align = paragraphDef.horizontalTextAlignment;\n var styleDef = textRunDef.textStyle;\n if (styleDef) {\n if (styleDef.fontFamily) {\n formats.font = RichText.getCssFontFamily(removeQuotes(styleDef.fontFamily));\n }\n if (styleDef.fontSize) {\n formats.size = styleDef.fontSize;\n }\n formats.italic = (styleDef.fontStyle === 'italic');\n formats.bold = (styleDef.fontWeight === 'bold');\n formats.underline = (styleDef.textDecoration === 'underline');\n }\n var text = textRunDef.value;\n if (textRunDef.url && UrlUtils.isValidUrl(textRunDef.url))\n formats.link = textRunDef.url;\n var op = {\n insert: text,\n attributes: formats,\n };\n ops.push(op);\n // The last text run of the paragraph needs to end with '\\n' to get Quill to handle the text alignment correctly.\n if (textRunIndex === (jlen - 1) && !StringExtensions.endsWith(text, '\\n')) {\n ops.push({\n insert: '\\n',\n attributes: formats,\n });\n }\n }\n }\n return ops;\n }\n RichTextConversion.convertParagraphsToOps = convertParagraphsToOps;\n function convertFormatAttributesToTextStyle(attributes) {\n var style = {};\n // NOTE: Align is taken care of when converting to paragraphs.\n if (attributes.bold) {\n style.fontWeight = 'bold';\n }\n if (attributes.font) {\n // We should always save font names without any quotes.\n var font = removeQuotes(attributes.font);\n // Convert built-in font families back into their proper font families (e.g. wf_segoe-ui_normal -> Segoe UI)\n font = RichText.getFontFamilyForBuiltInFont(font);\n style.fontFamily = font;\n }\n if (attributes.italic) {\n style.fontStyle = 'italic';\n }\n if (attributes.size) {\n style.fontSize = attributes.size;\n }\n if (attributes.underline) {\n style.textDecoration = 'underline';\n }\n /*\n TODO:\n if (attributes.background) {\n }\n if (attributes.color) {\n }\n */\n return style;\n }\n function removeQuotes(text) {\n if (!StringExtensions.startsWith(text, \"'\"))\n return text;\n debug.assert(StringExtensions.endsWith(text, \"'\"), \"mismatched quotes\");\n return text.slice(1, text.length - 1);\n }\n })(RichTextConversion || (RichTextConversion = {}));\n var RichText;\n (function (RichText) {\n /**\n * These fonts are embedded using CSS, or are aliases to other fonts.\n */\n var fontMap = {\n 'Segoe (Bold)': 'wf_segoe-ui_bold',\n 'Segoe UI': 'wf_segoe-ui_normal',\n 'Segoe UI Light': 'wf_segoe-ui_light',\n 'Heading': 'wf_segoe-ui_light',\n 'Body': 'wf_segoe-ui_normal',\n };\n var fonts = [\n 'Arial',\n 'Arial Black',\n 'Arial Unicode MS',\n 'Calibri',\n 'Cambria',\n 'Cambria Math',\n 'Candara',\n 'Comic Sans MS',\n 'Consolas',\n 'Constantia',\n 'Corbel',\n 'Courier New',\n 'Georgia',\n 'Lucida Sans Unicode',\n 'Segoe (Bold)',\n 'Segoe UI',\n 'Segoe UI Light',\n 'Symbol',\n 'Tahoma',\n 'Times New Roman',\n 'Trebuchet MS',\n 'Verdana',\n 'Wingdings',\n ].map(function (font) { return { label: font, value: getCssFontFamily(font) }; });\n RichText.defaultFont = getCssFontFamily('Segoe UI Light');\n var fontSizes = [\n '8', '9', '10', '10.5', '11', '12', '14', '16', '18', '20', '24', '28', '32', '36', '40', '42', '44', '54', '60', '66', '72', '80', '88', '96'\n ].map(function (size) { return { label: size, value: size + 'px' }; });\n RichText.defaultFontSize = '14px';\n var textAlignments = [\n 'Left',\n 'Center',\n 'Right',\n ].map(function (alignment) { return { label: alignment, value: alignment.toLowerCase() }; });\n /**\n * Given a font family returns the value we should use for the font-family css property.\n */\n function getCssFontFamily(font) {\n var family = fontMap[font];\n if (family == null)\n family = font;\n return family;\n }\n RichText.getCssFontFamily = getCssFontFamily;\n /**\n * Convert built-in font families back into their proper font families (e.g. wf_segoe-ui_normal -> Segoe UI)\n */\n function getFontFamilyForBuiltInFont(font) {\n var fontFamily = _.findKey(fontMap, function (value) { return value === font; });\n return fontFamily || font;\n }\n RichText.getFontFamilyForBuiltInFont = getFontFamilyForBuiltInFont;\n var QuillWrapper = (function () {\n /**\n * JavaScript and CSS resources are typically resolved asynchronously.\n * This means we potentially defer certain events which typically occur\n * synchronously until resources are loaded.\n * Setting the global loadQuillResources flag to true will override\n * this behavior and cause the wrapper to assume these resources are already loaded\n * and not try to load them asynchronously (e.g. for use in unit tests).\n */\n function QuillWrapper(readOnly, host) {\n var _this = this;\n this.QuillPackage = {\n javaScriptFiles: QuillWrapper.quillJsFiles,\n cssFiles: QuillWrapper.quillCssFiles,\n };\n this.textChanged = function (d, s) { };\n this.host = host;\n this.$container = $('<div>');\n this.readOnly = readOnly;\n this.localizationProvider = {\n get: function (stringId) { return _this.host.getLocalizedString(stringId); },\n getOptional: function (stringId) { return _this.host.getLocalizedString(stringId); }\n };\n this.dependenciesLoaded = $.Deferred();\n if (QuillWrapper.loadQuillResources) {\n // Defer creation of the editor until after resources are loaded.\n this.initialized = false;\n // Note that these are called in the order registered so this will always be called before other callbacks.\n this.dependenciesLoaded.done(function () {\n _this.rebuildQuillEditor();\n _this.initialized = true;\n });\n jsCommon.requires(this.QuillPackage, function () { return _this.dependenciesLoaded.resolve(); });\n }\n else {\n this.rebuildQuillEditor();\n this.initialized = true;\n this.dependenciesLoaded.resolve();\n }\n }\n QuillWrapper.prototype.addModule = function (name, options) {\n if (this.editor)\n return this.editor.addModule(name, options);\n };\n QuillWrapper.prototype.getElement = function () {\n return this.$container;\n };\n QuillWrapper.prototype.getContents = function () {\n if (this.initialized)\n return this.editor.getContents();\n };\n QuillWrapper.prototype.setContents = function (contents) {\n var _this = this;\n // If we haven't loaded the editor yet, defer this call until we do\n // TODO: prevent these from stacking up?\n if (!this.initialized) {\n this.dependenciesLoaded.done(function () { return _this.setContents(contents); });\n return;\n }\n this.editor.setHTML('', 'api'); // Clear contents\n if (contents)\n this.editor.setContents(contents, 'api');\n };\n QuillWrapper.prototype.resize = function (viewport) {\n this.$container.width(viewport.width);\n this.$container.height(viewport.height);\n };\n QuillWrapper.prototype.setReadOnly = function (readOnly) {\n var readOnlyChanged = readOnly !== this.readOnly;\n this.readOnly = readOnly;\n if (this.initialized && readOnlyChanged) {\n this.rebuildQuillEditor();\n }\n };\n QuillWrapper.prototype.setSelection = function (start, end) {\n if (this.editor)\n this.editor.setSelection(start, end, 'api');\n };\n QuillWrapper.prototype.getSelection = function () {\n if (this.editor)\n return this.editor.getSelection();\n };\n QuillWrapper.prototype.focus = function () {\n if (!this.editor)\n return;\n if ($(document.activeElement).closest(this.$container).length === 0)\n this.editor.focus();\n };\n QuillWrapper.prototype.destroy = function () {\n this.host.setToolbar(null);\n this.$container.remove();\n this.$container = null;\n this.$toolbarDiv = null;\n this.$editorDiv = null;\n this.editor = null;\n };\n QuillWrapper.prototype.getSelectionAtCursor = function () {\n var text = this.getTextWithoutTrailingBreak();\n // Ensure editor has focus before selection interactions\n this.editor.focus();\n var selection = this.getSelection();\n if (selection && selection.start === selection.end) {\n return jsCommon.WordBreaker.find(selection.start, text);\n }\n return selection;\n };\n QuillWrapper.prototype.getWord = function () {\n var selection = this.getSelectionAtCursor();\n return this.getTextWithoutTrailingBreak().slice(selection.start, selection.end);\n };\n QuillWrapper.prototype.insertLinkAtCursor = function (link, index) {\n var endIndex = index + link.length;\n this.editor.insertText(index, link, 'api');\n this.editor.formatText(index, endIndex, 'link', link, 'api');\n this.setSelection(index, endIndex);\n this.onTextChanged(null, null);\n return endIndex;\n };\n QuillWrapper.prototype.getEditorContainer = function () {\n if (this.editor)\n return $(this.editor.container);\n };\n ;\n QuillWrapper.prototype.getTextWithoutTrailingBreak = function () {\n return this.editor.getText().slice(0, -1);\n };\n QuillWrapper.prototype.rebuildQuillEditor = function () {\n var _this = this;\n // Preserve contents if we already have an editor.\n var contents = null;\n if (this.editor) {\n this.editor.removeAllListeners();\n contents = this.editor.getContents();\n }\n this.$container.empty();\n // Prevent parent elements from handling keyboard shortcuts (e.g. ctrl+a) that have special meaning for textboxes.\n // Quill will also capture and prevent bubbling of some keyboard shortcuts, such as ctrl+c, ctrl+b, etc.\n this.$container.keydown(function (e) {\n if (e.ctrlKey && _.contains(QuillWrapper.preventDefaultKeys, e.which))\n e.stopPropagation();\n if (KeyUtils.isArrowKey(e.which))\n e.stopPropagation();\n });\n var $editorDiv = this.$editorDiv = $('<div>');\n // HACK: Quill does not apply the correct default styling if you clear all the content and add new content.\n $editorDiv.css('font-family', RichText.defaultFont);\n $editorDiv.css('font-size', RichText.defaultFontSize);\n var configs = {\n readOnly: this.readOnly,\n formats: ['bold', 'italic', 'underline', 'font', 'size', 'link', 'align',],\n styles: false,\n };\n this.editor = new Quill($editorDiv.get(0), configs);\n // If not readonly we add a toolbar and disable drag/resize\n if (!this.readOnly) {\n var $toolbarDiv = this.$toolbarDiv;\n if (!$toolbarDiv) {\n this.$toolbarDiv = $toolbarDiv = Toolbar.buildToolbar(this, this.localizationProvider);\n }\n $toolbarDiv.addClass('unselectable');\n this.host.setToolbar($toolbarDiv);\n this.editor.addModule('toolbar', { container: $toolbarDiv.get(0) });\n // Disable this so we can select text in the editor.\n $editorDiv.attr('drag-resize-disabled', 'true');\n }\n this.$container.append($editorDiv);\n if (contents)\n this.setContents(contents);\n // Throttle text-changed events to not more frequent than once per 200ms\n var textChangeThrottler = new jsCommon.ThrottleUtility(QuillWrapper.textChangeThrottle);\n this.editor.on('text-change', function (delta, source) {\n if (source !== 'api')\n textChangeThrottler.run(function () { return _this.onTextChanged(delta, source); });\n });\n /*\n Webkit browsers have a bug with regard to focus on div elements\n with the contenteditable attribute:\n \n https://bugs.webkit.org/show_bug.cgi?id=38696\n \n When we blur our rich text box editor the focus remains with the selection\n instead of the focused element. This allows the user to continue typing as\n if focus remains within the RichTextbox.\n \n To fix this issue we add an event listener to the contenteditable div\n which listens for the 'blur' event and will properly blur our quill\n editor as well.\n \n http://quilljs.com/docs/api/#quillprototypesetselection\n \n Verified in Chrome 43.0.2357.130 m\n \n In IE10+ the setSelection method explicitly sets focus to the body which\n causes a bug where the user must click twice when attempting to interact\n with a <select> element. To prevent this issue we explicitly do not call\n setSelection to blur if the user is changing focus to a <select> element.\n This issue is also present for link tooltips from the Quill module which\n will cause a blur onto the tooltip.\n */\n this.editor.root.addEventListener('blur', function (event) {\n var target = (event.relatedTarget || document.activeElement);\n // The browser will handle moving the cursor and setting focus properly for these types of elements.\n if (target &&\n target.tagName === 'SELECT' || target.tagName === 'INPUT' || target.getAttribute('contentEditable')) {\n return;\n }\n _this.setSelection(null, null);\n }, false);\n };\n QuillWrapper.prototype.onTextChanged = function (delta, source) {\n this.textChanged(delta, source);\n };\n QuillWrapper.textChangeThrottle = 200; // ms\n QuillWrapper.preventDefaultKeys = [\n jsCommon.DOMConstants.aKeyCode,\n jsCommon.DOMConstants.cKeyCode,\n jsCommon.DOMConstants.xKeyCode,\n jsCommon.DOMConstants.vKeyCode,\n ];\n QuillWrapper.loadQuillResources = true;\n // TODO: How to choose between minified/unminified?\n // TODO: Consider loading this from the CDN.\n QuillWrapper.quillJsFiles = [powerbi.build + '/externals/quill.min.js'];\n QuillWrapper.quillCssFiles = [powerbi.build + '/externals/quill.base.css'];\n return QuillWrapper;\n }());\n RichText.QuillWrapper = QuillWrapper;\n var Toolbar;\n (function (Toolbar) {\n var DefaultLinkInputValue = 'http://';\n Toolbar.selectors = {\n linkTooltip: createClassAndSelector('ql-link-tooltip'),\n toolbarUrlInput: createClassAndSelector('toolbar-url-input'),\n };\n function buildToolbar(quillWrapper, localizationProvider) {\n // Module for adding custom hyperlinks\n var linkTooltipTemplate = buildToolbarLinkInputTemplate(localizationProvider);\n quillWrapper.addModule('link-tooltip', { template: linkTooltipTemplate });\n var toolbarLinkInput = buildToolbarLinkInput(quillWrapper, getTooltip('Link', localizationProvider), localizationProvider.get('RichTextbox_Link_DefaultText'));\n var fontPicker = picker(getTooltip('Font', localizationProvider), fonts, 'font', RichText.defaultFont, \n // Show the fonts in their own font face.\n function ($option, option) { $option.css('font-family', option.value); return $option; });\n var $container = div()\n .addClass('toolbar ql-toolbar')\n .append(formatGroup()\n .append(label(localizationProvider.get('RichTextbox_Font_Label')))\n .append(fontPicker)\n .append(picker(getTooltip('Size', localizationProvider), fontSizes, 'size', RichText.defaultFontSize)))\n .append(formatGroup()\n .append(formatButton(getTooltip('Bold', localizationProvider), 'bold'))\n .append(formatButton(getTooltip('Italic', localizationProvider), 'italic'))\n .append(formatButton(getTooltip('Underline', localizationProvider), 'underline')))\n .append(formatGroup()\n .append(toggleGroup('Text Alignment', textAlignments, 'align', 'Left', localizationProvider)))\n .append(toolbarLinkInput);\n // Prevent mousedown from triggering subsequent blur on editor\n $container.on('mousedown', function (event) {\n var target = (event.target || document.activeElement);\n if (target.tagName !== 'INPUT' && target.tagName !== 'SELECT')\n event.preventDefault();\n });\n return $container;\n }\n Toolbar.buildToolbar = buildToolbar;\n function setSelectValue($select, value) {\n $select.val(value);\n // NOTE: The 'change' event is not raised when the value of the SELECT element is changed programatically,\n // and Quill uses it's own, non-JQuery, method to hook up to the 'change' event, therefore, we need to dispatch\n // this event manually on the SELECT element.\n var evt = document.createEvent('UIEvent');\n evt.initUIEvent('change', false, false, null, 0);\n $select.get(0).dispatchEvent(evt);\n }\n Toolbar.setSelectValue = setSelectValue;\n function linkTooltipTemplateGenerator(removeText, doneText) {\n return $(\"\\n <a href=\\\"#\\\" class=\\\"url\\\" target=\\\"_blank\\\"></a>\\n <input class=\\\"input\\\" type=\\\"text\\\">\\n <span class=\\\"bar\\\">&nbsp;|&nbsp;</span>\\n <a class=\\\"change\\\"></a>\\n <a class=\\\"remove\\\">\" + removeText + \"</a>\\n <a class=\\\"done\\\">\" + doneText + \"</a>\\n \");\n }\n ;\n function buildToolbarLinkInputTemplate(localizationProvider) {\n var template = div();\n var doneText = localizationProvider.get('RichTextbox_Link_Done');\n var removeText = localizationProvider.get('RichTextbox_Link_Remove');\n template.append(linkTooltipTemplateGenerator(removeText, doneText));\n return template.html();\n }\n function formatGroup() {\n return span()\n .addClass('ql-format-group')\n .attr('drag-resize-disabled', 'true');\n }\n function label(text) {\n return $('<label>').text(text);\n }\n function div() {\n return $('<div>');\n }\n function span() {\n return $('<span>');\n }\n function toggleGroup(title, list, format, defaultValue, localizationProvider) {\n var tooltip = getTooltip(title, localizationProvider);\n var $group = span()\n .attr('title', tooltip)\n .addClass('ql-toggle-group');\n // Hidden selector that Quill will use to hook up change listeners.\n var $select = selector(tooltip, list, defaultValue)\n .addClass('ql-picker ql-' + format)\n .css('display', 'none');\n var $buttons = list.map(function (option) {\n var $button = formatButton(getTooltip(option.label, localizationProvider), 'align' + option.value)\n .attr('data-value', option.value)\n .click(function (e) { return setSelectValue($select, option.value); });\n return $button;\n });\n // Quill will change the value of the selector when the text selection changes, so we need to set the state of the buttons to match.\n $select.change(function (e) {\n var newValue = $select.val();\n for (var i = 0; i < $buttons.length; i++) {\n $buttons[i].toggleClass('ql-active', $buttons[i].attr('data-value') === newValue);\n }\n });\n $group.append($select);\n $group.append($buttons);\n return $group;\n }\n function picker(tooltip, list, format, defaultValue, optionModifier) {\n var $selector = selector(tooltip, list, defaultValue, optionModifier)\n .addClass('ql-picker ql-' + format);\n return $selector;\n }\n function selector(tooltip, list, defaultValue, optionModifier) {\n var $selector = $('<select>')\n .attr('title', tooltip);\n for (var i = 0; i < list.length; i++) {\n var option = list[i];\n var $option = $('<option>')\n .attr('value', option.value)\n .text(option.label);\n if (option.value === defaultValue)\n $option.attr('selected', 'selected');\n if (optionModifier !== undefined)\n $option = optionModifier($option, option);\n $selector.append($option);\n }\n return $selector;\n }\n function formatButton(tooltip, format) {\n var $button = span()\n .addClass('ql-format-button');\n if (tooltip != null)\n $button.attr('title', tooltip);\n if (format != null) {\n $button.addClass('ql-' + format);\n $button.addClass('powervisuals-glyph ' + format);\n }\n return $button;\n }\n function getTooltip(name, localizationProvider) {\n return localizationProvider.get('RichTextbox_' + name + '_ToolTip');\n }\n function clearLinkInput(linkTooltip) {\n linkTooltip.removeClass('editing');\n linkTooltip.removeClass('blank-editing');\n linkTooltip.find('.input').val(DefaultLinkInputValue);\n }\n function buildToolbarLinkInput(quillWrapper, buttonTooltip, defaultLinkText) {\n // Pull out link tooltip\n var linkTooltip = quillWrapper.getEditorContainer().find(Toolbar.selectors.linkTooltip.selector);\n // Append link tooltip to a new toolbar format group\n var toolbarLinkInput = formatGroup()\n .addClass(Toolbar.selectors.toolbarUrlInput.class)\n .append(formatButton(buttonTooltip, 'link').append('<div>'))\n .append(linkTooltip);\n // Special case for blank selection (no text near cursor) when enter key or done button clicked\n toolbarLinkInput.on('keydown mousedown', function (event) {\n if (event.keyCode === jsCommon.DOMConstants.enterKeyCode || event.target.classList.contains('done')) {\n if (!linkTooltip.hasClass('blank-editing'))\n return true;\n // Only perform these steps if tooltip was not in editing mode (special case for blank)\n var link = toolbarLinkInput.find('.input').val();\n var selection = quillWrapper.getSelectionAtCursor();\n var word = quillWrapper.getWord();\n if (!word) {\n // Insert the input text as a link\n var endCursor = quillWrapper.insertLinkAtCursor(link, selection.start);\n clearLinkInput(linkTooltip);\n quillWrapper.setSelection(endCursor, endCursor);\n return false;\n }\n }\n });\n toolbarLinkInput.find('.input').blur(function (event) {\n var blurTarget = event.relatedTarget;\n // Remove editing class from insert link tooltip (to hide via CSS)\n // only when we are not blurring to the 'done' button (tab from input field)\n if (blurTarget === null || blurTarget && !blurTarget.classList.contains('done'))\n clearLinkInput(linkTooltip);\n });\n toolbarLinkInput.find('.ql-link div')\n .click(function (event) {\n // Handle click on button before Quill removes link (default behavior)\n var target = event.target.parentElement;\n if (target && target.classList.contains('ql-active')) {\n toolbarLinkInput.find('.change')[0].click();\n return false;\n }\n // If blank selection (no text near cursor), special case for link button\n var word = quillWrapper.getWord();\n if (!word) {\n linkTooltip.addClass('editing blank-editing');\n var inputElem = toolbarLinkInput.find('.input').get(0);\n inputElem.value = DefaultLinkInputValue;\n inputElem.selectionStart = inputElem.selectionEnd = DefaultLinkInputValue.length;\n inputElem.focus();\n return false;\n }\n })\n .mousedown(function (event) {\n // Properly set selection before we handle the click\n var linkButton = event.target.parentElement;\n if (linkButton && !linkButton.classList.contains('ql-active')) {\n var selection = quillWrapper.getSelectionAtCursor();\n quillWrapper.setSelection(selection.start, selection.end);\n }\n });\n return toolbarLinkInput;\n }\n })(Toolbar || (Toolbar = {}));\n })(RichText = visuals.RichText || (visuals.RichText = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n* Power BI Visualizations\n*\n* Copyright (c) Microsoft Corporation\n* All rights reserved.\n* MIT License\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* The above copyright notice and this permission notice shall be included in\n* all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n* THE SOFTWARE.\n*/\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var SelectionManager = visuals.utility.SelectionManager;\n visuals.cheerMeterProps = {\n dataPoint: {\n defaultColor: {\n objectName: 'dataPoint',\n propertyName: 'defaultColor'\n },\n fill: {\n objectName: 'dataPoint',\n propertyName: 'fill'\n },\n },\n };\n var CheerMeter = (function () {\n function CheerMeter() {\n this.isFirstTime = true;\n }\n CheerMeter.converter = function (dataView) {\n if (!dataView.categorical || !dataView.categorical.categories)\n return null;\n var cat = dataView.categorical.categories[0];\n if (!cat)\n return null;\n var catValues = cat.values;\n if (!catValues || _.isEmpty(dataView.categorical.values))\n return null;\n var values = dataView.categorical.values[0].values;\n var objects = dataView.categorical.categories[0].objects;\n var object1 = objects && objects.length > 0 ? objects[0] : undefined;\n var object2 = objects && objects.length > 1 ? objects[1] : undefined;\n var metadataObjects = dataView.metadata.objects;\n var backgroundColor = CheerMeter.DefaultBackgroundColor;\n if (metadataObjects) {\n var general = metadataObjects['general'];\n if (general) {\n var fill = general['fill'];\n if (fill) {\n backgroundColor = fill.solid.color;\n }\n }\n }\n var color1 = powerbi.DataViewObjects.getFillColor(object1, visuals.cheerMeterProps.dataPoint.fill, CheerMeter.DefaultFontColor);\n var color2 = powerbi.DataViewObjects.getFillColor(object2, visuals.cheerMeterProps.dataPoint.fill, CheerMeter.DefaultFontColor);\n var idn1 = visuals.SelectionIdBuilder.builder()\n .withCategory(cat, 0)\n .createSelectionId();\n var idn2 = visuals.SelectionIdBuilder.builder()\n .withCategory(cat, 1)\n .createSelectionId();\n var data = {\n teamA: {\n name: catValues[0],\n value: values[0],\n color: color1,\n identity: idn1\n },\n teamB: {\n name: catValues[1],\n value: values[1],\n color: color2,\n identity: idn2\n },\n background: backgroundColor\n };\n return data;\n };\n CheerMeter.prototype.init = function (options) {\n this.selectionManager = new SelectionManager({ hostServices: options.host });\n var svg = this.svg = d3.select(options.element.get(0)).append('svg');\n this.textOne = svg.append('text')\n .style('font-family', CheerMeter.DefaultFontFamily);\n this.textTwo = svg.append('text')\n .style('font-family', CheerMeter.DefaultFontFamily);\n };\n CheerMeter.prototype.update = function (options) {\n if (!options.dataViews[0]) {\n return;\n }\n var data = this.data = CheerMeter.converter(options.dataViews[0]);\n if (!data)\n return;\n var duration = options.suppressAnimations ? 0 : visuals.AnimatorCommon.MinervaAnimationDuration;\n this.draw(data, duration, options.viewport);\n };\n CheerMeter.prototype.getRecomendedFontProperties = function (text1, text2, parentViewport) {\n var textProperties = {\n fontSize: '',\n fontFamily: CheerMeter.DefaultFontFamily,\n text: text1 + text2\n };\n var min = 1;\n var max = 1000;\n var i;\n var maxWidth = parentViewport.width;\n var width = 0;\n while (min <= max) {\n i = (min + max) / 2 | 0;\n textProperties.fontSize = i + 'px';\n width = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n if (maxWidth > width)\n min = i + 1;\n else if (maxWidth < width)\n max = i - 1;\n else\n break;\n }\n textProperties.fontSize = i + 'px';\n width = powerbi.TextMeasurementService.measureSvgTextWidth(textProperties);\n if (width > maxWidth) {\n i--;\n textProperties.fontSize = i + 'px';\n }\n return textProperties;\n };\n CheerMeter.prototype.calculateLayout = function (data, viewport) {\n var text1 = data.teamA.name;\n var text2 = data.teamB.name;\n var avaliableViewport = {\n height: viewport.height,\n width: viewport.width - CheerMeter.PaddingBetweenText\n };\n var recomendedFontProperties = this.getRecomendedFontProperties(text1, text2, avaliableViewport);\n recomendedFontProperties.text = text1;\n var width1 = powerbi.TextMeasurementService.measureSvgTextWidth(recomendedFontProperties) | 0;\n recomendedFontProperties.text = text2;\n var width2 = powerbi.TextMeasurementService.measureSvgTextWidth(recomendedFontProperties) | 0;\n var padding = ((viewport.width - width1 - width2 - CheerMeter.PaddingBetweenText) / 2) | 0;\n recomendedFontProperties.text = text1 + text2;\n var offsetHeight = (powerbi.TextMeasurementService.measureSvgTextHeight(recomendedFontProperties)) | 0;\n var max = data.teamA.value + data.teamB.value;\n var availableHeight = viewport.height - offsetHeight;\n var y1 = (((max - data.teamA.value) / max) * availableHeight + offsetHeight / 2) | 0;\n var y2 = (((max - data.teamB.value) / max) * availableHeight + offsetHeight / 2) | 0;\n return {\n x1: padding,\n x2: padding + width1 + CheerMeter.PaddingBetweenText,\n y1: y1,\n y2: y2,\n fontSize: recomendedFontProperties.fontSize\n };\n };\n CheerMeter.prototype.ensureStartState = function (layout, viewport) {\n if (this.isFirstTime) {\n this.isFirstTime = false;\n var startY = viewport.height / 2;\n this.textOne.attr({\n 'x': layout.x1,\n 'y': startY\n });\n this.textTwo.attr({\n 'x': layout.x2,\n 'y': startY\n });\n }\n };\n CheerMeter.prototype.clearSelection = function () {\n var _this = this;\n this.selectionManager.clear().then(function () {\n _this.clearSelectionUI();\n });\n };\n CheerMeter.prototype.clearSelectionUI = function () {\n this.textOne.style('stroke', '#FFF').style('stroke-width', 0);\n this.textTwo.style('stroke', '#FFF').style('stroke-width', 0);\n };\n CheerMeter.prototype.updateSelectionUI = function (ids) {\n this.textOne.style('stroke', '#FFF').style('stroke-width', SelectionManager.containsSelection(ids, this.data.teamA.identity) ? '2px' : '0px');\n this.textTwo.style('stroke', '#FFF').style('stroke-width', SelectionManager.containsSelection(ids, this.data.teamB.identity) ? '2px' : '0px');\n };\n CheerMeter.prototype.draw = function (data, duration, viewport) {\n var _this = this;\n var easeName = 'back';\n var textOne = this.textOne;\n var textTwo = this.textTwo;\n this.svg\n .attr({\n 'height': viewport.height,\n 'width': viewport.width\n })\n .on('click', function () {\n _this.clearSelection();\n })\n .style('background-color', data.background);\n var layout = this.calculateLayout(data, viewport);\n this.ensureStartState(layout, viewport);\n textOne\n .style('font-size', layout.fontSize)\n .style('fill', data.teamA.color)\n .on('click', function () {\n _this.selectionManager.select(data.teamA.identity, d3.event.ctrlKey).then(function (ids) {\n _this.updateSelectionUI(ids);\n });\n d3.event.stopPropagation();\n })\n .text(data.teamA.name);\n textTwo\n .style('font-size', layout.fontSize)\n .style('fill', data.teamB.color)\n .on('click', function () {\n _this.selectionManager.select(data.teamB.identity, d3.event.ctrlKey).then(function (ids) {\n _this.updateSelectionUI(ids);\n });\n d3.event.stopPropagation();\n })\n .text(data.teamB.name);\n textOne.transition()\n .duration(duration)\n .ease(easeName)\n .attr({\n y: layout.y1,\n x: layout.x1\n });\n textTwo.transition()\n .duration(duration)\n .ease(easeName)\n .attr({\n y: layout.y2,\n x: layout.x2\n });\n };\n CheerMeter.prototype.destroy = function () {\n this.svg = null;\n this.textOne = this.textTwo = null;\n };\n CheerMeter.prototype.enumerateObjectInstances = function (options) {\n var instances = [];\n var data = this.data;\n switch (options.objectName) {\n case 'dataPoint':\n if (data) {\n var teams = [data.teamA, data.teamB];\n for (var i = 0; i < teams.length; i++) {\n var slice = teams[i];\n var color = slice.color;\n var selector = slice.identity;\n var dataPointInstance = {\n objectName: 'dataPoint',\n displayName: slice.name,\n selector: selector,\n properties: {\n fill: { solid: { color: color } }\n },\n };\n instances.push(dataPointInstance);\n }\n ;\n }\n break;\n case 'general':\n var general = {\n objectName: 'general',\n displayName: 'General',\n selector: null,\n properties: {\n fill: { solid: { color: data ? data.background : CheerMeter.DefaultBackgroundColor } }\n }\n };\n instances.push(general);\n break;\n }\n return instances;\n };\n CheerMeter.capabilities = {\n dataRoles: [\n {\n displayName: 'Category',\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n },\n {\n displayName: 'Noise Measure',\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n },\n ],\n dataViewMappings: [{\n categorical: {\n categories: {\n for: { in: 'Category' },\n },\n values: {\n select: [{ bind: { to: 'Y' } }]\n },\n },\n }],\n objects: {\n dataPoint: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_DataPoint'),\n description: powerbi.data.createDisplayNameGetter('Visual_DataPointDescription'),\n properties: {\n fill: {\n displayName: powerbi.data.createDisplayNameGetter('Visual_Fill'),\n type: { fill: { solid: { color: true } } }\n },\n width: {\n displayName: '',\n type: { numeric: true }\n }\n }\n },\n general: {\n displayName: 'General',\n properties: {\n fill: {\n displayName: 'Background color',\n type: { fill: { solid: { color: true } } }\n },\n }\n }\n }\n };\n CheerMeter.DefaultFontFamily = 'cursive';\n CheerMeter.DefaultFontColor = 'rgb(165, 172, 175)';\n CheerMeter.DefaultBackgroundColor = '#243C18';\n CheerMeter.PaddingBetweenText = 15;\n return CheerMeter;\n }());\n visuals.CheerMeter = CheerMeter;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Color = jsCommon.Color;\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var PixelConverter = jsCommon.PixelConverter;\n var DataRoleHelper = powerbi.data.DataRoleHelper;\n var ScatterChart = (function () {\n function ScatterChart(options) {\n if (options) {\n this.tooltipsEnabled = options.tooltipsEnabled;\n this.interactivityService = options.interactivityService;\n this.animator = options.animator;\n }\n this.renderer = new SvgRenderer();\n }\n ScatterChart.prototype.init = function (options) {\n this.options = options;\n this.element = options.element;\n this.currentViewport = options.viewport;\n this.style = options.style;\n this.host = options.host;\n this.colors = this.style.colorPalette.dataColors;\n this.interactivity = options.interactivity;\n this.cartesianVisualHost = options.cartesianHost;\n this.isMobileChart = options.interactivity && options.interactivity.isInteractiveLegend;\n var svg = this.svg = options.svg;\n // TODO: should we always be adding the playchart class name?\n svg.classed(ScatterChart.ClassName + ' ' + visuals.PlayChart.ClassName, true);\n this.renderer.init(svg, options.labelsContext, this.isMobileChart, this.tooltipsEnabled);\n };\n ScatterChart.getAdditionalTelemetry = function (dataView) {\n var telemetry = {\n hasSize: DataRoleHelper.hasRoleInDataView(dataView, 'Size'),\n hasPlayAxis: DataRoleHelper.hasRoleInDataView(dataView, 'Play'),\n };\n return telemetry;\n };\n ScatterChart.getObjectProperties = function (dataView, dataLabelsSettings) {\n var objects;\n if (dataView && dataView.metadata && dataView.metadata.objects)\n objects = dataView.metadata.objects;\n else\n objects = {};\n var objectProperties = {};\n objectProperties.defaultDataPointColor = powerbi.DataViewObjects.getFillColor(objects, visuals.columnChartProps.dataPoint.defaultColor);\n objectProperties.showAllDataPoints = powerbi.DataViewObjects.getValue(objects, visuals.columnChartProps.dataPoint.showAllDataPoints, false);\n var labelsObj = objects['categoryLabels'];\n if (labelsObj && dataLabelsSettings)\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\n // NOTE: \"fill point\" defaults to on when we have a gradient role.\n var hasGradient = dataView && visuals.GradientUtils.hasGradientRole(dataView.categorical);\n objectProperties.fillPoint = powerbi.DataViewObjects.getValue(objects, visuals.scatterChartProps.fillPoint.show, hasGradient);\n objectProperties.colorBorder = powerbi.DataViewObjects.getValue(objects, visuals.scatterChartProps.colorBorder.show, false);\n objectProperties.colorByCategory = powerbi.DataViewObjects.getValue(objects, visuals.scatterChartProps.colorByCategory.show, false);\n return objectProperties;\n };\n ScatterChart.converter = function (dataView, options, playFrameInfo, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n var categoryValues, categoryFormatter, categoryObjects, categoryIdentities, categoryQueryName;\n var currentViewport = options.viewport;\n var colorPalette = options.colors;\n var interactivityService = options.interactivityService;\n var categoryAxisProperties = options.categoryAxisProperties;\n var valueAxisProperties = options.valueAxisProperties;\n var dataViewCategorical = dataView.categorical;\n var gradientValueColumn = visuals.GradientUtils.getGradientValueColumn(dataViewCategorical);\n if (dataViewCategorical.categories && dataViewCategorical.categories.length > 0) {\n categoryValues = dataViewCategorical.categories[0].values;\n categoryFormatter = visuals.valueFormatter.create({ format: visuals.valueFormatter.getFormatString(dataViewCategorical.categories[0].source, visuals.scatterChartProps.general.formatString), value: categoryValues[0], value2: categoryValues[categoryValues.length - 1] });\n categoryIdentities = dataViewCategorical.categories[0].identity;\n categoryObjects = dataViewCategorical.categories[0].objects;\n categoryQueryName = dataViewCategorical.categories[0].source.queryName;\n }\n else {\n categoryValues = [null];\n // creating default formatter for null value (to get the right string of empty value from the locale)\n categoryFormatter = visuals.valueFormatter.createDefaultFormatter(null);\n }\n var categories = dataViewCategorical.categories;\n var dataValues = dataViewCategorical.values;\n var hasDynamicSeries = !!dataValues.source;\n var grouped = dataValues.grouped();\n var dvSource = dataValues.source;\n var scatterMetadata = ScatterChart.getMetadata(grouped, dvSource);\n var dataLabelsSettings = visuals.dataLabelUtils.getDefaultPointLabelSettings();\n var sizeRange = ScatterChart.getSizeRangeForGroups(grouped, scatterMetadata.idx.size);\n var objProps = ScatterChart.getObjectProperties(dataView, dataLabelsSettings);\n var dataPointSeries = ScatterChart.createDataPointSeries(reader, dataValues, scatterMetadata, categories, categoryValues, categoryFormatter, categoryIdentities, categoryObjects, colorPalette, currentViewport, hasDynamicSeries, dataLabelsSettings, gradientValueColumn, objProps.defaultDataPointColor, categoryQueryName, objProps.colorByCategory, playFrameInfo, tooltipsEnabled);\n var dataPoints = _.reduce(dataPointSeries, function (a, s) { return a.concat(s.dataPoints); }, []);\n var legendItems = hasDynamicSeries\n ? ScatterChart.createSeriesLegend(dataValues, colorPalette, dataValues, visuals.valueFormatter.getFormatString(dvSource, visuals.scatterChartProps.general.formatString), objProps.defaultDataPointColor)\n : [];\n var legendTitle = dataValues && dvSource ? dvSource.displayName : \"\";\n if (!legendTitle) {\n legendTitle = categories && categories.length > 0 && categories[0].source.displayName ? categories[0].source.displayName : \"\";\n }\n if (categoryAxisProperties && categoryAxisProperties[\"showAxisTitle\"] !== null && categoryAxisProperties[\"showAxisTitle\"] === false) {\n scatterMetadata.axesLabels.x = null;\n }\n if (valueAxisProperties && valueAxisProperties[\"showAxisTitle\"] !== null && valueAxisProperties[\"showAxisTitle\"] === false) {\n scatterMetadata.axesLabels.y = null;\n }\n if (interactivityService) {\n interactivityService.applySelectionStateToData(dataPoints);\n interactivityService.applySelectionStateToData(legendItems);\n }\n return {\n xCol: scatterMetadata.cols.x,\n yCol: scatterMetadata.cols.y,\n dataPoints: dataPoints,\n dataPointSeries: dataPointSeries,\n legendData: { title: legendTitle, dataPoints: legendItems },\n axesLabels: scatterMetadata.axesLabels,\n size: scatterMetadata.cols.size,\n sizeRange: sizeRange,\n dataLabelsSettings: dataLabelsSettings,\n defaultDataPointColor: objProps.defaultDataPointColor,\n hasDynamicSeries: hasDynamicSeries,\n showAllDataPoints: objProps.showAllDataPoints,\n fillPoint: objProps.fillPoint,\n colorBorder: objProps.colorBorder,\n colorByCategory: objProps.colorByCategory,\n };\n };\n ScatterChart.getSizeRangeForGroups = function (dataViewValueGroups, sizeColumnIndex) {\n var result = {};\n if (dataViewValueGroups) {\n dataViewValueGroups.forEach(function (group) {\n var sizeColumn = ScatterChart.getMeasureValue(sizeColumnIndex, group.values);\n var currentRange = visuals.AxisHelper.getRangeForColumn(sizeColumn);\n if (result.min == null || result.min > currentRange.min) {\n result.min = currentRange.min;\n }\n if (result.max == null || result.max < currentRange.max) {\n result.max = currentRange.max;\n }\n });\n }\n return result;\n };\n ScatterChart.createDataPointSeries = function (reader, dataValues, metadata, categories, categoryValues, categoryFormatter, categoryIdentities, categoryObjects, colorPalette, viewport, hasDynamicSeries, labelSettings, gradientValueColumn, defaultDataPointColor, categoryQueryName, colorByCategory, playFrameInfo, tooltipsEnabled) {\n var hasX = reader.hasValues(\"X\");\n var hasY = reader.hasValues(\"Y\");\n if (!hasX && !hasY) {\n return [];\n }\n var dataPointSeries = [], indicies = metadata.idx, formatStringProp = visuals.scatterChartProps.general.formatString, dataValueSource = dataValues.source, grouped = dataValues.grouped();\n var colorHelper = new visuals.ColorHelper(colorPalette, visuals.scatterChartProps.dataPoint.fill, defaultDataPointColor);\n for (var seriesIndex = 0, len = grouped.length; seriesIndex < len; seriesIndex++) {\n var grouping = grouped[seriesIndex];\n var seriesValues = grouping.values;\n var measureX = ScatterChart.getMeasureValue(indicies.x, seriesValues);\n var measureY = ScatterChart.getMeasureValue(indicies.y, seriesValues);\n var measureSize = ScatterChart.getMeasureValue(indicies.size, seriesValues);\n var seriesColor = void 0;\n if (hasDynamicSeries) {\n seriesColor = colorHelper.getColorForSeriesValue(grouping.objects, dataValues.identityFields, grouping.name);\n }\n else if (!colorByCategory && !categoryObjects) {\n // If we have no Size measure then use a blank query name\n var measureSource = (measureSize != null)\n ? measureSize.source.queryName\n : '';\n seriesColor = colorHelper.getColorForMeasure(null, measureSource);\n }\n var series = {\n identityKey: (grouping && grouping.identity && grouping.identity.key) || \"\",\n dataPoints: [],\n hasSize: !!(measureSize && measureSize.values),\n fill: seriesColor,\n };\n dataPointSeries.push(series);\n for (var categoryIndex = 0, ilen = categoryValues.length; categoryIndex < ilen; categoryIndex++) {\n var categoryValue = categoryValues[categoryIndex];\n // Zero out X and Y if the role doesn't exist, so you still get a set of vertical/horizontal dots\n var xVal = hasX ? visuals.AxisHelper.normalizeNonFiniteNumber(reader.getValue(\"X\", categoryIndex, seriesIndex)) : 0;\n var yVal = hasY ? visuals.AxisHelper.normalizeNonFiniteNumber(reader.getValue(\"Y\", categoryIndex, seriesIndex)) : 0;\n // Undefined size is handled later if we don't have a size role, so this is fine to just be undefined\n var size = visuals.AxisHelper.normalizeNonFiniteNumber(reader.getValue(\"Size\", categoryIndex, seriesIndex));\n // Do not render a dot if X or Y are null\n if (xVal == null || yVal == null)\n continue;\n var color = void 0;\n if (hasDynamicSeries) {\n color = colorHelper.getColorForSeriesValue(grouping.objects, dataValues.identityFields, grouping.name);\n }\n else if (colorByCategory) {\n color = colorHelper.getColorForSeriesValue(categoryObjects && categoryObjects[categoryIndex], dataValues.identityFields, categoryValue);\n }\n else {\n // If we have no Size measure then use a blank query name\n var measureSource = (measureSize != null)\n ? measureSize.source.queryName\n : '';\n color = colorHelper.getColorForMeasure(categoryObjects && categoryObjects[categoryIndex], measureSource);\n }\n var category = !_.isEmpty(categories) ? categories[0] : null;\n var identity = visuals.SelectionIdBuilder.builder()\n .withCategory(category, categoryIndex)\n .withSeries(dataValues, grouping)\n .createSelectionId();\n var tooltipInfo = void 0;\n if (tooltipsEnabled) {\n tooltipInfo = [];\n if (category) {\n tooltipInfo.push({\n displayName: category.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(categoryValue, category.source, formatStringProp),\n });\n }\n if (hasDynamicSeries) {\n // Dynamic series\n if (!category || category.source !== dataValueSource) {\n tooltipInfo.push({\n displayName: dataValueSource.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(grouping.name, dataValueSource, formatStringProp),\n });\n }\n }\n if (measureX && xVal != null) {\n tooltipInfo.push({\n displayName: measureX.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(xVal, measureX.source, formatStringProp),\n });\n }\n if (measureY && yVal != null) {\n tooltipInfo.push({\n displayName: measureY.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(yVal, measureY.source, formatStringProp),\n });\n }\n if (measureSize && measureSize.values[categoryIndex] != null) {\n tooltipInfo.push({\n displayName: measureSize.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(measureSize.values[categoryIndex], measureSize.source, formatStringProp),\n });\n }\n if (gradientValueColumn && gradientValueColumn.values[categoryIndex] != null) {\n tooltipInfo.push({\n displayName: gradientValueColumn.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(gradientValueColumn.values[categoryIndex], gradientValueColumn.source, formatStringProp),\n });\n }\n if (playFrameInfo) {\n tooltipInfo.push({\n displayName: playFrameInfo.column.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(playFrameInfo.label, playFrameInfo.column, formatStringProp),\n });\n }\n }\n var dataPoint = {\n x: xVal,\n y: yVal,\n size: size,\n radius: { sizeMeasure: measureSize, index: categoryIndex },\n fill: color,\n formattedCategory: ScatterChart.createLazyFormattedCategory(categoryFormatter, categories != null ? categoryValue : grouping.name),\n selected: false,\n identity: identity,\n tooltipInfo: tooltipInfo,\n labelFill: labelSettings.labelColor,\n };\n series.dataPoints.push(dataPoint);\n }\n }\n return dataPointSeries;\n };\n ScatterChart.createLazyFormattedCategory = function (formatter, value) {\n return new jsCommon.Lazy(function () { return formatter.format(value); });\n };\n ScatterChart.createSeriesLegend = function (dataValues, colorPalette, categorical, formatString, defaultDataPointColor) {\n var grouped = dataValues.grouped();\n var colorHelper = new visuals.ColorHelper(colorPalette, visuals.scatterChartProps.dataPoint.fill, defaultDataPointColor);\n var legendItems = [];\n for (var i = 0, len = grouped.length; i < len; i++) {\n var grouping = grouped[i];\n var color = colorHelper.getColorForSeriesValue(grouping.objects, dataValues.identityFields, grouping.name);\n legendItems.push({\n color: color,\n icon: visuals.LegendIcon.Circle,\n label: visuals.valueFormatter.format(grouping.name, formatString),\n identity: grouping.identity ? visuals.SelectionId.createWithId(grouping.identity) : visuals.SelectionId.createNull(),\n selected: false\n });\n }\n return legendItems;\n };\n ScatterChart.getBubbleRadius = function (radiusData, sizeRange, viewport) {\n var actualSizeDataRange = null;\n var bubblePixelAreaSizeRange = null;\n var measureSize = radiusData.sizeMeasure;\n if (!measureSize)\n return ScatterChart.BubbleRadius;\n var minSize = sizeRange.min ? sizeRange.min : 0;\n var maxSize = sizeRange.max ? sizeRange.max : 0;\n var min = Math.min(minSize, 0);\n var max = Math.max(maxSize, 0);\n actualSizeDataRange = {\n minRange: min,\n maxRange: max,\n delta: max - min\n };\n bubblePixelAreaSizeRange = ScatterChart.getBubblePixelAreaSizeRange(viewport, ScatterChart.MinSizeRange, ScatterChart.MaxSizeRange);\n if (measureSize.values) {\n var sizeValue = measureSize.values[radiusData.index];\n if (sizeValue != null) {\n return ScatterChart.projectSizeToPixels(sizeValue, actualSizeDataRange, bubblePixelAreaSizeRange) / 2;\n }\n }\n return ScatterChart.BubbleRadius;\n };\n ScatterChart.getMeasureValue = function (measureIndex, seriesValues) {\n if (measureIndex >= 0)\n return seriesValues[measureIndex];\n return null;\n };\n ScatterChart.getMetadata = function (grouped, source) {\n var xIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, 'X');\n var yIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, 'Y');\n var sizeIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, 'Size');\n var xCol;\n var yCol;\n var sizeCol;\n var xAxisLabel = \"\";\n var yAxisLabel = \"\";\n if (grouped && grouped.length) {\n var firstGroup = grouped[0];\n if (xIndex >= 0) {\n xCol = firstGroup.values[xIndex].source;\n xAxisLabel = firstGroup.values[xIndex].source.displayName;\n }\n if (yIndex >= 0) {\n yCol = firstGroup.values[yIndex].source;\n yAxisLabel = firstGroup.values[yIndex].source.displayName;\n }\n if (sizeIndex >= 0) {\n sizeCol = firstGroup.values[sizeIndex].source;\n }\n }\n return {\n idx: {\n x: xIndex,\n y: yIndex,\n size: sizeIndex,\n },\n cols: {\n x: xCol,\n y: yCol,\n size: sizeCol,\n },\n axesLabels: {\n x: xAxisLabel,\n y: yAxisLabel\n }\n };\n };\n /** Create a new viewmodel with default data. */\n ScatterChart.getDefaultData = function () {\n return {\n xCol: undefined,\n yCol: undefined,\n dataPoints: [],\n dataPointSeries: [],\n legendData: { dataPoints: [] },\n axesLabels: { x: '', y: '' },\n sizeRange: [],\n dataLabelsSettings: visuals.dataLabelUtils.getDefaultPointLabelSettings(),\n defaultDataPointColor: null,\n hasDynamicSeries: false,\n };\n };\n ScatterChart.prototype.renderAtFrame = function (data) {\n this.data = data;\n this.cartesianVisualHost.triggerRender(false);\n };\n ScatterChart.prototype.setData = function (dataViews) {\n var _this = this;\n this.data = ScatterChart.getDefaultData();\n if (dataViews.length > 0) {\n var dataView = dataViews[0] || dataViews[1];\n if (dataView) {\n this.categoryAxisProperties = visuals.CartesianHelper.getCategoryAxisProperties(dataView.metadata, true);\n this.valueAxisProperties = visuals.CartesianHelper.getValueAxisProperties(dataView.metadata, true);\n this.dataView = dataView;\n var converterOptions_1 = {\n viewport: this.currentViewport,\n colors: this.colors,\n interactivityService: this.interactivityService,\n categoryAxisProperties: this.categoryAxisProperties,\n valueAxisProperties: this.valueAxisProperties,\n };\n if (visuals.PlayChart.isDataViewPlayable(dataView)) {\n if (!this.playAxis) {\n this.playAxis = new visuals.PlayAxis({\n animator: this.animator,\n interactivityService: this.interactivityService,\n isScrollable: false,\n });\n this.playAxis.init(this.options);\n }\n var playData = this.playAxis.setData(dataView, function (dataView, playFrameInfo) {\n return ScatterChart.converter(dataView, converterOptions_1, playFrameInfo, _this.tooltipsEnabled);\n });\n this.mergeSizeRanges(playData);\n this.data = playData.currentViewModel;\n this.playAxis.setRenderFunction(function (data) { return _this.renderAtFrame(data); });\n }\n else {\n if (this.playAxis) {\n this.playAxis.remove();\n this.playAxis = null;\n }\n if (dataView.categorical && dataView.categorical.values) {\n this.data = ScatterChart.converter(dataView, converterOptions_1, undefined, this.tooltipsEnabled);\n }\n }\n }\n }\n else if (this.playAxis) {\n this.playAxis.remove();\n this.playAxis = null;\n }\n };\n ScatterChart.prototype.mergeSizeRanges = function (playData) {\n if (playData && playData.currentViewModel) {\n var mergedSizeRange = playData.currentViewModel.sizeRange;\n for (var _i = 0, _a = playData.allViewModels; _i < _a.length; _i++) {\n var data_3 = _a[_i];\n var sizeRange = data_3.sizeRange;\n if (sizeRange.min != null)\n mergedSizeRange.min = Math.min(mergedSizeRange.min, sizeRange.min);\n if (sizeRange.max != null)\n mergedSizeRange.max = Math.max(mergedSizeRange.max, sizeRange.max);\n }\n for (var _b = 0, _c = playData.allViewModels; _b < _c.length; _b++) {\n var data_4 = _c[_b];\n data_4.sizeRange = mergedSizeRange;\n }\n }\n };\n ScatterChart.prototype.calculateLegend = function () {\n return this.data && this.data.legendData;\n };\n ScatterChart.prototype.hasLegend = function () {\n return this.data && this.data.hasDynamicSeries;\n };\n ScatterChart.prototype.enumerateObjectInstances = function (enumeration, options) {\n switch (options.objectName) {\n case 'colorByCategory':\n if (this.data) {\n // Color by Legend takes precedent during render. Hide the slice but keep the colorByCategory value unchanged in case they remove the Legend field.\n if (!this.data.hasDynamicSeries) {\n enumeration.pushInstance({\n objectName: 'colorByCategory',\n selector: null,\n properties: {\n show: this.data.colorByCategory,\n },\n });\n }\n }\n break;\n case 'dataPoint':\n // TODO: DataViewMatix (for PlayAxis) doesn't support category- or series-specific properties yet.\n if (!this.playAxis) {\n var categoricalDataView = this.dataView && this.dataView.categorical ? this.dataView.categorical : null;\n if (!visuals.GradientUtils.hasGradientRole(categoricalDataView))\n return this.enumerateDataPoints(enumeration);\n }\n break;\n case 'categoryAxis':\n enumeration.pushInstance({\n selector: null,\n properties: {\n showAxisTitle: !this.categoryAxisProperties || this.categoryAxisProperties[\"showAxisTitle\"] == null ? true : this.categoryAxisProperties[\"showAxisTitle\"]\n },\n objectName: 'categoryAxis'\n });\n break;\n case 'valueAxis':\n enumeration.pushInstance({\n selector: null,\n properties: {\n showAxisTitle: !this.valueAxisProperties || this.valueAxisProperties[\"showAxisTitle\"] == null ? true : this.valueAxisProperties[\"showAxisTitle\"]\n },\n objectName: 'valueAxis'\n });\n break;\n case 'categoryLabels':\n if (this.data)\n visuals.dataLabelUtils.enumerateCategoryLabels(enumeration, this.data.dataLabelsSettings, true);\n else\n visuals.dataLabelUtils.enumerateCategoryLabels(enumeration, null, true);\n break;\n case 'fillPoint':\n // Check if the card should be shown or not based on the existence of size measure\n if (this.hasSizeMeasure())\n return;\n enumeration.pushInstance({\n objectName: 'fillPoint',\n selector: null,\n properties: {\n show: this.data.fillPoint,\n },\n });\n break;\n case 'colorBorder':\n // Check if the card should be shown or not based on the existence of size measure\n if (this.hasSizeMeasure())\n enumeration.pushInstance({\n objectName: 'colorBorder',\n selector: null,\n properties: {\n show: this.data.colorBorder,\n },\n });\n break;\n }\n };\n ScatterChart.prototype.hasSizeMeasure = function () {\n var sizeRange = this.data.sizeRange;\n return sizeRange && sizeRange.min !== undefined;\n };\n ScatterChart.prototype.enumerateDataPoints = function (enumeration) {\n var data = this.data;\n if (!data)\n return;\n var seriesCount = data.dataPoints.length;\n if (!data.hasDynamicSeries) {\n enumeration.pushInstance({\n objectName: 'dataPoint',\n selector: null,\n properties: {\n defaultColor: { solid: { color: data.defaultDataPointColor || this.colors.getColorByIndex(0).value } }\n }\n }).pushInstance({\n objectName: 'dataPoint',\n selector: null,\n properties: {\n showAllDataPoints: !!data.showAllDataPoints\n }\n });\n for (var i = 0; i < seriesCount; i++) {\n var seriesDataPoints = data.dataPoints[i];\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: seriesDataPoints.formattedCategory.getValue(),\n selector: visuals.ColorHelper.normalizeSelector(seriesDataPoints.identity.getSelector(), /*isSingleSeries*/ true),\n properties: {\n fill: { solid: { color: seriesDataPoints.fill } }\n },\n });\n }\n }\n else {\n var legendDataPointLength = data.legendData.dataPoints.length;\n for (var i = 0; i < legendDataPointLength; i++) {\n var series = data.legendData.dataPoints[i];\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: series.label,\n selector: visuals.ColorHelper.normalizeSelector(series.identity.getSelector()),\n properties: {\n fill: { solid: { color: series.color } }\n },\n });\n }\n }\n };\n ScatterChart.prototype.supportsTrendLine = function () {\n var data = this.data;\n if (!data)\n return false;\n return !this.hasSizeMeasure() && data.dataPointSeries.length > 0;\n };\n ScatterChart.getExtents = function (data) {\n var dps = data.dataPoints;\n if (_.isEmpty(dps)) {\n return {\n minY: 0,\n maxY: 0,\n minX: 0,\n maxX: 0,\n };\n }\n return {\n minY: d3.min(dps, function (d) { return d.y; }),\n maxY: d3.max(dps, function (d) { return d.y; }),\n minX: d3.min(dps, function (d) { return d.x; }),\n maxX: d3.max(dps, function (d) { return d.x; }),\n };\n };\n ScatterChart.prototype.calculateAxesProperties = function (options) {\n var data = this.data;\n var viewport = this.currentViewport = options.viewport;\n var margin = options.margin;\n this.currentViewport = viewport;\n this.margin = margin;\n var width = viewport.width - (margin.left + margin.right);\n var height = viewport.height - (margin.top + margin.bottom);\n var extents = {\n minY: 0,\n maxY: 10,\n minX: 0,\n maxX: 10\n };\n if (this.playAxis) {\n extents = this.playAxis.getCartesianExtents(extents, ScatterChart.getExtents);\n this.playAxis.setPlayControlPosition(options.playAxisControlLayout);\n }\n else if (!_.isEmpty(data.dataPoints)) {\n extents = ScatterChart.getExtents(data);\n }\n var xDomain = [extents.minX, extents.maxX];\n var combinedXDomain = visuals.AxisHelper.combineDomain(options.forcedXDomain, xDomain, options.ensureXDomain);\n this.xAxisProperties = visuals.AxisHelper.createAxis({\n pixelSpan: width,\n dataDomain: combinedXDomain,\n metaDataColumn: data.xCol,\n formatString: visuals.valueFormatter.getFormatString(data.xCol, visuals.scatterChartProps.general.formatString),\n outerPadding: 0,\n isScalar: true,\n isVertical: false,\n forcedTickCount: options.forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: true,\n scaleType: options.categoryAxisScaleType,\n axisDisplayUnits: options.categoryAxisDisplayUnits,\n axisPrecision: options.categoryAxisPrecision\n });\n this.xAxisProperties.axis.tickSize(-height, 0);\n this.xAxisProperties.axisLabel = this.data.axesLabels.x;\n var combinedDomain = visuals.AxisHelper.combineDomain(options.forcedYDomain, [extents.minY, extents.maxY], options.ensureYDomain);\n this.yAxisProperties = visuals.AxisHelper.createAxis({\n pixelSpan: height,\n dataDomain: combinedDomain,\n metaDataColumn: data.yCol,\n formatString: visuals.valueFormatter.getFormatString(data.yCol, visuals.scatterChartProps.general.formatString),\n outerPadding: 0,\n isScalar: true,\n isVertical: true,\n forcedTickCount: options.forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false,\n scaleType: options.valueAxisScaleType,\n axisDisplayUnits: options.valueAxisDisplayUnits,\n axisPrecision: options.valueAxisPrecision\n });\n this.yAxisProperties.axisLabel = this.data.axesLabels.y;\n // TODO: these should be passed into the render method.\n return [this.xAxisProperties, this.yAxisProperties];\n };\n ScatterChart.prototype.overrideXScale = function (xProperties) {\n this.xAxisProperties = xProperties;\n };\n ScatterChart.prototype.render = function (suppressAnimations, resizeMode) {\n if (!this.data)\n return;\n var data = this.data;\n var margin = this.margin;\n var viewport = this.currentViewport;\n var hasSelection = this.interactivityService && this.interactivityService.hasSelection();\n var plotArea = {\n width: viewport.width - (margin.left + margin.right),\n height: viewport.height - (margin.top + margin.bottom)\n };\n var duration = visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n if (this.playAxis && this.playAxis.isCurrentlyPlaying() && (this.isMobileChart || duration > 0)) {\n duration = visuals.PlayChart.FrameAnimationDuration;\n }\n var easeType = this.playAxis ? 'linear' : 'cubic-in-out'; // cubic-in-out is the d3.ease default\n var fillMarkers = (!data.sizeRange || !data.sizeRange.min) && data.fillPoint;\n var drawBubbles = this.hasSizeMeasure();\n var suppressDataPointRendering = resizeMode === 1 /* Resizing */ && data.dataPoints && data.dataPoints.length > ScatterChart.NoRenderResizeThreshold;\n var viewModel = {\n data: data,\n drawBubbles: drawBubbles,\n isPlay: !!this.playAxis,\n xAxisProperties: this.xAxisProperties,\n yAxisProperties: this.yAxisProperties,\n viewport: plotArea,\n hasSelection: hasSelection,\n animationDuration: duration,\n animationOptions: this.options.animation,\n fillMarkers: fillMarkers,\n easeType: easeType,\n suppressDataPointRendering: suppressDataPointRendering,\n };\n if (drawBubbles) {\n // Bubbles must be drawn from largest to smallest.\n var sortedData = data.dataPoints.sort(ScatterChart.sortBubbles);\n viewModel.data = powerbi.Prototype.inherit(viewModel.data);\n viewModel.data.dataPoints = sortedData;\n }\n var labelDataPoints = [];\n if (data.dataLabelsSettings && data.dataLabelsSettings.show || data.dataLabelsSettings.showCategory) {\n labelDataPoints = ScatterChartDataLabels.createLabelDataPoints(viewModel);\n }\n var behaviorOptions = this.renderer.render(viewModel, this.interactivityService);\n if (this.isMobileChart) {\n behaviorOptions = {\n data: behaviorOptions.data,\n dataPointsSelection: behaviorOptions.dataPointsSelection,\n eventGroup: behaviorOptions.eventGroup,\n plotContext: behaviorOptions.plotContext,\n host: this.cartesianVisualHost,\n root: this.svg,\n visualInitOptions: this.options,\n xAxisProperties: this.xAxisProperties,\n yAxisProperties: this.yAxisProperties,\n background: d3.select(this.element.get(0)),\n };\n }\n var playRenderResult;\n if (this.playAxis) {\n playRenderResult = this.playAxis.render(suppressAnimations, viewModel, viewport, margin);\n if (this.interactivityService) {\n var playBehaviorOptions = {\n traceLineRenderer: this.renderer.createTraceLineRenderer(playRenderResult.viewModel),\n };\n if (hasSelection) {\n visuals.PlayChart.renderTraceLines(playRenderResult.allDataPoints, playBehaviorOptions.traceLineRenderer, !suppressAnimations);\n }\n behaviorOptions.playOptions = playBehaviorOptions;\n }\n }\n return {\n dataPoints: playRenderResult ? playRenderResult.allDataPoints : data.dataPoints,\n behaviorOptions: behaviorOptions,\n labelDataPoints: labelDataPoints,\n labelsAreNumeric: false,\n };\n };\n ScatterChart.getStrokeFill = function (d, colorBorder) {\n if (d.size != null && colorBorder) {\n var colorRgb = Color.parseColorString(d.fill);\n return Color.hexString(Color.darken(colorRgb, ScatterChart.StrokeDarkenColorValue));\n }\n return d.fill;\n };\n ScatterChart.getBubblePixelAreaSizeRange = function (viewPort, minSizeRange, maxSizeRange) {\n var ratio = 1.0;\n if (viewPort.height > 0 && viewPort.width > 0) {\n var minSize = Math.min(viewPort.height, viewPort.width);\n ratio = (minSize * minSize) / ScatterChart.AreaOf300By300Chart;\n }\n var minRange = Math.round(minSizeRange * ratio);\n var maxRange = Math.round(maxSizeRange * ratio);\n return {\n minRange: minRange,\n maxRange: maxRange,\n delta: maxRange - minRange\n };\n };\n ScatterChart.project = function (value, actualSizeDataRange, bubblePixelAreaSizeRange) {\n if (actualSizeDataRange.delta === 0 || bubblePixelAreaSizeRange.delta === 0) {\n return (ScatterChart.rangeContains(actualSizeDataRange, value)) ? bubblePixelAreaSizeRange.minRange : null;\n }\n var relativeX = (value - actualSizeDataRange.minRange) / actualSizeDataRange.delta;\n return bubblePixelAreaSizeRange.minRange + relativeX * bubblePixelAreaSizeRange.delta;\n };\n ScatterChart.projectSizeToPixels = function (size, actualSizeDataRange, bubblePixelAreaSizeRange) {\n var projectedSize = 0;\n if (actualSizeDataRange) {\n // Project value on the required range of bubble area sizes\n projectedSize = bubblePixelAreaSizeRange.maxRange;\n if (actualSizeDataRange.delta !== 0) {\n var value = Math.min(Math.max(size, actualSizeDataRange.minRange), actualSizeDataRange.maxRange);\n projectedSize = ScatterChart.project(value, actualSizeDataRange, bubblePixelAreaSizeRange);\n }\n projectedSize = Math.sqrt(projectedSize / Math.PI) * 2;\n }\n return Math.round(projectedSize);\n };\n ScatterChart.rangeContains = function (range, value) {\n return range.minRange <= value && value <= range.maxRange;\n };\n ScatterChart.getMarkerFillOpacity = function (hasSize, shouldEnableFill, hasSelection, isSelected) {\n if (hasSize || shouldEnableFill) {\n if (hasSelection && !isSelected) {\n return ScatterChart.DimmedBubbleOpacity;\n }\n return ScatterChart.DefaultBubbleOpacity;\n }\n else {\n return 0;\n }\n };\n ScatterChart.getMarkerStrokeOpacity = function (hasSize, colorBorder, hasSelection, isSelected) {\n if (hasSize && colorBorder) {\n return 1;\n }\n else {\n if (hasSelection && !isSelected) {\n return ScatterChart.DimmedBubbleOpacity;\n }\n return ScatterChart.DefaultBubbleOpacity;\n }\n };\n ScatterChart.getMarkerStrokeFill = function (hasSize, colorBorder, fill) {\n if (hasSize && colorBorder) {\n var colorRgb = Color.parseColorString(fill);\n return Color.hexString(Color.darken(colorRgb, ScatterChart.StrokeDarkenColorValue));\n }\n return fill;\n };\n ScatterChart.getMarkerStyle = function (d, colorBorder, hasSelection, fillMarkers) {\n return {\n 'stroke-opacity': ScatterChart.getMarkerStrokeOpacity(d.size != null, colorBorder, hasSelection, d.selected),\n stroke: ScatterChart.getMarkerStrokeFill(d.size != null, colorBorder, d.fill),\n fill: d.fill,\n 'fill-opacity': ScatterChart.getMarkerFillOpacity(d.size != null, fillMarkers, hasSelection, d.selected),\n };\n };\n ScatterChart.getSeriesStyle = function (hasSize, colorBorder, hasSelection, fillMarkers, fill) {\n return {\n 'stroke-opacity': ScatterChart.getMarkerStrokeOpacity(hasSize, colorBorder, hasSelection, false),\n stroke: ScatterChart.getMarkerStrokeFill(hasSize, colorBorder, fill),\n fill: fill,\n 'fill-opacity': ScatterChart.getMarkerFillOpacity(hasSize, fillMarkers, hasSelection, false),\n };\n };\n ScatterChart.getBubbleOpacity = function (d, hasSelection) {\n if (hasSelection && !d.selected) {\n return ScatterChart.DimmedBubbleOpacity;\n }\n return ScatterChart.DefaultBubbleOpacity;\n };\n ScatterChart.prototype.onClearSelection = function () {\n if (this.interactivityService)\n this.interactivityService.clearSelection();\n };\n ScatterChart.prototype.getSupportedCategoryAxisType = function () {\n return visuals.axisType.scalar;\n };\n ScatterChart.sortBubbles = function (a, b) {\n var diff = (b.radius.sizeMeasure.values[b.radius.index] - a.radius.sizeMeasure.values[a.radius.index]);\n if (diff !== 0)\n return diff;\n // Tie-break equal size bubbles using identity.\n return b.identity.getKey().localeCompare(a.identity.getKey());\n };\n ScatterChart.BubbleRadius = 3 * 2;\n ScatterChart.DefaultBubbleOpacity = 0.85;\n ScatterChart.DimmedBubbleOpacity = 0.4;\n ScatterChart.StrokeDarkenColorValue = 255 * 0.25;\n //label layout settings\n ScatterChart.dataLabelLayoutStartingOffset = 2;\n ScatterChart.dataLabelLayoutOffsetIterationDelta = 6;\n ScatterChart.dataLabelLayoutMaximumOffset = ScatterChart.dataLabelLayoutStartingOffset + (2 * ScatterChart.dataLabelLayoutOffsetIterationDelta);\n // Chart Area and size range values as defined by PV charts\n ScatterChart.AreaOf300By300Chart = 90000;\n ScatterChart.MinSizeRange = 200;\n ScatterChart.MaxSizeRange = 3000;\n ScatterChart.ClassName = 'scatterChart';\n // Animated rendering threshold - if more than this number of data points, rendering is grouped by series and not animated\n ScatterChart.NoAnimationThreshold = 1000;\n // No render resize threshold - if more than this number of data points, rendering is suppressed during resize\n ScatterChart.NoRenderResizeThreshold = 1000;\n return ScatterChart;\n }());\n visuals.ScatterChart = ScatterChart;\n var SvgRenderer = (function () {\n function SvgRenderer() {\n }\n SvgRenderer.prototype.init = function (element, labelsContext, isMobileChart, tooltipsEnabled) {\n this.mainGraphicsG = element.append('g')\n .classed(SvgRenderer.MainGraphicsContext.class, true);\n this.isMobileChart = isMobileChart;\n if (isMobileChart) {\n // The backgroundRect catch user interactions when clicking/dragging on the background of the chart.\n this.mainGraphicsBackgroundRect = this.mainGraphicsG\n .append(\"rect\")\n .classed(\"backgroundRect\", true)\n .attr({ width: \"100%\", height: \"100%\" });\n }\n this.mainGraphicsContext = this.mainGraphicsG.append('svg');\n this.labelGraphicsContext = labelsContext;\n this.tooltipsEnabled = tooltipsEnabled;\n // common rendering attributes\n this.mainGraphicsContext.attr('stroke-width', \"1\");\n };\n SvgRenderer.prototype.render = function (viewModel, interactivityService) {\n var viewport = viewModel.viewport;\n this.mainGraphicsContext\n .attr({\n 'width': viewport.width,\n 'height': viewport.height\n });\n var scatterMarkers;\n if (viewModel.suppressDataPointRendering) {\n scatterMarkers = this.removeScatterMarkers();\n }\n else if (viewModel.animationDuration > 0 && viewModel.data.dataPoints.length <= ScatterChart.NoAnimationThreshold) {\n scatterMarkers = this.drawScatterMarkers(viewModel);\n }\n else {\n scatterMarkers = this.drawScatterMarkersNoAnimation(viewModel, viewModel.drawBubbles);\n }\n if (viewModel.drawBubbles)\n scatterMarkers.order();\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(this.mainGraphicsContext, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(viewModel.animationOptions);\n return {\n dataPointsSelection: scatterMarkers,\n eventGroup: this.mainGraphicsG,\n data: viewModel.data,\n plotContext: this.mainGraphicsContext,\n };\n };\n SvgRenderer.prototype.createTraceLineRenderer = function (viewModel) {\n return new ScatterTraceLineRenderer(viewModel, this.mainGraphicsContext, this.tooltipsEnabled);\n };\n SvgRenderer.prototype.removeScatterMarkers = function () {\n this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector)\n .remove();\n return this.mainGraphicsContext.selectAll(SvgRenderer.DotClass.selector);\n };\n SvgRenderer.prototype.drawScatterMarkers = function (viewModel) {\n var data = viewModel.data;\n var xScale = viewModel.xAxisProperties.scale;\n var yScale = viewModel.yAxisProperties.scale;\n // put all the markers in a single fake group. keeps the dom structure consistent between\n // drawScatterMarkers and drawScatterMarkersGrouped.\n var fakeDataPointSeries = [\n {\n identityKey: \"\",\n dataPoints: data.dataPoints,\n },\n ];\n var fakeSeriesGroups = this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector)\n .data(fakeDataPointSeries, function (s) { return s.identityKey; });\n fakeSeriesGroups.enter()\n .append('g')\n .classed(SvgRenderer.ScatterMarkerSeriesGroup.class, true);\n // groups for real series may have been inserted by drawScatterMarkersGrouped, remove them\n fakeSeriesGroups.exit()\n .remove();\n var markers = fakeSeriesGroups.selectAll(SvgRenderer.DotClass.selector)\n .data(function (s) { return s.dataPoints; }, function (d) { return d.identity.getKey(); });\n markers.enter().append('circle')\n .classed(SvgRenderer.DotClass.class, true)\n .style('opacity', 0) // Fade new bubbles into visibility\n .attr('r', 0);\n markers\n .style({\n 'stroke-opacity': function (d) { return ScatterChart.getMarkerStrokeOpacity(d.size != null, data.colorBorder, viewModel.hasSelection, d.selected); },\n 'stroke': function (d) { return ScatterChart.getStrokeFill(d, data.colorBorder); },\n 'fill': function (d) { return d.fill; },\n 'fill-opacity': function (d) { return ScatterChart.getMarkerFillOpacity(d.size != null, viewModel.fillMarkers, viewModel.hasSelection, d.selected); },\n })\n .transition()\n .ease(viewModel.easeType)\n .duration(viewModel.animationDuration)\n .style('opacity', 1) // Fill-opacity is used for selected / highlight changes, opacity is for enter/exit fadein/fadeout\n .attr({\n r: function (d) { return ScatterChart.getBubbleRadius(d.radius, data.sizeRange, viewModel.viewport); },\n cx: function (d) { return xScale(d.x); },\n cy: function (d) { return yScale(d.y); },\n });\n markers\n .exit()\n .transition()\n .ease(viewModel.easeType)\n .duration(viewModel.animationDuration)\n .style('opacity', 0) // Fade out bubbles that are removed\n .attr('r', 0)\n .remove();\n return markers;\n };\n SvgRenderer.prototype.drawScatterMarkersNoAnimation = function (viewModel, isBubble) {\n var data = viewModel.data;\n var xScale = viewModel.xAxisProperties.scale;\n var yScale = viewModel.yAxisProperties.scale;\n var seriesGroups;\n if (isBubble) {\n var fakeDataPointSeries = [\n {\n identityKey: \"\",\n dataPoints: data.dataPoints,\n },\n ];\n seriesGroups = this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector)\n .data(fakeDataPointSeries, function (s) { return s.identityKey; });\n }\n else {\n seriesGroups = this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector).data(data.dataPointSeries, function (s) { return s.identityKey; });\n }\n // a group for each series\n seriesGroups.enter()\n .append('g')\n .classed(SvgRenderer.ScatterMarkerSeriesGroup.class, true);\n // this will also remove the fake group that might have been created by drawScatterMarkers\n seriesGroups.exit()\n .remove();\n seriesGroups\n .each(function (s) {\n var seriesStyle = ScatterChart.getSeriesStyle(s.hasSize, data.colorBorder, viewModel.hasSelection, viewModel.fillMarkers, s.fill);\n var g = d3.select(this);\n SvgRenderer.applyStyle(this, seriesStyle);\n var markers = g.selectAll(SvgRenderer.DotClass.selector).data(s.dataPoints, function (m) { return m.identity.getKey(); });\n markers.enter()\n .append('circle')\n .classed(SvgRenderer.DotClass.class, true);\n markers.exit()\n .remove();\n markers.each(function (d) {\n var style = ScatterChart.getMarkerStyle(d, data.colorBorder, viewModel.hasSelection, viewModel.fillMarkers);\n SvgRenderer.styleException(style, seriesStyle);\n SvgRenderer.applyStyle(this, style);\n });\n markers.attr({\n r: function (d) { return ScatterChart.getBubbleRadius(d.radius, data.sizeRange, viewModel.viewport); },\n cx: function (d) { return xScale(d.x); },\n cy: function (d) { return yScale(d.y); },\n });\n });\n return this.mainGraphicsContext.selectAll(SvgRenderer.DotClass.selector);\n };\n SvgRenderer.styleException = function (elementStyle, seriesStyle) {\n if (seriesStyle) {\n for (var name_1 in elementStyle) {\n if (elementStyle[name_1] === seriesStyle[name_1]) {\n elementStyle[name_1] = null;\n }\n }\n }\n };\n SvgRenderer.applyStyle = function (element, style) {\n for (var name_2 in style) {\n var elementValue = element.style[name_2];\n var styleValue = style[name_2];\n if (styleValue == null) {\n if (elementValue === \"\")\n continue;\n }\n else {\n styleValue = styleValue.toString();\n if (styleValue === elementValue)\n continue;\n }\n element.style[name_2] = styleValue;\n }\n };\n SvgRenderer.DotClass = createClassAndSelector('dot');\n SvgRenderer.MainGraphicsContext = createClassAndSelector('mainGraphicsContext');\n SvgRenderer.ScatterMarkerSeriesGroup = createClassAndSelector('scatterMarkerSeriesGroup');\n return SvgRenderer;\n }());\n var ScatterChartDataLabels;\n (function (ScatterChartDataLabels) {\n var validLabelPositions = [\n 2 /* Below */,\n 1 /* Above */,\n 8 /* Right */,\n 4 /* Left */,\n 16 /* BelowRight */,\n 32 /* BelowLeft */,\n 64 /* AboveRight */,\n 128 /* AboveLeft */\n ];\n function createLabelDataPoints(viewModel) {\n var xScale = viewModel.xAxisProperties.scale;\n var yScale = viewModel.yAxisProperties.scale;\n var sizeRange = viewModel.data.sizeRange;\n var labelDataPoints = [];\n var dataPoints = viewModel.data.dataPoints;\n var labelSettings = viewModel.data.dataLabelsSettings;\n var preferredLabelsKeys = getPreferredLabelsKeys(viewModel);\n for (var _i = 0, dataPoints_5 = dataPoints; _i < dataPoints_5.length; _i++) {\n var dataPoint = dataPoints_5[_i];\n var text = dataPoint.formattedCategory.getValue();\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties);\n labelDataPoints.push({\n isPreferred: preferredLabelsKeys ? isLabelPreferred(dataPoint.identity.getKey(), preferredLabelsKeys) : false,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : visuals.NewDataLabelUtils.defaultLabelColor,\n insideFill: visuals.NewDataLabelUtils.defaultInsideLabelColor,\n parentType: 0 /* Point */,\n parentShape: {\n point: {\n x: xScale(dataPoint.x),\n y: yScale(dataPoint.y),\n },\n radius: ScatterChart.getBubbleRadius(dataPoint.radius, sizeRange, viewModel.viewport),\n validPositions: validLabelPositions,\n },\n identity: dataPoint.identity,\n fontSize: labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt,\n });\n }\n return labelDataPoints;\n }\n ScatterChartDataLabels.createLabelDataPoints = createLabelDataPoints;\n function getPreferredLabelsKeys(viewModel) {\n var width = viewModel.viewport.width;\n var height = viewModel.viewport.height;\n var visualCenter = new visuals.Point(width / 2, height / 2);\n var quadrantsCenters = getQuadrantsCenters(width, height);\n return getCandidateLabels(visualCenter, quadrantsCenters, viewModel);\n }\n function getQuadrantsCenters(visualWidth, visualHeight) {\n var quadrantsCenters = [];\n var quarterWidth = visualWidth / 4;\n var quarterHeight = visualHeight / 4;\n quadrantsCenters.push(new visuals.Point(quarterWidth, quarterHeight));\n quadrantsCenters.push(new visuals.Point(quarterWidth * 3, quarterHeight));\n quadrantsCenters.push(new visuals.Point(quarterWidth, quarterHeight * 3));\n quadrantsCenters.push(new visuals.Point(quarterWidth * 3, quarterHeight * 3));\n return quadrantsCenters;\n }\n function getCandidateLabels(visualCenter, quadrantsCenters, viewModel) {\n var minDistances = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE];\n var ids = [];\n var xScale = viewModel.xAxisProperties.scale;\n var yScale = viewModel.yAxisProperties.scale;\n var distance;\n for (var _i = 0, _a = viewModel.data.dataPoints; _i < _a.length; _i++) {\n var dp = _a[_i];\n var x = xScale(dp.x);\n var y = yScale(dp.y);\n var quadrantNumber = getPointQuadrantNumber(x, y, visualCenter);\n if (viewModel.drawBubbles) {\n // Since the array is sorted by size the preferred label will be the first label in the quadrant\n if (!ids[quadrantNumber])\n ids[quadrantNumber] = dp.identity;\n }\n else {\n distance = getDistanceBetweenPoints(quadrantsCenters[quadrantNumber].x, quadrantsCenters[quadrantNumber].y, x, y);\n if (distance < minDistances[quadrantNumber]) {\n ids[quadrantNumber] = dp.identity;\n minDistances[quadrantNumber] = distance;\n }\n }\n }\n var preferredLabelsKeys = [];\n for (var _b = 0, ids_1 = ids; _b < ids_1.length; _b++) {\n var id = ids_1[_b];\n if (id)\n preferredLabelsKeys.push(id.getKey());\n }\n return preferredLabelsKeys;\n }\n function getPointQuadrantNumber(x, y, centerPoint) {\n if (x > centerPoint.x && y <= centerPoint.y)\n return 0 /* First */;\n if (x <= centerPoint.x && y <= centerPoint.y)\n return 1 /* Second */;\n if (x <= centerPoint.x && y > centerPoint.y)\n return 2 /* Third */;\n else\n return 3 /* Fourth */;\n }\n function getDistanceBetweenPoints(x1, y1, x2, y2) {\n return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));\n }\n function isLabelPreferred(key, preferredLabelsKeys) {\n for (var _i = 0, preferredLabelsKeys_1 = preferredLabelsKeys; _i < preferredLabelsKeys_1.length; _i++) {\n var preferredLabel = preferredLabelsKeys_1[_i];\n if (key.localeCompare(preferredLabel) === 0)\n return true;\n }\n return false;\n }\n })(ScatterChartDataLabels || (ScatterChartDataLabels = {}));\n var ScatterTraceLineRenderer = (function () {\n function ScatterTraceLineRenderer(viewModel, element, tooltipsEnabled) {\n this.viewModel = viewModel;\n this.element = element;\n this.tooltipsEnabled = tooltipsEnabled;\n }\n ScatterTraceLineRenderer.prototype.remove = function () {\n this.element.selectAll(ScatterTraceLineRenderer.TraceLine.selector).remove();\n this.element.selectAll(ScatterTraceLineRenderer.TraceBubble.selector).remove();\n };\n ScatterTraceLineRenderer.prototype.render = function (selectedPoints, shouldAnimate) {\n var viewModel = this.viewModel;\n var scatterViewModel = viewModel.viewModel;\n var seriesPoints = [];\n if (!_.isEmpty(selectedPoints) && !scatterViewModel.suppressDataPointRendering) {\n var currentFrameIndex_1 = viewModel.data.currentFrameIndex;\n // filter to the selected identity, only up to and including the current frame. Add frames during play.\n var hasBubbleAtCurrentFrame = [];\n for (var selectedIndex = 0, selectedLen = selectedPoints.length; selectedIndex < selectedLen; selectedIndex++) {\n seriesPoints[selectedIndex] = [];\n hasBubbleAtCurrentFrame[selectedIndex] = false;\n for (var frameIndex = 0, frameLen = viewModel.data.allViewModels.length; frameIndex < frameLen && frameIndex <= currentFrameIndex_1; frameIndex++) {\n var value = _.find(viewModel.data.allViewModels[frameIndex].dataPoints, function (value, index) {\n return value.identity.getKey() === selectedPoints[selectedIndex].identity.getKey();\n });\n if (value != null) {\n // TODO: Revisit this, we should be able to keep track without modifying Scatter's data points.\n value.frameIndex = frameIndex;\n seriesPoints[selectedIndex].push(value);\n if (frameIndex === currentFrameIndex_1)\n hasBubbleAtCurrentFrame[selectedIndex] = true;\n }\n }\n }\n var xScale_1 = scatterViewModel.xAxisProperties.scale;\n var yScale_1 = scatterViewModel.yAxisProperties.scale;\n var line_1 = d3.svg.line()\n .x(function (d) { return xScale_1(d.x); })\n .y(function (d) { return yScale_1(d.y); })\n .defined(function (d) { return d.x !== null && d.y !== null; });\n // Render Lines\n var traceLines = this.element.selectAll(ScatterTraceLineRenderer.TraceLine.selector)\n .data(selectedPoints, function (sp) { return sp.identity.getKey(); });\n traceLines.enter()\n .append('path')\n .classed(ScatterTraceLineRenderer.TraceLine.class, true);\n // prepare array of new/previous lengths\n // NOTE: can't use lambda because we need the \"this\" context to be the DOM Element associated with the .each()\n var previousLengths_1 = [], newLengths_1 = [];\n var reverse_1 = false;\n traceLines.each(function (d, i) {\n var existingPath = this;\n var previousLength = existingPath.hasAttribute('d') ? existingPath.getTotalLength() : 0;\n previousLengths_1.push(previousLength);\n // create offline SVG for new path measurement\n var tempSvgPath = $('<svg><path></path></svg>');\n var tempPath = $('path', tempSvgPath);\n tempPath.attr('d', line_1(seriesPoints[i]));\n var newLength = seriesPoints[i].length > 0 ? tempPath.get()[0].getTotalLength() : 0;\n newLengths_1.push(newLength);\n reverse_1 = reverse_1 || (newLength < previousLength);\n });\n // animate using stroke-dash* trick\n if (!reverse_1) {\n // growing line\n traceLines\n .style('stroke', function (d) { return ScatterChart.getStrokeFill(d, true); })\n .attr({\n 'd': function (d, i) {\n return line_1(seriesPoints[i]);\n },\n 'stroke-dasharray': function (d, i) { return newLengths_1[i] + \" \" + newLengths_1[i]; },\n 'stroke-dashoffset': function (d, i) { return newLengths_1[i] - previousLengths_1[i]; },\n });\n if (shouldAnimate) {\n traceLines\n .transition()\n .ease('linear')\n .duration(visuals.PlayChart.FrameAnimationDuration)\n .attr('stroke-dashoffset', 0);\n }\n else {\n traceLines.attr('stroke-dashoffset', 0);\n }\n }\n else {\n // shrinking line\n if (shouldAnimate) {\n traceLines\n .transition()\n .ease('linear')\n .duration(visuals.PlayChart.FrameAnimationDuration)\n .attr('stroke-dashoffset', function (d, i) { return previousLengths_1[i] - newLengths_1[i]; })\n .transition()\n .ease('linear')\n .duration(1) // animate the shrink first, then update with new line properties\n .delay(visuals.PlayChart.FrameAnimationDuration)\n .style('stroke', function (d) { return ScatterChart.getStrokeFill(d, true); })\n .attr({\n 'd': function (d, i) {\n return line_1(seriesPoints[i]);\n },\n 'stroke-dasharray': function (d, i) { return newLengths_1[i] + \" \" + newLengths_1[i]; },\n 'stroke-dashoffset': 0,\n });\n }\n else {\n traceLines\n .style('stroke', function (d) { return ScatterChart.getStrokeFill(d, true); })\n .attr({\n 'd': function (d, i) {\n return line_1(seriesPoints[i]);\n },\n 'stroke-dasharray': function (d, i) { return newLengths_1[i] + \" \" + newLengths_1[i]; },\n 'stroke-dashoffset': 0,\n });\n }\n }\n traceLines.exit()\n .remove();\n // Render circles\n var circlePoints = [];\n for (var selectedIndex_1 = 0; selectedIndex_1 < seriesPoints.length; selectedIndex_1++) {\n var points = seriesPoints[selectedIndex_1];\n // slice to length-1 because we draw lines to the current bubble but we don't need to draw the current frame's bubble\n var newPoints = hasBubbleAtCurrentFrame[selectedIndex_1] ? points.slice(0, points.length - 1) : points;\n circlePoints = circlePoints.concat(newPoints);\n }\n var circles = this.element.selectAll(ScatterTraceLineRenderer.TraceBubble.selector)\n .data(circlePoints, function (d) { return d.identity.getKey() + d.x + d.y + d.size; });\n circles.enter()\n .append('circle')\n .style('opacity', 0) //fade new bubbles into visibility\n .classed(ScatterTraceLineRenderer.TraceBubble.class, true);\n circles\n .attr('cx', function (d) { return xScale_1(d.x); })\n .attr('cy', function (d) { return yScale_1(d.y); })\n .attr('r', function (d) { return ScatterChart.getBubbleRadius(d.radius, viewModel.data.currentViewModel.sizeRange, viewModel.viewport); })\n .style({\n 'stroke-opacity': function (d) { return ScatterChart.getBubbleOpacity(d, true); },\n 'stroke': function (d) { return ScatterChart.getStrokeFill(d, viewModel.data.currentViewModel.colorBorder); },\n 'fill': function (d) { return d.fill; },\n // vary the opacity along the traceline from 0.20 to 0.80, with 0.85 left for the circle already drawn by scatterChart\n 'fill-opacity': function (d) { return d.size != null ? 0.20 + (d.frameIndex / currentFrameIndex_1) * 0.60 : 0; },\n })\n .transition()\n .ease('linear')\n .duration(visuals.PlayChart.FrameAnimationDuration)\n .style('opacity', 1);\n circles.exit()\n .transition()\n .ease('linear')\n .duration(visuals.PlayChart.FrameAnimationDuration)\n .style('opacity', 0) // fade exiting bubbles out\n .remove();\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(circles, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n }\n // sort the z-order, smallest size on top\n circles.sort(function (d1, d2) { return d2.size - d1.size; });\n }\n else {\n this.remove();\n }\n };\n ScatterTraceLineRenderer.TraceLine = createClassAndSelector('traceLine');\n ScatterTraceLineRenderer.TraceBubble = createClassAndSelector('traceBubble');\n return ScatterTraceLineRenderer;\n }());\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var createDataViewScopeIdentity = powerbi.data.createDataViewScopeIdentity;\n var DataViewConcatenateCategoricalColumns = powerbi.data.DataViewConcatenateCategoricalColumns;\n var DataViewMatrixUtils = powerbi.data.utils.DataViewMatrixUtils;\n var SQExprBuilder = powerbi.data.SQExprBuilder;\n ;\n ;\n var PlayAxis = (function () {\n function PlayAxis(options) {\n if (options) {\n this.interactivityService = options.interactivityService;\n }\n }\n PlayAxis.prototype.init = function (options) {\n var _this = this;\n debug.assertValue(options, 'options');\n this.element = options.element;\n this.svg = options.svg;\n this.host = options.host;\n this.isMobileChart = options.interactivity && options.interactivity.isInteractiveLegend;\n if (this.interactivityService) {\n this.playControl = new PlayControl(this.element, function (frameIndex) { return _this.moveToFrameAndRender(frameIndex); }, this.isMobileChart);\n this.playControl.onPlay(function () { return _this.play(); });\n }\n };\n PlayAxis.prototype.setData = function (dataView, visualConverter) {\n if (dataView) {\n if (this.ridiculousFlagForPersistProperties && dataView.metadata) {\n // BUG FIX: customer feedback has been strong that we should always default to show the last frame.\n // This is essential for dashboard tiles to refresh properly.\n // Only copy frameIndex since it is the only property using persistProperties\n //let objectProps = getObjectProperties(dataView.metadata);\n //playData.currentFrameIndex = objectProps.currentFrameIndex;\n // Turn off the flag that was set by our persistProperties call\n this.ridiculousFlagForPersistProperties = false;\n return this.playData;\n }\n else if (dataView.matrix || dataView.categorical) {\n this.playData = PlayChart.converter(dataView, visualConverter);\n }\n else {\n this.playData = PlayChart.getDefaultPlayData();\n }\n }\n else {\n this.playData = PlayChart.getDefaultPlayData();\n }\n // Next render should be a full one.\n this.lastViewport = undefined;\n return this.playData;\n };\n PlayAxis.prototype.render = function (suppressAnimations, viewModel, viewport, margin) {\n var playData = this.playData;\n var resized = !this.lastViewport || (this.lastViewport.height !== viewport.height || this.lastViewport.width !== viewport.width);\n this.lastViewport = viewport;\n if (resized)\n this.stop();\n if (!playData)\n return;\n var playViewModel = {\n data: this.playData,\n viewModel: viewModel,\n viewport: viewport,\n };\n var hasSelection = false;\n if (this.interactivityService) {\n var data_5 = playData.currentViewModel;\n this.interactivityService.applySelectionStateToData(data_5.dataPoints);\n hasSelection = this.interactivityService.hasSelection();\n }\n this.updateCallout(viewport, margin);\n if (this.playControl && resized) {\n this.playControl.rebuild(playData, viewport);\n }\n var allDataPoints = playData.allViewModels.map(function (vm) { return vm.dataPoints; });\n var flatAllDataPoints = _.flatten(allDataPoints);\n // NOTE: Return data points to keep track of current selected bubble even if it drops out for a few frames\n return {\n allDataPoints: flatAllDataPoints,\n viewModel: playViewModel,\n };\n };\n PlayAxis.prototype.updateCallout = function (viewport, margin) {\n var playData = this.playData;\n var frameData = playData.frameData;\n var currentFrameIndex = playData.currentFrameIndex;\n var height = viewport.height;\n var plotAreaHeight = height - margin.top - margin.bottom;\n var width = viewport.width;\n var plotAreaWidth = width - margin.left - margin.right;\n var calloutDimension = Math.min(height, width * 1.3); //1.3 to compensate for tall, narrow-width viewport\n var fontSize = Math.max(12, Math.round(calloutDimension / 7));\n fontSize = Math.min(fontSize, 70);\n var textProperties = {\n fontSize: jsCommon.PixelConverter.toString(fontSize),\n text: frameData[currentFrameIndex].text || \"\",\n fontFamily: \"wf_segoe-ui_normal\",\n };\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(textProperties) - powerbi.TextMeasurementService.estimateSvgTextBaselineDelta(textProperties);\n var calloutData = [];\n if (currentFrameIndex < frameData.length && currentFrameIndex >= 0 && textHeight < plotAreaHeight) {\n var maxTextWidth = plotAreaWidth - (2 * PlayAxis.calloutOffsetMultiplier * textHeight);\n var calloutText = powerbi.TextMeasurementService.getTailoredTextOrDefault(textProperties, maxTextWidth);\n calloutData = [calloutText];\n }\n var callout = this.svg.selectAll(PlayAxis.PlayCallout.selector).data(calloutData);\n callout.enter()\n .append('text')\n .classed(PlayAxis.PlayCallout.class, true);\n callout\n .text(function (d) { return d; })\n .attr({\n x: plotAreaWidth - PlayAxis.calloutOffsetMultiplier * textHeight,\n y: function () { return textHeight; },\n })\n .style({\n 'font-size': fontSize + 'px',\n 'text-anchor': 'end',\n });\n callout.exit().remove();\n };\n PlayAxis.prototype.play = function () {\n var playData = this.playData;\n if (this.isPlaying) {\n this.stop();\n }\n else if (this.playControl) {\n this.isPlaying = true;\n this.playControl.play();\n var indexToShow = Math.round(this.playControl.getCurrentIndex());\n if (indexToShow >= playData.allViewModels.length - 1) {\n playData.currentFrameIndex = -1;\n }\n else {\n playData.currentFrameIndex = indexToShow - 1;\n }\n this.playNextFrame(playData);\n }\n };\n PlayAxis.prototype.playNextFrame = function (playData, startFrame, endFrame) {\n var _this = this;\n if (!this.isPlaying) {\n this.stop();\n return;\n }\n var nextFrame = playData.currentFrameIndex + 1;\n if (startFrame != null && endFrame != null) {\n nextFrame = Math.abs(endFrame - startFrame + 1);\n startFrame = nextFrame;\n }\n if (nextFrame < playData.allViewModels.length && nextFrame > -1) {\n playData.currentFrameIndex = nextFrame;\n playData.currentViewModel = playData.allViewModels[nextFrame];\n this.renderDelegate(playData.currentViewModel);\n this.playControl.setFrame(nextFrame);\n if (nextFrame < playData.allViewModels.length) {\n window.setTimeout(function () {\n _this.playNextFrame(playData, startFrame, endFrame);\n }, PlayChart.FrameStepDuration);\n }\n }\n else {\n this.stop();\n }\n };\n PlayAxis.prototype.stop = function () {\n if (this.playControl)\n this.playControl.pause();\n this.isPlaying = false;\n };\n PlayAxis.prototype.remove = function () {\n if (this.playControl)\n this.playControl.remove();\n d3.selectAll(PlayAxis.PlayCallout.selector).remove();\n // TODO: remove any tracelines\n };\n PlayAxis.prototype.setRenderFunction = function (fn) {\n this.renderDelegate = fn;\n };\n PlayAxis.prototype.getCartesianExtents = function (existingExtents, getExtents) {\n if (this.playData && this.playData.allViewModels && this.playData.allViewModels.length > 0) {\n return PlayChart.getMinMaxForAllFrames(this.playData, getExtents);\n }\n return existingExtents;\n };\n PlayAxis.prototype.setPlayControlPosition = function (playControlLayout) {\n if (this.playControl) {\n var container = this.playControl.getContainer();\n container.css('left', playControlLayout.left ? playControlLayout.left + 'px' : '');\n container.css('top', playControlLayout.top ? playControlLayout.top + 'px' : '');\n }\n };\n PlayAxis.prototype.moveToFrameAndRender = function (frameIndex) {\n var playData = this.playData;\n this.isPlaying = false;\n if (playData && frameIndex >= 0 && frameIndex < playData.allViewModels.length && frameIndex !== playData.currentFrameIndex) {\n playData.currentFrameIndex = frameIndex;\n var data_6 = playData.allViewModels[frameIndex];\n playData.currentViewModel = data_6;\n this.renderDelegate(data_6);\n }\n };\n PlayAxis.prototype.isCurrentlyPlaying = function () {\n return this.isPlaying;\n };\n PlayAxis.PlayCallout = createClassAndSelector('play-callout');\n PlayAxis.calloutOffsetMultiplier = 0.3;\n return PlayAxis;\n }());\n visuals.PlayAxis = PlayAxis;\n var PlayControl = (function () {\n function PlayControl(element, renderDelegate, isMobileChart) {\n this.isMobileChart = isMobileChart;\n this.createSliderDOM(element);\n this.renderDelegate = renderDelegate;\n }\n PlayControl.prototype.getContainer = function () {\n return this.playAxisContainer;\n };\n PlayControl.prototype.remove = function () {\n if (this.playAxisContainer)\n this.playAxisContainer.remove();\n };\n PlayControl.prototype.pause = function () {\n this.playButton.removeClass('pause').addClass('play');\n };\n PlayControl.prototype.play = function () {\n this.playButton.removeClass('play').addClass('pause');\n };\n PlayControl.prototype.getCurrentIndex = function () {\n // TODO: round() necessary?\n return Math.round(this.noUiSlider.get());\n };\n PlayControl.prototype.onPlay = function (handler) {\n this.playButtonCircle.off('click');\n this.playButtonCircle.on('click', handler);\n };\n PlayControl.prototype.setFrame = function (frameIndex) {\n this.noUiSlider.set([frameIndex]);\n };\n ;\n PlayControl.prototype.rebuild = function (playData, viewport) {\n var _this = this;\n var slider = this.slider;\n // re-create the slider\n if (this.noUiSlider)\n this.noUiSlider.destroy();\n var labelData = playData.labelData;\n var sliderSize = PlayControl.calucalateSliderSize(labelData, viewport.width);\n var container = this.getContainer();\n if (sliderSize.marginLeft > PlayControl.SliderMarginLeft) {\n container.css(\"padding-left\", sliderSize.marginLeft - PlayControl.SliderMarginLeft + \"px\");\n container.css(\"box-sizing\", \"border-box\");\n }\n var skipStep = this.updateSliderControl(playData, sliderSize.width);\n var width = PlayControl.adjustWidthRegardingLastItem(labelData, skipStep, sliderSize.width);\n this.slider.css('width', width + 'px');\n this.noUiSlider.on('slide', function () {\n var indexToShow = _this.getCurrentIndex();\n _this.renderDelegate(indexToShow);\n });\n var nextLabelIndex = 0;\n // update the width and margin-left to center up each label\n $('.noUi-value', slider).each(function (idx, elem) {\n var actualWidth = labelData.labelInfo[nextLabelIndex].labelWidth;\n $(elem).width(actualWidth);\n $(elem).css('margin-left', -actualWidth / 2 + 'px');\n nextLabelIndex += skipStep;\n });\n };\n /**\n * Updates slider control regarding new data.\n * @param playData {PlayChartData<T>} Data for the slider.\n * @param sliderWidth {number} Slider width.\n * @returns {number} skip mode for the slider.\n */\n PlayControl.prototype.updateSliderControl = function (playData, sliderWidth) {\n var labelData = playData.labelData;\n var sliderElement = this.slider.get(0);\n var numFrames = playData.frameData.length;\n var options = {\n start: numFrames === 0 ? 0 : playData.currentFrameIndex,\n step: 1,\n range: {\n min: 0,\n max: numFrames === 0 ? 0 : numFrames - 1\n }\n };\n var pipOptions = null;\n var skipMode = 0;\n if (numFrames > 0) {\n var filterPipLabels = PlayControl.createPipsFilterFn(playData, sliderWidth, labelData);\n skipMode = filterPipLabels.skipStep;\n pipOptions = {\n mode: 'steps',\n density: Math.ceil(100 / numFrames),\n format: {\n to: function (index) { return playData.frameData[index].escapedText; },\n from: function (value) { return playData.frameData.indexOf(value); },\n },\n filter: filterPipLabels.filter,\n };\n }\n options.pips = pipOptions;\n noUiSlider.create(sliderElement, options);\n this.noUiSlider = sliderElement.noUiSlider;\n return skipMode;\n };\n PlayControl.createPipsFilterFn = function (playData, sliderWidth, labelData) {\n var maxLabelWidth = _.max(_.map(labelData.labelInfo, function (l) { return l.labelWidth; }));\n var pipSize = 1; //0=hide, 1=large, 2=small\n var skipMode = 1;\n var maxAllowedLabelWidth = playData.frameData.length > 1 ? sliderWidth / (playData.frameData.length - 1) : sliderWidth;\n var widthRatio = maxLabelWidth / maxAllowedLabelWidth;\n if (widthRatio > 1.25) {\n skipMode = Math.ceil(widthRatio);\n pipSize = 2;\n }\n else if (widthRatio > 1.0 || labelData.anyWordBreaks) {\n // wordbreak line wrapping is automatic, and we don't reserve enough space to show two lines of text with the larger font\n pipSize = 2;\n }\n var filterPipLabels = function (index, type) {\n // noUiSlider will word break / wrap to new lines, so max width is the max word length\n if (index % skipMode === 0) {\n return pipSize;\n }\n return 0; //hide\n };\n return { filter: filterPipLabels, skipStep: skipMode };\n };\n /**\n * Adjusts width regarding the last visible label size.\n * @param labelData label data for chart.\n * @param skipMode skip factor.\n * @param sliderWidth current width of slider.\n */\n PlayControl.adjustWidthRegardingLastItem = function (labelData, skipMode, sliderWidth) {\n var labelLenth = labelData.labelInfo.length;\n var lastVisibleItemIndex = Math.floor((labelLenth - 1) / skipMode) * skipMode;\n var distanceToEnd = sliderWidth + PlayControl.SliderMarginRight - (sliderWidth / labelLenth * (lastVisibleItemIndex + 1));\n var lastItemWidth = labelData.labelInfo[lastVisibleItemIndex].labelWidth;\n var requiredWidth = lastItemWidth / 2 - distanceToEnd;\n if (requiredWidth > 0) {\n var maxMargin = PlayControl.SliderMaxMargin - PlayControl.SliderMarginRight;\n requiredWidth = requiredWidth > maxMargin ? maxMargin : requiredWidth;\n return sliderWidth - requiredWidth;\n }\n return sliderWidth;\n };\n PlayControl.prototype.createSliderDOM = function (element) {\n this.playAxisContainer = $('<div class=\"play-axis-container\"></div>')\n .appendTo(element)\n .css('height', PlayControl.PlayControlHeight + 'px');\n this.playButtonCircle = $('<div class=\"button-container\"></div>')\n .appendTo(this.playAxisContainer);\n if (this.isMobileChart) {\n this.playButtonCircle.addClass('mobile-button-container');\n }\n this.playButton = $('<div class=\"play\"></div>')\n .appendTo(this.playButtonCircle);\n this.slider = $('<div class=\"sliders\"></div>')\n .appendTo(this.playAxisContainer);\n };\n PlayControl.calucalateSliderSize = function (labelData, viewportWidth) {\n var leftMargin = 0;\n if (!_.isEmpty(labelData.labelInfo)) {\n leftMargin = _.first(labelData.labelInfo).labelWidth / 2;\n }\n var sliderLeftMargin = Math.max(leftMargin, PlayControl.SliderMarginLeft);\n sliderLeftMargin = Math.min(PlayControl.SliderMaxMargin, sliderLeftMargin);\n var sliderWidth = Math.max((viewportWidth - sliderLeftMargin - PlayControl.SliderMarginRight), 1);\n return { width: sliderWidth, marginLeft: sliderLeftMargin };\n };\n PlayControl.SliderMarginLeft = 24 + 10 * 2; // playButton width + playButton margin * 2\n PlayControl.SliderMarginRight = 20;\n PlayControl.SliderMaxMargin = 100;\n PlayControl.PlayControlHeight = 80; //tuned for two rows of label text to be perfectly clipped before the third row. Dependent on current font sizes in noui-pips.css\n return PlayControl;\n }());\n var PlayChart;\n (function (PlayChart) {\n // TODO: add speed control to property pane\n // NOTE: current noUiSlider speed is a CSS property of the class .noUi-state-tap, and also is hard-coded in noUiSlider.js. We'll need to add a new create param for transition time.\n // 800ms matches Silverlight frame speed\n PlayChart.FrameStepDuration = 800;\n PlayChart.FrameAnimationDuration = 750; //leave 50ms for the traceline animation - to avoid being cancelled. TODO: add a proper wait impl.\n PlayChart.ClassName = 'playChart';\n function convertMatrixToCategorical(sourceDataView, frame) {\n debug.assert(sourceDataView && sourceDataView.metadata && !!sourceDataView.matrix, 'sourceDataView && sourceDataView.metadata && !!sourceDataView.matrix');\n var matrix = sourceDataView.matrix;\n var categorical = {\n categories: [],\n values: powerbi.data.DataViewTransform.createValueColumns()\n };\n // If we don't have enough fields, just return early. We need at least:\n // 2 rows and 1 column: (play->category, measures)\n // or:\n // 1 row and 2 columns: (play, series->measures)\n if ((_.isEmpty(matrix.columns.levels)) || (matrix.rows.levels.length < 2 && matrix.columns.levels.length < 2)) {\n return { metadata: sourceDataView.metadata, categorical: categorical };\n }\n var CategoryRowLevelsStartingIndex = 1;\n var categories = [];\n // Ignore the play field (first row level); the Category field(s) starts from the second row group (play->category) or we don't use this variable (categories)\n // Note related to VSTS 6986788 and 6885783: there are multiple levels for category during drilldown and expand.\n for (var i_2 = CategoryRowLevelsStartingIndex, ilen = matrix.rows.levels.length; i_2 < ilen; i_2++) {\n // Consider: Change the following debug.assert() to retail.assert() when the infrastructure is ready.\n debug.assert(matrix.rows.levels[i_2].sources.length > 0, 'The sources is always expected to contain at least one metadata column.');\n var sourceColumn = matrix.rows.levels[i_2].sources[0];\n categories.push({\n source: sourceColumn,\n values: [],\n identity: [],\n objects: undefined,\n });\n }\n // Matrix shape for Play:\n //\n // Series1 | Series2 | ...\n // --------- -------- \n // Play1 | Category1 | values | values\n // | Category2 | values | values\n // | ...\n // Play2 | Category1 | values | values\n // | Category2 | values | values\n // ...\n // Or, with drilldown / expand on Category (e.g. expand Country -> Region):\n // Series1 | Series2 | ...\n // --------- -------- \n // Play1 | Country1 | Region1 | values | values\n // | | Region2 | values | values\n // | Country2 | Region3 | values | values\n // | | Region4 | values | values\n // | ...\n // Play2 | Country1 | Region1 | values | values\n // | | Region2 | values | values\n // | Country2 | Region3 | values | values\n // | | Region4 | values | values\n // we are guaranteed at least one row (it will be the Play field)\n var hasRowChildren = !_.isEmpty(matrix.rows.root.children);\n var hasColChildren = !_.isEmpty(matrix.columns.root.children);\n var hasSeries = matrix.columns.levels.length > 1 && hasColChildren;\n var hasPlayAndCategory = matrix.rows.levels.length > 1 && hasRowChildren;\n if (hasSeries && !hasPlayAndCategory) {\n // set categories to undefined\n categorical.categories = undefined;\n var node = matrix.columns.root;\n categorical.values.source = matrix.columns.levels[0].sources[0];\n var columnLength_1 = matrix.valueSources.length;\n for (var i_3 = 0, len_1 = node.children.length; i_3 < len_1; i_3++) {\n // add all the value sources for each series\n var columnNode = node.children[i_3];\n for (var j = 0; j < columnLength_1; j++) {\n // DEFECT 6547170: groupName must be null to turn into (Blank), undefined will use the field name\n var source = _.create(matrix.valueSources[j], { groupName: columnNode.value === undefined ? null : columnNode.value });\n var dataViewColumn = {\n identity: columnNode.identity,\n values: [],\n source: source\n };\n categorical.values.push(dataViewColumn);\n }\n }\n // Copying the values from matrix intersection to the categorical values columns...\n // Given that this is the case without category levels, the matrix intersection values are stored in playFrameNode.values\n var playFrameNode = matrix.rows.root.children[frame];\n var matrixIntersectionValues = playFrameNode.values;\n for (var i = 0, len = node.children.length; i < len; i++) {\n for (var j = 0; j < columnLength_1; j++) {\n categorical.values[i * columnLength_1 + j].values.push(matrixIntersectionValues[i * columnLength_1 + j].value);\n }\n }\n }\n else if (hasSeries && hasRowChildren) {\n // series and categories\n var playFrameNode = matrix.rows.root.children[frame];\n // create the categories first\n DataViewMatrixUtils.forEachLeafNode(playFrameNode.children, function (categoryGroupLeafNode, index, categoryHierarchicalGroupNodes) {\n addMatrixHierarchicalGroupToCategories(categoryHierarchicalGroupNodes, categories);\n });\n categorical.categories = categories;\n // now add the series info\n categorical.values.source = matrix.columns.levels[0].sources[0];\n var nodeQueue = [];\n var columnNode = matrix.columns.root;\n var seriesIndex_1 = -1;\n while (columnNode) {\n if (columnNode.children && columnNode.children[0].children) {\n for (var j = 0, jlen = columnNode.children.length; j < jlen; j++) {\n // each of these is a \"series\"\n nodeQueue.push(columnNode.children[j]);\n }\n }\n else if (columnNode.children && playFrameNode.children) {\n // Processing a single series under here, push all the value sources for every series.\n var columnLength = columnNode.children.length;\n for (var j = 0; j < columnLength; j++) {\n var source = _.create(matrix.valueSources[j], { groupName: columnNode.value });\n var dataViewColumn = {\n identity: columnNode.identity,\n values: [],\n source: source,\n };\n categorical.values.push(dataViewColumn);\n }\n // Copying the values from matrix intersection to the categorical values columns...\n DataViewMatrixUtils.forEachLeafNode(playFrameNode.children, function (leafNode) {\n for (var j = 0; j < columnLength; j++) {\n categorical.values[seriesIndex_1 * columnLength + j].values.push(leafNode.values[seriesIndex_1 * columnLength + j].value);\n }\n });\n }\n if (nodeQueue.length > 0) {\n columnNode = nodeQueue[0];\n nodeQueue = nodeQueue.splice(1);\n seriesIndex_1++;\n }\n else\n columnNode = undefined;\n }\n }\n else if (hasPlayAndCategory) {\n // no series, just play and category\n var playFrameNode = matrix.rows.root.children[frame];\n var measureLength_1 = matrix.valueSources.length;\n for (var j = 0; j < measureLength_1; j++) {\n var dataViewColumn = {\n identity: undefined,\n values: [],\n source: matrix.valueSources[j]\n };\n categorical.values.push(dataViewColumn);\n }\n DataViewMatrixUtils.forEachLeafNode(playFrameNode.children, function (categoryGroupLeafNode, index, categoryHierarchicalGroupNodes) {\n addMatrixHierarchicalGroupToCategories(categoryHierarchicalGroupNodes, categories);\n // Copying the values from matrix intersection to the categorical values columns...\n for (var j = 0; j < measureLength_1; j++) {\n categorical.values[j].values.push(categoryGroupLeafNode.values[j].value);\n }\n });\n categorical.categories = categories;\n }\n // the visual code today expects only 1 category column, hence apply DataViewConcatenateCategoricalColumns\n return DataViewConcatenateCategoricalColumns.applyToPlayChartCategorical(sourceDataView.metadata, visuals.scatterChartCapabilities.objects, 'Category', categorical);\n }\n PlayChart.convertMatrixToCategorical = convertMatrixToCategorical;\n function addMatrixHierarchicalGroupToCategories(sourceCategoryHierarchicalGroupNodes, destinationCategories) {\n debug.assertNonEmpty(sourceCategoryHierarchicalGroupNodes, 'sourceCategoryHierarchicalGroupNodes');\n debug.assertNonEmpty(destinationCategories, 'destinationCategories');\n debug.assert(sourceCategoryHierarchicalGroupNodes.length === destinationCategories.length, 'pre-condition: there should be one category column per matrix row level for Category.');\n // Note: Before the Categorical concatenation logic got added to this playChart logic, the code did NOT populate\n // the ***DataViewCategoryColumn.identityFields*** property, and the playChart visual code does not seem to need it.\n // If we do want to populate that property, we might want to do reuse data.ISQExpr[] across nodes as much as possible \n // because all the child nodes under a given parent will have the exact same identityFields value, and a lot of \n // DataViewCategory objects can get created for a given playChart.\n var identity = sourceCategoryHierarchicalGroupNodes[0].identity;\n if (sourceCategoryHierarchicalGroupNodes.length > 1) {\n // if the hierarchical group has more than 1 level, create a composite identity from the nodes\n var identityExpr = identity.expr;\n for (var i = 1, ilen = sourceCategoryHierarchicalGroupNodes.length; i < ilen; i++) {\n var identityExprToAdd = sourceCategoryHierarchicalGroupNodes[i].identity.expr;\n identityExpr = SQExprBuilder.and(identityExpr, identityExprToAdd);\n }\n identity = createDataViewScopeIdentity(identityExpr);\n }\n // add the Category value of each matrix node into its respective category column\n for (var j = 0, jlen = destinationCategories.length; j < jlen; j++) {\n destinationCategories[j].identity.push(identity);\n var node = sourceCategoryHierarchicalGroupNodes[j];\n destinationCategories[j].values.push(node.value);\n }\n }\n function getObjectProperties(dataViewMetadata, dataLabelsSettings) {\n var objectProperties = {};\n if (dataViewMetadata && dataViewMetadata.objects) {\n var objects = dataViewMetadata.objects;\n // TODO: remove?\n objectProperties.currentFrameIndex = powerbi.DataViewObjects.getValue(objects, visuals.scatterChartProps.currentFrameIndex.index, null);\n }\n return objectProperties;\n }\n function converter(dataView, visualConverter) {\n var dataViewMetadata = dataView.metadata;\n var dataLabelsSettings = visuals.dataLabelUtils.getDefaultPointLabelSettings();\n var objectProperties = getObjectProperties(dataViewMetadata, dataLabelsSettings);\n var allViewModels = [];\n var frameKeys = [];\n var convertedData = undefined;\n var matrixRows = dataView.matrix.rows;\n var rowChildrenLength = matrixRows.root.children ? matrixRows.root.children.length : 0;\n var keySourceColumn;\n if (dataView.matrix && rowChildrenLength > 0 && !_.isEmpty(matrixRows.levels) && !_.isEmpty(matrixRows.levels[0].sources)) {\n keySourceColumn = matrixRows.levels[0].sources[0];\n // TODO: this should probably defer to the visual which knows how to format the categories.\n var formatString = visuals.valueFormatter.getFormatString(keySourceColumn, visuals.scatterChartProps.general.formatString);\n var keyFormatter = void 0;\n if (keySourceColumn.type.numeric) {\n // use value range, not actual values\n var valueRange = Math.abs(matrixRows.root.children[rowChildrenLength - 1].value - matrixRows.root.children[0].value);\n keyFormatter = visuals.valueFormatter.create({\n format: formatString,\n value: valueRange,\n value2: 0,\n });\n }\n else {\n keyFormatter = visuals.valueFormatter.createDefaultFormatter(formatString, true);\n }\n for (var i = 0, len = rowChildrenLength; i < len; i++) {\n var key = matrixRows.root.children[i];\n var frameLabelText = keyFormatter.format(key.value);\n // escaped html\n var frameLabelHtml = $(\"<div/>\").text(frameLabelText).html();\n frameKeys.push({ escapedText: frameLabelHtml, text: frameLabelText });\n var dataViewCategorical = convertMatrixToCategorical(dataView, i);\n var frameInfo = { label: frameLabelHtml, column: keySourceColumn };\n convertedData = visualConverter(dataViewCategorical, frameInfo);\n allViewModels.push(convertedData);\n }\n }\n else {\n var dataViewCategorical = convertMatrixToCategorical(dataView, 0);\n convertedData = visualConverter(dataViewCategorical);\n allViewModels.push(convertedData);\n }\n // NOTE: currentViewModel is already set to the last frame\n objectProperties.currentFrameIndex = frameKeys.length - 1;\n return {\n allViewModels: allViewModels,\n currentViewModel: convertedData,\n frameData: frameKeys,\n currentFrameIndex: objectProperties.currentFrameIndex,\n labelData: getLabelData(frameKeys, keySourceColumn),\n };\n }\n PlayChart.converter = converter;\n function getDefaultPlayData() {\n var defaultData = {\n frameData: [],\n allViewModels: [],\n currentFrameIndex: 0,\n currentViewModel: undefined,\n labelData: {\n anyWordBreaks: false,\n labelInfo: [],\n },\n };\n return defaultData;\n }\n PlayChart.getDefaultPlayData = getDefaultPlayData;\n function getMinMaxForAllFrames(playData, getExtents) {\n var extents = {\n minY: 0,\n maxY: 10,\n minX: 0,\n maxX: 10,\n };\n if (playData.allViewModels && playData.allViewModels.length > 0) {\n extents.minY = extents.minX = Number.MAX_VALUE;\n extents.maxY = extents.maxX = Number.MIN_VALUE;\n for (var i = 0, len = playData.allViewModels.length; i < len; i++) {\n var data_7 = playData.allViewModels[i];\n var e = getExtents(data_7);\n // NOTE: D3.min/max handle undefined and NaN nicely, as opposed to Math.min/max\n extents = {\n minY: d3.min([e.minY, extents.minY]),\n maxY: d3.max([e.maxY, extents.maxY]),\n minX: d3.min([e.minX, extents.minX]),\n maxX: d3.max([e.maxX, extents.maxX]),\n };\n }\n }\n return extents;\n }\n PlayChart.getMinMaxForAllFrames = getMinMaxForAllFrames;\n function getLabelData(keys, keyColumn) {\n var textProperties = {\n fontFamily: 'wf_segoe-ui_normal',\n fontSize: jsCommon.PixelConverter.toString(14),\n };\n var labelInfo = [];\n var anyWordBreaks = false;\n for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {\n var key = keys_1[_i];\n var labelWidth = jsCommon.WordBreaker.getMaxWordWidth(key.escapedText, powerbi.TextMeasurementService.measureSvgTextWidth, textProperties);\n // TODO: Why isn't this last part included in hasBreakers()?\n anyWordBreaks = anyWordBreaks || jsCommon.WordBreaker.hasBreakers(key.escapedText) || (key.escapedText).indexOf('-') > -1;\n labelInfo.push({ label: key.escapedText, labelWidth: labelWidth });\n }\n return {\n labelInfo: labelInfo,\n anyWordBreaks: anyWordBreaks,\n labelFieldName: keyColumn && keyColumn.displayName,\n };\n }\n function isDataViewPlayable(dataView, playRole) {\n if (playRole === void 0) { playRole = 'Play'; }\n debug.assertValue(dataView, 'dataView');\n var firstRowSourceRoles = dataView.matrix &&\n dataView.matrix.rows &&\n dataView.matrix.rows.levels &&\n dataView.matrix.rows.levels[0] &&\n dataView.matrix.rows.levels[0].sources &&\n dataView.matrix.rows.levels[0].sources[0] &&\n dataView.matrix.rows.levels[0].sources[0].roles;\n return firstRowSourceRoles && firstRowSourceRoles[playRole];\n }\n PlayChart.isDataViewPlayable = isDataViewPlayable;\n /** Render trace-lines for selected data points. */\n function renderTraceLines(allDataPoints, traceLineRenderer, shouldAnimate) {\n var selectedDataPoints = _.filter(allDataPoints, function (d) { return d.selected; });\n selectedDataPoints = _.uniq(selectedDataPoints, function (d) { return d.identity.getKey(); });\n traceLineRenderer.render(selectedDataPoints, shouldAnimate);\n }\n PlayChart.renderTraceLines = renderTraceLines;\n })(PlayChart = visuals.PlayChart || (visuals.PlayChart = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var PixelConverter = jsCommon.PixelConverter;\n var VerticalSlicerRenderer = (function () {\n function VerticalSlicerRenderer(options) {\n this.textProperties = {\n 'fontFamily': 'wf_segoe-ui_normal, helvetica, arial, sans-serif',\n 'fontSize': '14px',\n };\n if (options) {\n this.behavior = options.behavior;\n }\n this.domHelper = options.domHelper;\n }\n // SlicerDefaultValueHandler\n VerticalSlicerRenderer.prototype.getDefaultValue = function () {\n if (this.data && this.data.defaultValue)\n return this.data.defaultValue.value;\n };\n VerticalSlicerRenderer.prototype.getIdentityFields = function () {\n return visuals.SlicerUtil.DefaultValueHandler.getIdentityFields(this.dataView);\n };\n VerticalSlicerRenderer.prototype.init = function (slicerInitOptions) {\n var _this = this;\n this.element = slicerInitOptions.visualInitOptions.element;\n this.currentViewport = slicerInitOptions.visualInitOptions.viewport;\n var hostServices = this.hostServices = slicerInitOptions.visualInitOptions.host;\n var settings = this.settings = visuals.Slicer.DefaultStyleProperties();\n var domHelper = this.domHelper;\n var bodyViewport = domHelper.getSlicerBodyViewport(this.currentViewport, settings, this.textProperties);\n var interactivityService;\n if (this.behavior)\n interactivityService = visuals.createInteractivityService(hostServices);\n var containerDiv = document.createElement('div');\n containerDiv.className = Selectors.Container.class;\n var container = this.container = d3.select(containerDiv);\n var header = domHelper.createSlicerHeader(hostServices);\n containerDiv.appendChild(header);\n this.header = d3.select(header);\n this.body = container.append('div').classed(visuals.SlicerUtil.Selectors.Body.class, true)\n .style({\n 'height': PixelConverter.toString(bodyViewport.height),\n 'width': PixelConverter.toString(bodyViewport.width),\n });\n var rowEnter = function (rowSelection) {\n _this.onEnterSelection(rowSelection);\n };\n var rowUpdate = function (rowSelection) {\n _this.onUpdateSelection(rowSelection, interactivityService);\n };\n var rowExit = function (rowSelection) {\n rowSelection.remove();\n };\n var listViewOptions = {\n rowHeight: domHelper.getRowHeight(settings, this.textProperties),\n enter: rowEnter,\n exit: rowExit,\n update: rowUpdate,\n loadMoreData: function () { return slicerInitOptions.loadMoreData(); },\n scrollEnabled: true,\n viewport: domHelper.getSlicerBodyViewport(this.currentViewport, settings, this.textProperties),\n baseContainer: this.body,\n isReadMode: function () {\n return (_this.hostServices.getViewMode() !== 1 /* Edit */);\n }\n };\n this.listView = visuals.ListViewFactory.createListView(listViewOptions);\n // Append container to DOM\n this.element.get(0).appendChild(containerDiv);\n return interactivityService;\n };\n VerticalSlicerRenderer.prototype.render = function (options) {\n var data = this.data = options.data;\n this.currentViewport = options.viewport;\n var dataView = options.dataView;\n if (!dataView || !data) {\n this.listView.empty();\n return;\n }\n this.dataView = dataView;\n var settings = this.settings = data.slicerSettings;\n var domHelper = this.domHelper;\n domHelper.updateSlicerBodyDimensions(this.currentViewport, this.body, settings);\n this.updateSelectionStyle();\n this.listView\n .viewport(domHelper.getSlicerBodyViewport(this.currentViewport, settings, this.textProperties))\n .rowHeight(domHelper.getRowHeight(settings, this.textProperties))\n .data(data.slicerDataPoints, function (d) { return $.inArray(d, data.slicerDataPoints); }, options.resetScrollbarPosition);\n };\n VerticalSlicerRenderer.prototype.updateSelectionStyle = function () {\n var settings = this.settings;\n this.container.classed('isMultiSelectEnabled', settings && settings.selection && !settings.selection.singleSelect);\n };\n VerticalSlicerRenderer.prototype.onEnterSelection = function (rowSelection) {\n var settings = this.settings;\n var listItemElement = rowSelection.append('li')\n .classed(Selectors.ItemContainer.class, true);\n var labelElement = listItemElement.append('div')\n .classed(Selectors.Input.class, true);\n labelElement.append('input')\n .attr('type', 'checkbox');\n labelElement.append('span')\n .classed(Selectors.Checkbox.class, true);\n listItemElement.each(function (d, i) {\n var item = d3.select(this);\n if (d.isImage) {\n item.append('img')\n .classed(visuals.SlicerUtil.Selectors.LabelImage.class, true);\n }\n else {\n item.append('span')\n .classed(visuals.SlicerUtil.Selectors.LabelText.class, true);\n }\n if (d.count != null) {\n item.append('span')\n .classed(visuals.SlicerUtil.Selectors.CountText.class, true)\n .style('font-size', PixelConverter.fromPoint(settings.slicerText.textSize));\n }\n });\n };\n VerticalSlicerRenderer.prototype.onUpdateSelection = function (rowSelection, interactivityService) {\n var settings = this.settings;\n var data = this.data;\n if (data && settings) {\n // Style Slicer Header\n var domHelper = this.domHelper;\n domHelper.styleSlicerHeader(this.header, settings, data.categorySourceName);\n this.header.attr('title', data.categorySourceName);\n var labelText = rowSelection.selectAll(visuals.SlicerUtil.Selectors.LabelText.selector);\n labelText.text(function (d) {\n return d.value;\n }).attr('title', function (d) {\n return d.tooltip;\n });\n domHelper.setSlicerTextStyle(labelText, settings);\n var labelImage = rowSelection.selectAll(visuals.SlicerUtil.Selectors.LabelImage.selector);\n if (!labelImage.empty()) {\n labelImage.attr('src', function (d) {\n return d.value;\n });\n }\n var countText = rowSelection.selectAll(visuals.SlicerUtil.Selectors.CountText.selector);\n if (!countText.empty()) {\n countText.text(function (d) { return d.count; });\n domHelper.setSlicerTextStyle(countText, settings);\n }\n if (interactivityService && this.body) {\n var body = this.body.attr('width', this.currentViewport.width);\n var slicerItemContainers = body.selectAll(Selectors.ItemContainer.selector);\n var slicerItemLabels = body.selectAll(visuals.SlicerUtil.Selectors.LabelText.selector);\n var slicerItemInputs = body.selectAll(Selectors.Input.selector);\n var slicerClear = this.header.select(visuals.SlicerUtil.Selectors.Clear.selector);\n var behaviorOptions = {\n dataPoints: data.slicerDataPoints,\n slicerContainer: this.container,\n itemContainers: slicerItemContainers,\n itemLabels: slicerItemLabels,\n itemInputs: slicerItemInputs,\n clear: slicerClear,\n interactivityService: interactivityService,\n settings: data.slicerSettings,\n };\n var orientationBehaviorOptions = {\n behaviorOptions: behaviorOptions,\n orientation: 0 /* Vertical */,\n };\n interactivityService.bind(data.slicerDataPoints, this.behavior, orientationBehaviorOptions, { overrideSelectionFromData: true, hasSelectionOverride: data.hasSelectionOverride, slicerDefaultValueHandler: this });\n visuals.SlicerWebBehavior.styleSlicerItems(rowSelection.select(Selectors.Input.selector), data.hasSelectionOverride, interactivityService.isSelectionModeInverted());\n }\n else {\n visuals.SlicerWebBehavior.styleSlicerItems(rowSelection.select(Selectors.Input.selector), false, false);\n }\n }\n };\n return VerticalSlicerRenderer;\n }());\n visuals.VerticalSlicerRenderer = VerticalSlicerRenderer;\n var Selectors;\n (function (Selectors) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n Selectors.Container = createClassAndSelector('slicerContainer');\n Selectors.ItemContainer = createClassAndSelector('slicerItemContainer');\n Selectors.Input = createClassAndSelector('slicerCheckbox');\n Selectors.Checkbox = createClassAndSelector('checkbox');\n })(Selectors || (Selectors = {}));\n var CheckboxSprite;\n (function (CheckboxSprite) {\n CheckboxSprite.MinimumSize = 8;\n CheckboxSprite.Size = 13;\n CheckboxSprite.SizeRange = CheckboxSprite.Size - CheckboxSprite.MinimumSize;\n })(CheckboxSprite || (CheckboxSprite = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var PixelConverter = jsCommon.PixelConverter;\n var ItemWidthSampleSize = 50;\n var MinTextWidth = 80;\n var LoadMoreDataThreshold = 0.8; // The value indicates the percentage of data already shown that triggers a loadMoreData call.\n var DefaultStyleProperties = {\n labelText: {\n marginRight: 2,\n paddingLeft: 8,\n paddingRight: 8,\n },\n };\n var HorizontalSlicerRenderer = (function () {\n function HorizontalSlicerRenderer(options) {\n this.textProperties = {\n fontFamily: 'wf_segoe-ui_normal',\n fontSize: '14px'\n };\n if (options) {\n this.behavior = options.behavior;\n }\n this.domHelper = options.domHelper;\n this.dataStartIndex = 0;\n }\n // SlicerDefaultValueHandler\n HorizontalSlicerRenderer.prototype.getDefaultValue = function () {\n if (this.data && this.data.defaultValue)\n return this.data.defaultValue.value;\n };\n HorizontalSlicerRenderer.prototype.getIdentityFields = function () {\n return visuals.SlicerUtil.DefaultValueHandler.getIdentityFields(this.dataView);\n };\n HorizontalSlicerRenderer.prototype.init = function (slicerInitOptions) {\n this.element = slicerInitOptions.visualInitOptions.element;\n this.currentViewport = slicerInitOptions.visualInitOptions.viewport;\n var hostServices = this.hostServices = slicerInitOptions.visualInitOptions.host;\n if (this.behavior) {\n this.interactivityService = visuals.createInteractivityService(hostServices);\n }\n this.loadMoreData = function () { return slicerInitOptions.loadMoreData(); };\n var containerDiv = document.createElement('div');\n containerDiv.className = Selectors.container.class;\n var container = this.container = d3.select(containerDiv);\n var header = this.domHelper.createSlicerHeader(this.hostServices);\n containerDiv.appendChild(header);\n this.header = d3.select(header);\n var body = this.body = container.append('div').classed(visuals.SlicerUtil.Selectors.Body.class + \" \" + Selectors.FlexDisplay.class, true);\n this.leftNavigationArrow = body.append(\"button\")\n .classed(Selectors.NavigationArrow.class + \" \" + Selectors.LeftNavigationArrow.class, true);\n this.itemsContainer = body.append(\"div\")\n .classed(Selectors.ItemsContainer.class + \" \" + Selectors.FlexDisplay.class, true);\n this.rightNavigationArrow = body.append(\"button\")\n .classed(Selectors.NavigationArrow.class + \" \" + Selectors.RightNavigationArrow.class, true);\n // Append container to DOM\n this.element.get(0).appendChild(containerDiv);\n this.bindNavigationEvents();\n return this.interactivityService;\n };\n HorizontalSlicerRenderer.prototype.render = function (options) {\n var data = options.data;\n var dataView = options.dataView;\n if (!dataView || !data) {\n this.itemsContainer.selectAll(\"*\").remove();\n return;\n }\n this.data = data;\n this.dataView = dataView;\n var resized = this.currentViewport && options.viewport\n && (this.currentViewport.height !== options.viewport.height || this.currentViewport.width !== options.viewport.width);\n if (!(this.isMaxWidthCalculated() && resized)) {\n // Max width calculation is not required during resize, but required on data changes like changes to formatting properties fontSize, outline, outline weight, etc...\n // So calculating only on data updates\n this.calculateAndSetMaxItemWidth();\n this.calculateAndSetTotalItemWidth();\n }\n this.currentViewport = options.viewport;\n this.updateStyle();\n var availableWidthForItemsContainer = this.element.find(Selectors.ItemsContainer.selector).width();\n this.itemsToDisplay = this.getNumberOfItemsToDisplay(availableWidthForItemsContainer);\n if (this.itemsToDisplay === 0)\n return;\n this.renderCore();\n };\n HorizontalSlicerRenderer.prototype.renderCore = function () {\n var data = this.data;\n if (!data || !data.slicerDataPoints)\n return;\n this.normalizePosition(data.slicerDataPoints);\n var itemsToDisplay = this.itemsToDisplay;\n var dataStartIndex = this.dataStartIndex;\n // Update Navigation Arrows\n this.container.classed(Selectors.CanScrollRight.class, dataStartIndex + this.itemsToDisplay <= data.slicerDataPoints.length - 1);\n this.container.classed(Selectors.CanScrollLeft.class, dataStartIndex > 0);\n // Manipulate DOM\n this.renderItems(data.slicerSettings);\n // Bind Interactivity Service\n this.bindInteractivityService();\n // Load More Data\n if (dataStartIndex + itemsToDisplay >= data.slicerDataPoints.length * LoadMoreDataThreshold) {\n this.loadMoreData();\n }\n };\n HorizontalSlicerRenderer.prototype.updateStyle = function () {\n var viewport = this.currentViewport;\n var data = this.data;\n var defaultSettings = data.slicerSettings;\n var domHelper = this.domHelper;\n this.container\n .classed(Selectors.MultiSelectEnabled.class, !defaultSettings.selection.singleSelect)\n .style({\n \"width\": PixelConverter.toString(viewport.width),\n \"height\": PixelConverter.toString(viewport.height),\n });\n // Style Slicer Header\n domHelper.styleSlicerHeader(this.header, defaultSettings, data.categorySourceName);\n var headerTextProperties = domHelper.getHeaderTextProperties(defaultSettings);\n this.header.attr('title', data.categorySourceName);\n // Update body width and height\n var bodyViewport = this.bodyViewport = domHelper.getSlicerBodyViewport(viewport, defaultSettings, headerTextProperties);\n this.body.style({\n \"height\": PixelConverter.toString(bodyViewport.height),\n \"width\": PixelConverter.toString(bodyViewport.width),\n });\n };\n HorizontalSlicerRenderer.prototype.renderItems = function (defaultSettings) {\n var _this = this;\n var itemsToDisplay = this.itemsToDisplay;\n debug.assert(itemsToDisplay > 0, 'items to display should be greater than zero');\n var dataStartIndex = this.dataStartIndex;\n var materializedDataPoints = this.data.slicerDataPoints.slice(dataStartIndex, dataStartIndex + itemsToDisplay);\n var items = this.itemsContainer\n .selectAll(visuals.SlicerUtil.Selectors.LabelText.selector)\n .data(materializedDataPoints, function (d) { return _.indexOf(_this.data.slicerDataPoints, d); });\n items\n .enter()\n .append(\"div\")\n .classed(visuals.SlicerUtil.Selectors.LabelText.class + \" \" + Selectors.FlexDisplay.class, true);\n items.order();\n items\n .style({\n \"font-family\": this.textProperties.fontFamily,\n \"padding-left\": PixelConverter.toString(DefaultStyleProperties.labelText.paddingLeft),\n \"padding-right\": PixelConverter.toString(DefaultStyleProperties.labelText.paddingRight),\n \"margin-right\": function (d, i) { return _this.isLastRowItem(i, itemsToDisplay) ? \"0px\" : PixelConverter.toString(DefaultStyleProperties.labelText.marginRight); },\n });\n // Default style settings from formatting pane settings\n this.domHelper.setSlicerTextStyle(items, defaultSettings);\n items.exit().remove();\n window.setTimeout(function () {\n items\n .attr(\"title\", function (d) { return d.tooltip; })\n .text(function (d) { return d.value; });\n // Wrap long text into multiple columns based on height availbale\n var labels = _this.element.find(visuals.SlicerUtil.Selectors.LabelText.selector);\n var item = labels.first();\n var itemWidth = item.width();\n var itemHeight = item.height();\n labels.each(function (i, element) {\n powerbi.TextMeasurementService.wordBreakOverflowingText(element, itemWidth, itemHeight);\n });\n });\n };\n HorizontalSlicerRenderer.prototype.bindInteractivityService = function () {\n if (this.interactivityService && this.body) {\n var body = this.body;\n var itemsContainer = body.selectAll(Selectors.ItemsContainer.selector);\n var itemLabels = body.selectAll(visuals.SlicerUtil.Selectors.LabelText.selector);\n var clear = this.header.select(visuals.SlicerUtil.Selectors.Clear.selector);\n var data_8 = this.data;\n var behaviorOptions = {\n dataPoints: data_8.slicerDataPoints,\n slicerContainer: this.container,\n itemsContainer: itemsContainer,\n itemLabels: itemLabels,\n clear: clear,\n interactivityService: this.interactivityService,\n settings: data_8.slicerSettings,\n };\n var orientationBehaviorOptions = {\n behaviorOptions: behaviorOptions,\n orientation: 1 /* Horizontal */,\n };\n this.interactivityService.bind(data_8.slicerDataPoints, this.behavior, orientationBehaviorOptions, { overrideSelectionFromData: true, hasSelectionOverride: data_8.hasSelectionOverride });\n visuals.SlicerWebBehavior.styleSlicerItems(this.itemsContainer.selectAll(visuals.SlicerUtil.Selectors.LabelText.selector), this.interactivityService.hasSelection(), this.interactivityService.isSelectionModeInverted());\n }\n else {\n visuals.SlicerWebBehavior.styleSlicerItems(this.itemsContainer.selectAll(visuals.SlicerUtil.Selectors.LabelText.selector), false, false);\n }\n };\n HorizontalSlicerRenderer.prototype.normalizePosition = function (points) {\n var dataStartIndex = this.dataStartIndex;\n // if dataStartIndex >= points.length\n dataStartIndex = Math.min(dataStartIndex, points.length - 1);\n // if dataStartIndex < 0 \n this.dataStartIndex = Math.max(dataStartIndex, 0);\n };\n HorizontalSlicerRenderer.prototype.bindNavigationEvents = function () {\n this.registerMouseWheelScrollEvents();\n this.registerMouseClickEvents();\n };\n HorizontalSlicerRenderer.prototype.registerMouseClickEvents = function () {\n var _this = this;\n var rightNavigationArrow = this.container.selectAll(Selectors.RightNavigationArrow.selector);\n var leftNavigationArrow = this.container.selectAll(Selectors.LeftNavigationArrow.selector);\n rightNavigationArrow\n .on(\"click\", function () {\n _this.scrollRight();\n });\n leftNavigationArrow\n .on(\"click\", function () {\n _this.scrollLeft();\n });\n };\n // Register for mouse wheel scroll events\n HorizontalSlicerRenderer.prototype.registerMouseWheelScrollEvents = function () {\n var _this = this;\n var scrollableElement = this.body.node();\n scrollableElement.addEventListener(\"mousewheel\", function (e) {\n _this.onMouseWheel(e.wheelDelta);\n });\n scrollableElement.addEventListener(\"DOMMouseScroll\", function (e) {\n _this.onMouseWheel(e.detail);\n });\n };\n HorizontalSlicerRenderer.prototype.onMouseWheel = function (wheelDelta) {\n if (wheelDelta < 0) {\n this.scrollRight();\n }\n else if (wheelDelta > 0) {\n this.scrollLeft();\n }\n };\n /* If there is only one item being displayed, we show the next item when navigation arrows are clicked\n * But when there are more than 1 item, n-1 items are shown say we have 10 items in total , in initial page if we show 1 to 5 items when right button is clicked we will show items from 5 to 10\n */\n HorizontalSlicerRenderer.prototype.scrollRight = function () {\n var itemsToDisplay = this.itemsToDisplay;\n var startIndex = this.dataStartIndex;\n var dataPointsLength = this.data.slicerDataPoints.length;\n var lastItemIndex = dataPointsLength - 1;\n // If it is the last page stay on the same page and don't navigate\n if (itemsToDisplay + startIndex > lastItemIndex) {\n return;\n }\n if (itemsToDisplay === 1) {\n startIndex += itemsToDisplay;\n }\n else {\n startIndex += itemsToDisplay - 1;\n }\n // Adjust the startIndex to show last n items if startIndex + itemsToDisplay is greater than total datapoints\n if (itemsToDisplay + startIndex > lastItemIndex) {\n startIndex = lastItemIndex - itemsToDisplay + 1;\n }\n this.dataStartIndex = startIndex;\n this.renderCore();\n };\n /* If there is only one item being displayed, we show the next item when navigation arrows are clicked\n * But when there are more than 1 item, n-1 items are shown\n */\n HorizontalSlicerRenderer.prototype.scrollLeft = function () {\n var itemsToDisplay = this.itemsToDisplay;\n var startIndex = this.dataStartIndex;\n var firstItemIndex = 0;\n // If it is the first page stay on the same page and don't navigate\n if (startIndex === 0) {\n return;\n }\n // If there is only item shown when left navigation button is clicked we want to navigate back to show previous item\n if (itemsToDisplay === 1) {\n startIndex -= itemsToDisplay;\n }\n if (startIndex - itemsToDisplay < firstItemIndex) {\n startIndex = firstItemIndex;\n }\n else {\n startIndex = startIndex - itemsToDisplay + 1;\n }\n this.dataStartIndex = startIndex;\n this.renderCore();\n };\n HorizontalSlicerRenderer.prototype.isLastRowItem = function (fieldIndex, columnsToDisplay) {\n return fieldIndex === columnsToDisplay - 1;\n };\n HorizontalSlicerRenderer.prototype.getScaledTextWidth = function (textSize) {\n return (textSize / jsCommon.TextSizeDefaults.TextSizeMin) * MinTextWidth;\n };\n HorizontalSlicerRenderer.prototype.isMaxWidthCalculated = function () {\n return this.maxItemWidth !== undefined;\n };\n // Sampling a subset of total datapoints to calculate max item width\n HorizontalSlicerRenderer.prototype.calculateAndSetMaxItemWidth = function () {\n var dataPointsLength = this.getDataPointsCount();\n var maxItemWidth = 0;\n if (dataPointsLength === 0) {\n this.maxItemWidth = maxItemWidth;\n return;\n }\n var data = this.data;\n var dataPoints = data.slicerDataPoints;\n var sampleSize = Math.min(dataPointsLength, ItemWidthSampleSize);\n var properties = jQuery.extend(true, {}, this.textProperties);\n var textSize = data.slicerSettings.slicerText.textSize;\n // Update text properties from formatting pane values\n properties.fontSize = PixelConverter.fromPoint(textSize);\n var getMaxWordWidth = jsCommon.WordBreaker.getMaxWordWidth;\n for (var i = 0; i < sampleSize; i++) {\n var itemText = dataPoints[i].value;\n properties.text = itemText;\n maxItemWidth = Math.max(maxItemWidth, getMaxWordWidth(itemText, powerbi.TextMeasurementService.measureSvgTextWidth, properties));\n }\n this.maxItemWidth = Math.min(maxItemWidth, this.getScaledTextWidth(textSize));\n };\n HorizontalSlicerRenderer.prototype.calculateAndSetTotalItemWidth = function () {\n var data = this.data;\n var itemPadding = DefaultStyleProperties.labelText.paddingLeft + DefaultStyleProperties.labelText.paddingRight + DefaultStyleProperties.labelText.marginRight;\n var borderWidth = this.domHelper.getRowsOutlineWidth(data.slicerSettings.slicerText.outline, data.slicerSettings.general.outlineWeight);\n this.totalItemWidth = this.maxItemWidth + itemPadding + borderWidth;\n };\n HorizontalSlicerRenderer.prototype.getNumberOfItemsToDisplay = function (widthAvailable) {\n var totalItemWidth = this.totalItemWidth;\n if (totalItemWidth === 0)\n return 0;\n var dataPointsLength = this.getDataPointsCount();\n var numberOfItems = Math.min(dataPointsLength, Math.round(widthAvailable / totalItemWidth));\n // Show atleast 1 item by default \n return Math.max(numberOfItems, 1);\n };\n HorizontalSlicerRenderer.prototype.getDataPointsCount = function () {\n return _.size(this.data.slicerDataPoints);\n };\n return HorizontalSlicerRenderer;\n }());\n visuals.HorizontalSlicerRenderer = HorizontalSlicerRenderer;\n var Selectors;\n (function (Selectors) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n Selectors.container = createClassAndSelector('horizontalSlicerContainer');\n Selectors.ItemsContainer = createClassAndSelector('slicerItemsContainer');\n Selectors.NavigationArrow = createClassAndSelector('navigationArrow');\n Selectors.LeftNavigationArrow = createClassAndSelector('left');\n Selectors.RightNavigationArrow = createClassAndSelector('right');\n Selectors.MultiSelectEnabled = createClassAndSelector('isMultiSelectEnabled');\n Selectors.FlexDisplay = createClassAndSelector('flexDisplay');\n Selectors.CanScrollRight = createClassAndSelector('canScrollRight');\n Selectors.CanScrollLeft = createClassAndSelector('canScrollLeft');\n })(Selectors || (Selectors = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var DisplayNameKeys = visuals.SlicerUtil.DisplayNameKeys;\n var DOMHelper = visuals.SlicerUtil.DOMHelper;\n var SettingsHelper = visuals.SlicerUtil.SettingsHelper;\n var Slicer = (function () {\n function Slicer(options) {\n if (options) {\n this.behavior = options.behavior;\n }\n this.domHelper = new DOMHelper();\n }\n Slicer.DefaultStyleProperties = function () {\n return {\n general: {\n outlineColor: '#808080',\n outlineWeight: 1,\n orientation: 0 /* Vertical */,\n },\n header: {\n borderBottomWidth: 1,\n show: true,\n outline: visuals.outline.bottomOnly,\n fontColor: '#000000',\n textSize: 10,\n },\n slicerText: {\n color: '#666666',\n outline: visuals.outline.none,\n textSize: 10,\n },\n selection: {\n selectAllCheckboxEnabled: false,\n singleSelect: true,\n },\n };\n };\n Slicer.prototype.init = function (options) {\n this.initOptions = options;\n this.element = options.element;\n this.currentViewport = options.viewport;\n this.hostServices = options.host;\n var settings = this.settings = Slicer.DefaultStyleProperties();\n this.slicerOrientation = settings.general.orientation;\n this.waitingForData = false;\n this.initializeSlicerRenderer(this.slicerOrientation);\n };\n Slicer.prototype.onDataChanged = function (options) {\n debug.assertValue(options, 'options');\n var dataViews = options.dataViews;\n debug.assertValue(dataViews, 'dataViews');\n if (_.isEmpty(dataViews)) {\n return;\n }\n var existingDataView = this.dataView;\n this.dataView = dataViews[0];\n // Reset scrollbar by default, unless it's an Append operation or Selecting an item\n var resetScrollbarPosition = options.operationKind !== powerbi.VisualDataChangeOperationKind.Append\n && !powerbi.DataViewAnalysis.hasSameCategoryIdentity(existingDataView, this.dataView);\n this.render(resetScrollbarPosition, true);\n };\n Slicer.prototype.onResizing = function (finalViewport) {\n this.currentViewport = finalViewport;\n this.render(false /* resetScrollbarPosition */);\n };\n Slicer.prototype.enumerateObjectInstances = function (options) {\n return ObjectEnumerator.enumerateObjectInstances(options, this.slicerData, this.settings, this.dataView);\n };\n // public for testability\n Slicer.prototype.loadMoreData = function () {\n var dataView = this.dataView;\n if (!dataView)\n return;\n var dataViewMetadata = dataView.metadata;\n // Making sure that hostservices.loadMoreData is not invoked when waiting for server to load the next segment of data\n if (!this.waitingForData && dataViewMetadata && dataViewMetadata.segment) {\n this.hostServices.loadMoreData();\n this.waitingForData = true;\n }\n };\n Slicer.prototype.onClearSelection = function () {\n if (this.interactivityService) {\n this.interactivityService.clearSelection();\n // calls render so that default behavior can be applied after clear selection.\n this.render(false /* resetScrollbarPosition */);\n }\n };\n Slicer.prototype.render = function (resetScrollbarPosition, stopWaitingForData) {\n var localizedSelectAllText = this.hostServices.getLocalizedString(DisplayNameKeys.SelectAll);\n this.slicerData = visuals.DataConversion.convert(this.dataView, localizedSelectAllText, this.interactivityService, this.hostServices);\n if (this.slicerData) {\n this.slicerData.slicerSettings.general.outlineWeight = Math.max(this.slicerData.slicerSettings.general.outlineWeight, 0);\n this.settings = this.slicerData.slicerSettings;\n // TODO: Do we need to check SettingsHelper.areSettingsDefined(), etc. here? Can we just do value validation and coercion in the same place that we create the slicerSettings?\n var slicerOrientation_1 = SettingsHelper.areSettingsDefined(this.slicerData) && this.slicerData.slicerSettings.general && this.slicerData.slicerSettings.general.orientation ?\n this.slicerData.slicerSettings.general.orientation : Slicer.DefaultStyleProperties().general.orientation;\n var orientationHasChanged = this.orientationHasChanged(slicerOrientation_1);\n if (orientationHasChanged) {\n this.slicerOrientation = slicerOrientation_1;\n // Clear the previous slicer type when rendering the new slicer type\n this.element.empty();\n this.initializeSlicerRenderer(slicerOrientation_1);\n }\n }\n this.slicerRenderer.render({ dataView: this.dataView, data: this.slicerData, viewport: this.currentViewport, resetScrollbarPosition: resetScrollbarPosition });\n if (stopWaitingForData)\n this.waitingForData = false;\n };\n Slicer.prototype.orientationHasChanged = function (slicerOrientation) {\n return this.slicerOrientation !== slicerOrientation;\n };\n Slicer.prototype.initializeSlicerRenderer = function (slicerOrientation) {\n switch (slicerOrientation) {\n case 1 /* Horizontal */:\n this.initializeHorizontalSlicer();\n break;\n case 0 /* Vertical */:\n this.initializeVerticalSlicer();\n break;\n }\n };\n Slicer.prototype.initializeVerticalSlicer = function () {\n var verticalSlicerRenderer = this.slicerRenderer = new visuals.VerticalSlicerRenderer({ domHelper: this.domHelper, behavior: this.behavior });\n var options = this.createInitOptions();\n this.interactivityService = verticalSlicerRenderer.init(options);\n };\n Slicer.prototype.initializeHorizontalSlicer = function () {\n var horizontalSlicerRenderer = this.slicerRenderer = new visuals.HorizontalSlicerRenderer({ domHelper: this.domHelper, behavior: this.behavior });\n var options = this.createInitOptions();\n this.interactivityService = horizontalSlicerRenderer.init(options);\n };\n Slicer.prototype.createInitOptions = function () {\n var _this = this;\n return {\n visualInitOptions: this.initOptions,\n loadMoreData: function () { return _this.loadMoreData(); }\n };\n };\n return Slicer;\n }());\n visuals.Slicer = Slicer;\n /** Helper class for calculating the current slicer settings. */\n var ObjectEnumerator;\n (function (ObjectEnumerator) {\n function enumerateObjectInstances(options, data, settings, dataView) {\n if (!data)\n return;\n switch (options.objectName) {\n case 'items':\n return enumerateItems(data, settings);\n case 'header':\n return enumerateHeader(data, settings);\n case 'general':\n return enumerateGeneral(data, settings);\n case 'selection':\n if (shouldShowSelectionOption(dataView))\n return enumerateSelection(data, settings);\n }\n }\n ObjectEnumerator.enumerateObjectInstances = enumerateObjectInstances;\n function shouldShowSelectionOption(dataView) {\n return !(dataView &&\n dataView.metadata &&\n dataView.metadata.columns &&\n _.some(dataView.metadata.columns, function (column) { return column.discourageAggregationAcrossGroups; }));\n }\n function enumerateSelection(data, settings) {\n var slicerSettings = settings;\n var areSelectionSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.selection;\n var selectAllCheckboxEnabled = areSelectionSettingsDefined && data.slicerSettings.selection.selectAllCheckboxEnabled ?\n data.slicerSettings.selection.selectAllCheckboxEnabled : slicerSettings.selection.selectAllCheckboxEnabled;\n var singleSelect = data && data.slicerSettings && data.slicerSettings.selection && data.slicerSettings.selection.singleSelect !== undefined ?\n data.slicerSettings.selection.singleSelect : slicerSettings.selection.singleSelect;\n return [{\n selector: null,\n objectName: 'selection',\n properties: {\n selectAllCheckboxEnabled: selectAllCheckboxEnabled,\n singleSelect: singleSelect,\n }\n }];\n }\n function enumerateHeader(data, settings) {\n var slicerSettings = settings;\n var areHeaderSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.header;\n var fontColor = areHeaderSettingsDefined && data.slicerSettings.header.fontColor ?\n data.slicerSettings.header.fontColor : slicerSettings.header.fontColor;\n var background = areHeaderSettingsDefined && data.slicerSettings.header.background ?\n data.slicerSettings.header.background : slicerSettings.header.background;\n return [{\n selector: null,\n objectName: 'header',\n properties: {\n show: slicerSettings.header.show,\n fontColor: fontColor,\n background: background,\n outline: slicerSettings.header.outline,\n textSize: slicerSettings.header.textSize,\n }\n }];\n }\n function enumerateItems(data, settings) {\n var slicerSettings = settings;\n var areTextSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.slicerText;\n var fontColor = areTextSettingsDefined && data.slicerSettings.slicerText.color ?\n data.slicerSettings.slicerText.color : slicerSettings.slicerText.color;\n var background = areTextSettingsDefined && data.slicerSettings.slicerText.background ?\n data.slicerSettings.slicerText.background : slicerSettings.slicerText.background;\n return [{\n selector: null,\n objectName: 'items',\n properties: {\n fontColor: fontColor,\n background: background,\n outline: slicerSettings.slicerText.outline,\n textSize: slicerSettings.slicerText.textSize,\n }\n }];\n }\n function enumerateGeneral(data, settings) {\n var slicerSettings = settings;\n var areGeneralSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.general != null;\n var outlineColor = areGeneralSettingsDefined && data.slicerSettings.general.outlineColor ?\n data.slicerSettings.general.outlineColor : slicerSettings.general.outlineColor;\n var outlineWeight = areGeneralSettingsDefined && data.slicerSettings.general.outlineWeight ?\n data.slicerSettings.general.outlineWeight : slicerSettings.general.outlineWeight;\n var orientation = areGeneralSettingsDefined && data.slicerSettings.general.orientation != null ?\n data.slicerSettings.general.orientation : slicerSettings.general.orientation;\n return [{\n selector: null,\n objectName: 'general',\n properties: {\n outlineColor: outlineColor,\n outlineWeight: outlineWeight,\n orientation: orientation,\n }\n }];\n }\n })(ObjectEnumerator || (ObjectEnumerator = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var TablixUtils = visuals.controls.internal.TablixUtils;\n var TablixObjects = visuals.controls.internal.TablixObjects;\n var TableHierarchyNavigator = (function () {\n function TableHierarchyNavigator(tableDataView, formatter) {\n debug.assertValue(tableDataView, 'tableDataView');\n debug.assertValue(formatter, 'formatter');\n this.tableDataView = tableDataView;\n this.formatter = formatter;\n }\n /**\n * Returns the depth of the Columnm hierarchy.\n */\n TableHierarchyNavigator.prototype.getColumnHierarchyDepth = function () {\n return 1;\n };\n /**\n * Returns the depth of the Row hierarchy.\n */\n TableHierarchyNavigator.prototype.getRowHierarchyDepth = function () {\n return 1;\n };\n /**\n * Returns the leaf count of a hierarchy.\n */\n TableHierarchyNavigator.prototype.getLeafCount = function (hierarchy) {\n return hierarchy.length;\n };\n /**\n * Returns the leaf member of a hierarchy at a specified index.\n */\n TableHierarchyNavigator.prototype.getLeafAt = function (hierarchy, index) {\n return hierarchy[index];\n };\n /**\n * Returns the specified hierarchy member parent.\n */\n TableHierarchyNavigator.prototype.getParent = function (item) {\n return null;\n };\n /**\n * Returns the index of the hierarchy member relative to its parent.\n */\n TableHierarchyNavigator.prototype.getIndex = function (item) {\n if (!item)\n return -1;\n if (this.isRow(item))\n return item.index;\n return this.getColumnIndex(item);\n };\n TableHierarchyNavigator.prototype.isRow = function (item) {\n if (!item)\n return false;\n var row = item;\n return row.index !== undefined && row.values !== undefined;\n };\n TableHierarchyNavigator.prototype.getColumnIndex = function (item) {\n return TableHierarchyNavigator.getIndex(this.tableDataView.columns, item);\n };\n /**\n * Checks whether a hierarchy member is a leaf.\n */\n TableHierarchyNavigator.prototype.isLeaf = function (item) {\n return true;\n };\n TableHierarchyNavigator.prototype.isRowHierarchyLeaf = function (cornerItem) {\n return false;\n };\n TableHierarchyNavigator.prototype.isColumnHierarchyLeaf = function (cornerItem) {\n return true;\n };\n TableHierarchyNavigator.prototype.isFirstItem = function (item, items) {\n // checking for item.index is unreliable because reordering the columns would cause a mismatch between index and items order\n return item === items[0];\n };\n TableHierarchyNavigator.prototype.areAllParentsFirst = function (item, items) {\n return this.isFirstItem(item, items);\n };\n /**\n * Checks whether a hierarchy member is the last item within its parent.\n */\n TableHierarchyNavigator.prototype.isLastItem = function (item, items) {\n debug.assertValue(item, 'item');\n return items[items.length - 1] === item;\n };\n TableHierarchyNavigator.prototype.areAllParentsLast = function (item, items) {\n return this.isLastItem(item, items);\n };\n /**\n * Gets the children members of a hierarchy member.\n */\n TableHierarchyNavigator.prototype.getChildren = function (item) {\n return null;\n };\n TableHierarchyNavigator.prototype.getChildrenLevelDifference = function (item) {\n return Infinity;\n };\n /**\n * Gets the members count in a specified collection.\n */\n TableHierarchyNavigator.prototype.getCount = function (items) {\n return items.length;\n };\n /**\n * Gets the member at the specified index.\n */\n TableHierarchyNavigator.prototype.getAt = function (items, index) {\n return items[index];\n };\n /**\n * Gets the hierarchy member level.\n */\n TableHierarchyNavigator.prototype.getLevel = function (item) {\n return 0;\n };\n /**\n * Returns the intersection between a row and a column item.\n */\n TableHierarchyNavigator.prototype.getIntersection = function (rowItem, columnItem) {\n var value;\n var isTotal = false;\n var position = new TablixUtils.CellPosition();\n var columnIndex = TableHierarchyNavigator.getIndex(this.tableDataView.columns, columnItem);\n ;\n position.column.index = columnIndex;\n position.column.isFirst = columnIndex === 0 ? true : false;\n position.column.isLast = columnIndex === this.tableDataView.columns.length - 1;\n var totalRow = rowItem;\n if (totalRow.totalCells != null) {\n isTotal = true;\n value = totalRow.totalCells[columnIndex];\n }\n else {\n var row = rowItem;\n var rowIndex = row.index;\n position.row.index = rowIndex;\n position.row.isFirst = rowIndex === 0;\n position.row.isLast = rowIndex === this.tableDataView.rows.length - 1;\n value = row.values[columnIndex];\n }\n var cellItem = new TablixUtils.TablixVisualCell(value, isTotal, columnItem, this.formatter);\n cellItem.position = position;\n var tableRow = rowItem;\n if (tableRow && tableRow.values) {\n var rowObjects = tableRow.values.objects;\n if (rowObjects) {\n var cellObject = rowObjects[columnIndex];\n if (cellObject) {\n cellItem.backColor = TablixObjects.PropValuesBackColor.getValue(cellObject);\n }\n }\n }\n return cellItem;\n };\n /**\n * Returns the corner cell between a row and a column level.\n */\n TableHierarchyNavigator.prototype.getCorner = function (rowLevel, columnLevel) {\n return null;\n };\n TableHierarchyNavigator.prototype.headerItemEquals = function (item1, item2) {\n if (item1 === item2)\n return true;\n // Typechecking does not work with interfaces nor at runtime. We need to explicitly check for\n // properties of DataViewMetadataColumn to determine if we can use the column equivalency check.\n // We expect this method to handle either VisualTableRows or DataViewMetadataColumns so checking\n // for displayName should be sufficient.\n if (item1.displayName && item2.displayName) {\n var column1 = item1;\n var column2 = item2;\n return powerbi.DataViewAnalysis.areMetadataColumnsEquivalent(column1, column2);\n }\n if (this.isRow(item1) && this.isRow(item2))\n return item1.index === item2.index;\n return false;\n };\n TableHierarchyNavigator.prototype.bodyCellItemEquals = function (item1, item2) {\n //return (item1.dataPoint === item2.dataPoint);\n return (item1.isMatch(item2));\n };\n TableHierarchyNavigator.prototype.cornerCellItemEquals = function (item1, item2) {\n // Should not be called as we don't return any corner items for table\n return true;\n };\n TableHierarchyNavigator.prototype.update = function (table) {\n this.tableDataView = table;\n };\n TableHierarchyNavigator.getIndex = function (items, item) {\n for (var index = 0, len = items.length; index < len; index++) {\n // For cases when the item was re-created during the DataTransformation phase,\n // we check for the item's index to verify equality.\n var arrayItem = items[index];\n if (arrayItem.index != null && item.index != null && arrayItem.index === item.index) {\n return index;\n }\n else {\n if (item === items[index])\n return index;\n }\n }\n return -1;\n };\n return TableHierarchyNavigator;\n }());\n visuals.TableHierarchyNavigator = TableHierarchyNavigator;\n /**\n * Note: Public for testability.\n */\n var TableBinder = (function () {\n function TableBinder(options) {\n this.options = options;\n }\n TableBinder.prototype.onDataViewChanged = function (dataView) {\n this.tableDataView = dataView;\n this.formattingProperties = dataView.formattingProperties;\n this.updateTextHeights();\n };\n TableBinder.prototype.updateTextHeights = function () {\n var textProps = {\n fontFamily: '',\n fontSize: TablixObjects.getTextSizeInPx(this.formattingProperties.general.textSize),\n text: 'a',\n };\n textProps.fontFamily = TablixUtils.FontFamilyHeader;\n this.textHeightHeader = Math.ceil(powerbi.TextMeasurementService.measureSvgTextHeight(textProps));\n textProps.fontFamily = TablixUtils.FontFamilyCell;\n this.textHeightValue = Math.ceil(powerbi.TextMeasurementService.measureSvgTextHeight(textProps));\n textProps.fontFamily = TablixUtils.FontFamilyTotal;\n this.textHeightTotal = Math.ceil(powerbi.TextMeasurementService.measureSvgTextHeight(textProps));\n };\n TableBinder.prototype.onStartRenderingSession = function () {\n };\n TableBinder.prototype.onEndRenderingSession = function () {\n };\n /**\n * Row Header.\n */\n TableBinder.prototype.bindRowHeader = function (item, cell) {\n cell.contentHeight = this.textHeightValue;\n // To clear the CSS classes that adds paddings\n TablixUtils.clearCellStyle(cell);\n if (this.options.onBindRowHeader)\n this.options.onBindRowHeader(item);\n };\n TableBinder.prototype.unbindRowHeader = function (item, cell) {\n };\n /**\n * Column Header.\n */\n TableBinder.prototype.bindColumnHeader = function (item, cell) {\n var _this = this;\n cell.extension.disableDragResize();\n TablixUtils.resetCellCssClass(cell);\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixHeader);\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixColumnHeaderLeaf);\n var cellStyle = new TablixUtils.CellStyle();\n // Set default style\n cellStyle.fontFamily = TablixUtils.FontFamilyHeader;\n cellStyle.fontColor = TablixUtils.FontColorHeaders;\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\n cell.contentHeight = this.textHeightHeader;\n if (this.sortIconsEnabled())\n TablixUtils.createColumnHeaderWithSortIcon(item, cell);\n else\n TablixUtils.setCellTextAndTooltip(cell, item.displayName);\n if (this.options.onColumnHeaderClick) {\n var handler = function (e) {\n if (TablixUtils.isValidSortClick(e)) {\n var sortDirection = TablixUtils.reverseSort(item.sort);\n _this.options.onColumnHeaderClick(item.queryName ? item.queryName : item.displayName, sortDirection);\n }\n };\n cell.extension.registerClickHandler(handler);\n }\n this.setColumnHeaderStyle(cell, cellStyle);\n cell.applyStyle(cellStyle);\n };\n TableBinder.prototype.setColumnHeaderStyle = function (cell, style) {\n var propsGrid = this.formattingProperties.grid;\n var props = this.formattingProperties.columnHeaders;\n var propsTotal = this.formattingProperties.total;\n var propsValues = this.formattingProperties.values;\n style.borders.top = new TablixUtils.EdgeSettings();\n style.borders.top.applyParams(visuals.outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n style.borders.bottom = new TablixUtils.EdgeSettings();\n style.borders.bottom.applyParams(visuals.outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n style.borders.left = new TablixUtils.EdgeSettings();\n if (cell.position.column.isFirst) {\n style.borders.left.applyParams(visuals.outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have left border, but Footer or Body has, we need to apply extra padding\n if (!visuals.outline.showLeft(props.outline) && (visuals.outline.showLeft(propsTotal.outline) || visuals.outline.showLeft(propsValues.outline)))\n style.paddings.left += propsGrid.outlineWeight;\n } // else: do nothing\n style.borders.right = new TablixUtils.EdgeSettings();\n if (cell.position.column.isLast) {\n style.borders.right.applyParams(visuals.outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have right border, but Footer or Body has, we need to apply extra padding\n if (!visuals.outline.showRight(props.outline) && (visuals.outline.showRight(propsTotal.outline) || visuals.outline.showRight(propsValues.outline)))\n style.paddings.right += propsGrid.outlineWeight;\n }\n else {\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\n }\n style.fontColor = props.fontColor;\n style.backColor = props.backColor;\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\n };\n TableBinder.prototype.unbindColumnHeader = function (item, cell) {\n TablixUtils.clearCellStyle(cell);\n TablixUtils.clearCellTextAndTooltip(cell);\n if (this.sortIconsEnabled())\n TablixUtils.removeSortIcons(cell);\n if (this.options.onColumnHeaderClick) {\n cell.extension.unregisterClickHandler();\n }\n };\n /**\n * Body Cell.\n */\n TableBinder.prototype.bindBodyCell = function (item, cell) {\n TablixUtils.resetCellCssClass(cell);\n var imgHeight;\n imgHeight = this.formattingProperties.grid.imageHeight;\n var cellStyle = new TablixUtils.CellStyle();\n if (item.isImage) {\n cell.contentHeight = imgHeight;\n }\n else {\n cell.contentHeight = this.textHeightValue;\n }\n if (item.isUrl && item.isValidUrl) {\n TablixUtils.appendATagToBodyCell(item.textContent, cell, this.formattingProperties.values.urlIcon);\n }\n else if (item.isImage && item.isValidUrl) {\n TablixUtils.appendImgTagToBodyCell(item.textContent, cell, imgHeight);\n cellStyle.hasImage = true;\n }\n else if (item.domContent) {\n $(cell.extension.contentHost).append(item.domContent);\n }\n else if (item.textContent) {\n TablixUtils.setCellTextAndTooltip(cell, item.textContent);\n }\n else {\n TablixUtils.setCellTextAndTooltip(cell, \" \");\n }\n if (item.isTotal) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueTotal);\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTableFooter);\n cellStyle.fontFamily = TablixUtils.FontFamilyTotal;\n cellStyle.borders.top = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\n cell.contentHeight = this.textHeightTotal;\n }\n else if (item.position.row.isLast) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTableBodyCellBottom);\n }\n else {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTableBodyCell);\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridHorizontalWeight.defaultValue, TablixObjects.PropGridHorizontalColor.defaultValue);\n }\n if (item.isNumeric)\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueNumeric);\n if (item.isTotal)\n this.setFooterStyle(cell, cellStyle);\n else\n this.setBodyStyle(item, cell, cellStyle);\n cell.applyStyle(cellStyle);\n };\n TableBinder.prototype.setBodyStyle = function (item, cell, style) {\n var propsGrid = this.formattingProperties.grid;\n var props = this.formattingProperties.values;\n var propsTotal = this.formattingProperties.total;\n var propsColumns = this.formattingProperties.columnHeaders;\n style.borders.top = new TablixUtils.EdgeSettings();\n if (cell.position.row.isFirst) {\n style.borders.top.applyParams(visuals.outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n } // else: do nothing\n style.borders.bottom = new TablixUtils.EdgeSettings();\n if (cell.position.row.isLast) {\n style.borders.bottom.applyParams(visuals.outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n }\n else {\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\n }\n style.borders.left = new TablixUtils.EdgeSettings();\n if (cell.position.column.isFirst) {\n style.borders.left.applyParams(visuals.outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have left border, but Footer or Header has, we need to apply extra padding\n if (!visuals.outline.showLeft(props.outline) && (visuals.outline.showLeft(propsTotal.outline) || visuals.outline.showLeft(propsColumns.outline)))\n style.paddings.left += propsGrid.outlineWeight;\n } // else: do nothing\n style.borders.right = new TablixUtils.EdgeSettings();\n if (cell.position.column.isLast) {\n style.borders.right.applyParams(visuals.outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have right border, but Footer has, we need to apply extra padding\n if (!visuals.outline.showRight(props.outline) && (visuals.outline.showRight(propsTotal.outline) || visuals.outline.showRight(propsColumns.outline)))\n style.paddings.right += propsGrid.outlineWeight;\n }\n else {\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\n }\n style.fontColor = cell.position.row.index % 2 === 0 ? props.fontColorPrimary : props.fontColorSecondary;\n // Conditional formatting on the cell overrides primary/secondary background colors.\n if (item.backColor)\n style.backColor = item.backColor;\n else\n style.backColor = cell.position.row.index % 2 === 0 ? props.backColorPrimary : props.backColorSecondary;\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\n };\n TableBinder.prototype.setFooterStyle = function (cell, style) {\n var props = this.formattingProperties.total;\n var propsGrid = this.formattingProperties.grid;\n var propsValues = this.formattingProperties.values;\n var propsColumns = this.formattingProperties.columnHeaders;\n style.borders.top = new TablixUtils.EdgeSettings();\n style.borders.top.applyParams(visuals.outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n style.borders.bottom = new TablixUtils.EdgeSettings();\n style.borders.bottom.applyParams(visuals.outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n style.borders.left = new TablixUtils.EdgeSettings();\n if (cell.position.column.isFirst) {\n style.borders.left.applyParams(visuals.outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have left border, but values or column headers have, we need to apply padding\n if (!visuals.outline.showLeft(props.outline) && (visuals.outline.showLeft(propsValues.outline) || visuals.outline.showLeft(propsColumns.outline)))\n style.paddings.left += propsGrid.outlineWeight;\n } // else: do nothing\n style.borders.right = new TablixUtils.EdgeSettings();\n if (cell.position.column.isLast) {\n style.borders.right.applyParams(visuals.outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have left border, but values or column headers have, we need to apply padding\n if (!visuals.outline.showRight(props.outline) && (visuals.outline.showRight(propsValues.outline) || visuals.outline.showRight(propsColumns.outline)))\n style.paddings.right += propsGrid.outlineWeight;\n }\n else {\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\n }\n style.fontColor = props.fontColor;\n style.backColor = props.backColor;\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\n };\n TableBinder.prototype.unbindBodyCell = function (item, cell) {\n TablixUtils.clearCellStyle(cell);\n TablixUtils.clearCellTextAndTooltip(cell);\n };\n /**\n * Corner Cell.\n */\n TableBinder.prototype.bindCornerCell = function (item, cell) {\n };\n TableBinder.prototype.unbindCornerCell = function (item, cell) {\n };\n TableBinder.prototype.bindEmptySpaceHeaderCell = function (cell) {\n // Not needed for Table\n };\n TableBinder.prototype.unbindEmptySpaceHeaderCell = function (cell) {\n // Not needed for Table\n };\n TableBinder.prototype.bindEmptySpaceFooterCell = function (cell) {\n // Not needed for Table\n };\n TableBinder.prototype.unbindEmptySpaceFooterCell = function (cell) {\n // Not needed for Table\n };\n /**\n * Measurement Helper.\n */\n TableBinder.prototype.getHeaderLabel = function (item) {\n return item.displayName;\n };\n TableBinder.prototype.getCellContent = function (item) {\n return item;\n };\n TableBinder.prototype.hasRowGroups = function () {\n return false;\n };\n TableBinder.prototype.sortIconsEnabled = function () {\n return this.options.layoutKind === 0 /* Canvas */;\n };\n return TableBinder;\n }());\n visuals.TableBinder = TableBinder;\n var Table = (function () {\n function Table(options) {\n if (options) {\n this.isConditionalFormattingEnabled = options.isConditionalFormattingEnabled;\n this.isTouchEnabled = options.isTouchEnabled;\n }\n }\n Table.customizeQuery = function (options) {\n var dataViewMapping = options.dataViewMappings[0];\n if (!dataViewMapping || !dataViewMapping.table || !dataViewMapping.metadata)\n return;\n var dataViewTableRows = dataViewMapping.table.rows;\n var objects = dataViewMapping.metadata.objects;\n dataViewTableRows.for.in.subtotalType = TablixObjects.shouldShowTableTotals(objects) ? 1 /* Before */ : 0 /* None */;\n };\n Table.getSortableRoles = function () {\n return ['Values'];\n };\n Table.prototype.init = function (options) {\n this.element = options.element;\n this.style = options.style;\n this.updateViewport(options.viewport);\n this.formatter = visuals.valueFormatter.formatValueColumn;\n this.isInteractive = options.interactivity && options.interactivity.selection != null;\n this.getLocalizedString = options.host.getLocalizedString;\n this.hostServices = options.host;\n this.persistingObjects = false;\n this.waitingForData = false;\n this.lastAllowHeaderResize = true;\n this.waitingForSort = false;\n };\n /**\n * Note: Public for testability.\n */\n Table.converter = function (dataView) {\n var table = dataView.table;\n debug.assertValue(table, 'table');\n debug.assertValue(table.rows, 'table.rows');\n var visualTable = powerbi.Prototype.inherit(table);\n visualTable.visualRows = [];\n for (var i = 0; i < table.rows.length; i++) {\n var visualRow = {\n index: i,\n values: table.rows[i]\n };\n visualTable.visualRows.push(visualRow);\n }\n visualTable.formattingProperties = TablixObjects.getTableObjects(dataView);\n return visualTable;\n };\n Table.prototype.onResizing = function (finalViewport) {\n this.updateViewport(finalViewport);\n };\n // Public for testability\n Table.prototype.getColumnWidthManager = function () {\n return this.columnWidthManager;\n };\n Table.prototype.onDataChanged = function (options) {\n debug.assertValue(options, 'options');\n var dataViews = options.dataViews;\n if (dataViews && dataViews.length > 0) {\n var previousDataView = this.dataView;\n this.dataView = dataViews[0];\n /* To avoid OnDataChanged being called every time we persist Objects. If:\n * AutoSizeColumns options was flipped\n * A Column was resized manually\n * A Column was auto-sized\n */\n if (this.persistingObjects) {\n this.persistingObjects = false;\n return;\n }\n var visualTable = Table.converter(this.dataView);\n var textSize = visualTable.formattingProperties.general.textSize;\n if (options.operationKind === powerbi.VisualDataChangeOperationKind.Append) {\n this.hierarchyNavigator.update(visualTable);\n this.tablixControl.updateModels(/*resetScrollOffsets*/ false, visualTable.visualRows, visualTable.columns);\n this.refreshControl(/*clear*/ false);\n }\n else {\n this.createOrUpdateHierarchyNavigator(visualTable);\n this.createColumnWidthManager();\n this.createTablixControl(textSize);\n var binder = this.tablixControl.getBinder();\n binder.onDataViewChanged(visualTable);\n this.updateInternal(textSize, previousDataView, visualTable);\n }\n }\n this.waitingForData = false;\n this.waitingForSort = false;\n };\n Table.prototype.createColumnWidthManager = function () {\n var _this = this;\n if (!this.columnWidthManager) {\n this.columnWidthManager = new visuals.controls.TablixColumnWidthManager(this.dataView, false /* isMatrix */, function (objectInstances) { return _this.persistColumnWidths(objectInstances); });\n }\n else {\n this.columnWidthManager.updateDataView(this.dataView);\n }\n };\n Table.prototype.persistColumnWidths = function (objectInstances) {\n this.persistingObjects = true;\n this.hostServices.persistProperties(objectInstances);\n };\n Table.prototype.updateViewport = function (newViewport) {\n this.currentViewport = newViewport;\n if (this.tablixControl) {\n this.tablixControl.viewport = this.currentViewport;\n this.verifyHeaderResize();\n this.refreshControl(false);\n }\n };\n Table.prototype.refreshControl = function (clear) {\n if (visuals.visibilityHelper.partiallyVisible(this.element) || this.getLayoutKind() === 1 /* DashboardTile */) {\n this.tablixControl.refresh(clear);\n }\n };\n Table.prototype.getLayoutKind = function () {\n return this.isInteractive ? 0 /* Canvas */ : 1 /* DashboardTile */;\n };\n Table.prototype.createOrUpdateHierarchyNavigator = function (visualTable) {\n if (!this.tablixControl) {\n var dataNavigator = new TableHierarchyNavigator(visualTable, this.formatter);\n this.hierarchyNavigator = dataNavigator;\n }\n else {\n this.hierarchyNavigator.update(visualTable);\n }\n };\n Table.prototype.createTablixControl = function (textSize) {\n if (!this.tablixControl) {\n // Create the control\n this.tablixControl = this.createControl(this.hierarchyNavigator, textSize);\n }\n };\n Table.prototype.createControl = function (dataNavigator, textSize) {\n var _this = this;\n var layoutKind = this.getLayoutKind();\n var tableBinderOptions = {\n onBindRowHeader: function (item) { return _this.onBindRowHeader(item); },\n onColumnHeaderClick: function (queryName, sortDirection) { return _this.onColumnHeaderClick(queryName, sortDirection); },\n layoutKind: layoutKind\n };\n var tableBinder = new TableBinder(tableBinderOptions);\n var layoutManager = layoutKind === 1 /* DashboardTile */\n ? visuals.controls.internal.DashboardTablixLayoutManager.createLayoutManager(tableBinder)\n : visuals.controls.internal.CanvasTablixLayoutManager.createLayoutManager(tableBinder, this.columnWidthManager);\n // Create Host element\n var tablixContainer = document.createElement('div');\n this.element.append(tablixContainer);\n var tablixOptions = {\n interactive: this.isInteractive,\n enableTouchSupport: this.isTouchEnabled,\n layoutKind: layoutKind,\n fontSize: TablixObjects.getTextSizeInPx(textSize),\n };\n return new visuals.controls.TablixControl(dataNavigator, layoutManager, tableBinder, tablixContainer, tablixOptions);\n };\n Table.prototype.updateInternal = function (textSize, previousDataView, visualTable) {\n var _this = this;\n if (this.getLayoutKind() === 1 /* DashboardTile */) {\n this.tablixControl.layoutManager.adjustContentSize(visuals.converterHelper.hasImageUrlColumn(this.dataView));\n }\n this.tablixControl.fontSize = TablixObjects.getTextSizeInPx(textSize);\n this.verifyHeaderResize();\n // Update models before the viewport to make sure column widths are computed correctly\n this.tablixControl.updateModels(/*resetScrollOffsets*/ true, visualTable.visualRows, visualTable.columns);\n var totals = this.createTotalsRow(this.dataView);\n this.tablixControl.rowDimension.setFooter(totals);\n this.tablixControl.viewport = this.currentViewport;\n var shouldClearControl = this.shouldClearControl(previousDataView, this.dataView);\n // Render\n // We need the layout for the DIV to be done so that the control can measure items correctly.\n setTimeout(function () {\n // Render\n _this.refreshControl(shouldClearControl);\n //Persist actual widths if autoSize flipped to true\n if (_this.columnWidthManager.shouldPersistAllColumnWidths()) {\n _this.columnWidthManager.persistAllColumnWidths(_this.tablixControl.layoutManager.columnWidthsToPersist);\n }\n }, 0);\n };\n Table.prototype.shouldClearControl = function (previousDataView, newDataView) {\n if (!this.waitingForSort || !previousDataView || !newDataView)\n return true;\n return !powerbi.DataViewAnalysis.isMetadataEquivalent(previousDataView.metadata, newDataView.metadata);\n };\n Table.prototype.createTotalsRow = function (dataView) {\n if (!TablixObjects.shouldShowTableTotals(dataView.metadata.objects))\n return null;\n var totals = dataView.table.totals;\n if (!totals || totals.length === 0)\n return null;\n var totalRow = [];\n var columns = dataView.table.columns;\n // Add totals for measure columns, blank for non-measure columns unless it's the first column\n for (var i = 0, len = columns.length; i < len; ++i) {\n var column = columns[i];\n var totalValue = totals[column.index];\n if (totalValue != null) {\n totalRow.push(totalValue);\n }\n else {\n // If the first column is a non-measure column, we put 'Total' as the text similar to PV.\n // Note that if the first column is a measure column we don't render any Total text at\n // all, once again similar to PV.\n totalRow.push((i === 0) ? this.getLocalizedString('TableTotalLabel') : '');\n }\n }\n return { totalCells: totalRow };\n };\n Table.prototype.onBindRowHeader = function (item) {\n if (this.needsMoreData(item)) {\n this.hostServices.loadMoreData();\n this.waitingForData = true;\n }\n };\n Table.prototype.onColumnHeaderClick = function (queryName, sortDirection) {\n this.waitingForSort = true;\n this.hostServices.onCustomSort(TablixUtils.getCustomSortEventArgs(queryName, sortDirection));\n };\n /**\n * Note: Public for testability.\n */\n Table.prototype.needsMoreData = function (item) {\n if (this.waitingForData || !this.dataView.metadata || !this.dataView.metadata.segment)\n return false;\n var leafCount = this.tablixControl.rowDimension.getItemsCount();\n var loadMoreThreshold = leafCount * Table.preferredLoadMoreThreshold;\n return this.hierarchyNavigator.getIndex(item) >= loadMoreThreshold;\n };\n Table.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n // Visuals are initialized with an empty data view before queries are run, therefore we need to make sure that\n // we are resilient here when we do not have data view.\n if (this.dataView) {\n TablixObjects.enumerateObjectInstances(options, enumeration, this.dataView, visuals.controls.TablixType.Table);\n }\n return enumeration.complete();\n };\n Table.prototype.enumerateObjectRepetition = function () {\n var enumeration = [];\n // Visuals are initialized with an empty data view before queries are run, therefore we need to make sure that\n // we are resilient here when we do not have data view.\n if (this.isConditionalFormattingEnabled && this.dataView) {\n TablixObjects.enumerateObjectRepetition(enumeration, this.dataView, visuals.controls.TablixType.Table);\n }\n return enumeration;\n };\n Table.prototype.shouldAllowHeaderResize = function () {\n return this.hostServices.getViewMode() === 1 /* Edit */;\n };\n Table.prototype.onViewModeChanged = function (viewMode) {\n /* Refreshes the column headers to enable/disable Column resizing */\n this.updateViewport(this.currentViewport);\n };\n Table.prototype.verifyHeaderResize = function () {\n var currentAllowHeaderResize = this.shouldAllowHeaderResize();\n if (currentAllowHeaderResize !== this.lastAllowHeaderResize) {\n this.lastAllowHeaderResize = currentAllowHeaderResize;\n this.tablixControl.layoutManager.setAllowHeaderResize(currentAllowHeaderResize);\n }\n };\n Table.preferredLoadMoreThreshold = 0.8;\n return Table;\n }());\n visuals.Table = Table;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var TablixUtils = visuals.controls.internal.TablixUtils;\n var TablixObjects = visuals.controls.internal.TablixObjects;\n var UrlUtils = jsCommon.UrlUtils;\n var MatrixVisualBodyItem = (function (_super) {\n __extends(MatrixVisualBodyItem, _super);\n function MatrixVisualBodyItem() {\n _super.apply(this, arguments);\n }\n Object.defineProperty(MatrixVisualBodyItem.prototype, \"isMeasure\", {\n get: function () {\n return true;\n },\n enumerable: true,\n configurable: true\n });\n ;\n Object.defineProperty(MatrixVisualBodyItem.prototype, \"isValidUrl\", {\n get: function () {\n return false;\n },\n enumerable: true,\n configurable: true\n });\n ;\n Object.defineProperty(MatrixVisualBodyItem.prototype, \"isValidImage\", {\n get: function () {\n return false;\n },\n enumerable: true,\n configurable: true\n });\n ;\n return MatrixVisualBodyItem;\n }(TablixUtils.TablixVisualCell));\n visuals.MatrixVisualBodyItem = MatrixVisualBodyItem;\n /**\n * Factory method used by unit tests.\n */\n function createMatrixHierarchyNavigator(matrix, formatter) {\n return new MatrixHierarchyNavigator(matrix, formatter);\n }\n visuals.createMatrixHierarchyNavigator = createMatrixHierarchyNavigator;\n var MatrixHierarchyNavigator = (function () {\n function MatrixHierarchyNavigator(matrix, formatter) {\n this.matrix = matrix;\n this.rowHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(matrix.rows);\n this.columnHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(matrix.columns);\n this.formatter = formatter;\n this.update();\n }\n /**\n * Returns the data view matrix.\n */\n MatrixHierarchyNavigator.prototype.getDataViewMatrix = function () {\n return this.matrix;\n };\n /**\n * Returns the depth of the column hierarchy.\n */\n MatrixHierarchyNavigator.prototype.getColumnHierarchyDepth = function () {\n return Math.max(this.columnHierarchy.levels.length, 1);\n };\n /**\n * Returns the depth of the Row hierarchy.\n */\n MatrixHierarchyNavigator.prototype.getRowHierarchyDepth = function () {\n return Math.max(this.rowHierarchy.levels.length, 1);\n };\n /**\n * Returns the leaf count of a hierarchy.\n */\n MatrixHierarchyNavigator.prototype.getLeafCount = function (hierarchy) {\n var matrixHierarchy = this.getMatrixHierarchy(hierarchy);\n if (matrixHierarchy)\n return matrixHierarchy.leafNodes.length;\n return 0;\n };\n /**\n * Returns the leaf member of a hierarchy at a specified index.\n */\n MatrixHierarchyNavigator.prototype.getLeafAt = function (hierarchy, index) {\n var matrixHierarchy = this.getMatrixHierarchy(hierarchy);\n if (matrixHierarchy)\n return matrixHierarchy.leafNodes[index];\n return null;\n };\n /**\n * Returns the leaf index of the visual node.\n */\n MatrixHierarchyNavigator.prototype.getLeafIndex = function (item) {\n debug.assertValue(item, 'item');\n return item.leafIndex;\n };\n /**\n * Returns the specified hierarchy member parent.\n */\n MatrixHierarchyNavigator.prototype.getParent = function (item) {\n debug.assertValue(item, 'item');\n // Return null for outermost nodes\n if (item.level === 0)\n return null;\n return item.parent;\n };\n /**\n * Returns the index of the hierarchy member relative to its parent.\n */\n MatrixHierarchyNavigator.prototype.getIndex = function (item) {\n debug.assertValue(item, 'item');\n return item.index;\n };\n /**\n * Checks whether a hierarchy member is a leaf.\n */\n MatrixHierarchyNavigator.prototype.isLeaf = function (item) {\n debug.assertValue(item, 'item');\n return !item.children || item.children.length === 0;\n };\n MatrixHierarchyNavigator.prototype.isRowHierarchyLeaf = function (item) {\n return true;\n };\n MatrixHierarchyNavigator.prototype.isColumnHierarchyLeaf = function (item) {\n return false;\n };\n MatrixHierarchyNavigator.prototype.isFirstItem = function (item, items) {\n return item === _.first(items);\n };\n MatrixHierarchyNavigator.prototype.areAllParentsFirst = function (item, items) {\n if (!item)\n return false;\n var parent = this.getParent(item);\n if (!parent) {\n return this.isFirstItem(item, item.siblings);\n }\n else {\n return this.isFirstItem(item, item.siblings) && this.areAllParentsFirst(parent, parent.siblings);\n }\n };\n /**\n * Checks whether a hierarchy member is the last item within its parent.\n */\n MatrixHierarchyNavigator.prototype.isLastItem = function (item, items) {\n debug.assertValue(item, 'item');\n return item === _.last(items);\n };\n MatrixHierarchyNavigator.prototype.areAllParentsLast = function (item, items) {\n if (!item)\n return false;\n var parent = this.getParent(item);\n if (!parent) {\n return this.isLastItem(item, item.siblings);\n }\n else {\n return this.isLastItem(item, item.siblings) && this.areAllParentsLast(parent, parent.siblings);\n }\n };\n /**\n * Gets the children members of a hierarchy member.\n */\n MatrixHierarchyNavigator.prototype.getChildren = function (item) {\n debug.assertValue(item, 'item');\n return item.children;\n };\n /**\n * Gets the difference between current level and highest child's level. Can be > 1 if there are multiple values\n * @param {MatrixVisualNode} item\n * @returns\n */\n MatrixHierarchyNavigator.prototype.getChildrenLevelDifference = function (item) {\n var diff = Infinity;\n var children = this.getChildren(item);\n for (var i = 0, ilen = children.length; i < ilen; i++) {\n diff = Math.min(diff, children[i].level - item.level);\n }\n return diff;\n };\n /**\n * Gets the members count in a specified collection.\n */\n MatrixHierarchyNavigator.prototype.getCount = function (items) {\n debug.assertValue(items, 'items');\n return items.length;\n };\n /**\n * Gets the member at the specified index.\n */\n MatrixHierarchyNavigator.prototype.getAt = function (items, index) {\n debug.assertValue(items, 'items');\n return items[index];\n };\n /**\n * Gets the hierarchy member level.\n */\n MatrixHierarchyNavigator.prototype.getLevel = function (item) {\n debug.assertValue(item, 'item');\n return item.level;\n };\n /**\n * Returns the intersection between a row and a column item.\n */\n MatrixHierarchyNavigator.prototype.getIntersection = function (rowItem, columnItem) {\n debug.assertValue(rowItem, 'rowItem');\n debug.assertValue(columnItem, 'columnItem');\n var isSubtotalItem = rowItem.isSubtotal === true || columnItem.isSubtotal === true;\n var node;\n var valueSource;\n var rowIndex = rowItem.leafIndex;\n var colIndex = columnItem.leafIndex;\n var bodyCell;\n if (!rowItem.values) {\n node = undefined;\n }\n else {\n node = (rowItem.values[columnItem.leafIndex]);\n }\n if (node) {\n valueSource = this.matrix.valueSources[node.valueSourceIndex || 0];\n bodyCell = new MatrixVisualBodyItem(node.value, isSubtotalItem, valueSource, this.formatter);\n }\n else {\n bodyCell = new MatrixVisualBodyItem(undefined, isSubtotalItem, undefined, this.formatter);\n }\n bodyCell.position.row.index = rowIndex;\n bodyCell.position.row.indexInSiblings = rowItem.siblings.indexOf(rowItem);\n bodyCell.position.row.isFirst = rowIndex === 0;\n bodyCell.position.row.isLast = rowIndex === this.rowHierarchy.leafNodes.length - 1;\n bodyCell.position.column.index = colIndex;\n bodyCell.position.column.indexInSiblings = columnItem.siblings.indexOf(columnItem);\n bodyCell.position.column.isFirst = colIndex === 0;\n bodyCell.position.column.isLast = colIndex === this.columnHierarchy.leafNodes.length - 1;\n return bodyCell;\n };\n /**\n * Returns the corner cell between a row and a column level.\n */\n MatrixHierarchyNavigator.prototype.getCorner = function (rowLevel, columnLevel) {\n debug.assert(rowLevel >= 0, 'rowLevel');\n debug.assert(columnLevel >= 0, 'columnLevel');\n var columnLevels = this.columnHierarchy.levels;\n var rowLevels = this.rowHierarchy.levels;\n if (columnLevel === columnLevels.length - 1 || columnLevels.length === 0) {\n var levelSource = rowLevels[rowLevel];\n if (levelSource)\n return {\n metadata: levelSource.sources[0],\n isColumnHeaderLeaf: true,\n isRowHeaderLeaf: rowLevel === rowLevels.length - 1,\n };\n }\n if (rowLevel === rowLevels.length - 1) {\n var levelSource = columnLevels[columnLevel];\n if (levelSource)\n return {\n metadata: levelSource.sources[0],\n isColumnHeaderLeaf: false,\n isRowHeaderLeaf: true,\n };\n }\n return {\n metadata: null,\n isColumnHeaderLeaf: false,\n isRowHeaderLeaf: false,\n };\n };\n MatrixHierarchyNavigator.prototype.headerItemEquals = function (item1, item2) {\n if (item1 && item2)\n return (item1 === item2);\n else\n return false;\n };\n MatrixHierarchyNavigator.prototype.bodyCellItemEquals = function (item1, item2) {\n return (item1.position.isMatch(item2.position));\n };\n MatrixHierarchyNavigator.prototype.cornerCellItemEquals = function (item1, item2) {\n return item1 === item2;\n };\n MatrixHierarchyNavigator.prototype.getMatrixColumnHierarchy = function () {\n return this.columnHierarchy;\n };\n MatrixHierarchyNavigator.prototype.getMatrixRowHierarchy = function () {\n return this.rowHierarchy;\n };\n /**\n * Implementation for MatrixDataAdapter interface.\n */\n MatrixHierarchyNavigator.prototype.update = function (dataViewMatrix, updateColumns) {\n if (updateColumns === void 0) { updateColumns = true; }\n if (dataViewMatrix) {\n this.matrix = dataViewMatrix;\n this.rowHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(dataViewMatrix.rows);\n if (updateColumns)\n this.columnHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(dataViewMatrix.columns);\n }\n this.updateHierarchy(this.rowHierarchy);\n if (updateColumns) {\n this.updateHierarchy(this.columnHierarchy);\n MatrixHierarchyNavigator.updateStaticColumnHeaders(this.columnHierarchy);\n }\n };\n MatrixHierarchyNavigator.wrapMatrixHierarchy = function (hierarchy) {\n var matrixHierarchy = powerbi.Prototype.inherit(hierarchy);\n matrixHierarchy.leafNodes = [];\n return matrixHierarchy;\n };\n MatrixHierarchyNavigator.prototype.updateHierarchy = function (hierarchy) {\n if (hierarchy.leafNodes.length > 0)\n hierarchy.leafNodes.length = 0;\n if (hierarchy.root.children)\n this.updateRecursive(hierarchy, hierarchy.root.children, null, hierarchy.leafNodes);\n };\n MatrixHierarchyNavigator.prototype.updateRecursive = function (hierarchy, nodes, parent, cache) {\n var level;\n for (var i = 0, ilen = nodes.length; i < ilen; i++) {\n var node = nodes[i];\n node.siblings = nodes;\n if (parent)\n node.parent = parent;\n if (!level)\n level = hierarchy.levels[node.level];\n if (level) {\n var source = level.sources[node.levelSourceIndex ? node.levelSourceIndex : 0];\n var formatString = visuals.valueFormatter.getFormatString(source, TablixObjects.PropColumnFormatString.getPropertyID());\n if (formatString)\n node.name = this.formatter(node.value, source, TablixObjects.PropColumnFormatString.getPropertyID());\n node.queryName = source.queryName;\n }\n node.index = i;\n if (node.children && node.children.length > 0) {\n this.updateRecursive(hierarchy, node.children, node, cache);\n }\n else {\n node.leafIndex = cache.length;\n cache.push(node);\n }\n }\n };\n MatrixHierarchyNavigator.updateStaticColumnHeaders = function (columnHierarchy) {\n var columnLeafNodes = columnHierarchy.leafNodes;\n if (columnLeafNodes && columnLeafNodes.length > 0) {\n var columnLeafSources = columnHierarchy.levels[columnLeafNodes[0].level].sources;\n for (var i = 0, ilen = columnLeafNodes.length; i < ilen; i++) {\n var columnLeafNode = columnLeafNodes[i];\n // Static leaf may need to get label from it's definition\n if (!columnLeafNode.identity && columnLeafNode.value === undefined) {\n // We make distincion between null and undefined. Null can be considered as legit value, undefined means we need to fall back to metadata\n var source = columnLeafSources[columnLeafNode.levelSourceIndex ? columnLeafNode.levelSourceIndex : 0];\n if (source)\n columnLeafNode.name = source.displayName;\n }\n }\n }\n };\n MatrixHierarchyNavigator.prototype.getMatrixHierarchy = function (rootNodes) {\n var rowHierarchyRootNodes = this.rowHierarchy.root.children;\n if (rowHierarchyRootNodes && rootNodes === rowHierarchyRootNodes)\n return this.rowHierarchy;\n var columnHierarchyRootNodes = this.columnHierarchy.root.children;\n if (columnHierarchyRootNodes && rootNodes === columnHierarchyRootNodes)\n return this.columnHierarchy;\n return null;\n };\n return MatrixHierarchyNavigator;\n }());\n var MatrixBinder = (function () {\n function MatrixBinder(hierarchyNavigator, options) {\n // We pass the hierarchy navigator in here because it is the object that will\n // survive data changes and gets updated with the latest data view.\n this.hierarchyNavigator = hierarchyNavigator;\n this.options = options;\n }\n MatrixBinder.prototype.onDataViewChanged = function (formattingProperties) {\n this.formattingProperties = formattingProperties;\n this.updateTextHeights();\n };\n MatrixBinder.prototype.updateTextHeights = function () {\n var textProps = {\n fontFamily: '',\n fontSize: TablixObjects.getTextSizeInPx(this.formattingProperties.general.textSize),\n text: 'a',\n };\n textProps.fontFamily = TablixUtils.FontFamilyHeader;\n this.textHeightHeader = Math.ceil(powerbi.TextMeasurementService.measureSvgTextHeight(textProps));\n textProps.fontFamily = TablixUtils.FontFamilyCell;\n this.textHeightValue = Math.ceil(powerbi.TextMeasurementService.measureSvgTextHeight(textProps));\n textProps.fontFamily = TablixUtils.FontFamilyTotal;\n this.textHeightTotal = Math.ceil(powerbi.TextMeasurementService.measureSvgTextHeight(textProps));\n };\n MatrixBinder.prototype.onStartRenderingSession = function () {\n };\n MatrixBinder.prototype.onEndRenderingSession = function () {\n };\n /**\n * Row Header.\n */\n MatrixBinder.prototype.bindRowHeader = function (item, cell) {\n TablixUtils.resetCellCssClass(cell);\n var cellStyle = new TablixUtils.CellStyle();\n var isLeaf = this.hierarchyNavigator && this.hierarchyNavigator.isLeaf(item);\n if (isLeaf) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassMatrixRowHeaderLeaf);\n cellStyle.borders.right = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\n }\n if (item.isSubtotal) {\n cellStyle.paddings.left = TablixUtils.CellPaddingLeftMatrixTotal;\n }\n this.bindHeader(item, cell, this.getRowHeaderMetadata(item), cellStyle);\n if (this.options.onBindRowHeader)\n this.options.onBindRowHeader(item);\n this.setRowHeaderStyle(cell, cellStyle);\n cell.applyStyle(cellStyle);\n };\n MatrixBinder.prototype.setRowHeaderStyle = function (cell, style) {\n var propsGrid = this.formattingProperties.grid;\n var props = this.formattingProperties.rowHeaders;\n var propsValues = this.formattingProperties.values;\n var propsCols = this.formattingProperties.columnHeaders;\n style.borders.top = new TablixUtils.EdgeSettings();\n if (cell.position.row.isFirst) {\n style.borders.top.applyParams(visuals.outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have top border, but Values have, we need to apply extra padding\n if (!visuals.outline.showTop(props.outline) && visuals.outline.showTop(propsValues.outline))\n style.paddings.top += propsGrid.outlineWeight;\n } // else: do nothing\n style.borders.bottom = new TablixUtils.EdgeSettings();\n if (cell.position.row.isLast) {\n style.borders.bottom.applyParams(visuals.outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have bottom border, but Values have, we need to apply extra padding\n if (!visuals.outline.showBottom(props.outline) && visuals.outline.showBottom(propsValues.outline))\n style.paddings.bottom += propsGrid.outlineWeight;\n }\n else {\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\n }\n style.borders.left = new TablixUtils.EdgeSettings();\n if (cell.position.column.isFirst) {\n style.borders.left.applyParams(visuals.outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have left border, but Column Headers have, we need to apply extra padding\n if (!visuals.outline.showLeft(props.outline) && visuals.outline.showLeft(propsCols.outline))\n style.paddings.left += propsGrid.outlineWeight;\n } // else: do nothing\n style.borders.right = new TablixUtils.EdgeSettings();\n if (cell.position.column.isLast) {\n style.borders.right.applyParams(visuals.outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n }\n else {\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\n }\n style.fontColor = props.fontColor;\n style.backColor = props.backColor;\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\n };\n MatrixBinder.prototype.unbindRowHeader = function (item, cell) {\n TablixUtils.clearCellStyle(cell);\n TablixUtils.clearCellTextAndTooltip(cell);\n };\n /**\n * Column Header.\n */\n MatrixBinder.prototype.bindColumnHeader = function (item, cell) {\n TablixUtils.resetCellCssClass(cell);\n // Set default style\n var cellStyle = new TablixUtils.CellStyle();\n var overwriteTotalLabel = false;\n var isLeaf = this.hierarchyNavigator && this.hierarchyNavigator.isLeaf(item);\n if (isLeaf) {\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixColumnHeaderLeaf);\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueNumeric);\n var sortableHeaderColumnMetadata = this.getSortableHeaderColumnMetadata(item);\n if (sortableHeaderColumnMetadata && this.options.showSortIcons) {\n this.registerColumnHeaderClickHandler(sortableHeaderColumnMetadata, cell);\n TablixUtils.createColumnHeaderWithSortIcon(sortableHeaderColumnMetadata, cell);\n }\n // Overwrite only if the there are subtotal siblings (like in the multimeasure case), which means ALL siblings are subtotals.\n if (item.isSubtotal && item.parent && item.parent.children.length > 1 && item.parent.children[0].isSubtotal)\n overwriteTotalLabel = true;\n }\n cell.extension.disableDragResize();\n this.bindHeader(item, cell, this.getColumnHeaderMetadata(item), cellStyle, overwriteTotalLabel);\n this.setColumnHeaderStyle(cell, cellStyle);\n cell.applyStyle(cellStyle);\n };\n MatrixBinder.prototype.setColumnHeaderStyle = function (cell, style) {\n var propsGrid = this.formattingProperties.grid;\n var props = this.formattingProperties.columnHeaders;\n var propsValues = this.formattingProperties.values;\n style.fontColor = props.fontColor;\n style.backColor = props.backColor;\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\n style.borders.top = new TablixUtils.EdgeSettings();\n if (cell.position.row.isFirst) {\n style.borders.top.applyParams(visuals.outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n } // else: do nothing\n style.borders.bottom = new TablixUtils.EdgeSettings();\n if (cell.position.row.isLast) {\n style.borders.bottom.applyParams(visuals.outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n }\n else {\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\n }\n style.borders.left = new TablixUtils.EdgeSettings();\n if (cell.position.column.isFirst) {\n // If we dont have left border, but Values have, we need to apply extra padding\n if (!visuals.outline.showLeft(props.outline) && visuals.outline.showLeft(propsValues.outline))\n style.paddings.left += propsGrid.outlineWeight;\n }\n style.borders.right = new TablixUtils.EdgeSettings();\n if (cell.position.column.isLast) {\n style.borders.right.applyParams(visuals.outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have right border, but Values have, we need to apply extra padding\n if (!visuals.outline.showRight(props.outline) && visuals.outline.showRight(propsValues.outline))\n style.paddings.right += propsGrid.outlineWeight;\n }\n else {\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\n }\n };\n MatrixBinder.prototype.unbindColumnHeader = function (item, cell) {\n TablixUtils.clearCellStyle(cell);\n TablixUtils.clearCellTextAndTooltip(cell);\n var sortableHeaderColumnMetadata = this.getSortableHeaderColumnMetadata(item);\n if (sortableHeaderColumnMetadata) {\n this.unregisterColumnHeaderClickHandler(cell);\n }\n if (this.options.showSortIcons)\n TablixUtils.removeSortIcons(cell);\n };\n MatrixBinder.prototype.bindHeader = function (item, cell, metadata, style, overwriteSubtotalLabel) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixHeader);\n style.fontFamily = TablixUtils.FontFamilyHeader;\n style.fontColor = TablixUtils.FontColorHeaders;\n var imgHeight = this.formattingProperties.grid.imageHeight;\n if (visuals.converterHelper.isImageUrlColumn(metadata))\n cell.contentHeight = imgHeight;\n else if (item.isSubtotal)\n cell.contentHeight = this.textHeightTotal;\n else\n cell.contentHeight = this.textHeightValue;\n if (item.isSubtotal) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueTotal);\n style.fontFamily = TablixUtils.FontFamilyTotal;\n if (!overwriteSubtotalLabel) {\n TablixUtils.setCellTextAndTooltip(cell, this.options.totalLabel);\n return;\n }\n }\n var value = MatrixBinder.getNodeLabel(item);\n if (!value) {\n // just to maintain the height of the row in case all realized cells are nulls\n cell.extension.contentHost.innerHTML = TablixUtils.StringNonBreakingSpace;\n }\n else if (visuals.converterHelper.isWebUrlColumn(metadata) && UrlUtils.isValidUrl(value)) {\n TablixUtils.appendATagToBodyCell(item.value, cell);\n }\n else if (visuals.converterHelper.isImageUrlColumn(metadata)) {\n style.hasImage = true;\n if (UrlUtils.isValidImageUrl(value)) {\n TablixUtils.appendImgTagToBodyCell(item.value, cell, imgHeight);\n }\n else {\n TablixUtils.setCellTextAndTooltip(cell, value);\n }\n }\n else {\n TablixUtils.setCellTextAndTooltip(cell, value);\n }\n };\n MatrixBinder.prototype.registerColumnHeaderClickHandler = function (columnMetadata, cell) {\n var _this = this;\n if (this.options.onColumnHeaderClick) {\n var handler = function (e) {\n if (TablixUtils.isValidSortClick(e)) {\n var sortDirection = TablixUtils.reverseSort(columnMetadata.sort);\n _this.options.onColumnHeaderClick(columnMetadata.queryName ? columnMetadata.queryName : columnMetadata.displayName, sortDirection);\n }\n };\n cell.extension.registerClickHandler(handler);\n }\n };\n MatrixBinder.prototype.unregisterColumnHeaderClickHandler = function (cell) {\n if (this.options.onColumnHeaderClick) {\n cell.extension.unregisterClickHandler();\n }\n };\n /**\n * Body Cell.\n */\n MatrixBinder.prototype.bindBodyCell = function (item, cell) {\n TablixUtils.resetCellCssClass(cell);\n var cellStyle = new TablixUtils.CellStyle();\n cell.contentHeight = this.textHeightValue;\n if (item.domContent) {\n $(cell.extension.contentHost).append(item.domContent);\n }\n else {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueNumeric);\n if (item.isTotal) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueTotal);\n cellStyle.fontFamily = TablixUtils.FontFamilyTotal;\n cell.contentHeight = this.textHeightTotal;\n }\n if (item.textContent) {\n TablixUtils.setCellTextAndTooltip(cell, item.textContent);\n }\n }\n this.setBodyCellStyle(cell, item, cellStyle);\n cell.applyStyle(cellStyle);\n };\n MatrixBinder.prototype.setBodyCellStyle = function (cell, item, style) {\n var propsGrid = this.formattingProperties.grid;\n var props = this.formattingProperties.values;\n var propsTotal = this.formattingProperties.subtotals;\n var propsRows = this.formattingProperties.rowHeaders;\n var propsColumns = this.formattingProperties.columnHeaders;\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\n style.borders.top = new TablixUtils.EdgeSettings();\n if (cell.position.row.isFirst) {\n style.borders.top.applyParams(visuals.outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have top border, but Row Headers have, we need to apply extra padding\n if (!visuals.outline.showTop(props.outline) && visuals.outline.showTop(propsRows.outline))\n style.paddings.top += propsGrid.outlineWeight;\n } // else: do nothing\n style.borders.bottom = new TablixUtils.EdgeSettings();\n if (cell.position.row.isLast) {\n style.borders.bottom.applyParams(visuals.outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have bottom border, but Row Headers have, we need to apply extra padding\n if (!visuals.outline.showBottom(props.outline) && visuals.outline.showBottom(propsRows.outline))\n style.paddings.bottom += propsGrid.outlineWeight;\n }\n else {\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\n }\n style.borders.left = new TablixUtils.EdgeSettings();\n if (cell.position.column.isFirst) {\n style.borders.left.applyParams(visuals.outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n } // else: do nothing\n style.borders.right = new TablixUtils.EdgeSettings();\n if (cell.position.column.isLast) {\n style.borders.right.applyParams(visuals.outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have right border, but Column Headers have, we need to apply extra padding\n if (!visuals.outline.showRight(props.outline) && visuals.outline.showRight(propsColumns.outline))\n style.paddings.right += propsGrid.outlineWeight;\n }\n else {\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\n }\n var rowBandingIndex;\n if (this.formattingProperties.general.rowSubtotals && propsTotal.backColor)\n rowBandingIndex = item.position.row.indexInSiblings;\n else\n rowBandingIndex = item.position.row.index;\n if (item.isTotal && propsTotal.fontColor) {\n style.fontColor = propsTotal.fontColor;\n }\n else {\n style.fontColor = rowBandingIndex % 2 === 0 ? props.fontColorPrimary : props.fontColorSecondary;\n }\n if (item.isTotal && propsTotal.backColor) {\n style.backColor = propsTotal.backColor;\n }\n else {\n style.backColor = rowBandingIndex % 2 === 0 ? props.backColorPrimary : props.backColorSecondary;\n }\n };\n MatrixBinder.prototype.unbindBodyCell = function (item, cell) {\n TablixUtils.clearCellStyle(cell);\n TablixUtils.clearCellTextAndTooltip(cell);\n };\n /**\n * Corner Cell.\n */\n MatrixBinder.prototype.bindCornerCell = function (item, cell) {\n TablixUtils.resetCellCssClass(cell);\n var cellStyle = new TablixUtils.CellStyle();\n cellStyle.fontFamily = TablixUtils.FontFamilyHeader;\n cellStyle.fontColor = TablixUtils.FontColorHeaders;\n cell.contentHeight = this.textHeightHeader;\n if (item.isColumnHeaderLeaf) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixColumnHeaderLeaf);\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\n var cornerHeaderMetadata = this.getSortableCornerColumnMetadata(item);\n if (cornerHeaderMetadata)\n this.registerColumnHeaderClickHandler(cornerHeaderMetadata, cell);\n if (this.options.showSortIcons)\n TablixUtils.createColumnHeaderWithSortIcon(cornerHeaderMetadata, cell);\n else\n TablixUtils.setCellTextAndTooltip(cell, cornerHeaderMetadata.displayName);\n }\n else {\n var itemText = item.metadata ? item.metadata.displayName : '';\n TablixUtils.setCellTextAndTooltip(cell, itemText);\n }\n if (item.isRowHeaderLeaf) {\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassMatrixRowHeaderLeaf);\n }\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixHeader);\n this.setCornerCellsStyle(cell, cellStyle);\n cell.applyStyle(cellStyle);\n cell.extension.disableDragResize();\n };\n MatrixBinder.prototype.setCornerCellsStyle = function (cell, style) {\n var propsGrid = this.formattingProperties.grid;\n var propsCol = this.formattingProperties.columnHeaders;\n var propsRow = this.formattingProperties.rowHeaders;\n style.fontColor = propsCol.fontColor || propsRow.fontColor;\n style.backColor = propsCol.backColor || propsRow.backColor;\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\n style.borders.top = new TablixUtils.EdgeSettings();\n if (cell.position.row.isFirst) {\n style.borders.top.applyParams(visuals.outline.showTop(propsCol.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n } // else: do nothing\n style.borders.bottom = new TablixUtils.EdgeSettings();\n if (cell.position.row.isLast) {\n style.borders.bottom.applyParams(visuals.outline.showBottom(propsCol.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n }\n else {\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\n }\n style.borders.left = new TablixUtils.EdgeSettings();\n if (cell.position.column.isFirst) {\n style.borders.left.applyParams(visuals.outline.showLeft(propsCol.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\n // If we dont have left border, but Row Headers have, we need to apply extra padding\n if (!visuals.outline.showLeft(propsCol.outline) && visuals.outline.showLeft(propsRow.outline))\n style.paddings.left += propsGrid.outlineWeight;\n } // else: do nothing\n style.borders.right = new TablixUtils.EdgeSettings();\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\n };\n MatrixBinder.prototype.unbindCornerCell = function (item, cell) {\n TablixUtils.clearCellStyle(cell);\n TablixUtils.clearCellTextAndTooltip(cell);\n if (this.options.showSortIcons)\n TablixUtils.removeSortIcons(cell);\n if (item.isColumnHeaderLeaf) {\n this.unregisterColumnHeaderClickHandler(cell);\n }\n };\n MatrixBinder.prototype.bindEmptySpaceHeaderCell = function (cell) {\n };\n MatrixBinder.prototype.unbindEmptySpaceHeaderCell = function (cell) {\n };\n MatrixBinder.prototype.bindEmptySpaceFooterCell = function (cell) {\n };\n MatrixBinder.prototype.unbindEmptySpaceFooterCell = function (cell) {\n };\n /**\n * Measurement Helper.\n */\n MatrixBinder.prototype.getHeaderLabel = function (item) {\n return MatrixBinder.getNodeLabel(item);\n };\n MatrixBinder.prototype.getCellContent = function (item) {\n return item.textContent || '';\n };\n MatrixBinder.prototype.hasRowGroups = function () {\n // Figure out whether we have a static row header, i.e., not row groups\n var dataView = this.hierarchyNavigator.getDataViewMatrix();\n if (!dataView || !dataView.rows || !dataView.rows.levels || dataView.rows.levels.length === 0)\n return false;\n return true;\n };\n MatrixBinder.getNodeLabel = function (node) {\n // Return formatted value\n if (node.name)\n return node.name;\n // Return unformatted value (fallback case)\n if (node.value != null)\n return node.value.toString();\n return '';\n };\n /**\n * Returns the column metadata of the column that needs to be sorted for the specified matrix corner node.\n *\n * @return Column metadata or null if the specified corner node does not represent a sortable header.\n */\n MatrixBinder.prototype.getSortableCornerColumnMetadata = function (item) {\n if (item.isColumnHeaderLeaf)\n return item.metadata;\n };\n MatrixBinder.prototype.getRowHeaderMetadata = function (item) {\n if (!this.hierarchyNavigator || !item)\n return;\n var dataView = this.hierarchyNavigator.getDataViewMatrix();\n if (!dataView || !dataView.rows)\n return;\n return this.getHierarchyMetadata(dataView.rows, item.level);\n };\n MatrixBinder.prototype.getColumnHeaderMetadata = function (item) {\n if (!this.hierarchyNavigator || !item)\n return;\n var dataView = this.hierarchyNavigator.getDataViewMatrix();\n if (!dataView || !dataView.columns)\n return;\n return this.getHierarchyMetadata(dataView.columns, item.level);\n };\n MatrixBinder.prototype.getHierarchyMetadata = function (hierarchy, level) {\n if (!hierarchy || !hierarchy.levels || hierarchy.levels.length < level)\n return;\n var levelInfo = hierarchy.levels[level];\n if (!levelInfo || !levelInfo.sources || levelInfo.sources.length === 0)\n return;\n // This assumes the source will always be the first item in the array of sources.\n return levelInfo.sources[0];\n };\n /**\n * Returns the column metadata of the column that needs to be sorted for the specified header node.\n *\n * @return Column metadata or null if the specified header node does not represent a sortable header.\n */\n MatrixBinder.prototype.getSortableHeaderColumnMetadata = function (item) {\n var dataView = this.hierarchyNavigator.getDataViewMatrix();\n // If there are no row groups, sorting is not supported (as it does not make sense).\n if (!dataView.rows || !dataView.rows.levels || dataView.rows.levels.length === 0)\n return null;\n var isMultiMeasure = dataView.valueSources && dataView.valueSources.length > 1;\n var columnGroupCount = dataView.columns ? dataView.columns.levels.length : 0;\n // If we have multiple values, they establish an extra level, so need to subtract 1\n if (isMultiMeasure) {\n columnGroupCount--;\n }\n else if (columnGroupCount === 1 &&\n dataView.columns.levels[0] &&\n dataView.columns.levels[0].sources && dataView.columns.levels[0].sources[0] &&\n dataView.columns.levels[0].sources[0].roles && dataView.columns.levels[0].sources[0].roles[\"Values\"]) {\n columnGroupCount = 0;\n }\n var valueIndex = -1;\n if (columnGroupCount === 0) {\n // Matrices without column groups, support sorting on all columns (which are then measure columns).\n valueIndex = item.levelSourceIndex;\n }\n else if (item.isSubtotal) {\n // Matrices with column groups support sorting only on the column grand total.\n if (isMultiMeasure) {\n // In the multi-measure case we need to check if the parent's level is 0 in order\n // to determine whether this is the column grand total. The cells are layed out such\n // that the clickable cells are at the innermost level, but the parent for the column\n // grand total will have level 0.\n if (item.parent && item.parent.level === 0)\n valueIndex = item.levelSourceIndex;\n }\n else {\n // In the single-measure case we can directly check the level of the subtotal to\n // detect the column grand total (at level 0).\n if (item.level === 0)\n valueIndex = item.levelSourceIndex;\n }\n }\n if (valueIndex !== -1) {\n // NOTE: if the valueIndex is undefined it implicitly means that it is 0 based on the \n // visual node contract\n valueIndex = valueIndex ? valueIndex : 0;\n return dataView.valueSources[valueIndex];\n }\n return null;\n };\n return MatrixBinder;\n }());\n visuals.MatrixBinder = MatrixBinder;\n var Matrix = (function () {\n function Matrix(options) {\n if (options) {\n this.isTouchEnabled = options.isTouchEnabled;\n }\n }\n Matrix.customizeQuery = function (options) {\n var dataViewMapping = options.dataViewMappings[0];\n if (!dataViewMapping || !dataViewMapping.matrix || !dataViewMapping.metadata)\n return;\n var dataViewMatrix = dataViewMapping.matrix;\n // If Columns Hierarchy is not empty, set Window DataReduction Count to 100\n if (!_.isEmpty(dataViewMatrix.columns.for.in.items)) {\n dataViewMatrix.rows.dataReductionAlgorithm.window.count = 100;\n }\n var objects = dataViewMapping.metadata.objects;\n dataViewMatrix.rows.for.in.subtotalType = TablixObjects.shouldShowRowSubtotals(objects) ? 2 /* After */ : 0 /* None */;\n dataViewMatrix.columns.for.in.subtotalType = TablixObjects.shouldShowColumnSubtotals(objects) ? 2 /* After */ : 0 /* None */;\n };\n Matrix.getSortableRoles = function () {\n return ['Rows', 'Values'];\n };\n Matrix.prototype.init = function (options) {\n this.element = options.element;\n this.style = options.style;\n this.updateViewport(options.viewport);\n this.formatter = visuals.valueFormatter.formatValueColumn;\n this.isInteractive = options.interactivity && options.interactivity.selection != null;\n this.hostServices = options.host;\n this.persistingObjects = false;\n this.waitingForData = false;\n this.lastAllowHeaderResize = true;\n this.waitingForSort = false;\n };\n Matrix.converter = function (dataView) {\n debug.assertValue(dataView, 'dataView');\n return TablixObjects.getMatrixObjects(dataView);\n };\n Matrix.prototype.onResizing = function (finalViewport) {\n this.updateViewport(finalViewport);\n };\n /*\n Public for testing\n */\n Matrix.prototype.getColumnWidthManager = function () {\n return this.columnWidthManager;\n };\n Matrix.prototype.onDataChanged = function (options) {\n debug.assertValue(options, 'options');\n var dataViews = options.dataViews;\n if (dataViews && dataViews.length > 0) {\n var previousDataView = this.dataView;\n this.dataView = dataViews[0];\n // We don't check for persisting flag\n // Any change to the Column Widths need to go through to update all column group instances\n // ToDo: Consider not resetting scrollbar everytime\n var formattingProperties = Matrix.converter(this.dataView);\n var textSize = formattingProperties.general.textSize;\n if (options.operationKind === powerbi.VisualDataChangeOperationKind.Append) {\n var rootChanged = previousDataView.matrix.rows.root !== this.dataView.matrix.rows.root;\n this.hierarchyNavigator.update(this.dataView.matrix, rootChanged);\n // If Root for Rows or Columns has changed by the DataViewTransform (e.g. when having reorders in values)\n if (rootChanged)\n this.tablixControl.updateModels(/*resetScrollOffsets*/ false, this.dataView.matrix.rows.root.children, this.dataView.matrix.columns.root.children);\n this.refreshControl(/*clear*/ false);\n }\n else {\n this.createOrUpdateHierarchyNavigator();\n this.createColumnWidthManager();\n this.createTablixControl(textSize);\n var binder = this.tablixControl.getBinder();\n binder.onDataViewChanged(formattingProperties);\n this.updateInternal(textSize, previousDataView);\n }\n }\n this.waitingForData = false;\n this.waitingForSort = false;\n };\n Matrix.prototype.createColumnWidthManager = function () {\n var _this = this;\n var columnHierarchy = this.hierarchyNavigator.getMatrixColumnHierarchy();\n if (!this.columnWidthManager) {\n this.columnWidthManager = new visuals.controls.TablixColumnWidthManager(this.dataView, true /* isMatrix */, function (objectInstances) { return _this.persistColumnWidths(objectInstances); }, columnHierarchy.leafNodes);\n }\n else if (!this.persistingObjects) {\n this.columnWidthManager.updateDataView(this.dataView, columnHierarchy.leafNodes);\n }\n };\n Matrix.prototype.persistColumnWidths = function (objectInstances) {\n this.persistingObjects = true;\n this.hostServices.persistProperties(objectInstances);\n };\n Matrix.prototype.updateViewport = function (newViewport) {\n this.currentViewport = newViewport;\n if (this.tablixControl) {\n this.tablixControl.viewport = this.currentViewport;\n this.verifyHeaderResize();\n this.refreshControl(/*clear*/ false);\n }\n };\n Matrix.prototype.refreshControl = function (clear) {\n if (visuals.visibilityHelper.partiallyVisible(this.element) || this.getLayoutKind() === 1 /* DashboardTile */) {\n this.tablixControl.refresh(clear);\n }\n };\n Matrix.prototype.getLayoutKind = function () {\n return this.isInteractive ? 0 /* Canvas */ : 1 /* DashboardTile */;\n };\n Matrix.prototype.createOrUpdateHierarchyNavigator = function () {\n if (!this.tablixControl) {\n var matrixNavigator = createMatrixHierarchyNavigator(this.dataView.matrix, this.formatter);\n this.hierarchyNavigator = matrixNavigator;\n }\n else {\n this.hierarchyNavigator.update(this.dataView.matrix);\n }\n };\n Matrix.prototype.createTablixControl = function (textSize) {\n if (!this.tablixControl) {\n // Create the control\n this.tablixControl = this.createControl(this.hierarchyNavigator, textSize);\n }\n };\n Matrix.prototype.createControl = function (matrixNavigator, textSize) {\n var _this = this;\n var layoutKind = this.getLayoutKind();\n var matrixBinderOptions = {\n onBindRowHeader: function (item) { _this.onBindRowHeader(item); },\n totalLabel: this.hostServices.getLocalizedString(Matrix.TotalLabel),\n onColumnHeaderClick: function (queryName, sortDirection) { return _this.onColumnHeaderClick(queryName, sortDirection); },\n showSortIcons: layoutKind === 0 /* Canvas */,\n };\n var matrixBinder = new MatrixBinder(this.hierarchyNavigator, matrixBinderOptions);\n var layoutManager = layoutKind === 1 /* DashboardTile */\n ? visuals.controls.internal.DashboardTablixLayoutManager.createLayoutManager(matrixBinder)\n : visuals.controls.internal.CanvasTablixLayoutManager.createLayoutManager(matrixBinder, this.columnWidthManager);\n var tablixContainer = document.createElement('div');\n this.element.append(tablixContainer);\n var tablixOptions = {\n interactive: this.isInteractive,\n enableTouchSupport: this.isTouchEnabled,\n layoutKind: layoutKind,\n fontSize: TablixObjects.getTextSizeInPx(textSize),\n };\n return new visuals.controls.TablixControl(matrixNavigator, layoutManager, matrixBinder, tablixContainer, tablixOptions);\n };\n Matrix.prototype.updateInternal = function (textSize, previousDataView) {\n var _this = this;\n if (this.getLayoutKind() === 1 /* DashboardTile */) {\n this.tablixControl.layoutManager.adjustContentSize(visuals.converterHelper.hasImageUrlColumn(this.dataView));\n }\n this.tablixControl.fontSize = TablixObjects.getTextSizeInPx(textSize);\n this.verifyHeaderResize();\n /* To avoid resetting scrollbar every time we persist Objects. If:\n * AutoSizeColumns options was flipped\n * A Column was resized manually\n * A Column was auto-sized\n */\n // Update models before the viewport to make sure column widths are computed correctly\n // if a persisting operation is going, don't reset the scrollbar (column resize)\n this.tablixControl.updateModels(/*resetScrollOffsets*/ !this.persistingObjects, this.dataView.matrix.rows.root.children, this.dataView.matrix.columns.root.children);\n this.tablixControl.viewport = this.currentViewport;\n var shouldClearControl = this.shouldClearControl(previousDataView, this.dataView);\n // We need the layout for the DIV to be done so that the control can measure items correctly.\n setTimeout(function () {\n // Render\n _this.refreshControl(shouldClearControl);\n // At this point, all columns are rendered with proper width, reset the flag if it was raised\n if (_this.persistingObjects) {\n _this.persistingObjects = false;\n return;\n }\n // if AutoSize option was set to OFF, persist all columns width\n if (_this.columnWidthManager.shouldPersistAllColumnWidths()) {\n _this.columnWidthManager.persistAllColumnWidths(_this.tablixControl.layoutManager.columnWidthsToPersist);\n }\n }, 0);\n };\n Matrix.prototype.shouldClearControl = function (previousDataView, newDataView) {\n if (!this.waitingForSort || !previousDataView || !newDataView)\n return true;\n // ToDo: Get better criteria\n return !powerbi.DataViewAnalysis.isMetadataEquivalent(previousDataView.metadata, newDataView.metadata);\n };\n Matrix.prototype.onBindRowHeader = function (item) {\n if (this.needsMoreData(item)) {\n this.hostServices.loadMoreData();\n this.waitingForData = true;\n }\n };\n Matrix.prototype.onColumnHeaderClick = function (queryName, sortDirection) {\n this.waitingForSort = true;\n this.hostServices.onCustomSort(TablixUtils.getCustomSortEventArgs(queryName, sortDirection));\n };\n /**\n * Note: Public for testability.\n */\n Matrix.prototype.needsMoreData = function (item) {\n if (this.waitingForData || !this.hierarchyNavigator.isLeaf(item) || !this.dataView.metadata || !this.dataView.metadata.segment)\n return false;\n var leafCount = this.tablixControl.rowDimension.getItemsCount();\n var loadMoreThreshold = leafCount * Matrix.preferredLoadMoreThreshold;\n return this.hierarchyNavigator.getLeafIndex(item) >= loadMoreThreshold;\n };\n Matrix.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n // Visuals are initialized with an empty data view before queries are run, therefore we need to make sure that\n // we are resilient here when we do not have data view.\n if (this.dataView) {\n TablixObjects.enumerateObjectInstances(options, enumeration, this.dataView, visuals.controls.TablixType.Matrix);\n }\n return enumeration.complete();\n };\n Matrix.prototype.shouldAllowHeaderResize = function () {\n return this.hostServices.getViewMode() === 1 /* Edit */;\n };\n Matrix.prototype.onViewModeChanged = function (viewMode) {\n /* Refreshes the column headers to enable/disable Column resizing */\n this.updateViewport(this.currentViewport);\n };\n Matrix.prototype.verifyHeaderResize = function () {\n var currentAllowHeaderResize = this.shouldAllowHeaderResize();\n if (currentAllowHeaderResize !== this.lastAllowHeaderResize) {\n this.lastAllowHeaderResize = currentAllowHeaderResize;\n this.tablixControl.layoutManager.setAllowHeaderResize(currentAllowHeaderResize);\n }\n };\n Matrix.preferredLoadMoreThreshold = 0.8;\n /**\n * Note: Public only for testing.\n */\n Matrix.TotalLabel = 'TableTotalLabel';\n return Matrix;\n }());\n visuals.Matrix = Matrix;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var CssConstants = jsCommon.CssConstants;\n /**\n * Renders an interactive treemap visual from categorical data.\n */\n var Treemap = (function () {\n function Treemap(options) {\n this.tooltipsEnabled = options && options.tooltipsEnabled;\n if (options && options.animator) {\n this.animator = options.animator;\n this.isScrollable = options.isScrollable ? options.isScrollable : false;\n this.behavior = options.behavior;\n }\n }\n Treemap.getLayout = function (labelsSettings, alternativeScale) {\n var formattersCache = visuals.dataLabelUtils.createColumnFormatterCacheManager();\n var majorLabelsEnabled = labelsSettings.showCategory;\n var minorLabelsEnabled = labelsSettings.show || labelsSettings.showCategory;\n return {\n shapeClass: function (d) { return Treemap.getNodeClass(d, false); },\n shapeLayout: Treemap.createTreemapShapeLayout(false),\n highlightShapeClass: function (d) { return Treemap.getNodeClass(d, true); },\n highlightShapeLayout: Treemap.createTreemapShapeLayout(true),\n zeroShapeLayout: Treemap.createTreemapZeroShapeLayout(),\n majorLabelClass: function (d) { return Treemap.MajorLabelClassName; },\n majorLabelLayout: {\n x: function (d) { return d.x + Treemap.TextMargin; },\n y: function (d) { return d.y + Treemap.TextMargin + Treemap.MajorLabelTextSize; },\n },\n majorLabelText: function (d) { return Treemap.createMajorLabelText(d, labelsSettings, alternativeScale, formattersCache); },\n minorLabelClass: function (d) { return Treemap.MinorLabelClassName; },\n minorLabelLayout: {\n x: function (d) { return d.x + Treemap.TextMargin; },\n y: function (d) { return d.y + d.dy - Treemap.TextMargin; },\n },\n minorLabelText: function (d) { return Treemap.createMinorLabelText(d, labelsSettings, alternativeScale, formattersCache); },\n areMajorLabelsEnabled: function () { return majorLabelsEnabled; },\n areMinorLabelsEnabled: function () { return minorLabelsEnabled; },\n };\n };\n Treemap.prototype.init = function (options) {\n this.options = options;\n var element = options.element;\n // Ensure viewport is empty on init\n element.empty();\n this.svg = d3.select(element.get(0))\n .append('svg')\n .style('position', 'absolute')\n .classed(Treemap.ClassName, true);\n this.shapeGraphicsContext = this.svg\n .append('g')\n .classed(Treemap.ShapesClassName, true);\n this.labelGraphicsContext = this.svg\n .append('g')\n .classed(Treemap.LabelsGroupClassName, true);\n this.element = element;\n // avoid deep copy\n this.currentViewport = {\n height: options.viewport.height,\n width: options.viewport.width,\n };\n this.style = options.style;\n this.treemap = d3.layout.treemap()\n .sticky(false)\n .sort(function (a, b) { return a.size - b.size; })\n .value(function (d) { return d.size; })\n .round(false);\n if (this.behavior) {\n this.interactivityService = visuals.createInteractivityService(options.host);\n }\n this.legend = visuals.createLegend(element, options.interactivity && options.interactivity.isInteractiveLegend, this.interactivityService, this.isScrollable);\n this.colors = this.style.colorPalette.dataColors;\n this.hostService = options.host;\n };\n /**\n * Note: Public for testing purposes.\n */\n Treemap.converter = function (dataView, colors, labelSettings, interactivityService, viewport, legendObjectProperties, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n var rootNode = {\n key: \"root\",\n name: \"root\",\n children: [],\n selected: false,\n highlightMultiplier: 0,\n identity: visuals.SelectionId.createNull(),\n color: undefined,\n };\n var allNodes = [];\n var hasHighlights;\n var legendDataPoints = [];\n var legendTitle = \"\";\n var colorHelper = new visuals.ColorHelper(colors, visuals.treemapProps.dataPoint.fill);\n var dataWasCulled = undefined;\n if (dataView && dataView.metadata && dataView.metadata.objects) {\n var objects = dataView.metadata.objects;\n labelSettings.show = powerbi.DataViewObjects.getValue(objects, visuals.treemapProps.labels.show, labelSettings.show);\n labelSettings.labelColor = powerbi.DataViewObjects.getFillColor(objects, visuals.treemapProps.labels.color, labelSettings.labelColor);\n labelSettings.displayUnits = powerbi.DataViewObjects.getValue(objects, visuals.treemapProps.labels.labelDisplayUnits, labelSettings.displayUnits);\n labelSettings.precision = powerbi.DataViewObjects.getValue(objects, visuals.treemapProps.labels.labelPrecision, labelSettings.precision);\n labelSettings.showCategory = powerbi.DataViewObjects.getValue(objects, visuals.treemapProps.categoryLabels.show, labelSettings.showCategory);\n }\n if (dataView && dataView.categorical && dataView.categorical.values) {\n var categorical = dataView.categorical;\n var valueColumns = categorical.values;\n hasHighlights = !!(valueColumns.length > 0 && valueColumns[0].highlights);\n var formatStringProp = visuals.treemapProps.general.formatString;\n var result = Treemap.getValuesFromCategoricalDataView(categorical, hasHighlights);\n var values = result.values;\n var highlights = result.highlights;\n var totalValue = result.totalValue;\n if (result.highlightsOverflow) {\n hasHighlights = false;\n values = highlights;\n }\n var cullableValue = Treemap.getCullableValue(totalValue, viewport);\n var grouped = valueColumns.grouped();\n var isMultiSeries = grouped && grouped.length > 0 && grouped[0].values && grouped[0].values.length > 1;\n var hasDynamicSeries = !!valueColumns.source;\n dataWasCulled = false;\n var shouldCullValue = undefined;\n var gradientValueColumn = visuals.GradientUtils.getGradientValueColumn(categorical);\n if ((categorical.categories == null) && !_.isEmpty(values)) {\n // No categories, sliced by series and measures\n for (var i = 0, ilen = values[0].length; i < ilen; i++) {\n var valueColumn = valueColumns[i];\n if (!powerbi.data.DataRoleHelper.hasRoleInValueColumn(valueColumn, Treemap.ValuesRoleName)) {\n continue;\n }\n var value = values[0][i];\n if (!Treemap.checkValueForShape(value)) {\n continue;\n }\n if (value < cullableValue) {\n dataWasCulled = dataWasCulled || shouldCullValue;\n continue;\n }\n var nodeName = hasDynamicSeries ? reader.getSeriesValueColumnGroup(i).name : visuals.converterHelper.formatFromMetadataColumn(reader.getValueDisplayName(\"Values\", i), valueColumn.source, formatStringProp);\n var identity = new visuals.SelectionIdBuilder()\n .withSeries(valueColumns, hasDynamicSeries ? valueColumns[i] : undefined)\n .withMeasure(valueColumns[i].source.queryName)\n .createSelectionId();\n var key = identity.getKey();\n var color = hasDynamicSeries\n ? colorHelper.getColorForSeriesValue(grouped[i] && grouped[i].objects, categorical.values.identityFields, visuals.converterHelper.getSeriesName(valueColumn.source))\n : colorHelper.getColorForMeasure(valueColumn.source.objects, valueColumn.source.queryName);\n var highlightedValue = hasHighlights ? highlights[0][i] : undefined;\n var tooltipInfo = void 0;\n if (tooltipsEnabled) {\n tooltipInfo = [];\n if (hasDynamicSeries) {\n var seriesMetadataColumn = reader.getSeriesMetadataColumn();\n var seriesValue = reader.getSeriesValueColumnGroup(i).name;\n tooltipInfo.push({\n displayName: seriesMetadataColumn.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(seriesValue, seriesMetadataColumn, formatStringProp),\n });\n }\n if (value != null) {\n tooltipInfo.push({\n displayName: valueColumn.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(value, valueColumn.source, formatStringProp),\n });\n }\n if (highlightedValue != null) {\n tooltipInfo.push({\n displayName: visuals.ToolTipComponent.localizationOptions.highlightedValueDisplayName,\n value: visuals.converterHelper.formatFromMetadataColumn(highlightedValue, valueColumn.source, formatStringProp),\n });\n }\n }\n var node = {\n key: key,\n name: nodeName,\n size: value,\n color: color,\n selected: false,\n identity: identity,\n tooltipInfo: tooltipInfo,\n highlightedTooltipInfo: tooltipInfo,\n labelFormatString: visuals.valueFormatter.getFormatString(valueColumn.source, formatStringProp),\n };\n if (hasHighlights && highlights) {\n node.highlightMultiplier = value !== 0 ? highlights[0][i] / value : 0;\n node.highlightValue = highlights[0][i];\n }\n rootNode.children.push(node);\n allNodes.push(node);\n legendDataPoints.push({\n label: nodeName,\n color: color,\n icon: visuals.LegendIcon.Box,\n identity: identity,\n selected: false\n });\n }\n }\n else if (categorical.categories && categorical.categories.length > 0) {\n // Count the columns that have the value roles\n var valueColumnCount = _.filter(valueColumns, function (x) { return x.source && x.source.roles && x.source.roles[Treemap.ValuesRoleName] === true; }).length;\n // Do not add second level if it's one and only one data point per shape and it's not a group value\n // e.g. Category/Series group plus only one Value field (excluding the gradient)\n var omitSecondLevel = valueColumnCount === 1 && (valueColumns[0].source.groupName == null);\n // Create the first level from categories\n var categoryColumn = categorical.categories[0];\n legendTitle = categoryColumn.source.displayName;\n var categoryFormat = visuals.valueFormatter.getFormatString(categoryColumn.source, formatStringProp);\n for (var categoryIndex = 0, categoryLen = values.length; categoryIndex < categoryLen; categoryIndex++) {\n var objects = categoryColumn.objects && categoryColumn.objects[categoryIndex];\n var color = colorHelper.getColorForSeriesValue(objects, categoryColumn.identityFields, categoryColumn.values[categoryIndex]);\n var categoryValue = visuals.valueFormatter.format(categoryColumn.values[categoryIndex], categoryFormat);\n var currentValues = values[categoryIndex];\n // This section area builds the tooltip for the parent node. It's only displayed if the node doesn't have any children (essentially if omitSecondLevel is true).\n // seriesIndex is the index of the 1st series with the role Values.\n var seriesIndex = powerbi.data.DataRoleHelper.getMeasureIndexOfRole(grouped, Treemap.ValuesRoleName);\n var value = currentValues[seriesIndex];\n var highlightValue = hasHighlights && highlights ? highlights[categoryIndex][seriesIndex] : undefined;\n var tooltipInfo = void 0;\n var categoryTooltipItem = void 0;\n if (tooltipsEnabled) {\n tooltipInfo = [];\n categoryTooltipItem = {\n displayName: categoryColumn.source.displayName,\n value: categoryValue,\n };\n tooltipInfo.push(categoryTooltipItem);\n var valueColumnMetadata = void 0;\n if (value != null) {\n valueColumnMetadata = valueColumns[seriesIndex].source;\n tooltipInfo.push({\n displayName: valueColumnMetadata.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(value, valueColumnMetadata, formatStringProp),\n });\n }\n if (highlightValue != null) {\n tooltipInfo.push({\n displayName: visuals.ToolTipComponent.localizationOptions.highlightedValueDisplayName,\n value: visuals.converterHelper.formatFromMetadataColumn(highlightValue, valueColumnMetadata, formatStringProp),\n });\n }\n var gradientValueColumnMetadata = gradientValueColumn ? gradientValueColumn.source : undefined;\n if (omitSecondLevel && gradientValueColumnMetadata && gradientValueColumnMetadata !== valueColumnMetadata && gradientValueColumn.values[categoryIndex] != null) {\n tooltipInfo.push({\n displayName: gradientValueColumnMetadata.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(gradientValueColumn.values[categoryIndex], gradientValueColumnMetadata, formatStringProp),\n });\n }\n }\n var identity = visuals.SelectionIdBuilder.builder()\n .withCategory(categoryColumn, categoryIndex)\n .withMeasure(omitSecondLevel ? valueColumns[seriesIndex].source.queryName : undefined)\n .createSelectionId();\n var key = JSON.stringify({ nodeKey: identity.getKey(), depth: 1 });\n var node = {\n key: key,\n name: categoryValue,\n color: color,\n selected: false,\n identity: identity,\n tooltipInfo: tooltipInfo,\n highlightedTooltipInfo: tooltipInfo,\n labelFormatString: valueColumnCount === 1 ? visuals.valueFormatter.getFormatString(valueColumns[seriesIndex].source, formatStringProp) : categoryFormat,\n };\n if (hasHighlights) {\n node.highlightMultiplier = value !== 0 ? highlightValue / value : 0;\n node.highlightValue = highlightValue;\n }\n legendDataPoints.push({\n label: categoryValue,\n color: color,\n icon: visuals.LegendIcon.Box,\n identity: identity,\n selected: false\n });\n var total = 0;\n var highlightTotal = 0; // Used if omitting second level\n for (var j = 0, jlen = currentValues.length; j < jlen; j++) {\n var valueColumn = valueColumns[j];\n if (!powerbi.data.DataRoleHelper.hasRoleInValueColumn(valueColumn, Treemap.ValuesRoleName)) {\n continue;\n }\n var value_1 = currentValues[j];\n var highlight = void 0;\n shouldCullValue = value_1 < cullableValue;\n if (!Treemap.checkValueForShape(value_1) || shouldCullValue) {\n dataWasCulled = dataWasCulled || shouldCullValue;\n continue;\n }\n total += value_1;\n if (hasHighlights) {\n highlight = highlights[categoryIndex][j];\n highlightTotal += highlight;\n }\n if (!omitSecondLevel) {\n var childName = null;\n if (isMultiSeries) {\n // Measure: use name and index\n childName = valueColumn.source.displayName;\n }\n else {\n // Series group instance\n childName = valueColumn.source.groupName;\n }\n var categoricalValues = categorical ? categorical.values : null;\n var measureId = valueColumn.source.queryName;\n var childIdentity = visuals.SelectionIdBuilder.builder()\n .withCategory(categoryColumn, categoryIndex)\n .withSeries(categoricalValues, valueColumn)\n .withMeasure(measureId)\n .createSelectionId();\n var childKey = JSON.stringify({ nodeKey: childIdentity.getKey(), depth: 2 });\n var highlightedValue = hasHighlights && highlight !== 0 ? highlight : undefined;\n var tooltipInfo_1 = void 0;\n if (tooltipsEnabled) {\n tooltipInfo_1 = [];\n tooltipInfo_1.push(categoryTooltipItem);\n if (hasDynamicSeries) {\n if (!categoryColumn || categoryColumn.source !== categoricalValues.source) {\n // Category/series on the same column -- don't repeat its value in the tooltip.\n tooltipInfo_1.push({\n displayName: categoricalValues.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(grouped[j].name, categoricalValues.source, formatStringProp),\n });\n }\n }\n if (value_1 != null) {\n tooltipInfo_1.push({\n displayName: valueColumn.source.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(value_1, valueColumn.source, formatStringProp),\n });\n }\n if (highlightValue != null) {\n tooltipInfo_1.push({\n displayName: visuals.ToolTipComponent.localizationOptions.highlightedValueDisplayName,\n value: visuals.converterHelper.formatFromMetadataColumn(highlightedValue, valueColumn.source, formatStringProp),\n });\n }\n }\n var childNode = {\n key: childKey,\n name: childName,\n size: value_1,\n color: color,\n selected: false,\n identity: childIdentity,\n tooltipInfo: tooltipInfo_1,\n highlightedTooltipInfo: tooltipInfo_1,\n labelFormatString: visuals.valueFormatter.getFormatString(valueColumn.source, formatStringProp),\n };\n if (hasHighlights) {\n childNode.highlightMultiplier = value_1 !== 0 ? highlight / value_1 : 0;\n childNode.highlightValue = highlight;\n }\n if (node.children == null)\n node.children = [];\n node.children.push(childNode);\n allNodes.push(childNode);\n }\n }\n if (Treemap.checkValueForShape(total)) {\n node.size = total;\n rootNode.children.push(node);\n allNodes.push(node);\n }\n if (hasHighlights)\n node.highlightMultiplier = total ? highlightTotal / total : 0;\n }\n }\n }\n if (interactivityService) {\n interactivityService.applySelectionStateToData(allNodes);\n interactivityService.applySelectionStateToData(legendDataPoints);\n }\n return {\n root: rootNode,\n hasHighlights: hasHighlights,\n legendData: { title: legendTitle, dataPoints: legendDataPoints, fontSize: visuals.SVGLegend.DefaultFontSizeInPt },\n dataLabelsSettings: labelSettings,\n legendObjectProperties: legendObjectProperties,\n dataWasCulled: dataWasCulled,\n };\n };\n Treemap.getValuesFromCategoricalDataView = function (data, hasHighlights) {\n var valueColumns = data.values;\n var categoryValueCount;\n if (valueColumns && (data.categories == null)) {\n categoryValueCount = 1; // We only get the first value out of each valueColumn since we don't have a category\n }\n else if (valueColumns && data.categories && data.categories.length > 0) {\n categoryValueCount = data.categories[0].values.length;\n }\n var values = [];\n var highlights = [];\n var totalValue = 0;\n for (var i = 0; i < categoryValueCount; i++) {\n values.push([]);\n if (hasHighlights)\n highlights.push([]);\n }\n var highlightsOverflow;\n for (var j = 0; j < valueColumns.length; j++) {\n var valueColumn = valueColumns[j];\n for (var i = 0; i < categoryValueCount; i++) {\n var value = valueColumn.values[i];\n values[i].push(value);\n totalValue += isNaN(value) ? 0 : value;\n if (hasHighlights) {\n var highlight = valueColumn.highlights[i];\n if (!highlight)\n highlight = 0;\n highlights[i].push(highlight);\n if (highlight > value)\n highlightsOverflow = true;\n }\n }\n }\n return {\n values: values,\n highlights: hasHighlights ? highlights : undefined,\n highlightsOverflow: hasHighlights ? highlightsOverflow : undefined,\n totalValue: totalValue,\n };\n };\n Treemap.getCullableValue = function (totalValue, viewport) {\n var totalArea = viewport.width * viewport.height;\n var culledPercent = Treemap.CullableArea / totalArea;\n return culledPercent * totalValue;\n };\n Treemap.prototype.update = function (options) {\n debug.assertValue(options, 'options');\n var dataViews = this.dataViews = options.dataViews;\n this.currentViewport = options.viewport;\n var dataViewCategorical = dataViews && dataViews.length > 0 && dataViews[0].categorical ? dataViews[0].categorical : undefined;\n var labelSettings = visuals.dataLabelUtils.getDefaultTreemapLabelSettings();\n var legendObjectProperties = null;\n if (dataViewCategorical) {\n var dataView = dataViews[0];\n var dataViewMetadata = dataView.metadata;\n var objects = void 0;\n if (dataViewMetadata)\n objects = dataViewMetadata.objects;\n if (objects) {\n legendObjectProperties = objects['legend'];\n }\n this.data = Treemap.converter(dataView, this.colors, labelSettings, this.interactivityService, this.currentViewport, legendObjectProperties, this.tooltipsEnabled);\n }\n else {\n var rootNode = {\n key: \"root\",\n name: \"root\",\n children: [],\n selected: false,\n highlightMultiplier: 0,\n identity: visuals.SelectionId.createNull(),\n color: undefined,\n };\n var legendData = { title: \"\", dataPoints: [] };\n var treeMapData = {\n root: rootNode,\n hasHighlights: false,\n legendData: legendData,\n dataLabelsSettings: labelSettings,\n dataWasCulled: false,\n };\n this.data = treeMapData;\n }\n this.updateInternal(options.suppressAnimations);\n if (dataViews) {\n var warnings = visuals.getInvalidValueWarnings(dataViews, false /*supportsNaN*/, false /*supportsNegativeInfinity*/, false /*supportsPositiveInfinity*/);\n this.hostService.setWarnings(warnings);\n }\n };\n // TODO: Remove this once all visuals have implemented update.\n Treemap.prototype.onDataChanged = function (options) {\n this.update({\n suppressAnimations: options.suppressAnimations,\n dataViews: options.dataViews,\n viewport: this.currentViewport\n });\n };\n // TODO: Remove this once all visuals have implemented update.\n Treemap.prototype.onResizing = function (viewport) {\n this.update({\n suppressAnimations: true,\n dataViews: this.dataViews,\n viewport: viewport\n });\n };\n Treemap.prototype.onClearSelection = function () {\n if (this.interactivityService)\n this.interactivityService.clearSelection();\n };\n Treemap.prototype.enumerateObjectInstances = function (options) {\n var data = this.data;\n if (!data)\n return;\n var objectName = options.objectName, enumeration = new visuals.ObjectEnumerationBuilder();\n var dataLabelsSettings = this.data.dataLabelsSettings\n ? this.data.dataLabelsSettings\n : visuals.dataLabelUtils.getDefaultTreemapLabelSettings();\n switch (objectName) {\n case 'dataPoint':\n var dataViewCat = this.dataViews && this.dataViews.length > 0 && this.dataViews[0] && this.dataViews[0].categorical;\n var hasGradientRole = visuals.GradientUtils.hasGradientRole(dataViewCat);\n if (!hasGradientRole)\n this.enumerateDataPoints(enumeration, data);\n break;\n case 'legend':\n return this.enumerateLegend(data);\n case 'labels':\n var labelSettingOptions = {\n enumeration: enumeration,\n dataLabelsSettings: dataLabelsSettings,\n show: true,\n displayUnits: true,\n precision: true,\n };\n visuals.dataLabelUtils.enumerateDataLabels(labelSettingOptions);\n break;\n case 'categoryLabels':\n visuals.dataLabelUtils.enumerateCategoryLabels(enumeration, dataLabelsSettings, false /* withFill */, true /* isShowCategory */);\n break;\n }\n return enumeration.complete();\n };\n Treemap.prototype.enumerateDataPoints = function (enumeration, data) {\n var rootChildren = data.root.children;\n if (_.isEmpty(rootChildren))\n return;\n for (var y = 0; y < rootChildren.length; y++) {\n var treemapNode = rootChildren[y];\n enumeration.pushInstance({\n displayName: treemapNode.name,\n selector: visuals.ColorHelper.normalizeSelector(treemapNode.identity.getSelector()),\n properties: {\n fill: { solid: { color: treemapNode.color } }\n },\n objectName: 'dataPoint'\n });\n }\n };\n Treemap.prototype.enumerateLegend = function (data) {\n var legendObjectProperties = { legend: data.legendObjectProperties };\n var show = powerbi.DataViewObjects.getValue(legendObjectProperties, visuals.treemapProps.legend.show, this.legend.isVisible());\n var showTitle = powerbi.DataViewObjects.getValue(legendObjectProperties, visuals.treemapProps.legend.showTitle, true);\n var titleText = powerbi.DataViewObjects.getValue(legendObjectProperties, visuals.treemapProps.legend.titleText, this.data.legendData.title);\n var labelColor = powerbi.DataViewObject.getValue(legendObjectProperties, visuals.legendProps.labelColor, this.data.legendData ? this.data.legendData.labelColor : visuals.LegendData.DefaultLegendLabelFillColor);\n var labelFontSize = powerbi.DataViewObject.getValue(legendObjectProperties, visuals.legendProps.fontSize, this.data.legendData && this.data.legendData.fontSize ? this.data.legendData.fontSize : visuals.SVGLegend.DefaultFontSizeInPt);\n return [{\n selector: null,\n objectName: 'legend',\n properties: {\n show: show,\n position: visuals.LegendPosition[this.legend.getOrientation()],\n showTitle: showTitle,\n titleText: titleText,\n labelColor: labelColor,\n fontSize: labelFontSize,\n }\n }];\n };\n Treemap.checkValueForShape = function (value) {\n if (!value)\n return false;\n return value > 0;\n };\n Treemap.prototype.calculateTreemapSize = function () {\n var legendMargins = this.legend.getMargins();\n return {\n height: this.currentViewport.height - legendMargins.height,\n width: this.currentViewport.width - legendMargins.width\n };\n };\n Treemap.prototype.initViewportDependantProperties = function (duration) {\n if (duration === void 0) { duration = 0; }\n var viewport = this.calculateTreemapSize();\n this.svg.attr({\n width: viewport.width,\n height: viewport.height\n });\n visuals.Legend.positionChartArea(this.svg, this.legend);\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n };\n Treemap.hasChildrenWithIdentity = function (node) {\n var children = node.children;\n if (!children)\n return false;\n var count = children.length;\n if (count === 0)\n return false;\n for (var i = count - 1; i >= 0; i--) {\n if (children[i].identity.hasIdentity())\n return true;\n }\n return false;\n };\n Treemap.canDisplayMajorLabel = function (node) {\n // Only display major labels for level 1\n if (node.depth !== 1)\n return false;\n if (_.isEmpty(node.name))\n return false;\n // Check if the room is enough for text with or without ellipse\n var availableWidth = node.dx - Treemap.TextMargin * 2;\n if (availableWidth < Treemap.MinTextWidthForMajorLabel)\n return false;\n // Check if the shape is high enough for label\n var textHeightWithMargin = Treemap.MajorLabelTextSize + Treemap.TextMargin * 2;\n if (node.dy < textHeightWithMargin)\n return false;\n return true;\n };\n Treemap.canDisplayMinorLabel = function (node, labelSettings) {\n // Only display minor labels for level 1 and 2\n if (node.depth < 1 || node.depth > 2)\n return false;\n // If a depth 1 node has children or is not showing data labels, do not show minor labels\n if (node.depth === 1 && (node.children || !labelSettings.show)) {\n return false;\n }\n if (_.isEmpty(node.name))\n return false;\n // Check if the room is enough for text with or without ellipse\n var availableWidth = node.dx - Treemap.TextMargin * 2;\n if (availableWidth < Treemap.MinTextWidthForMinorLabel)\n return false;\n // Check if the shape is high enough for label\n var textHeightWithMargin = Treemap.MinorLabelTextSize + Treemap.TextMargin * 2;\n if (node.dy < textHeightWithMargin)\n return false;\n if (node.depth === 1) {\n var roomTop = node.y + Treemap.MajorLabelTextSize + Treemap.TextMargin * 2;\n if (node.y + node.dy - roomTop < textHeightWithMargin)\n return false;\n }\n else if (node.depth === 2) {\n var parent_1 = node.parent;\n var roomTop = Math.max(parent_1.y + Treemap.MajorLabelTextSize + Treemap.TextMargin * 2, node.y);\n // Parent's label needs the room\n if (node.y + node.dy - roomTop < textHeightWithMargin)\n return false;\n }\n return true;\n };\n Treemap.createMajorLabelText = function (node, labelsSettings, alternativeScale, formattersCache) {\n var spaceAvaliableForLabels = node.dx - Treemap.TextMargin * 2;\n var baseTextProperties = Treemap.MajorLabelTextProperties;\n var textProperties = {\n text: node.name,\n fontFamily: baseTextProperties.fontFamily,\n fontSize: baseTextProperties.fontSize\n };\n return powerbi.TextMeasurementService.getTailoredTextOrDefault(textProperties, spaceAvaliableForLabels);\n };\n Treemap.createMinorLabelText = function (node, labelsSettings, alternativeScale, formattersCache) {\n var spaceAvaliableForLabels = node.dx - Treemap.TextMargin * 2;\n var label = node.name;\n if (labelsSettings.show) {\n var measureFormatter = formattersCache.getOrCreate(node.labelFormatString, labelsSettings, alternativeScale);\n // Create measure label\n label = visuals.dataLabelUtils.getLabelFormattedText({\n label: node.highlightValue != null ? node.highlightValue : node.value, maxWidth: spaceAvaliableForLabels, formatter: measureFormatter\n });\n // Add category if needed (we're showing category and the node depth is 2)\n if (labelsSettings.showCategory && node.depth === 2)\n label = visuals.dataLabelUtils.getLabelFormattedText({\n label: node.name,\n maxWidth: spaceAvaliableForLabels\n }) + \" \" + label;\n }\n return visuals.dataLabelUtils.getLabelFormattedText({\n label: label,\n maxWidth: spaceAvaliableForLabels,\n fontSize: labelsSettings.fontSize\n });\n };\n Treemap.getFill = function (d, isHighlightRect) {\n // NOTE: only painted shapes will catch click event. We either paint children or their parent but not both.\n // If it's a leaf with no category, parent will be painted instead (and support interactivity)\n if (d.depth > 1 && !d.identity.hasIdentity() && !isHighlightRect)\n return CssConstants.noneValue;\n // If it's not a leaf and it has children with a category, children will be painted\n if (Treemap.hasChildrenWithIdentity(d))\n return CssConstants.noneValue;\n return d.color;\n };\n Treemap.getFillOpacity = function (d, hasSelection, hasHighlights, isHighlightRect) {\n if (hasHighlights) {\n if (isHighlightRect)\n return null;\n return Treemap.DimmedShapeOpacity.toString();\n }\n if (!hasSelection || d.selected)\n return null;\n // Parent node is selected (as an optimization, we only check below level 1 because root node cannot be selected anyway)\n if (d.depth > 1 && d.parent.selected)\n return null;\n // It's a parent node with interactive children, fall back to default opacity\n if (Treemap.hasChildrenWithIdentity(d))\n return null;\n return Treemap.DimmedShapeOpacity.toString();\n };\n Treemap.prototype.updateInternal = function (suppressAnimations) {\n var data = this.data;\n var hasHighlights = data && data.hasHighlights;\n var labelSettings = data ? data.dataLabelsSettings : null;\n var duration = visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n if (!(this.options.interactivity && this.options.interactivity.isInteractiveLegend) && this.data) {\n this.renderLegend();\n }\n this.initViewportDependantProperties(duration);\n var viewport = this.calculateTreemapSize();\n this.treemap.size([viewport.width, viewport.height]);\n // Shapes are drawn for all nodes\n var nodes = (data && data.root) ? this.treemap.nodes(data.root) : [];\n // Highlight shapes are drawn only for nodes with non-null/undefed highlightMultipliers that have no children\n var highlightNodes = nodes.filter(function (value) { return value.highlightMultiplier != null && (!value.children || value.children.length === 0); });\n var majorLabeledNodes = [];\n var minorLabeledNodes = [];\n var alternativeScale = null;\n // Only populate major labels if category labels are turned on\n if (labelSettings.showCategory) {\n majorLabeledNodes = nodes.filter(function (d) { return Treemap.canDisplayMajorLabel(d); });\n }\n // Only populate minor labels if category or data labels are turned on\n if (labelSettings.show || labelSettings.showCategory) {\n minorLabeledNodes = nodes.filter(function (d) { return Treemap.canDisplayMinorLabel(d, labelSettings); });\n // If the display unit is 0 we calculate the format scale using the maximum value available\n if (labelSettings.displayUnits === 0)\n alternativeScale = d3.max(minorLabeledNodes, function (d) { return Math.abs(d.value); });\n }\n var treemapLayout = Treemap.getLayout(labelSettings, alternativeScale);\n var shapes;\n var highlightShapes;\n var majorLabels;\n var minorLabels;\n var result;\n if (this.animator && !suppressAnimations) {\n var options = {\n viewModel: data,\n nodes: nodes,\n highlightNodes: highlightNodes,\n majorLabeledNodes: majorLabeledNodes,\n minorLabeledNodes: minorLabeledNodes,\n shapeGraphicsContext: this.shapeGraphicsContext,\n labelGraphicsContext: this.labelGraphicsContext,\n interactivityService: this.interactivityService,\n layout: treemapLayout,\n labelSettings: labelSettings,\n };\n result = this.animator.animate(options);\n shapes = result.shapes;\n highlightShapes = result.highlightShapes;\n majorLabels = result.majorLabels;\n minorLabels = result.minorLabels;\n }\n if (!this.animator || suppressAnimations || result.failed) {\n var hasSelection = this.interactivityService && this.interactivityService.hasSelection();\n var shapeGraphicsContext = this.shapeGraphicsContext;\n shapes = Treemap.drawDefaultShapes(shapeGraphicsContext, nodes, hasSelection, hasHighlights, treemapLayout);\n highlightShapes = Treemap.drawDefaultHighlightShapes(shapeGraphicsContext, highlightNodes, hasSelection, hasHighlights, treemapLayout);\n var labelGraphicsContext = this.labelGraphicsContext;\n majorLabels = Treemap.drawDefaultMajorLabels(labelGraphicsContext, majorLabeledNodes, labelSettings, treemapLayout);\n minorLabels = Treemap.drawDefaultMinorLabels(labelGraphicsContext, minorLabeledNodes, labelSettings, treemapLayout);\n }\n if (this.interactivityService) {\n var behaviorOptions = {\n shapes: shapes,\n highlightShapes: highlightShapes,\n majorLabels: majorLabels,\n minorLabels: minorLabels,\n nodes: nodes,\n hasHighlights: data.hasHighlights,\n };\n this.interactivityService.bind(nodes, this.behavior, behaviorOptions);\n }\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(shapes, function (tooltipEvent) { return tooltipEvent.data.highlightedTooltipInfo ? tooltipEvent.data.highlightedTooltipInfo : tooltipEvent.data.tooltipInfo; });\n visuals.TooltipManager.addTooltip(highlightShapes, function (tooltipEvent) { return tooltipEvent.data.highlightedTooltipInfo; });\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n };\n Treemap.prototype.renderLegend = function () {\n var legendObjectProperties = this.data.legendObjectProperties;\n if (legendObjectProperties) {\n var legendData = this.data.legendData;\n visuals.LegendData.update(legendData, legendObjectProperties);\n var position = legendObjectProperties[visuals.legendProps.position];\n if (position)\n this.legend.changeOrientation(visuals.LegendPosition[position]);\n this.legend.drawLegend(legendData, this.currentViewport);\n }\n else {\n // TODO: Draw should be the only API. Visuals should only call that with orientation, props, etc \n // instead of managing state. Will follow up with another change.\n this.legend.changeOrientation(visuals.LegendPosition.Top);\n this.legend.drawLegend({ dataPoints: [] }, this.currentViewport);\n }\n };\n Treemap.getNodeClass = function (d, highlight) {\n var nodeClass;\n switch (d.depth) {\n case 1:\n nodeClass = Treemap.ParentGroupClassName;\n break;\n case 2:\n nodeClass = Treemap.NodeGroupClassName;\n break;\n case 0:\n nodeClass = Treemap.RootNodeClassName;\n break;\n default:\n debug.assertFail('Treemap only supports 2 levels maxiumum');\n }\n nodeClass += \" \" + (highlight ? Treemap.HighlightNodeClassName : Treemap.TreemapNodeClassName);\n return nodeClass;\n };\n Treemap.createTreemapShapeLayout = function (isHighlightRect) {\n if (isHighlightRect === void 0) { isHighlightRect = false; }\n return {\n x: function (d) { return d.x; },\n y: function (d) { return d.y + (isHighlightRect ? d.dy * (1 - d.highlightMultiplier) : 0); },\n width: function (d) { return Math.max(0, d.dx); },\n height: function (d) { return Math.max(0, d.dy * (isHighlightRect ? d.highlightMultiplier : 1)); },\n };\n };\n Treemap.createTreemapZeroShapeLayout = function () {\n return {\n x: function (d) { return d.x; },\n y: function (d) { return d.y + d.dy; },\n width: function (d) { return Math.max(0, d.dx); },\n height: function (d) { return 0; },\n };\n };\n Treemap.drawDefaultShapes = function (context, nodes, hasSelection, hasHighlights, layout) {\n var isHighlightShape = false;\n var shapes = context.selectAll('.' + Treemap.TreemapNodeClassName)\n .data(nodes, function (d) { return d.key; });\n shapes.enter().append('rect')\n .attr('class', layout.shapeClass);\n shapes\n .style(\"fill\", function (d) { return Treemap.getFill(d, isHighlightShape); })\n .style(\"fill-opacity\", function (d) { return Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape); })\n .attr(layout.shapeLayout);\n shapes.exit().remove();\n return shapes;\n };\n Treemap.drawDefaultHighlightShapes = function (context, nodes, hasSelection, hasHighlights, layout) {\n var isHighlightShape = true;\n var highlightShapes = context.selectAll('.' + Treemap.HighlightNodeClassName)\n .data(nodes, function (d) { return d.key + \"highlight\"; });\n highlightShapes.enter().append('rect')\n .attr('class', layout.highlightShapeClass);\n highlightShapes\n .style(\"fill\", function (d) { return Treemap.getFill(d, isHighlightShape); })\n .style(\"fill-opacity\", function (d) { return Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape); })\n .attr(layout.highlightShapeLayout);\n highlightShapes.exit().remove();\n return highlightShapes;\n };\n Treemap.drawDefaultMajorLabels = function (context, nodes, labelSettings, layout) {\n var labels = context\n .selectAll('.' + Treemap.MajorLabelClassName)\n .data(nodes, function (d) { return d.key; });\n labels.enter().append('text')\n .attr('class', layout.majorLabelClass);\n labels\n .attr(layout.majorLabelLayout)\n .text(layout.majorLabelText)\n .style('fill', function () { return labelSettings.labelColor; });\n labels.exit().remove();\n return labels;\n };\n Treemap.drawDefaultMinorLabels = function (context, nodes, labelSettings, layout) {\n var labels = context\n .selectAll('.' + Treemap.MinorLabelClassName)\n .data(nodes, function (d) { return d.key; });\n labels.enter().append('text')\n .attr('class', layout.minorLabelClass);\n labels\n .attr(layout.minorLabelLayout)\n .text(layout.minorLabelText)\n .style('fill', function () { return labelSettings.labelColor; });\n labels.exit().remove();\n return labels;\n };\n Treemap.cleanMinorLabels = function (context) {\n var empty = [];\n var labels = context\n .selectAll('.' + Treemap.LabelsGroupClassName)\n .selectAll('.' + Treemap.MinorLabelClassName)\n .data(empty);\n labels.exit().remove();\n };\n Treemap.DimmedShapeOpacity = 0.4;\n Treemap.ClassName = 'treemap';\n Treemap.LabelsGroupClassName = \"labels\";\n Treemap.MajorLabelClassName = 'majorLabel';\n Treemap.MinorLabelClassName = 'minorLabel';\n Treemap.ShapesClassName = \"shapes\";\n Treemap.TreemapNodeClassName = \"treemapNode\";\n Treemap.RootNodeClassName = 'rootNode';\n Treemap.ParentGroupClassName = 'parentGroup';\n Treemap.NodeGroupClassName = 'nodeGroup';\n Treemap.HighlightNodeClassName = 'treemapNodeHighlight';\n Treemap.TextMargin = 5;\n Treemap.MinorLabelTextSize = 10;\n Treemap.MinTextWidthForMinorLabel = 18;\n Treemap.MajorLabelTextSize = 12;\n Treemap.MinTextWidthForMajorLabel = 22;\n Treemap.MajorLabelTextProperties = {\n fontFamily: 'wf_segoe-ui_normal',\n fontSize: Treemap.MajorLabelTextSize + 'px'\n };\n Treemap.ValuesRoleName = 'Values';\n /**\n * A rect with an area of 9 is a treemap rectangle of only\n * a single pixel in the middle with a 1 pixel stroke on each edge.\n */\n Treemap.CullableArea = 9;\n return Treemap;\n }());\n visuals.Treemap = Treemap;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var getKpiImageMetadata = powerbi.visuals.KpiUtil.getKpiImageMetadata;\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var Card = (function (_super) {\n __extends(Card, _super);\n function Card(options) {\n _super.call(this, Card.cardClassName);\n this.isScrollable = false;\n this.displayUnitSystemType = powerbi.DisplayUnitSystemType.WholeUnits;\n if (options) {\n this.isScrollable = !!options.isScrollable;\n if (options.animator)\n this.animator = options.animator;\n if (options.displayUnitSystemType != null)\n this.displayUnitSystemType = options.displayUnitSystemType;\n }\n }\n Card.prototype.init = function (options) {\n debug.assertValue(options, 'options');\n this.animationOptions = options.animation;\n var element = options.element;\n this.kpiImage = d3.select(element.get(0)).append('div')\n .classed(Card.KPIImage.class, true);\n var svg = this.svg = d3.select(element.get(0)).append('svg');\n this.graphicsContext = svg.append('g');\n this.currentViewport = options.viewport;\n this.hostServices = options.host;\n this.style = options.style;\n this.updateViewportProperties();\n if (this.isScrollable) {\n svg.attr('class', Card.cardClassName);\n this.labelContext = svg.append('g');\n }\n };\n Card.prototype.onDataChanged = function (options) {\n debug.assertValue(options, 'options');\n var dataView = options.dataViews[0];\n var value;\n if (dataView) {\n this.getMetaDataColumn(dataView);\n if (dataView.single) {\n value = dataView.single.value;\n }\n // Update settings based on new metadata column\n this.cardFormatSetting = this.getDefaultFormatSettings();\n var dataViewMetadata = dataView.metadata;\n if (dataViewMetadata) {\n var objects = dataViewMetadata.objects;\n if (objects) {\n var labelSettings = this.cardFormatSetting.labelSettings;\n labelSettings.labelColor = powerbi.DataViewObjects.getFillColor(objects, visuals.cardProps.labels.color, labelSettings.labelColor);\n labelSettings.precision = powerbi.DataViewObjects.getValue(objects, visuals.cardProps.labels.labelPrecision, labelSettings.precision);\n labelSettings.fontSize = powerbi.DataViewObjects.getValue(objects, visuals.cardProps.labels.fontSize, labelSettings.fontSize);\n // The precision can't go below 0\n if (labelSettings.precision !== visuals.dataLabelUtils.defaultLabelPrecision && labelSettings.precision < 0) {\n labelSettings.precision = 0;\n }\n labelSettings.displayUnits = powerbi.DataViewObjects.getValue(objects, visuals.cardProps.labels.labelDisplayUnits, labelSettings.displayUnits);\n //category labels\n labelSettings.showCategory = powerbi.DataViewObjects.getValue(objects, visuals.cardProps.categoryLabels.show, labelSettings.showCategory);\n labelSettings.categoryLabelColor = powerbi.DataViewObjects.getFillColor(objects, visuals.cardProps.categoryLabels.color, labelSettings.categoryLabelColor);\n this.cardFormatSetting.wordWrap = powerbi.DataViewObjects.getValue(objects, visuals.cardProps.wordWrap.show, this.cardFormatSetting.wordWrap);\n this.cardFormatSetting.textSize = powerbi.DataViewObjects.getValue(objects, visuals.cardProps.categoryLabels.fontSize, this.cardFormatSetting.textSize);\n }\n }\n }\n this.updateInternal(value, true /* suppressAnimations */, true /* forceUpdate */);\n };\n Card.prototype.onResizing = function (viewport) {\n this.currentViewport = viewport;\n this.updateViewportProperties();\n this.updateInternal(this.value, true /* suppressAnimations */, true /* forceUpdate */);\n };\n Card.prototype.updateViewportProperties = function () {\n var viewport = this.currentViewport;\n this.svg.attr('width', viewport.width)\n .attr('height', viewport.height);\n };\n Card.prototype.setTextProperties = function (text, fontSize) {\n Card.cardTextProperties.fontSize = jsCommon.PixelConverter.fromPoint(fontSize);\n Card.cardTextProperties.text = text;\n };\n Card.prototype.getCardFormatTextSize = function () {\n return this.cardFormatSetting.textSize;\n };\n Card.prototype.getAdjustedFontHeight = function (availableWidth, textToMeasure, seedFontHeight) {\n var adjustedFontHeight = _super.prototype.getAdjustedFontHeight.call(this, availableWidth, textToMeasure, seedFontHeight);\n return Math.min(adjustedFontHeight, Card.DefaultStyle.card.maxFontSize);\n };\n Card.prototype.clear = function (valueOnly) {\n if (valueOnly === void 0) { valueOnly = false; }\n this.svg.select(Card.Value.selector).text('');\n if (!valueOnly)\n this.svg.select(Card.Label.selector).text('');\n _super.prototype.clear.call(this);\n };\n Card.prototype.updateInternal = function (target, suppressAnimations, forceUpdate) {\n if (forceUpdate === void 0) { forceUpdate = false; }\n var start = this.value;\n var duration = visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n if (target === undefined) {\n if (start !== undefined)\n this.clear();\n return;\n }\n var metaDataColumn = this.metaDataColumn;\n var labelSettings = this.cardFormatSetting.labelSettings;\n var isDefaultDisplayUnit = labelSettings.displayUnits === 0;\n var format = this.getFormatString(metaDataColumn);\n var formatter = visuals.valueFormatter.create({\n format: format,\n value: isDefaultDisplayUnit ? target : labelSettings.displayUnits,\n precision: visuals.dataLabelUtils.getLabelPrecision(labelSettings.precision, format),\n displayUnitSystemType: isDefaultDisplayUnit && labelSettings.precision === visuals.dataLabelUtils.defaultLabelPrecision ? this.displayUnitSystemType : powerbi.DisplayUnitSystemType.WholeUnits,\n formatSingleValues: isDefaultDisplayUnit ? true : false,\n allowFormatBeautification: true,\n columnType: metaDataColumn ? metaDataColumn.type : undefined\n });\n var formatSettings = this.cardFormatSetting;\n var valueTextHeightInPx = jsCommon.PixelConverter.fromPointToPixel(labelSettings.fontSize);\n var valueStyles = Card.DefaultStyle.value;\n this.setTextProperties(target, this.getCardFormatTextSize());\n var labelTextHeightInPx = powerbi.TextMeasurementService.estimateSvgTextHeight(Card.cardTextProperties);\n var labelHeightWithPadding = labelTextHeightInPx + Card.DefaultStyle.label.paddingTop;\n var width = this.currentViewport.width;\n var height = this.currentViewport.height;\n var translateX = this.getTranslateX(width);\n var translateY = (height - labelHeightWithPadding - valueTextHeightInPx) / 2;\n var statusGraphicInfo = getKpiImageMetadata(metaDataColumn, target, 1 /* Big */);\n if (this.isScrollable) {\n if (!forceUpdate && start === target)\n return;\n // We want to format for null/blank/empty string and anything that is not a string\n if (start !== target && (_.isEmpty(target) || typeof (target) !== \"string\"))\n target = formatter.format(target);\n var label = metaDataColumn ? metaDataColumn.displayName : undefined;\n var labelData = labelSettings.showCategory\n ? [label]\n : [];\n var translatedLabelY = this.getTranslateY(valueTextHeightInPx + labelHeightWithPadding + translateY);\n var labelElement = this.labelContext\n .attr('transform', visuals.SVGUtil.translate(translateX, translatedLabelY))\n .selectAll('text')\n .data(labelData);\n labelElement\n .enter()\n .append('text')\n .attr('class', Card.Label.class);\n labelElement\n .text(function (d) { return d; })\n .style({\n 'font-size': jsCommon.PixelConverter.fromPoint(this.getCardFormatTextSize()),\n 'fill': labelSettings.categoryLabelColor,\n 'text-anchor': this.getTextAnchor()\n });\n var labelElementNode = labelElement.node();\n if (labelElementNode) {\n if (formatSettings.wordWrap)\n powerbi.TextMeasurementService.wordBreak(labelElementNode, width / 2, height - translatedLabelY);\n else\n labelElement.call(visuals.AxisHelper.LabelLayoutStrategy.clip, width, powerbi.TextMeasurementService.svgEllipsis);\n }\n labelElement\n .append('title')\n .text(function (d) { return d; });\n labelElement.exit().remove();\n if (statusGraphicInfo) {\n // Display card KPI icon\n this.graphicsContext.selectAll('text').remove();\n this.displayStatusGraphic(statusGraphicInfo, translateX, translateY, valueTextHeightInPx);\n }\n else {\n // Display card text value\n this.kpiImage.selectAll('div').remove();\n var valueElement = this.graphicsContext\n .attr('transform', visuals.SVGUtil.translate(translateX, this.getTranslateY(valueTextHeightInPx + translateY)))\n .selectAll('text')\n .data([target]);\n valueElement\n .enter()\n .append('text')\n .attr('class', Card.Value.class);\n valueElement\n .text(function (d) { return d; })\n .style({\n 'font-size': jsCommon.PixelConverter.fromPoint(labelSettings.fontSize),\n 'fill': labelSettings.labelColor,\n 'font-family': valueStyles.fontFamily,\n 'text-anchor': this.getTextAnchor(),\n });\n valueElement.call(visuals.AxisHelper.LabelLayoutStrategy.clip, width, powerbi.TextMeasurementService.svgEllipsis);\n valueElement\n .append('title')\n .text(function (d) { return d; });\n valueElement.exit().remove();\n }\n }\n else {\n if (statusGraphicInfo) {\n // Display card KPI icon\n this.graphicsContext.selectAll('text').remove();\n this.displayStatusGraphic(statusGraphicInfo, translateX, translateY, valueTextHeightInPx);\n }\n else {\n this.kpiImage.selectAll('div').remove();\n this.doValueTransition(start, target, this.displayUnitSystemType, this.animationOptions, duration, forceUpdate, formatter);\n //in order to remove duplicated title values we first remove all and than add a new one\n this.graphicsContext.call(visuals.tooltipUtils.tooltipUpdate, [target]);\n }\n }\n this.value = target;\n };\n Card.prototype.displayStatusGraphic = function (statusGraphicInfo, translateX, translateY, labelTextSizeInPx) {\n // Remove existing text\n this.graphicsContext.selectAll('text').remove();\n // Create status graphic, if necessary\n var kpiImageDiv = this.kpiImage.select('div');\n if (!kpiImageDiv || kpiImageDiv.empty())\n kpiImageDiv = this.kpiImage.append('div');\n // Style status graphic\n kpiImageDiv\n .attr('class', statusGraphicInfo.class)\n .style('position', 'absolute')\n .style('font-size', labelTextSizeInPx + 'px');\n // Layout thrash to get image dimensions (could set as a const in future when icon font is fixed)\n var imageWidth = kpiImageDiv.node().offsetWidth;\n var imageHeight = kpiImageDiv.node().offsetHeight;\n // Position based on image height\n kpiImageDiv.style('transform', visuals.SVGUtil.translateWithPixels((translateX - (imageWidth / 2)), this.getTranslateY(labelTextSizeInPx + translateY) - imageHeight));\n };\n Card.prototype.getDefaultFormatSettings = function () {\n return {\n labelSettings: visuals.dataLabelUtils.getDefaultCardLabelSettings(Card.DefaultStyle.value.color, Card.DefaultStyle.label.color, Card.DefaultStyle.value.textSize),\n wordWrap: false,\n textSize: Card.DefaultStyle.label.textSize,\n };\n };\n Card.prototype.enumerateObjectInstances = function (options) {\n if (!this.cardFormatSetting)\n this.cardFormatSetting = this.getDefaultFormatSettings();\n var formatSettings = this.cardFormatSetting;\n var enumeration = new visuals.ObjectEnumerationBuilder();\n switch (options.objectName) {\n case 'categoryLabels':\n visuals.dataLabelUtils.enumerateCategoryLabels(enumeration, formatSettings.labelSettings, true /* withFill */, true /* isShowCategory */, formatSettings.textSize);\n break;\n case 'labels':\n var labelSettingOptions = {\n enumeration: enumeration,\n dataLabelsSettings: formatSettings.labelSettings,\n show: true,\n displayUnits: true,\n precision: true,\n fontSize: true,\n };\n visuals.dataLabelUtils.enumerateDataLabels(labelSettingOptions);\n break;\n case 'wordWrap':\n enumeration.pushInstance({\n objectName: 'wordWrap',\n selector: null,\n properties: {\n show: formatSettings.wordWrap,\n },\n });\n break;\n }\n return enumeration.complete();\n };\n Card.cardClassName = 'card';\n Card.Label = createClassAndSelector('label');\n Card.Value = createClassAndSelector('value');\n Card.KPIImage = createClassAndSelector('caption');\n Card.cardTextProperties = {\n fontSize: null,\n text: null,\n fontFamily: visuals.dataLabelUtils.LabelTextProperties.fontFamily,\n };\n Card.DefaultStyle = {\n card: {\n maxFontSize: 200\n },\n label: {\n textSize: 12,\n color: '#a6a6a6',\n paddingTop: 8\n },\n value: {\n textSize: 27,\n color: '#333333',\n fontFamily: 'wf_standard-font'\n }\n };\n return Card;\n }(visuals.AnimatedText));\n visuals.Card = Card;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var OwlHappiness;\n (function (OwlHappiness) {\n OwlHappiness[OwlHappiness[\"Sad\"] = 0] = \"Sad\";\n OwlHappiness[OwlHappiness[\"Meh\"] = 1] = \"Meh\";\n OwlHappiness[OwlHappiness[\"Happy\"] = 2] = \"Happy\";\n })(OwlHappiness || (OwlHappiness = {}));\n var OwlGauge = (function () {\n function OwlGauge() {\n }\n OwlGauge.converter = function (dataView) {\n return {};\n };\n OwlGauge.getGaugeData = function (dataView) {\n var settings = {\n max: 100,\n min: 0,\n target: undefined,\n total: 0,\n tooltipItems: []\n };\n if (dataView && dataView.categorical && dataView.categorical.values && dataView.metadata && dataView.metadata.columns) {\n var values = dataView.categorical.values;\n var metadataColumns = dataView.metadata.columns;\n debug.assert(metadataColumns.length >= values.length, 'length');\n for (var i = 0; i < values.length; i++) {\n var col = metadataColumns[i], value = values[i].values[0] || 0;\n if (col && col.roles) {\n if (col.roles[visuals.gaugeRoleNames.y]) {\n settings.total = value;\n if (value)\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: visuals.converterHelper.formatFromMetadataColumn(value, values[i].source, visuals.Gauge.formatStringProp) });\n }\n else if (col.roles[visuals.gaugeRoleNames.minValue]) {\n settings.min = value;\n }\n else if (col.roles[visuals.gaugeRoleNames.maxValue]) {\n settings.max = value;\n }\n else if (col.roles[visuals.gaugeRoleNames.targetValue]) {\n settings.target = value;\n if (value)\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: visuals.converterHelper.formatFromMetadataColumn(value, values[i].source, visuals.Gauge.formatStringProp) });\n }\n }\n }\n }\n return settings;\n };\n OwlGauge.prototype.init = function (options) {\n var _this = this;\n this.rootElem = options.element;\n this.rootElem.addClass('owlGaugeVisual');\n this.svgTailElem = $(OwlGauge.owlTailSvg);\n this.svgBgElem = $(OwlGauge.visualBgSvg);\n this.svgBodyElem = $(OwlGauge.owlBodySvg);\n this.rootElem.append(this.svgBgElem).append(this.svgTailElem).append(this.svgBodyElem);\n if (OwlGauge.OwlDemoMode) {\n window.setInterval(function () {\n var randomPercentage = Math.random() * 100 + 1;\n _this.updateGauge(randomPercentage);\n }, 2000);\n }\n this.updateViewportSize(options.viewport.width, options.viewport.height);\n };\n OwlGauge.prototype.update = function (options) {\n this.updateViewportSize(options.viewport.width, options.viewport.height);\n var dataView = options.dataViews.length > 0 ? options.dataViews[0] : null;\n if (dataView) {\n var gaugeData = OwlGauge.getGaugeData(options.dataViews[0]);\n var percentage = (gaugeData.total - gaugeData.min) / (gaugeData.max - gaugeData.min);\n this.updateGauge(percentage * 100 | 0);\n }\n else\n this.updateGauge(0);\n };\n OwlGauge.prototype.updateGauge = function (percentage) {\n if (percentage >= 0 && percentage <= 100) {\n var rotationDeg = -180 + (180 * percentage / 100);\n this.svgBgElem.css({ transform: 'rotate(' + rotationDeg + 'deg)' });\n if (percentage >= 66) {\n this.happinessLevel = OwlHappiness.Happy;\n }\n else if (percentage >= 33) {\n this.happinessLevel = OwlHappiness.Meh;\n }\n else {\n this.happinessLevel = OwlHappiness.Sad;\n }\n }\n };\n Object.defineProperty(OwlGauge.prototype, \"happinessLevel\", {\n set: function (level) {\n this.rootElem.removeClass('sad').removeClass('meh').removeClass('happy');\n switch (level) {\n case OwlHappiness.Sad:\n this.rootElem.addClass('sad');\n break;\n case OwlHappiness.Meh:\n this.rootElem.addClass('meh');\n break;\n case OwlHappiness.Happy:\n this.rootElem.addClass('happy');\n break;\n default:\n console.log('Well, this is interesting...');\n }\n },\n enumerable: true,\n configurable: true\n });\n OwlGauge.prototype.updateViewportSize = function (width, height) {\n var _this = this;\n var smoothingFn = window.setImmediate || window.requestAnimationFrame;\n smoothingFn(function () {\n _this.rootElem.css({\n height: height,\n width: width\n });\n _this.svgBodyElem.height(_this.svgBodyElem.width() * OwlGauge.owlBodyHeightMultiplier);\n _this.svgBgElem.height(_this.svgBgElem.width() * OwlGauge.visualBgHeightMultiplier);\n _this.svgTailElem.height(_this.svgTailElem.width() * OwlGauge.owlTailHeightMultiplier);\n });\n };\n OwlGauge.owlBodySvg = '<svg version=\"1.1\" class=\"owlGaugeBody\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 267.7 291.2\" style=\"enable-background:new 0 0 267.7 291.2;\" xml:space=\"preserve\"> <style type=\"text/css\"> .owlGaugeBody .st0{fill:#A87D50;} .owlGaugeBody .st1{fill:#C2B59B;} .owlGaugeBody .st2{fill:#EB2227;} .owlGaugeBody .st3{fill:#FFFFFF;} .owlGaugeBody .st4{fill:#F9D018;} .owlGaugeBody .st5{fill:none;} .owlGaugeBody .st6{fill:#83381B;} .owlGaugeBody .st7{fill:#231F20;} </style> <g id=\"XMLID_31_\"> <g id=\"XMLID_34_\"> <ellipse id=\"XMLID_21_\" transform=\"matrix(0.9998 1.947640e-02 -1.947640e-02 0.9998 2.8614 -2.5802)\" class=\"st0\" cx=\"133.9\" cy=\"145.6\" rx=\"133.9\" ry=\"145.6\"/> <polygon id=\"XMLID_20_\" class=\"st0\" points=\"199.2,32.8 184,11.3 209,9.7 \"/> <polygon id=\"XMLID_19_\" class=\"st0\" points=\"73.9,31.2 62.1,7.7 87.1,9.8 \"/> <circle id=\"XMLID_18_\" class=\"st1\" cx=\"134.8\" cy=\"189.2\" r=\"89.8\"/> <path id=\"XMLID_17_\" class=\"st2\" d=\"M140.1,88c-2.7,3.8-7.9,4.7-11.7,2c-2.7-1.9-3.9-5.1-3.4-8.1c0,0,9.6-41.8,9.6-41.8l6.9,40.8 C142,83.2,141.6,85.8,140.1,88z\"/> <path id=\"XMLID_16_\" class=\"st3\" d=\"M164.6,16.2c-14.2,0-26.3,9.2-30.6,21.9c-4.1-13.1-16.3-22.6-30.8-22.6 C85.4,15.6,71,30,71,47.8s14.4,32.3,32.3,32.3c14.2,0,26.3-9.2,30.6-21.9c4.1,13.1,16.3,22.6,30.8,22.6 c17.8,0,32.3-14.4,32.3-32.3S182.4,16.2,164.6,16.2z\"/> <path id=\"XMLID_15_\" class=\"st4\" d=\"M122,58.7l23.3-0.1c0,0-9,14.8-10.2,16.6c-1.2,1.9-2.2,0.1-2.2,0.1L122,58.7z\"/> <rect id=\"XMLID_14_\" x=\"-11.4\" y=\"-68.8\" class=\"st5\" width=\"288.3\" height=\"259.7\"/> <g id=\"XMLID_37_\"> <path id=\"XMLID_13_\" class=\"st6\" d=\"M121.6,125.5c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_12_\" class=\"st6\" d=\"M160.1,126.5c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_11_\" class=\"st6\" d=\"M142.4,148.1c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_10_\" class=\"st6\" d=\"M183.1,148.8c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_9_\" class=\"st6\" d=\"M160.9,177.4c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_8_\" class=\"st6\" d=\"M201.6,178c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_7_\" class=\"st6\" d=\"M76.4,177.4c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_6_\" class=\"st6\" d=\"M117,178c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_5_\" class=\"st6\" d=\"M98.6,148.1c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> </g> <circle id=\"XMLID_4_\" class=\"st7\" cx=\"164.1\" cy=\"49\" r=\"6.4\"/> <circle id=\"XMLID_3_\" class=\"st7\" cx=\"102.7\" cy=\"47.7\" r=\"6.4\"/> </g> <path id=\"XMLID_2_\" class=\"st0\" d=\"M160.1,140.9c11.1-8.4,55.6-36,55.6-36l4.7,0.8l10.2,38.8c0,0-3,3-9.2,3.1 c-5.1,0.1-45.9-2.6-60.2-3.5C158.1,143.9,157.7,142.7,160.1,140.9z\"/> <path id=\"XMLID_1_\" class=\"st0\" d=\"M110.6,140.8c-11.1-8.4-55.6-36-55.6-36l-4.7,0.8L40,144.4c0,0,3,3,9.2,3.1 c5.1,0.1,45.9-2.6,60.2-3.5C112.5,143.8,113,142.6,110.6,140.8z\"/> </g> </svg>';\n OwlGauge.owlTailSvg = '<svg version=\"1.1\" class=\"owlGaugeTail\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 587.8 295.5\" style=\"enable-background:new 0 0 587.8 295.5;\" xml:space=\"preserve\"> <style type=\"text/css\"> .owlGaugeTail .st0{fill:#3B2416;} .owlGaugeTail .st1{fill:#5B4B43;} .owlGaugeTail .st2{fill:#603A17;} .owlGaugeTail .st3{fill:#726659;} </style> <g id=\"XMLID_55_\"> <path id=\"XMLID_29_\" class=\"st0\" d=\"M85.2,106.2c-27.1,0-49.2,22-49.2,49.2c0,19.1,10.9,35.7,26.9,43.8c0,0,231.2,95.9,231.2,95.9 l-171-171C114.1,113.2,100.5,106.2,85.2,106.2z\"/> <g id=\"XMLID_56_\"> <path id=\"XMLID_28_\" class=\"st1\" d=\"M482.5,86.4c0-27.1-22-49.2-49.2-49.2c-19.1,0-35.7,10.9-43.8,26.9c0,0-95.9,231.2-95.9,231.2 l171-171C475.5,115.3,482.5,101.7,482.5,86.4z\"/> <path id=\"XMLID_27_\" class=\"st2\" d=\"M573.5,281.3c19.2-19.2,19.2-50.3,0-69.5c-13.5-13.5-33-17.5-50-12c0,0-231.3,95.7-231.3,95.7 l241.8,0C548,296.9,562.6,292.1,573.5,281.3z\"/> <path id=\"XMLID_26_\" class=\"st3\" d=\"M279.9,14.4c-19.2-19.2-50.3-19.2-69.5,0c-13.5,13.5-17.5,33-12,50c0,0,95.7,231.3,95.7,231.3 L294,54C295.4,39.8,290.7,25.2,279.9,14.4z\"/> <path id=\"XMLID_25_\" class=\"st2\" d=\"M105.3,86.4c0-27.1,22-49.2,49.2-49.2c19.1,0,35.7,10.9,43.8,26.9c0,0,95.9,231.2,95.9,231.2 l-171-171C112.3,115.3,105.3,101.7,105.3,86.4z\"/> <path id=\"XMLID_24_\" class=\"st2\" d=\"M14.4,281.4c-19.2-19.2-19.2-50.3,0-69.5c13.5-13.5,33-17.5,50-12c0,0,231.3,95.7,231.3,95.7 l-241.8,0C39.8,297,25.2,292.3,14.4,281.4z\"/> <path id=\"XMLID_23_\" class=\"st2\" d=\"M308.2,14c19.2-19.2,50.3-19.2,69.5,0c13.5,13.5,17.5,33,12,50c0,0-95.7,231.3-95.7,231.3 l0-241.8C292.6,39.4,297.4,24.8,308.2,14z\"/> <path id=\"XMLID_22_\" class=\"st0\" d=\"M503.2,106c27.1,0,49.2,22,49.2,49.2c0,19.1-10.9,35.7-26.9,43.8c0,0-231.2,95.9-231.2,95.9 l171-171C474.2,113,487.8,106,503.2,106z\"/> </g> </g> </svg>';\n OwlGauge.visualBgSvg = '<svg version=\"1.1\" class=\"owlGaugeBg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"123.8 94.9 349.1 175.3\" style=\"enable-background:new 123.8 94.9 349.1 175.3;\" xml:space=\"preserve\"> <style type=\"text/css\"> .owlGaugeBg .st0{fill:#EF4137;} .owlGaugeBg .st1{fill:#FAAF42;} .owlGaugeBg .st2{fill:#F15B2A;} .owlGaugeBg .st3{fill:#F69321;} </style> <g id=\"XMLID_10_\"> <path id=\"XMLID_8_\" class=\"st0\" d=\"M174.3,158c-16.1,0-29.2,13.1-29.2,29.2c0,11.4,6.5,21.2,16,26.1l137.3,57L196.9,168.7 C191.5,162.2,183.4,158,174.3,158z\"/> <g id=\"XMLID_11_\"> <path id=\"XMLID_7_\" class=\"st1\" d=\"M410.2,146.3c0-16.1-13.1-29.2-29.2-29.2c-11.4,0-21.2,6.5-26,16l-57,137.5L399.5,169 C406.1,163.5,410.2,155.4,410.2,146.3z\"/> <path id=\"XMLID_6_\" class=\"st0\" d=\"M464.3,262.2c11.4-11.4,11.4-29.9,0-41.3c-8-8-19.6-10.4-29.7-7.1l-137.4,56.9h143.6 C449.2,271.4,457.9,268.6,464.3,262.2z\"/> <path id=\"XMLID_5_\" class=\"st2\" d=\"M290,103.5c-11.4-11.4-29.9-11.4-41.3,0c-8,8-10.4,19.6-7.1,29.7l56.8,137.5V127 C299.2,118.6,296.4,109.9,290,103.5z\"/> <path id=\"XMLID_4_\" class=\"st3\" d=\"M186.3,146.3c0-16.1,13.1-29.2,29.2-29.2c11.4,0,21.2,6.5,26,16l57,137.5L197,168.8 C190.5,163.5,186.3,155.4,186.3,146.3z\"/> <path id=\"XMLID_3_\" class=\"st2\" d=\"M132.3,262.2c-11.4-11.4-11.4-29.9,0-41.3c8-8,19.6-10.4,29.7-7.1l137.4,56.9H155.8 C147.4,271.5,138.7,268.7,132.3,262.2z\"/> <path id=\"XMLID_2_\" class=\"st3\" d=\"M306.8,103.2c11.4-11.4,29.9-11.4,41.3,0c8,8,10.4,19.6,7.1,29.7l-56.8,137.5V126.7 C297.5,118.3,300.3,109.7,306.8,103.2z\"/> <path id=\"XMLID_1_\" class=\"st2\" d=\"M422.5,157.9c16.1,0,29.2,13.1,29.2,29.2c0,11.4-6.5,21.2-16,26.1l-137.3,57L400,168.6 C405.3,162.1,413.4,157.9,422.5,157.9z\"/> </g> </g> </svg>';\n OwlGauge.owlBodyHeightMultiplier = 291.2 / 267.7;\n OwlGauge.owlTailHeightMultiplier = 295.5 / 587.8;\n OwlGauge.visualBgHeightMultiplier = 295.5 / 587.8;\n OwlGauge.OwlDemoMode = false;\n OwlGauge.capabilities = {\n dataRoles: [\n {\n displayName: 'Category',\n name: 'Category',\n kind: powerbi.VisualDataRoleKind.Grouping,\n },\n {\n displayName: 'Y Axis',\n name: 'Y',\n kind: powerbi.VisualDataRoleKind.Measure,\n },\n ],\n dataViewMappings: [{\n categories: {\n for: { in: 'Category' },\n dataReductionAlgorithm: { top: {} }\n },\n values: {\n select: [{ bind: { to: 'Y' } }]\n },\n }]\n };\n return OwlGauge;\n }());\n visuals.OwlGauge = OwlGauge;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var NoMapLocationWarning = (function () {\n function NoMapLocationWarning() {\n }\n Object.defineProperty(NoMapLocationWarning.prototype, \"code\", {\n get: function () {\n return 'NoMapLocation';\n },\n enumerable: true,\n configurable: true\n });\n NoMapLocationWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'NoMapLocationMessage';\n var titleKey = 'NoMapLocationKey';\n var detailKey = 'NoMapLocationValue';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: resourceProvider.get(titleKey),\n detail: resourceProvider.get(detailKey),\n };\n return visualMessage;\n };\n return NoMapLocationWarning;\n }());\n visuals.NoMapLocationWarning = NoMapLocationWarning;\n var FilledMapWithoutValidGeotagCategoryWarning = (function () {\n function FilledMapWithoutValidGeotagCategoryWarning() {\n }\n Object.defineProperty(FilledMapWithoutValidGeotagCategoryWarning.prototype, \"code\", {\n get: function () {\n return 'NoValidGeotaggedCategory';\n },\n enumerable: true,\n configurable: true\n });\n FilledMapWithoutValidGeotagCategoryWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'NoValidGeotaggedCategoryMessage';\n var titleKey = 'NoValidGeotaggedCategoryKey';\n var detailKey = 'NoValidGeotaggedCategoryValue';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: resourceProvider.get(titleKey),\n detail: resourceProvider.get(detailKey),\n };\n return visualMessage;\n };\n return FilledMapWithoutValidGeotagCategoryWarning;\n }());\n visuals.FilledMapWithoutValidGeotagCategoryWarning = FilledMapWithoutValidGeotagCategoryWarning;\n var GeometryCulledWarning = (function () {\n function GeometryCulledWarning() {\n }\n Object.defineProperty(GeometryCulledWarning.prototype, \"code\", {\n get: function () {\n return 'GeometryCulledWarning';\n },\n enumerable: true,\n configurable: true\n });\n GeometryCulledWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'GeometryCulledWarningMessage';\n var titleKey = 'GeometryCulledWarningKey';\n var detailKey = 'GeometryCulledWarningVal';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: resourceProvider.get(titleKey),\n detail: resourceProvider.get(detailKey),\n };\n return visualMessage;\n };\n return GeometryCulledWarning;\n }());\n visuals.GeometryCulledWarning = GeometryCulledWarning;\n var NegativeValuesNotSupportedWarning = (function () {\n function NegativeValuesNotSupportedWarning() {\n }\n Object.defineProperty(NegativeValuesNotSupportedWarning.prototype, \"code\", {\n get: function () {\n return 'NegativeValuesNotSupported';\n },\n enumerable: true,\n configurable: true\n });\n NegativeValuesNotSupportedWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'VisualWarning_NegativeValues';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: '',\n detail: '',\n };\n return visualMessage;\n };\n return NegativeValuesNotSupportedWarning;\n }());\n visuals.NegativeValuesNotSupportedWarning = NegativeValuesNotSupportedWarning;\n var AllNegativeValuesWarning = (function () {\n function AllNegativeValuesWarning() {\n }\n Object.defineProperty(AllNegativeValuesWarning.prototype, \"code\", {\n get: function () {\n return 'AllNegativeValuesNotSupported';\n },\n enumerable: true,\n configurable: true\n });\n AllNegativeValuesWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'VisualWarning_AllNegativeValues';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: '',\n detail: '',\n };\n return visualMessage;\n };\n return AllNegativeValuesWarning;\n }());\n visuals.AllNegativeValuesWarning = AllNegativeValuesWarning;\n var NaNNotSupportedWarning = (function () {\n function NaNNotSupportedWarning() {\n }\n Object.defineProperty(NaNNotSupportedWarning.prototype, \"code\", {\n get: function () {\n return 'NaNNotSupported';\n },\n enumerable: true,\n configurable: true\n });\n NaNNotSupportedWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'VisualWarning_NanValues';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: '',\n detail: '',\n };\n return visualMessage;\n };\n return NaNNotSupportedWarning;\n }());\n visuals.NaNNotSupportedWarning = NaNNotSupportedWarning;\n var InfinityValuesNotSupportedWarning = (function () {\n function InfinityValuesNotSupportedWarning() {\n }\n Object.defineProperty(InfinityValuesNotSupportedWarning.prototype, \"code\", {\n get: function () {\n return 'InfinityValuesNotSupported';\n },\n enumerable: true,\n configurable: true\n });\n InfinityValuesNotSupportedWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'VisualWarning_InfinityValues';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: '',\n detail: '',\n };\n return visualMessage;\n };\n return InfinityValuesNotSupportedWarning;\n }());\n visuals.InfinityValuesNotSupportedWarning = InfinityValuesNotSupportedWarning;\n var ValuesOutOfRangeWarning = (function () {\n function ValuesOutOfRangeWarning() {\n }\n Object.defineProperty(ValuesOutOfRangeWarning.prototype, \"code\", {\n get: function () {\n return 'ValuesOutOfRange';\n },\n enumerable: true,\n configurable: true\n });\n ValuesOutOfRangeWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'VisualWarning_VisualizationOutOfRange';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: '',\n detail: '',\n };\n return visualMessage;\n };\n return ValuesOutOfRangeWarning;\n }());\n visuals.ValuesOutOfRangeWarning = ValuesOutOfRangeWarning;\n var ZeroValueWarning = (function () {\n function ZeroValueWarning() {\n }\n Object.defineProperty(ZeroValueWarning.prototype, \"code\", {\n get: function () {\n return \"ZeroValuesNotSupported\";\n },\n enumerable: true,\n configurable: true\n });\n ZeroValueWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'VisualWarning_ZeroValues';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: '',\n detail: '',\n };\n return visualMessage;\n };\n return ZeroValueWarning;\n }());\n visuals.ZeroValueWarning = ZeroValueWarning;\n var VisualKPIDataMissingWarning = (function () {\n function VisualKPIDataMissingWarning() {\n }\n Object.defineProperty(VisualKPIDataMissingWarning.prototype, \"code\", {\n get: function () {\n return \"VisualKPIDataMissing\";\n },\n enumerable: true,\n configurable: true\n });\n VisualKPIDataMissingWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'Visual_KPI_DataMissing';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: '',\n detail: '',\n };\n return visualMessage;\n };\n return VisualKPIDataMissingWarning;\n }());\n visuals.VisualKPIDataMissingWarning = VisualKPIDataMissingWarning;\n var ScriptVisualRefreshWarning = (function () {\n function ScriptVisualRefreshWarning() {\n }\n Object.defineProperty(ScriptVisualRefreshWarning.prototype, \"code\", {\n get: function () {\n return \"ScriptVisualNotRefreshed\";\n },\n enumerable: true,\n configurable: true\n });\n ScriptVisualRefreshWarning.prototype.getMessages = function (resourceProvider) {\n var messageKey = 'ScriptVisualRefreshWarningMessage';\n var detailKey = 'ScriptVisualRefreshWarningValue';\n var visualMessage = {\n message: resourceProvider.get(messageKey),\n title: resourceProvider.get(messageKey),\n detail: resourceProvider.get(detailKey),\n };\n return visualMessage;\n };\n return ScriptVisualRefreshWarning;\n }());\n visuals.ScriptVisualRefreshWarning = ScriptVisualRefreshWarning;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var PixelConverter = jsCommon.PixelConverter;\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n var WaterfallChart = (function () {\n function WaterfallChart(options) {\n this.isScrollable = options.isScrollable;\n this.tooltipsEnabled = options.tooltipsEnabled;\n this.interactivityService = options.interactivityService;\n }\n WaterfallChart.prototype.init = function (options) {\n debug.assertValue(options, 'options');\n this.svg = options.svg;\n this.svg.classed(WaterfallChart.WaterfallClassName, true);\n this.style = options.style;\n this.currentViewport = options.viewport;\n this.hostServices = options.host;\n this.interactivity = options.interactivity;\n this.cartesianVisualHost = options.cartesianHost;\n this.options = options;\n this.element = options.element;\n this.colors = this.style.colorPalette.dataColors;\n this.mainGraphicsSVG = this.svg.append('svg');\n this.mainGraphicsContext = this.mainGraphicsSVG.append('g')\n .classed(WaterfallChart.MainGraphicsContextClassName, true);\n this.labelGraphicsContext = this.mainGraphicsSVG.append('g')\n .classed(visuals.NewDataLabelUtils.labelGraphicsContextClass.class, true);\n };\n WaterfallChart.converter = function (dataView, palette, hostServices, dataLabelSettings, sentimentColors, interactivityService, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n debug.assertValue(palette, 'palette');\n var reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n var formatStringProp = WaterfallChart.formatStringProp;\n var categories = dataView.categorical.categories || [];\n var increaseColor = sentimentColors.increaseFill.solid.color;\n var decreaseColor = sentimentColors.decreaseFill.solid.color;\n var totalColor = sentimentColors.totalFill.solid.color;\n var totalLabel = hostServices.getLocalizedString(WaterfallChart.TotalLabel);\n var increaseLabel = hostServices.getLocalizedString(WaterfallChart.IncreaseLabel);\n var decreaseLabel = hostServices.getLocalizedString(WaterfallChart.DecreaseLabel);\n var legend = [\n {\n label: increaseLabel,\n color: increaseColor,\n icon: visuals.LegendIcon.Box,\n identity: visuals.SelectionIdBuilder.builder().withMeasure('increase').createSelectionId(),\n selected: false,\n }, {\n label: decreaseLabel,\n color: decreaseColor,\n icon: visuals.LegendIcon.Box,\n identity: visuals.SelectionIdBuilder.builder().withMeasure('decrease').createSelectionId(),\n selected: false,\n }, {\n label: totalLabel,\n color: totalColor,\n icon: visuals.LegendIcon.Box,\n identity: visuals.SelectionIdBuilder.builder().withMeasure('total').createSelectionId(),\n selected: false,\n }];\n /**\n * The position represents the starting point for each bar,\n * for any value it is the sum of all previous values.\n * Values > 0 are considered gains, values < 0 are losses.\n */\n var pos = 0, posMin = 0, posMax = 0;\n var dataPoints = [];\n var categoryValues = [];\n var categoryMetadata;\n var valuesMetadata = undefined;\n if (reader.hasValues(\"Y\")) {\n valuesMetadata = reader.getValueMetadataColumn(\"Y\");\n var labelFormatString = valuesMetadata.format;\n if (_.isEmpty(categories)) {\n // We have values but no category, just show the total bar.\n pos = posMax = reader.getValue(\"Y\", 0);\n posMin = 0;\n }\n else {\n var categoryColumn = categories[0];\n categoryMetadata = categoryColumn.source;\n categoryValues = categoryColumn.values.slice();\n categoryValues.push(totalLabel);\n for (var categoryIndex = 0, catLen = reader.getCategoryCount(); categoryIndex < catLen; categoryIndex++) {\n var category = categoryValues[categoryIndex];\n var value = reader.getValue(\"Y\", categoryIndex) || 0;\n var identity = visuals.SelectionIdBuilder.builder()\n .withCategory(categoryColumn, categoryIndex)\n .withMeasure(valuesMetadata.queryName)\n .createSelectionId();\n var tooltipInfo_2 = void 0;\n if (tooltipsEnabled) {\n tooltipInfo_2 = [];\n tooltipInfo_2.push({\n displayName: categoryMetadata.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(category, categoryMetadata, formatStringProp),\n });\n if (value != null) {\n tooltipInfo_2.push({\n displayName: valuesMetadata.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(value, valuesMetadata, formatStringProp),\n });\n }\n }\n var color = value > 0 ? increaseColor : decreaseColor;\n dataPoints.push({\n value: value,\n position: pos,\n color: color,\n categoryValue: category,\n categoryIndex: categoryIndex,\n seriesIndex: 0,\n selected: false,\n identity: identity,\n highlight: false,\n key: identity.getKey(),\n tooltipInfo: tooltipInfo_2,\n labelFill: dataLabelSettings.labelColor,\n labelFormatString: labelFormatString,\n });\n pos += value;\n if (pos > posMax)\n posMax = pos;\n if (pos < posMin)\n posMin = pos;\n }\n }\n var tooltipInfo = void 0;\n if (tooltipsEnabled) {\n tooltipInfo = [];\n if (categoryMetadata) {\n tooltipInfo.push({\n displayName: categoryMetadata.displayName,\n value: totalLabel,\n });\n }\n if (pos != null) {\n tooltipInfo.push({\n displayName: valuesMetadata.displayName,\n value: visuals.converterHelper.formatFromMetadataColumn(pos, valuesMetadata, formatStringProp),\n });\n }\n }\n var totalIdentity = visuals.SelectionId.createNull();\n dataPoints.push({\n value: pos,\n position: 0,\n color: totalColor,\n categoryValue: totalLabel,\n categoryIndex: categoryIndex,\n identity: totalIdentity,\n seriesIndex: 0,\n selected: false,\n highlight: false,\n key: totalIdentity.getKey(),\n tooltipInfo: tooltipInfo,\n labelFill: dataLabelSettings.labelColor,\n labelFormatString: labelFormatString,\n isTotal: true,\n });\n }\n if (interactivityService) {\n interactivityService.applySelectionStateToData(dataPoints);\n }\n var xAxisProperties = visuals.CartesianHelper.getCategoryAxisProperties(dataView.metadata);\n var yAxisProperties = visuals.CartesianHelper.getValueAxisProperties(dataView.metadata);\n var axesLabels = visuals.converterHelper.createAxesLabels(xAxisProperties, yAxisProperties, categoryMetadata, [valuesMetadata]);\n return {\n series: [{ data: dataPoints }],\n categories: categoryValues,\n categoryMetadata: categoryMetadata,\n valuesMetadata: valuesMetadata,\n legend: { dataPoints: legend },\n hasHighlights: false,\n positionMin: posMin,\n positionMax: posMax,\n dataLabelsSettings: dataLabelSettings,\n sentimentColors: sentimentColors,\n axesLabels: { x: axesLabels.xAxisLabel, y: axesLabels.yAxisLabel },\n };\n };\n WaterfallChart.prototype.setData = function (dataViews) {\n debug.assertValue(dataViews, \"dataViews\");\n var sentimentColors = this.getSentimentColorsFromObjects(null);\n var dataView = dataViews.length > 0 ? dataViews[0] : undefined;\n this.data = {\n series: [{ data: [] }],\n categories: [],\n valuesMetadata: null,\n legend: { dataPoints: [], },\n hasHighlights: false,\n categoryMetadata: null,\n scalarCategoryAxis: false,\n positionMax: 0,\n positionMin: 0,\n dataLabelsSettings: visuals.dataLabelUtils.getDefaultLabelSettings(/* show */ false, /* labelColor */ undefined),\n sentimentColors: sentimentColors,\n axesLabels: { x: null, y: null },\n };\n if (dataView) {\n if (dataView.metadata && dataView.metadata.objects) {\n var objects = dataView.metadata.objects;\n var labelsObj = objects['labels'];\n if (labelsObj) {\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, this.data.dataLabelsSettings);\n }\n sentimentColors = this.getSentimentColorsFromObjects(objects);\n }\n if (dataView.categorical) {\n this.data = WaterfallChart.converter(dataView, this.colors, this.hostServices, this.data.dataLabelsSettings, sentimentColors, this.interactivityService, this.tooltipsEnabled);\n }\n }\n };\n WaterfallChart.prototype.enumerateObjectInstances = function (enumeration, options) {\n switch (options.objectName) {\n case 'sentimentColors':\n this.enumerateSentimentColors(enumeration);\n break;\n case 'labels':\n var labelSettingOptions = {\n enumeration: enumeration,\n dataLabelsSettings: this.data.dataLabelsSettings,\n show: true,\n displayUnits: true,\n precision: true,\n fontSize: true,\n };\n visuals.dataLabelUtils.enumerateDataLabels(labelSettingOptions);\n break;\n }\n };\n WaterfallChart.prototype.enumerateSentimentColors = function (enumeration) {\n var sentimentColors = this.data.sentimentColors;\n enumeration.pushInstance({\n selector: null,\n properties: {\n increaseFill: sentimentColors.increaseFill,\n decreaseFill: sentimentColors.decreaseFill,\n totalFill: sentimentColors.totalFill\n },\n objectName: 'sentimentColors'\n });\n };\n WaterfallChart.prototype.calculateLegend = function () {\n // TODO: support interactive legend\n return this.data.legend;\n };\n WaterfallChart.prototype.hasLegend = function () {\n // Waterfall legend is more like a color-key, so just return true\n return true;\n };\n WaterfallChart.createClippedDataIfOverflowed = function (data, renderableDataCount) {\n var clipped = data;\n var dataPoints = data.series[0].data;\n if (data && renderableDataCount < dataPoints.length) {\n clipped = powerbi.Prototype.inherit(data);\n clipped.series = [{ data: dataPoints.slice(0, renderableDataCount) }];\n clipped.categories = data.categories.slice(0, renderableDataCount);\n }\n return clipped;\n };\n WaterfallChart.prototype.calculateAxesProperties = function (options) {\n var _this = this;\n debug.assertValue(options, 'options');\n this.currentViewport = options.viewport;\n this.margin = options.margin;\n var data = this.clippedData = this.data;\n var categoryCount = data.categories.length;\n var preferredPlotArea = this.getPreferredPlotArea(false, categoryCount, visuals.CartesianChart.MinOrdinalRectThickness);\n var cartesianLayout = visuals.CartesianChart.getLayout(null, {\n availableWidth: preferredPlotArea.width,\n categoryCount: categoryCount,\n domain: null,\n isScalar: false,\n isScrollable: this.isScrollable,\n trimOrdinalDataOnOverflow: options.trimOrdinalDataOnOverflow\n });\n // In the case that we have overflowed horizontally we want to clip the data and use that to calculate the axes on the dashboard. \n if (!this.isScrollable) {\n data = this.clippedData = WaterfallChart.createClippedDataIfOverflowed(data, cartesianLayout.categoryCount);\n }\n var xAxisCreationOptions = WaterfallChart.getXAxisCreationOptions(data, preferredPlotArea.width, cartesianLayout, options);\n var yAxisCreationOptions = WaterfallChart.getYAxisCreationOptions(data, preferredPlotArea.height, options);\n var xAxisProperties = this.xAxisProperties = visuals.AxisHelper.createAxis(xAxisCreationOptions);\n var yAxisProperties = this.yAxisProperties = visuals.AxisHelper.createAxis(yAxisCreationOptions);\n var categoryWidth = this.xAxisProperties.categoryThickness * (1 - visuals.CartesianChart.InnerPaddingRatio);\n var formattersCache = visuals.dataLabelUtils.createColumnFormatterCacheManager();\n var labelSettings = data.dataLabelsSettings;\n var value2 = WaterfallChart.getDisplayUnitValueFromAxisFormatter(yAxisProperties, labelSettings);\n this.layout = {\n categoryCount: cartesianLayout.categoryCount,\n categoryThickness: cartesianLayout.categoryThickness,\n isScalar: cartesianLayout.isScalar,\n outerPaddingRatio: cartesianLayout.outerPaddingRatio,\n categoryWidth: categoryWidth,\n labelText: function (d) {\n //total value has no identity\n var formatter = formattersCache.getOrCreate(d.labelFormatString, labelSettings, value2);\n return visuals.dataLabelUtils.getLabelFormattedText({ label: formatter.format(d.value) });\n },\n labelLayout: visuals.dataLabelUtils.getLabelLayoutXYForWaterfall(xAxisProperties, categoryWidth, yAxisProperties, yAxisCreationOptions.dataDomain),\n filter: function (d) {\n return visuals.dataLabelUtils.doesDataLabelFitInShape(d, yAxisProperties, _this.layout);\n },\n style: {\n 'fill': function (d) {\n if (d.isLabelInside)\n return visuals.dataLabelUtils.defaultInsideLabelColor;\n return d.labelFill;\n },\n },\n };\n this.xAxisProperties.axisLabel = options.showCategoryAxisLabel ? data.axesLabels.x : null;\n this.yAxisProperties.axisLabel = options.showValueAxisLabel ? data.axesLabels.y : null;\n return [xAxisProperties, yAxisProperties];\n };\n WaterfallChart.getDisplayUnitValueFromAxisFormatter = function (yAxisProperties, labelSettings) {\n return (yAxisProperties.formatter && yAxisProperties.formatter.displayUnit && labelSettings.displayUnits === 0) ? yAxisProperties.formatter.displayUnit.value : null;\n };\n WaterfallChart.lookupXValue = function (data, index, type) {\n var dataPoints = data.series[0].data;\n if (index === dataPoints.length - 1)\n // Total\n return dataPoints[index].categoryValue;\n else\n return visuals.CartesianHelper.lookupXValue(data, index, type, false);\n };\n WaterfallChart.getXAxisCreationOptions = function (data, width, layout, options) {\n debug.assertValue(data, 'data');\n debug.assertValue(options, 'options');\n var categoryDataType = visuals.AxisHelper.getCategoryValueType(data.categoryMetadata);\n var domain = visuals.AxisHelper.createDomain(data.series, categoryDataType, /* isScalar */ false, options.forcedXDomain, options.ensureXDomain);\n var categoryThickness = layout.categoryThickness;\n var outerPadding = categoryThickness * layout.outerPaddingRatio;\n return {\n pixelSpan: width,\n dataDomain: domain,\n metaDataColumn: data.categoryMetadata,\n formatString: visuals.valueFormatter.getFormatString(data.categoryMetadata, WaterfallChart.formatStringProp),\n isScalar: false,\n outerPadding: outerPadding,\n categoryThickness: categoryThickness,\n getValueFn: function (index, type) { return WaterfallChart.lookupXValue(data, index, type); },\n forcedTickCount: options.forcedTickCount,\n isCategoryAxis: true,\n axisDisplayUnits: options.categoryAxisDisplayUnits,\n axisPrecision: options.categoryAxisPrecision\n };\n };\n WaterfallChart.getYAxisCreationOptions = function (data, height, options) {\n debug.assertValue(data, 'data');\n debug.assertValue(options, 'options');\n var combinedDomain = visuals.AxisHelper.combineDomain(options.forcedYDomain, [data.positionMin, data.positionMax], options.ensureYDomain);\n return {\n pixelSpan: height,\n dataDomain: combinedDomain,\n isScalar: true,\n isVertical: true,\n metaDataColumn: data.valuesMetadata,\n formatString: visuals.valueFormatter.getFormatString(data.valuesMetadata, WaterfallChart.formatStringProp),\n outerPadding: 0,\n forcedTickCount: options.forcedTickCount,\n useTickIntervalForDisplayUnits: true,\n isCategoryAxis: false,\n axisDisplayUnits: options.valueAxisDisplayUnits,\n axisPrecision: options.valueAxisPrecision\n };\n };\n WaterfallChart.prototype.getPreferredPlotArea = function (isScalar, categoryCount, categoryThickness) {\n return visuals.CartesianChart.getPreferredPlotArea(categoryCount, categoryThickness, this.currentViewport, this.isScrollable, isScalar, this.margin);\n };\n WaterfallChart.prototype.getVisualCategoryAxisIsScalar = function () {\n return false;\n };\n WaterfallChart.prototype.overrideXScale = function (xProperties) {\n this.xAxisProperties = xProperties;\n };\n WaterfallChart.prototype.setFilteredData = function (startIndex, endIndex) {\n var data = this.clippedData = powerbi.Prototype.inherit(this.data);\n data.series = [{ data: data.series[0].data.slice(startIndex, endIndex) }];\n data.categories = data.categories.slice(startIndex, endIndex);\n return data;\n };\n WaterfallChart.prototype.createRects = function (data) {\n var mainGraphicsContext = this.mainGraphicsContext;\n var colsSelection = mainGraphicsContext.selectAll(WaterfallChart.CategoryValueClasses.selector);\n var cols = colsSelection.data(data, function (d) { return d.key; });\n cols\n .enter()\n .append('rect')\n .attr('class', function (d) { return WaterfallChart.CategoryValueClasses.class.concat(d.highlight ? 'highlight' : ''); });\n cols.exit().remove();\n return cols;\n };\n WaterfallChart.prototype.createConnectors = function (data) {\n var mainGraphicsContext = this.mainGraphicsContext;\n var connectorSelection = mainGraphicsContext.selectAll(WaterfallChart.WaterfallConnectorClasses.selector);\n var connectors = connectorSelection.data(data.slice(0, data.length - 1), function (d) { return d.key; });\n connectors\n .enter()\n .append('line')\n .classed(WaterfallChart.WaterfallConnectorClasses.class, true);\n connectors.exit().remove();\n return connectors;\n };\n WaterfallChart.prototype.render = function (suppressAnimations) {\n var _this = this;\n var dataPoints = this.clippedData.series[0].data;\n var bars = this.createRects(dataPoints);\n var connectors = this.createConnectors(dataPoints);\n if (this.tooltipsEnabled)\n visuals.TooltipManager.addTooltip(bars, function (tooltipEvent) { return tooltipEvent.data.tooltipInfo; });\n var hasSelection = this.interactivityService && this.interactivityService.hasSelection();\n var xScale = this.xAxisProperties.scale;\n var yScale = this.yAxisProperties.scale;\n var y0 = yScale(0);\n this.mainGraphicsSVG.attr('height', this.getAvailableHeight())\n .attr('width', this.getAvailableWidth());\n /**\n * The y-value is always at the top of the rect. If the data value is negative then we can\n * use the scaled position directly since we are drawing down. If the data value is positive\n * we have to calculate the top of the rect and use that as the y-value. Since the y-value\n * is always the top of the rect, height should always be positive.\n */\n bars\n .style('fill', function (d) { return d.color; })\n .style('fill-opacity', function (d) { return d.isTotal ? visuals.ColumnUtil.DefaultOpacity : visuals.ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, _this.data.hasHighlights); })\n .attr('width', this.layout.categoryWidth)\n .attr('x', function (d) { return xScale(d.categoryIndex); })\n .attr('y', function (d) { return WaterfallChart.getRectTop(yScale, d.position, d.value); })\n .attr('height', function (d) { return y0 - yScale(Math.abs(d.value)); });\n connectors\n .attr({\n 'x1': function (d) { return xScale(d.categoryIndex); },\n 'y1': function (d) { return yScale(d.position + d.value); },\n 'x2': function (d) { return xScale(d.categoryIndex + 1) + _this.layout.categoryWidth; },\n 'y2': function (d) { return yScale(d.position + d.value); },\n });\n var labelSettings = this.data.dataLabelsSettings;\n var labelDataPoints = [];\n if (labelSettings && labelSettings.show || labelSettings.showCategory) {\n labelDataPoints = this.createLabelDataPoints();\n }\n var behaviorOptions = undefined;\n if (this.interactivityService) {\n behaviorOptions = {\n bars: bars,\n datapoints: dataPoints,\n };\n }\n // This should always be the last line in the render code.\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n return { dataPoints: dataPoints, behaviorOptions: behaviorOptions, labelDataPoints: labelDataPoints, labelsAreNumeric: true };\n };\n WaterfallChart.prototype.onClearSelection = function () {\n if (this.interactivityService)\n this.interactivityService.clearSelection();\n };\n WaterfallChart.prototype.getSupportedCategoryAxisType = function () {\n return visuals.axisType.categorical;\n };\n WaterfallChart.getRectTop = function (scale, pos, value) {\n if (value < 0)\n return scale(pos);\n else\n return scale(pos) - (scale(0) - scale(value));\n };\n WaterfallChart.prototype.getAvailableWidth = function () {\n return this.currentViewport.width - (this.margin.left + this.margin.right);\n };\n WaterfallChart.prototype.getAvailableHeight = function () {\n return this.currentViewport.height - (this.margin.top + this.margin.bottom);\n };\n WaterfallChart.prototype.getSentimentColorsFromObjects = function (objects) {\n var defaultSentimentColors = this.colors.getSentimentColors();\n var increaseColor = powerbi.DataViewObjects.getFillColor(objects, visuals.waterfallChartProps.sentimentColors.increaseFill, defaultSentimentColors[2].value);\n var decreaseColor = powerbi.DataViewObjects.getFillColor(objects, visuals.waterfallChartProps.sentimentColors.decreaseFill, defaultSentimentColors[0].value);\n var totalColor = powerbi.DataViewObjects.getFillColor(objects, visuals.waterfallChartProps.sentimentColors.totalFill, WaterfallChart.defaultTotalColor);\n return {\n increaseFill: { solid: { color: increaseColor } },\n decreaseFill: { solid: { color: decreaseColor } },\n totalFill: { solid: { color: totalColor } }\n };\n };\n // Public for testing\n WaterfallChart.prototype.createLabelDataPoints = function () {\n var labelDataPoints = [];\n var data = this.data;\n var xScale = this.xAxisProperties.scale;\n var yScale = this.yAxisProperties.scale;\n var y0 = yScale(0);\n var series = data.series;\n var formattersCache = visuals.NewDataLabelUtils.createColumnFormatterCacheManager();\n var axisFormatter = visuals.NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yAxisProperties.formatter, data.dataLabelsSettings);\n var labelSettings = this.data.dataLabelsSettings;\n for (var _i = 0, series_6 = series; _i < series_6.length; _i++) {\n var currentSeries = series_6[_i];\n for (var _a = 0, _b = currentSeries.data; _a < _b.length; _a++) {\n var dataPoint = _b[_a];\n // Calculate parent rectangle\n var parentRect = {\n left: xScale(dataPoint.categoryIndex),\n top: WaterfallChart.getRectTop(yScale, dataPoint.position, dataPoint.value),\n width: this.layout.categoryWidth,\n height: y0 - yScale(Math.abs(dataPoint.value)),\n };\n // Calculate label text\n var formatString = dataPoint.labelFormatString;\n var formatter = formattersCache.getOrCreate(formatString, this.data.dataLabelsSettings, axisFormatter);\n var text = visuals.NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\n // Calculate text size\n var properties = {\n text: text,\n fontFamily: visuals.NewDataLabelUtils.LabelTextProperties.fontFamily,\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || visuals.NewDataLabelUtils.DefaultLabelFontSizeInPt),\n fontWeight: visuals.NewDataLabelUtils.LabelTextProperties.fontWeight,\n };\n var textWidth = powerbi.TextMeasurementService.measureSvgTextWidth(properties);\n var textHeight = powerbi.TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\n labelDataPoints.push({\n isPreferred: true,\n text: text,\n textSize: {\n width: textWidth,\n height: textHeight,\n },\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : visuals.NewDataLabelUtils.defaultLabelColor,\n insideFill: visuals.NewDataLabelUtils.defaultInsideLabelColor,\n parentType: 1 /* Rectangle */,\n parentShape: {\n rect: parentRect,\n orientation: dataPoint.value >= 0 ? 1 /* VerticalBottomBased */ : 2 /* VerticalTopBased */,\n validPositions: dataPoint.value === 0 ? WaterfallChart.validZeroLabelPosition : WaterfallChart.validLabelPositions,\n },\n fontSize: labelSettings.fontSize,\n identity: undefined,\n });\n }\n }\n return labelDataPoints;\n };\n WaterfallChart.formatStringProp = { objectName: 'general', propertyName: 'formatString' };\n WaterfallChart.WaterfallClassName = 'waterfallChart';\n WaterfallChart.MainGraphicsContextClassName = 'mainGraphicsContext';\n WaterfallChart.IncreaseLabel = \"Waterfall_IncreaseLabel\";\n WaterfallChart.DecreaseLabel = \"Waterfall_DecreaseLabel\";\n WaterfallChart.TotalLabel = \"Waterfall_TotalLabel\";\n WaterfallChart.CategoryValueClasses = createClassAndSelector('column');\n WaterfallChart.WaterfallConnectorClasses = createClassAndSelector('waterfall-connector');\n WaterfallChart.defaultTotalColor = \"#00b8aa\";\n WaterfallChart.validLabelPositions = [16 /* OutsideEnd */, 4 /* InsideEnd */];\n WaterfallChart.validZeroLabelPosition = [16 /* OutsideEnd */, 8 /* OutsideBase */];\n return WaterfallChart;\n }());\n visuals.WaterfallChart = WaterfallChart;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var TouchUtils = powerbi.visuals.controls.TouchUtils;\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n ;\n var ContainerClassName = createClassAndSelector(\"tooltip-container\");\n var ContentContainerClassName = createClassAndSelector(\"tooltip-content-container\");\n var ArrowClassName = createClassAndSelector(\"arrow\");\n var TooltipHeaderClassName = createClassAndSelector(\"tooltip-header\");\n var TooltipRowClassName = createClassAndSelector(\"tooltip-row\");\n var TooltipColorCellClassName = createClassAndSelector(\"tooltip-color-cell\");\n var TooltipTitleCellClassName = createClassAndSelector(\"tooltip-title-cell\");\n var TooltipValueCellClassName = createClassAndSelector(\"tooltip-value-cell\");\n var ToolTipComponent = (function () {\n function ToolTipComponent(tooltipOptions) {\n this.tooltipOptions = tooltipOptions;\n this.isTooltipVisible = false;\n if (!tooltipOptions) {\n this.tooltipOptions = ToolTipComponent.DefaultTooltipOptions;\n }\n }\n ToolTipComponent.prototype.isTooltipComponentVisible = function () {\n return this.isTooltipVisible;\n };\n /** Note: For tests only */\n ToolTipComponent.prototype.setTestScreenSize = function (width, height) {\n this.customScreenWidth = width;\n this.customScreenHeight = height;\n };\n ToolTipComponent.prototype.show = function (tooltipData, clickedArea) {\n this.isTooltipVisible = true;\n if (!this.tooltipContainer) {\n this.tooltipContainer = this.createTooltipContainer();\n }\n this.setTooltipContent(tooltipData);\n this.tooltipContainer\n .style(\"visibility\", \"visible\")\n .transition()\n .duration(0) // Cancel previous transitions\n .style(\"opacity\", this.tooltipOptions.opacity);\n this.setPosition(clickedArea);\n };\n ToolTipComponent.prototype.move = function (tooltipData, clickedArea) {\n if (this.isTooltipVisible) {\n if (tooltipData) {\n this.setTooltipContent(tooltipData);\n }\n this.setPosition(clickedArea);\n }\n };\n ToolTipComponent.prototype.hide = function () {\n if (this.isTooltipVisible) {\n this.isTooltipVisible = false;\n this.tooltipContainer\n .transition()\n .duration(this.tooltipOptions.animationDuration)\n .style(\"opacity\", 0)\n .each('end', function () { this.style.visibility = \"hidden\"; });\n }\n };\n ToolTipComponent.prototype.createTooltipContainer = function () {\n var container = d3.select(ToolTipComponent.parentContainerSelector)\n .append(\"div\")\n .attr(\"class\", ContainerClassName.class);\n container.append(\"div\").attr(\"class\", ArrowClassName.class);\n container.append(\"div\").attr(\"class\", ContentContainerClassName.class);\n return container;\n };\n ToolTipComponent.prototype.setTooltipContent = function (tooltipData) {\n if (_.isEqual(tooltipData, this.currentTooltipData))\n return;\n this.currentTooltipData = tooltipData;\n var rowsSelector = TooltipRowClassName.selector;\n var contentContainer = this.tooltipContainer.select(ContentContainerClassName.selector);\n // Clear existing content\n contentContainer.selectAll(TooltipHeaderClassName.selector).remove();\n contentContainer.selectAll(TooltipRowClassName.selector).remove();\n if (tooltipData.length === 0)\n return;\n if (tooltipData[0].header) {\n contentContainer.append(\"div\").attr(\"class\", TooltipHeaderClassName.class).text(tooltipData[0].header);\n }\n var tooltipRow = contentContainer.selectAll(rowsSelector).data(tooltipData);\n var newRow = tooltipRow.enter().append(\"div\").attr(\"class\", TooltipRowClassName.class);\n if (tooltipData[0].color) {\n var newColorCell = newRow.append(\"div\").attr(\"class\", TooltipColorCellClassName.class);\n newColorCell\n .append('svg')\n .attr({\n 'width': '100%',\n 'height': '15px'\n })\n .append('circle')\n .attr({\n 'cx': '5',\n 'cy': '8',\n 'r': '5'\n })\n .style({\n 'fill': function (d) { return d.color; }\n });\n }\n var newTitleCell = newRow.append(\"div\").attr(\"class\", TooltipTitleCellClassName.class);\n var newValueCell = newRow.append(\"div\").attr(\"class\", TooltipValueCellClassName.class);\n newTitleCell.text(function (d) { return d.displayName; });\n newValueCell.text(function (d) { return d.value; });\n };\n ToolTipComponent.prototype.getTooltipPosition = function (clickedArea, clickedScreenArea) {\n var tooltipContainerBounds = this.tooltipContainer.node().getBoundingClientRect();\n var centerPointOffset = Math.floor(clickedArea.width / 2);\n var offsetX = 0;\n var offsetY = 0;\n var centerPoint = new TouchUtils.Point(clickedArea.x + centerPointOffset, clickedArea.y + centerPointOffset);\n var arrowOffset = 7;\n if (clickedScreenArea === 0 /* TopLeft */) {\n offsetX += 3 * arrowOffset + centerPointOffset;\n offsetY -= 2 * arrowOffset + centerPointOffset;\n }\n else if (clickedScreenArea === 1 /* TopRight */) {\n offsetX -= (2 * arrowOffset + tooltipContainerBounds.width + centerPointOffset);\n offsetY -= 2 * arrowOffset + centerPointOffset;\n }\n else if (clickedScreenArea === 3 /* BottomLeft */) {\n offsetX += 3 * arrowOffset + centerPointOffset;\n offsetY -= (tooltipContainerBounds.height - 2 * arrowOffset + centerPointOffset);\n }\n else if (clickedScreenArea === 2 /* BottomRight */) {\n offsetX -= (2 * arrowOffset + tooltipContainerBounds.width + centerPointOffset);\n offsetY -= (tooltipContainerBounds.height - 2 * arrowOffset + centerPointOffset);\n }\n centerPoint.offset(offsetX, offsetY);\n return centerPoint;\n };\n ToolTipComponent.prototype.setPosition = function (clickedArea) {\n var clickedScreenArea = this.getClickedScreenArea(clickedArea);\n var tooltipPosition = this.getTooltipPosition(clickedArea, clickedScreenArea);\n this.tooltipContainer.style({ \"left\": tooltipPosition.x + \"px\", \"top\": tooltipPosition.y + \"px\" });\n this.setArrowPosition(clickedArea, clickedScreenArea);\n };\n ToolTipComponent.prototype.setArrowPosition = function (clickedArea, clickedScreenArea) {\n var arrow = this.getArrowElement();\n var arrowClassName;\n if (clickedScreenArea === 0 /* TopLeft */) {\n arrowClassName = \"top left\";\n }\n else if (clickedScreenArea === 1 /* TopRight */) {\n arrowClassName = \"top right\";\n }\n else if (clickedScreenArea === 3 /* BottomLeft */) {\n arrowClassName = \"bottom left\";\n }\n else if (clickedScreenArea === 2 /* BottomRight */) {\n arrowClassName = \"bottom right\";\n }\n arrow\n .attr('class', 'arrow') // Reset all classes\n .classed(arrowClassName, true);\n };\n ToolTipComponent.prototype.getArrowElement = function () {\n return this.tooltipContainer.select(ArrowClassName.selector);\n };\n ToolTipComponent.prototype.getClickedScreenArea = function (clickedArea) {\n var screenWidth = this.customScreenWidth || window.innerWidth;\n var screenHeight = this.customScreenHeight || window.innerHeight;\n var centerPointOffset = clickedArea.width / 2;\n var centerPoint = new TouchUtils.Point(clickedArea.x + centerPointOffset, clickedArea.y + centerPointOffset);\n var halfWidth = screenWidth / 2;\n var halfHeight = screenHeight / 2;\n if (centerPoint.x < halfWidth && centerPoint.y < halfHeight) {\n return 0 /* TopLeft */;\n }\n else if (centerPoint.x >= halfWidth && centerPoint.y < halfHeight) {\n return 1 /* TopRight */;\n }\n else if (centerPoint.x < halfWidth && centerPoint.y >= halfHeight) {\n return 3 /* BottomLeft */;\n }\n else if (centerPoint.x >= halfWidth && centerPoint.y >= halfHeight) {\n return 2 /* BottomRight */;\n }\n };\n ToolTipComponent.DefaultTooltipOptions = {\n opacity: 1,\n animationDuration: 250,\n offsetX: 10,\n offsetY: 10\n };\n ToolTipComponent.parentContainerSelector = \"body\";\n ToolTipComponent.highlightedValueDisplayNameResorceKey = \"Tooltip_HighlightedValueDisplayName\";\n return ToolTipComponent;\n }());\n visuals.ToolTipComponent = ToolTipComponent;\n var TooltipManager;\n (function (TooltipManager) {\n TooltipManager.ShowTooltips = true;\n TooltipManager.ToolTipInstance = new ToolTipComponent();\n var GlobalTooltipEventsAttached = false;\n var tooltipMouseOverDelay = 350;\n var tooltipMouseOutDelay = 500;\n var tooltipTouchDelay = 350;\n var tooltipTimeoutId;\n var handleTouchDelay = 1000;\n var handleTouchTimeoutId = 0;\n var mouseCoordinates;\n var tooltipData;\n function addTooltip(selection, getTooltipInfoDelegate, reloadTooltipDataOnMouseMove, onMouseOutDelegate) {\n if (!TooltipManager.ShowTooltips) {\n return;\n }\n debug.assertValue(selection, \"selection\");\n var rootNode = d3.select(ToolTipComponent.parentContainerSelector).node();\n // Mouse events\n selection.on(\"mouseover\", function () {\n var target = d3.event.target;\n var data = d3.select(target).datum();\n // Ignore mouseover while handling touch events\n if (handleTouchTimeoutId || !canDisplayTooltip(d3.event))\n return;\n mouseCoordinates = getCoordinates(rootNode, true);\n var elementCoordinates = getCoordinates(target, true);\n var tooltipEvent = {\n data: data,\n coordinates: mouseCoordinates,\n elementCoordinates: elementCoordinates,\n context: target,\n isTouchEvent: false\n };\n clearTooltipTimeout();\n // if it is already visible, change contents immediately (use 16ms minimum perceivable frame rate to prevent thrashing)\n var delay = TooltipManager.ToolTipInstance.isTooltipComponentVisible() ? 16 : tooltipMouseOverDelay;\n tooltipTimeoutId = showDelayedTooltip(tooltipEvent, getTooltipInfoDelegate, delay);\n });\n selection.on(\"mouseout\", function () {\n if (!handleTouchTimeoutId) {\n clearTooltipTimeout();\n tooltipTimeoutId = hideDelayedTooltip(tooltipMouseOutDelay);\n }\n if (onMouseOutDelegate) {\n onMouseOutDelegate();\n }\n });\n selection.on(\"mousemove\", function () {\n var target = d3.event.target;\n var data = d3.select(target).datum();\n // Ignore mousemove while handling touch events\n if (handleTouchTimeoutId || !canDisplayTooltip(d3.event))\n return;\n mouseCoordinates = getCoordinates(rootNode, true);\n var elementCoordinates = getCoordinates(target, true);\n var tooltipEvent = {\n data: data,\n coordinates: mouseCoordinates,\n elementCoordinates: elementCoordinates,\n context: target,\n isTouchEvent: false\n };\n moveTooltipEventHandler(tooltipEvent, getTooltipInfoDelegate, reloadTooltipDataOnMouseMove);\n });\n // --- Touch events ---\n // TODO: static?\n var touchStartEventName = getTouchStartEventName();\n var touchEndEventName = getTouchEndEventName();\n var isPointerEvent = touchStartEventName === \"pointerdown\" || touchStartEventName === \"MSPointerDown\";\n if (!GlobalTooltipEventsAttached) {\n // Add root container hide tooltip event\n attachGlobalEvents(touchStartEventName);\n GlobalTooltipEventsAttached = true;\n }\n selection.on(touchStartEventName, function () {\n var target = d3.event.target;\n var data = d3.select(target).datum();\n hideTooltipEventHandler();\n var coordinates = getCoordinates(rootNode, isPointerEvent);\n var elementCoordinates = getCoordinates(target, isPointerEvent);\n var tooltipEvent = {\n data: data,\n coordinates: coordinates,\n elementCoordinates: elementCoordinates,\n context: target,\n isTouchEvent: true\n };\n clearTooltipTimeout();\n tooltipTimeoutId = showDelayedTooltip(tooltipEvent, getTooltipInfoDelegate, tooltipTouchDelay);\n });\n selection.on(touchEndEventName, function () {\n clearTooltipTimeout();\n if (handleTouchTimeoutId)\n clearTimeout(handleTouchTimeoutId);\n // At the end of touch action, set a timeout that will let us ignore the incoming mouse events for a small amount of time\n handleTouchTimeoutId = setTimeout(function () {\n handleTouchTimeoutId = 0;\n }, handleTouchDelay);\n });\n }\n TooltipManager.addTooltip = addTooltip;\n function showDelayedTooltip(tooltipEvent, getTooltipInfoDelegate, delayInMs) {\n return setTimeout(function () { return showTooltipEventHandler(tooltipEvent, getTooltipInfoDelegate); }, delayInMs);\n }\n TooltipManager.showDelayedTooltip = showDelayedTooltip;\n function hideDelayedTooltip(delayInMs) {\n return setTimeout(function () { return hideTooltipEventHandler(); }, delayInMs);\n }\n TooltipManager.hideDelayedTooltip = hideDelayedTooltip;\n function setLocalizedStrings(localizationOptions) {\n ToolTipComponent.localizationOptions = localizationOptions;\n }\n TooltipManager.setLocalizedStrings = setLocalizedStrings;\n function showTooltipEventHandler(tooltipEvent, getTooltipInfoDelegate) {\n var tooltipInfo = tooltipData || getTooltipInfoDelegate(tooltipEvent);\n if (!_.isEmpty(tooltipInfo)) {\n var coordinates = mouseCoordinates || tooltipEvent.coordinates;\n var clickedArea = getClickedArea(coordinates[0], coordinates[1], tooltipEvent.isTouchEvent);\n TooltipManager.ToolTipInstance.show(tooltipInfo, clickedArea);\n }\n }\n function moveTooltipEventHandler(tooltipEvent, getTooltipInfoDelegate, reloadTooltipDataOnMouseMove) {\n tooltipData = undefined;\n if (reloadTooltipDataOnMouseMove) {\n tooltipData = getTooltipInfoDelegate(tooltipEvent);\n }\n var clickedArea = getClickedArea(tooltipEvent.coordinates[0], tooltipEvent.coordinates[1], tooltipEvent.isTouchEvent);\n TooltipManager.ToolTipInstance.move(tooltipData, clickedArea);\n }\n ;\n function hideTooltipEventHandler() {\n TooltipManager.ToolTipInstance.hide();\n }\n ;\n function clearTooltipTimeout() {\n if (tooltipTimeoutId) {\n clearTimeout(tooltipTimeoutId);\n }\n }\n function canDisplayTooltip(d3Event) {\n var cadDisplay = true;\n var mouseEvent = d3Event;\n if (mouseEvent.buttons !== undefined) {\n // Check mouse buttons state\n var hasMouseButtonPressed = mouseEvent.buttons !== 0;\n cadDisplay = !hasMouseButtonPressed;\n }\n return cadDisplay;\n }\n function getTouchStartEventName() {\n var eventName = \"touchstart\";\n if (window[\"PointerEvent\"]) {\n // IE11\n eventName = \"pointerdown\";\n }\n else if (window[\"MSPointerEvent\"]) {\n // IE10\n eventName = \"MSPointerDown\";\n }\n return eventName;\n }\n function getTouchEndEventName() {\n var eventName = \"touchend\";\n if (window[\"PointerEvent\"]) {\n // IE11\n eventName = \"pointerup\";\n }\n else if (window[\"MSPointerEvent\"]) {\n // IE10\n eventName = \"MSPointerUp\";\n }\n return eventName;\n }\n function getCoordinates(rootNode, isPointerEvent) {\n var coordinates;\n if (isPointerEvent) {\n // DO NOT USE - WebKit bug in getScreenCTM with nested SVG results in slight negative coordinate shift\n // Also, IE will incorporate transform scale but WebKit does not, forcing us to detect browser and adjust appropriately.\n // Just use non-scaled coordinates for all browsers, and adjust for the transform scale later (see lineChart.findIndex)\n //coordinates = d3.mouse(rootNode);\n // copied from d3_eventSource (which is not exposed)\n var e = d3.event, s = void 0;\n while (s = e.sourceEvent)\n e = s;\n var rect = rootNode.getBoundingClientRect();\n coordinates = [e.clientX - rect.left - rootNode.clientLeft, e.clientY - rect.top - rootNode.clientTop];\n }\n else {\n var touchCoordinates = d3.touches(rootNode);\n if (touchCoordinates && touchCoordinates.length > 0) {\n coordinates = touchCoordinates[0];\n }\n }\n return coordinates;\n }\n function attachGlobalEvents(touchStartEventName) {\n d3.select(ToolTipComponent.parentContainerSelector).on(touchStartEventName, function (d, i) {\n TooltipManager.ToolTipInstance.hide();\n });\n }\n function getClickedArea(x, y, isTouchEvent) {\n var width = 0;\n var pointX = x;\n var pointY = y;\n if (isTouchEvent) {\n width = 12;\n var offset = width / 2;\n pointX = Math.max(x - offset, 0);\n pointY = Math.max(y - offset, 0);\n }\n return new TouchUtils.Rectangle(pointX, pointY, width, width);\n }\n })(TooltipManager = visuals.TooltipManager || (visuals.TooltipManager = {}));\n var TooltipBuilder;\n (function (TooltipBuilder) {\n // TODO: implement options bag as input parameter\n function createTooltipInfo(formatStringProp, dataViewCat, categoryValue, value, categories, seriesData, seriesIndex, categoryIndex, highlightedValue, gradientValueColumn) {\n var categorySource;\n var seriesSource = [];\n var valuesSource = undefined;\n seriesIndex = seriesIndex | 0;\n var categoriesData = dataViewCat ? dataViewCat.categories : categories;\n if (categoriesData && categoriesData.length > 0) {\n if (categoriesData.length > 1) {\n var compositeCategoriesData = [];\n for (var i = 0, ilen = categoriesData.length; i < ilen; i++) {\n compositeCategoriesData.push(categoriesData[i].source);\n }\n categorySource = { value: categoryValue, metadata: compositeCategoriesData };\n }\n else {\n categorySource = { value: categoryValue, metadata: [categoriesData[0].source] };\n }\n }\n if (dataViewCat && dataViewCat.values) {\n if (categorySource && categorySource.metadata[0] === dataViewCat.values.source) {\n }\n else {\n valuesSource = dataViewCat.values.source;\n }\n if (dataViewCat.values.length > 0) {\n var valueColumn = dataViewCat.values[seriesIndex];\n var isAutoGeneratedColumn = !!(valueColumn && valueColumn.source && valueColumn.source.isAutoGeneratedColumn);\n if (!isAutoGeneratedColumn) {\n seriesSource.push({ value: value, highlightedValue: highlightedValue, metadata: valueColumn });\n }\n }\n //Create Gradient tooltip value\n var gradientToolTipData = createGradientToolTipData(gradientValueColumn, categoryIndex);\n if (gradientToolTipData != null)\n seriesSource.push(gradientToolTipData);\n }\n if (seriesData) {\n for (var i = 0, len = seriesData.length; i < len; i++) {\n var singleSeriesData = seriesData[i];\n if (categorySource && categorySource.metadata[0] === singleSeriesData.metadata.source)\n continue;\n seriesSource.push({ value: singleSeriesData.value, metadata: singleSeriesData.metadata });\n }\n }\n var tooltipInfo = createTooltipData(formatStringProp, categorySource, valuesSource, seriesSource);\n return tooltipInfo;\n }\n TooltipBuilder.createTooltipInfo = createTooltipInfo;\n function createGradientToolTipData(gradientValueColumn, categoryIndex) {\n if (gradientValueColumn) {\n // Saturation color\n return { value: gradientValueColumn.values[categoryIndex], metadata: { source: gradientValueColumn.source, values: [] } };\n }\n return null;\n }\n TooltipBuilder.createGradientToolTipData = createGradientToolTipData;\n function createTooltipData(formatStringProp, categoryValue, valuesSource, seriesValues) {\n debug.assertValue(seriesValues, \"seriesSource\");\n debug.assertValue(ToolTipComponent.localizationOptions, \"ToolTipComponent.localizationOptions\");\n debug.assertAnyValue(formatStringProp, 'formatStringProp');\n var items = [];\n if (categoryValue) {\n if (categoryValue.metadata.length > 1) {\n var displayName = '';\n // This is being done simply for lat/long for now, as that's the only composite category we use. If we ever have tooltips\n // involving other composite categories, we need to do a more thorough design and be more careful here.\n for (var i = 0, ilen = categoryValue.metadata.length; i < ilen; i++) {\n if (i !== 0)\n displayName += '/';\n displayName += categoryValue.metadata[i].displayName;\n }\n var categoryFormattedValue = getFormattedValue(categoryValue.metadata[0], formatStringProp, categoryValue.value);\n items.push({ displayName: displayName, value: categoryFormattedValue });\n }\n else {\n var categoryFormattedValue = getFormattedValue(categoryValue.metadata[0], formatStringProp, categoryValue.value);\n items.push({ displayName: categoryValue.metadata[0].displayName, value: categoryFormattedValue });\n }\n }\n if (valuesSource) {\n // Dynamic series value\n var dynamicValue = void 0;\n if (seriesValues.length > 0) {\n var dynamicValueMetadata = seriesValues[0].metadata.source;\n dynamicValue = getFormattedValue(valuesSource, formatStringProp, dynamicValueMetadata.groupName);\n }\n items.push({ displayName: valuesSource.displayName, value: dynamicValue });\n }\n for (var i = 0; i < seriesValues.length; i++) {\n var seriesData = seriesValues[i];\n if (seriesData && seriesData.metadata) {\n var seriesMetadataColumn = seriesData.metadata.source;\n var value = seriesData.value;\n var highlightedValue = seriesData.highlightedValue;\n if (value || value === 0) {\n var formattedValue = getFormattedValue(seriesMetadataColumn, formatStringProp, value);\n items.push({ displayName: seriesMetadataColumn.displayName, value: formattedValue });\n }\n if (highlightedValue || highlightedValue === 0) {\n var formattedHighlightedValue = getFormattedValue(seriesMetadataColumn, formatStringProp, highlightedValue);\n var displayName = ToolTipComponent.localizationOptions.highlightedValueDisplayName;\n items.push({ displayName: displayName, value: formattedHighlightedValue });\n }\n }\n }\n return items;\n }\n function getFormattedValue(column, formatStringProp, value) {\n var formatString = getFormatStringFromColumn(column, formatStringProp);\n return visuals.valueFormatter.format(value, formatString);\n }\n function getFormatStringFromColumn(column, formatStringProp) {\n if (column) {\n var formatString = visuals.valueFormatter.getFormatString(column, formatStringProp, true);\n return formatString || column.format;\n }\n return null;\n }\n })(TooltipBuilder = visuals.TooltipBuilder || (visuals.TooltipBuilder = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var visualStyles;\n (function (visualStyles) {\n function create(dataColors) {\n if (dataColors === undefined)\n dataColors = new visuals.DataColorPalette();\n return {\n titleText: {\n color: { value: 'rgba(51,51,51,1)' }\n },\n subTitleText: {\n color: { value: 'rgba(145,145,145,1)' }\n },\n colorPalette: {\n dataColors: dataColors,\n },\n labelText: {\n color: {\n value: 'rgba(51,51,51,1)',\n },\n fontSize: '11px'\n },\n isHighContrast: false,\n };\n }\n visualStyles.create = create;\n })(visualStyles = visuals.visualStyles || (visuals.visualStyles = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\n /**\n * Renders a donut chart.\n */\n var DonutChart = (function () {\n function DonutChart(options) {\n if (options) {\n this.sliceWidthRatio = options.sliceWidthRatio;\n this.animator = options.animator;\n this.isScrollable = options.isScrollable ? options.isScrollable : false;\n this.disableGeometricCulling = options.disableGeometricCulling ? options.disableGeometricCulling : false;\n this.behavior = options.behavior;\n this.tooltipsEnabled = options.tooltipsEnabled;\n if (options.smallViewPortProperties) {\n this.maxHeightToScaleDonutLegend = options.smallViewPortProperties.maxHeightToScaleDonutLegend;\n }\n }\n if (this.sliceWidthRatio == null) {\n this.sliceWidthRatio = DonutChart.defaultSliceWidthRatio;\n }\n }\n DonutChart.converter = function (dataView, colors, defaultDataPointColor, viewport, disableGeometricCulling, interactivityService, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var converter = new DonutChartConversion.DonutChartConverter(dataView, colors, defaultDataPointColor, tooltipsEnabled);\n converter.convert();\n var d3PieLayout = d3.layout.pie()\n .sort(null)\n .value(function (d) {\n return d.percentage;\n });\n if (interactivityService) {\n interactivityService.applySelectionStateToData(converter.dataPoints);\n interactivityService.applySelectionStateToData(converter.legendData.dataPoints);\n }\n var culledDataPoints = (!disableGeometricCulling && viewport) ? DonutChart.cullDataByViewport(converter.dataPoints, converter.maxValue, viewport) : converter.dataPoints;\n return {\n dataPointsToDeprecate: culledDataPoints,\n dataPoints: d3PieLayout(culledDataPoints),\n unCulledDataPoints: converter.dataPoints,\n dataPointsToEnumerate: converter.legendData.dataPoints,\n legendData: converter.legendData,\n hasHighlights: converter.hasHighlights,\n dataLabelsSettings: converter.dataLabelsSettings,\n legendObjectProperties: converter.legendObjectProperties,\n maxValue: converter.maxValue,\n visibleGeometryCulled: converter.dataPoints.length !== culledDataPoints.length,\n };\n };\n DonutChart.prototype.init = function (options) {\n this.options = options;\n var element = options.element;\n // Ensure viewport is empty on init\n element.empty();\n this.parentViewport = options.viewport;\n // avoid deep copy\n this.currentViewport = {\n height: options.viewport.height,\n width: options.viewport.width,\n };\n this.formatter = visuals.valueFormatter.format;\n this.data = {\n dataPointsToDeprecate: [],\n dataPointsToEnumerate: [],\n dataPoints: [],\n unCulledDataPoints: [],\n legendData: { title: \"\", dataPoints: [], fontSize: visuals.SVGLegend.DefaultFontSizeInPt },\n hasHighlights: false,\n dataLabelsSettings: visuals.dataLabelUtils.getDefaultDonutLabelSettings(),\n };\n this.drilled = false;\n // Leaving this false for now, will depend on the datacategory in the future\n this.allowDrilldown = false;\n this.style = options.style;\n this.colors = this.style.colorPalette.dataColors;\n this.radius = 0;\n this.isInteractive = options.interactivity && options.interactivity.isInteractiveLegend;\n var donutChartSettings = this.settings;\n if (this.behavior) {\n this.interactivityService = visuals.createInteractivityService(options.host);\n }\n this.legend = visuals.createLegend(element, options.interactivity && options.interactivity.isInteractiveLegend, this.interactivityService, this.isScrollable);\n this.hostService = options.host;\n if (this.isInteractive) {\n this.chartRotationAnimationDuration = (donutChartSettings && donutChartSettings.chartRotationAnimationDuration) ? donutChartSettings.chartRotationAnimationDuration : 0;\n // Create interactive legend\n var legendContainer = this.legendContainer = d3.select(element.get(0))\n .append('div')\n .classed(DonutChart.InteractiveLegendClassName, true);\n this.interactivityState = {\n interactiveLegend: new DonutChartInteractiveLegend(this, legendContainer, this.colors, options, this.settings),\n valueToAngleFactor: 0,\n sliceAngles: [],\n currentRotate: 0,\n interactiveChosenSliceFinishedSetting: false,\n lastChosenInteractiveSliceIndex: 0,\n totalDragAngleDifference: 0,\n currentIndexDrag: 0,\n previousIndexDrag: 0,\n previousDragAngle: 0,\n donutCenter: { x: 0, y: 0 },\n };\n }\n this.svg = d3.select(element.get(0))\n .append('svg')\n .style('position', 'absolute')\n .classed(DonutChart.ClassName, true);\n if (this.behavior)\n this.clearCatcher = visuals.appendClearCatcher(this.svg);\n this.mainGraphicsContext = this.svg.append('g');\n this.mainGraphicsContext.append(\"g\")\n .classed('slices', true);\n this.labelGraphicsContext = this.svg\n .append(\"g\")\n .classed(visuals.NewDataLabelUtils.labelGraphicsContextClass.class, true);\n this.pie = d3.layout.pie()\n .sort(null)\n .value(function (d) {\n return d.percentage;\n });\n };\n DonutChart.prototype.update = function (options) {\n debug.assertValue(options, 'options');\n // Viewport resizing\n var viewport = options.viewport;\n this.parentViewport = viewport;\n var dataViews = this.dataViews = options.dataViews;\n if (dataViews && dataViews.length > 0 && dataViews[0].categorical) {\n var dataViewMetadata = dataViews[0].metadata;\n var defaultDataPointColor = undefined;\n if (dataViewMetadata) {\n var objects = dataViewMetadata.objects;\n if (objects) {\n defaultDataPointColor = powerbi.DataViewObjects.getFillColor(objects, visuals.donutChartProps.dataPoint.defaultColor);\n }\n }\n this.data = DonutChart.converter(dataViews[0], this.colors, defaultDataPointColor, this.currentViewport, this.disableGeometricCulling, this.interactivityService, this.tooltipsEnabled);\n this.data.defaultDataPointColor = defaultDataPointColor;\n if (!(this.options.interactivity && this.options.interactivity.isInteractiveLegend))\n this.renderLegend();\n }\n else {\n this.data = {\n dataPointsToDeprecate: [],\n dataPointsToEnumerate: [],\n dataPoints: [],\n unCulledDataPoints: [],\n legendData: { title: \"\", dataPoints: [] },\n hasHighlights: false,\n dataLabelsSettings: visuals.dataLabelUtils.getDefaultDonutLabelSettings(),\n };\n }\n this.initViewportDependantProperties();\n this.initDonutProperties();\n this.updateInternal(this.data, options.suppressAnimations);\n this.hasSetData = true;\n if (dataViews) {\n var warnings = visuals.getInvalidValueWarnings(dataViews, false /*supportsNaN*/, false /*supportsNegativeInfinity*/, false /*supportsPositiveInfinity*/);\n this.hostService.setWarnings(warnings);\n }\n };\n DonutChart.prototype.onDataChanged = function (options) {\n debug.assertValue(options, 'options');\n this.update({\n dataViews: options.dataViews,\n suppressAnimations: options.suppressAnimations,\n viewport: this.currentViewport,\n });\n };\n DonutChart.prototype.onResizing = function (viewport) {\n this.update({\n dataViews: this.dataViews,\n suppressAnimations: true,\n viewport: viewport,\n });\n };\n DonutChart.prototype.enumerateObjectInstances = function (options) {\n var enumeration = new visuals.ObjectEnumerationBuilder();\n var dataLabelsSettings = this.data && this.data.dataLabelsSettings\n ? this.data.dataLabelsSettings\n : visuals.dataLabelUtils.getDefaultDonutLabelSettings();\n switch (options.objectName) {\n case 'legend':\n this.enumerateLegend(enumeration);\n break;\n case 'dataPoint':\n this.enumerateDataPoints(enumeration);\n break;\n case 'labels':\n var labelSettingOptions = {\n enumeration: enumeration,\n dataLabelsSettings: dataLabelsSettings,\n show: true,\n displayUnits: true,\n precision: true,\n fontSize: true,\n labelStyle: true,\n };\n visuals.dataLabelUtils.enumerateDataLabels(labelSettingOptions);\n break;\n }\n return enumeration.complete();\n };\n DonutChart.prototype.enumerateDataPoints = function (enumeration) {\n var data = this.data;\n if (!data)\n return;\n var dataPoints = data.dataPointsToEnumerate;\n var dataPointsLength = dataPoints.length;\n for (var i = 0; i < dataPointsLength; i++) {\n var dataPoint = dataPoints[i];\n enumeration.pushInstance({\n objectName: 'dataPoint',\n displayName: dataPoint.label,\n selector: visuals.ColorHelper.normalizeSelector(dataPoint.identity.getSelector()),\n properties: {\n fill: { solid: { color: dataPoint.color } }\n },\n });\n }\n };\n DonutChart.prototype.enumerateLegend = function (enumeration) {\n var data = this.data;\n if (!data)\n return;\n var legendObjectProperties = { legend: data.legendObjectProperties };\n var show = powerbi.DataViewObjects.getValue(legendObjectProperties, visuals.donutChartProps.legend.show, this.legend.isVisible());\n var showTitle = powerbi.DataViewObjects.getValue(legendObjectProperties, visuals.donutChartProps.legend.showTitle, true);\n var titleText = powerbi.DataViewObjects.getValue(legendObjectProperties, visuals.donutChartProps.legend.titleText, this.data.legendData.title);\n var labelColor = powerbi.DataViewObject.getValue(legendObjectProperties, visuals.legendProps.labelColor, this.data.legendData.labelColor);\n var labelFontSize = powerbi.DataViewObject.getValue(legendObjectProperties, visuals.legendProps.fontSize, this.data.legendData.fontSize);\n enumeration.pushInstance({\n selector: null,\n objectName: 'legend',\n properties: {\n show: show,\n position: visuals.LegendPosition[this.legend.getOrientation()],\n showTitle: showTitle,\n titleText: titleText,\n labelColor: labelColor,\n fontSize: labelFontSize\n }\n });\n };\n DonutChart.prototype.setInteractiveChosenSlice = function (sliceIndex) {\n var _this = this;\n if (this.interactivityState.sliceAngles.length === 0)\n return;\n this.interactivityState.lastChosenInteractiveSliceIndex = sliceIndex;\n this.interactivityState.interactiveChosenSliceFinishedSetting = false;\n var viewport = this.currentViewport;\n var moduledIndex = sliceIndex % this.data.dataPoints.length;\n var angle = this.interactivityState.sliceAngles[moduledIndex];\n this.svg.select('g')\n .transition()\n .duration(this.chartRotationAnimationDuration)\n .ease('elastic')\n .attr('transform', visuals.SVGUtil.translateAndRotate(viewport.width / 2, viewport.height / 2, 0, 0, angle))\n .each('end', function () { _this.interactivityState.interactiveChosenSliceFinishedSetting = true; });\n this.interactivityState.currentRotate = angle;\n this.interactivityState.interactiveLegend.updateLegend(moduledIndex);\n // Set the opacity of chosen slice to full and the others to semi-transparent\n this.svg.selectAll('.slice').attr('opacity', function (d, index) {\n return index === moduledIndex ? 1 : 0.6;\n });\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n };\n DonutChart.prototype.calculateRadius = function () {\n var viewport = this.currentViewport;\n if (!this.isInteractive && this.data && this.data.dataLabelsSettings.show) {\n // if we have category or data labels, use a sigmoid to blend the desired denominator from 2 to 3.\n // if we are taller than we are wide, we need to use a larger denominator to leave horizontal room for the labels.\n var hw = viewport.height / viewport.width;\n var denom = 2 + (1 / (1 + Math.exp(-5 * (hw - 1))));\n return Math.min(viewport.height, viewport.width) / denom;\n }\n // no labels (isInteractive does not have labels since the interactive legend shows extra info)\n return Math.min(viewport.height, viewport.width) / 2;\n };\n DonutChart.prototype.getScaleForLegendArrow = function () {\n var ratio = 1.0;\n if (this.maxHeightToScaleDonutLegend && this.currentViewport.height < this.maxHeightToScaleDonutLegend) {\n ratio = this.currentViewport.height / this.maxHeightToScaleDonutLegend;\n }\n return ratio;\n };\n DonutChart.prototype.initViewportDependantProperties = function (duration) {\n if (duration === void 0) { duration = 0; }\n this.currentViewport.height = this.parentViewport.height;\n this.currentViewport.width = this.parentViewport.width;\n var viewport = this.currentViewport;\n if (this.isInteractive) {\n viewport.height -= DonutChart.InteractiveLegendContainerHeight; // leave space for the legend\n }\n else {\n var legendMargins = this.legend.getMargins();\n viewport.height -= legendMargins.height;\n viewport.width -= legendMargins.width;\n }\n this.svg.attr({\n 'width': viewport.width,\n 'height': viewport.height\n });\n if (this.isInteractive) {\n this.legendContainer\n .style({\n 'width': '100%',\n 'height': DonutChart.InteractiveLegendContainerHeight + 'px',\n 'overflow': 'hidden',\n 'top': 0\n });\n this.svg\n .style('top', DonutChart.InteractiveLegendContainerHeight);\n }\n else {\n visuals.Legend.positionChartArea(this.svg, this.legend);\n }\n this.previousRadius = this.radius;\n var radius = this.radius = this.calculateRadius();\n var halfViewportWidth = viewport.width / 2;\n var halfViewportHeight = viewport.height / 2;\n this.arc = d3.svg.arc();\n this.outerArc = d3.svg.arc()\n .innerRadius(radius * DonutChart.OuterArcRadiusRatio)\n .outerRadius(radius * DonutChart.OuterArcRadiusRatio);\n if (this.isInteractive) {\n this.mainGraphicsContext.attr('transform', visuals.SVGUtil.translate(halfViewportWidth, halfViewportHeight));\n this.labelGraphicsContext.attr('transform', visuals.SVGUtil.translate(halfViewportWidth, halfViewportHeight));\n }\n else {\n this.mainGraphicsContext.transition().duration(duration).attr('transform', visuals.SVGUtil.translate(halfViewportWidth, halfViewportHeight));\n this.labelGraphicsContext.transition().duration(duration).attr('transform', visuals.SVGUtil.translate(halfViewportWidth, halfViewportHeight));\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n };\n DonutChart.prototype.initDonutProperties = function () {\n this.donutProperties = {\n viewport: this.currentViewport,\n radius: this.radius,\n arc: this.arc.innerRadius(0).outerRadius(this.radius * DonutChart.InnerArcRadiusRatio),\n outerArc: this.outerArc,\n innerArcRadiusRatio: DonutChart.InnerArcRadiusRatio,\n outerArcRadiusRatio: DonutChart.OuterArcRadiusRatio,\n dataLabelsSettings: this.data.dataLabelsSettings,\n };\n };\n DonutChart.prototype.mergeDatasets = function (first, second) {\n var secondSet = d3.set();\n second.forEach(function (d) {\n secondSet.add(d.identity ? d.identity.getKey() : d.data.identity.getKey());\n });\n var onlyFirst = first.filter(function (d) {\n return !secondSet.has(d.identity ? d.identity.getKey() : d.data.identity.getKey());\n }).map(function (d) {\n var derived = powerbi.Prototype.inherit(d);\n derived.percentage === undefined ? derived.data.percentage = 0 : derived.percentage = 0;\n return derived;\n });\n return d3.merge([second, onlyFirst]);\n };\n DonutChart.prototype.updateInternal = function (data, suppressAnimations, duration) {\n if (duration === void 0) { duration = 0; }\n var viewport = this.currentViewport;\n duration = duration || visuals.AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\n if (this.animator) {\n var layout = DonutChart.getLayout(this.radius, this.sliceWidthRatio, viewport);\n var result = void 0;\n var shapes_1;\n var highlightShapes = void 0;\n var labelSettings = data.dataLabelsSettings;\n var labels = [];\n if (labelSettings && labelSettings.show) {\n labels = this.createLabels();\n }\n if (!suppressAnimations) {\n var animationOptions = {\n viewModel: data,\n colors: this.colors,\n graphicsContext: this.mainGraphicsContext,\n labelGraphicsContext: this.labelGraphicsContext,\n interactivityService: this.interactivityService,\n layout: layout,\n radius: this.radius,\n sliceWidthRatio: this.sliceWidthRatio,\n viewport: viewport,\n labels: labels,\n innerArcRadiusRatio: DonutChart.InnerArcRadiusRatio,\n };\n result = this.animator.animate(animationOptions);\n shapes_1 = result.shapes;\n highlightShapes = result.highlightShapes;\n }\n if (suppressAnimations || result.failed) {\n shapes_1 = DonutChart.drawDefaultShapes(this.svg, data, layout, this.colors, this.radius, this.interactivityService && this.interactivityService.hasSelection(), this.sliceWidthRatio, this.data.defaultDataPointColor);\n highlightShapes = DonutChart.drawDefaultHighlightShapes(this.svg, data, layout, this.colors, this.radius, this.sliceWidthRatio);\n visuals.NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, labels, false, true, true /*has tooltip */);\n visuals.NewDataLabelUtils.drawLabelLeaderLines(this.labelGraphicsContext, labels);\n }\n this.assignInteractions(shapes_1, highlightShapes, data);\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(shapes_1, function (tooltipEvent) { return tooltipEvent.data.data.tooltipInfo; });\n visuals.TooltipManager.addTooltip(highlightShapes, function (tooltipEvent) { return tooltipEvent.data.data.tooltipInfo; });\n }\n }\n else {\n this.updateInternalToMove(data, duration);\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n };\n DonutChart.prototype.createLabels = function () {\n var labelLayout = new powerbi.DonutLabelLayout({\n maximumOffset: visuals.NewDataLabelUtils.maxLabelOffset,\n startingOffset: visuals.NewDataLabelUtils.startingLabelOffset\n }, this.donutProperties);\n var labelDataPoints = this.createLabelDataPoints();\n return labelLayout.layout(labelDataPoints);\n };\n DonutChart.prototype.createLabelDataPoints = function () {\n var data = this.data;\n var labelDataPoints = [];\n var measureFormatterCache = visuals.dataLabelUtils.createColumnFormatterCacheManager();\n var alternativeScale = null;\n if (data.dataLabelsSettings.displayUnits === 0)\n alternativeScale = d3.max(data.dataPoints, function (d) { return Math.abs(d.data.measure); });\n for (var i = 0; i < this.data.dataPoints.length; i++) {\n var label = this.createLabelDataPoint(data.dataPoints[i], alternativeScale, measureFormatterCache);\n labelDataPoints.push(label);\n }\n return labelDataPoints;\n };\n DonutChart.prototype.createLabelDataPoint = function (d, alternativeScale, measureFormatterCache) {\n var labelPoint = this.outerArc.centroid(d);\n var labelX = visuals.DonutLabelUtils.getXPositionForDonutLabel(labelPoint[0]);\n var labelY = labelPoint[1];\n var labelSettings = this.data.dataLabelsSettings;\n var measureFormatter = measureFormatterCache.getOrCreate(d.data.labelFormatString, labelSettings, alternativeScale);\n var position = labelX < 0 ? 4 /* Left */ : 8 /* Right */;\n var pointPosition = {\n point: {\n x: labelX,\n y: labelY,\n },\n validPositions: [position],\n radius: 0,\n };\n var outsideFill = labelSettings.labelColor ? labelSettings.labelColor : visuals.NewDataLabelUtils.defaultLabelColor;\n var dataLabel;\n var dataLabelSize;\n var categoryLabel;\n var categoryLabelSize;\n var textSize;\n var labelSettingsStyle = labelSettings.labelStyle;\n var fontSize = labelSettings.fontSize;\n var tooltip = \"\";\n if (labelSettingsStyle === visuals.labelStyle.both || labelSettingsStyle === visuals.labelStyle.data) {\n dataLabel = measureFormatter.format(d.data.highlightValue != null ? d.data.highlightValue : d.data.measure);\n dataLabelSize = visuals.NewDataLabelUtils.getTextSize(dataLabel, fontSize);\n }\n if (labelSettingsStyle === visuals.labelStyle.both || labelSettingsStyle === visuals.labelStyle.category) {\n categoryLabel = d.data.label;\n categoryLabelSize = visuals.NewDataLabelUtils.getTextSize(categoryLabel, fontSize);\n }\n switch (labelSettingsStyle) {\n case visuals.labelStyle.both:\n var text = categoryLabel + \" (\" + dataLabel + \")\";\n tooltip = text;\n textSize = visuals.NewDataLabelUtils.getTextSize(text, fontSize);\n break;\n case visuals.labelStyle.category:\n textSize = _.clone(categoryLabelSize);\n tooltip = categoryLabel;\n break;\n case visuals.labelStyle.data:\n textSize = _.clone(dataLabelSize);\n tooltip = dataLabel;\n break;\n }\n var leaderLinePoints = visuals.DonutLabelUtils.getLabelLeaderLineForDonutChart(d, this.donutProperties, pointPosition.point);\n var leaderLinesSize = visuals.DonutLabelUtils.getLabelLeaderLinesSizeForDonutChart(leaderLinePoints);\n return {\n isPreferred: true,\n text: \"\",\n tooltip: tooltip,\n textSize: textSize,\n outsideFill: outsideFill,\n fontSize: fontSize,\n identity: d.data.identity,\n parentShape: pointPosition,\n insideFill: visuals.NewDataLabelUtils.defaultInsideLabelColor,\n parentType: 0 /* Point */,\n alternativeScale: alternativeScale,\n donutArcDescriptor: d,\n angle: (d.startAngle + d.endAngle) / 2 - (Math.PI / 2),\n dataLabel: dataLabel,\n dataLabelSize: dataLabelSize,\n categoryLabel: categoryLabel,\n categoryLabelSize: categoryLabelSize,\n leaderLinePoints: leaderLinePoints,\n linesSize: leaderLinesSize,\n };\n };\n DonutChart.prototype.renderLegend = function () {\n if (!this.isInteractive) {\n var legendObjectProperties = this.data.legendObjectProperties;\n if (legendObjectProperties) {\n var legendData = this.data.legendData;\n visuals.LegendData.update(legendData, legendObjectProperties);\n var position = legendObjectProperties[visuals.legendProps.position];\n if (position)\n this.legend.changeOrientation(visuals.LegendPosition[position]);\n this.legend.drawLegend(legendData, this.parentViewport);\n }\n else {\n this.legend.changeOrientation(visuals.LegendPosition.Top);\n this.legend.drawLegend({ dataPoints: [] }, this.parentViewport);\n }\n }\n };\n DonutChart.prototype.addInteractiveLegendArrow = function () {\n if (!this.data || !this.data.dataPoints || this.data.dataPoints.length === 0)\n return;\n var arrowHeightOffset = 11;\n var arrowWidthOffset = 33 / 2;\n if (!this.interactiveLegendArrow) {\n var interactiveLegendArrow = this.svg.append('g');\n interactiveLegendArrow.append('path')\n .classed(DonutChart.InteractiveLegendArrowClassName, true)\n .attr('d', 'M1.5,2.6C0.65,1.15,1.85,0,3,0l27,0c1.65,0,2.35,1.15,1.5,2.6L18,26.45c-0.8,1.45-2.15,1.45-2.95,0L1.95,2.6z');\n this.interactiveLegendArrow = interactiveLegendArrow;\n }\n var viewport = this.currentViewport;\n // Calculate the offsets from the legend container to the arrow.\n var scaleRatio = this.getScaleForLegendArrow();\n var distanceBetweenLegendAndArrow = (viewport.height - 2 * this.radius) / 2 + (arrowHeightOffset * scaleRatio);\n var middleOfChart = viewport.width / 2 - (arrowWidthOffset * scaleRatio);\n this.interactiveLegendArrow.attr('transform', visuals.SVGUtil.translateAndScale(middleOfChart, distanceBetweenLegendAndArrow, scaleRatio));\n };\n DonutChart.prototype.calculateSliceAngles = function () {\n var angles = [];\n var data = this.data.dataPoints;\n if (data.length === 0) {\n this.interactivityState.valueToAngleFactor = 0;\n this.interactivityState.sliceAngles = [];\n return;\n }\n var sum = 0;\n for (var i = 0, ilen = data.length; i < ilen; i++) {\n sum += data[i].data.percentage; // value is an absolute number\n }\n debug.assert(sum !== 0, 'sum of slices values cannot be zero');\n this.interactivityState.valueToAngleFactor = 360 / sum; // Calculate the ratio between 360 and the sum to know the angles to rotate by\n var currentAngle = 0;\n for (var i = 0, ilen = data.length; i < ilen; i++) {\n var relativeAngle = data[i].data.percentage * this.interactivityState.valueToAngleFactor;\n currentAngle += relativeAngle;\n angles.push((relativeAngle / 2) - currentAngle);\n }\n this.interactivityState.sliceAngles = angles;\n };\n DonutChart.prototype.assignInteractions = function (slices, highlightSlices, data) {\n // assign interactions according to chart interactivity type\n if (this.isInteractive) {\n this.assignInteractiveChartInteractions(slices);\n }\n else if (this.interactivityService) {\n var dataPoints = data.dataPoints.map(function (value) { return value.data; });\n var behaviorOptions = {\n clearCatcher: this.clearCatcher,\n slices: slices,\n highlightSlices: highlightSlices,\n allowDrilldown: this.allowDrilldown,\n visual: this,\n hasHighlights: data.hasHighlights,\n svg: this.svg,\n };\n this.interactivityService.bind(dataPoints, this.behavior, behaviorOptions);\n }\n };\n DonutChart.prototype.setDrilldown = function (selection) {\n if (selection) {\n var d3PieLayout = d3.layout.pie()\n .sort(null)\n .value(function (d) {\n return d.percentage;\n });\n // Drill into the current selection.\n var legendDataPoints = [{ label: selection.label, color: selection.color, icon: visuals.LegendIcon.Box, identity: selection.identity, selected: selection.selected }];\n var legendData = { title: \"\", dataPoints: legendDataPoints };\n var drilledDataPoints = d3PieLayout(selection.internalDataPoints);\n this.updateInternal({\n dataPointsToDeprecate: selection.internalDataPoints,\n dataPoints: drilledDataPoints,\n unCulledDataPoints: drilledDataPoints.map(function (value) { return value.data; }),\n legendData: legendData,\n hasHighlights: false,\n dataLabelsSettings: this.data.dataLabelsSettings,\n }, false /* suppressAnimations */, DonutChart.DrillDownAnimationDuration);\n }\n else {\n // Pop out of drill down to view the \"outer\" data.\n this.updateInternal(this.data, false /* suppressAnimations */, DonutChart.DrillDownAnimationDuration);\n }\n };\n DonutChart.prototype.assignInteractiveChartInteractions = function (slice) {\n var _this = this;\n var svg = this.svg;\n this.interactivityState.interactiveChosenSliceFinishedSetting = true;\n var svgRect = svg.node().getBoundingClientRect();\n this.interactivityState.donutCenter = { x: svgRect.left + svgRect.width / 2, y: svgRect.top + svgRect.height / 2 }; // Center of the donut chart\n this.interactivityState.totalDragAngleDifference = 0;\n this.interactivityState.currentRotate = 0;\n this.calculateSliceAngles();\n // Set the on click method for the slices so thsete pie chart will turn according to each slice's corresponding angle [the angle its on top]\n slice.on('click', function (d, clickedIndex) {\n if (d3.event.defaultPrevented)\n return; // click was suppressed, for example from drag event\n _this.setInteractiveChosenSlice(clickedIndex);\n });\n // Set the drag events\n var drag = d3.behavior.drag()\n .origin(Object)\n .on('dragstart', function () { return _this.interactiveDragStart(); })\n .on('drag', function () { return _this.interactiveDragMove(); })\n .on('dragend', function () { return _this.interactiveDragEnd(); });\n svg\n .style('touch-action', 'none')\n .call(drag);\n };\n /**\n * Get the angle (in degrees) of the drag event coordinates.\n * The angle is calculated against the plane of the center of the donut\n * (meaning, when the center of the donut is at (0,0) coordinates).\n */\n DonutChart.prototype.getAngleFromDragEvent = function () {\n var interactivityState = this.interactivityState;\n // get pageX and pageY (coordinates of the drag event) according to event type\n var pageX, pageY;\n var sourceEvent = d3.event.sourceEvent;\n // check if that's a touch event or not\n if (sourceEvent.type.toLowerCase().indexOf('touch') !== -1) {\n if (sourceEvent.touches.length !== 1)\n return null; // in case there isn't a single touch - return null and do nothing.\n // take the first, single, touch surface.\n var touch = sourceEvent.touches[0];\n pageX = touch.pageX;\n pageY = touch.pageY;\n }\n else {\n pageX = sourceEvent.pageX;\n pageY = sourceEvent.pageY;\n }\n // Adjust the coordinates, putting the donut center as the (0,0) coordinates\n var adjustedCoordinates = { x: pageX - interactivityState.donutCenter.x, y: -pageY + interactivityState.donutCenter.y };\n // Move to polar axis - take only the angle (theta), and convert to degrees\n var angleToThePlane = Math.atan2(adjustedCoordinates.y, adjustedCoordinates.x) * 180 / Math.PI;\n return angleToThePlane;\n };\n DonutChart.prototype.interactiveDragStart = function () {\n this.interactivityState.totalDragAngleDifference = 0;\n this.interactivityState.previousDragAngle = this.getAngleFromDragEvent();\n };\n DonutChart.prototype.interactiveDragMove = function () {\n var data = this.data.dataPoints;\n var viewport = this.currentViewport;\n var interactivityState = this.interactivityState;\n if (interactivityState.interactiveChosenSliceFinishedSetting === true) {\n // get current angle from the drag event\n var currentDragAngle = this.getAngleFromDragEvent();\n if (!currentDragAngle)\n return; // if no angle was returned, do nothing\n // compare it to the previous drag event angle\n var angleDragDiff = interactivityState.previousDragAngle - currentDragAngle;\n interactivityState.totalDragAngleDifference += angleDragDiff;\n interactivityState.previousDragAngle = currentDragAngle;\n // Rotate the chart by the difference in angles\n interactivityState.currentRotate += angleDragDiff;\n // Rotate the chart to the current rotate angle\n this.svg.select('g')\n .attr('transform', visuals.SVGUtil.translateAndRotate(viewport.width / 2, viewport.height / 2, 0, 0, this.interactivityState.currentRotate));\n var currentHigherLimit = data[0].data.percentage * interactivityState.valueToAngleFactor;\n var currentAngle = interactivityState.currentRotate <= 0 ? (interactivityState.currentRotate * -1) % 360 : (360 - (interactivityState.currentRotate % 360));\n interactivityState.currentIndexDrag = 0;\n //consider making this ++interactivityState.currentIndexDrag ? then you don't need the if statement, the interactivityState.currentIndexDrag +1 and interactivityState.currentIndexDrag++\n // Check the current index according to the angle \n var dataLength = data.length;\n while ((interactivityState.currentIndexDrag < dataLength) && (currentAngle > currentHigherLimit)) {\n if (interactivityState.currentIndexDrag < (dataLength - 1)) {\n currentHigherLimit += (data[interactivityState.currentIndexDrag + 1].data.percentage * interactivityState.valueToAngleFactor);\n }\n interactivityState.currentIndexDrag++;\n }\n // If the index changed update the legend and opacity\n if (interactivityState.currentIndexDrag !== interactivityState.previousIndexDrag) {\n interactivityState.interactiveLegend.updateLegend(interactivityState.currentIndexDrag);\n // set the opacticity of the top slice to full and the others to semi-transparent\n this.svg.selectAll('.slice').attr('opacity', function (d, index) {\n return index === interactivityState.currentIndexDrag ? DonutChart.OpaqueOpacity : DonutChart.SemiTransparentOpacity;\n });\n interactivityState.previousIndexDrag = interactivityState.currentIndexDrag;\n }\n }\n };\n DonutChart.prototype.interactiveDragEnd = function () {\n // If totalDragDifference was changed, means we have a drag event (compared to a click event)\n if (this.interactivityState.totalDragAngleDifference !== 0) {\n this.setInteractiveChosenSlice(this.interactivityState.currentIndexDrag);\n // drag happened - disable click event\n d3.event.sourceEvent.stopPropagation();\n }\n };\n DonutChart.prototype.updateInternalToMove = function (data, duration) {\n if (duration === void 0) { duration = 0; }\n // Cache for performance\n var svg = this.svg;\n var pie = this.pie;\n var key = this.key;\n var arc = this.arc;\n var radius = this.radius;\n var previousRadius = this.previousRadius;\n var sliceWidthRatio = this.sliceWidthRatio;\n var existingData = this.svg.select('.slices')\n .selectAll('path' + DonutChart.sliceClass.selector)\n .data().map(function (d) { return d.data; });\n if (existingData.length === 0) {\n existingData = data.dataPointsToDeprecate;\n }\n var is = this.mergeDatasets(existingData, data.dataPointsToDeprecate);\n var slice = svg.select('.slices')\n .selectAll('path' + DonutChart.sliceClass.selector)\n .data(pie(data.dataPointsToDeprecate), key);\n slice.enter()\n .insert('path')\n .classed(DonutChart.sliceClass.class, true)\n .each(function (d) { this._current = d; });\n slice = svg.select('.slices')\n .selectAll('path' + DonutChart.sliceClass.selector)\n .data(pie(is), key);\n var innerRadius = radius * sliceWidthRatio;\n DonutChart.isSingleColor(data.dataPoints);\n slice\n .style('fill', function (d) { return d.data.color; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, false, data.hasHighlights); })\n .style('stroke', 'white')\n .style('stroke-dasharray', function (d) { return DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio); })\n .style('stroke-width', function (d) { return d.data.strokeWidth; })\n .transition().duration(duration)\n .attrTween('d', function (d) {\n var i = d3.interpolate(this._current, d), k = d3.interpolate(previousRadius * DonutChart.InnerArcRadiusRatio, radius * DonutChart.InnerArcRadiusRatio);\n this._current = i(0);\n return function (t) {\n return arc.innerRadius(innerRadius).outerRadius(k(t))(i(t));\n };\n });\n slice = svg.select('.slices')\n .selectAll('path' + DonutChart.sliceClass.selector)\n .data(pie(data.dataPointsToDeprecate), key);\n slice.exit()\n .transition()\n .delay(duration)\n .duration(0)\n .remove();\n // For interactive chart, there shouldn't be slice labels (as you have the legend).\n if (!this.isInteractive) {\n var labelSettings = data.dataLabelsSettings;\n var labels = [];\n if (labelSettings && labelSettings.show) {\n labels = this.createLabels();\n }\n visuals.NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, labels, false, true);\n visuals.NewDataLabelUtils.drawLabelLeaderLines(this.labelGraphicsContext, labels);\n }\n var highlightSlices = undefined;\n if (data.hasHighlights) {\n // Draw partial highlight slices.\n highlightSlices = svg\n .select('.slices')\n .selectAll('path' + DonutChart.sliceHighlightClass.selector)\n .data(pie(data.dataPointsToDeprecate), key);\n highlightSlices\n .enter()\n .insert('path')\n .classed(DonutChart.sliceHighlightClass.class, true)\n .each(function (d) { this._current = d; });\n DonutChart.isSingleColor(data.dataPoints);\n highlightSlices\n .style('fill', function (d) { return d.data.color; })\n .style('fill-opacity', 1.0)\n .style('stroke', 'white')\n .style('stroke-dasharray', function (d) { return DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio, d.data.highlightRatio); })\n .style('stroke-width', function (d) { return d.data.highlightRatio === 0 ? 0 : d.data.strokeWidth; })\n .transition().duration(duration)\n .attrTween('d', function (d) {\n var i = d3.interpolate(this._current, d), k = d3.interpolate(previousRadius * DonutChart.InnerArcRadiusRatio, DonutChart.getHighlightRadius(radius, sliceWidthRatio, d.data.highlightRatio));\n this._current = i(0);\n return function (t) {\n return arc.innerRadius(innerRadius).outerRadius(k(t))(i(t));\n };\n });\n highlightSlices\n .exit()\n .transition()\n .delay(duration)\n .duration(0)\n .remove();\n }\n else {\n svg\n .selectAll('path' + DonutChart.sliceHighlightClass.selector)\n .transition()\n .delay(duration)\n .duration(0)\n .remove();\n }\n this.assignInteractions(slice, highlightSlices, data);\n if (this.tooltipsEnabled) {\n visuals.TooltipManager.addTooltip(slice, function (tooltipEvent) { return tooltipEvent.data.data.tooltipInfo; });\n if (data.hasHighlights) {\n visuals.TooltipManager.addTooltip(highlightSlices, function (tooltipEvent) { return tooltipEvent.data.data.tooltipInfo; });\n }\n }\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\n if (this.isInteractive) {\n this.addInteractiveLegendArrow();\n this.interactivityState.interactiveLegend.drawLegend(this.data.dataPointsToDeprecate);\n this.setInteractiveChosenSlice(this.interactivityState.lastChosenInteractiveSliceIndex ? this.interactivityState.lastChosenInteractiveSliceIndex : 0);\n }\n };\n DonutChart.drawDefaultShapes = function (graphicsContext, donutData, layout, colors, radius, hasSelection, sliceWidthRatio, defaultColor) {\n var shapes = graphicsContext.select('.slices')\n .selectAll('path' + DonutChart.sliceClass.selector)\n .data(donutData.dataPoints, function (d) { return d.data.identity.getKey(); });\n shapes.enter()\n .insert('path')\n .classed(DonutChart.sliceClass.class, true);\n DonutChart.isSingleColor(donutData.dataPoints);\n shapes\n .style('fill', function (d) { return d.data.color; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, donutData.hasHighlights); })\n .style('stroke-dasharray', function (d) { return DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio); })\n .style('stroke-width', function (d) { return d.data.strokeWidth; })\n .attr(layout.shapeLayout);\n shapes.exit()\n .remove();\n return shapes;\n };\n DonutChart.drawDefaultHighlightShapes = function (graphicsContext, donutData, layout, colors, radius, sliceWidthRatio) {\n var shapes = graphicsContext.select('.slices')\n .selectAll('path' + DonutChart.sliceHighlightClass.selector)\n .data(donutData.dataPoints.filter(function (value) { return value.data.highlightRatio != null; }), function (d) { return d.data.identity.getKey(); });\n shapes.enter()\n .insert('path')\n .classed(DonutChart.sliceHighlightClass.class, true)\n .each(function (d) { this._current = d; });\n DonutChart.isSingleColor(donutData.dataPoints);\n shapes\n .style('fill', function (d) { return d.data.color; })\n .style('fill-opacity', function (d) { return visuals.ColumnUtil.getFillOpacity(d.data.selected, true, false, donutData.hasHighlights); })\n .style('stroke', 'white')\n .style('stroke-dasharray', function (d) { return DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio, d.data.highlightRatio); })\n .style('stroke-width', function (d) { return d.data.highlightRatio === 0 ? 0 : d.data.strokeWidth; })\n .attr(layout.highlightShapeLayout);\n shapes.exit()\n .remove();\n return shapes;\n };\n /**\n Set true to the last data point when all slices have the same color\n */\n DonutChart.isSingleColor = function (dataPoints) {\n if (dataPoints.length > 1) {\n var lastPoint = dataPoints.length - 1;\n dataPoints[lastPoint].data.isLastInDonut = dataPoints[lastPoint].data.color === dataPoints[0].data.color;\n }\n };\n DonutChart.drawStrokeForDonutChart = function (radius, innerArcRadiusRatio, d, sliceWidthRatio, highlightRatio) {\n if (highlightRatio === void 0) { highlightRatio = 1; }\n var sliceRadius = radius * innerArcRadiusRatio * highlightRatio;\n var sliceArc = (d.endAngle - d.startAngle) * sliceRadius;\n var sectionWithoutStroke;\n var sectionWithStroke;\n /*Donut chart*/\n if (sliceWidthRatio) {\n var innerRadius = radius * sliceWidthRatio;\n var outerRadius = highlightRatio * radius * (DonutChart.InnerArcRadiusRatio - sliceWidthRatio);\n var innerSliceArc = (d.endAngle - d.startAngle) * innerRadius;\n if (d.data.highlightRatio)\n sliceArc = (d.endAngle - d.startAngle) * (outerRadius + innerRadius);\n if (d.data.isLastInDonut) {\n //if all slices have the same color, the stroke of the last slice needs to be drawn on both radiuses\n return 0 + \" \" + sliceArc + \" \" + outerRadius + \" \" + innerSliceArc + \" \" + outerRadius;\n }\n sectionWithoutStroke = sliceArc + outerRadius + innerSliceArc;\n sectionWithStroke = outerRadius;\n }\n else {\n if (d.data.isLastInDonut) {\n //if all slices have the same color, the stroke of the last slice needs to be drawn on both radiuses\n sectionWithoutStroke = sliceArc;\n sectionWithStroke = sliceRadius * 2;\n }\n else {\n sectionWithoutStroke = sliceArc + sliceRadius;\n sectionWithStroke = sliceRadius;\n }\n }\n return 0 + \" \" + sectionWithoutStroke + \" \" + sectionWithStroke;\n };\n DonutChart.prototype.onClearSelection = function () {\n if (this.interactivityService)\n this.interactivityService.clearSelection();\n };\n DonutChart.getLayout = function (radius, sliceWidthRatio, viewport) {\n var innerRadius = radius * sliceWidthRatio;\n var arc = d3.svg.arc().innerRadius(innerRadius);\n var arcWithRadius = arc.outerRadius(radius * DonutChart.InnerArcRadiusRatio);\n return {\n shapeLayout: {\n d: function (d) {\n return arcWithRadius(d);\n }\n },\n highlightShapeLayout: {\n d: function (d) {\n var highlightArc = arc.outerRadius(DonutChart.getHighlightRadius(radius, sliceWidthRatio, d.data.highlightRatio));\n return highlightArc(d);\n }\n },\n zeroShapeLayout: {\n d: function (d) {\n var zeroWithZeroRadius = arc.outerRadius(innerRadius || DonutChart.EffectiveZeroValue);\n return zeroWithZeroRadius(d);\n }\n },\n };\n };\n DonutChart.getHighlightRadius = function (radius, sliceWidthRatio, highlightRatio) {\n var innerRadius = radius * sliceWidthRatio;\n return innerRadius + highlightRatio * radius * (DonutChart.InnerArcRadiusRatio - sliceWidthRatio);\n };\n DonutChart.cullDataByViewport = function (dataPoints, maxValue, viewport) {\n var estimatedRadius = Math.min(viewport.width, viewport.height) / 2;\n // Ratio of slice too small to show (invisible) = invisbleArcLength / circumference\n var cullRatio = this.invisibleArcLengthInPixels / (estimatedRadius * DonutChart.twoPi);\n var cullableValue = cullRatio * maxValue;\n var culledDataPoints = [];\n var prevPointColor;\n for (var _i = 0, dataPoints_6 = dataPoints; _i < dataPoints_6.length; _i++) {\n var datapoint = dataPoints_6[_i];\n if (datapoint.measure >= cullableValue) {\n //updates the stroke width\n datapoint.strokeWidth = prevPointColor === datapoint.color ? 1 : 0;\n prevPointColor = datapoint.color;\n culledDataPoints.push(datapoint);\n }\n }\n return culledDataPoints;\n };\n DonutChart.ClassName = 'donutChart';\n DonutChart.InteractiveLegendClassName = 'donutLegend';\n DonutChart.InteractiveLegendArrowClassName = 'donutLegendArrow';\n DonutChart.DrillDownAnimationDuration = 1000;\n DonutChart.OuterArcRadiusRatio = 0.9;\n DonutChart.InnerArcRadiusRatio = 0.8;\n DonutChart.OpaqueOpacity = 1.0;\n DonutChart.SemiTransparentOpacity = 0.6;\n DonutChart.defaultSliceWidthRatio = 0.48;\n DonutChart.invisibleArcLengthInPixels = 3;\n DonutChart.sliceClass = createClassAndSelector('slice');\n DonutChart.sliceHighlightClass = createClassAndSelector('slice-highlight');\n DonutChart.twoPi = 2 * Math.PI;\n DonutChart.InteractiveLegendContainerHeight = 70;\n DonutChart.EffectiveZeroValue = 0.000000001; // Very small multiplier so that we have a properly shaped zero arc to animate to/from.\n DonutChart.PolylineOpacity = 0.5;\n return DonutChart;\n }());\n visuals.DonutChart = DonutChart;\n /**\n * This class is an interactive legend for the Donut Chart.\n *\n * Features: It is scrollable indefinitely, using drag gesture\n * when you interact with it, it updates the donut chart itself.\n */\n var DonutChartInteractiveLegend = (function () {\n function DonutChartInteractiveLegend(donutChart, legendContainer, colors, visualInitOptions, settings) {\n this.legendContainerParent = legendContainer;\n this.colors = colors;\n this.donutChart = donutChart;\n this.visualInitOptions = visualInitOptions;\n this.legendItemsPositions = [];\n this.legendTransitionAnimationDuration = settings && settings.legendTransitionAnimationDuration ? settings.legendTransitionAnimationDuration : 0;\n }\n DonutChartInteractiveLegend.prototype.drawLegend = function (data) {\n var _this = this;\n this.data = data;\n this.currentNumberOfLegendItems = data.length;\n this.currentIndex = 0;\n this.leftMostIndex = 0;\n this.rightMostIndex = data.length - 1;\n if (this.legendContainerParent.select(DonutChartInteractiveLegend.LegendContainerSelector).empty()) {\n this.legendContainer = this.legendContainerParent.append('div').classed(DonutChartInteractiveLegend.LegendContainerClassName, true);\n }\n var legendItems = this.legendContainer.selectAll(DonutChartInteractiveLegend.LegendItemSelector).data(data);\n var legendContainerWidth = this.legendContainerWidth = this.legendContainer.node().getBoundingClientRect().width;\n var initialXOffset = legendContainerWidth / 2 - (legendContainerWidth * 0.4 / 2) + DonutChartInteractiveLegend.ItemMargin;\n var currX = initialXOffset;\n this.currentXOffset = initialXOffset;\n // Given the legend item div, create the item values (category, percentage and measure) on top of it.\n var createLegendItem = function (itemDiv, datum) {\n // position the legend item\n itemDiv\n .attr('data-legend-index', datum.index) // assign index for later use\n .css({\n 'position': 'absolute',\n 'left': currX,\n });\n // Add the category, percentage and value\n var itemCategory = visuals.valueFormatter.format(datum.label);\n var itemValue = visuals.valueFormatter.format(datum.measure, datum.measureFormat);\n var itemPercentage = visuals.valueFormatter.format(datum.percentage, '0.00 %;-0.00 %;0.00 %');\n var itemColor = datum.color;\n // Create basic spans for width calculations\n var itemValueSpan = DonutChartInteractiveLegend.createBasicLegendItemSpan(DonutChartInteractiveLegend.LegendItemValueClassName, itemValue, 11);\n var itemCategorySpan = DonutChartInteractiveLegend.createBasicLegendItemSpan(DonutChartInteractiveLegend.LegendItemCategoryClassName, itemCategory, 11);\n var itemPercentageSpan = DonutChartInteractiveLegend.createBasicLegendItemSpan(DonutChartInteractiveLegend.LegendItemPercentageClassName, itemPercentage, 20);\n // Calculate Legend Box size according to widths and set the width accordingly\n var valueSpanWidth = DonutChartInteractiveLegend.spanWidth(itemValueSpan);\n var categorySpanWidth = DonutChartInteractiveLegend.spanWidth(itemCategorySpan);\n var precentageSpanWidth = DonutChartInteractiveLegend.spanWidth(itemPercentageSpan);\n var currentLegendBoxWidth = DonutChartInteractiveLegend.legendBoxSize(valueSpanWidth, categorySpanWidth, precentageSpanWidth);\n itemDiv.css('width', currentLegendBoxWidth);\n // Calculate margins so that all the spans will be placed in the middle\n var getLeftValue = function (spanWidth) {\n return currentLegendBoxWidth - spanWidth > 0 ? (currentLegendBoxWidth - spanWidth) / 2 : 0;\n };\n var marginLeftValue = getLeftValue(valueSpanWidth);\n var marginLeftCategory = getLeftValue(categorySpanWidth);\n var marginLeftPrecentage = getLeftValue(precentageSpanWidth);\n // Create the actual spans with the right styling and margins so it will be center aligned and add them\n DonutChartInteractiveLegend.createLegendItemSpan(itemCategorySpan, marginLeftCategory);\n DonutChartInteractiveLegend.createLegendItemSpan(itemValueSpan, marginLeftValue);\n DonutChartInteractiveLegend.createLegendItemSpan(itemPercentageSpan, marginLeftPrecentage).css('color', itemColor);\n itemDiv.append(itemCategorySpan);\n itemDiv.append(itemPercentageSpan);\n itemDiv.append(itemValueSpan);\n _this.legendItemsPositions.push({\n startX: currX,\n boxWidth: currentLegendBoxWidth,\n });\n currX += currentLegendBoxWidth + DonutChartInteractiveLegend.ItemMargin;\n };\n // Create the Legend Items\n legendItems.enter()\n .insert('div')\n .classed(DonutChartInteractiveLegend.LegendItemClassName, true)\n .each(function (d) {\n createLegendItem($(this), d);\n });\n legendItems.exit().remove();\n // Assign interactions on the legend\n this.assignInteractions();\n };\n DonutChartInteractiveLegend.prototype.updateLegend = function (sliceIndex) {\n var _this = this;\n var legendContainerWidth = this.legendContainerWidth;\n this.currentIndex = sliceIndex;\n // \"rearrange\" legend items if needed, so we would have contnious endless scrolling\n this.updateLabelBlocks(sliceIndex);\n var legendTransitionAnimationDuration = this.legendTransitionAnimationDuration;\n // Transform the legend so that the selected slice would be in the middle\n var nextXOffset = (this.legendItemsPositions[sliceIndex].startX + (this.legendItemsPositions[sliceIndex].boxWidth / 2) - (legendContainerWidth / 2)) * (-1);\n this.legendContainer\n .transition()\n .styleTween('-webkit-transform', function (d, i, a) {\n return d3.interpolate(visuals.SVGUtil.translateWithPixels(_this.currentXOffset, 0), visuals.SVGUtil.translateWithPixels(nextXOffset, 0));\n })\n .styleTween('transform', function (d, i, a) {\n return d3.interpolate(visuals.SVGUtil.translateWithPixels(_this.currentXOffset, 0), visuals.SVGUtil.translateWithPixels(nextXOffset, 0));\n })\n .duration(legendTransitionAnimationDuration)\n .ease('bounce')\n .each('end', function () {\n _this.currentXOffset = nextXOffset;\n });\n visuals.SVGUtil.flushAllD3TransitionsIfNeeded(this.visualInitOptions);\n };\n DonutChartInteractiveLegend.prototype.assignInteractions = function () {\n var _this = this;\n var currentDX = 0; // keep how much drag had happened\n var hasChanged = false; // flag to indicate if we changed the \"center\" value in the legend. We only change it once per swipe.\n var dragStart = function () {\n currentDX = 0; // start of drag gesture\n hasChanged = false;\n };\n var dragMove = function () {\n currentDX += d3.event.dx;\n // Detect if swipe occured and if the index already changed in this drag\n if (hasChanged || Math.abs(currentDX) < DonutChartInteractiveLegend.MinimumSwipeDX)\n return;\n var dragDirectionLeft = (currentDX < 0);\n _this.dragLegend(dragDirectionLeft);\n hasChanged = true;\n };\n var drag = d3.behavior.drag()\n .origin(Object)\n .on('drag', dragMove)\n .on('dragstart', dragStart);\n this.legendContainer\n .style({\n 'touch-action': 'none',\n 'cursor': 'pointer'\n })\n .call(drag);\n };\n DonutChartInteractiveLegend.prototype.dragLegend = function (dragDirectionLeft) {\n if (this.currentNumberOfLegendItems > (DonutChartInteractiveLegend.MinimumItemsInLegendForCycled - 1)) {\n this.currentIndex = this.getCyclingCurrentIndex(dragDirectionLeft);\n }\n else {\n if (this.shouldChangeIndexInNonCycling(dragDirectionLeft)) {\n if (dragDirectionLeft) {\n this.currentIndex++;\n }\n else {\n this.currentIndex--;\n }\n }\n }\n this.donutChart.setInteractiveChosenSlice(this.currentIndex);\n };\n DonutChartInteractiveLegend.prototype.shouldChangeIndexInNonCycling = function (dragDirectionLeft) {\n if ((this.currentIndex === 0 && !dragDirectionLeft) || (this.currentIndex === (this.currentNumberOfLegendItems - 1) && dragDirectionLeft)) {\n return false;\n }\n return true;\n };\n DonutChartInteractiveLegend.prototype.getCyclingCurrentIndex = function (dragDirectionLeft) {\n var dataLen = this.data.length;\n var delta = dragDirectionLeft ? 1 : -1;\n var newIndex = (this.currentIndex + delta) % (dataLen || 1); // modolu of negative number stays negative on javascript\n return (newIndex < 0) ? newIndex + dataLen : newIndex;\n };\n DonutChartInteractiveLegend.prototype.updateLegendItemsBlocks = function (rightSidedShift, numberOfLegendItemsBlocksToShift) {\n var legendContainer$ = $(this.legendContainer[0]);\n if (rightSidedShift) {\n var smallestItem = legendContainer$.find('[data-legend-index=' + this.leftMostIndex + ']');\n smallestItem.remove().insertAfter(legendContainer$.find('[data-legend-index=' + this.rightMostIndex + ']'));\n var newX = this.legendItemsPositions[this.rightMostIndex].startX + this.legendItemsPositions[this.rightMostIndex].boxWidth + DonutChartInteractiveLegend.ItemMargin;\n this.legendItemsPositions[this.leftMostIndex].startX = newX;\n smallestItem.css('left', newX);\n this.rightMostIndex = this.leftMostIndex;\n this.leftMostIndex = (this.leftMostIndex + 1) % this.data.length;\n }\n else {\n var highestItem = legendContainer$.find('[data-legend-index=' + this.rightMostIndex + ']');\n highestItem.remove().insertBefore(legendContainer$.find('[data-legend-index=' + this.leftMostIndex + ']'));\n var newX = this.legendItemsPositions[this.leftMostIndex].startX - this.legendItemsPositions[this.rightMostIndex].boxWidth - DonutChartInteractiveLegend.ItemMargin;\n this.legendItemsPositions[this.rightMostIndex].startX = newX;\n highestItem.css('left', newX);\n this.leftMostIndex = this.rightMostIndex;\n this.rightMostIndex = (this.rightMostIndex - 1) === -1 ? (this.legendItemsPositions.length - 1) : (this.rightMostIndex - 1);\n }\n if ((numberOfLegendItemsBlocksToShift - 1) !== 0) {\n this.updateLegendItemsBlocks(rightSidedShift, (numberOfLegendItemsBlocksToShift - 1));\n }\n };\n /** Update the legend items, allowing for endless rotation */\n DonutChartInteractiveLegend.prototype.updateLabelBlocks = function (index) {\n if (this.currentNumberOfLegendItems > DonutChartInteractiveLegend.MinimumItemsInLegendForCycled) {\n // The idea of the four if's is to keep two labels before and after the current one so it will fill the screen.\n // If the index of the slice is the highest currently availble add 2 labels \"ahead\" of it\n if (this.rightMostIndex === index)\n this.updateLegendItemsBlocks(true, 2);\n // If the index of the slice is the lowest currently availble add 2 labels \"before\" it\n if (this.leftMostIndex === index)\n this.updateLegendItemsBlocks(false, 2);\n // If the index of the slice is the second highest currently availble add a labels \"ahead\" of it\n if (this.rightMostIndex === (index + 1) || ((this.rightMostIndex === 0) && (index === (this.currentNumberOfLegendItems - 1))))\n this.updateLegendItemsBlocks(true, 1);\n // If the index of the slice is the second lowest currently availble add a labels \"before\" it\n if (this.leftMostIndex === (index - 1) || ((this.leftMostIndex === (this.currentNumberOfLegendItems - 1) && (index === 0))))\n this.updateLegendItemsBlocks(false, 1);\n }\n else {\n if (this.currentNumberOfLegendItems === DonutChartInteractiveLegend.MinimumItemsInLegendForCycled) {\n // If the index of the slice is the highest currently availble add a label \"ahead\" of it\n if (this.rightMostIndex === index)\n this.updateLegendItemsBlocks(true, 1);\n // If the index of the slice is the lowest currently availble add a label \"before\" it\n if (this.leftMostIndex === index)\n this.updateLegendItemsBlocks(false, 1);\n }\n }\n };\n DonutChartInteractiveLegend.createBasicLegendItemSpan = function (spanClass, text, fontSize) {\n return $('<span/>')\n .addClass(spanClass)\n .css({\n 'white-space': 'nowrap',\n 'font-size': fontSize + 'px',\n })\n .text(text);\n };\n /** This method alters the given span and sets it to the final legen item span style. */\n DonutChartInteractiveLegend.createLegendItemSpan = function (existingSpan, marginLeft) {\n existingSpan\n .css({\n 'overflow': 'hidden',\n 'text-overflow': 'ellipsis',\n 'display': 'inline-block',\n 'width': '100%',\n 'margin-left': marginLeft\n });\n return existingSpan;\n };\n /** Caclulte entire legend box size according to its building spans */\n DonutChartInteractiveLegend.legendBoxSize = function (valueSpanWidth, categorySpanWidth, precentageSpanWidth) {\n var boxSize = valueSpanWidth > categorySpanWidth ? valueSpanWidth : categorySpanWidth;\n boxSize = boxSize > precentageSpanWidth ? boxSize : precentageSpanWidth;\n boxSize = boxSize > DonutChartInteractiveLegend.MaxLegendItemBoxSize ? DonutChartInteractiveLegend.MaxLegendItemBoxSize : (boxSize + 2);\n return boxSize;\n };\n DonutChartInteractiveLegend.spanWidth = function (span) {\n if (!this.FakeElementSpan) {\n this.FakeElementSpan = $('<span>').hide().appendTo(document.body);\n }\n this.FakeElementSpan.empty();\n this.FakeElementSpan.append(span);\n return this.FakeElementSpan.width();\n };\n DonutChartInteractiveLegend.LegendContainerClassName = 'legend-container';\n DonutChartInteractiveLegend.LegendContainerSelector = '.legend-container';\n DonutChartInteractiveLegend.LegendItemClassName = 'legend-item';\n DonutChartInteractiveLegend.LegendItemSelector = '.legend-item';\n DonutChartInteractiveLegend.LegendItemCategoryClassName = 'category';\n DonutChartInteractiveLegend.LegendItemPercentageClassName = 'percentage';\n DonutChartInteractiveLegend.LegendItemValueClassName = 'value';\n DonutChartInteractiveLegend.MaxLegendItemBoxSize = 160;\n DonutChartInteractiveLegend.ItemMargin = 30; // Margin between items\n DonutChartInteractiveLegend.MinimumSwipeDX = 15; // Minimup swipe gesture to create a change in the legend\n DonutChartInteractiveLegend.MinimumItemsInLegendForCycled = 3; // Minimum items in the legend before we cycle it\n return DonutChartInteractiveLegend;\n }());\n var DonutChartConversion;\n (function (DonutChartConversion) {\n ;\n var DonutChartConverter = (function () {\n function DonutChartConverter(dataView, colors, defaultDataPointColor, tooltipsEnabled) {\n if (tooltipsEnabled === void 0) { tooltipsEnabled = true; }\n var reader = this.reader = powerbi.data.createIDataViewCategoricalReader(dataView);\n var dataViewCategorical = dataView.categorical;\n this.dataViewCategorical = dataViewCategorical;\n this.dataViewMetadata = dataView.metadata;\n this.tooltipsEnabled = tooltipsEnabled;\n this.colorHelper = new visuals.ColorHelper(colors, visuals.donutChartProps.dataPoint.fill, defaultDataPointColor);\n this.maxValue = 0;\n if (dataViewCategorical.categories && dataViewCategorical.categories.length > 0) {\n var category = dataViewCategorical.categories[0];\n this.categoryIdentities = category.identity;\n this.categoryValues = category.values;\n this.allCategoryObjects = category.objects;\n this.categoryColumnRef = category.identityFields;\n this.categoryFormatString = visuals.valueFormatter.getFormatString(category.source, visuals.donutChartProps.general.formatString);\n }\n var grouped = this.grouped = dataViewCategorical && dataViewCategorical.values ? dataViewCategorical.values.grouped() : undefined;\n this.isMultiMeasure = grouped && grouped.length > 0 && grouped[0].values && grouped[0].values.length > 1;\n this.isSingleMeasure = grouped && grouped.length === 1 && grouped[0].values && grouped[0].values.length === 1;\n this.isDynamicSeries = !!(dataViewCategorical.values && dataViewCategorical.values.source);\n this.highlightsOverflow = false;\n this.total = 0;\n this.highlightTotal = 0;\n this.dataPoints = [];\n this.legendDataPoints = [];\n this.dataLabelsSettings = null;\n if (reader.hasValues(\"Y\")) {\n var seriesCount = this.seriesCount = reader.getSeriesCount(\"Y\");\n this.hasHighlights = this.seriesCount > 0 && !_.isEmpty(dataViewCategorical.values) && !!dataViewCategorical.values[0].highlights;\n // We iterate over all categories, or if we have no categories, we just iterate over the series (category index = 0 is fine in that case)\n for (var categoryIndex = 0, categoryCount = reader.getCategoryCount() || 1; categoryIndex < categoryCount; categoryIndex++) {\n for (var seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\n this.total += Math.abs(reader.getValue(\"Y\", categoryIndex, seriesIndex));\n this.highlightTotal += this.hasHighlights ? Math.abs(reader.getHighlight(\"Y\", categoryIndex, seriesIndex)) : 0;\n }\n }\n }\n this.total = visuals.AxisHelper.normalizeNonFiniteNumber(this.total);\n this.highlightTotal = visuals.AxisHelper.normalizeNonFiniteNumber(this.highlightTotal);\n }\n DonutChartConverter.normalizedMeasureAndValue = function (measureAndValue) {\n var normalized = $.extend(true, {}, measureAndValue);\n normalized.measure = visuals.AxisHelper.normalizeNonFiniteNumber(normalized.measure);\n normalized.value = visuals.AxisHelper.normalizeNonFiniteNumber(normalized.value);\n return normalized;\n };\n DonutChartConverter.prototype.convert = function () {\n var reader = this.reader;\n var convertedData;\n if (this.total !== 0) {\n // We render based on categories, series, or measures in that order of preference\n if (this.categoryValues) {\n convertedData = this.convertCategoricalWithSlicing();\n }\n else if (this.isDynamicSeries) {\n // Series but no category.\n convertedData = this.convertSeries();\n }\n else {\n // No category or series; only measures.\n convertedData = this.convertMeasures();\n }\n }\n else {\n convertedData = [];\n }\n // Check if any of the highlight values are > non-highlight values\n var highlightsOverflow = false;\n for (var i = 0, dataPointCount = convertedData.length; i < dataPointCount && !highlightsOverflow; i++) {\n var point = convertedData[i];\n if (Math.abs(point.highlightMeasureValue.measure) > Math.abs(point.measureValue.measure)) {\n highlightsOverflow = true;\n }\n }\n // Create data labels settings\n this.dataLabelsSettings = this.convertDataLabelSettings();\n var dataViewMetadata = this.dataViewMetadata;\n if (dataViewMetadata) {\n var objects = dataViewMetadata.objects;\n if (objects) {\n this.legendObjectProperties = objects['legend'];\n }\n }\n var category = !_.isEmpty(this.dataViewCategorical.categories) ? this.dataViewCategorical.categories[0] : null;\n this.dataPoints = [];\n var formatStringProp = visuals.donutChartProps.general.formatString;\n var prevPointColor;\n var pctFormatString = visuals.valueFormatter.getLocalizedString('Percentage');\n for (var i = 0, dataPointCount = convertedData.length; i < dataPointCount; i++) {\n var point = convertedData[i];\n // Normalize the values here and then handle tooltip value as infinity\n var normalizedHighlight = DonutChartConverter.normalizedMeasureAndValue(point.highlightMeasureValue);\n var normalizedNonHighlight = DonutChartConverter.normalizedMeasureAndValue(point.measureValue);\n var measure = normalizedNonHighlight.measure;\n var percentage = (this.total > 0) ? normalizedNonHighlight.value / this.total : 0.0;\n var highlightRatio = void 0;\n var highlightPercentage = void 0;\n if (normalizedNonHighlight.value > this.maxValue)\n this.maxValue = normalizedNonHighlight.value;\n if (normalizedHighlight.value > this.maxValue)\n this.maxValue = normalizedHighlight.value;\n if (this.hasHighlights) {\n // When any highlight value is greater than the corresponding non-highlight value\n // we just render all of the highlight values and discard the non-highlight values.\n if (highlightsOverflow) {\n measure = normalizedHighlight.measure;\n percentage = (this.highlightTotal > 0) ? normalizedHighlight.value / this.highlightTotal : 0.0;\n highlightRatio = 1;\n }\n else {\n highlightRatio = normalizedNonHighlight.value !== 0 ? normalizedHighlight.value / normalizedNonHighlight.value : 0;\n }\n if (!highlightRatio) {\n highlightRatio = DonutChart.EffectiveZeroValue;\n }\n highlightPercentage = percentage * highlightRatio;\n }\n var categoryValue = point.categoryLabel;\n var categorical = this.dataViewCategorical;\n var valueIndex = void 0;\n if (point.seriesIndex != null) {\n valueIndex = point.seriesIndex;\n }\n else {\n // Static series with no categories\n valueIndex = i;\n }\n var valuesMetadata = reader.getValueMetadataColumn(\"Y\", valueIndex);\n var value = this.hasHighlights && highlightsOverflow ? point.highlightMeasureValue.measure : point.measureValue.measure;\n var highlightValue = this.hasHighlights && !highlightsOverflow ? point.highlightMeasureValue.measure : undefined;\n var formatString = visuals.valueFormatter.getFormatString(valuesMetadata, formatStringProp);\n var pct = visuals.valueFormatter.format(percentage, pctFormatString);\n var valueAndPct = void 0;\n valueAndPct = visuals.valueFormatter.format(value, formatString) + ' (' + pct + ')';\n var highlightValueAndPct = void 0;\n if (this.hasHighlights && highlightValue != null && highlightPercentage != null) {\n var highlightedPct = visuals.valueFormatter.format(highlightPercentage, pctFormatString);\n highlightValueAndPct = visuals.valueFormatter.format(highlightValue, formatString) + ' (' + highlightedPct + ')';\n }\n var tooltipInfo = void 0;\n if (this.tooltipsEnabled) {\n tooltipInfo = [];\n if (category) {\n tooltipInfo.push({\n displayName: category.source.displayName,\n value: categoryValue,\n });\n }\n if (this.isDynamicSeries) {\n if (!category || category.source !== categorical.values.source) {\n // Category/series on the same column -- don't repeat its value in the tooltip.\n tooltipInfo.push({\n displayName: categorical.values.source.displayName,\n value: point.label,\n });\n }\n }\n if (valueAndPct != null) {\n tooltipInfo.push({\n displayName: valuesMetadata.displayName,\n value: valueAndPct,\n });\n }\n if (highlightValueAndPct != null) {\n tooltipInfo.push({\n displayName: visuals.ToolTipComponent.localizationOptions.highlightedValueDisplayName,\n value: highlightValueAndPct,\n });\n }\n }\n var strokeWidth = prevPointColor === point.color && value && value > 0 ? 1 : 0;\n prevPointColor = value && value > 0 ? point.color : prevPointColor;\n this.dataPoints.push({\n identity: point.identity,\n measure: measure,\n measureFormat: point.measureFormat,\n percentage: percentage,\n index: point.index,\n label: point.label,\n highlightRatio: highlightRatio,\n highlightValue: highlightValue,\n selected: false,\n tooltipInfo: tooltipInfo,\n color: point.color,\n strokeWidth: strokeWidth,\n labelFormatString: valuesMetadata.format,\n });\n }\n this.legendData = this.convertLegendData();\n };\n DonutChartConverter.prototype.getLegendTitle = function () {\n if (this.total !== 0) {\n // If category exists, we render title using category source. If not, we render title\n // using measure.\n var dvValuesSourceName = this.dataViewCategorical.values && this.dataViewCategorical.values.source\n ? this.dataViewCategorical.values.source.displayName : \"\";\n var dvCategorySourceName = this.dataViewCategorical.categories && this.dataViewCategorical.categories.length > 0 && this.dataViewCategorical.categories[0].source\n ? this.dataViewCategorical.categories[0].source.displayName : \"\";\n if (this.categoryValues) {\n return dvCategorySourceName;\n }\n else {\n return dvValuesSourceName;\n }\n }\n else {\n return \"\";\n }\n };\n DonutChartConverter.prototype.convertCategoricalWithSlicing = function () {\n var reader = this.reader;\n var dataViewCategorical = this.dataViewCategorical;\n var formatStringProp = visuals.donutChartProps.general.formatString;\n var dataPoints = [];\n for (var categoryIndex = 0, categoryCount = this.categoryValues.length; categoryIndex < categoryCount; categoryIndex++) {\n var categoryValue = this.categoryValues[categoryIndex];\n var thisCategoryObjects = this.allCategoryObjects ? this.allCategoryObjects[categoryIndex] : undefined;\n var legendIdentity = visuals.SelectionId.createWithId(this.categoryIdentities[categoryIndex]);\n var color = this.colorHelper.getColorForSeriesValue(thisCategoryObjects, this.categoryColumnRef, categoryValue);\n var categoryLabel = visuals.valueFormatter.format(categoryValue, this.categoryFormatString);\n // Series are either measures in the multi-measure case, or the single series otherwise\n for (var seriesIndex = 0; seriesIndex < this.seriesCount; seriesIndex++) {\n var valueColumn = reader.getValueColumn(\"Y\", seriesIndex);\n var label = this.isSingleMeasure\n ? categoryLabel\n : visuals.converterHelper.getFormattedLegendLabel(valueColumn.source, dataViewCategorical.values, formatStringProp);\n var nonHighlight = reader.getValue(\"Y\", categoryIndex, seriesIndex) || 0;\n var highlight = void 0;\n if (this.hasHighlights) {\n highlight = reader.getHighlight(\"Y\", categoryIndex, seriesIndex);\n }\n var measure = valueColumn.source.queryName;\n var identity = visuals.SelectionIdBuilder.builder()\n .withCategory(dataViewCategorical.categories[0], categoryIndex)\n .withSeries(dataViewCategorical.values, this.isDynamicSeries ? valueColumn : undefined)\n .withMeasure(measure)\n .createSelectionId();\n var dataPoint = {\n identity: identity,\n measureFormat: visuals.valueFormatter.getFormatString(valueColumn.source, formatStringProp, true),\n measureValue: {\n measure: nonHighlight,\n value: Math.abs(nonHighlight),\n },\n highlightMeasureValue: {\n measure: highlight,\n value: highlight != null ? Math.abs(highlight) : null,\n },\n index: categoryIndex * this.seriesCount + seriesIndex,\n label: label,\n categoryLabel: categoryLabel,\n color: color,\n seriesIndex: seriesIndex\n };\n dataPoints.push(dataPoint);\n }\n this.legendDataPoints.push({\n label: categoryLabel,\n color: color,\n icon: visuals.LegendIcon.Box,\n identity: legendIdentity,\n selected: false\n });\n }\n return dataPoints;\n };\n DonutChartConverter.prototype.convertMeasures = function () {\n var reader = this.reader;\n var dataPoints = [];\n var formatStringProp = visuals.donutChartProps.general.formatString;\n for (var measureIndex = 0; measureIndex < this.seriesCount; measureIndex++) {\n var valueColumn = reader.getValueColumn(\"Y\", measureIndex);\n var measureFormat = visuals.valueFormatter.getFormatString(valueColumn.source, formatStringProp, true);\n var measureLabel = valueColumn.source.displayName;\n var identity = visuals.SelectionId.createWithMeasure(valueColumn.source.queryName);\n var nonHighlight = reader.getValue(\"Y\", 0, measureIndex) || 0;\n var highlight = this.hasHighlights ? reader.getHighlight(\"Y\", 0, measureIndex) : 0;\n var color = this.colorHelper.getColorForMeasure(valueColumn.source.objects, valueColumn.source.queryName);\n var dataPoint = {\n identity: identity,\n measureFormat: measureFormat,\n measureValue: {\n measure: nonHighlight,\n value: Math.abs(nonHighlight),\n },\n highlightMeasureValue: {\n measure: highlight,\n value: Math.abs(highlight),\n },\n index: measureIndex,\n label: measureLabel,\n categoryLabel: measureLabel,\n color: color\n };\n dataPoints.push(dataPoint);\n this.legendDataPoints.push({\n label: dataPoint.label,\n color: dataPoint.color,\n icon: visuals.LegendIcon.Box,\n identity: dataPoint.identity,\n selected: false\n });\n }\n return dataPoints;\n };\n DonutChartConverter.prototype.convertSeries = function () {\n var reader = this.reader;\n var dataViewCategorical = this.dataViewCategorical;\n var dataPoints = [];\n var formatStringProp = visuals.donutChartProps.general.formatString;\n for (var seriesIndex = 0; seriesIndex < this.seriesCount; seriesIndex++) {\n var valueColumn = reader.getValueColumn(\"Y\", seriesIndex);\n var seriesFormat = visuals.valueFormatter.getFormatString(valueColumn.source, formatStringProp, true);\n var label = visuals.converterHelper.getFormattedLegendLabel(valueColumn.source, dataViewCategorical.values, formatStringProp);\n var identity = new visuals.SelectionIdBuilder()\n .withSeries(dataViewCategorical.values, valueColumn)\n .withMeasure(valueColumn.source.queryName)\n .createSelectionId();\n var seriesName = visuals.converterHelper.getSeriesName(valueColumn.source);\n var objects = this.grouped && this.grouped[seriesIndex] && this.grouped[seriesIndex].objects;\n var nonHighlight = reader.getValue(\"Y\", 0, seriesIndex) || 0;\n var highlight = this.hasHighlights ? reader.getHighlight(\"Y\", 0, seriesIndex) || 0 : 0;\n var color = this.colorHelper.getColorForSeriesValue(objects, dataViewCategorical.values.identityFields, seriesName);\n var dataPoint = {\n identity: identity,\n measureFormat: seriesFormat,\n measureValue: {\n measure: nonHighlight,\n value: Math.abs(nonHighlight),\n },\n highlightMeasureValue: {\n measure: highlight,\n value: Math.abs(highlight),\n },\n index: seriesIndex,\n label: label,\n categoryLabel: label,\n color: color,\n seriesIndex: seriesIndex\n };\n dataPoints.push(dataPoint);\n this.legendDataPoints.push({\n label: dataPoint.label,\n color: dataPoint.color,\n icon: visuals.LegendIcon.Box,\n identity: dataPoint.identity,\n selected: false\n });\n }\n return dataPoints;\n };\n DonutChartConverter.prototype.convertDataLabelSettings = function () {\n var dataViewMetadata = this.dataViewMetadata;\n var dataLabelsSettings = visuals.dataLabelUtils.getDefaultDonutLabelSettings();\n if (dataViewMetadata) {\n var objects = dataViewMetadata.objects;\n if (objects) {\n // Handle lables settings\n var labelsObj = objects['labels'];\n if (labelsObj) {\n visuals.dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\n }\n }\n }\n return dataLabelsSettings;\n };\n DonutChartConverter.prototype.convertLegendData = function () {\n return {\n dataPoints: this.legendDataPoints,\n labelColor: visuals.LegendData.DefaultLegendLabelFillColor,\n title: this.getLegendTitle(),\n fontSize: visuals.SVGLegend.DefaultFontSizeInPt,\n };\n };\n return DonutChartConverter;\n }());\n DonutChartConversion.DonutChartConverter = DonutChartConverter;\n })(DonutChartConversion || (DonutChartConversion = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var Utility = jsCommon.Utility;\n var ScriptVisual = (function () {\n function ScriptVisual(options) {\n this.canRefresh = options.canRefresh;\n }\n ScriptVisual.prototype.init = function (options) {\n this.element = options.element;\n this.hostServices = options.host;\n if (!this.canRefresh) {\n this.hostServices.setWarnings([new visuals.ScriptVisualRefreshWarning()]);\n }\n };\n ScriptVisual.prototype.update = function (options) {\n debug.assertValue(options, 'options');\n var dataViews = options.dataViews;\n if (!dataViews || dataViews.length === 0)\n return;\n var dataView = dataViews[0];\n if (!dataView || !dataView.metadata)\n return;\n var imageUrl = this.getImageUrl(dataView);\n var div = this.ensureHtmlElement();\n if (imageUrl && Utility.isValidImageDataUrl(imageUrl)) {\n var viewport = options.viewport;\n div.css({ height: viewport.height, width: viewport.width, backgroundImage: 'url(' + imageUrl + ')' });\n }\n else {\n div.css({ backgroundImage: 'none' });\n }\n };\n ScriptVisual.prototype.onResizing = function (finalViewport) {\n var div = this.ensureHtmlElement();\n div.css({ height: finalViewport.height, width: finalViewport.width });\n };\n ScriptVisual.prototype.getImageUrl = function (dataView) {\n debug.assertValue(dataView, 'dataView');\n if (dataView.scriptResult && dataView.scriptResult.imageBase64) {\n return \"data:image/png;base64,\" + dataView.scriptResult.imageBase64;\n }\n return null;\n };\n ScriptVisual.prototype.ensureHtmlElement = function () {\n var div = this.imageBackgroundElement;\n if (!div) {\n div = $(\"<div class='imageBackground' />\");\n this.imageBackgroundElement = div;\n this.imageBackgroundElement.appendTo(this.element);\n }\n return div;\n };\n return ScriptVisual;\n }());\n visuals.ScriptVisual = ScriptVisual;\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var plugins;\n (function (plugins) {\n // This file registers the built-in visualizations\n plugins.animatedNumber = {\n name: 'animatedNumber',\n capabilities: visuals.capabilities.animatedNumber,\n create: function () { return new visuals.AnimatedNumber(); }\n };\n plugins.areaChart = {\n name: 'areaChart',\n watermarkKey: 'area',\n capabilities: visuals.capabilities.lineChart,\n create: function () { return new visuals.CartesianChart({ chartType: 1 /* Area */ }); },\n customizeQuery: visuals.LineChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.barChart = {\n name: 'barChart',\n watermarkKey: 'bar',\n capabilities: visuals.capabilities.barChart,\n create: function () { return new visuals.CartesianChart({ chartType: 6 /* StackedBar */ }); },\n customizeQuery: visuals.ColumnChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.basicShape = {\n name: 'basicShape',\n capabilities: visuals.basicShapeCapabilities,\n create: function () { return new visuals.BasicShapeVisual(); }\n };\n plugins.card = {\n name: 'card',\n watermarkKey: 'card',\n capabilities: visuals.capabilities.card,\n create: function () { return new visuals.Card(); }\n };\n plugins.multiRowCard = {\n name: 'multiRowCard',\n watermarkKey: 'multiRowCard',\n capabilities: visuals.capabilities.multiRowCard,\n create: function () { return new visuals.MultiRowCard(); },\n getSortableRoles: function (visualSortableOptions) { return visuals.MultiRowCard.getSortableRoles(visualSortableOptions); },\n };\n plugins.clusteredBarChart = {\n name: 'clusteredBarChart',\n watermarkKey: 'clusteredBar',\n capabilities: visuals.capabilities.clusteredBarChart,\n create: function () { return new visuals.CartesianChart({ chartType: 5 /* ClusteredBar */ }); },\n customizeQuery: visuals.ColumnChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.clusteredColumnChart = {\n name: 'clusteredColumnChart',\n watermarkKey: 'clusteredColumn',\n capabilities: visuals.capabilities.clusteredColumnChart,\n create: function () { return new visuals.CartesianChart({ chartType: 3 /* ClusteredColumn */ }); },\n customizeQuery: visuals.ColumnChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.columnChart = {\n name: 'columnChart',\n watermarkKey: 'column',\n capabilities: visuals.capabilities.columnChart,\n create: function () { return new visuals.CartesianChart({ chartType: 4 /* StackedColumn */ }); },\n customizeQuery: visuals.ColumnChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.comboChart = {\n name: 'comboChart',\n watermarkKey: 'combo',\n capabilities: visuals.capabilities.comboChart,\n customizeQuery: visuals.ComboChart.customizeQuery,\n create: function () { return new visuals.CartesianChart({ chartType: 10 /* ComboChart */ }); },\n getSortableRoles: function (visualSortableOptions) { return visuals.ComboChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.dataDotChart = {\n name: 'dataDotChart',\n capabilities: visuals.capabilities.dataDotChart,\n create: function () { return new visuals.CartesianChart({ chartType: 11 /* DataDot */ }); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.dataDotClusteredColumnComboChart = {\n name: 'dataDotClusteredColumnComboChart',\n watermarkKey: 'combo',\n capabilities: visuals.capabilities.dataDotClusteredColumnComboChart,\n customizeQuery: visuals.ComboChart.customizeQuery,\n create: function () { return new visuals.CartesianChart({ chartType: 15 /* DataDotClusteredColumnCombo */ }); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.dataDotStackedColumnComboChart = {\n name: 'dataDotStackedColumnComboChart',\n watermarkKey: 'combo',\n capabilities: visuals.capabilities.dataDotStackedColumnComboChart,\n customizeQuery: visuals.ComboChart.customizeQuery,\n create: function () { return new visuals.CartesianChart({ chartType: 16 /* DataDotStackedColumnCombo */ }); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.donutChart = {\n name: 'donutChart',\n watermarkKey: 'donut',\n capabilities: visuals.capabilities.donutChart,\n create: function () { return new visuals.DonutChart(); }\n };\n plugins.funnel = {\n name: 'funnel',\n watermarkKey: 'funnel',\n capabilities: visuals.capabilities.funnel,\n create: function () { return new visuals.FunnelChart(); }\n };\n plugins.gauge = {\n name: 'gauge',\n watermarkKey: 'gauge',\n capabilities: visuals.capabilities.gauge,\n create: function () { return new visuals.Gauge(); }\n };\n plugins.hundredPercentStackedBarChart = {\n name: 'hundredPercentStackedBarChart',\n watermarkKey: '100stackedbar',\n capabilities: visuals.capabilities.hundredPercentStackedBarChart,\n create: function () { return new visuals.CartesianChart({ chartType: 7 /* HundredPercentStackedBar */ }); },\n customizeQuery: visuals.ColumnChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.hundredPercentStackedColumnChart = {\n name: 'hundredPercentStackedColumnChart',\n watermarkKey: '100stackedcolumn',\n capabilities: visuals.capabilities.hundredPercentStackedColumnChart,\n create: function () { return new visuals.CartesianChart({ chartType: 8 /* HundredPercentStackedColumn */ }); },\n customizeQuery: visuals.ColumnChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.image = {\n name: 'image',\n capabilities: visuals.capabilities.image,\n create: function () { return new visuals.ImageVisual(); }\n };\n plugins.lineChart = {\n name: 'lineChart',\n watermarkKey: 'line',\n capabilities: visuals.capabilities.lineChart,\n create: function () { return new visuals.CartesianChart({ chartType: 0 /* Line */ }); },\n customizeQuery: visuals.LineChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.LineChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.lineStackedColumnComboChart = {\n name: 'lineStackedColumnComboChart',\n watermarkKey: 'combo',\n capabilities: visuals.capabilities.lineStackedColumnComboChart,\n customizeQuery: visuals.ComboChart.customizeQuery,\n create: function () { return new visuals.CartesianChart({ chartType: 14 /* LineStackedColumnCombo */ }); },\n getSortableRoles: function (visualSortableOptions) { return visuals.ComboChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.lineClusteredColumnComboChart = {\n name: 'lineClusteredColumnComboChart',\n watermarkKey: 'combo',\n capabilities: visuals.capabilities.lineClusteredColumnComboChart,\n customizeQuery: visuals.ComboChart.customizeQuery,\n create: function () { return new visuals.CartesianChart({ chartType: 13 /* LineClusteredColumnCombo */ }); },\n getSortableRoles: function (visualSortableOptions) { return visuals.ComboChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.map = {\n name: 'map',\n watermarkKey: 'map',\n capabilities: visuals.capabilities.map,\n create: function () { return new visuals.Map({ filledMap: false }); }\n };\n plugins.filledMap = {\n name: 'filledMap',\n watermarkKey: 'filledMap',\n capabilities: visuals.capabilities.filledMap,\n create: function () { return new visuals.Map({ filledMap: true }); }\n };\n plugins.treemap = {\n name: 'treemap',\n watermarkKey: 'tree',\n capabilities: visuals.capabilities.treemap,\n create: function () { return new visuals.Treemap(); }\n };\n plugins.pieChart = {\n name: 'pieChart',\n watermarkKey: 'pie',\n capabilities: visuals.capabilities.donutChart,\n create: function () { return new visuals.DonutChart({ sliceWidthRatio: 0 }); }\n };\n plugins.scatterChart = {\n name: 'scatterChart',\n watermarkKey: 'scatterplot',\n capabilities: visuals.capabilities.scatterChart,\n create: function () { return new visuals.CartesianChart({ chartType: 9 /* Scatter */ }); },\n getAdditionalTelemetry: function (dataView) { return visuals.ScatterChart.getAdditionalTelemetry(dataView); },\n };\n plugins.stackedAreaChart = {\n name: 'stackedAreaChart',\n watermarkKey: 'stackedarea',\n capabilities: visuals.capabilities.lineChart,\n create: function () { return new visuals.CartesianChart({ chartType: 2 /* StackedArea */ }); },\n customizeQuery: visuals.LineChart.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.ColumnChart.getSortableRoles(visualSortableOptions); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.table = {\n name: 'table',\n watermarkKey: 'table',\n capabilities: visuals.capabilities.table,\n create: function () { return new visuals.Table(); },\n customizeQuery: visuals.Table.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.Table.getSortableRoles(); },\n };\n plugins.matrix = {\n name: 'matrix',\n watermarkKey: 'matrix',\n capabilities: visuals.capabilities.matrix,\n create: function () { return new visuals.Matrix(); },\n customizeQuery: visuals.Matrix.customizeQuery,\n getSortableRoles: function (visualSortableOptions) { return visuals.Matrix.getSortableRoles(); },\n };\n plugins.slicer = {\n name: 'slicer',\n watermarkKey: 'slicer',\n capabilities: visuals.capabilities.slicer,\n create: function () { return new visuals.Slicer(); }\n };\n plugins.textbox = {\n name: 'textbox',\n capabilities: visuals.capabilities.textbox,\n create: function () { return new visuals.Textbox(); }\n };\n plugins.waterfallChart = {\n name: 'waterfallChart',\n watermarkKey: 'waterfall',\n capabilities: visuals.capabilities.waterfallChart,\n create: function () { return new visuals.CartesianChart({ chartType: 12 /* Waterfall */ }); },\n getAdditionalTelemetry: function (dataView) { return visuals.CartesianChart.getAdditionalTelemetry(dataView); },\n };\n plugins.cheerMeter = {\n name: 'cheerMeter',\n capabilities: visuals.CheerMeter.capabilities,\n create: function () { return new visuals.CheerMeter(); }\n };\n plugins.consoleWriter = {\n name: 'consoleWriter',\n capabilities: visuals.samples.consoleWriterCapabilities,\n create: function () { return new visuals.samples.ConsoleWriter(); }\n };\n plugins.helloIVisual = {\n name: 'helloIVisual',\n capabilities: visuals.samples.HelloIVisual.capabilities,\n create: function () { return new visuals.samples.HelloIVisual(); }\n };\n plugins.owlGauge = {\n name: 'owlGauge',\n watermarkKey: 'gauge',\n capabilities: visuals.OwlGauge.capabilities,\n create: function () { return new visuals.OwlGauge(); }\n };\n plugins.scriptVisual = {\n name: 'scriptVisual',\n watermarkKey: 'scriptvisual',\n capabilities: visuals.capabilities.scriptVisual,\n create: function () { return new visuals.ScriptVisual({ canRefresh: false }); }\n };\n plugins.kpi = {\n name: 'kpi',\n watermarkKey: 'kpi',\n capabilities: visuals.capabilities.kpi,\n create: function () { return new visuals.KPIStatusWithHistory(); }\n };\n })(plugins = visuals.plugins || (visuals.plugins = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n/*\n * Power BI Visualizations\n *\n * Copyright (c) Microsoft Corporation\n * All rights reserved.\n * MIT License\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nvar powerbi;\n(function (powerbi) {\n var visuals;\n (function (visuals) {\n var CanvasBackgroundHelper;\n (function (CanvasBackgroundHelper) {\n function getDefaultColor() {\n return '#FFFFFF';\n }\n CanvasBackgroundHelper.getDefaultColor = getDefaultColor;\n function getDefaultValues() {\n return {\n color: getDefaultColor(),\n };\n }\n CanvasBackgroundHelper.getDefaultValues = getDefaultValues;\n })(CanvasBackgroundHelper = visuals.CanvasBackgroundHelper || (visuals.CanvasBackgroundHelper = {}));\n })(visuals = powerbi.visuals || (powerbi.visuals = {}));\n})(powerbi || (powerbi = {}));\n\n\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export class Point implements IPoint {\r\n public x: number;\r\n public y: number;\r\n\r\n constructor(x?: number, y?: number) {\r\n this.x = x || 0;\r\n this.y = y || 0;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n export class Rect implements IRect {\r\n // Fields\r\n public left: number;\r\n public top: number;\r\n public width: number;\r\n public height: number;\r\n\r\n // Constructor\r\n constructor(left?: number, top?: number, width?: number, height?: number) {\r\n this.left = left || 0;\r\n this.top = top || 0;\r\n this.width = width || 0;\r\n this.height = height || 0;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n\r\n export enum LegendIcon {\r\n Box,\r\n Circle,\r\n Line\r\n }\r\n\r\n export enum LegendPosition {\r\n Top,\r\n Bottom,\r\n Right,\r\n Left,\r\n None,\r\n TopCenter,\r\n BottomCenter,\r\n RightCenter,\r\n LeftCenter, \r\n }\r\n\r\n export interface LegendPosition2D {\r\n textPosition?: Point;\r\n glyphPosition?: Point;\r\n }\r\n\r\n export interface LegendDataPoint extends SelectableDataPoint, LegendPosition2D {\r\n label: string;\r\n color: string;\r\n icon: LegendIcon;\r\n category?: string;\r\n measure?: any;\r\n iconOnlyOnLabel?: boolean;\r\n tooltip?: string;\r\n layerNumber?: number;\r\n }\r\n\r\n export interface LegendData {\r\n title?: string;\r\n dataPoints: LegendDataPoint[];\r\n grouped?: boolean;\r\n labelColor?: string;\r\n fontSize?: number;\r\n }\r\n\r\n export const legendProps = {\r\n show: 'show',\r\n position: 'position',\r\n titleText: 'titleText',\r\n showTitle: 'showTitle',\r\n labelColor: 'labelColor',\r\n fontSize: 'fontSize',\r\n };\r\n\r\n export function createLegend(legendParentElement: JQuery,\r\n interactive: boolean,\r\n interactivityService: IInteractivityService,\r\n isScrollable: boolean = false,\r\n legendPosition: LegendPosition = LegendPosition.Top): ILegend {\r\n if (interactive) return new CartesianChartInteractiveLegend(legendParentElement);\r\n else return new SVGLegend(legendParentElement, legendPosition, interactivityService, isScrollable);\r\n }\r\n\r\n export interface ILegend {\r\n getMargins(): IViewport;\r\n\r\n isVisible(): boolean;\r\n changeOrientation(orientation: LegendPosition): void;\r\n getOrientation(): LegendPosition;\r\n drawLegend(data: LegendData, viewport: IViewport);\r\n /**\r\n * Reset the legend by clearing it\r\n */\r\n reset(): void;\r\n }\r\n\r\n export module Legend {\r\n export function isLeft(orientation: LegendPosition): boolean {\r\n switch (orientation) {\r\n case LegendPosition.Left:\r\n case LegendPosition.LeftCenter:\r\n return true;\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n export function isTop(orientation: LegendPosition): boolean {\r\n switch (orientation) {\r\n case LegendPosition.Top:\r\n case LegendPosition.TopCenter:\r\n return true;\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n export function positionChartArea(chartArea: D3.Selection, legend: ILegend): void {\r\n let legendMargins = legend.getMargins();\r\n let legendOrientation = legend.getOrientation();\r\n chartArea.style({\r\n 'margin-left': Legend.isLeft(legendOrientation) ? legendMargins.width + 'px' : null,\r\n 'margin-top': Legend.isTop(legendOrientation) ? legendMargins.height + 'px' : null,\r\n });\r\n }\r\n }\r\n\r\n interface TitleLayout {\r\n x: number;\r\n y: number;\r\n text: string;\r\n width: number;\r\n height: number;\r\n }\r\n\r\n const enum NavigationArrowType {\r\n Increase,\r\n Decrease\r\n }\r\n\r\n interface NavigationArrow {\r\n x: number;\r\n y: number;\r\n path: string;\r\n rotateTransform: string;\r\n type: NavigationArrowType;\r\n }\r\n\r\n interface LegendLayout {\r\n numberOfItems: number;\r\n title: TitleLayout;\r\n navigationArrows: NavigationArrow[];\r\n }\r\n \r\n interface LegendItem {\r\n dataPoint: LegendDataPoint;\r\n textProperties: TextProperties;\r\n width: number;\r\n desiredWidth: number;\r\n desiredOverMaxWidth: boolean;\r\n }\r\n\r\n export class SVGLegend implements ILegend {\r\n private orientation: LegendPosition;\r\n private viewport: IViewport;\r\n private parentViewport: IViewport;\r\n private svg: D3.Selection;\r\n private group: D3.Selection;\r\n private clearCatcher: D3.Selection;\r\n private element: JQuery;\r\n private interactivityService: IInteractivityService;\r\n private legendDataStartIndex = 0;\r\n private arrowPosWindow = 1;\r\n private data: LegendData;\r\n private isScrollable: boolean;\r\n\r\n private lastCalculatedWidth = 0;\r\n private visibleLegendWidth = 0;\r\n private visibleLegendHeight = 0;\r\n private legendFontSizeMarginDifference = 0;\r\n private legendFontSizeMarginValue = 0;\r\n\r\n public static DefaultFontSizeInPt = 8;\r\n private static LegendIconRadius = 5;\r\n private static LegendIconRadiusFactor = 5;\r\n private static MaxTextLength = 60;\r\n private static MaxTitleLength = 80;\r\n private static TextAndIconPadding = 5;\r\n private static TitlePadding = 15;\r\n private static LegendEdgeMariginWidth = 10;\r\n private static LegendMaxWidthFactor = 0.3;\r\n private static TopLegendHeight = 24;\r\n private static DefaultTextMargin = PixelConverter.fromPointToPixel(SVGLegend.DefaultFontSizeInPt);\r\n private static DefaultMaxLegendFactor = SVGLegend.MaxTitleLength / SVGLegend.DefaultTextMargin;\r\n private static LegendIconYRatio = 0.52;\r\n \r\n // Navigation Arrow constants\r\n private static LegendArrowOffset = 10;\r\n private static LegendArrowHeight = 15;\r\n private static LegendArrowWidth = 7.5;\r\n\r\n private static DefaultFontFamily = 'wf_segoe-ui_normal';\r\n private static DefaultTitleFontFamily = 'wf_segoe-ui_Semibold';\r\n\r\n private static LegendItem: ClassAndSelector = createClassAndSelector('legendItem');\r\n private static LegendText: ClassAndSelector = createClassAndSelector('legendText');\r\n private static LegendIcon: ClassAndSelector = createClassAndSelector('legendIcon');\r\n private static LegendTitle: ClassAndSelector = createClassAndSelector('legendTitle');\r\n private static NavigationArrow: ClassAndSelector = createClassAndSelector('navArrow');\r\n\r\n constructor(\r\n element: JQuery,\r\n legendPosition: LegendPosition,\r\n interactivityService: IInteractivityService,\r\n isScrollable: boolean) {\r\n\r\n this.svg = d3.select(element.get(0)).append('svg').style('position', 'absolute');\r\n this.svg.style('display', 'inherit');\r\n this.svg.classed('legend', true);\r\n if (interactivityService)\r\n this.clearCatcher = appendClearCatcher(this.svg);\r\n this.group = this.svg.append('g').attr('id', 'legendGroup');\r\n this.interactivityService = interactivityService;\r\n this.isScrollable = isScrollable;\r\n this.element = element;\r\n this.changeOrientation(legendPosition);\r\n this.parentViewport = { height: 0, width: 0 };\r\n this.calculateViewport();\r\n this.updateLayout();\r\n }\r\n\r\n private updateLayout() {\r\n let legendViewport = this.viewport;\r\n let orientation = this.orientation;\r\n this.svg.attr({\r\n 'height': legendViewport.height || (orientation === LegendPosition.None ? 0 : this.parentViewport.height),\r\n 'width': legendViewport.width || (orientation === LegendPosition.None ? 0 : this.parentViewport.width)\r\n });\r\n\r\n let isRight = orientation === LegendPosition.Right || orientation === LegendPosition.RightCenter;\r\n let isBottom = orientation === LegendPosition.Bottom || orientation === LegendPosition.BottomCenter;\r\n this.svg.style({\r\n 'margin-left': isRight ? (this.parentViewport.width - legendViewport.width) + 'px' : null,\r\n 'margin-top': isBottom ? (this.parentViewport.height - legendViewport.height) + 'px' : null,\r\n });\r\n }\r\n\r\n private calculateViewport(): void {\r\n switch (this.orientation) {\r\n case LegendPosition.Top:\r\n case LegendPosition.Bottom:\r\n case LegendPosition.TopCenter:\r\n case LegendPosition.BottomCenter:\r\n let pixelHeight = PixelConverter.fromPointToPixel(this.data && this.data.fontSize ? this.data.fontSize : SVGLegend.DefaultFontSizeInPt);\r\n let fontHeightSize = SVGLegend.TopLegendHeight + (pixelHeight - SVGLegend.DefaultFontSizeInPt);\r\n this.viewport = { height: fontHeightSize, width: 0 };\r\n return;\r\n case LegendPosition.Right:\r\n case LegendPosition.Left:\r\n case LegendPosition.RightCenter:\r\n case LegendPosition.LeftCenter:\r\n let width = this.lastCalculatedWidth ? this.lastCalculatedWidth : this.parentViewport.width * SVGLegend.LegendMaxWidthFactor;\r\n this.viewport = { height: 0, width: width };\r\n return;\r\n\r\n case LegendPosition.None:\r\n this.viewport = { height: 0, width: 0 };\r\n }\r\n }\r\n\r\n public getMargins(): IViewport {\r\n return this.viewport;\r\n }\r\n\r\n public isVisible(): boolean {\r\n return this.orientation !== LegendPosition.None;\r\n }\r\n\r\n public changeOrientation(orientation: LegendPosition): void {\r\n if (orientation) {\r\n this.orientation = orientation;\r\n } else {\r\n this.orientation = LegendPosition.Top;\r\n }\r\n this.svg.attr('orientation', orientation);\r\n }\r\n\r\n public getOrientation(): LegendPosition {\r\n return this.orientation;\r\n }\r\n\r\n public drawLegend(data: LegendData, viewport: IViewport): void {\r\n // clone because we modify legend item label with ellipsis if it is truncated\r\n let clonedData = Prototype.inherit(data);\r\n let newDataPoints: LegendDataPoint[] = [];\r\n for (let dp of data.dataPoints) {\r\n newDataPoints.push(Prototype.inherit(dp));\r\n }\r\n clonedData.dataPoints = newDataPoints;\r\n\r\n this.setTooltipToLegendItems(clonedData);\r\n this.drawLegendInternal(clonedData, viewport, true /* perform auto width */);\r\n }\r\n\r\n public drawLegendInternal(data: LegendData, viewport: IViewport, autoWidth: boolean): void {\r\n this.parentViewport = viewport;\r\n this.data = data;\r\n\r\n if (this.interactivityService)\r\n this.interactivityService.applySelectionStateToData(data.dataPoints);\r\n\r\n if (data.dataPoints.length === 0) {\r\n this.changeOrientation(LegendPosition.None);\r\n }\r\n\r\n if (this.getOrientation() === LegendPosition.None) {\r\n data.dataPoints = [];\r\n }\r\n\r\n // Adding back the workaround for Legend Left/Right position for Map\r\n let mapControl = this.element.children(\".mapControl\");\r\n if (mapControl.length > 0 && !this.isTopOrBottom(this.orientation)) {\r\n mapControl.css(\"display\", \"inline-block\");\r\n }\r\n\r\n this.calculateViewport();\r\n\r\n let layout = this.calculateLayout(data, autoWidth);\r\n let titleLayout = layout.title;\r\n let titleData = titleLayout ? [titleLayout] : [];\r\n let hasSelection = this.interactivityService && powerbi.visuals.dataHasSelection(data.dataPoints);\r\n\r\n let group = this.group;\r\n\r\n //transform the wrapping group if position is centered\r\n if (this.isCentered(this.orientation)) {\r\n let centerOffset = 0;\r\n if (this.isTopOrBottom(this.orientation)) {\r\n centerOffset = Math.max(0, (this.parentViewport.width - this.visibleLegendWidth) / 2);\r\n group.attr('transform', SVGUtil.translate(centerOffset, 0));\r\n }\r\n else {\r\n centerOffset = Math.max((this.parentViewport.height - this.visibleLegendHeight) / 2);\r\n group.attr('transform', SVGUtil.translate(0, centerOffset));\r\n }\r\n }\r\n else {\r\n group.attr('transform', null);\r\n }\r\n\r\n let legendTitle = group\r\n .selectAll(SVGLegend.LegendTitle.selector)\r\n .data(titleData);\r\n\r\n legendTitle.enter()\r\n .append('text')\r\n .classed(SVGLegend.LegendTitle.class, true);\r\n\r\n legendTitle\r\n .style({\r\n 'fill': data.labelColor,\r\n 'font-size': PixelConverter.fromPoint(data.fontSize),\r\n 'font-family': SVGLegend.DefaultTitleFontFamily\r\n })\r\n .text((d: TitleLayout) => d.text)\r\n .attr({\r\n 'x': (d: TitleLayout) => d.x,\r\n 'y': (d: TitleLayout) => d.y\r\n })\r\n .append('title').text(data.title);\r\n\r\n legendTitle.exit().remove();\r\n\r\n let virtualizedDataPoints = data.dataPoints.slice(this.legendDataStartIndex, this.legendDataStartIndex + layout.numberOfItems);\r\n\r\n let iconRadius = TextMeasurementService.estimateSvgTextHeight(SVGLegend.getTextProperties(false, '', this.data.fontSize)) / SVGLegend.LegendIconRadiusFactor;\r\n iconRadius = (this.legendFontSizeMarginValue > SVGLegend.DefaultTextMargin) && iconRadius > SVGLegend.LegendIconRadius\r\n ? iconRadius :\r\n SVGLegend.LegendIconRadius;\r\n\r\n let legendItems = group\r\n .selectAll(SVGLegend.LegendItem.selector)\r\n .data(virtualizedDataPoints, (d: LegendDataPoint) => d.identity.getKey() + (d.layerNumber != null ? d.layerNumber : ''));\r\n\r\n let itemsEnter = legendItems.enter()\r\n .append('g')\r\n .classed(SVGLegend.LegendItem.class, true);\r\n\r\n itemsEnter\r\n .append('circle')\r\n .classed(SVGLegend.LegendIcon.class, true);\r\n\r\n itemsEnter\r\n .append('text')\r\n .classed(SVGLegend.LegendText.class, true);\r\n\r\n itemsEnter\r\n .append('title')\r\n .text((d: LegendDataPoint) => d.tooltip);\r\n\r\n itemsEnter\r\n .style({\r\n 'font-family': SVGLegend.DefaultFontFamily\r\n });\r\n\r\n legendItems\r\n .select(SVGLegend.LegendIcon.selector)\r\n .attr({\r\n 'cx': (d: LegendDataPoint, i) => d.glyphPosition.x,\r\n 'cy': (d: LegendDataPoint) => d.glyphPosition.y,\r\n 'r': iconRadius,\r\n })\r\n .style({\r\n 'fill': (d: LegendDataPoint) => {\r\n if (hasSelection && !d.selected)\r\n return LegendBehavior.dimmedLegendColor;\r\n else\r\n return d.color;\r\n }\r\n });\r\n\r\n legendItems\r\n .select('title')\r\n .text((d: LegendDataPoint) => d.tooltip);\r\n\r\n legendItems\r\n .select(SVGLegend.LegendText.selector)\r\n .attr({\r\n 'x': (d: LegendDataPoint) => d.textPosition.x,\r\n 'y': (d: LegendDataPoint) => d.textPosition.y,\r\n })\r\n .text((d: LegendDataPoint) => d.label)\r\n .style({\r\n 'fill': data.labelColor,\r\n 'font-size': PixelConverter.fromPoint(data.fontSize)\r\n });\r\n\r\n if (this.interactivityService) {\r\n let iconsSelection = legendItems.select(SVGLegend.LegendIcon.selector);\r\n let behaviorOptions: LegendBehaviorOptions = {\r\n legendItems: legendItems,\r\n legendIcons: iconsSelection,\r\n clearCatcher: this.clearCatcher,\r\n };\r\n\r\n this.interactivityService.bind(data.dataPoints, new LegendBehavior(), behaviorOptions, { isLegend: true });\r\n }\r\n\r\n legendItems.exit().remove();\r\n\r\n this.drawNavigationArrows(layout.navigationArrows);\r\n\r\n this.updateLayout();\r\n }\r\n\r\n private normalizePosition(points: any[]): void {\r\n if (this.legendDataStartIndex >= points.length) {\r\n this.legendDataStartIndex = points.length - 1;\r\n }\r\n\r\n if (this.legendDataStartIndex < 0) {\r\n this.legendDataStartIndex = 0;\r\n }\r\n }\r\n\r\n private calculateTitleLayout(title: string): TitleLayout {\r\n let width = 0;\r\n let hasTitle = !_.isEmpty(title);\r\n\r\n if (hasTitle) {\r\n let isHorizontal = this.isTopOrBottom(this.orientation);\r\n let maxMeasureLength: number;\r\n\r\n if (isHorizontal) {\r\n let fontSizeMargin = this.legendFontSizeMarginValue > SVGLegend.DefaultTextMargin ? SVGLegend.TextAndIconPadding + this.legendFontSizeMarginDifference : SVGLegend.TextAndIconPadding;\r\n let fixedHorizontalIconShift = SVGLegend.TextAndIconPadding + SVGLegend.LegendIconRadius;\r\n let fixedHorizontalTextShift = SVGLegend.LegendIconRadius + fontSizeMargin + fixedHorizontalIconShift;\r\n // TODO This can be negative for narrow viewports. May need to rework this logic.\r\n maxMeasureLength = this.parentViewport.width * SVGLegend.LegendMaxWidthFactor - fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth;\r\n }\r\n else {\r\n maxMeasureLength = this.legendFontSizeMarginValue < SVGLegend.DefaultTextMargin ? SVGLegend.MaxTitleLength :\r\n SVGLegend.MaxTitleLength + (SVGLegend.DefaultMaxLegendFactor * this.legendFontSizeMarginDifference);\r\n }\r\n\r\n let textProperties = SVGLegend.getTextProperties(true, title, this.data.fontSize);\r\n let text = title;\r\n width = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n\r\n if (width > maxMeasureLength) {\r\n text = TextMeasurementService.getTailoredTextOrDefault(textProperties, maxMeasureLength);\r\n textProperties.text = text;\r\n \r\n // Remeasure the text since its measurement may be different than the max (ex. when the max is negative, the text will be ellipsis, and not have a negative width)\r\n width = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n };\r\n\r\n if (isHorizontal)\r\n width += SVGLegend.TitlePadding;\r\n else\r\n text = TextMeasurementService.getTailoredTextOrDefault(textProperties, this.viewport.width);\r\n\r\n return {\r\n x: 0,\r\n y: 0,\r\n text: text,\r\n width: width,\r\n height: TextMeasurementService.estimateSvgTextHeight(textProperties)\r\n };\r\n }\r\n return null;\r\n\r\n }\r\n /** Performs layout offline for optimal perfomance */\r\n private calculateLayout(data: LegendData, autoWidth: boolean): LegendLayout {\r\n let dataPoints = data.dataPoints;\r\n if (data.dataPoints.length === 0) {\r\n return {\r\n startIndex: null,\r\n numberOfItems: 0,\r\n title: null,\r\n navigationArrows: []\r\n };\r\n }\r\n\r\n this.legendFontSizeMarginValue = PixelConverter.fromPointToPixel(this.data && this.data.fontSize !== undefined ? this.data.fontSize : SVGLegend.DefaultFontSizeInPt);\r\n this.legendFontSizeMarginDifference = (this.legendFontSizeMarginValue - SVGLegend.DefaultTextMargin);\r\n\r\n this.normalizePosition(dataPoints);\r\n if (this.legendDataStartIndex < dataPoints.length) {\r\n dataPoints = dataPoints.slice(this.legendDataStartIndex);\r\n }\r\n\r\n let title = this.calculateTitleLayout(data.title);\r\n\r\n let navArrows: NavigationArrow[];\r\n let numberOfItems: number;\r\n if (this.isTopOrBottom(this.orientation)) {\r\n navArrows = this.isScrollable ? this.calculateHorizontalNavigationArrowsLayout(title) : [];\r\n numberOfItems = this.calculateHorizontalLayout(dataPoints, title, navArrows);\r\n }\r\n else {\r\n navArrows = this.isScrollable ? this.calculateVerticalNavigationArrowsLayout(title) : [];\r\n numberOfItems = this.calculateVerticalLayout(dataPoints, title, navArrows, autoWidth);\r\n }\r\n return {\r\n numberOfItems: numberOfItems,\r\n title: title,\r\n navigationArrows: navArrows\r\n };\r\n }\r\n\r\n private updateNavigationArrowLayout(navigationArrows: NavigationArrow[], remainingDataLength: number, visibleDataLength: number): void {\r\n if (this.legendDataStartIndex === 0) {\r\n navigationArrows.shift();\r\n }\r\n\r\n let lastWindow = this.arrowPosWindow;\r\n this.arrowPosWindow = visibleDataLength;\r\n\r\n if (navigationArrows && navigationArrows.length > 0 && this.arrowPosWindow === remainingDataLength) {\r\n this.arrowPosWindow = lastWindow;\r\n navigationArrows.length = navigationArrows.length - 1;\r\n }\r\n }\r\n\r\n private calculateHorizontalNavigationArrowsLayout(title: TitleLayout): NavigationArrow[] {\r\n let height = SVGLegend.LegendArrowHeight;\r\n let width = SVGLegend.LegendArrowWidth;\r\n let translateY = (this.viewport.height / 2) - (height / 2);\r\n\r\n let data: NavigationArrow[] = [];\r\n let rightShift = title ? title.x + title.width : 0;\r\n let arrowLeft = SVGUtil.createArrow(width, height, 180 /*angle*/);\r\n let arrowRight = SVGUtil.createArrow(width, height, 0 /*angle*/);\r\n\r\n data.push({\r\n x: rightShift,\r\n y: translateY,\r\n path: arrowLeft.path,\r\n rotateTransform: arrowLeft.transform,\r\n type: NavigationArrowType.Decrease\r\n });\r\n\r\n data.push({\r\n x: this.parentViewport.width - width,\r\n y: translateY,\r\n path: arrowRight.path,\r\n rotateTransform: arrowRight.transform,\r\n type: NavigationArrowType.Increase\r\n });\r\n\r\n return data;\r\n }\r\n\r\n private calculateVerticalNavigationArrowsLayout(title: TitleLayout): NavigationArrow[] {\r\n let height = SVGLegend.LegendArrowHeight;\r\n let width = SVGLegend.LegendArrowWidth;\r\n\r\n let verticalCenter = this.viewport.height / 2;\r\n let data: NavigationArrow[] = [];\r\n let rightShift = verticalCenter + height / 2;\r\n let arrowTop = SVGUtil.createArrow(width, height, 270 /*angle*/);\r\n let arrowBottom = SVGUtil.createArrow(width, height, 90 /*angle*/);\r\n let titleHeight = title ? title.height : 0;\r\n\r\n data.push({\r\n x: rightShift,\r\n y: width + titleHeight,\r\n path: arrowTop.path,\r\n rotateTransform: arrowTop.transform,\r\n type: NavigationArrowType.Decrease\r\n });\r\n\r\n data.push({\r\n x: rightShift,\r\n y: this.parentViewport.height - height,\r\n path: arrowBottom.path,\r\n rotateTransform: arrowBottom.transform,\r\n type: NavigationArrowType.Increase\r\n });\r\n\r\n return data;\r\n }\r\n \r\n /**\r\n * Calculates the widths for each horizontal legend item.\r\n */\r\n private static calculateHorizontalLegendItemsWidths(dataPoints: LegendDataPoint[], availableWidth: number, iconPadding: number, fontSize: number): LegendItem[] {\r\n\r\n let dataPointsLength = dataPoints.length;\r\n\r\n // Set the maximum amount of space available to each item. They can use less, but can't go over this number.\r\n let maxItemWidth = dataPointsLength > 0 ? availableWidth / dataPointsLength | 0 : 0;\r\n let maxItemTextWidth = maxItemWidth - iconPadding;\r\n\r\n // Makes sure the amount of space available to each item is at least SVGLegend.MaxTextLength wide.\r\n // If you had many items and/or a narrow amount of available width, the availableTextWidthPerItem would be small, essentially making everything ellipsis.\r\n // This prevents that from happening by giving each item at least SVGLegend.MaxTextLength of space.\r\n if (maxItemTextWidth < SVGLegend.MaxTextLength) {\r\n maxItemTextWidth = SVGLegend.MaxTextLength;\r\n maxItemWidth = maxItemTextWidth + iconPadding;\r\n }\r\n\r\n // Make sure the availableWidthPerItem is less than the availableWidth. This lets the long text properly add ellipsis when we're displaying one item at a time.\r\n if (maxItemWidth > availableWidth) {\r\n maxItemWidth = availableWidth;\r\n maxItemTextWidth = maxItemWidth - iconPadding;\r\n }\r\n\r\n let occupiedWidth = 0;\r\n let legendItems: LegendItem[] = [];\r\n\r\n // Add legend items until we can't fit any more (the last one doesn't fit) or we've added all of them\r\n for (let dataPoint of dataPoints) {\r\n\r\n let textProperties = SVGLegend.getTextProperties(false, dataPoint.label, fontSize);\r\n let itemTextWidth = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n let desiredWidth = itemTextWidth + iconPadding;\r\n let overMaxWidth = desiredWidth > maxItemWidth;\r\n let actualWidth = overMaxWidth ? maxItemWidth : desiredWidth;\r\n occupiedWidth += actualWidth;\r\n\r\n if (occupiedWidth >= availableWidth) {\r\n \r\n // Always add at least 1 element\r\n if (legendItems.length === 0) {\r\n\r\n legendItems.push({\r\n dataPoint: dataPoint,\r\n textProperties: textProperties,\r\n desiredWidth: desiredWidth,\r\n desiredOverMaxWidth: true,\r\n width: desiredWidth\r\n });\r\n \r\n // Set the width to the amount of space we actually have\r\n occupiedWidth = availableWidth;\r\n } else {\r\n // Subtract the width from what was just added since it won't fit\r\n occupiedWidth -= actualWidth;\r\n }\r\n break;\r\n }\r\n\r\n legendItems.push({\r\n dataPoint: dataPoint,\r\n textProperties: textProperties,\r\n desiredWidth: desiredWidth,\r\n desiredOverMaxWidth: overMaxWidth,\r\n width: desiredWidth\r\n });\r\n }\r\n\r\n // If there are items at max width, evenly redistribute the extra space to them\r\n let itemsOverMax = _.filter(legendItems, (li) => li.desiredOverMaxWidth);\r\n let numItemsOverMax = itemsOverMax.length;\r\n\r\n if (numItemsOverMax > 0) {\r\n let extraWidth = availableWidth - occupiedWidth;\r\n\r\n for (let item of itemsOverMax) {\r\n // Divvy up the extra space and add it to the max\r\n // We need to do this calculation in every loop since the remainingWidth may not be changed by the same amount every time\r\n let extraWidthPerItem = extraWidth / numItemsOverMax;\r\n let newMaxItemWidth = maxItemWidth + extraWidthPerItem;\r\n\r\n let usedExtraWidth: number;\r\n if (item.desiredWidth <= newMaxItemWidth) {\r\n // If the item doesn't need all the extra space, it's not at max anymore\r\n item.desiredOverMaxWidth = false;\r\n usedExtraWidth = item.desiredWidth - maxItemWidth;\r\n } else {\r\n // Otherwise the item is taking up all the extra space so update the actual width to indicate that\r\n item.width = newMaxItemWidth;\r\n usedExtraWidth = newMaxItemWidth - maxItemWidth;\r\n }\r\n \r\n extraWidth -= usedExtraWidth;\r\n numItemsOverMax--;\r\n }\r\n }\r\n\r\n return legendItems;\r\n }\r\n\r\n private calculateHorizontalLayout(dataPoints: LegendDataPoint[], title: TitleLayout, navigationArrows: NavigationArrow[]): number {\r\n debug.assertValue(navigationArrows, 'navigationArrows');\r\n // calculate the text shift\r\n let HorizontalTextShift = 4 + SVGLegend.LegendIconRadius;\r\n // check if we need more space for the margin, or use the default text padding\r\n let fontSizeBiggerThanDefault = this.legendFontSizeMarginDifference > 0;\r\n let fontSizeMargin = fontSizeBiggerThanDefault ? SVGLegend.TextAndIconPadding + this.legendFontSizeMarginDifference : SVGLegend.TextAndIconPadding;\r\n let fixedTextShift = (fontSizeMargin / (SVGLegend.LegendIconRadiusFactor / 2)) + HorizontalTextShift;\r\n let occupiedWidth = 0;\r\n // calculate the size of the space for both sides of the radius\r\n let iconTotalItemPadding = SVGLegend.LegendIconRadius * 2 + fontSizeMargin * 1.5;\r\n let numberOfItems: number = dataPoints.length;\r\n // get the Y coordinate which is the middle of the container + the middle of the text height - the delta of the text \r\n let defaultTextProperties = SVGLegend.getTextProperties(false, '', this.data.fontSize);\r\n let verticalCenter = this.viewport.height / 2;\r\n let textYCoordinate = verticalCenter + TextMeasurementService.estimateSvgTextHeight(defaultTextProperties) / 2\r\n - TextMeasurementService.estimateSvgTextBaselineDelta(defaultTextProperties);\r\n\r\n if (title) {\r\n occupiedWidth += title.width;\r\n // get the Y coordinate which is the middle of the container + the middle of the text height - the delta of the text \r\n title.y = verticalCenter + title.height / 2 - TextMeasurementService.estimateSvgTextBaselineDelta(SVGLegend.getTextProperties(true, title.text, this.data.fontSize));\r\n }\r\n\r\n // if an arrow should be added, we add space for it\r\n if (this.legendDataStartIndex > 0) {\r\n occupiedWidth += SVGLegend.LegendArrowOffset;\r\n }\r\n\r\n // Calculate the width for each of the legend items\r\n let dataPointsLength = dataPoints.length;\r\n let availableWidth = this.parentViewport.width - occupiedWidth;\r\n let legendItems = SVGLegend.calculateHorizontalLegendItemsWidths(dataPoints, availableWidth, iconTotalItemPadding, this.data.fontSize);\r\n numberOfItems = legendItems.length;\r\n\r\n // If we can't show all the legend items, subtract the \"next\" arrow space from the available space and re-run the width calculations \r\n if (numberOfItems !== dataPointsLength) {\r\n availableWidth -= SVGLegend.LegendArrowOffset;\r\n legendItems = SVGLegend.calculateHorizontalLegendItemsWidths(dataPoints, availableWidth, iconTotalItemPadding, this.data.fontSize);\r\n numberOfItems = legendItems.length;\r\n }\r\n\r\n for (let legendItem of legendItems) {\r\n\r\n let dataPoint = legendItem.dataPoint;\r\n\r\n dataPoint.glyphPosition = {\r\n // the space taken so far + the radius + the margin / radiusFactor to prevent huge spaces\r\n x: occupiedWidth + SVGLegend.LegendIconRadius + (this.legendFontSizeMarginDifference / SVGLegend.LegendIconRadiusFactor),\r\n // The middle of the container but a bit lower due to text not being in the middle (qP for example making middle between q and P)\r\n y: (this.viewport.height * SVGLegend.LegendIconYRatio),\r\n };\r\n\r\n dataPoint.textPosition = {\r\n x: occupiedWidth + fixedTextShift,\r\n y: textYCoordinate,\r\n };\r\n\r\n // If we're over the max width, process it so it fits\r\n if (legendItem.desiredOverMaxWidth) {\r\n let textWidth = legendItem.width - iconTotalItemPadding;\r\n let text = TextMeasurementService.getTailoredTextOrDefault(legendItem.textProperties, textWidth);\r\n dataPoint.label = text;\r\n }\r\n\r\n occupiedWidth += legendItem.width;\r\n }\r\n\r\n this.visibleLegendWidth = occupiedWidth;\r\n this.updateNavigationArrowLayout(navigationArrows, dataPointsLength, numberOfItems);\r\n\r\n return numberOfItems;\r\n }\r\n\r\n private calculateVerticalLayout(\r\n dataPoints: LegendDataPoint[],\r\n title: TitleLayout,\r\n navigationArrows: NavigationArrow[],\r\n autoWidth: boolean): number {\r\n // check if we need more space for the margin, or use the default text padding\r\n let fontSizeBiggerThenDefault = this.legendFontSizeMarginDifference > 0;\r\n let fontFactor = fontSizeBiggerThenDefault ? this.legendFontSizeMarginDifference : 0;\r\n // calculate the size needed after font size change\r\n let verticalLegendHeight = 20 + fontFactor;\r\n let spaceNeededByTitle = 15 + fontFactor;\r\n let extraShiftForTextAlignmentToIcon = 4 + fontFactor;\r\n let totalSpaceOccupiedThusFar = verticalLegendHeight;\r\n // the default space for text and icon radius + the margin after the font size change\r\n let fixedHorizontalIconShift = SVGLegend.TextAndIconPadding + SVGLegend.LegendIconRadius + (this.legendFontSizeMarginDifference / SVGLegend.LegendIconRadiusFactor);\r\n let fixedHorizontalTextShift = fixedHorizontalIconShift * 2;\r\n // check how much space is needed\r\n let maxHorizontalSpaceAvaliable = autoWidth\r\n ? this.parentViewport.width * SVGLegend.LegendMaxWidthFactor\r\n - fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth\r\n : this.lastCalculatedWidth\r\n - fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth;\r\n let numberOfItems: number = dataPoints.length;\r\n\r\n let maxHorizontalSpaceUsed = 0;\r\n let parentHeight = this.parentViewport.height;\r\n\r\n if (title) {\r\n totalSpaceOccupiedThusFar += spaceNeededByTitle;\r\n title.x = SVGLegend.TextAndIconPadding;\r\n title.y = spaceNeededByTitle;\r\n maxHorizontalSpaceUsed = title.width || 0;\r\n }\r\n // if an arrow should be added, we add space for it\r\n if (this.legendDataStartIndex > 0)\r\n totalSpaceOccupiedThusFar += SVGLegend.LegendArrowOffset;\r\n\r\n let dataPointsLength = dataPoints.length;\r\n for (let i = 0; i < dataPointsLength; i++) {\r\n let dp = dataPoints[i];\r\n let textProperties = SVGLegend.getTextProperties(false, dp.label, this.data.fontSize);\r\n\r\n dp.glyphPosition = {\r\n x: fixedHorizontalIconShift,\r\n y: (totalSpaceOccupiedThusFar + extraShiftForTextAlignmentToIcon) - TextMeasurementService.estimateSvgTextBaselineDelta(textProperties)\r\n };\r\n\r\n dp.textPosition = {\r\n x: fixedHorizontalTextShift,\r\n y: totalSpaceOccupiedThusFar + extraShiftForTextAlignmentToIcon\r\n };\r\n\r\n // TODO: [PERF] Get rid of this extra measurement, and modify\r\n // getTailoredTextToReturnWidth + Text\r\n let width = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n if (width > maxHorizontalSpaceUsed) {\r\n maxHorizontalSpaceUsed = width;\r\n }\r\n\r\n if (width > maxHorizontalSpaceAvaliable) {\r\n let text = TextMeasurementService.getTailoredTextOrDefault(\r\n textProperties,\r\n maxHorizontalSpaceAvaliable);\r\n dp.label = text;\r\n }\r\n\r\n totalSpaceOccupiedThusFar += verticalLegendHeight;\r\n\r\n if (totalSpaceOccupiedThusFar > parentHeight) {\r\n numberOfItems = i;\r\n break;\r\n }\r\n }\r\n\r\n if (autoWidth) {\r\n if (maxHorizontalSpaceUsed < maxHorizontalSpaceAvaliable) {\r\n this.lastCalculatedWidth = this.viewport.width = Math.ceil(maxHorizontalSpaceUsed + fixedHorizontalTextShift + SVGLegend.LegendEdgeMariginWidth);\r\n } else {\r\n this.lastCalculatedWidth = this.viewport.width = Math.ceil(this.parentViewport.width * SVGLegend.LegendMaxWidthFactor);\r\n }\r\n }\r\n else {\r\n this.viewport.width = this.lastCalculatedWidth;\r\n }\r\n\r\n this.visibleLegendHeight = totalSpaceOccupiedThusFar;\r\n\r\n navigationArrows.forEach(d => d.x = this.lastCalculatedWidth / 2);\r\n this.updateNavigationArrowLayout(navigationArrows, dataPointsLength, numberOfItems);\r\n\r\n return numberOfItems;\r\n }\r\n\r\n private drawNavigationArrows(layout: NavigationArrow[]) {\r\n let arrows = this.group.selectAll(SVGLegend.NavigationArrow.selector)\r\n .data(layout);\r\n\r\n arrows\r\n .enter()\r\n .append('g')\r\n .on('click', (d: NavigationArrow) => {\r\n let pos = this.legendDataStartIndex;\r\n this.legendDataStartIndex = d.type === NavigationArrowType.Increase\r\n ? pos + this.arrowPosWindow : pos - this.arrowPosWindow;\r\n this.drawLegendInternal(this.data, this.parentViewport, false);\r\n })\r\n .classed(SVGLegend.NavigationArrow.class, true)\r\n .append('path');\r\n\r\n arrows\r\n .attr('transform', (d: NavigationArrow) => SVGUtil.translate(d.x, d.y))\r\n .select('path')\r\n .attr({\r\n 'd': (d: NavigationArrow) => d.path,\r\n 'transform': (d: NavigationArrow) => d.rotateTransform\r\n });\r\n\r\n arrows.exit().remove();\r\n }\r\n\r\n private isTopOrBottom(orientation: LegendPosition) {\r\n switch (orientation) {\r\n case LegendPosition.Top:\r\n case LegendPosition.Bottom:\r\n case LegendPosition.BottomCenter:\r\n case LegendPosition.TopCenter:\r\n return true;\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n private isCentered(orientation: LegendPosition): boolean {\r\n switch (orientation) {\r\n case LegendPosition.BottomCenter:\r\n case LegendPosition.LeftCenter:\r\n case LegendPosition.RightCenter:\r\n case LegendPosition.TopCenter:\r\n return true;\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n public reset(): void {\r\n // Intentionally left blank. \r\n }\r\n\r\n private static getTextProperties(isTitle: boolean, text?: string, fontSize?: number): TextProperties {\r\n return {\r\n text: text,\r\n fontFamily: isTitle ? SVGLegend.DefaultTitleFontFamily : SVGLegend.DefaultFontFamily,\r\n fontSize: PixelConverter.fromPoint(fontSize || SVGLegend.DefaultFontSizeInPt)\r\n };\r\n }\r\n\r\n private setTooltipToLegendItems(data: LegendData) {\r\n //we save the values to tooltip before cut\r\n for (let dataPoint of data.dataPoints) {\r\n dataPoint.tooltip = dataPoint.label;\r\n }\r\n }\r\n }\r\n\r\n class CartesianChartInteractiveLegend implements ILegend {\r\n private static LegendHeight = 70;\r\n private static LegendContainerClass = 'interactive-legend';\r\n private static LegendContainerSelector = '.interactive-legend';\r\n private static LegendTitleClass = 'title';\r\n private static LegendItem = 'item';\r\n private static legendPlaceSelector = '\\u25A0';\r\n private static legendIconClass = 'icon';\r\n private static legendColorCss = 'color';\r\n private static legendItemNameClass = 'itemName';\r\n private static legendItemMeasureClass = 'itemMeasure';\r\n private legendContainerParent: D3.Selection;\r\n private legendContainerDiv: D3.Selection;\r\n\r\n constructor(element: JQuery) {\r\n this.legendContainerParent = d3.select(element.get(0));\r\n }\r\n \r\n public getMargins(): IViewport {\r\n return {\r\n height: CartesianChartInteractiveLegend.LegendHeight,\r\n width: 0\r\n };\r\n }\r\n\r\n public drawLegend(legendData: LegendData) {\r\n debug.assertValue(legendData, 'legendData');\r\n let data = legendData.dataPoints;\r\n debug.assertValue(data, 'dataPoints');\r\n if (data.length < 1) return;\r\n\r\n let legendContainerDiv = this.legendContainerParent.select(CartesianChartInteractiveLegend.LegendContainerSelector);\r\n if (legendContainerDiv.empty()) {\r\n if (!data.length) return;\r\n let divToPrepend = $('<div></div>')\r\n .height(this.getMargins().height)\r\n .addClass(CartesianChartInteractiveLegend.LegendContainerClass);\r\n // Prepending, as legend should always be on topmost visual.\r\n $(this.legendContainerParent[0]).prepend(divToPrepend);\r\n legendContainerDiv = d3.select(divToPrepend.get(0));\r\n }\r\n this.legendContainerDiv = legendContainerDiv;\r\n\r\n // Construct the legend title and items.\r\n this.drawTitle(data);\r\n this.drawLegendItems(data);\r\n }\r\n\r\n public reset(): void {\r\n if (this.legendContainerDiv) {\r\n this.legendContainerDiv.remove();\r\n this.legendContainerDiv = null;\r\n }\r\n }\r\n\r\n public isVisible(): boolean {\r\n return true;\r\n }\r\n\r\n public changeOrientation(orientation: LegendPosition) {\r\n // Not supported\r\n }\r\n\r\n public getOrientation(): LegendPosition {\r\n return LegendPosition.Top;\r\n }\r\n\r\n /**\r\n * Draw the legend title\r\n */\r\n private drawTitle(data: LegendDataPoint[]): void {\r\n debug.assert(data && data.length > 0, 'data is null or empty');\r\n let titleDiv: D3.Selection = this.legendContainerDiv.selectAll('div.' + CartesianChartInteractiveLegend.LegendTitleClass);\r\n let item: D3.UpdateSelection = titleDiv.data([data[0]]);\r\n\r\n // Enter\r\n let itemEnter: D3.EnterSelection = item.enter();\r\n let titleDivEnter: D3.Selection = itemEnter.append('div').attr('class', CartesianChartInteractiveLegend.LegendTitleClass);\r\n titleDivEnter\r\n .filter((d: LegendDataPoint) => d.iconOnlyOnLabel)\r\n .append('span')\r\n .attr('class', CartesianChartInteractiveLegend.legendIconClass)\r\n .html(CartesianChartInteractiveLegend.legendPlaceSelector);\r\n titleDivEnter.append('span');\r\n\r\n // Update\r\n item.filter((d: LegendDataPoint) => d.iconOnlyOnLabel)\r\n .select('span.' + CartesianChartInteractiveLegend.legendIconClass)\r\n .style(CartesianChartInteractiveLegend.legendColorCss, (d: LegendDataPoint) => d.color);\r\n item.select('span:last-child').text((d: LegendDataPoint) => d.category);\r\n }\r\n\r\n /**\r\n * Draw the legend items\r\n */\r\n private drawLegendItems(data: LegendDataPoint[]): void {\r\n // Add Mesaures - the items of the category in the legend\r\n this.ensureLegendTableCreated();\r\n let dataPointsMatrix: LegendDataPoint[][] = CartesianChartInteractiveLegend.splitArrayToOddEven(data);\r\n let legendItemsContainer: D3.UpdateSelection = this.legendContainerDiv.select('tbody').selectAll('tr').data(dataPointsMatrix);\r\n\r\n // trs is table rows. \r\n // there are two table rows.\r\n // the order of insertion to the legend table is:\r\n // Even data points got inserted into the 1st line\r\n // Odd data points got inserted into the 2nd line\r\n // ----------------------------\r\n // | value0 | value 2 | value 4\r\n // ----------------------------\r\n // | value1 | value 3 | \r\n // ----------------------------\r\n // \r\n\r\n // Enter\r\n let legendItemsEnter: D3.EnterSelection = legendItemsContainer.enter();\r\n let rowEnter: D3.Selection = legendItemsEnter.append('tr');\r\n let cellEnter: D3.Selection = rowEnter.selectAll('td')\r\n .data((d: LegendDataPoint[]) => d, (d: LegendDataPoint) => d.label)\r\n .enter()\r\n .append('td').attr('class', CartesianChartInteractiveLegend.LegendItem);\r\n let cellSpanEnter: D3.Selection = cellEnter.append('span');\r\n cellSpanEnter.filter((d: LegendDataPoint) => !d.iconOnlyOnLabel)\r\n .append('span')\r\n .html(CartesianChartInteractiveLegend.legendPlaceSelector)\r\n .attr('class', CartesianChartInteractiveLegend.legendIconClass)\r\n .attr('white-space', 'nowrap');\r\n cellSpanEnter.append('span').attr('class', CartesianChartInteractiveLegend.legendItemNameClass);\r\n cellSpanEnter.append('span').attr('class', CartesianChartInteractiveLegend.legendItemMeasureClass);\r\n\r\n // Update\r\n let legendCells: D3.UpdateSelection = legendItemsContainer.selectAll('td').data((d: LegendDataPoint[]) => d, (d: LegendDataPoint) => d.label);\r\n legendCells.select('span.' + CartesianChartInteractiveLegend.legendItemNameClass).html((d: LegendDataPoint) => powerbi.visuals.TextUtil.removeBreakingSpaces(d.label));\r\n legendCells.select('span.' + CartesianChartInteractiveLegend.legendItemMeasureClass).html((d: LegendDataPoint) => '&nbsp;' + d.measure);\r\n legendCells.select('span.' + CartesianChartInteractiveLegend.legendIconClass).style('color', (d: LegendDataPoint) => d.color);\r\n\r\n // Exit\r\n legendCells.exit().remove();\r\n }\r\n\r\n /**\r\n * Ensure legend table is created and set horizontal pan gestures on it\r\n */\r\n private ensureLegendTableCreated(): void {\r\n if (this.legendContainerDiv.select('div table').empty()) {\r\n let legendTable: D3.Selection = this.legendContainerDiv.append('div').append('table');\r\n legendTable.style('table-layout', 'fixed').append('tbody');\r\n // Setup Pan Gestures of the legend\r\n this.setPanGestureOnLegend(legendTable);\r\n }\r\n }\r\n\r\n /**\r\n * Set Horizontal Pan gesture for the legend\r\n */\r\n private setPanGestureOnLegend(legendTable: D3.Selection): void {\r\n let viewportWidth: number = $(this.legendContainerDiv.select('div:nth-child(2)')[0]).width();\r\n let xscale: D3.Scale.LinearScale = d3.scale.linear().domain([0, viewportWidth]).range([0, viewportWidth]);\r\n let zoom: D3.Behavior.Zoom = d3.behavior.zoom()\r\n .scaleExtent([1, 1]) // disable scaling\r\n .x(xscale)\r\n .on(\"zoom\", () => {\r\n // horizontal pan is valid only in case the legend items width are bigger than the viewport width\r\n if ($(legendTable[0]).width() > viewportWidth) {\r\n let t: number[] = zoom.translate();\r\n let tx: number = t[0];\r\n let ty: number = t[1];\r\n tx = Math.min(tx, 0);\r\n tx = Math.max(tx, viewportWidth - $(legendTable[0]).width());\r\n zoom.translate([tx, ty]);\r\n legendTable.style(\"-ms-transform\", () => { /* IE 9 */\r\n return SVGUtil.translateXWithPixels(tx);\r\n });\r\n legendTable.style(\"-webkit-transform\", () => { /* Safari */\r\n return SVGUtil.translateXWithPixels(tx);\r\n });\r\n legendTable.style(\"transform\", () => {\r\n return SVGUtil.translateXWithPixels(tx);\r\n });\r\n }\r\n });\r\n if (this.legendContainerDiv) {\r\n this.legendContainerDiv.call(zoom);\r\n } else {\r\n legendTable.call(zoom);\r\n }\r\n }\r\n\r\n /**\r\n * Split legend data points array into odd and even arrays\r\n * Even array will be the legend first line and Odd array will be the 2nd legend line \r\n */\r\n private static splitArrayToOddEven(data: LegendDataPoint[]): LegendDataPoint[][] {\r\n let oddData: LegendDataPoint[] = [];\r\n let evenData: LegendDataPoint[] = [];\r\n for (let i = 0; i < data.length; ++i) {\r\n if (i % 2 === 0) {\r\n evenData.push(data[i]);\r\n }\r\n else {\r\n oddData.push(data[i]);\r\n }\r\n }\r\n return [evenData, oddData];\r\n }\r\n }\r\n\r\n export module LegendData {\r\n\r\n export var DefaultLegendLabelFillColor: string = '#666666';\r\n\r\n export function update(legendData: LegendData, legendObject: DataViewObject): void {\r\n debug.assertValue(legendData, 'legendData');\r\n debug.assertValue(legendObject, 'legendObject');\r\n\r\n if (legendObject[legendProps.show] == null) {\r\n legendObject[legendProps.show] = true;\r\n }\r\n\r\n if (legendObject[legendProps.show] === false)\r\n legendData.dataPoints = [];\r\n\r\n if (legendObject[legendProps.show] === true && legendObject[legendProps.position] == null)\r\n legendObject[legendProps.position] = legendPosition.top;\r\n\r\n if (legendObject[legendProps.fontSize] !== undefined)\r\n legendData.fontSize = <number>legendObject[legendProps.fontSize];\r\n\r\n if (legendObject[legendProps.labelColor] !== undefined) {\r\n\r\n let fillColor = <Fill>legendObject[legendProps.labelColor];\r\n\r\n if (fillColor != null) {\r\n legendData.labelColor = fillColor.solid.color;\r\n }\r\n }\r\n\r\n if (legendObject[legendProps.showTitle] === false)\r\n legendData.title = \"\";\r\n else if (legendObject[legendProps.titleText] !== undefined) {\r\n legendData.title = <string>legendObject[legendProps.titleText];\r\n }\r\n }\r\n }\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.visuals {\r\n export module axisScale {\r\n export const linear: string = 'linear';\r\n export const log: string = 'log'; \r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: linear, displayName: resources => resources.get('Visual_Axis_Linear') },\r\n { value: log, displayName: resources => resources.get('Visual_Axis_Log') } \r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module axisStyle {\r\n export const showBoth: string = 'showBoth';\r\n export const showTitleOnly: string = 'showTitleOnly';\r\n export const showUnitOnly: string = 'showUnitOnly';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: showTitleOnly, displayName: resources => resources.get('Visual_Axis_ShowTitleOnly') },\r\n { value: showUnitOnly, displayName: resources => resources.get('Visual_Axis_ShowUnitOnly') },\r\n { value: showBoth, displayName: resources => resources.get('Visual_Axis_ShowBoth') }\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module axisType {\r\n export const scalar: string = 'Scalar';\r\n export const categorical: string = 'Categorical'; \r\n export const both: string = 'Both';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: scalar, displayName: resources => resources.get('Visual_Axis_Scalar') },\r\n { value: categorical, displayName: resources => resources.get('Visual_Axis_Categorical') },\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module basicShapeType {\r\n export const rectangle: string = 'rectangle';\r\n export const oval: string = 'oval';\r\n export const line: string = 'line';\r\n export const arrow: string = 'arrow';\r\n export const triangle: string = 'triangle';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: rectangle, displayName: 'rectangle' },\r\n { value: oval, displayName: 'oval' },\r\n { value: line, displayName: 'line' },\r\n { value: arrow, displayName: 'arrow' },\r\n { value: triangle, displayName: 'triangle' }\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module imageScalingType {\r\n export const normal: string = 'Normal';\r\n export const fit: string = 'Fit';\r\n export const fill: string = 'Fill';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: normal, displayName: resources => resources.get('Visual_ImageScalingType_Normal') },\r\n { value: fit, displayName: resources => resources.get('Visual_ImageScalingType_Fit') },\r\n { value: fill, displayName: resources => resources.get('Visual_ImageScalingType_Fill') },\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n export module labelPosition {\r\n\r\n export const insideEnd: string = 'InsideEnd';\r\n export const insideCenter: string = 'InsideCenter';\r\n export const outsideEnd: string = 'OutsideEnd';\r\n export const insideBase: string = 'InsideBase';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: insideEnd, displayName: resources => resources.get('Visual_LabelPosition_InsideEnd') },\r\n { value: outsideEnd, displayName: resources => resources.get('Visual_LabelPosition_OutsideEnd') },\r\n { value: insideCenter, displayName: resources => resources.get('Visual_LabelPosition_InsideCenter') },\r\n { value: insideBase, displayName: resources => resources.get('Visual_LabelPosition_InsideBase') },\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module labelStyle {\r\n export const category: string = 'Category';\r\n export const data: string = 'Data';\r\n export const both: string = 'Both';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: category, displayName: resources => resources.get('Visual_LabelStyle_Category') },\r\n { value: data, displayName: resources => resources.get('Visual_LabelStyle_DataValue') },\r\n { value: both, displayName: resources => resources.get('Visual_LabelStyle_Both') },\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module legendPosition {\r\n export const top: string = 'Top';\r\n export const bottom: string = 'Bottom';\r\n export const left: string = 'Left';\r\n export const right: string = 'Right';\r\n export const topCenter: string = 'TopCenter';\r\n export const bottomCenter: string = 'BottomCenter';\r\n export const leftCenter: string = 'LeftCenter';\r\n export const rightCenter: string = 'RightCenter';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: top, displayName: resources => resources.get('Visual_LegendPosition_Top') },\r\n { value: bottom, displayName: resources => resources.get('Visual_LegendPosition_Bottom') },\r\n { value: left, displayName: resources => resources.get('Visual_LegendPosition_Left') },\r\n { value: right, displayName: resources => resources.get('Visual_LegendPosition_Right') },\r\n { value: topCenter, displayName: resources => resources.get('Visual_LegendPosition_TopCenter') },\r\n { value: bottomCenter, displayName: resources => resources.get('Visual_LegendPosition_BottomCenter') },\r\n { value: leftCenter, displayName: resources => resources.get('Visual_LegendPosition_LeftCenter') },\r\n { value: rightCenter, displayName: resources => resources.get('Visual_LegendPosition_RightCenter') },\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module kpiDirection {\r\n export const positive: string = 'Positive';\r\n export const negative: string = 'Negative';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: positive, displayName: resources => resources.get('Visual_KPI_Direction_Positive') },\r\n { value: negative, displayName: resources => resources.get('Visual_KPI_Direction_Negative') }\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module lineStyle {\r\n export const dashed: string = 'dashed';\r\n export const solid: string = 'solid';\r\n export const dotted: string = 'dotted';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: dashed, displayName: resources => resources.get('Visual_LineStyle_Dashed') },\r\n { value: solid, displayName: resources => resources.get('Visual_LineStyle_Solid') },\r\n { value: dotted, displayName: resources => resources.get('Visual_LineStyle_Dotted') }\r\n ]);\r\n }\r\n}"," /*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.visuals {\r\n export module outline {\r\n export const none: string = 'None';\r\n export const bottomOnly: string = 'BottomOnly';\r\n export const topOnly: string = 'TopOnly';\r\n export const leftOnly: string = 'LeftOnly';\r\n export const rightOnly: string = 'RightOnly';\r\n export const topBottom: string = 'TopBottom';\r\n export const leftRight: string = 'LeftRight';\r\n export const frame: string = 'Frame';\r\n\r\n export function showTop(outline: string): boolean {\r\n return [topOnly, topBottom, frame].some((o) => o === outline);\r\n }\r\n\r\n export function showRight(outline: string): boolean {\r\n return [rightOnly, leftRight, frame].some((o) => o === outline);\r\n }\r\n\r\n export function showBottom(outline: string): boolean {\r\n return [bottomOnly, topBottom, frame].some((o) => o === outline);\r\n }\r\n\r\n export function showLeft(outline: string): boolean {\r\n return [leftOnly, leftRight, frame].some((o) => o === outline);\r\n }\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: none, displayName: resources => resources.get('Visual_Outline_none') },\r\n { value: bottomOnly, displayName: resources => resources.get('Visual_Outline_bottom_only') },\r\n { value: topOnly, displayName: resources => resources.get('Visual_Outline_top_only') },\r\n { value: leftOnly, displayName: resources => resources.get('Visual_Outline_LeftOnly') },\r\n { value: rightOnly, displayName: resources => resources.get('Visual_Outline_RightOnly') },\r\n { value: topBottom, displayName: resources => resources.get('Visual_Outline_top_Bottom') },\r\n { value: leftRight, displayName: resources => resources.get('Visual_Outline_leftRight') },\r\n { value: frame, displayName: resources => resources.get('Visual_Outline_frame') }\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module referenceLinePosition {\r\n export const back: string = 'back';\r\n export const front: string = 'front';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: back, displayName: resources => resources.get('Visual_Reference_Line_Behind') },\r\n { value: front, displayName: resources => resources.get('Visual_Reference_Line_InFront') },\r\n ]);\r\n }\r\n\r\n export module referenceLineDataLabelHorizontalPosition {\r\n export const left: string = 'left';\r\n export const right: string = 'right';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: left, displayName: resources => resources.get('Visual_Reference_Line_Data_Label_Left') },\r\n { value: right, displayName: resources => resources.get('Visual_Reference_Line_Data_Label_Right') },\r\n ]);\r\n }\r\n\r\n export module referenceLineDataLabelVerticalPosition {\r\n export const above: string = 'above';\r\n export const under: string = 'under';\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: above, displayName: resources => resources.get('Visual_Reference_Line_Data_Label_Above') },\r\n { value: under, displayName: resources => resources.get('Visual_Reference_Line_Data_Label_Under') },\r\n ]);\r\n }\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.visuals {\r\n export module slicerOrientation {\r\n export const enum Orientation {\r\n Vertical,\r\n Horizontal\r\n }\r\n\r\n export const type: IEnumType = createEnumType([\r\n { value: Orientation.Vertical, displayName: resources => resources.get('Slicer_Orientation_Vertical') },\r\n { value: Orientation.Horizontal, displayName: resources => resources.get('Slicer_Orientation_Horizontal') },\r\n ]);\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module yAxisPosition {\r\n export const left: string = 'Left';\r\n export const right: string = 'Right'; \r\n \r\n export const type: IEnumType = createEnumType([\r\n { value: left, displayName: resources => resources.get('Visual_yAxis_Left') },\r\n { value: right, displayName: resources => resources.get('Visual_yAxis_Right') },\r\n ]);\r\n }\r\n}"," /*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module AnimatorCommon {\r\n export const MinervaAnimationDuration = 250;\r\n \r\n // The maximum number of data points we can performantly animate with SVG. If we have more, turn off animations.\r\n export const MaxDataPointsToAnimate = 1000;\r\n\r\n export function GetAnimationDuration(animator: IGenericAnimator, suppressAnimations: boolean) {\r\n return (suppressAnimations || !animator) ? 0 : animator.getDuration();\r\n }\r\n }\r\n\r\n export interface IAnimatorOptions {\r\n duration?: number;\r\n }\r\n\r\n export interface IAnimationOptions {\r\n interactivityService: IInteractivityService;\r\n }\r\n\r\n export interface IAnimationResult {\r\n failed: boolean;\r\n }\r\n\r\n export interface IAnimator<T extends IAnimatorOptions, U extends IAnimationOptions, V extends IAnimationResult> {\r\n getDuration(): number;\r\n getEasing(): string;\r\n\r\n animate(options: U): V;\r\n }\r\n\r\n export type IGenericAnimator = IAnimator<IAnimatorOptions, IAnimationOptions, IAnimationResult>;\r\n\r\n /** \r\n * We just need to have a non-null animator to allow axis animations in cartesianChart.\r\n * Note: Use this temporarily for Line/Scatter until we add more animations (MinervaPlugins only).\r\n */\r\n export class BaseAnimator<T extends IAnimatorOptions, U extends IAnimationOptions, V extends IAnimationResult> implements IAnimator<T, U, V> {\r\n protected animationDuration: number;\r\n\r\n constructor(options?: T) {\r\n if (options && options.duration) {\r\n this.animationDuration = options.duration;\r\n }\r\n\r\n this.animationDuration = this.animationDuration >= 0 ? this.animationDuration : AnimatorCommon.MinervaAnimationDuration;\r\n }\r\n\r\n public getDuration(): number {\r\n return this.animationDuration;\r\n }\r\n\r\n public animate(options: U): V {\r\n return null;\r\n }\r\n\r\n public getEasing(): string {\r\n return 'cubic-in-out';\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n\r\n export interface ColumnChartAnimationOptions extends IAnimationOptions {\r\n viewModel: ColumnChartData;\r\n series: D3.UpdateSelection;\r\n layout: IColumnLayout;\r\n itemCS: ClassAndSelector;\r\n mainGraphicsContext: D3.Selection;\r\n viewPort: IViewport;\r\n }\r\n\r\n export interface ColumnChartAnimationResult extends IAnimationResult {\r\n shapes: D3.UpdateSelection;\r\n }\r\n\r\n export type IColumnChartAnimator = IAnimator<IAnimatorOptions, ColumnChartAnimationOptions, ColumnChartAnimationResult>;\r\n\r\n export class WebColumnChartAnimator extends BaseAnimator<IAnimatorOptions, ColumnChartAnimationOptions, ColumnChartAnimationResult> implements IColumnChartAnimator {\r\n private previousViewModel: ColumnChartData;\r\n\r\n constructor(options?: IAnimatorOptions) {\r\n super(options);\r\n }\r\n\r\n public animate(options: ColumnChartAnimationOptions): ColumnChartAnimationResult {\r\n let result: ColumnChartAnimationResult = {\r\n failed: true,\r\n shapes: null,\r\n };\r\n\r\n let viewModel = options.viewModel;\r\n let previousViewModel = this.previousViewModel;\r\n \r\n let dataPointCount = viewModel.categories.length * viewModel.series.length;\r\n if (dataPointCount > AnimatorCommon.MaxDataPointsToAnimate) {\r\n // Too many data points to animate.\r\n return result;\r\n }\r\n\r\n if (!previousViewModel) {\r\n // This is the initial drawing of the chart, which has no special animation for now.\r\n }\r\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\r\n result = this.animateNormalToHighlighted(options);\r\n }\r\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToHighlighted(options);\r\n }\r\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToNormal(options);\r\n }\r\n\r\n this.previousViewModel = viewModel;\r\n return result;\r\n }\r\n\r\n private animateNormalToHighlighted(options: ColumnChartAnimationOptions): ColumnChartAnimationResult {\r\n let data = options.viewModel;\r\n let itemCS = options.itemCS;\r\n let shapeSelection = options.series.selectAll(itemCS.selector);\r\n let shapes = shapeSelection.data((d: ColumnChartSeries) => d.data, (d: ColumnChartDataPoint) => d.key);\r\n let hasHighlights = data.hasHighlights;\r\n\r\n shapes\r\n .enter()\r\n .append('rect')\r\n .attr(\"class\", (d: ColumnChartDataPoint) => itemCS.class.concat(d.highlight ? \" highlight\" : \"\"))\r\n .attr(options.layout.shapeLayoutWithoutHighlights); // Start out at the non-highlight layout\r\n\r\n shapes\r\n .style(\"fill\", (d: ColumnChartDataPoint) => d.color)\r\n .style(\"fill-opacity\", (d: ColumnChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, false, hasHighlights))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(options.layout.shapeLayout);\r\n\r\n shapes\r\n .exit()\r\n .remove();\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n };\r\n }\r\n\r\n private animateHighlightedToHighlighted(options: ColumnChartAnimationOptions): ColumnChartAnimationResult {\r\n let shapes = this.animateDefaultShapes(options.viewModel, options.series, options.layout, options.itemCS);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n };\r\n }\r\n\r\n private animateHighlightedToNormal(options: ColumnChartAnimationOptions): ColumnChartAnimationResult {\r\n let itemCS = options.itemCS;\r\n let shapeSelection = options.series.selectAll(itemCS.selector);\r\n let shapes = shapeSelection.data((d: ColumnChartSeries) => d.data, (d: ColumnChartDataPoint) => d.key);\r\n let hasSelection = options.interactivityService && options.interactivityService.hasSelection();\r\n\r\n shapes\r\n .enter()\r\n .append('rect')\r\n .attr(\"class\", (d: ColumnChartDataPoint) => itemCS.class.concat(d.highlight ? \" highlight\" : \"\"));\r\n\r\n shapes\r\n .style(\"fill\", (d: ColumnChartDataPoint) => d.color)\r\n .style(\"fill-opacity\", (d: ColumnChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, d.selected, !d.selected))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(options.layout.shapeLayout)\r\n .transition()\r\n .duration(0)\r\n .delay(this.animationDuration)\r\n .style(\"fill-opacity\", (d: ColumnChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false));\r\n\r\n shapes\r\n .exit()\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(hasSelection ? options.layout.zeroShapeLayout : options.layout.shapeLayoutWithoutHighlights)\r\n .remove();\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n };\r\n }\r\n\r\n private animateDefaultShapes(data: ColumnChartData, series: D3.UpdateSelection, layout: IColumnLayout, itemCS: ClassAndSelector): D3.UpdateSelection {\r\n let shapeSelection = series.selectAll(itemCS.selector);\r\n let shapes = shapeSelection.data((d: ColumnChartSeries) => d.data, (d: ColumnChartDataPoint) => d.key);\r\n\r\n shapes\r\n .enter()\r\n .append('rect')\r\n .attr(\"class\", (d: ColumnChartDataPoint) => itemCS.class.concat(d.highlight ? \" highlight\" : \"\"));\r\n\r\n shapes\r\n .style(\"fill\", (d: ColumnChartDataPoint) => d.color)\r\n .style(\"fill-opacity\", (d: ColumnChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, false, data.hasHighlights))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(layout.shapeLayout);\r\n\r\n shapes\r\n .exit()\r\n .remove();\r\n\r\n return shapes;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface DonutChartAnimationOptions extends IAnimationOptions {\r\n viewModel: DonutData;\r\n graphicsContext: D3.Selection;\r\n labelGraphicsContext: D3.Selection;\r\n colors: IDataColorPalette;\r\n layout: DonutLayout;\r\n sliceWidthRatio: number;\r\n radius: number;\r\n viewport: IViewport;\r\n innerArcRadiusRatio: number;\r\n labels: Label[];\r\n }\r\n\r\n export interface DonutChartAnimationResult extends IAnimationResult {\r\n shapes: D3.UpdateSelection;\r\n highlightShapes: D3.UpdateSelection;\r\n }\r\n\r\n export type IDonutChartAnimator = IAnimator<IAnimatorOptions, DonutChartAnimationOptions, DonutChartAnimationResult>;\r\n\r\n export class WebDonutChartAnimator extends BaseAnimator<IAnimatorOptions, DonutChartAnimationOptions, DonutChartAnimationResult> implements IDonutChartAnimator {\r\n private previousViewModel: DonutData;\r\n\r\n constructor(options?: IAnimatorOptions) {\r\n super(options);\r\n }\r\n\r\n public animate(options: DonutChartAnimationOptions): DonutChartAnimationResult {\r\n let result: DonutChartAnimationResult = {\r\n failed: true,\r\n shapes: null,\r\n highlightShapes: null,\r\n };\r\n\r\n let viewModel = options.viewModel;\r\n let previousViewModel = this.previousViewModel;\r\n\r\n if (!previousViewModel) {\r\n // This is the initial drawing of the chart, which has no special animation for now.\r\n }\r\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\r\n result = this.animateNormalToHighlighted(options);\r\n }\r\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToHighlighted(options);\r\n }\r\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToNormal(options);\r\n }\r\n\r\n this.previousViewModel = viewModel;\r\n return result;\r\n }\r\n\r\n private animateNormalToHighlighted(options: DonutChartAnimationOptions): DonutChartAnimationResult {\r\n let shapes = this.animateDefaultShapes(options);\r\n\r\n let highlightShapes = options.graphicsContext.select('.slices')\r\n .selectAll('path.slice-highlight')\r\n .data(options.viewModel.dataPoints.filter((value: DonutArcDescriptor) => value.data.highlightRatio != null), (d: DonutArcDescriptor) => d.data.identity.getKey());\r\n\r\n highlightShapes.enter()\r\n .insert('path')\r\n .classed('slice-highlight', true)\r\n .each(function (d) { this._current = d; });\r\n\r\n DonutChart.isSingleColor(options.viewModel.dataPoints.filter((value: DonutArcDescriptor) => value.data.highlightRatio != null));\r\n\r\n highlightShapes\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, true, false, options.viewModel.hasHighlights))\r\n .style(\"stroke-dasharray\", (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio, d.data.highlightRatio))\r\n .style(\"stroke-width\", (d: DonutArcDescriptor) => d.data.strokeWidth)\r\n .attr(options.layout.shapeLayout) // Start at the non-highlight layout, then transition to the highlight layout.\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(options.layout.highlightShapeLayout);\r\n\r\n highlightShapes.exit()\r\n .remove();\r\n\r\n NewDataLabelUtils.drawDefaultLabels(options.labelGraphicsContext, options.labels, false, true, true /*has tooltip */);\r\n NewDataLabelUtils.drawLabelLeaderLines(options.labelGraphicsContext, options.labels);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n highlightShapes: highlightShapes,\r\n };\r\n }\r\n\r\n private animateHighlightedToHighlighted(options: DonutChartAnimationOptions): DonutChartAnimationResult {\r\n let shapes = this.animateDefaultShapes(options);\r\n\r\n let highlightShapes = this.animateDefaultHighlightShapes(options);\r\n NewDataLabelUtils.drawDefaultLabels(options.labelGraphicsContext, options.labels, false, true, true /*has tooltip */);\r\n NewDataLabelUtils.drawLabelLeaderLines(options.labelGraphicsContext, options.labels);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n highlightShapes: highlightShapes,\r\n };\r\n }\r\n\r\n private animateHighlightedToNormal(options: DonutChartAnimationOptions): DonutChartAnimationResult {\r\n let hasSelection = options.interactivityService && options.interactivityService.hasSelection();\r\n let duration = this.animationDuration;\r\n\r\n let shapes = options.graphicsContext.select('.slices')\r\n .selectAll('path.slice')\r\n .data(options.viewModel.dataPoints, (d: DonutArcDescriptor) => d.data.identity.getKey());\r\n\r\n shapes.enter()\r\n .insert('path')\r\n .classed('slice', true)\r\n .each(function (d) { this._current = d; });\r\n\r\n DonutChart.isSingleColor(options.viewModel.dataPoints);\r\n\r\n // For any slice that is selected we want to keep showing it as dimmed (partially highlighted). After the highlight animation\r\n // finishes we will set the opacity based on the selection state.\r\n shapes\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, false, d.data.selected, !d.data.selected))\r\n .style(\"stroke-dasharray\", (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio))\r\n .style(\"stroke-width\", (d: DonutArcDescriptor) => d.data.strokeWidth)\r\n .transition()\r\n .duration(duration)\r\n .attr(options.layout.shapeLayout)\r\n .transition()\r\n .duration(0)\r\n .delay(duration)\r\n .style(\"fill-opacity\", (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false));;\r\n\r\n shapes.exit()\r\n .remove();\r\n\r\n let highlightShapes = options.graphicsContext.select('.slices')\r\n .selectAll('path.slice-highlight')\r\n .data(options.viewModel.dataPoints.filter((value: DonutArcDescriptor) => value.data.highlightRatio != null), (d: DonutArcDescriptor) => d.data.identity.getKey());\r\n\r\n highlightShapes.enter()\r\n .insert('path')\r\n .classed('slice-highlight', true)\r\n .each(function (d) { this._current = d; });\r\n\r\n DonutChart.isSingleColor(options.viewModel.dataPoints.filter((value: DonutArcDescriptor) => value.data.highlightRatio != null));\r\n\r\n highlightShapes\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(false, true, false, true))\r\n .style(\"stroke-dasharray\", (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio, d.data.highlightRatio))\r\n .style(\"stroke-width\", (d: DonutArcDescriptor) => d.data.strokeWidth)\r\n .transition()\r\n .duration(duration)\r\n .attr(hasSelection ? options.layout.zeroShapeLayout : options.layout.shapeLayout) // Transition to the non-highlight layout\r\n .remove();\r\n\r\n highlightShapes.exit()\r\n .remove();\r\n\r\n NewDataLabelUtils.drawDefaultLabels(options.labelGraphicsContext, options.labels, false, true, true /*has tooltip */);\r\n NewDataLabelUtils.drawLabelLeaderLines(options.labelGraphicsContext, options.labels);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n highlightShapes: highlightShapes,\r\n };\r\n }\r\n\r\n private animateDefaultShapes(options: DonutChartAnimationOptions): D3.UpdateSelection {\r\n let shapes = options.graphicsContext.select('.slices')\r\n .selectAll('path.slice')\r\n .data(options.viewModel.dataPoints, (d: DonutArcDescriptor) => d.data.identity.getKey());\r\n\r\n shapes.enter()\r\n .insert('path')\r\n .classed('slice', true)\r\n .each(function (d) { this._current = d; });\r\n\r\n DonutChart.isSingleColor(options.viewModel.dataPoints);\r\n\r\n shapes\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, false, false, options.viewModel.hasHighlights))\r\n .style(\"stroke-dasharray\", (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio))\r\n .style(\"stroke-width\", (d: DonutArcDescriptor) => d.data.strokeWidth)\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(options.layout.shapeLayout);\r\n\r\n shapes.exit()\r\n .remove();\r\n\r\n return shapes;\r\n }\r\n\r\n private animateDefaultHighlightShapes(options: DonutChartAnimationOptions): D3.UpdateSelection {\r\n let highlightShapes = options.graphicsContext.select('.slices')\r\n .selectAll('path.slice-highlight')\r\n .data(options.viewModel.dataPoints.filter((value: DonutArcDescriptor) => value.data.highlightRatio != null), (d: DonutArcDescriptor) => d.data.identity.getKey());\r\n\r\n highlightShapes.enter()\r\n .insert('path')\r\n .classed('slice-highlight', true)\r\n .each(function (d) { this._current = d; });\r\n\r\n DonutChart.isSingleColor(options.viewModel.dataPoints.filter((value: DonutArcDescriptor) => value.data.highlightRatio != null));\r\n\r\n highlightShapes\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color ? d.data.color : options.colors.getNewColorScale().getColor(d.data.identity.getKey()).value)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, true, false, options.viewModel.hasHighlights))\r\n .style(\"stroke-dasharray\", (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(options.radius, options.innerArcRadiusRatio, d, options.sliceWidthRatio, d.data.highlightRatio))\r\n .style(\"stroke-width\", (d: DonutArcDescriptor) => d.data.strokeWidth)\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(options.layout.highlightShapeLayout);\r\n\r\n highlightShapes.exit()\r\n .remove();\r\n\r\n return highlightShapes;\r\n }\r\n }\r\n} "," /*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface FunnelAnimationOptions extends IAnimationOptions{\r\n viewModel: FunnelData;\r\n layout: IFunnelLayout;\r\n axisGraphicsContext: D3.Selection;\r\n shapeGraphicsContext: D3.Selection;\r\n percentGraphicsContext: D3.Selection;\r\n labelGraphicsContext: D3.Selection;\r\n axisOptions: FunnelAxisOptions;\r\n slicesWithoutHighlights: FunnelSlice[];\r\n labelLayout: ILabelLayout; \r\n isHidingPercentBars: boolean;\r\n visualInitOptions: VisualInitOptions;\r\n }\r\n\r\n export interface FunnelAnimationResult extends IAnimationResult {\r\n shapes: D3.UpdateSelection;\r\n dataLabels: D3.UpdateSelection;\r\n }\r\n\r\n export type IFunnelAnimator = IAnimator<IAnimatorOptions, FunnelAnimationOptions, FunnelAnimationResult>;\r\n\r\n export class WebFunnelAnimator extends BaseAnimator<IAnimatorOptions, FunnelAnimationOptions, FunnelAnimationResult> implements IFunnelAnimator {\r\n private previousViewModel: FunnelData;\r\n\r\n constructor(options?: IAnimatorOptions) {\r\n super(options);\r\n }\r\n\r\n public animate(options: FunnelAnimationOptions): FunnelAnimationResult {\r\n let result: FunnelAnimationResult = {\r\n failed: true,\r\n shapes: null,\r\n dataLabels: null,\r\n };\r\n\r\n let viewModel = options.viewModel;\r\n let previousViewModel = this.previousViewModel;\r\n\r\n if (!previousViewModel) {\r\n // This is the initial drawing of the chart, which has no special animation for now.\r\n }\r\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\r\n result = this.animateNormalToHighlighted(options);\r\n }\r\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToHighlighted(options);\r\n }\r\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToNormal(options);\r\n }\r\n\r\n this.previousViewModel = viewModel;\r\n return result;\r\n }\r\n\r\n private animateNormalToHighlighted(options: FunnelAnimationOptions): FunnelAnimationResult {\r\n let data = options.viewModel;\r\n let layout = options.layout;\r\n let hasHighlights = true;\r\n let hasSelection = false;\r\n\r\n this.animateDefaultAxis(options.axisGraphicsContext, options.axisOptions, options.isHidingPercentBars);\r\n\r\n let shapes = options.shapeGraphicsContext.selectAll(FunnelChart.Selectors.funnel.bars.selector).data(data.slices, (d: FunnelSlice) => d.key);\r\n\r\n shapes.enter()\r\n .append('rect')\r\n .attr(\"class\", (d: FunnelSlice) => d.highlight ? FunnelChart.FunnelBarHighlightClass : FunnelChart.Selectors.funnel.bars.class)\r\n .attr(layout.shapeLayoutWithoutHighlights); // Start by laying out all rectangles ignoring highlights\r\n\r\n shapes\r\n .style(\"fill\", (d: FunnelSlice) => d.color)\r\n .style(\"fill-opacity\", (d: FunnelSlice) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(layout.shapeLayout); // Then transition to the layout that uses highlights\r\n\r\n shapes.exit().remove();\r\n\r\n this.animatePercentBars(options);\r\n\r\n let dataLabels: D3.UpdateSelection = this.animateDefaultDataLabels(options);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n dataLabels: dataLabels,\r\n };\r\n }\r\n\r\n private animateHighlightedToHighlighted(options: FunnelAnimationOptions): FunnelAnimationResult {\r\n let data = options.viewModel;\r\n let layout = options.layout;\r\n\r\n this.animateDefaultAxis(options.axisGraphicsContext, options.axisOptions, options.isHidingPercentBars);\r\n\r\n // Simply animate to the new shapes.\r\n let shapes = this.animateDefaultShapes(data, data.slices, options.shapeGraphicsContext, layout);\r\n this.animatePercentBars(options);\r\n let dataLabels: D3.UpdateSelection = this.animateDefaultDataLabels(options);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n dataLabels: dataLabels,\r\n };\r\n }\r\n\r\n private animateHighlightedToNormal(options: FunnelAnimationOptions): FunnelAnimationResult {\r\n let data = options.viewModel;\r\n let layout = options.layout;\r\n let hasSelection = options.interactivityService ? options.interactivityService.hasSelection() : false;\r\n\r\n this.animateDefaultAxis(options.axisGraphicsContext, options.axisOptions, options.isHidingPercentBars);\r\n\r\n let shapes = options.shapeGraphicsContext.selectAll(FunnelChart.Selectors.funnel.bars.selector).data(data.slices, (d: FunnelSlice) => d.key);\r\n\r\n shapes.enter()\r\n .append('rect')\r\n .attr(\"class\", (d: FunnelSlice) => d.highlight ? FunnelChart.FunnelBarHighlightClass : FunnelChart.Selectors.funnel.bars.class);\r\n\r\n shapes\r\n .style(\"fill\",(d: FunnelSlice) => d.color)\r\n .style(\"fill-opacity\", (d: FunnelSlice) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, !d.selected))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(layout.shapeLayoutWithoutHighlights) // Transition to layout without highlights\r\n .transition()\r\n .duration(0)\r\n .delay(this.animationDuration)\r\n .style(\"fill-opacity\", (d: FunnelSlice) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false));\r\n\r\n let exitShapes = shapes.exit();\r\n\r\n exitShapes\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(hasSelection ? layout.zeroShapeLayout : layout.shapeLayoutWithoutHighlights) // Transition to layout without highlights\r\n .remove();\r\n\r\n this.animatePercentBars(options);\r\n\r\n let dataLabels: D3.UpdateSelection = this.animateDefaultDataLabels(options);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n dataLabels: dataLabels,\r\n };\r\n }\r\n\r\n private animateDefaultAxis(graphicsContext: D3.Selection, axisOptions: FunnelAxisOptions, isHidingPercentBars: boolean): void {\r\n let xScaleForAxis = d3.scale.ordinal()\r\n .domain(axisOptions.categoryLabels)\r\n .rangeBands([axisOptions.rangeStart, axisOptions.rangeEnd], axisOptions.barToSpaceRatio, isHidingPercentBars ? axisOptions.barToSpaceRatio : FunnelChart.PercentBarToBarRatio);\r\n let xAxis = d3.svg.axis()\r\n .scale(xScaleForAxis)\r\n .orient(\"right\")\r\n .tickPadding(FunnelChart.TickPadding)\r\n .innerTickSize(FunnelChart.InnerTickSize);\r\n graphicsContext.classed('axis', true)\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr('transform', SVGUtil.translate(0, axisOptions.margin.top))\r\n .call(xAxis);\r\n }\r\n\r\n private animateDefaultShapes(data: FunnelData, slices: FunnelSlice[], graphicsContext: D3.Selection, layout: IFunnelLayout): D3.UpdateSelection {\r\n let hasHighlights = data.hasHighlights;\r\n let shapes = graphicsContext.selectAll(FunnelChart.Selectors.funnel.bars.selector).data(slices, (d: FunnelSlice) => d.key);\r\n\r\n shapes.enter()\r\n .append('rect')\r\n .attr(\"class\", (d: FunnelSlice) => d.highlight ? FunnelChart.FunnelBarHighlightClass : FunnelChart.Selectors.funnel.bars.class);\r\n\r\n shapes\r\n .style(\"fill\", (d: FunnelSlice) => d.color)\r\n .style(\"fill-opacity\", d => (d: FunnelSlice) => ColumnUtil.getFillOpacity(d.selected, d.highlight, false, hasHighlights))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(layout.shapeLayout);\r\n\r\n shapes.exit().remove();\r\n\r\n return shapes;\r\n }\r\n\r\n private animateDefaultDataLabels(options: FunnelAnimationOptions): D3.UpdateSelection {\r\n let dataLabels: D3.UpdateSelection;\r\n\r\n if (options.viewModel.dataLabelsSettings.show && options.viewModel.canShowDataLabels) {\r\n dataLabels = dataLabelUtils.drawDefaultLabelsForFunnelChart(options.viewModel.slices, options.labelGraphicsContext, options.labelLayout, true, this.animationDuration);\r\n }\r\n else {\r\n dataLabelUtils.cleanDataLabels(options.labelGraphicsContext);\r\n }\r\n\r\n return dataLabels;\r\n }\r\n\r\n private animatePercentBars(options: FunnelAnimationOptions): void {\r\n let data: FunnelData = options.viewModel;\r\n let isHidingPercentBars: boolean = options.isHidingPercentBars;\r\n\r\n if (isHidingPercentBars || !data.slices || (data.hasHighlights ? data.slices.length / 2 : data.slices.length) < 2) {\r\n // TODO: call percentBarComponents with flag with empty data to clear drawing smoothly\r\n this.animatePercentBarComponents([], options);\r\n return;\r\n }\r\n\r\n let slices = [data.slices[data.hasHighlights ? 1 : 0], data.slices[data.slices.length - 1]];\r\n let baseline = FunnelChart.getFunnelSliceValue(slices[0]);\r\n\r\n if (baseline <= 0) {\r\n // TODO: call percentBarComponents with flag with empty data to clear drawing smoothly\r\n this.animatePercentBarComponents([], options);\r\n return;\r\n }\r\n\r\n let percentData = slices.map((slice, i) => <FunnelPercent>{\r\n value: FunnelChart.getFunnelSliceValue(slice),\r\n percent: i === 0 ? 1 : FunnelChart.getFunnelSliceValue(slice) / baseline,\r\n isTop: i === 0,\r\n });\r\n\r\n this.animatePercentBarComponents(percentData, options);\r\n }\r\n\r\n private animateToFunnelPercent(context: D3.Selection, targetData: FunnelPercent[], layout: any): D3.Transition.Transition {\r\n return context\r\n .data(targetData)\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(layout);\r\n }\r\n\r\n private animatePercentBarComponents(data: FunnelPercent[], options: FunnelAnimationOptions) {\r\n let graphicsContext: D3.Selection = options.percentGraphicsContext;\r\n let layout: IFunnelLayout = options.layout;\r\n let zeroData: FunnelPercent[] = [\r\n { percent: 0, value: 0, isTop: true },\r\n { percent: 0, value: 0, isTop: false },\r\n ];\r\n\r\n // Main line\r\n let mainLine: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.mainLine.selector).data(data);\r\n\r\n this.animateToFunnelPercent(mainLine.exit(), zeroData, layout.percentBarLayout.mainLine)\r\n .remove();\r\n\r\n mainLine.enter()\r\n .append('line')\r\n .classed(FunnelChart.Selectors.percentBar.mainLine.class, true)\r\n .data(zeroData)\r\n .attr(layout.percentBarLayout.mainLine);\r\n\r\n this.animateToFunnelPercent(mainLine, data, layout.percentBarLayout.mainLine);\r\n\r\n // Left tick\r\n let leftTick: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.leftTick.selector).data(data);\r\n\r\n this.animateToFunnelPercent(leftTick.exit(), zeroData, layout.percentBarLayout.leftTick)\r\n .remove();\r\n \r\n leftTick.enter()\r\n .append('line')\r\n .classed(FunnelChart.Selectors.percentBar.leftTick.class, true)\r\n .data(zeroData)\r\n .attr(layout.percentBarLayout.leftTick);\r\n\r\n this.animateToFunnelPercent(leftTick, data, layout.percentBarLayout.leftTick);\r\n\r\n // Right tick\r\n let rightTick: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.rightTick.selector).data(data);\r\n \r\n this.animateToFunnelPercent(rightTick.exit(), zeroData, layout.percentBarLayout.rightTick)\r\n .remove();\r\n\r\n rightTick.enter()\r\n .append('line')\r\n .classed(FunnelChart.Selectors.percentBar.rightTick.class, true)\r\n .data(zeroData)\r\n .attr(layout.percentBarLayout.rightTick);\r\n\r\n this.animateToFunnelPercent(rightTick, data, layout.percentBarLayout.rightTick);\r\n\r\n // Text\r\n let text: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.text.selector).data(data);\r\n \r\n this.animateToFunnelPercent(text.exit(), zeroData, layout.percentBarLayout.text)\r\n .remove();\r\n\r\n text.enter()\r\n .append('text')\r\n .classed(FunnelChart.Selectors.percentBar.text.class, true)\r\n .data(zeroData)\r\n .attr(layout.percentBarLayout.text);\r\n\r\n this.animateToFunnelPercent(text, data, layout.percentBarLayout.text)\r\n .text((fp: FunnelPercent) => {\r\n return formattingService.formatValue(fp.percent, valueFormatter.getLocalizedString(\"Percentage1\"));\r\n });\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(options.visualInitOptions);\r\n }\r\n }\r\n}"," /*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface TreemapAnimationOptions extends IAnimationOptions {\r\n viewModel: TreemapData;\r\n nodes: D3.Layout.GraphNode[];\r\n highlightNodes: D3.Layout.GraphNode[];\r\n majorLabeledNodes: D3.Layout.GraphNode[];\r\n minorLabeledNodes: D3.Layout.GraphNode[];\r\n shapeGraphicsContext: D3.Selection;\r\n labelGraphicsContext: D3.Selection;\r\n layout: ITreemapLayout;\r\n labelSettings: VisualDataLabelsSettings;\r\n }\r\n\r\n export interface TreemapAnimationResult extends IAnimationResult {\r\n shapes: D3.UpdateSelection;\r\n highlightShapes: D3.UpdateSelection;\r\n majorLabels: D3.UpdateSelection;\r\n minorLabels: D3.UpdateSelection;\r\n }\r\n\r\n export type ITreemapAnimator = IAnimator<IAnimatorOptions, TreemapAnimationOptions, TreemapAnimationResult>;\r\n\r\n export class WebTreemapAnimator extends BaseAnimator<IAnimatorOptions, TreemapAnimationOptions, TreemapAnimationResult> implements ITreemapAnimator {\r\n previousViewModel: TreemapData;\r\n\r\n constructor(options?: IAnimatorOptions) {\r\n super(options);\r\n }\r\n\r\n public animate(options: TreemapAnimationOptions): TreemapAnimationResult {\r\n let result: TreemapAnimationResult = {\r\n failed: true,\r\n shapes: null,\r\n highlightShapes: null,\r\n majorLabels: null,\r\n minorLabels: null,\r\n };\r\n\r\n let viewModel = options.viewModel;\r\n let previousViewModel = this.previousViewModel;\r\n\r\n if (!previousViewModel) {\r\n // This is the initial drawing of the chart, which has no special animation for now.\r\n }\r\n else if (viewModel.hasHighlights && !previousViewModel.hasHighlights) {\r\n result = this.animateNormalToHighlighted(options);\r\n }\r\n else if (viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToHighlighted(options);\r\n }\r\n else if (!viewModel.hasHighlights && previousViewModel.hasHighlights) {\r\n result = this.animateHighlightedToNormal(options);\r\n }\r\n\r\n this.previousViewModel = viewModel;\r\n return result;\r\n }\r\n\r\n private animateNormalToHighlighted(options: TreemapAnimationOptions): TreemapAnimationResult {\r\n let hasSelection = false;\r\n let hasHighlights = true;\r\n\r\n let shapes = this.animateDefaultShapes(options.shapeGraphicsContext, options.nodes, hasSelection, hasHighlights, options.layout);\r\n\r\n let highlightShapes = options.shapeGraphicsContext.selectAll('.' + Treemap.HighlightNodeClassName)\r\n .data(options.highlightNodes, (d: TreemapNode) => d.key + \"highlight\");\r\n\r\n highlightShapes.enter().append('rect')\r\n .attr('class', options.layout.highlightShapeClass)\r\n .attr(options.layout.shapeLayout); // Start using the normal shape layout\r\n\r\n highlightShapes\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, true))\r\n .style(\"fill-opacity\", (d: TreemapNode) => Treemap.getFillOpacity(d, hasSelection, hasHighlights, true))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(options.layout.highlightShapeLayout); // Animate to the highlighted positions\r\n\r\n highlightShapes.exit().remove();\r\n\r\n let majorLabels = this.animateDefaultMajorLabels(options.labelGraphicsContext, options.majorLabeledNodes, options.labelSettings, options.layout);\r\n let minorLabels = this.animateDefaultMinorLabels(options.labelGraphicsContext, options.minorLabeledNodes, options.labelSettings, options.layout);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n highlightShapes: highlightShapes,\r\n majorLabels: majorLabels,\r\n minorLabels: minorLabels,\r\n };\r\n }\r\n\r\n private animateHighlightedToHighlighted(options: TreemapAnimationOptions): TreemapAnimationResult {\r\n let hasSelection = false;\r\n let hasHighlights = true;\r\n\r\n let shapes = this.animateDefaultShapes(options.shapeGraphicsContext, options.nodes, hasSelection, hasHighlights, options.layout);\r\n\r\n options.shapeGraphicsContext.selectAll('.' + Treemap.HighlightNodeClassName)\r\n .data(options.highlightNodes, (d: TreemapNode) => d.key + \"highlight\");\r\n\r\n let highlightShapes = this.animateDefaultHighlightShapes(options.shapeGraphicsContext, options.highlightNodes, hasSelection, hasHighlights, options.layout);\r\n \r\n let majorLabels = this.animateDefaultMajorLabels(options.labelGraphicsContext, options.majorLabeledNodes, options.labelSettings, options.layout);\r\n let minorLabels = this.animateDefaultMinorLabels(options.labelGraphicsContext, options.minorLabeledNodes, options.labelSettings, options.layout);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n highlightShapes: highlightShapes,\r\n majorLabels: majorLabels,\r\n minorLabels: minorLabels,\r\n };\r\n }\r\n\r\n private animateHighlightedToNormal(options: TreemapAnimationOptions): TreemapAnimationResult {\r\n let hasSelection = options.interactivityService ? options.interactivityService.hasSelection() : false;\r\n\r\n let shapes = options.shapeGraphicsContext.selectAll('.' + Treemap.TreemapNodeClassName)\r\n .data(options.nodes, (d: TreemapNode) => d.key);\r\n\r\n shapes.enter().append('rect')\r\n .attr('class', options.layout.shapeClass);\r\n\r\n shapes\r\n .transition()\r\n .duration(this.animationDuration)\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, false))\r\n .style(\"fill-opacity\", (d: TreemapNode) => ColumnUtil.getFillOpacity(d.selected, false, d.selected, !d.selected))\r\n .attr(options.layout.shapeLayout)\r\n .transition()\r\n .duration(0)\r\n .delay(this.animationDuration)\r\n .style(\"fill-opacity\", (d: TreemapNode) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false));\r\n\r\n shapes.exit().remove();\r\n\r\n let highlightShapes = options.shapeGraphicsContext.selectAll('.' + Treemap.HighlightNodeClassName)\r\n .data(options.nodes, (d: TreemapNode) => d.key + \"highlight\");\r\n\r\n highlightShapes.enter().append('rect')\r\n .attr('class', options.layout.highlightShapeClass);\r\n\r\n highlightShapes\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, true))\r\n .style(\"fill-opacity\", (d: TreemapNode) => ColumnUtil.getFillOpacity(d.selected, true, d.selected, !d.selected))\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(hasSelection ? options.layout.zeroShapeLayout : options.layout.shapeLayout) // Animate to the normal shape layout or zero shape layout depending on whether we have a selection or not\r\n .remove();\r\n\r\n highlightShapes.exit().remove();\r\n\r\n let majorLabels = this.animateDefaultMajorLabels(options.labelGraphicsContext, options.majorLabeledNodes, options.labelSettings, options.layout);\r\n let minorLabels = this.animateDefaultMinorLabels(options.labelGraphicsContext, options.minorLabeledNodes, options.labelSettings, options.layout);\r\n\r\n return {\r\n failed: false,\r\n shapes: shapes,\r\n highlightShapes: highlightShapes,\r\n majorLabels: majorLabels,\r\n minorLabels: minorLabels,\r\n };\r\n }\r\n\r\n private animateDefaultShapes(context: D3.Selection, nodes: D3.Layout.GraphNode[], hasSelection: boolean, hasHighlights: boolean, layout: ITreemapLayout): D3.UpdateSelection {\r\n let isHighlightShape = false;\r\n let shapes = context.selectAll('.' + Treemap.TreemapNodeClassName)\r\n .data(nodes, (d: TreemapNode) => d.key);\r\n\r\n shapes.enter().append('rect')\r\n .attr('class', layout.shapeClass);\r\n\r\n shapes\r\n .transition()\r\n .duration(this.animationDuration)\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, isHighlightShape))\r\n .style(\"fill-opacity\", (d: TreemapNode) => Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape))\r\n .attr(layout.shapeLayout);\r\n\r\n shapes.exit().remove();\r\n\r\n return shapes;\r\n }\r\n\r\n private animateDefaultHighlightShapes(context: D3.Selection, nodes: D3.Layout.GraphNode[], hasSelection: boolean, hasHighlights: boolean, layout: ITreemapLayout): D3.UpdateSelection {\r\n let isHighlightShape = true;\r\n let highlightShapes = context.selectAll('.' + Treemap.HighlightNodeClassName)\r\n .data(nodes, (d) => d.key + \"highlight\");\r\n\r\n highlightShapes.enter().append('rect')\r\n .attr('class', layout.highlightShapeClass);\r\n\r\n highlightShapes\r\n .transition()\r\n .duration(this.animationDuration)\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, isHighlightShape))\r\n .style(\"fill-opacity\", (d: TreemapNode) => Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape))\r\n .attr(layout.highlightShapeLayout);\r\n\r\n highlightShapes.exit().remove();\r\n return highlightShapes;\r\n }\r\n\r\n private animateDefaultMajorLabels(context: D3.Selection, nodes: D3.Layout.GraphNode[], labelSettings: VisualDataLabelsSettings, layout: ITreemapLayout): D3.UpdateSelection {\r\n let labels = context\r\n .selectAll('.' + Treemap.MajorLabelClassName)\r\n .data(nodes, (d: TreemapNode) => d.key);\r\n\r\n labels.enter().append('text')\r\n .attr('class', layout.majorLabelClass);\r\n\r\n labels\r\n .text(layout.majorLabelText)\r\n .style('fill', () => labelSettings.labelColor)\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(layout.majorLabelLayout);\r\n\r\n labels.exit().remove();\r\n\r\n return labels;\r\n }\r\n\r\n private animateDefaultMinorLabels(context: D3.Selection, nodes: D3.Layout.GraphNode[], labelSettings: VisualDataLabelsSettings, layout: ITreemapLayout): D3.UpdateSelection {\r\n let labels = context\r\n .selectAll('.' + Treemap.MinorLabelClassName)\r\n .data(nodes, (d: TreemapNode) => d.key);\r\n\r\n labels.enter().append('text')\r\n .attr('class', layout.minorLabelClass);\r\n\r\n labels\r\n .text(layout.minorLabelText)\r\n .style('fill', () => labelSettings.labelColor)\r\n .transition()\r\n .duration(this.animationDuration)\r\n .attr(layout.minorLabelLayout);\r\n\r\n labels.exit().remove();\r\n\r\n return labels;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n /**\r\n * This is the baseline for some most common used object properties across visuals.\r\n * When adding new properties, please try to reuse the existing ones.\r\n */\r\n export const StandardObjectProperties = {\r\n axisEnd: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_End'),\r\n description: data.createDisplayNameGetter('Visual_Axis_EndDescription'),\r\n placeHolderText: data.createDisplayNameGetter('Visual_Precision_Auto'),\r\n type: { numeric: true },\r\n suppressFormatPainterCopy: true,\r\n },\r\n axisScale: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Scale'),\r\n type: { enumeration: axisScale.type }\r\n },\r\n axisStart: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Start'),\r\n description: data.createDisplayNameGetter('Visual_Axis_StartDescription'),\r\n placeHolderText: data.createDisplayNameGetter('Visual_Precision_Auto'),\r\n type: { numeric: true },\r\n suppressFormatPainterCopy: true,\r\n },\r\n axisStyle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Style'),\r\n type: { enumeration: axisStyle.type }\r\n },\r\n axisType: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Type'),\r\n type: { enumeration: axisType.type },\r\n },\r\n backColor: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_BackColor'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_BackColor_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n dataColor: {\r\n displayName: data.createDisplayNameGetter('Visual_LabelsFill'),\r\n description: data.createDisplayNameGetter('Visual_LabelsFillDescription'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n dataLabelColor: {\r\n displayName: data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Label_Color\"),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Color_Description'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n dataLabelDecimalPoints: {\r\n displayName: data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Decimal_Points\"),\r\n placeHolderText: data.createDisplayNameGetter('Visual_Precision_Auto'),\r\n type: { numeric: true }\r\n },\r\n dataLabelDisplayUnits: {\r\n displayName: data.createDisplayNameGetter('Visual_DisplayUnits'),\r\n description: data.createDisplayNameGetter('Visual_DisplayUnitsDescription'),\r\n type: { formatting: { labelDisplayUnits: true } },\r\n suppressFormatPainterCopy: true,\r\n },\r\n dataLabelHorizontalPosition: {\r\n displayName: data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Horizontal_Position\"),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Horizontal_Position_Description'),\r\n type: { enumeration: referenceLineDataLabelHorizontalPosition.type }\r\n },\r\n dataLabelShow: {\r\n displayName: data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Label\"),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Show_Description'),\r\n type: { bool: true }\r\n },\r\n dataLabelVerticalPosition: {\r\n displayName: data.createDisplayNameGetter(\"Visual_Reference_Line_Data_Vertical_Position\"),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Data_Label_Vertical_Position_Description'),\r\n type: { enumeration: referenceLineDataLabelVerticalPosition.type }\r\n },\r\n defaultColor: {\r\n displayName: data.createDisplayNameGetter('Visual_DefaultColor'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n fill: {\r\n displayName: data.createDisplayNameGetter('Visual_Fill'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n fontColor: {\r\n displayName: data.createDisplayNameGetter('Visual_FontColor'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_FontColor_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n fontSize: {\r\n displayName: data.createDisplayNameGetter('Visual_TextSize'),\r\n type: { formatting: { fontSize: true } }\r\n },\r\n formatString: {\r\n type: { formatting: { formatString: true } },\r\n },\r\n image: {\r\n type: { image: {} },\r\n },\r\n labelColor: {\r\n displayName: data.createDisplayNameGetter('Visual_LegendTitleColor'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n labelDisplayUnits: {\r\n displayName: data.createDisplayNameGetter('Visual_DisplayUnits'),\r\n description: data.createDisplayNameGetter('Visual_DisplayUnitsDescription'),\r\n type: { formatting: { labelDisplayUnits: true } }\r\n },\r\n labelPrecision: {\r\n displayName: data.createDisplayNameGetter('Visual_Precision'),\r\n description: data.createDisplayNameGetter('Visual_PrecisionDescription'),\r\n placeHolderText: data.createDisplayNameGetter('Visual_Precision_Auto'),\r\n type: { numeric: true }\r\n },\r\n legendPosition: {\r\n displayName: data.createDisplayNameGetter('Visual_LegendPosition'),\r\n description: data.createDisplayNameGetter('Visual_LegendPositionDescription'),\r\n type: { enumeration: legendPosition.type },\r\n },\r\n legendTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_LegendName'),\r\n description: data.createDisplayNameGetter('Visual_LegendNameDescription'),\r\n type: { text: true },\r\n },\r\n lineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Color'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Color_Description'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n outline: {\r\n displayName: data.createDisplayNameGetter('Visual_Outline'),\r\n type: { enumeration: outline.type }\r\n },\r\n outlineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_OutlineColor'),\r\n description: data.createDisplayNameGetter('Visual_OutlineColor_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n outlineWeight: {\r\n displayName: data.createDisplayNameGetter('Visual_OutlineWeight'),\r\n description: data.createDisplayNameGetter('Visual_OutlineWeight_Desc'),\r\n type: { numeric: true }\r\n },\r\n show: {\r\n displayName: data.createDisplayNameGetter('Visual_Show'),\r\n type: { bool: true }\r\n },\r\n showAllDataPoints: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint_Show_All'),\r\n type: { bool: true }\r\n },\r\n showLegendTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_LegendShowTitle'),\r\n description: data.createDisplayNameGetter('Visual_LegendShowTitleDescription'),\r\n type: { bool: true }\r\n },\r\n referenceLinePosition: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Arrange'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Arrange_Description'),\r\n type: { enumeration: referenceLinePosition.type }\r\n },\r\n referenceLineStyle: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Style'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Style_Description'),\r\n type: { enumeration: lineStyle.type }\r\n },\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Background_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Background_TransparencyDescription'),\r\n type: { numeric: true }\r\n },\r\n yAxisPosition: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis_Position'),\r\n description: data.createDisplayNameGetter('Visual_YAxis_PositionDescription'),\r\n type: { enumeration: yAxisPosition.type },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const animatedTextObjectDescs: data.DataViewObjectDescriptors = {\r\n general: {\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n }\r\n };\r\n\r\n export const animatedNumberCapabilities: VisualCapabilities = {\r\n objects: animatedTextObjectDescs,\r\n dataViewMappings: [{\r\n single: { role: \"Values\" }\r\n }],\r\n supportsSelection: false,\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const basicShapeCapabilities: VisualCapabilities = {\r\n objects: {\r\n line: {\r\n displayName: data.createDisplayNameGetter('Visual_BasicShape_Line'),\r\n properties: {\r\n lineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_BasicShape_LineColor'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n transparency: StandardObjectProperties.transparency,\r\n weight: {\r\n displayName: data.createDisplayNameGetter('Visual_BasicShape_Weight'),\r\n type: { numeric: true }\r\n },\r\n roundEdge: {\r\n displayName: data.createDisplayNameGetter('Visual_BasicShape_RoundEdges'),\r\n type: { numeric: true }\r\n }\r\n }\r\n },\r\n fill: {\r\n displayName: data.createDisplayNameGetter('Visual_Fill'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n fillColor: {\r\n displayName: data.createDisplayNameGetter('Visual_BasicShape_FillColor'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n transparency: StandardObjectProperties.transparency,\r\n }\r\n },\r\n rotation: {\r\n displayName: data.createDisplayNameGetter('Visual_BasicShape_Rotate'),\r\n properties: {\r\n angle: {\r\n displayName: data.createDisplayNameGetter('Visual_BasicShape_Rotate'),\r\n type: { numeric: true }\r\n }\r\n }\r\n },\r\n general: {\r\n properties: {\r\n shapeType: {\r\n type: { text: true },\r\n suppressFormatPainterCopy: true,\r\n }\r\n }\r\n }\r\n },\r\n suppressDefaultTitle: true,\r\n suppressDefaultPadding: true,\r\n canRotate: false,\r\n supportsSelection: false,\r\n };\r\n\r\n export const basicShapeProps = {\r\n general: {\r\n shapeType: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'shapeType' },\r\n },\r\n line: {\r\n transparency: <DataViewObjectPropertyIdentifier>{ objectName: 'line', propertyName: 'transparency' },\r\n weight: <DataViewObjectPropertyIdentifier>{ objectName: 'line', propertyName: 'weight' },\r\n roundEdge: <DataViewObjectPropertyIdentifier>{ objectName: 'line', propertyName: 'roundEdge' },\r\n lineColor: <DataViewObjectPropertyIdentifier>{ objectName: 'line', propertyName: 'lineColor' }\r\n },\r\n fill: {\r\n transparency: <DataViewObjectPropertyIdentifier>{ objectName: 'fill', propertyName: 'transparency' },\r\n fillColor: <DataViewObjectPropertyIdentifier>{ objectName: 'fill', propertyName: 'fillColor' },\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'fill', propertyName: 'show' }\r\n },\r\n rotation: {\r\n angle: <DataViewObjectPropertyIdentifier>{ objectName: 'rotation', propertyName: 'angle' }\r\n }\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export function getColumnChartCapabilities(transposeAxes: boolean = false): VisualCapabilities {\r\n return {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Axis'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_AxisDescription'),\r\n cartesianKind: CartesianRoleKind.X,\r\n }, {\r\n name: 'Series',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Legend'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Value'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n cartesianKind: CartesianRoleKind.Y,\r\n }, {\r\n name: 'Gradient',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Gradient'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: $.extend({}, StandardObjectProperties.legendTitle, {\r\n suppressFormatPainterCopy: true\r\n }),\r\n labelColor: StandardObjectProperties.labelColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n categoryAxis: {\r\n displayName: transposeAxes ? data.createDisplayNameGetter('Visual_YAxis') : data.createDisplayNameGetter('Visual_XAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.yAxisPosition,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n axisType: StandardObjectProperties.axisType,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: transposeAxes ? data.createDisplayNameGetter('Visual_Axis_YTitleDescription') : data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n valueAxis: {\r\n displayName: transposeAxes ? data.createDisplayNameGetter('Visual_XAxis') : data.createDisplayNameGetter('Visual_YAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.yAxisPosition,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n intersection: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Intersection'),\r\n type: { numeric: true },\r\n placeHolderText: data.createDisplayNameGetter('Visual_Precision_Auto'),\r\n },\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: transposeAxes ? data.createDisplayNameGetter('Visual_Axis_YTitleDescription') : data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n y1AxisReferenceLine: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Description'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n value: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Value'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\r\n type: { numeric: true }\r\n },\r\n lineColor: StandardObjectProperties.lineColor,\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: StandardObjectProperties.referenceLineStyle,\r\n position: StandardObjectProperties.referenceLinePosition,\r\n dataLabelShow: StandardObjectProperties.dataLabelShow,\r\n dataLabelColor: StandardObjectProperties.dataLabelColor,\r\n dataLabelDecimalPoints: StandardObjectProperties.dataLabelDecimalPoints,\r\n dataLabelHorizontalPosition: StandardObjectProperties.dataLabelHorizontalPosition,\r\n dataLabelVerticalPosition: StandardObjectProperties.dataLabelVerticalPosition,\r\n dataLabelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n },\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: StandardObjectProperties.defaultColor,\r\n showAllDataPoints: StandardObjectProperties.showAllDataPoints,\r\n fill: StandardObjectProperties.fill,\r\n fillRule: {\r\n displayName: data.createDisplayNameGetter('Visual_Gradient'),\r\n type: { fillRule: {} },\r\n rule: {\r\n inputRole: 'Gradient',\r\n output: {\r\n property: 'fill',\r\n selector: ['Category'],\r\n },\r\n },\r\n }\r\n }\r\n },\r\n trend: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line'),\r\n properties: {\r\n show: {\r\n type: { bool: true }\r\n },\r\n lineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Color'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Style'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\r\n type: { enumeration: lineStyle.type }\r\n },\r\n combineSeries: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\r\n type: { bool: true }\r\n },\r\n useHighlightValues: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues_Description'),\r\n type: { bool: true }\r\n },\r\n }\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n description: data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n showSeries: {\r\n displayName: data.createDisplayNameGetter('Visual_Show'),\r\n type: { bool: true }\r\n },\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n labelPrecision: $.extend({}, StandardObjectProperties.labelPrecision, {\r\n suppressFormatPainterCopy: true\r\n }),\r\n showAll: {\r\n displayName: data.createDisplayNameGetter('Visual_LabelSeriesShowAll'), \r\n type: { bool: true } \r\n },\r\n fontSize: StandardObjectProperties.fontSize,\r\n },\r\n },\r\n plotArea: {\r\n displayName: data.createDisplayNameGetter('Visual_Plot'),\r\n //description: data.createDisplayNameGetter('Visual_PlotDescription'),\r\n properties: {\r\n transparency: StandardObjectProperties.transparency,\r\n image: StandardObjectProperties.image,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Gradient': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 }, 'Gradient': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Y': { min: 0, max: 1 }, 'Gradient': { max: 1 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [{ for: { in: 'Y' } }, { bind: { to: 'Gradient' } }],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 }, supported: { min: 0 } }\r\n },\r\n }, {\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Gradient': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 }, 'Gradient': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Y': { min: 0, max: 1 }, 'Gradient': { max: 1 } },\r\n ],\r\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\r\n usage: {\r\n regression: {\r\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\r\n },\r\n },\r\n categorical: {\r\n categories: {\r\n for: { in: 'regression.X' },\r\n },\r\n values: {\r\n group: {\r\n by: 'regression.Series',\r\n select: [{ for: { in: 'regression.Y' } }],\r\n },\r\n }\r\n }\r\n }],\r\n supportsHighlight: true,\r\n sorting: {\r\n default: {},\r\n },\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n }\r\n\r\n export const columnChartProps = {\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'defaultColor' },\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n showAllDataPoints: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\r\n },\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n categoryAxis: {\r\n axisType: <DataViewObjectPropertyIdentifier>{ objectName: 'categoryAxis', propertyName: 'axisType' },\r\n },\r\n legend: {\r\n labelColor: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'labelColor' },\r\n },\r\n plotArea: {\r\n image: <DataViewObjectPropertyIdentifier>{ objectName: 'plotArea', propertyName: 'image' },\r\n transparency: <DataViewObjectPropertyIdentifier>{ objectName: 'plotArea', propertyName: 'transparency' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const comboChartCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_ComboChart_Category'),\r\n description: data.createDisplayNameGetter('Role_ComboChart_CategoryDescription'),\r\n cartesianKind: CartesianRoleKind.X,\r\n }, {\r\n name: 'Series',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_ComboChart_Series'),\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_ComboChart_Y'),\r\n description: data.createDisplayNameGetter('Role_ComboChart_YDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n cartesianKind: CartesianRoleKind.Y,\r\n }, {\r\n name: 'Y2',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_ComboChart_Y2'),\r\n description: data.createDisplayNameGetter('Role_ComboChart_Y2Description'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n cartesianKind: CartesianRoleKind.Y,\r\n },\r\n ],\r\n objects: {\r\n general: {\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n visualType1: {\r\n type: { text: true }\r\n },\r\n visualType2: {\r\n type: { text: true }\r\n },\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: $.extend({}, StandardObjectProperties.legendTitle, {\r\n suppressFormatPainterCopy: true\r\n }),\r\n labelColor: StandardObjectProperties.labelColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n categoryAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_XAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n axisType: StandardObjectProperties.axisType,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n valueAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n axisLabel: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis_ColumnTitle'),\r\n type: { none: true },\r\n },\r\n position: StandardObjectProperties.yAxisPosition,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n secShow: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis_ShowSecondary'),\r\n type: { bool: true },\r\n },\r\n secAxisLabel: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis_LineTitle'),\r\n type: { none: true },\r\n },\r\n secPosition: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis_Position'),\r\n type: { enumeration: yAxisPosition.type },\r\n },\r\n secAxisScale: StandardObjectProperties.axisScale,\r\n secStart: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Start'),\r\n description: data.createDisplayNameGetter('Visual_Axis_StartDescription'),\r\n type: { numeric: true },\r\n },\r\n secEnd: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_End'),\r\n description: data.createDisplayNameGetter('Visual_Axis_EndDescription'),\r\n type: { numeric: true },\r\n },\r\n secShowAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\r\n type: { bool: true },\r\n },\r\n secAxisStyle: StandardObjectProperties.axisStyle,\r\n secLabelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n secLabelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: $.extend({}, StandardObjectProperties.defaultColor, {\r\n displayName: data.createDisplayNameGetter('Visual_DefaultColumnColor'),\r\n }),\r\n showAllDataPoints: StandardObjectProperties.showAllDataPoints,\r\n fill: StandardObjectProperties.fill,\r\n fillRule: {\r\n displayName: data.createDisplayNameGetter('Visual_Gradient'),\r\n type: { fillRule: {} },\r\n rule: {\r\n inputRole: 'Gradient',\r\n output: {\r\n property: 'fill',\r\n selector: ['Category'],\r\n },\r\n },\r\n }\r\n }\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n description: data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n labelPrecision: $.extend({}, StandardObjectProperties.labelPrecision, {\r\n suppressFormatPainterCopy: true,\r\n }),\r\n fontSize: StandardObjectProperties.fontSize,\r\n },\r\n },\r\n plotArea: {\r\n displayName: data.createDisplayNameGetter('Visual_Plot'),\r\n properties: {\r\n transparency: StandardObjectProperties.transparency,\r\n image: StandardObjectProperties.image,\r\n },\r\n },\r\n trend: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line'),\r\n properties: {\r\n show: {\r\n type: { bool: true }\r\n },\r\n lineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Color'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Style'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\r\n type: { enumeration: lineStyle.type }\r\n },\r\n combineSeries: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\r\n type: { bool: true }\r\n },\r\n useHighlightValues: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues_Description'),\r\n type: { bool: true }\r\n },\r\n }\r\n },\r\n },\r\n dataViewMappings: [\r\n {\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [\r\n { for: { in: 'Y' } }\r\n ],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 }, supported: { min: 0 } }\r\n }\r\n }, {\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'Y2': { min: 1 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 }, 'Y2': { min: 1 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n select: [\r\n { for: { in: 'Y2' } }\r\n ],\r\n },\r\n rowCount: { preferred: { min: 2 }, supported: { min: 0 } }\r\n },\r\n }, {\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } },\r\n ],\r\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\r\n usage: {\r\n regression: {\r\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\r\n },\r\n },\r\n categorical: {\r\n categories: {\r\n for: { in: 'regression.X' }\r\n },\r\n values: {\r\n group: {\r\n by: 'regression.Series',\r\n select: [{ for: { in: 'regression.Y' } }],\r\n },\r\n },\r\n }\r\n },\r\n ],\r\n supportsHighlight: true,\r\n sorting: {\r\n default: {},\r\n },\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n\r\n export const comboChartProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n valueAxis: {\r\n secShow: <DataViewObjectPropertyIdentifier>{ objectName: 'valueAxis', propertyName: 'secShow' },\r\n },\r\n legend: {\r\n labelColor: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'labelColor' },\r\n },\r\n dataPoint: {\r\n showAllDataPoints: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const donutChartCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Legend'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\r\n }, {\r\n name: 'Series',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Details'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_DetailsDonutChartDescription'),\r\n\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }\r\n ],\r\n objects:{ \r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: $.extend({}, StandardObjectProperties.legendTitle, {\r\n suppressFormatPainterCopy: true\r\n }),\r\n labelColor: StandardObjectProperties.labelColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: StandardObjectProperties.defaultColor,\r\n fill: StandardObjectProperties.fill,\r\n }\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DetailLabels'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n labelPrecision: $.extend({}, StandardObjectProperties.labelPrecision, {\r\n suppressFormatPainterCopy: true,\r\n }),\r\n fontSize: $.extend({}, StandardObjectProperties.fontSize, {\r\n suppressFormatPainterCopy: true,\r\n }),\r\n labelStyle: {\r\n displayName: data.createDisplayNameGetter('Visual_LabelStyle'),\r\n type: { enumeration: labelStyle.type }\r\n },\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } }\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [{ bind: { to: 'Y' } }],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 }, supported: { min: 1 } }\r\n },\r\n }],\r\n sorting: {\r\n default: {},\r\n },\r\n supportsHighlight: true,\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n\r\n export const donutChartProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'defaultColor' },\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n },\r\n legend: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'show' },\r\n position: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'position' },\r\n showTitle: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'showTitle' },\r\n titleText: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'titleText' },\r\n labelColor: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'labelColor' },\r\n }, \r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n // I support a categorical (ordinal) X with measure Y for a single series\r\n export const dataDotChartCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Axis'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_AxisDescription')\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Value'),\r\n requiredTypes: [{ numeric: true }, { integer: true }]\r\n },\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Y': { max: 1 } }\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n select: [{\r\n for: { in: 'Y' },\r\n dataReductionAlgorithm: { top: {} }\r\n }]\r\n },\r\n },\r\n }]\r\n };\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const filledMapCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Location'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LocationFilledMapDescription'),\r\n preferredTypes: [\r\n { geography: { address: true } },\r\n { geography: { city: true } },\r\n { geography: { continent: true } },\r\n { geography: { country: true } },\r\n { geography: { county: true } },\r\n { geography: { place: true } },\r\n { geography: { postalCode: true } },\r\n { geography: { region: true } },\r\n { geography: { stateOrProvince: true } },\r\n ],\r\n }, {\r\n name: 'Series',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Legend'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\r\n }, {\r\n name: 'X',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Longitude'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LongitudeFilledMapDescription'),\r\n preferredTypes: [\r\n { geography: { longitude: true } }\r\n ],\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Latitude'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LatitudeFilledMapDescription'),\r\n preferredTypes: [\r\n { geography: { latitude: true } }\r\n ],\r\n }, {\r\n name: 'Size',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Gradient'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: StandardObjectProperties.legendTitle,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: StandardObjectProperties.defaultColor,\r\n showAllDataPoints: StandardObjectProperties.showAllDataPoints,\r\n fill: StandardObjectProperties.fill,\r\n fillRule: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\r\n type: { fillRule: {} },\r\n rule: {\r\n inputRole: 'Size',\r\n output: {\r\n property: 'fill',\r\n selector: ['Category'],\r\n },\r\n },\r\n }\r\n }\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n },\r\n },\r\n categoryLabels: {\r\n displayName: data.createDisplayNameGetter('Visual_CategoryLabels'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n },\r\n }\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 } },\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 } }\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [\r\n { bind: { to: 'X' } },\r\n { bind: { to: 'Y' } },\r\n { bind: { to: 'Size' } },\r\n ],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 } },\r\n dataVolume: 4,\r\n },\r\n }],\r\n sorting: {\r\n custom: {},\r\n },\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n\r\n export const filledMapProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'defaultColor' },\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n showAllDataPoints: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\r\n },\r\n legend: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'show' },\r\n position: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'position' },\r\n showTitle: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'showTitle' },\r\n titleText: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'titleText' },\r\n },\r\n labels: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'show' },\r\n color: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'color' },\r\n labelDisplayUnits: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'labelDisplayUnits' },\r\n labelPrecision: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'labelPrecision' },\r\n },\r\n categoryLabels: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'categoryLabels', propertyName: 'show' },\r\n }\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const funnelChartCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Group'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GroupFunnelDescription')\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: 'Gradient',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Gradient'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }\r\n ],\r\n dataViewMappings: [{\r\n conditions: [\r\n // NOTE: Ordering of the roles prefers to add measures to Y before Gradient.\r\n { 'Category': { max: 0 }, 'Gradient': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Y': { max: 1 }, 'Gradient': { max: 1 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n select: [{ for: { in: 'Y' } }, { bind: { to: 'Gradient' } }],\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n rowCount: { preferred: { min: 1 } }\r\n },\r\n }],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: StandardObjectProperties.defaultColor,\r\n fill: StandardObjectProperties.fill,\r\n fillRule: {\r\n displayName: data.createDisplayNameGetter('Visual_Gradient'),\r\n type: { fillRule: {} },\r\n rule: {\r\n inputRole: 'Gradient',\r\n output: {\r\n property: 'fill',\r\n selector: ['Category'],\r\n },\r\n },\r\n }\r\n }\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n description: data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelPosition: {\r\n displayName: data.createDisplayNameGetter('Visual_Position'),\r\n type: { enumeration: labelPosition.type },\r\n suppressFormatPainterCopy: true,\r\n },\r\n labelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n labelPrecision: $.extend({}, StandardObjectProperties.labelPrecision, {\r\n suppressFormatPainterCopy: true,\r\n }),\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n percentBarLabel: {\r\n displayName: data.createDisplayNameGetter('Visual_PercentBarLabel'),\r\n description: data.createDisplayNameGetter('Visual_PercentBarLabelDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n },\r\n supportsHighlight: true,\r\n sorting: {\r\n default: {},\r\n },\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n\r\n export const funnelChartProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'defaultColor' },\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const gaugeRoleNames = {\r\n y: 'Y',\r\n minValue: 'MinValue',\r\n maxValue: 'MaxValue',\r\n targetValue: 'TargetValue'\r\n };\r\n\r\n export const gaugeCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: gaugeRoleNames.y,\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Value'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_ValueDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: gaugeRoleNames.minValue,\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_MinValue'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_MinValueDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: gaugeRoleNames.maxValue,\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_MaxValue'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_MaxValueDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: gaugeRoleNames.targetValue,\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_TargetValue'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_TargetValueDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n axis: {\r\n displayName: data.createDisplayNameGetter('Visual_Gauge_Axis'),\r\n properties: {\r\n min: {\r\n displayName: data.createDisplayNameGetter('Visual_Gauge_Axis_Min'),\r\n type: { numeric: true }\r\n },\r\n max: {\r\n displayName: data.createDisplayNameGetter('Visual_Gauge_Axis_Max'),\r\n type: { numeric: true }\r\n },\r\n target: {\r\n displayName: data.createDisplayNameGetter('Visual_Gauge_Axis_Target'),\r\n type: { numeric: true }\r\n },\r\n },\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n fontSize: StandardObjectProperties.fontSize,\r\n },\r\n },\r\n calloutValue: {\r\n displayName: data.createDisplayNameGetter('Visual_Gauge_CalloutValue'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n },\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n properties: {\r\n fill: StandardObjectProperties.fill,\r\n target: {\r\n // TODO find a better string\r\n displayName: data.createDisplayNameGetter('Visual_Gauge_Axis_Target'),\r\n type: { fill: { solid: { color: true } } }\r\n }\r\n }\r\n }\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Y': { max: 1 }, 'MinValue': { max: 1 }, 'MaxValue': { max: 1 }, 'TargetValue': { max: 1 } },\r\n ],\r\n categorical: {\r\n values: {\r\n select: [\r\n { bind: { to: 'Y' } },\r\n { bind: { to: 'MinValue' } },\r\n { bind: { to: 'MaxValue' } },\r\n { bind: { to: 'TargetValue' } },\r\n ]\r\n },\r\n },\r\n }],\r\n supportsSelection: false,\r\n };\r\n\r\n export const gaugeProps = {\r\n dataPoint: {\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n target: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'target' }\r\n }\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const imageVisualCapabilities: VisualCapabilities = {\r\n objects: {\r\n general: {\r\n properties: {\r\n imageUrl: {\r\n type: { misc: { imageUrl: true } }\r\n }\r\n }\r\n },\r\n imageScaling: {\r\n displayName: data.createDisplayNameGetter('Visual_Image_Scaling_Type'),\r\n properties: {\r\n imageScalingType: {\r\n displayName: data.createDisplayNameGetter('Visual_Image_Scaling_Type'),\r\n type: { enumeration: imageScalingType.type }\r\n },\r\n }\r\n },\r\n },\r\n suppressDefaultTitle: true,\r\n supportsSelection: false,\r\n };\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export var scriptVisualCapabilities: VisualCapabilities = {\r\n dataRoles: [{\r\n name: 'Values',\r\n kind: VisualDataRoleKind.GroupingOrMeasure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values'),\r\n }],\r\n dataViewMappings: [{\r\n scriptResult: {\r\n dataInput: {\r\n table: {\r\n rows: {\r\n for: {\r\n in: 'Values'\r\n },\r\n dataReductionAlgorithm: {\r\n top: {}\r\n }\r\n },\r\n },\r\n },\r\n script: {\r\n source: {\r\n objectName: 'script',\r\n propertyName: 'source'\r\n },\r\n provider: {\r\n objectName: 'script',\r\n propertyName: 'provider'\r\n },\r\n }\r\n }\r\n }],\r\n objects: {\r\n script: {\r\n properties: {\r\n provider: {\r\n type: { text: true }\r\n },\r\n source: {\r\n type: { scripting: { source: true }\r\n }\r\n },\r\n }\r\n },\r\n },\r\n };\r\n} ","\r\n/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.visuals.samples {\r\n export var consoleWriterCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Axis'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_AxisDescription')\r\n },\r\n {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Y'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_YDescription')\r\n },\r\n ],\r\n dataViewMappings: [{\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n },\r\n },\r\n }],\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.samples {\r\n\r\n export class ConsoleWriter implements IVisual {\r\n\r\n public static converter(dataView: DataView): any {\r\n window.console.log('converter');\r\n window.console.log(dataView);\r\n\r\n return {};\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n let div = d3.select(options.element.get(0)).append(\"div\");\r\n \r\n div.append(\"h1\").text(\"ConsoleWriter\");\r\n div.append(\"p\").text(\"This IVisual writes messages passed to it to the javscript console output. Check your console for the actual messages passed. For more information, click below\");\r\n let anchor = div.append('a');\r\n anchor.attr('href', \"http://microsoft.github.io/PowerBI-visuals/modules/powerbi.html\")\r\n .text(\"Online help\");\r\n\r\n window.console.log('init');\r\n window.console.log(options);\r\n }\r\n\r\n public onResizing(viewport: IViewport) { /* This API will be depricated */ }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n window.console.log('update');\r\n window.console.log(options);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const lineChartCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Axis'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_AxisDescription'),\r\n cartesianKind: CartesianRoleKind.X,\r\n }, {\r\n name: 'Series',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Legend'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n cartesianKind: CartesianRoleKind.Y,\r\n },\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: $.extend({}, StandardObjectProperties.legendTitle, {\r\n suppressFormatPainterCopy: true\r\n }),\r\n labelColor: StandardObjectProperties.labelColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: StandardObjectProperties.defaultColor,\r\n fill: StandardObjectProperties.fill,\r\n }\r\n },\r\n trend: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n lineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Color'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Style'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\r\n type: { enumeration: lineStyle.type }\r\n },\r\n combineSeries: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\r\n type: { bool: true }\r\n },\r\n useHighlightValues: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_UseHighlightValues_Description'),\r\n type: { bool: true }\r\n },\r\n }\r\n },\r\n categoryAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_XAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n axisType: StandardObjectProperties.axisType,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n valueAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.yAxisPosition,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n y1AxisReferenceLine: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Description'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n value: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Value'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\r\n type: { numeric: true }\r\n },\r\n lineColor: StandardObjectProperties.lineColor,\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: StandardObjectProperties.referenceLineStyle,\r\n position: StandardObjectProperties.referenceLinePosition,\r\n dataLabelShow: StandardObjectProperties.dataLabelShow,\r\n dataLabelColor: StandardObjectProperties.dataLabelColor,\r\n dataLabelDecimalPoints: StandardObjectProperties.dataLabelDecimalPoints,\r\n dataLabelHorizontalPosition: StandardObjectProperties.dataLabelHorizontalPosition,\r\n dataLabelVerticalPosition: StandardObjectProperties.dataLabelVerticalPosition,\r\n dataLabelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n },\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n description: data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n showSeries: {\r\n displayName: data.createDisplayNameGetter('Visual_Show'),\r\n type: { bool: true }\r\n },\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n labelPrecision: $.extend({}, StandardObjectProperties.labelPrecision, {\r\n suppressFormatPainterCopy: true,\r\n }),\r\n showAll: {\r\n displayName: data.createDisplayNameGetter('Visual_LabelSeriesShowAll'),\r\n type: { bool: true }\r\n },\r\n fontSize: StandardObjectProperties.fontSize,\r\n labelDensity: {\r\n displayName: data.createDisplayNameGetter('Visual_LabelDensity'),\r\n type: { formatting: { labelDensity: true } },\r\n },\r\n },\r\n },\r\n plotArea: {\r\n displayName: data.createDisplayNameGetter('Visual_Plot'),\r\n //description: data.createDisplayNameGetter('Visual_PlotDescription'),\r\n properties: {\r\n transparency: StandardObjectProperties.transparency,\r\n image: StandardObjectProperties.image,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } }\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [{ for: { in: 'Y' } }],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n },\r\n }, {\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { min: 1, max: 1 }, 'Y': { max: 1 } }\r\n ],\r\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\r\n usage: {\r\n regression: {\r\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\r\n },\r\n },\r\n categorical: {\r\n categories: {\r\n for: { in: 'regression.X' },\r\n },\r\n values: {\r\n group: {\r\n by: 'regression.Series',\r\n select: [{ for: {in: 'regression.Y' } }],\r\n },\r\n }\r\n }\r\n }],\r\n sorting: {\r\n default: {},\r\n },\r\n };\r\n\r\n export const lineChartProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'defaultColor' },\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n },\r\n trend: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'trend', propertyName: 'show' },\r\n },\r\n categoryAxis: {\r\n axisType: <DataViewObjectPropertyIdentifier>{ objectName: 'categoryAxis', propertyName: 'axisType' },\r\n },\r\n legend: {\r\n labelColor: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'labelColor' },\r\n },\r\n labels: {\r\n labelDensity: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'labelDensity' },\r\n },\r\n plotArea: {\r\n image: <DataViewObjectPropertyIdentifier>{ objectName: 'plotArea', propertyName: 'image' },\r\n transparency: <DataViewObjectPropertyIdentifier>{ objectName: 'plotArea', propertyName: 'transparency' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const mapCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Location'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LocationMapDescription'),\r\n preferredTypes: [\r\n { geography: { address: true } },\r\n { geography: { city: true } },\r\n { geography: { continent: true } },\r\n { geography: { country: true } },\r\n { geography: { county: true } },\r\n { geography: { place: true } },\r\n { geography: { postalCode: true } },\r\n { geography: { region: true } },\r\n { geography: { stateOrProvince: true } },\r\n ],\r\n }, {\r\n name: 'Series',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Legend'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\r\n }, {\r\n name: 'X',\r\n kind: VisualDataRoleKind.GroupingOrMeasure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Longitude'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LongitudeMapDescription'),\r\n preferredTypes: [\r\n { geography: { longitude: true } }\r\n ],\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.GroupingOrMeasure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Latitude'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LatitudeMapDescription'),\r\n preferredTypes: [\r\n { geography: { latitude: true } }\r\n ],\r\n }, {\r\n name: 'Size',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Size'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_SizeDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: 'Gradient',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Gradient'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: StandardObjectProperties.legendTitle,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: StandardObjectProperties.defaultColor,\r\n showAllDataPoints: StandardObjectProperties.showAllDataPoints,\r\n fill: StandardObjectProperties.fill,\r\n fillRule: {\r\n displayName: data.createDisplayNameGetter('Visual_Gradient'),\r\n type: { fillRule: {} },\r\n rule: {\r\n inputRole: 'Gradient',\r\n output: {\r\n property: 'fill',\r\n selector: ['Category'],\r\n },\r\n },\r\n }\r\n }\r\n },\r\n categoryLabels: {\r\n displayName: data.createDisplayNameGetter('Visual_CategoryLabels'),\r\n description: data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { min: 1, max: 1 }, 'Series': { max: 1 }, 'X': { max: 1, kind: VisualDataRoleKind.Measure }, 'Y': { max: 1, kind: VisualDataRoleKind.Measure }, 'Size': { max: 1 }, 'Gradient': { max: 0 } },\r\n { 'Category': { min: 1, max: 1 }, 'Series': { max: 0 }, 'X': { max: 1, kind: VisualDataRoleKind.Measure }, 'Y': { max: 1, kind: VisualDataRoleKind.Measure }, 'Size': { max: 1 }, 'Gradient': { max: 1 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [\r\n { bind: { to: 'X' } },\r\n { bind: { to: 'Y' } },\r\n { bind: { to: 'Size' } },\r\n { bind: { to: 'Gradient' } },\r\n ],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 } },\r\n dataVolume: 4,\r\n }\r\n }, {\r\n conditions: [\r\n { 'Category': { max: 0 }, 'Series': { max: 1 }, 'X': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Y': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Size': { max: 1 }, 'Gradient': { max: 0 } },\r\n { 'Category': { max: 0 }, 'Series': { max: 0 }, 'X': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Y': { max: 1, kind: VisualDataRoleKind.Grouping }, 'Size': { max: 1 }, 'Gradient': { max: 1 } }\r\n ],\r\n categorical: {\r\n categories: {\r\n select: [\r\n { bind: { to: 'X' } },\r\n { bind: { to: 'Y' } },\r\n ],\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [\r\n { bind: { to: 'Size' } },\r\n { bind: { to: 'Gradient' } },\r\n ],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 } },\r\n dataVolume: 4,\r\n },\r\n }],\r\n sorting: {\r\n custom: {},\r\n },\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n\r\n export const mapProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'defaultColor' },\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n showAllDataPoints: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'showAllDataPoints' },\r\n },\r\n legend: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'show' },\r\n position: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'position' },\r\n showTitle: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'showTitle' },\r\n titleText: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'titleText' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const multiRowCardCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Values',\r\n kind: VisualDataRoleKind.GroupingOrMeasure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Fields'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_FieldsDescription')\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n cardTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_CardTitle'),\r\n description: data.createDisplayNameGetter('Visual_CardTitleDescription'),\r\n properties: {\r\n color: StandardObjectProperties.dataColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n dataLabels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n description: data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\r\n properties: {\r\n color: StandardObjectProperties.dataColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n categoryLabels: {\r\n displayName: data.createDisplayNameGetter('Visual_CategoryLabels'),\r\n description: data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n card: {\r\n displayName: data.createDisplayNameGetter('Card_ToolTip'),\r\n properties: {\r\n outline: {\r\n displayName: data.createDisplayNameGetter('Visual_Outline'),\r\n type: { enumeration: outline.type }\r\n },\r\n outlineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_OutlineColor'),\r\n description: data.createDisplayNameGetter('Visual_OutlineColor_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n outlineWeight: {\r\n displayName: data.createDisplayNameGetter('Visual_OutlineWeight'),\r\n description: data.createDisplayNameGetter('Visual_OutlineWeight_Desc'),\r\n type: { numeric: true }\r\n },\r\n barShow: {\r\n displayName: data.createDisplayNameGetter('Visual_MultiRowCard_BarShow'),\r\n description: data.createDisplayNameGetter('Visual_MultiRowCard_BarShow_Desc'),\r\n type: { bool: true }\r\n },\r\n barColor: {\r\n displayName: data.createDisplayNameGetter('Visual_MultiRowCard_BarColor'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n barWeight: {\r\n displayName: data.createDisplayNameGetter('Visual_MultiRowCard_BarWeight'),\r\n description: data.createDisplayNameGetter('Visual_MultiRowCard_BarWeight_Desc'),\r\n type: { numeric: true }\r\n },\r\n cardPadding: {\r\n displayName: data.createDisplayNameGetter('Visual_MultiRowCard_CardPadding'),\r\n description: data.createDisplayNameGetter('Visual_MultiRowCard_CardBackground'),\r\n type: { numeric: true }\r\n },\r\n cardBackground: {\r\n displayName: data.createDisplayNameGetter('Visual_Background'),\r\n type: { fill: { solid: { color: true } } }\r\n }\r\n }\r\n }\r\n },\r\n dataViewMappings: [{\r\n table: {\r\n rows: {\r\n for: { in: 'Values' },\r\n dataReductionAlgorithm: { window: {} }\r\n },\r\n rowCount: { preferred: { min: 1 } }\r\n },\r\n }],\r\n sorting: {\r\n default: {},\r\n },\r\n suppressDefaultTitle: true,\r\n supportsSelection: false,\r\n disableVisualDetails: true,\r\n };\r\n \r\n export const multiRowCardProps = {\r\n card: {\r\n outline: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'outline' },\r\n outlineColor: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'outlineColor' },\r\n outlineWeight: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'outlineWeight' },\r\n barShow: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'barShow' },\r\n barColor: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'barColor' },\r\n barWeight: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'barWeight' },\r\n cardPadding: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'cardPadding' },\r\n cardBackground: <DataViewObjectPropertyIdentifier>{ objectName: 'card', propertyName: 'cardBackground' },\r\n\r\n }\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const textboxCapabilities: VisualCapabilities = {\r\n objects: {\r\n general: {\r\n properties: {\r\n paragraphs: {\r\n type: { paragraphs: {} },\r\n suppressFormatPainterCopy: true,\r\n }\r\n }\r\n }\r\n },\r\n suppressDefaultTitle: true,\r\n supportsSelection: false,\r\n };\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.visuals {\r\n export const cheerMeterCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Axis'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_AxisDescription')\r\n },\r\n {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Y'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_YDescription')\r\n },\r\n ],\r\n dataViewMappings: [{\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n },\r\n },\r\n }],\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n fill: StandardObjectProperties.fill,\r\n }\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const scatterChartCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Details'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_DetailsScatterChartDescription'),\r\n }, {\r\n name: 'Series',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Legend'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_LegendDescription')\r\n }, {\r\n name: 'X',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_X'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_XScatterChartDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n cartesianKind: CartesianRoleKind.X,\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Y'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_YScatterChartDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n cartesianKind: CartesianRoleKind.Y,\r\n }, {\r\n name: 'Size',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Size'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_SizeDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: 'Gradient',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Gradient'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: 'Play',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Play'),\r\n }\r\n ],\r\n objects: {\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n defaultColor: StandardObjectProperties.defaultColor,\r\n showAllDataPoints: StandardObjectProperties.showAllDataPoints,\r\n fill: StandardObjectProperties.fill,\r\n fillRule: {\r\n displayName: data.createDisplayNameGetter('Visual_Gradient'),\r\n type: { fillRule: {} },\r\n rule: {\r\n inputRole: 'Gradient',\r\n output: {\r\n property: 'fill',\r\n selector: ['Category'],\r\n },\r\n },\r\n }\r\n }\r\n },\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n trend: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n lineColor: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Color'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Color_Description'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Style'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Style_Description'),\r\n type: { enumeration: lineStyle.type }\r\n },\r\n combineSeries: {\r\n displayName: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series'),\r\n description: data.createDisplayNameGetter('Visual_Trend_Line_Combine_Series_Description'),\r\n type: { bool: true }\r\n },\r\n }\r\n },\r\n categoryAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_XAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n valueAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.yAxisPosition,\r\n axisScale: StandardObjectProperties.axisScale,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n xAxisReferenceLine: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_X'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Description'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n value: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Value'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\r\n type: { numeric: true }\r\n },\r\n lineColor: StandardObjectProperties.lineColor,\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: StandardObjectProperties.referenceLineStyle,\r\n position: StandardObjectProperties.referenceLinePosition,\r\n dataLabelShow: StandardObjectProperties.dataLabelShow,\r\n dataLabelColor: StandardObjectProperties.dataLabelColor,\r\n dataLabelDecimalPoints: StandardObjectProperties.dataLabelDecimalPoints,\r\n dataLabelHorizontalPosition: StandardObjectProperties.dataLabelHorizontalPosition,\r\n dataLabelVerticalPosition: StandardObjectProperties.dataLabelVerticalPosition,\r\n dataLabelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n },\r\n },\r\n y1AxisReferenceLine: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Y'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Description'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n value: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Value'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\r\n type: { numeric: true }\r\n },\r\n lineColor: StandardObjectProperties.lineColor,\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: StandardObjectProperties.referenceLineStyle,\r\n position: StandardObjectProperties.referenceLinePosition,\r\n dataLabelShow: StandardObjectProperties.dataLabelShow,\r\n dataLabelColor: StandardObjectProperties.dataLabelColor,\r\n dataLabelDecimalPoints: StandardObjectProperties.dataLabelDecimalPoints,\r\n dataLabelHorizontalPosition: StandardObjectProperties.dataLabelHorizontalPosition,\r\n dataLabelVerticalPosition: StandardObjectProperties.dataLabelVerticalPosition,\r\n dataLabelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: $.extend({}, StandardObjectProperties.legendTitle, {\r\n suppressFormatPainterCopy: true\r\n }),\r\n labelColor: StandardObjectProperties.labelColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n categoryLabels: {\r\n displayName: data.createDisplayNameGetter('Visual_CategoryLabels'),\r\n description: data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n },\r\n },\r\n colorBorder: {\r\n displayName: data.createDisplayNameGetter('Visual_ColorBorder'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n },\r\n },\r\n fillPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_FillPoint'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n },\r\n },\r\n colorByCategory: {\r\n displayName: data.createDisplayNameGetter('Visual_ColorByCategory'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n }\r\n },\r\n currentFrameIndex: {\r\n properties: {\r\n index: {\r\n type: { numeric: true },\r\n }\r\n }\r\n },\r\n plotArea: {\r\n displayName: data.createDisplayNameGetter('Visual_Plot'),\r\n //description: data.createDisplayNameGetter('Visual_PlotDescription'),\r\n properties: {\r\n transparency: StandardObjectProperties.transparency,\r\n image: StandardObjectProperties.image,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 0 }, 'Play': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 1 }, 'Play': { max: 0 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n },\r\n values: {\r\n group: {\r\n by: 'Series',\r\n select: [\r\n { bind: { to: 'X' } },\r\n { bind: { to: 'Y' } },\r\n { bind: { to: 'Size' } },\r\n { bind: { to: 'Gradient' } },\r\n ],\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 } },\r\n dataReductionAlgorithm: { sample: {} },\r\n dataVolume: 4,\r\n }\r\n }, {\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 0 }, 'Play': { min: 1, max: 1 } },\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 1 }, 'Gradient': { max: 1 }, 'Play': { min: 1, max: 1 } },\r\n ],\r\n // Long term: consider adding the 'name' concept and have this be a reference to the other dataViewMapping above.\r\n // Then we'd also move the splitting logic of Matrix->Categorical[] into DataViewTransform, and other visuals would benefit.\r\n matrix: {\r\n rows: {\r\n select: [\r\n { bind: { to: 'Play' } },\r\n { bind: { to: 'Category' } },\r\n ],\r\n /* Explicitly override the server data reduction to make it appropriate for matrix/play. */\r\n dataReductionAlgorithm: { bottom: { count: 5000 } }\r\n },\r\n columns: {\r\n for: { in: 'Series' },\r\n /* Explicitly override the server data reduction to make it appropriate for matrix/play. */\r\n dataReductionAlgorithm: { top: { count: 60 } }\r\n },\r\n values: {\r\n select: [\r\n { bind: { to: 'X' } },\r\n { bind: { to: 'Y' } },\r\n { bind: { to: 'Size' } },\r\n ]\r\n }\r\n }\r\n }, {\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Series': { max: 1 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 0 }, 'Gradient': { max: 0 }, 'Play': { max: 0 } },\r\n { 'Category': { max: 1 }, 'Series': { max: 0 }, 'X': { max: 1 }, 'Y': { max: 1 }, 'Size': { max: 0 }, 'Gradient': { max: 1 }, 'Play': { max: 0 } },\r\n ],\r\n requiredProperties: [{ objectName: 'trend', propertyName: 'show' }],\r\n usage: {\r\n regression: {\r\n combineSeries: { objectName: 'trend', propertyName: 'combineSeries' }\r\n },\r\n },\r\n categorical: {\r\n categories: {\r\n for: { in: 'regression.X' }\r\n },\r\n values: {\r\n group: {\r\n by: 'regression.Series',\r\n select: [{ for: { in: 'regression.Y' } }],\r\n },\r\n },\r\n dataReductionAlgorithm: { sample: {} },\r\n dataVolume: 4,\r\n }\r\n }],\r\n sorting: {\r\n custom: {},\r\n implicit: {\r\n clauses: [{ role: 'Play', direction: SortDirection.Ascending }] //typically a datetime field, sort asc\r\n },\r\n },\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n\r\n export const scatterChartProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'defaultColor' },\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n },\r\n trend: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'trend', propertyName: 'show' },\r\n },\r\n colorBorder: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'colorBorder', propertyName: 'show' },\r\n },\r\n fillPoint: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'fillPoint', propertyName: 'show' },\r\n },\r\n colorByCategory: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'colorByCategory', propertyName: 'show' },\r\n },\r\n currentFrameIndex: {\r\n index: <DataViewObjectPropertyIdentifier>{ objectName: 'currentFrameIndex', propertyName: 'index' },\r\n },\r\n legend: {\r\n labelColor: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'labelColor' },\r\n },\r\n plotArea: {\r\n image: <DataViewObjectPropertyIdentifier>{ objectName: 'plotArea', propertyName: 'image' },\r\n transparency: <DataViewObjectPropertyIdentifier>{ objectName: 'plotArea', propertyName: 'transparency' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const slicerCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Values',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: powerbi.data.createDisplayNameGetter('Role_DisplayName_Field'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_FieldDescription')\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n filter: {\r\n type: { filter: {} },\r\n },\r\n defaultValue: {\r\n type: { expression: { defaultValue: true } },\r\n },\r\n formatString: StandardObjectProperties.formatString,\r\n outlineColor: StandardObjectProperties.outlineColor,\r\n outlineWeight: StandardObjectProperties.outlineWeight,\r\n orientation: {\r\n displayName: data.createDisplayNameGetter('Slicer_Orientation'),\r\n type: { enumeration: slicerOrientation.type }\r\n },\r\n count: {\r\n type: { integer: true }\r\n },\r\n },\r\n },\r\n selection: {\r\n displayName: data.createDisplayNameGetter('Visual_SelectionControls'),\r\n properties: {\r\n selectAllCheckboxEnabled: {\r\n displayName: data.createDisplayNameGetter('Visual_SelectAll'),\r\n type: { bool: true }\r\n },\r\n singleSelect: {\r\n displayName: data.createDisplayNameGetter('Visual_SingleSelect'),\r\n type: { bool: true }\r\n }\r\n },\r\n },\r\n header: {\r\n displayName: data.createDisplayNameGetter('Visual_Header'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n fontColor: StandardObjectProperties.fontColor,\r\n background: {\r\n displayName: data.createDisplayNameGetter('Visual_Background'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n outline: StandardObjectProperties.outline,\r\n textSize: {\r\n displayName: data.createDisplayNameGetter('Visual_TextSize'),\r\n type: { numeric: true }\r\n },\r\n }\r\n },\r\n items: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Items'),\r\n properties: {\r\n fontColor: StandardObjectProperties.fontColor,\r\n background: {\r\n displayName: data.createDisplayNameGetter('Visual_Background'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n outline: StandardObjectProperties.outline,\r\n textSize: {\r\n displayName: data.createDisplayNameGetter('Visual_TextSize'),\r\n type: { numeric: true }\r\n },\r\n }\r\n }\r\n },\r\n dataViewMappings: [{\r\n conditions: [{ 'Values': { max: 1 } }],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Values' },\r\n dataReductionAlgorithm: { window: {} }\r\n },\r\n includeEmptyGroups: true,\r\n }\r\n }],\r\n\r\n sorting: {\r\n default: {},\r\n },\r\n suppressDefaultTitle: true,\r\n disableVisualDetails: true,\r\n };\r\n\r\n // TODO: Generate these from above, defining twice just introduces potential for error\r\n export const slicerProps = {\r\n general: {\r\n outlineColor: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'outlineColor' },\r\n outlineWeight: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'outlineWeight' },\r\n orientation: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'orientation' },\r\n count: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'count' },\r\n },\r\n selection: {\r\n selectAllCheckboxEnabled: <DataViewObjectPropertyIdentifier>{ objectName: 'selection', propertyName: 'selectAllCheckboxEnabled' },\r\n singleSelect: <DataViewObjectPropertyIdentifier>{ objectName: 'selection', propertyName: 'singleSelect' }\r\n },\r\n header: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'header', propertyName: 'show' },\r\n fontColor: <DataViewObjectPropertyIdentifier>{ objectName: 'header', propertyName: 'fontColor' },\r\n background: <DataViewObjectPropertyIdentifier>{ objectName: 'header', propertyName: 'background' },\r\n outline: <DataViewObjectPropertyIdentifier>{ objectName: 'header', propertyName: 'outline' },\r\n textSize: <DataViewObjectPropertyIdentifier>{ objectName: 'header', propertyName: 'textSize' },\r\n },\r\n items: {\r\n fontColor: <DataViewObjectPropertyIdentifier>{ objectName: 'items', propertyName: 'fontColor' },\r\n background: <DataViewObjectPropertyIdentifier>{ objectName: 'items', propertyName: 'background' },\r\n outline: <DataViewObjectPropertyIdentifier>{ objectName: 'items', propertyName: 'outline' },\r\n textSize: <DataViewObjectPropertyIdentifier>{ objectName: 'items', propertyName: 'textSize' },\r\n },\r\n selectedPropertyIdentifier: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'selected' },\r\n filterPropertyIdentifier: <DataViewObjectPropertyIdentifier> { objectName: 'general', propertyName: 'filter' },\r\n formatString: <DataViewObjectPropertyIdentifier> { objectName: 'general', propertyName: 'formatString' },\r\n defaultValue: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'defaultValue' },\r\n };\r\n\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const tableCapabilities: VisualCapabilities = {\r\n dataRoles: [{\r\n name: 'Values',\r\n kind: VisualDataRoleKind.GroupingOrMeasure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values'),\r\n }],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n columnWidth: {\r\n type: { numeric: true }\r\n },\r\n totals: {\r\n type: { bool: true },\r\n displayName: data.createDisplayNameGetter('Visual_Totals'),\r\n suppressFormatPainterCopy: true,\r\n },\r\n autoSizeColumnWidth: {\r\n type: { bool: true },\r\n displayName: data.createDisplayNameGetter('Visual_Adjust_Column_Width'),\r\n suppressFormatPainterCopy: true,\r\n },\r\n textSize: {\r\n displayName: data.createDisplayNameGetter('Visual_TextSize'),\r\n type: { numeric: true }\r\n },\r\n },\r\n },\r\n\r\n grid: {\r\n displayName: data.createDisplayNameGetter('Visual_Grid'),\r\n properties: {\r\n outlineColor: StandardObjectProperties.outlineColor,\r\n outlineWeight: StandardObjectProperties.outlineWeight,\r\n gridVertical: {\r\n displayName: data.createDisplayNameGetter('Visual_GridVertical'),\r\n description: data.createDisplayNameGetter('Visual_GridVertical_Desc'),\r\n type: { bool: true }\r\n },\r\n gridVerticalColor: {\r\n displayName: data.createDisplayNameGetter('Visual_GridVertical_Color'),\r\n description: data.createDisplayNameGetter('Visual_GridVertical_Color_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n gridVerticalWeight: {\r\n displayName: data.createDisplayNameGetter('Visual_GridVertical_Weight'),\r\n description: data.createDisplayNameGetter('Visual_GridVertical_Weight_Desc'),\r\n type: { numeric: true }\r\n },\r\n gridHorizontal: {\r\n displayName: data.createDisplayNameGetter('Visual_GridHorizontal'),\r\n description: data.createDisplayNameGetter('Visual_GridHorizontal_Desc'),\r\n type: { bool: true }\r\n },\r\n gridHorizontalColor: {\r\n displayName: data.createDisplayNameGetter('Visual_GridHorizontal_Color'),\r\n description: data.createDisplayNameGetter('Visual_GridHorizontal_Color_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n gridHorizontalWeight: {\r\n displayName: data.createDisplayNameGetter('Visual_GridHorizontal_Weight'),\r\n description: data.createDisplayNameGetter('Visual_GridHorizontal_Weight_Desc'),\r\n type: { numeric: true }\r\n },\r\n rowPadding: {\r\n displayName: data.createDisplayNameGetter('Visual_RowPadding'),\r\n description: data.createDisplayNameGetter('Visual_RowPadding_Desc'),\r\n type: { numeric: true }\r\n },\r\n imageHeight: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_ImageHeight'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_ImageHeight_Desc'),\r\n type: { numeric: true }\r\n },\r\n }\r\n },\r\n\r\n columnHeaders: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_ColumnHeaders'),\r\n properties: {\r\n outline: StandardObjectProperties.outline,\r\n fontColor: StandardObjectProperties.fontColor,\r\n backColor: StandardObjectProperties.backColor,\r\n }\r\n },\r\n\r\n values: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_Values'),\r\n properties: {\r\n outline: StandardObjectProperties.outline,\r\n // backColor overrides backColorPrimary and Secondary (e.g., in the case of conditional formatting)\r\n backColor: {\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n fontColorPrimary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n backColorPrimary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n fontColorSecondary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n backColorSecondary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n urlIcon: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_UrlIcon'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_UrlIcon_Desc'),\r\n type: { bool: true }\r\n },\r\n }\r\n },\r\n\r\n total: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_TotalGrand'),\r\n properties: {\r\n outline: StandardObjectProperties.outline,\r\n fontColor: StandardObjectProperties.fontColor,\r\n backColor: StandardObjectProperties.backColor,\r\n }\r\n },\r\n },\r\n dataViewMappings: [{\r\n table: {\r\n rows: {\r\n for: { in: 'Values' },\r\n dataReductionAlgorithm: { window: { count: 500 } }\r\n },\r\n rowCount: { preferred: { min: 1 } }\r\n },\r\n }],\r\n sorting: {\r\n custom: {},\r\n },\r\n suppressDefaultTitle: true,\r\n supportsSelection: false,\r\n disableVisualDetails: true,\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const matrixRoleNames = {\r\n rows: 'Rows',\r\n columns: 'Columns',\r\n values: 'Values',\r\n };\r\n\r\n export const matrixCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: matrixRoleNames.rows,\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Rows'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_RowsDescription')\r\n }, {\r\n name: matrixRoleNames.columns,\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Columns'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_ColumnsDescription')\r\n }, {\r\n name: matrixRoleNames.values,\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values')\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n columnWidth: {\r\n type: { numeric: true }\r\n },\r\n rowSubtotals: {\r\n type: { bool: true },\r\n displayName: data.createDisplayNameGetter('Visual_TotalRow'),\r\n suppressFormatPainterCopy: true,\r\n },\r\n columnSubtotals: {\r\n type: { bool: true },\r\n displayName: data.createDisplayNameGetter('Visual_TotalColumn'),\r\n suppressFormatPainterCopy: true,\r\n },\r\n autoSizeColumnWidth: {\r\n type: { bool: true },\r\n displayName: data.createDisplayNameGetter('Visual_Adjust_Column_Width'),\r\n suppressFormatPainterCopy: true,\r\n },\r\n textSize: {\r\n displayName: data.createDisplayNameGetter('Visual_TextSize'),\r\n type: { numeric: true }\r\n },\r\n },\r\n },\r\n\r\n grid: {\r\n displayName: data.createDisplayNameGetter('Visual_Grid'),\r\n properties: {\r\n outlineColor: StandardObjectProperties.outlineColor,\r\n outlineWeight: StandardObjectProperties.outlineWeight,\r\n gridVertical: {\r\n displayName: data.createDisplayNameGetter('Visual_GridVertical'),\r\n description: data.createDisplayNameGetter('Visual_GridVertical_Desc'),\r\n type: { bool: true }\r\n },\r\n gridVerticalColor: {\r\n displayName: data.createDisplayNameGetter('Visual_GridVertical_Color'),\r\n description: data.createDisplayNameGetter('Visual_GridVertical_Color_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n gridVerticalWeight: {\r\n displayName: data.createDisplayNameGetter('Visual_GridVertical_Weight'),\r\n description: data.createDisplayNameGetter('Visual_GridVertical_Weight_Desc'),\r\n type: { numeric: true }\r\n },\r\n gridHorizontal: {\r\n displayName: data.createDisplayNameGetter('Visual_GridHorizontal'),\r\n description: data.createDisplayNameGetter('Visual_GridHorizontal_Desc'),\r\n type: { bool: true }\r\n },\r\n gridHorizontalColor: {\r\n displayName: data.createDisplayNameGetter('Visual_GridHorizontal_Color'),\r\n description: data.createDisplayNameGetter('Visual_GridHorizontal_Color_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n gridHorizontalWeight: {\r\n displayName: data.createDisplayNameGetter('Visual_GridHorizontal_Weight'),\r\n description: data.createDisplayNameGetter('Visual_GridHorizontal_Weight_Desc'),\r\n type: { numeric: true }\r\n },\r\n rowPadding: {\r\n displayName: data.createDisplayNameGetter('Visual_RowPadding'),\r\n description: data.createDisplayNameGetter('Visual_RowPadding_Desc'),\r\n type: { numeric: true }\r\n },\r\n imageHeight: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_ImageHeight'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_ImageHeight_Desc'),\r\n type: { numeric: true }\r\n },\r\n },\r\n },\r\n\r\n columnHeaders: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_ColumnHeaders'),\r\n properties: {\r\n outline: StandardObjectProperties.outline,\r\n fontColor: StandardObjectProperties.fontColor,\r\n backColor: StandardObjectProperties.backColor,\r\n }\r\n },\r\n\r\n rowHeaders:\r\n {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_RowHeaders'),\r\n properties: {\r\n outline: StandardObjectProperties.outline,\r\n fontColor: StandardObjectProperties.fontColor,\r\n backColor: StandardObjectProperties.backColor,\r\n }\r\n },\r\n values:\r\n {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_Values'),\r\n properties: {\r\n outline: StandardObjectProperties.outline,\r\n fontColorPrimary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_FontColorPrimary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n backColorPrimary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_BackColorPrimary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n fontColorSecondary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_FontColorSecondary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n backColorSecondary: {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary'),\r\n description: data.createDisplayNameGetter('Visual_Tablix_BackColorSecondary_Desc'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n }\r\n },\r\n subTotals:\r\n {\r\n displayName: data.createDisplayNameGetter('Visual_Tablix_TotalSub'),\r\n properties: {\r\n outline: StandardObjectProperties.outline,\r\n fontColor: StandardObjectProperties.fontColor,\r\n backColor: StandardObjectProperties.backColor,\r\n }\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Rows': { max: 0 }, 'Columns': { max: 0 }, 'Values': { min: 1 } },\r\n { 'Rows': { min: 1 }, 'Columns': { min: 0 }, 'Values': { min: 0 } },\r\n { 'Rows': { min: 0 }, 'Columns': { min: 1 }, 'Values': { min: 0 } }\r\n ],\r\n matrix: {\r\n rows: {\r\n for: { in: 'Rows' },\r\n /* Explicitly override the server data reduction to make it appropriate for matrix. */\r\n dataReductionAlgorithm: { window: { count: 500 } }\r\n },\r\n columns: {\r\n for: { in: 'Columns' },\r\n /* Explicitly override the server data reduction to make it appropriate for matrix. */\r\n dataReductionAlgorithm: { top: { count: 100 } }\r\n },\r\n values: {\r\n for: { in: 'Values' }\r\n }\r\n }\r\n }],\r\n filterMappings: {\r\n measureFilter: {\r\n targetRoles: [matrixRoleNames.rows]\r\n }\r\n },\r\n sorting: {\r\n custom: {},\r\n },\r\n suppressDefaultTitle: true,\r\n supportsSelection: false,\r\n disableVisualDetails: true,\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const treemapCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Group',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Group'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GroupTreemapDescription')\r\n }, {\r\n name: 'Details',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Details'),\r\n }, {\r\n name: 'Values',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Values'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_ValuesDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }, {\r\n name: 'Gradient',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Gradient'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_GradientDescription'),\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: StandardObjectProperties.legendTitle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: { \r\n fill: {\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n fillRule: {\r\n displayName: data.createDisplayNameGetter('Visual_Gradient'),\r\n type: { fillRule: {} },\r\n rule: {\r\n inputRole: 'Gradient',\r\n output: {\r\n property: 'fill',\r\n selector: ['Group'],\r\n }\r\n }\r\n }\r\n }\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n description: data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n categoryLabels: {\r\n displayName: data.createDisplayNameGetter('Visual_CategoryLabels'),\r\n description: data.createDisplayNameGetter('Visual_CategoryLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Group': { max: 1 }, 'Details': { max: 0 }, 'Gradient': { max: 1 } },\r\n { 'Group': { max: 1 }, 'Details': { min: 1, max: 1 }, 'Values': { max: 1 }, 'Gradient': { max: 0 } }\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Group' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n group: {\r\n by: 'Details',\r\n select: [{ bind: { to: 'Values' } }, { bind: { to: 'Gradient' } }],\r\n dataReductionAlgorithm: { top: {} }\r\n }\r\n },\r\n rowCount: { preferred: { min: 2 } }\r\n }\r\n }],\r\n supportsHighlight: true,\r\n sorting: {\r\n custom: {},\r\n implicit: {\r\n clauses: [{ role: 'Values', direction: SortDirection.Descending }]\r\n },\r\n },\r\n drilldown: {\r\n roles: ['Group']\r\n },\r\n };\r\n \r\n export const treemapProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n dataPoint: {\r\n fill: <DataViewObjectPropertyIdentifier>{ objectName: 'dataPoint', propertyName: 'fill' },\r\n },\r\n legend: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'show' },\r\n position: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'position' },\r\n showTitle: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'showTitle' },\r\n titleText: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'titleText' },\r\n labelColor: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'labelColor' },\r\n },\r\n labels: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'show' },\r\n color: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'color' },\r\n labelDisplayUnits: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'labelDisplayUnits' },\r\n labelPrecision: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'labelPrecision' },\r\n },\r\n categoryLabels: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'categoryLabels', propertyName: 'show' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const cardCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Values',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Fields'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_FieldsDescription'),\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointLabel'),\r\n properties: {\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n // NOTE: Consider adding a ValueType for fontSize.\r\n fontSize: StandardObjectProperties.fontSize,\r\n },\r\n },\r\n categoryLabels: {\r\n displayName: data.createDisplayNameGetter('Visual_CategoryLabel'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n // NOTE: Consider adding a ValueType for fontSize.\r\n fontSize: StandardObjectProperties.fontSize,\r\n },\r\n },\r\n wordWrap: {\r\n displayName: data.createDisplayNameGetter('Visual_WordWrap'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Values': { max: 1 } }\r\n ],\r\n single: { role: \"Values\" }\r\n }],\r\n suppressDefaultTitle: true,\r\n supportsSelection: false,\r\n };\r\n\r\n export var cardProps = {\r\n categoryLabels: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'categoryLabels', propertyName: 'show' },\r\n color: <DataViewObjectPropertyIdentifier>{ objectName: 'categoryLabels', propertyName: 'color' },\r\n fontSize: <DataViewObjectPropertyIdentifier>{ objectName: 'categoryLabels', propertyName: 'fontSize' },\r\n },\r\n labels: {\r\n color: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'color' },\r\n labelPrecision: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'labelPrecision' },\r\n labelDisplayUnits: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'labelDisplayUnits' },\r\n fontSize: <DataViewObjectPropertyIdentifier>{ objectName: 'labels', propertyName: 'fontSize' },\r\n },\r\n wordWrap: {\r\n show: <DataViewObjectPropertyIdentifier>{ objectName: 'wordWrap', propertyName: 'show' },\r\n },\r\n };\r\n\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const waterfallChartCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Category',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Category'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_CategoryWaterfallDescription')\r\n }, {\r\n name: 'Y',\r\n kind: VisualDataRoleKind.Measure,\r\n requiredTypes: [{ numeric: true }, { integer: true }],\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_Y'),\r\n }\r\n ],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n legend: {\r\n displayName: data.createDisplayNameGetter('Visual_Legend'),\r\n description: data.createDisplayNameGetter('Visual_LegendDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.legendPosition,\r\n showTitle: StandardObjectProperties.showLegendTitle,\r\n titleText: $.extend({}, StandardObjectProperties.legendTitle, {\r\n suppressFormatPainterCopy: true,\r\n }),\r\n labelColor: StandardObjectProperties.labelColor,\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n labels: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPointsLabels'),\r\n description: data.createDisplayNameGetter('Visual_DataPointsLabelsDescription'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n color: StandardObjectProperties.dataColor,\r\n labelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n labelPrecision: $.extend({}, StandardObjectProperties.labelPrecision, {\r\n suppressFormatPainterCopy: true,\r\n }),\r\n fontSize: StandardObjectProperties.fontSize,\r\n }\r\n },\r\n sentimentColors: {\r\n displayName: data.createDisplayNameGetter('Waterfall_SentimentColors'),\r\n properties: {\r\n increaseFill: {\r\n displayName: data.createDisplayNameGetter('Waterfall_IncreaseLabel'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n decreaseFill: {\r\n displayName: data.createDisplayNameGetter('Waterfall_DecreaseLabel'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n totalFill: {\r\n displayName: data.createDisplayNameGetter('Waterfall_TotalLabel'),\r\n type: { fill: { solid: { color: true } } }\r\n }\r\n },\r\n },\r\n categoryAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_XAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_XTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n }\r\n },\r\n valueAxis: {\r\n displayName: data.createDisplayNameGetter('Visual_YAxis'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n position: StandardObjectProperties.yAxisPosition,\r\n start: StandardObjectProperties.axisStart,\r\n end: StandardObjectProperties.axisEnd,\r\n showAxisTitle: {\r\n displayName: data.createDisplayNameGetter('Visual_Axis_Title'),\r\n description: data.createDisplayNameGetter('Visual_Axis_YTitleDescription'),\r\n type: { bool: true }\r\n },\r\n axisStyle: StandardObjectProperties.axisStyle,\r\n labelColor: StandardObjectProperties.labelColor,\r\n labelDisplayUnits: StandardObjectProperties.labelDisplayUnits,\r\n labelPrecision: StandardObjectProperties.labelPrecision,\r\n }\r\n },\r\n y1AxisReferenceLine: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Description'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n value: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Value'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Value_Description'),\r\n type: { numeric: true }\r\n },\r\n lineColor: StandardObjectProperties.lineColor,\r\n transparency: {\r\n displayName: data.createDisplayNameGetter('Visual_Reference_Line_Transparency'),\r\n description: data.createDisplayNameGetter('Visual_Reference_Line_Transparency_Description'),\r\n type: { numeric: true }\r\n },\r\n style: StandardObjectProperties.referenceLineStyle,\r\n position: StandardObjectProperties.referenceLinePosition,\r\n dataLabelShow: StandardObjectProperties.dataLabelShow,\r\n dataLabelColor: StandardObjectProperties.dataLabelColor,\r\n dataLabelDecimalPoints: StandardObjectProperties.dataLabelDecimalPoints,\r\n dataLabelHorizontalPosition: StandardObjectProperties.dataLabelHorizontalPosition,\r\n dataLabelVerticalPosition: StandardObjectProperties.dataLabelVerticalPosition,\r\n dataLabelDisplayUnits: StandardObjectProperties.dataLabelDisplayUnits,\r\n },\r\n },\r\n plotArea: {\r\n displayName: data.createDisplayNameGetter('Visual_Plot'),\r\n properties: {\r\n transparency: StandardObjectProperties.transparency,\r\n image: StandardObjectProperties.image,\r\n },\r\n },\r\n },\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Category': { max: 1 }, 'Y': { max: 1 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n select: [{ bind: { to: 'Y' } }]\r\n },\r\n },\r\n }],\r\n drilldown: {\r\n roles: ['Category']\r\n },\r\n };\r\n\r\n export const waterfallChartProps = {\r\n general: {\r\n formatString: <DataViewObjectPropertyIdentifier>{ objectName: 'general', propertyName: 'formatString' },\r\n },\r\n sentimentColors: {\r\n increaseFill: <DataViewObjectPropertyIdentifier>{ objectName: 'sentimentColors', propertyName: 'increaseFill' },\r\n decreaseFill: <DataViewObjectPropertyIdentifier>{ objectName: 'sentimentColors', propertyName: 'decreaseFill' },\r\n totalFill: <DataViewObjectPropertyIdentifier>{ objectName: 'sentimentColors', propertyName: 'totalFill' },\r\n },\r\n legend: {\r\n labelColor: <DataViewObjectPropertyIdentifier>{ objectName: 'legend', propertyName: 'labelColor' },\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export const KPIStatusWithHistoryCapabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n name: 'Indicator',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_Indicator'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_KPI_IndicatorDescription')\r\n }, {\r\n name: 'TrendLine',\r\n kind: VisualDataRoleKind.Grouping,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_TrendLine'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_KPI_Trendline_Description')\r\n }, {\r\n name: 'Goal',\r\n kind: VisualDataRoleKind.Measure,\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_Goal'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_KPI_GoalDescription')\r\n }],\r\n dataViewMappings: [{\r\n conditions: [\r\n { 'Indicator': { max: 1 }, 'TrendLine': { max: 1 }, 'Goal': { max: 2 } },\r\n ],\r\n categorical: {\r\n categories: {\r\n for: { in: 'TrendLine' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n select: [\r\n { bind: { to: 'Indicator' } },\r\n { bind: { to: 'Goal' } }\r\n ]\r\n }\r\n },\r\n }],\r\n objects: {\r\n general: {\r\n properties: {\r\n formatString: StandardObjectProperties.formatString,\r\n },\r\n },\r\n indicator: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_Indicator'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_KPI_IndicatorDescription'),\r\n properties: {\r\n indicatorDisplayUnits: {\r\n displayName: data.createDisplayNameGetter('Visual_DisplayUnits'),\r\n description: data.createDisplayNameGetter('Visual_DisplayUnitsDescription'),\r\n type: { formatting: { labelDisplayUnits: true } }\r\n },\r\n indicatorPrecision: {\r\n displayName: data.createDisplayNameGetter('Visual_Precision'),\r\n description: data.createDisplayNameGetter('Visual_PrecisionDescription'),\r\n placeHolderText: data.createDisplayNameGetter('Visual_Precision_Auto'),\r\n type: { numeric: true }\r\n },\r\n kpiFormat: {\r\n displayName: data.createDisplayNameGetter('TaskPane_Format'),\r\n type: { text: true },\r\n }\r\n }\r\n },\r\n trendline: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_TrendLine'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_KPI_Trendline_Description'),\r\n properties: {\r\n show: StandardObjectProperties.show,\r\n }\r\n },\r\n goals: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_Goals'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_KPI_Goals'),\r\n properties: {\r\n showGoal: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_Show_Goal'),\r\n type: { bool: true }\r\n },\r\n showDistance: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_Show_Distance'),\r\n type: { bool: true }\r\n },\r\n }\r\n },\r\n status: {\r\n displayName: data.createDisplayNameGetter('Role_DisplayName_KPI_Status'),\r\n description: data.createDisplayNameGetter('Role_DisplayName_KPI_Status'),\r\n properties: {\r\n direction: {\r\n displayName: data.createDisplayNameGetter('Visual_KPI_Direction'),\r\n type: { enumeration: kpiDirection.type }\r\n }\r\n }\r\n }\r\n },\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.capabilities {\r\n // This file registers the built-in capabilities\r\n // Please use this file to register the capabilities in the plugins.ts/pluginsNotForOSS.ts\r\n\r\n export let animatedNumber = powerbi.visuals.animatedNumberCapabilities;\r\n\r\n export let areaChart = powerbi.visuals.lineChartCapabilities;\r\n\r\n export let barChart = powerbi.visuals.getColumnChartCapabilities(true);\r\n\r\n export let card = powerbi.visuals.cardCapabilities;\r\n\r\n export let multiRowCard = powerbi.visuals.multiRowCardCapabilities;\r\n\r\n export let clusteredBarChart = powerbi.visuals.getColumnChartCapabilities(true);\r\n\r\n export let clusteredColumnChart = powerbi.visuals.getColumnChartCapabilities();\r\n\r\n export let columnChart = powerbi.visuals.getColumnChartCapabilities();\r\n\r\n export let comboChart = powerbi.visuals.comboChartCapabilities;\r\n\r\n export let dataDotChart = powerbi.visuals.dataDotChartCapabilities;\r\n\r\n export let dataDotClusteredColumnComboChart = powerbi.visuals.comboChartCapabilities;\r\n\r\n export let dataDotStackedColumnComboChart = powerbi.visuals.comboChartCapabilities;\r\n\r\n export let donutChart = powerbi.visuals.donutChartCapabilities;\r\n\r\n export let funnel = powerbi.visuals.funnelChartCapabilities;\r\n\r\n export let gauge = powerbi.visuals.gaugeCapabilities;\r\n\r\n export let hundredPercentStackedBarChart = powerbi.visuals.getColumnChartCapabilities(true);\r\n\r\n export let hundredPercentStackedColumnChart = powerbi.visuals.getColumnChartCapabilities();\r\n\r\n export let image = powerbi.visuals.imageVisualCapabilities;\r\n\r\n export let lineChart = powerbi.visuals.lineChartCapabilities;\r\n\r\n export let lineStackedColumnComboChart = powerbi.visuals.comboChartCapabilities;\r\n\r\n export let lineClusteredColumnComboChart = powerbi.visuals.comboChartCapabilities;\r\n\r\n export let map = powerbi.visuals.mapCapabilities;\r\n\r\n export let filledMap = powerbi.visuals.filledMapCapabilities;\r\n\r\n export let treemap = powerbi.visuals.treemapCapabilities;\r\n\r\n export let pieChart = powerbi.visuals.donutChartCapabilities;\r\n\r\n export let scatterChart = powerbi.visuals.scatterChartCapabilities;\r\n\r\n export let table = powerbi.visuals.tableCapabilities;\r\n\r\n export let matrix = powerbi.visuals.matrixCapabilities;\r\n\r\n export let slicer = powerbi.visuals.slicerCapabilities;\r\n\r\n export let textbox = powerbi.visuals.textboxCapabilities;\r\n\r\n export let waterfallChart = powerbi.visuals.waterfallChartCapabilities;\r\n\r\n export let cheerMeter = powerbi.visuals.cheerMeterCapabilities;\r\n\r\n export let scriptVisual = powerbi.visuals.scriptVisualCapabilities;\r\n \r\n export let kpi = powerbi.visuals.KPIStatusWithHistoryCapabilities;\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface ColumnBehaviorOptions {\r\n datapoints: SelectableDataPoint[];\r\n bars: D3.Selection;\r\n eventGroup: D3.Selection;\r\n mainGraphicsContext: D3.Selection;\r\n hasHighlights: boolean;\r\n viewport: IViewport;\r\n axisOptions: ColumnAxisOptions;\r\n showLabel: boolean;\r\n }\r\n\r\n export class ColumnChartWebBehavior implements IInteractiveBehavior {\r\n private options: ColumnBehaviorOptions;\r\n\r\n public bindEvents(options: ColumnBehaviorOptions, selectionHandler: ISelectionHandler) {\r\n this.options = options;\r\n let eventGroup = options.eventGroup;\r\n\r\n eventGroup.on('click', () => {\r\n let d = ColumnChartWebBehavior.getDatumForLastInputEvent();\r\n \r\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\r\n });\r\n\r\n eventGroup.on('contextmenu', () => {\r\n if (d3.event.ctrlKey)\r\n return;\r\n\r\n d3.event.preventDefault();\r\n\r\n let d = ColumnChartWebBehavior.getDatumForLastInputEvent();\r\n let position = InteractivityUtils.getPositionOfLastInputEvent();\r\n \r\n selectionHandler.handleContextMenu(d, position);\r\n });\r\n }\r\n\r\n public renderSelection(hasSelection: boolean) {\r\n let options = this.options;\r\n options.bars.style(\"fill-opacity\", (d: ColumnChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && options.hasHighlights));\r\n }\r\n\r\n private static getDatumForLastInputEvent(): any {\r\n let target = d3.event.target;\r\n return d3.select(target).datum();\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface DataDotChartBehaviorOptions {\r\n dots: D3.Selection;\r\n dotLabels: D3.Selection;\r\n isPartOfCombo?: boolean;\r\n datapoints?: DataDotChartDataPoint[];\r\n }\r\n\r\n export class DataDotChartWebBehavior implements IInteractiveBehavior {\r\n private dots: D3.Selection;\r\n\r\n public bindEvents(options: DataDotChartBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let dots = this.dots = options.dots;\r\n let dotLabels = options.dotLabels;\r\n\r\n InteractivityUtils.registerStandardInteractivityHandlers(dots, selectionHandler);\r\n\r\n if (dotLabels) {\r\n InteractivityUtils.registerStandardInteractivityHandlers(dotLabels, selectionHandler);\r\n }\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n this.dots.style(\"fill-opacity\",(d: DataDotChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false));\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface DonutBehaviorOptions {\r\n slices: D3.Selection;\r\n highlightSlices: D3.Selection;\r\n clearCatcher: D3.Selection;\r\n hasHighlights: boolean;\r\n allowDrilldown: boolean;\r\n visual: IVisual;\r\n }\r\n\r\n export class DonutChartWebBehavior implements IInteractiveBehavior {\r\n private slices: D3.Selection;\r\n private highlightSlices: D3.Selection;\r\n private hasHighlights: boolean;\r\n\r\n public bindEvents(options: DonutBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let slices = this.slices = options.slices;\r\n let highlightSlices = this.highlightSlices = options.highlightSlices;\r\n let clearCatcher = options.clearCatcher;\r\n this.hasHighlights = options.hasHighlights;\r\n\r\n let clickHandler = (d: DonutArcDescriptor) => {\r\n selectionHandler.handleSelection(d.data, d3.event.ctrlKey);\r\n };\r\n\r\n let contextMenuHandler = (d: DonutArcDescriptor) => {\r\n if (d3.event.ctrlKey)\r\n return;\r\n\r\n let position = InteractivityUtils.getPositionOfLastInputEvent();\r\n selectionHandler.handleContextMenu(d.data, position);\r\n d3.event.preventDefault();\r\n };\r\n\r\n slices.on('click', clickHandler);\r\n slices.on('contextmenu', contextMenuHandler);\r\n\r\n highlightSlices.on('click', clickHandler);\r\n highlightSlices.on('contextmenu', contextMenuHandler);\r\n\r\n clearCatcher.on('click', () => {\r\n selectionHandler.handleClearSelection();\r\n });\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n let hasHighlights = this.hasHighlights;\r\n this.slices.style(\"fill-opacity\", (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, hasHighlights && !d.data.selected));\r\n this.highlightSlices.style(\"fill-opacity\", (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, true, false, hasHighlights));\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface FunnelBehaviorOptions {\r\n bars: D3.Selection;\r\n interactors: D3.Selection;\r\n clearCatcher: D3.Selection;\r\n hasHighlights: boolean;\r\n }\r\n\r\n export class FunnelWebBehavior implements IInteractiveBehavior {\r\n private bars: D3.Selection;\r\n private interactors: D3.Selection;\r\n private hasHighlights: boolean;\r\n\r\n public bindEvents(options: FunnelBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n\r\n let bars = this.bars = options.bars;\r\n let interactors = this.interactors = options.interactors;\r\n let clearCatcher = options.clearCatcher;\r\n\r\n this.hasHighlights = options.hasHighlights;\r\n\r\n InteractivityUtils.registerStandardInteractivityHandlers(bars, selectionHandler);\r\n InteractivityUtils.registerStandardInteractivityHandlers(interactors, selectionHandler);\r\n\r\n clearCatcher.on('click', () => {\r\n selectionHandler.handleClearSelection();\r\n });\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n let hasHighlights = this.hasHighlights;\r\n this.bars.style(\"fill-opacity\", (d: FunnelSlice) => ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && hasHighlights));\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface LineChartBehaviorOptions {\r\n lines: D3.Selection;\r\n interactivityLines: D3.Selection;\r\n dots: D3.Selection;\r\n areas: D3.Selection;\r\n isPartOfCombo?: boolean;\r\n tooltipOverlay: D3.Selection;\r\n }\r\n\r\n export class LineChartWebBehavior implements IInteractiveBehavior {\r\n private lines: D3.Selection;\r\n private dots: D3.Selection;\r\n private areas: D3.Selection;\r\n private tooltipOverlay: D3.Selection;\r\n\r\n public bindEvents(options: LineChartBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n this.lines = options.lines;\r\n let interactivityLines = options.interactivityLines;\r\n let dots = this.dots = options.dots;\r\n let areas = this.areas = options.areas;\r\n let tooltipOverlay = this.tooltipOverlay = options.tooltipOverlay;\r\n\r\n InteractivityUtils.registerStandardInteractivityHandlers(interactivityLines, selectionHandler);\r\n InteractivityUtils.registerStandardInteractivityHandlers(dots, selectionHandler);\r\n\r\n if (areas) {\r\n InteractivityUtils.registerStandardInteractivityHandlers(areas, selectionHandler);\r\n }\r\n\r\n if (tooltipOverlay)\r\n tooltipOverlay.on('click', () => selectionHandler.handleClearSelection());\r\n }\r\n\r\n public renderSelection(hasSelection: boolean) {\r\n this.lines.style(\"stroke-opacity\", (d: SelectableDataPoint) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false));\r\n this.dots.style(\"fill-opacity\", (d: SelectableDataPoint) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false));\r\n if (this.areas)\r\n this.areas.style(\"fill-opacity\", (d: SelectableDataPoint) => (hasSelection && !d.selected) ? LineChart.DimmedAreaFillOpacity : LineChart.AreaFillOpacity);\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import MapSliceContainer = powerbi.visuals.MapSliceContainer;\r\n\r\n export interface MapBehaviorOptions {\r\n dataPoints: SelectableDataPoint[];\r\n bubbles?: D3.Selection;\r\n slices?: D3.Selection;\r\n shapes?: D3.Selection;\r\n clearCatcher: D3.Selection;\r\n bubbleEventGroup?: D3.Selection;\r\n sliceEventGroup?: D3.Selection;\r\n shapeEventGroup?: D3.Selection;\r\n }\r\n\r\n export class MapBehavior implements IInteractiveBehavior {\r\n private bubbles: D3.Selection;\r\n private slices: D3.Selection;\r\n private shapes: D3.Selection;\r\n private mapPointerEventsDisabled = false;\r\n private mapPointerTimeoutSet = false;\r\n private viewChangedSinceLastClearMouseDown = false;\r\n private receivedZoomOrPanEvent = false;\r\n\r\n public bindEvents(options: MapBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let bubbles = this.bubbles = options.bubbles;\r\n let slices = this.slices = options.slices;\r\n let shapes = this.shapes = options.shapes;\r\n let clearCatcher = options.clearCatcher;\r\n\r\n let clickHandler = () => {\r\n let target = d3.event.target;\r\n let d = <SelectableDataPoint>d3.select(target).datum();\r\n\r\n if (bubbles)\r\n bubbles.style(\"pointer-events\", \"all\");\r\n if (shapes)\r\n shapes.style(\"pointer-events\", \"all\");\r\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\r\n };\r\n\r\n if (!this.mapPointerEventsDisabled) {\r\n if (bubbles)\r\n bubbles.style(\"pointer-events\", \"all\");\r\n if (slices)\r\n slices.style(\"pointer-events\", \"all\");\r\n if (shapes)\r\n shapes.style(\"pointer-events\", \"all\");\r\n }\r\n\r\n if (bubbles) {\r\n options.bubbleEventGroup.on('click', clickHandler);\r\n options.bubbleEventGroup.on('mousewheel', () => {\r\n if (!this.mapPointerEventsDisabled)\r\n bubbles.style(\"pointer-events\", \"none\");\r\n this.mapPointerEventsDisabled = true;\r\n if (!this.mapPointerTimeoutSet) {\r\n this.mapPointerTimeoutSet = true;\r\n setTimeout(() => {\r\n if (bubbles)\r\n bubbles.style(\"pointer-events\", \"all\");\r\n this.mapPointerEventsDisabled = false;\r\n this.mapPointerTimeoutSet = false;\r\n }, 200);\r\n }\r\n });\r\n\r\n InteractivityUtils.registerGroupContextMenuHandler(options.bubbleEventGroup, selectionHandler);\r\n }\r\n\r\n if (slices) {\r\n options.sliceEventGroup.on('click', () => {\r\n slices.style(\"pointer-events\", \"all\");\r\n this.mapPointerEventsDisabled = false;\r\n\r\n let target = d3.event.target;\r\n let d = <MapSliceContainer>d3.select(target).datum();\r\n selectionHandler.handleSelection(d.data, d3.event.ctrlKey);\r\n });\r\n options.sliceEventGroup.on('mousewheel', () => {\r\n if (!this.mapPointerEventsDisabled)\r\n slices.style(\"pointer-events\", \"none\");\r\n this.mapPointerEventsDisabled = true;\r\n if (!this.mapPointerTimeoutSet) {\r\n this.mapPointerTimeoutSet = true;\r\n setTimeout(() => {\r\n if (slices)\r\n slices.style(\"pointer-events\", \"all\");\r\n this.mapPointerEventsDisabled = false;\r\n this.mapPointerTimeoutSet = false;\r\n }, 200);\r\n }\r\n });\r\n\r\n options.sliceEventGroup.on('contextmenu', () => {\r\n if (d3.event.ctrlKey)\r\n return;\r\n\r\n d3.event.preventDefault();\r\n let position = InteractivityUtils.getPositionOfLastInputEvent();\r\n\r\n let target = d3.event.target;\r\n let d = <MapSliceContainer>d3.select(target).datum();\r\n selectionHandler.handleContextMenu(d.data, position);\r\n });\r\n }\r\n\r\n if (shapes) {\r\n options.shapeEventGroup.on('click', clickHandler);\r\n options.shapeEventGroup.on('mousewheel', () => {\r\n if (!this.mapPointerEventsDisabled) {\r\n shapes.style(\"pointer-events\", \"none\");\r\n }\r\n this.mapPointerEventsDisabled = true;\r\n if (!this.mapPointerTimeoutSet) {\r\n this.mapPointerTimeoutSet = true;\r\n setTimeout(() => {\r\n if (shapes)\r\n shapes.style(\"pointer-events\", \"all\");\r\n this.mapPointerEventsDisabled = false;\r\n this.mapPointerTimeoutSet = false;\r\n }, 200);\r\n }\r\n });\r\n\r\n InteractivityUtils.registerGroupContextMenuHandler(options.shapeEventGroup, selectionHandler);\r\n }\r\n\r\n clearCatcher.on('mouseup', () => {\r\n if (!this.viewChangedSinceLastClearMouseDown) {\r\n selectionHandler.handleClearSelection();\r\n this.receivedZoomOrPanEvent = true;\r\n }\r\n });\r\n\r\n clearCatcher.on('mousedown', () => {\r\n this.viewChangedSinceLastClearMouseDown = false;\r\n });\r\n\r\n clearCatcher.on('mousewheel', () => {\r\n this.receivedZoomOrPanEvent = true;\r\n });\r\n }\r\n\r\n public renderSelection(hasSelection: boolean) {\r\n if (this.bubbles) {\r\n this.bubbles\r\n .style({\r\n 'fill-opacity': (d: MapBubble) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false),\r\n 'stroke-opacity': (d: MapBubble) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false),\r\n });\r\n }\r\n if (this.slices) {\r\n this.slices\r\n .style({\r\n \"fill-opacity\": (d) => ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false),\r\n \"stroke-opacity\": (d) => ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false),\r\n });\r\n }\r\n if (this.shapes) {\r\n this.shapes\r\n .style({\r\n \"fill-opacity\": (d) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false),\r\n \"stroke-opacity\": (d) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false),\r\n });\r\n }\r\n }\r\n\r\n public viewChanged() {\r\n this.viewChangedSinceLastClearMouseDown = true;\r\n }\r\n\r\n public resetZoomPan() {\r\n this.receivedZoomOrPanEvent = false;\r\n }\r\n\r\n public hasReceivedZoomOrPanEvent(): boolean {\r\n return this.receivedZoomOrPanEvent;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n export interface ScatterBehaviorChartData {\r\n xCol: DataViewMetadataColumn;\r\n yCol: DataViewMetadataColumn;\r\n dataPoints: ScatterChartDataPoint[];\r\n legendData: LegendData;\r\n axesLabels: ChartAxesLabels;\r\n size?: DataViewMetadataColumn;\r\n sizeRange: NumberRange;\r\n fillPoint?: boolean;\r\n colorBorder?: boolean;\r\n }\r\n\r\n export interface ScatterBehaviorOptions {\r\n dataPointsSelection: D3.Selection;\r\n eventGroup?: D3.Selection;\r\n data: ScatterBehaviorChartData;\r\n plotContext: D3.Selection;\r\n playOptions?: PlayBehaviorOptions;\r\n }\r\n\r\n export interface ScatterMobileBehaviorOptions extends ScatterBehaviorOptions {\r\n host: ICartesianVisualHost;\r\n root: D3.Selection;\r\n background: D3.Selection;\r\n visualInitOptions: VisualInitOptions;\r\n xAxisProperties: IAxisProperties;\r\n yAxisProperties: IAxisProperties;\r\n }\r\n\r\n export class ScatterChartWebBehavior implements IInteractiveBehavior {\r\n private bubbles: D3.Selection;\r\n private shouldEnableFill: boolean;\r\n private colorBorder: boolean;\r\n private playOptions: PlayBehaviorOptions;\r\n\r\n public bindEvents(options: ScatterBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let bubbles = this.bubbles = options.dataPointsSelection;\r\n let data = options.data;\r\n let eventGroup = options.eventGroup;\r\n\r\n // If we are removing play-axis, remove the trace lines as well\r\n // TODO: revisit this design, I think ideally this is done when rendering scatter.\r\n if (this.playOptions\r\n && this.playOptions.traceLineRenderer\r\n && (!options.playOptions || !options.playOptions.traceLineRenderer)) {\r\n this.playOptions.traceLineRenderer.remove();\r\n }\r\n\r\n this.playOptions = options.playOptions;\r\n this.shouldEnableFill = (!data.sizeRange || !data.sizeRange.min) && data.fillPoint;\r\n this.colorBorder = data.colorBorder;\r\n\r\n if (eventGroup) {\r\n InteractivityUtils.registerGroupInteractivityHandlers(eventGroup, selectionHandler);\r\n } else {\r\n InteractivityUtils.registerStandardInteractivityHandlers(bubbles, selectionHandler);\r\n }\r\n }\r\n\r\n public renderSelection(hasSelection: boolean) {\r\n let shouldEnableFill = this.shouldEnableFill;\r\n let colorBorder = this.colorBorder;\r\n this.bubbles.style(\"fill-opacity\", (d: ScatterChartDataPoint) => ScatterChart.getMarkerFillOpacity(d.size != null, shouldEnableFill, hasSelection, d.selected));\r\n this.bubbles.style(\"stroke-opacity\", (d: ScatterChartDataPoint) => ScatterChart.getMarkerStrokeOpacity(d.size != null, colorBorder, hasSelection, d.selected));\r\n\r\n if (this.playOptions && this.bubbles) {\r\n let selectedPoints = this.bubbles.filter((d: SelectableDataPoint) => d.selected).data();\r\n let traceLineRenderer = this.playOptions.traceLineRenderer;\r\n if (selectedPoints && selectedPoints.length > 0 && traceLineRenderer != null) {\r\n traceLineRenderer.render(selectedPoints, true);\r\n }\r\n else {\r\n traceLineRenderer.remove();\r\n }\r\n }\r\n }\r\n }\r\n\r\n export const enum DragType {\r\n Drag,\r\n DragEnd\r\n }\r\n\r\n interface MouseCoordinates {\r\n x: number;\r\n y: number;\r\n }\r\n\r\n export class ScatterChartMobileBehavior implements IInteractiveBehavior {\r\n private static CrosshairClassName = 'crosshair';\r\n private static ScatterChartCircleTagName = 'circle';\r\n private static DotClassName = 'dot';\r\n private static DotClassSelector = '.' + ScatterChartMobileBehavior.DotClassName;\r\n\r\n private static Horizontal: ClassAndSelector = createClassAndSelector('horizontal');\r\n private static Vertical: ClassAndSelector = createClassAndSelector('vertical');\r\n\r\n private host: ICartesianVisualHost;\r\n private mainGraphicsContext: D3.Selection;\r\n private data: ScatterBehaviorChartData;\r\n private crosshair: D3.Selection;\r\n private crosshairHorizontal: D3.Selection;\r\n private crosshairVertical: D3.Selection;\r\n private lastDotIndex: number;\r\n private xAxisProperties: IAxisProperties;\r\n private yAxisProperties: IAxisProperties;\r\n\r\n public bindEvents(options: ScatterMobileBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n this.setOptions(options);\r\n\r\n if (!options.visualInitOptions || !options.visualInitOptions.interactivity.isInteractiveLegend) {\r\n // Don't bind events if we are not in interactiveLegend mode\r\n // This case happend when on mobile we show the whole dashboard in still not on focus\r\n return;\r\n }\r\n\r\n this.makeDataPointsSelectable(options.dataPointsSelection);\r\n this.makeRootSelectable(options.root);\r\n this.makeDragable(options.root);\r\n this.disableDefaultTouchInteractions(options.root);\r\n this.selectRoot();\r\n }\r\n\r\n public renderSelection(HasSelection: boolean): void { }\r\n\r\n public setSelectionHandler(selectionHandler: ISelectionHandler): void { }\r\n\r\n private makeDataPointsSelectable(...selection: D3.Selection[]): void {\r\n for (let i = 0, len = selection.length; i < len; i++) {\r\n var sel = selection[i];\r\n\r\n sel.on('click', (d: SelectableDataPoint, i: number) => {\r\n this.select(i);\r\n });\r\n }\r\n }\r\n\r\n private makeRootSelectable(selection: D3.Selection): void {\r\n selection.on('click', (d: SelectableDataPoint, i: number) => {\r\n this.selectRoot();\r\n });\r\n }\r\n\r\n private makeDragable(...selection: D3.Selection[]): void {\r\n for (let i = 0, len = selection.length; i < len; i++) {\r\n let sel = selection[i];\r\n\r\n let drag = d3.behavior.drag()\r\n .on('drag', (d) => { this.drag(DragType.Drag); })\r\n .on('dragend', (d) => { this.drag(DragType.DragEnd); });\r\n\r\n sel.call(drag);\r\n }\r\n }\r\n\r\n private disableDefaultTouchInteractions(selection: D3.Selection): void {\r\n selection.style('touch-action', 'none');\r\n }\r\n\r\n public setOptions(options: ScatterMobileBehaviorOptions) {\r\n this.data = options.data;\r\n this.mainGraphicsContext = options.plotContext;\r\n this.xAxisProperties = options.xAxisProperties;\r\n this.yAxisProperties = options.yAxisProperties;\r\n this.host = options.host;\r\n }\r\n\r\n private select(index: number) {\r\n this.selectDotByIndex(index);\r\n }\r\n\r\n public selectRoot() {\r\n let marker = jsCommon.PerformanceUtil.create('selectRoot');\r\n this.onClick();\r\n marker.end();\r\n }\r\n\r\n public drag(t: DragType) {\r\n switch (t) {\r\n case DragType.Drag:\r\n this.onDrag();\r\n break;\r\n case DragType.DragEnd:\r\n this.onClick();\r\n break;\r\n default:\r\n debug.assertFail('Unknown Drag Type');\r\n }\r\n }\r\n\r\n private onDrag(): void {\r\n //find the current x and y position\r\n let xy = this.getMouseCoordinates();\r\n //move the crosshair to the current position\r\n this.moveCrosshairToXY(xy.x, xy.y);\r\n //update the style and the legend of the dots\r\n let selectedIndex = this.findClosestDotIndex(xy.x, xy.y);\r\n this.selectDot(selectedIndex);\r\n this.updateLegend(selectedIndex);\r\n }\r\n\r\n private onClick(): void {\r\n //find the current x and y position\r\n let xy = this.getMouseCoordinates();\r\n let selectedIndex = this.findClosestDotIndex(xy.x, xy.y);\r\n if (selectedIndex !== -1)\r\n this.selectDotByIndex(selectedIndex);\r\n }\r\n\r\n private getMouseCoordinates(): MouseCoordinates {\r\n let mainGfxContext = this.mainGraphicsContext;\r\n // select (0,0) in cartesian coordinates\r\n let x = 0;\r\n let y = parseInt(mainGfxContext.attr('height'), 10);\r\n y = y || 0;\r\n\r\n try {\r\n let mouse = d3.mouse(mainGfxContext.node());\r\n x = mouse[0];\r\n y = mouse[1];\r\n } catch(e){ \r\n }\r\n\r\n return { x: x, y: y, };\r\n }\r\n\r\n private selectDotByIndex(index: number): void {\r\n this.selectDot(index);\r\n this.moveCrosshairToIndexDot(index);\r\n this.updateLegend(index);\r\n }\r\n\r\n private selectDot(dotIndex: number): void {\r\n let root = this.mainGraphicsContext;\r\n\r\n root.selectAll(ScatterChartMobileBehavior.ScatterChartCircleTagName + ScatterChartMobileBehavior.DotClassSelector).classed({ selected: false, notSelected: true });\r\n root.selectAll(ScatterChartMobileBehavior.ScatterChartCircleTagName + ScatterChartMobileBehavior.DotClassSelector).filter((d, i) => {\r\n let dataPoints = this.data.dataPoints;\r\n debug.assert(dataPoints.length > dotIndex, \"dataPoints length:\" + dataPoints.length + \"is smaller than index:\" + dotIndex);\r\n let currentPoint: ScatterChartDataPoint = dataPoints[dotIndex];\r\n return (d.x === currentPoint.x) && (d.y === currentPoint.y);\r\n }).classed({ selected: true, notSelected: false });\r\n }\r\n\r\n private moveCrosshairToIndexDot(index: number): void {\r\n let dataPoints = this.data.dataPoints;\r\n let root = this.mainGraphicsContext;\r\n\r\n debug.assert(dataPoints.length > index, \"dataPoints length:\" + dataPoints.length + \"is smaller than index:\" + index);\r\n let x = this.xAxisProperties.scale(dataPoints[index].x);\r\n let y = this.yAxisProperties.scale(dataPoints[index].y);\r\n if (this.crosshair == null) {\r\n let width = +root.attr('width');\r\n let height = +root.attr('height');\r\n this.crosshair = this.drawCrosshair(root, x, y, width, height);\r\n this.crosshairHorizontal = this.crosshair.select(ScatterChartMobileBehavior.Horizontal.selector);\r\n this.crosshairVertical = this.crosshair.select(ScatterChartMobileBehavior.Vertical.selector);\r\n } else {\r\n this.moveCrosshairToXY(x, y);\r\n }\r\n }\r\n\r\n private moveCrosshairToXY(x: number, y: number): void {\r\n this.crosshairHorizontal.attr({ y1: y, y2: y });\r\n this.crosshairVertical.attr({ x1: x, x2: x });\r\n }\r\n\r\n private drawCrosshair(addTo: D3.Selection, x: number, y: number, width: number, height: number): D3.Selection {\r\n let crosshair = addTo.append(\"g\");\r\n crosshair.classed(ScatterChartMobileBehavior.CrosshairClassName, true);\r\n crosshair.append('line').classed(ScatterChartMobileBehavior.Horizontal.class, true).attr({ x1: 0, x2: width, y1: y, y2: y });\r\n crosshair.append('line').classed(ScatterChartMobileBehavior.Vertical.class, true).attr({ x1: x, x2: x, y1: height, y2: 0 });\r\n return crosshair;\r\n }\r\n\r\n private findClosestDotIndex(x: number, y: number): number {\r\n let selectedIndex = -1;\r\n let minDistance = Number.MAX_VALUE;\r\n let dataPoints = this.data.dataPoints;\r\n let xAxisPropertiesScale = this.xAxisProperties.scale;\r\n let yAxisPropertiesScale = this.yAxisProperties.scale;\r\n for (let i in dataPoints) {\r\n let currentPoint: ScatterChartDataPoint = dataPoints[i];\r\n let circleX = xAxisPropertiesScale(currentPoint.x);\r\n let circleY = yAxisPropertiesScale(currentPoint.y);\r\n let horizontalDistance = circleX - x;\r\n let verticalDistance = circleY - y;\r\n let distanceSqrd = (horizontalDistance * horizontalDistance) + (verticalDistance * verticalDistance);\r\n if (minDistance === Number.MAX_VALUE) {\r\n selectedIndex = <any>i;\r\n minDistance = distanceSqrd;\r\n }\r\n else if (minDistance && minDistance > distanceSqrd) {\r\n selectedIndex = <any>i;\r\n minDistance = distanceSqrd;\r\n }\r\n }\r\n return selectedIndex;\r\n }\r\n\r\n private updateLegend(dotIndex: number): void {\r\n if (this.lastDotIndex == null || this.lastDotIndex !== dotIndex) {//update the legend only if the data change.\r\n let legendItems = this.createLegendDataPoints(dotIndex);\r\n this.host.updateLegend(legendItems);\r\n this.lastDotIndex = dotIndex;\r\n }\r\n }\r\n\r\n private createLegendDataPoints(dotIndex: number): LegendData {\r\n let formatStringProp = scatterChartProps.general.formatString;\r\n let legendItems: LegendDataPoint[] = [];\r\n let data = this.data;\r\n debug.assert(data.dataPoints.length > dotIndex, \"dataPoints length:\" + data.dataPoints.length + \"is smaller than index:\" + dotIndex);\r\n let point = data.dataPoints[dotIndex];\r\n //set the title of the legend to be the category or radius or group or blank\r\n let blank = valueFormatter.format(null);\r\n let title = blank;\r\n let legendData = data.legendData;\r\n debug.assertValue(legendData, \"legendData\");\r\n debug.assertValue(legendData.dataPoints, \"legendData\");\r\n let legendDataPoints = legendData.dataPoints;\r\n let category = point.formattedCategory.getValue();\r\n if (category !== blank) {\r\n title = category;\r\n } else if (point.radius.sizeMeasure != null) {\r\n title = valueFormatter.format(point.radius.sizeMeasure.source.groupName);\r\n } else if (legendDataPoints.length >= dotIndex && legendDataPoints[dotIndex].label !== blank) {\r\n title = legendDataPoints[dotIndex].label;\r\n }\r\n\r\n if (data.xCol != null) {\r\n legendItems.push({\r\n category: title,\r\n color: point.fill,\r\n identity: SelectionIdBuilder.builder().withMeasure(data.xCol.queryName).createSelectionId(),\r\n selected: point.selected,\r\n icon: LegendIcon.Box,\r\n label: valueFormatter.format(this.data.axesLabels.x),\r\n measure: valueFormatter.format(point.x, valueFormatter.getFormatString(data.xCol, formatStringProp)),\r\n iconOnlyOnLabel: true,\r\n });\r\n }\r\n if (data.yCol != null) {\r\n legendItems.push({\r\n category: title,\r\n color: point.fill,\r\n identity: SelectionIdBuilder.builder().withMeasure(data.yCol.queryName).createSelectionId(),\r\n selected: point.selected,\r\n icon: LegendIcon.Box,\r\n label: valueFormatter.format(data.axesLabels.y),\r\n measure: valueFormatter.format(point.y, valueFormatter.getFormatString(data.yCol, formatStringProp)),\r\n iconOnlyOnLabel: true,\r\n });\r\n }\r\n if (data.size != null) {\r\n legendItems.push({\r\n category: title,\r\n color: point.fill,\r\n identity: SelectionIdBuilder.builder().withMeasure(data.size.queryName).createSelectionId(),\r\n selected: point.selected,\r\n icon: LegendIcon.Box,\r\n label: valueFormatter.format(data.size.displayName),\r\n measure: valueFormatter.format(point.radius.sizeMeasure.values[point.radius.index], valueFormatter.getFormatString(data.size, formatStringProp)),\r\n iconOnlyOnLabel: true\r\n });\r\n }\r\n\r\n return {dataPoints: legendItems };\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface HorizontalSlicerBehaviorOptions extends SlicerBehaviorOptions {\r\n itemsContainer: D3.Selection;\r\n }\r\n\r\n export class HorizontalSlicerWebBehavior implements IInteractiveBehavior {\r\n private itemLabels: D3.Selection;\r\n private dataPoints: SlicerDataPoint[];\r\n private interactivityService: IInteractivityService;\r\n private slicerSettings: SlicerSettings;\r\n\r\n public bindEvents(options: HorizontalSlicerBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n this.itemLabels = options.itemLabels;\r\n this.dataPoints = options.dataPoints;\r\n this.interactivityService = options.interactivityService;\r\n this.slicerSettings = options.settings;\r\n\r\n SlicerWebBehavior.bindSlicerEvents(options.slicerContainer, this.itemLabels, options.clear, selectionHandler, this.slicerSettings, this.interactivityService);\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n SlicerWebBehavior.setSelectionOnSlicerItems(this.itemLabels, this.itemLabels, hasSelection, this.interactivityService, this.slicerSettings);\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface VerticalSlicerBehaviorOptions extends SlicerBehaviorOptions {\r\n itemContainers: D3.Selection;\r\n itemInputs: D3.Selection;\r\n }\r\n\r\n export class VerticalSlicerWebBehavior implements IInteractiveBehavior {\r\n private itemLabels: D3.Selection;\r\n private itemInputs: D3.Selection;\r\n private dataPoints: SlicerDataPoint[];\r\n private interactivityService: IInteractivityService;\r\n private settings: SlicerSettings;\r\n\r\n public bindEvents(options: VerticalSlicerBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let slicers = options.itemContainers;\r\n\r\n this.itemLabels = options.itemLabels;\r\n this.itemInputs = options.itemInputs;\r\n this.dataPoints = options.dataPoints;\r\n this.interactivityService = options.interactivityService;\r\n this.settings = options.settings;\r\n\r\n SlicerWebBehavior.bindSlicerEvents(options.slicerContainer, slicers, options.clear, selectionHandler, this.settings, this.interactivityService);\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n SlicerWebBehavior.setSelectionOnSlicerItems(this.itemInputs, this.itemLabels, hasSelection, this.interactivityService, this.settings);\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import SlicerOrientation = slicerOrientation.Orientation;\r\n\r\n export interface SlicerOrientationBehaviorOptions {\r\n behaviorOptions: SlicerBehaviorOptions;\r\n orientation: slicerOrientation.Orientation;\r\n }\r\n\r\n export interface SlicerBehaviorOptions {\r\n slicerContainer: D3.Selection;\r\n itemLabels: D3.Selection;\r\n clear: D3.Selection;\r\n dataPoints: SlicerDataPoint[];\r\n interactivityService: IInteractivityService;\r\n settings: SlicerSettings;\r\n }\r\n\r\n export class SlicerWebBehavior implements IInteractiveBehavior {\r\n private behavior: IInteractiveBehavior;\r\n private static isTouch: boolean;\r\n\r\n public bindEvents(options: SlicerOrientationBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n this.behavior = this.createWebBehavior(options);\r\n this.behavior.bindEvents(options.behaviorOptions, selectionHandler);\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n this.behavior.renderSelection(hasSelection);\r\n }\r\n\r\n public static bindSlicerEvents(slicerContainer: D3.Selection, slicers: D3.Selection, slicerClear: D3.Selection, selectionHandler: ISelectionHandler, slicerSettings: SlicerSettings, interactivityService: IInteractivityService): void {\r\n SlicerWebBehavior.bindSlicerItemSelectionEvent(slicers, selectionHandler, slicerSettings, interactivityService);\r\n SlicerWebBehavior.bindSlicerClearEvent(slicerClear, selectionHandler);\r\n SlicerWebBehavior.styleSlicerContainer(slicerContainer, interactivityService);\r\n }\r\n\r\n public static setSelectionOnSlicerItems(selectableItems: D3.Selection, itemLabel: D3.Selection, hasSelection: boolean, interactivityService: IInteractivityService, slicerSettings: SlicerSettings): void {\r\n if (!hasSelection && !interactivityService.isSelectionModeInverted()) {\r\n selectableItems.filter('.selected').classed('selected', false);\r\n selectableItems.filter('.partiallySelected').classed('partiallySelected', false);\r\n let input = selectableItems.selectAll('input');\r\n if (input) {\r\n input.property('checked', false);\r\n }\r\n itemLabel.style('color', slicerSettings.slicerText.color);\r\n }\r\n else {\r\n SlicerWebBehavior.styleSlicerItems(selectableItems, hasSelection, interactivityService.isSelectionModeInverted());\r\n }\r\n }\r\n\r\n public static styleSlicerItems(slicerItems: D3.Selection, hasSelection: boolean, isSelectionInverted: boolean): void {\r\n slicerItems.each(function (d: SlicerDataPoint) {\r\n let slicerItem: HTMLElement = this;\r\n let shouldCheck: boolean = false;\r\n if (d.isSelectAllDataPoint) {\r\n if (hasSelection) {\r\n slicerItem.classList.add('partiallySelected');\r\n shouldCheck = false;\r\n }\r\n else {\r\n slicerItem.classList.remove('partiallySelected');\r\n shouldCheck = isSelectionInverted;\r\n }\r\n }\r\n else {\r\n shouldCheck = jsCommon.LogicExtensions.XOR(d.selected, isSelectionInverted);\r\n }\r\n \r\n if (shouldCheck)\r\n slicerItem.classList.add('selected');\r\n else\r\n slicerItem.classList.remove('selected');\r\n\r\n // Set input selected state to match selection\r\n let input = slicerItem.getElementsByTagName('input')[0];\r\n if (input)\r\n input.checked = shouldCheck;\r\n });\r\n }\r\n\r\n private static bindSlicerItemSelectionEvent(slicers: D3.Selection, selectionHandler: ISelectionHandler, slicerSettings: SlicerSettings, interactivityService: IInteractivityService): void {\r\n SlicerWebBehavior.isTouch = false;\r\n\r\n slicers.on(\"touchstart\", (d: SlicerDataPoint) => {\r\n SlicerWebBehavior.isTouch = true;\r\n });\r\n\r\n slicers.on(\"pointerdown\", (d: SlicerDataPoint) => {\r\n let e: PointerEvent = <any>d3.event;\r\n\r\n if (e && e.pointerType === \"touch\") {\r\n SlicerWebBehavior.isTouch = true;\r\n }\r\n });\r\n\r\n slicers.on(\"click\", (d: SlicerDataPoint) => {\r\n d3.event.preventDefault();\r\n if (d.isSelectAllDataPoint) {\r\n selectionHandler.toggleSelectionModeInversion();\r\n }\r\n else {\r\n selectionHandler.handleSelection(d, SlicerWebBehavior.isTouch || SlicerWebBehavior.isMultiSelect(d3.event, slicerSettings, interactivityService));\r\n }\r\n selectionHandler.persistSelectionFilter(slicerProps.filterPropertyIdentifier);\r\n\r\n SlicerWebBehavior.isTouch = false;\r\n });\r\n }\r\n\r\n private static bindSlicerClearEvent(slicerClear: D3.Selection, selectionHandler: ISelectionHandler): void {\r\n if (slicerClear) {\r\n slicerClear.on(\"click\", (d: SelectableDataPoint) => {\r\n selectionHandler.handleClearSelection();\r\n selectionHandler.persistSelectionFilter(slicerProps.filterPropertyIdentifier);\r\n });\r\n }\r\n }\r\n\r\n private static styleSlicerContainer(slicerContainer: D3.Selection, interactivityService: IInteractivityService) {\r\n let hasSelection = (interactivityService.hasSelection() && interactivityService.isDefaultValueEnabled() === undefined)\r\n || interactivityService.isDefaultValueEnabled() === false;\r\n slicerContainer.classed('hasSelection', hasSelection);\r\n }\r\n\r\n private static isMultiSelect(event: D3.D3Event, settings: SlicerSettings, interactivityService: IInteractivityService): boolean {\r\n // If selection is inverted, assume we're always in multi-select mode;\r\n // Also, Ctrl can be used to multi-select even in single-select mode.\r\n return interactivityService.isSelectionModeInverted()\r\n || !settings.selection.singleSelect\r\n || event.ctrlKey;\r\n }\r\n\r\n private createWebBehavior(options: SlicerOrientationBehaviorOptions): IInteractiveBehavior {\r\n let behavior: IInteractiveBehavior;\r\n let orientation = options.orientation;\r\n switch (orientation) {\r\n case SlicerOrientation.Horizontal:\r\n behavior = new HorizontalSlicerWebBehavior();\r\n break;\r\n\r\n case SlicerOrientation.Vertical:\r\n default:\r\n behavior = new VerticalSlicerWebBehavior();\r\n break;\r\n }\r\n return behavior;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface LegendBehaviorOptions {\r\n legendItems: D3.Selection;\r\n legendIcons: D3.Selection;\r\n clearCatcher: D3.Selection;\r\n }\r\n\r\n export class LegendBehavior implements IInteractiveBehavior {\r\n public static dimmedLegendColor = '#A6A6A6';\r\n private legendIcons;\r\n\r\n public bindEvents(options: LegendBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let legendItems = options.legendItems;\r\n this.legendIcons = options.legendIcons;\r\n let clearCatcher = options.clearCatcher;\r\n\r\n InteractivityUtils.registerStandardSelectionHandler(legendItems, selectionHandler);\r\n\r\n clearCatcher.on('click', () => {\r\n selectionHandler.handleClearSelection();\r\n });\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n if (hasSelection) {\r\n this.legendIcons.style({\r\n 'fill': (d: LegendDataPoint) => {\r\n if (!d.selected)\r\n return LegendBehavior.dimmedLegendColor; \r\n else\r\n return d.color;\r\n }\r\n });\r\n }\r\n else {\r\n this.legendIcons.style({\r\n 'fill': (d: LegendDataPoint) => {\r\n return d.color;\r\n }\r\n });\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface TreemapBehaviorOptions {\r\n shapes: D3.Selection;\r\n highlightShapes: D3.Selection;\r\n majorLabels: D3.Selection;\r\n minorLabels: D3.Selection;\r\n nodes: TreemapNode[];\r\n hasHighlights: boolean;\r\n }\r\n\r\n export class TreemapWebBehavior implements IInteractiveBehavior {\r\n private shapes: D3.Selection;\r\n private highlightShapes: D3.Selection;\r\n private hasHighlights: boolean;\r\n\r\n public bindEvents(options: TreemapBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let shapes = this.shapes = options.shapes;\r\n let highlightShapes = this.highlightShapes = options.highlightShapes;\r\n let majorLabels = options.majorLabels;\r\n let minorLabels = options.minorLabels;\r\n this.hasHighlights = options.hasHighlights;\r\n\r\n InteractivityUtils.registerStandardInteractivityHandlers(shapes, selectionHandler);\r\n InteractivityUtils.registerStandardInteractivityHandlers(highlightShapes, selectionHandler);\r\n\r\n if (majorLabels) {\r\n InteractivityUtils.registerStandardInteractivityHandlers(majorLabels, selectionHandler);\r\n }\r\n if (minorLabels) {\r\n InteractivityUtils.registerStandardInteractivityHandlers(minorLabels, selectionHandler);\r\n }\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n let hasHighlights = this.hasHighlights;\r\n this.shapes\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, /* isHighlightRect */ false))\r\n .style(\"fill-opacity\", (d: TreemapNode) => Treemap.getFillOpacity(d, hasSelection, !d.selected && hasHighlights, /* isHighlightRect */ false));\r\n this.highlightShapes\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, /* isHighlightRect */ true))\r\n .style(\"fill-opacity\", (d: TreemapNode) => Treemap.getFillOpacity(d, hasSelection, !d.selected && hasHighlights, /* isHighlightRect */ true));\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface WaterfallChartBehaviorOptions {\r\n bars: D3.Selection;\r\n }\r\n\r\n export class WaterfallChartWebBehavior {\r\n private bars: D3.Selection;\r\n\r\n public bindEvents(options: WaterfallChartBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let bars = this.bars = options.bars;\r\n\r\n bars.on('click', (d: WaterfallChartDataPoint) => {\r\n if (!d.isTotal) {\r\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\r\n }\r\n });\r\n\r\n bars.on('contextmenu', (d: WaterfallChartDataPoint) => {\r\n if (d3.event.ctrlKey)\r\n return;\r\n\r\n d3.event.preventDefault();\r\n\r\n if (!d.isTotal) {\r\n let position = InteractivityUtils.getPositionOfLastInputEvent();\r\n selectionHandler.handleContextMenu(d, position);\r\n }\r\n });\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n this.bars.style(\"fill-opacity\", (d: WaterfallChartDataPoint) => d.isTotal ? ColumnUtil.DefaultOpacity : ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, false));\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface LabelsBehaviorOptions {\r\n labelItems: D3.Selection;\r\n }\r\n\r\n export class LabelsBehavior implements IInteractiveBehavior {\r\n public static DefaultLabelOpacity = 1;\r\n public static DimmedLabelOpacity = 0.6;\r\n private labelItems: D3.Selection;\r\n\r\n public bindEvents(options: LabelsBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n this.labelItems = options.labelItems;\r\n\r\n InteractivityUtils.registerStandardSelectionHandler(this.labelItems, selectionHandler);\r\n }\r\n\r\n public renderSelection(hasSelection: boolean): void {\r\n if (hasSelection) {\r\n this.labelItems.style({\r\n 'opacity': (d: Label) => {\r\n if (!d.selected)\r\n return LabelsBehavior.DimmedLabelOpacity;\r\n else\r\n return LabelsBehavior.DefaultLabelOpacity;\r\n }\r\n });\r\n }\r\n else {\r\n this.labelItems.style({\r\n 'opacity': LabelsBehavior.DefaultLabelOpacity,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface CartesianBehaviorOptions {\r\n layerOptions: any[];\r\n clearCatcher: D3.Selection;\r\n }\r\n\r\n export class CartesianChartBehavior implements IInteractiveBehavior {\r\n private behaviors: IInteractiveBehavior[];\r\n\r\n constructor(behaviors: IInteractiveBehavior[]) {\r\n this.behaviors = behaviors;\r\n }\r\n\r\n public bindEvents(options: CartesianBehaviorOptions, selectionHandler: ISelectionHandler): void {\r\n let behaviors = this.behaviors;\r\n for (let i = 0, ilen = behaviors.length; i < ilen; i++) {\r\n behaviors[i].bindEvents(options.layerOptions[i], selectionHandler);\r\n }\r\n\r\n options.clearCatcher.on('click', () => {\r\n selectionHandler.handleClearSelection();\r\n });\r\n }\r\n\r\n public renderSelection(hasSelection: boolean) {\r\n for (let behavior of this.behaviors) {\r\n behavior.renderSelection(hasSelection);\r\n }\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ITextAsSVGMeasurer = powerbi.ITextAsSVGMeasurer;\r\n\r\n /**\r\n * Default ranges are for when we have a field chosen for the axis,\r\n * but no values are returned by the query.\r\n */\r\n export const emptyDomain = [0, 0];\r\n\r\n export interface IAxisProperties {\r\n /** \r\n * The D3 Scale object.\r\n */\r\n scale: D3.Scale.GenericScale<any>;\r\n /** \r\n * The D3 Axis object.\r\n */\r\n axis: D3.Svg.Axis;\r\n /**\r\n * An array of the tick values to display for this axis.\r\n */\r\n values: any[];\r\n /** \r\n * The ValueType of the column used for this axis.\r\n */\r\n axisType: ValueType;\r\n /**\r\n * A formatter with appropriate properties configured for this field.\r\n */\r\n formatter: IValueFormatter;\r\n /**\r\n * The axis title label.\r\n */\r\n axisLabel: string;\r\n /**\r\n * Cartesian axes are either a category or value axis.\r\n */\r\n isCategoryAxis: boolean; \r\n /** \r\n * (optional) The max width for category tick label values. used for ellipsis truncation / label rotation.\r\n */\r\n xLabelMaxWidth?: number;\r\n /** \r\n * (optional) The thickness of each category on the axis.\r\n */\r\n categoryThickness?: number;\r\n /** \r\n * (optional) The outer padding in pixels applied to the D3 scale.\r\n */\r\n outerPadding?: number;\r\n /** \r\n * (optional) Whether we are using a default domain.\r\n */\r\n usingDefaultDomain?: boolean;\r\n /** \r\n * (optional) do default d3 axis labels fit?\r\n */\r\n willLabelsFit?: boolean;\r\n /**\r\n * (optional) word break axis labels\r\n */\r\n willLabelsWordBreak?: boolean;\r\n /** \r\n * (optional) Whether log scale is possible on the current domain.\r\n */\r\n isLogScaleAllowed?: boolean;\r\n /** \r\n * (optional) Whether domain contains zero value and log scale is enabled.\r\n */\r\n hasDisallowedZeroInDomain?: boolean;\r\n /** \r\n *(optional) The original data domain. Linear scales use .nice() to round to cleaner edge values. Keep the original data domain for later.\r\n */\r\n dataDomain?: number[];\r\n /** \r\n * (optional) The D3 graphics context for this axis\r\n */\r\n graphicsContext?: D3.Selection;\r\n }\r\n\r\n export interface IMargin {\r\n top: number;\r\n bottom: number;\r\n left: number;\r\n right: number;\r\n }\r\n\r\n export interface CreateAxisOptions {\r\n /**\r\n * The dimension length for the axis, in pixels.\r\n */\r\n pixelSpan: number;\r\n /** \r\n * The data domain. [min, max] for a scalar axis, or [1...n] index array for ordinal.\r\n */\r\n dataDomain: number[];\r\n /** \r\n * The DataViewMetadataColumn will be used for dataType and tick value formatting.\r\n */\r\n metaDataColumn: DataViewMetadataColumn; //TODO: remove this, we should just be passing in the formatString and the ValueType, not this DataView-specific object\r\n /**\r\n * The format string.\r\n */\r\n formatString: string;\r\n /** \r\n * outerPadding to be applied to the axis.\r\n */\r\n outerPadding: number; \r\n /** \r\n * Indicates if this is the category axis.\r\n */\r\n isCategoryAxis?: boolean;\r\n /**\r\n * If true and the dataType is numeric or dateTime,\r\n * create a linear axis, else create an ordinal axis.\r\n */\r\n isScalar?: boolean;\r\n /**\r\n * (optional) The scale is inverted for a vertical axis,\r\n * and different optimizations are made for tick labels.\r\n */\r\n isVertical?: boolean;\r\n /** \r\n * (optional) For visuals that do not need zero (e.g. column/bar) use tickInterval.\r\n */\r\n useTickIntervalForDisplayUnits?: boolean;\r\n /**\r\n * (optional) Combo charts can override the tick count to\r\n * align y1 and y2 grid lines.\r\n */\r\n forcedTickCount?: number;\r\n /** \r\n * (optional) Callback for looking up actual values from indices, \r\n * used when formatting tick labels. \r\n */\r\n getValueFn?: (index: number, type: ValueType) => any;\r\n /**\r\n * (optional) The width/height of each category on the axis.\r\n */\r\n categoryThickness?: number;\r\n /** (optional) the scale type of the axis. e.g. log, linear */\r\n scaleType?: string;\r\n /** (optional) user selected display units */\r\n axisDisplayUnits?: number;\r\n /** (optional) user selected precision */\r\n axisPrecision?: number;\r\n /** (optional) for 100 percent stacked charts, causes formatString override and minTickInterval adjustments */\r\n is100Pct?: boolean;\r\n /** (optional) sets clamping on the D3 scale, useful for drawing column chart rectangles as it simplifies the math during layout */\r\n shouldClamp?: boolean;\r\n }\r\n\r\n export interface CreateScaleResult {\r\n scale: D3.Scale.GenericScale<any>;\r\n bestTickCount: number;\r\n usingDefaultDomain?: boolean;\r\n }\r\n\r\n export interface TickLabelMargins {\r\n xMax: number;\r\n yLeft: number;\r\n yRight: number;\r\n }\r\n\r\n export module AxisHelper {\r\n let XLabelMaxAllowedOverflow = 35;\r\n let TextHeightConstant = 10;\r\n let MinTickCount = 2;\r\n let DefaultBestTickCount = 3;\r\n let LeftPadding = 10;\r\n let ScalarTickLabelPadding = 3;\r\n\r\n export function getRecommendedNumberOfTicksForXAxis(availableWidth: number) {\r\n if (availableWidth < 300)\r\n return 3;\r\n if (availableWidth < 500)\r\n return 5;\r\n\r\n return 8;\r\n }\r\n\r\n export function getRecommendedNumberOfTicksForYAxis(availableWidth: number) {\r\n if (availableWidth < 150)\r\n return 3;\r\n if (availableWidth < 300)\r\n return 5;\r\n\r\n return 8;\r\n }\r\n\r\n /**\r\n * Get the best number of ticks based on minimum value, maximum value,\r\n * measure metadata and max tick count.\r\n * \r\n * @param min The minimum of the data domain.\r\n * @param max The maximum of the data domain.\r\n * @param valuesMetadata The measure metadata array.\r\n * @param maxTickCount The max count of intervals.\r\n * @param isDateTime - flag to show single tick when min is equal to max.\r\n */\r\n export function getBestNumberOfTicks(min: number, max: number, valuesMetadata: DataViewMetadataColumn[], maxTickCount: number, isDateTime?: boolean): number {\r\n debug.assert(maxTickCount >= 0, \"maxTickCount must be greater or equal to zero\");\r\n\r\n if (isNaN(min) || isNaN(max))\r\n return DefaultBestTickCount;\r\n\r\n debug.assert(min <= max, \"min value needs to be less or equal to max value\");\r\n\r\n if (maxTickCount <= 1 || (max <= 1 && min >= -1))\r\n return maxTickCount;\r\n\r\n if (min === max) {\r\n // datetime needs to only show one tick value in this case so formatting works correctly\r\n if (!!isDateTime)\r\n return 1;\r\n return DefaultBestTickCount;\r\n }\r\n\r\n if (hasNonIntegerData(valuesMetadata))\r\n return maxTickCount;\r\n\r\n // e.g. 5 - 2 + 1 = 4, => [2,3,4,5]\r\n return Math.min(max - min + 1, maxTickCount);\r\n }\r\n\r\n export function hasNonIntegerData(valuesMetadata: DataViewMetadataColumn[]): boolean {\r\n for (let i = 0, len = valuesMetadata.length; i < len; i++) {\r\n let currentMetadata = valuesMetadata[i];\r\n if (currentMetadata && currentMetadata.type && !currentMetadata.type.integer) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n export function getRecommendedTickValues(maxTicks: number,\r\n scale: D3.Scale.GenericScale<any>,\r\n axisType: ValueType,\r\n isScalar: boolean,\r\n minTickInterval?: number): any[] {\r\n\r\n if (!isScalar || isOrdinalScale(scale)) {\r\n return getRecommendedTickValuesForAnOrdinalRange(maxTicks, scale.domain());\r\n }\r\n else if (isDateTime(axisType)) {\r\n return getRecommendedTickValuesForADateTimeRange(maxTicks, scale.domain());\r\n }\r\n return getRecommendedTickValuesForAQuantitativeRange(maxTicks, scale, minTickInterval);\r\n }\r\n\r\n export function getRecommendedTickValuesForAnOrdinalRange(maxTicks: number, labels: string[]): string[] {\r\n let tickLabels: string[] = [];\r\n\r\n // return no ticks in this case\r\n if (maxTicks <= 0)\r\n return tickLabels;\r\n\r\n let len = labels.length;\r\n if (maxTicks > len)\r\n return labels;\r\n\r\n for (let i = 0, step = Math.ceil(len / maxTicks); i < len; i += step) {\r\n tickLabels.push(labels[i]);\r\n }\r\n return tickLabels;\r\n }\r\n\r\n export function getRecommendedTickValuesForAQuantitativeRange(maxTicks: number, scale: D3.Scale.GenericScale<any>, minInterval?: number): number[] {\r\n let tickLabels: number[] = [];\r\n\r\n //if maxticks is zero return none\r\n if (maxTicks === 0)\r\n return tickLabels;\r\n\r\n let quantitiveScale = <D3.Scale.QuantitativeScale>scale;\r\n if (quantitiveScale.ticks) {\r\n tickLabels = quantitiveScale.ticks(maxTicks);\r\n if (tickLabels.length > maxTicks && maxTicks > 1)\r\n tickLabels = quantitiveScale.ticks(maxTicks - 1);\r\n if (tickLabels.length < MinTickCount) {\r\n tickLabels = quantitiveScale.ticks(maxTicks + 1);\r\n }\r\n tickLabels = createTrueZeroTickLabel(tickLabels);\r\n\r\n if (minInterval && tickLabels.length > 1) {\r\n let tickInterval = tickLabels[1] - tickLabels[0];\r\n while (tickInterval > 0 && tickInterval < minInterval) {\r\n for (let i = 1; i < tickLabels.length; i++) {\r\n tickLabels.splice(i, 1);\r\n }\r\n\r\n tickInterval = tickInterval * 2;\r\n }\r\n // keep at least two labels - the loop above may trim all but one if we have odd # of tick labels and dynamic range < minInterval\r\n if (tickLabels.length === 1) {\r\n tickLabels.push(tickLabels[0] + minInterval);\r\n }\r\n }\r\n return tickLabels;\r\n }\r\n\r\n debug.assertFail('must pass a quantitative scale to this method');\r\n\r\n return tickLabels;\r\n }\r\n\r\n /** \r\n * Round out very small zero tick values (e.g. -1e-33 becomes 0).\r\n * \r\n * @param ticks Array of numbers (from d3.scale.ticks([maxTicks])).\r\n * @param epsilon Max ratio of calculated tick interval which we will recognize as zero.\r\n * \r\n * e.g.\r\n * ticks = [-2, -1, 1e-10, 3, 4]; epsilon = 1e-5;\r\n * closeZero = 1e-5 * | 2 - 1 | = 1e-5\r\n * // Tick values <= 1e-5 replaced with 0\r\n * return [-2, -1, 0, 3, 4];\r\n */\r\n function createTrueZeroTickLabel(ticks: number[], epsilon: number = 1e-5): number[] {\r\n if (!ticks || ticks.length < 2)\r\n return ticks;\r\n\r\n let closeZero = epsilon * Math.abs(ticks[1] - ticks[0]);\r\n\r\n return ticks.map((tick) => Math.abs(tick) <= closeZero ? 0 : tick);\r\n }\r\n\r\n function getRecommendedTickValuesForADateTimeRange(maxTicks: number, dataDomain: number[]): number[] {\r\n let tickLabels: number[] = [];\r\n\r\n if (dataDomain[0] === 0 && dataDomain[1] === 0)\r\n return [];\r\n\r\n let dateTimeTickLabels = DateTimeSequence.calculate(new Date(dataDomain[0]), new Date(dataDomain[1]), maxTicks).sequence;\r\n tickLabels = dateTimeTickLabels.map(d => d.getTime());\r\n tickLabels = ensureValuesInRange(tickLabels, dataDomain[0], dataDomain[1]);\r\n return tickLabels;\r\n }\r\n\r\n function normalizeLinearDomain(domain: NumberRange): NumberRange {\r\n if (isNaN(domain.min) || isNaN(domain.max)) {\r\n domain.min = emptyDomain[0];\r\n domain.max = emptyDomain[1];\r\n }\r\n else if (domain.min === domain.max) {\r\n // d3 linear scale will give zero tickValues if max === min, so extend a little\r\n domain.min = domain.min < 0 ? domain.min * 1.2 : domain.min * 0.8;\r\n domain.max = domain.max < 0 ? domain.max * 0.8 : domain.max * 1.2;\r\n }\r\n else {\r\n // Check that min is very small and is a negligable portion of the whole domain.\r\n // (fix floating pt precision bugs)\r\n // sometimes highlight value math causes small negative numbers which makes the axis add\r\n // a large tick interval instead of just rendering at zero.\r\n if (Math.abs(domain.min) < 0.0001 && domain.min / (domain.max - domain.min) < 0.0001) {\r\n domain.min = 0;\r\n }\r\n }\r\n\r\n return domain;\r\n }\r\n\r\n export function getMargin(availableWidth: number, availableHeight: number, xMargin: number, yMargin: number): IMargin {\r\n if (getRecommendedNumberOfTicksForXAxis(availableWidth - xMargin) === 0\r\n || getRecommendedNumberOfTicksForYAxis(availableHeight - yMargin) === 0) {\r\n return {\r\n top: 0,\r\n right: xMargin,\r\n bottom: yMargin,\r\n left: 0\r\n };\r\n }\r\n\r\n return {\r\n top: 20,\r\n right: 30,\r\n bottom: 40,\r\n left: 30\r\n };\r\n } \r\n\r\n // TODO: Put the parameters into one object\r\n export function getTickLabelMargins(\r\n viewport: IViewport,\r\n yMarginLimit: number,\r\n textWidthMeasurer: ITextAsSVGMeasurer,\r\n textHeightMeasurer: ITextAsSVGMeasurer,\r\n axes: CartesianAxisProperties,\r\n bottomMarginLimit: number,\r\n properties: TextProperties,\r\n scrollbarVisible?: boolean,\r\n showOnRight?: boolean,\r\n renderXAxis?: boolean,\r\n renderY1Axis?: boolean,\r\n renderY2Axis?: boolean): TickLabelMargins /*IMargin - can't update this because custom visuals use it*/ {\r\n\r\n debug.assertValue(axes, 'axes');\r\n let xAxisProperties: IAxisProperties = axes.x;\r\n let y1AxisProperties: IAxisProperties = axes.y1;\r\n let y2AxisProperties: IAxisProperties = axes.y2;\r\n\r\n debug.assertValue(viewport, 'viewport');\r\n debug.assertValue(textWidthMeasurer, 'textWidthMeasurer');\r\n debug.assertValue(textHeightMeasurer, 'textHeightMeasurer');\r\n debug.assertValue(xAxisProperties, 'xAxis');\r\n debug.assertValue(y1AxisProperties, 'yAxis');\r\n\r\n let xLabels = xAxisProperties.values;\r\n let y1Labels = y1AxisProperties.values;\r\n\r\n let leftOverflow = 0;\r\n let rightOverflow = 0;\r\n let maxWidthY1 = 0;\r\n let maxWidthY2 = 0;\r\n let xMax = 0; // bottom margin\r\n let ordinalLabelOffset = xAxisProperties.categoryThickness ? xAxisProperties.categoryThickness / 2 : 0;\r\n let scaleIsOrdinal = isOrdinalScale(xAxisProperties.scale);\r\n\r\n let xLabelOuterPadding = 0;\r\n if (xAxisProperties.outerPadding !== undefined) {\r\n xLabelOuterPadding = xAxisProperties.outerPadding;\r\n }\r\n else if (xAxisProperties.xLabelMaxWidth !== undefined) {\r\n xLabelOuterPadding = Math.max(0, (viewport.width - xAxisProperties.xLabelMaxWidth * xLabels.length) / 2);\r\n }\r\n\r\n if (getRecommendedNumberOfTicksForXAxis(viewport.width) !== 0\r\n || getRecommendedNumberOfTicksForYAxis(viewport.height) !== 0) {\r\n let rotation;\r\n if (scrollbarVisible)\r\n rotation = LabelLayoutStrategy.DefaultRotationWithScrollbar;\r\n else\r\n rotation = LabelLayoutStrategy.DefaultRotation;\r\n\r\n if (renderY1Axis) {\r\n for (let i = 0, len = y1Labels.length; i < len; i++) {\r\n properties.text = y1Labels[i];\r\n maxWidthY1 = Math.max(maxWidthY1, textWidthMeasurer(properties));\r\n }\r\n }\r\n\r\n if (y2AxisProperties && renderY2Axis) {\r\n let y2Labels = y2AxisProperties.values;\r\n for (let i = 0, len = y2Labels.length; i < len; i++) {\r\n properties.text = y2Labels[i];\r\n maxWidthY2 = Math.max(maxWidthY2, textWidthMeasurer(properties));\r\n }\r\n }\r\n\r\n let textHeight = textHeightMeasurer(properties);\r\n let maxNumLines = Math.floor(bottomMarginLimit / textHeight);\r\n let xScale = xAxisProperties.scale;\r\n let xDomain = xScale.domain();\r\n if (renderXAxis && xLabels.length > 0) {\r\n for (let i = 0, len = xLabels.length; i < len; i++) {\r\n // find the max height of the x-labels, perhaps rotated or wrapped\r\n let height: number;\r\n properties.text = xLabels[i];\r\n let width = textWidthMeasurer(properties);\r\n if (xAxisProperties.willLabelsWordBreak) {\r\n // Split label and count rows\r\n let wordBreaks = jsCommon.WordBreaker.splitByWidth(properties.text, properties, textWidthMeasurer, xAxisProperties.xLabelMaxWidth, maxNumLines);\r\n height = wordBreaks.length * textHeight;\r\n // word wrapping will truncate at xLabelMaxWidth\r\n width = xAxisProperties.xLabelMaxWidth;\r\n }\r\n else if (!xAxisProperties.willLabelsFit && scaleIsOrdinal) {\r\n height = width * rotation.sine;\r\n width = width * rotation.cosine;\r\n }\r\n else {\r\n height = TextHeightConstant;\r\n }\r\n\r\n // calculate left and right overflow due to wide X labels\r\n // (Note: no right overflow when rotated)\r\n if (i === 0) {\r\n if (scaleIsOrdinal) {\r\n if (!xAxisProperties.willLabelsFit /*rotated text*/)\r\n leftOverflow = width - ordinalLabelOffset - xLabelOuterPadding;\r\n else\r\n leftOverflow = (width / 2) - ordinalLabelOffset - xLabelOuterPadding;\r\n leftOverflow = Math.max(leftOverflow, 0);\r\n }\r\n else if (xDomain.length > 1) {\r\n // Scalar - do some math\r\n let xPos = xScale(xDomain[0]);\r\n // xPos already incorporates xLabelOuterPadding, don't subtract it twice\r\n leftOverflow = (width / 2) - xPos;\r\n leftOverflow = Math.max(leftOverflow, 0);\r\n }\r\n } else if (i === len - 1) {\r\n if (scaleIsOrdinal) {\r\n // if we are rotating text (!willLabelsFit) there won't be any right overflow\r\n if (xAxisProperties.willLabelsFit || xAxisProperties.willLabelsWordBreak) {\r\n // assume this label is placed near the edge\r\n rightOverflow = (width / 2) - ordinalLabelOffset - xLabelOuterPadding;\r\n rightOverflow = Math.max(rightOverflow, 0);\r\n }\r\n }\r\n else if (xDomain.length > 1) {\r\n // Scalar - do some math\r\n let xPos = xScale(xDomain[1]);\r\n // xPos already incorporates xLabelOuterPadding, don't subtract it twice\r\n rightOverflow = (width / 2) - (viewport.width - xPos);\r\n rightOverflow = Math.max(rightOverflow, 0);\r\n }\r\n }\r\n\r\n xMax = Math.max(xMax, height);\r\n }\r\n // trim any actual overflow to the limit\r\n leftOverflow = Math.min(leftOverflow, XLabelMaxAllowedOverflow);\r\n rightOverflow = Math.min(rightOverflow, XLabelMaxAllowedOverflow);\r\n }\r\n }\r\n\r\n let rightMargin = 0,\r\n leftMargin = 0,\r\n bottomMargin = Math.min(Math.ceil(xMax), bottomMarginLimit);\r\n\r\n if (showOnRight) {\r\n leftMargin = Math.min(Math.max(leftOverflow, maxWidthY2), yMarginLimit);\r\n rightMargin = Math.min(Math.max(rightOverflow, maxWidthY1), yMarginLimit);\r\n }\r\n else {\r\n leftMargin = Math.min(Math.max(leftOverflow, maxWidthY1), yMarginLimit);\r\n rightMargin = Math.min(Math.max(rightOverflow, maxWidthY2), yMarginLimit);\r\n }\r\n \r\n return {\r\n xMax: Math.ceil(bottomMargin),\r\n yLeft: Math.ceil(leftMargin),\r\n yRight: Math.ceil(rightMargin),\r\n };\r\n }\r\n\r\n export function columnDataTypeHasValue(dataType: ValueTypeDescriptor) {\r\n return dataType && (dataType.bool || dataType.numeric || dataType.text || dataType.dateTime);\r\n }\r\n\r\n export function createOrdinalType(): ValueType {\r\n return ValueType.fromDescriptor({ text: true });\r\n }\r\n\r\n export function isOrdinal(type: ValueTypeDescriptor): boolean {\r\n return !!(type && (type.text || type.bool));\r\n }\r\n\r\n export function isOrdinalScale(scale: any): boolean {\r\n return typeof scale.invert === 'undefined';\r\n }\r\n\r\n export function isDateTime(type: ValueTypeDescriptor): boolean {\r\n return !!(type && type.dateTime);\r\n }\r\n\r\n export function invertScale(scale: any, x) {\r\n if (isOrdinalScale(scale)) {\r\n return invertOrdinalScale(scale, x);\r\n }\r\n return scale.invert(x);\r\n }\r\n\r\n export function extent(scale: any): number[] {\r\n if (isOrdinalScale(scale)) {\r\n return scale.rangeExtent();\r\n }\r\n return scale.range();\r\n }\r\n\r\n export function invertOrdinalScale(scale: D3.Scale.OrdinalScale, x: number) {\r\n let leftEdges = scale.range();\r\n if (leftEdges.length < 2)\r\n return 0;\r\n\r\n let width = scale.rangeBand();\r\n let halfInnerPadding = (leftEdges[1] - leftEdges[0] - width) / 2;\r\n\r\n let j;\r\n for (j = 0; x > (leftEdges[j] + width + halfInnerPadding) && j < (leftEdges.length - 1); j++)\r\n ;\r\n return scale.domain()[j];\r\n }\r\n\r\n export function findClosestXAxisIndex(categoryValue: number, categoryAxisValues: CartesianDataPoint[]): number {\r\n let closestValueIndex: number = -1;\r\n let minDistance = Number.MAX_VALUE;\r\n for (let i in categoryAxisValues) {\r\n let distance = Math.abs(categoryValue - categoryAxisValues[i].categoryValue);\r\n if (distance < minDistance) {\r\n minDistance = distance;\r\n closestValueIndex = parseInt(i, 10);\r\n }\r\n }\r\n return closestValueIndex;\r\n }\r\n\r\n export function lookupOrdinalIndex(scale: D3.Scale.OrdinalScale, pixelValue: number): number {\r\n let closestValueIndex: number = -1;\r\n let minDistance = Number.MAX_VALUE;\r\n let domain = scale.domain();\r\n if (domain.length < 2)\r\n return 0;\r\n var halfWidth = (scale(1) - scale(0)) / 2;\r\n for (let idx in domain) {\r\n let leftEdgeInPixels = scale(idx);\r\n var midPoint = leftEdgeInPixels + halfWidth;\r\n let distance = Math.abs(pixelValue - midPoint);\r\n if (distance < minDistance) {\r\n minDistance = distance;\r\n closestValueIndex = parseInt(idx, 10);\r\n }\r\n }\r\n return closestValueIndex;\r\n }\r\n\r\n /** scale(value1) - scale(value2) with zero checking and min(+/-1, result) */\r\n export function diffScaled(\r\n scale: D3.Scale.GenericScale<any>,\r\n value1: any,\r\n value2: any): number {\r\n debug.assertValue(scale, 'scale');\r\n\r\n let value: number = scale(value1) - scale(value2);\r\n if (value === 0)\r\n return 0;\r\n\r\n if (value < 0)\r\n return Math.min(value, -1);\r\n return Math.max(value, 1);\r\n }\r\n\r\n export function createDomain(data: CartesianSeries[], axisType: ValueTypeDescriptor, isScalar: boolean, forcedScalarDomain: any[], ensureDomain?: NumberRange): number[] {\r\n if (isScalar && !isOrdinal(axisType)) {\r\n let userMin, userMax;\r\n if (forcedScalarDomain && forcedScalarDomain.length === 2) {\r\n userMin = forcedScalarDomain[0];\r\n userMax = forcedScalarDomain[1];\r\n }\r\n return createScalarDomain(data, userMin, userMax, axisType, ensureDomain);\r\n }\r\n\r\n return createOrdinalDomain(data);\r\n }\r\n\r\n export function ensureValuesInRange(values: number[], min: number, max: number): number[] {\r\n debug.assert(min <= max, \"min must be less or equal to max\");\r\n let filteredValues = values.filter(v => v >= min && v <= max);\r\n if (filteredValues.length < 2)\r\n filteredValues = [min, max];\r\n return filteredValues;\r\n }\r\n\r\n /**\r\n * Gets the ValueType of a category column, defaults to Text if the type is not present.\r\n */\r\n export function getCategoryValueType(metadataColumn: DataViewMetadataColumn, isScalar?: boolean): ValueType {\r\n if (metadataColumn && columnDataTypeHasValue(metadataColumn.type))\r\n return <ValueType>metadataColumn.type;\r\n\r\n if (isScalar) {\r\n return ValueType.fromDescriptor({ numeric: true });\r\n }\r\n\r\n return ValueType.fromDescriptor({ text: true });\r\n }\r\n\r\n /**\r\n * Create a D3 axis including scale. Can be vertical or horizontal, and either datetime, numeric, or text.\r\n * @param options The properties used to create the axis.\r\n */\r\n export function createAxis(options: CreateAxisOptions): IAxisProperties {\r\n let pixelSpan = options.pixelSpan,\r\n dataDomain = options.dataDomain,\r\n metaDataColumn = options.metaDataColumn,\r\n formatString = options.formatString,\r\n outerPadding = options.outerPadding || 0,\r\n isCategoryAxis = !!options.isCategoryAxis,\r\n isScalar = !!options.isScalar,\r\n isVertical = !!options.isVertical,\r\n useTickIntervalForDisplayUnits = !!options.useTickIntervalForDisplayUnits, // DEPRECATE: same meaning as isScalar?\r\n getValueFn = options.getValueFn,\r\n categoryThickness = options.categoryThickness,\r\n axisDisplayUnits = options.axisDisplayUnits,\r\n axisPrecision = options.axisPrecision,\r\n is100Pct = !!options.is100Pct;\r\n\r\n let dataType: ValueType = AxisHelper.getCategoryValueType(metaDataColumn, isScalar);\r\n\r\n // Create the Scale\r\n let scaleResult: CreateScaleResult = AxisHelper.createScale(options);\r\n let scale = scaleResult.scale;\r\n let bestTickCount = scaleResult.bestTickCount;\r\n let scaleDomain = scale.domain();\r\n let isLogScaleAllowed = AxisHelper.isLogScalePossible(dataDomain, dataType);\r\n\r\n // fix categoryThickness if scalar and the domain was adjusted when making the scale \"nice\"\r\n if (categoryThickness && isScalar && dataDomain && dataDomain.length === 2) {\r\n let oldSpan = dataDomain[1] - dataDomain[0];\r\n let newSpan = scaleDomain[1] - scaleDomain[0];\r\n if (oldSpan > 0 && newSpan > 0) {\r\n categoryThickness = categoryThickness * oldSpan / newSpan;\r\n }\r\n }\r\n\r\n // Prepare Tick Values for formatting\r\n let tickValues: any[];\r\n if (isScalar && bestTickCount === 1) {\r\n tickValues = [dataDomain[0]];\r\n }\r\n else {\r\n let minTickInterval = isScalar ? getMinTickValueInterval(formatString, dataType, is100Pct) : undefined;\r\n tickValues = getRecommendedTickValues(bestTickCount, scale, dataType, isScalar, minTickInterval);\r\n }\r\n\r\n if (options.scaleType && options.scaleType === axisScale.log && isLogScaleAllowed) {\r\n tickValues = tickValues.filter((d) => { return AxisHelper.powerOfTen(d); });\r\n }\r\n\r\n let formatter = createFormatter(\r\n scaleDomain,\r\n dataDomain,\r\n dataType,\r\n isScalar,\r\n formatString,\r\n bestTickCount,\r\n tickValues,\r\n getValueFn,\r\n useTickIntervalForDisplayUnits,\r\n axisDisplayUnits,\r\n axisPrecision);\r\n\r\n // sets default orientation only, cartesianChart will fix y2 for comboChart\r\n // tickSize(pixelSpan) is used to create gridLines\r\n let axis = d3.svg.axis()\r\n .scale(scale)\r\n .tickSize(6, 0)\r\n .orient(isVertical ? 'left' : 'bottom')\r\n .ticks(bestTickCount)\r\n .tickValues(tickValues);\r\n\r\n let formattedTickValues = [];\r\n if (metaDataColumn)\r\n formattedTickValues = formatAxisTickValues(axis, tickValues, formatter, dataType, getValueFn);\r\n\r\n let xLabelMaxWidth;\r\n // Use category layout of labels if specified, otherwise use scalar layout of labels\r\n if (!isScalar && categoryThickness) {\r\n xLabelMaxWidth = Math.max(1, categoryThickness - CartesianChart.TickLabelPadding * 2);\r\n }\r\n else {\r\n // When there are 0 or 1 ticks, then xLabelMaxWidth = pixelSpan \r\n xLabelMaxWidth = tickValues.length > 1 ? getScalarLabelMaxWidth(scale, tickValues) : pixelSpan;\r\n xLabelMaxWidth = xLabelMaxWidth - ScalarTickLabelPadding * 2;\r\n }\r\n\r\n return {\r\n scale: scale,\r\n axis: axis,\r\n formatter: formatter,\r\n values: formattedTickValues,\r\n axisType: dataType,\r\n axisLabel: null,\r\n isCategoryAxis: isCategoryAxis,\r\n xLabelMaxWidth: xLabelMaxWidth,\r\n categoryThickness: categoryThickness,\r\n outerPadding: outerPadding,\r\n usingDefaultDomain: scaleResult.usingDefaultDomain,\r\n isLogScaleAllowed: isLogScaleAllowed,\r\n dataDomain: dataDomain,\r\n };\r\n }\r\n\r\n function getScalarLabelMaxWidth(scale: D3.Scale.GenericScale<any>, tickValues: number[]): number {\r\n debug.assertValue(scale, \"scale\");\r\n debug.assertNonEmpty(tickValues, \"tickValues\");\r\n // find the distance between two ticks. scalar ticks can be anywhere, such as:\r\n // |---50----------100--------|\r\n if (scale && !_.isEmpty(tickValues)) {\r\n return Math.abs(scale(tickValues[1]) - scale(tickValues[0]));\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n export function createScale(options: CreateAxisOptions): CreateScaleResult {\r\n let pixelSpan = options.pixelSpan,\r\n dataDomain = options.dataDomain,\r\n metaDataColumn = options.metaDataColumn,\r\n outerPadding = options.outerPadding || 0,\r\n isScalar = !!options.isScalar,\r\n isVertical = !!options.isVertical,\r\n forcedTickCount = options.forcedTickCount,\r\n categoryThickness = options.categoryThickness,\r\n shouldClamp = !!options.shouldClamp;\r\n\r\n let dataType: ValueType = AxisHelper.getCategoryValueType(metaDataColumn, isScalar);\r\n let maxTicks = isVertical ? getRecommendedNumberOfTicksForYAxis(pixelSpan) : getRecommendedNumberOfTicksForXAxis(pixelSpan);\r\n let scalarDomain = dataDomain ? dataDomain.slice() : null;\r\n let bestTickCount = maxTicks;\r\n let scale: D3.Scale.GenericScale<any>;\r\n let usingDefaultDomain = false;\r\n\r\n if (dataDomain == null || (dataDomain.length === 2 && dataDomain[0] == null && dataDomain[1] == null) || (dataDomain.length !== 2 && isScalar)) {\r\n usingDefaultDomain = true;\r\n\r\n if (dataType.dateTime || !isOrdinal(dataType))\r\n dataDomain = emptyDomain;\r\n else //ordinal\r\n dataDomain = [];\r\n\r\n if (isOrdinal(dataType)) {\r\n scale = createOrdinalScale(pixelSpan, dataDomain, categoryThickness ? outerPadding / categoryThickness : 0);\r\n }\r\n else {\r\n scale = createNumericalScale(options.scaleType, pixelSpan, dataDomain, dataType, outerPadding, bestTickCount);\r\n }\r\n }\r\n else {\r\n if (isScalar && dataDomain.length > 0) {\r\n bestTickCount = forcedTickCount !== undefined\r\n ? (maxTicks !== 0 ? forcedTickCount : 0)\r\n : AxisHelper.getBestNumberOfTicks(dataDomain[0], dataDomain[dataDomain.length - 1], [metaDataColumn], maxTicks, dataType.dateTime);\r\n\r\n let normalizedRange = normalizeLinearDomain({ min: dataDomain[0], max: dataDomain[dataDomain.length - 1] });\r\n scalarDomain = [normalizedRange.min, normalizedRange.max];\r\n }\r\n\r\n if (isScalar && dataType.numeric && !dataType.dateTime) {\r\n scale = createNumericalScale(options.scaleType, pixelSpan, scalarDomain, dataType, outerPadding, bestTickCount, shouldClamp);\r\n }\r\n else if (isScalar && dataType.dateTime) {\r\n // Use of a linear scale, instead of a D3.time.scale, is intentional since we want\r\n // to control the formatting of the time values, since d3's implementation isn't\r\n // in accordance to our design.\r\n // scalarDomain: should already be in long-int time (via category.values[0].getTime())\r\n scale = createLinearScale(pixelSpan, scalarDomain, outerPadding, null, shouldClamp); // DO NOT PASS TICKCOUNT\r\n }\r\n else if (dataType.text || dataType.dateTime || dataType.numeric || dataType.bool) {\r\n scale = createOrdinalScale(pixelSpan, scalarDomain, categoryThickness ? outerPadding / categoryThickness : 0);\r\n bestTickCount = maxTicks === 0 ? 0\r\n : Math.min(\r\n scalarDomain.length,\r\n (pixelSpan - outerPadding * 2) / CartesianChart.MinOrdinalRectThickness);\r\n }\r\n else {\r\n debug.assertFail('unsupported dataType, something other than text or numeric');\r\n }\r\n }\r\n\r\n // vertical ordinal axis (e.g. categorical bar chart) does not need to reverse\r\n if (isVertical && isScalar) {\r\n scale.range(scale.range().reverse());\r\n }\r\n\r\n ColumnUtil.normalizeInfinityInScale(scale);\r\n\r\n return {\r\n scale: scale,\r\n bestTickCount: bestTickCount,\r\n usingDefaultDomain: usingDefaultDomain,\r\n };\r\n }\r\n\r\n export function createFormatter(\r\n scaleDomain: any[],\r\n dataDomain: any[],\r\n dataType,\r\n isScalar: boolean,\r\n formatString: string,\r\n bestTickCount: number,\r\n tickValues: any[],\r\n getValueFn: any,\r\n useTickIntervalForDisplayUnits: boolean = false,\r\n axisDisplayUnits?: number,\r\n axisPrecision?: number): IValueFormatter {\r\n\r\n let formatter: IValueFormatter;\r\n if (dataType.dateTime) {\r\n if (isScalar) {\r\n let value = new Date(scaleDomain[0]);\r\n let value2 = new Date(scaleDomain[1]);\r\n // datetime with only one value needs to pass the same value\r\n // (from the original dataDomain value, not the adjusted scaleDomain)\r\n // so formatting works correctly.\r\n if (bestTickCount === 1)\r\n value = value2 = new Date(dataDomain[0]);\r\n // this will ignore the formatString and create one based on the smallest non-zero portion of the values supplied.\r\n formatter = valueFormatter.create({\r\n format: formatString,\r\n value: value,\r\n value2: value2,\r\n tickCount: bestTickCount,\r\n });\r\n }\r\n else {\r\n // Use the model formatString for ordinal datetime\r\n formatter = valueFormatter.createDefaultFormatter(formatString, true);\r\n }\r\n }\r\n else {\r\n if (getValueFn == null && !isScalar) {\r\n debug.assertFail('getValueFn must be supplied for ordinal tickValues');\r\n }\r\n if (useTickIntervalForDisplayUnits && isScalar && tickValues.length > 1) {\r\n let value1 = axisDisplayUnits ? axisDisplayUnits : tickValues[1] - tickValues[0];\r\n\r\n let options: ValueFormatterOptions = {\r\n format: formatString,\r\n value: value1,\r\n value2: 0, //force tickInterval or display unit to be used\r\n allowFormatBeautification: true,\r\n };\r\n\r\n if (axisPrecision)\r\n options.precision = axisPrecision;\r\n else\r\n options.detectAxisPrecision = true;\r\n\r\n formatter = valueFormatter.create(options);\r\n }\r\n else {\r\n // do not use display units, just the basic value formatter\r\n // datetime is handled above, so we are ordinal and either boolean, numeric, or text.\r\n formatter = valueFormatter.createDefaultFormatter(formatString, true);\r\n }\r\n }\r\n\r\n return formatter;\r\n }\r\n \r\n /**\r\n * Format the linear tick labels or the category labels.\r\n */\r\n function formatAxisTickValues(\r\n axis: D3.Svg.Axis,\r\n tickValues: any[],\r\n formatter: IValueFormatter,\r\n dataType: ValueType,\r\n getValueFn?: (index: number, type: ValueType) => any) {\r\n\r\n let formattedTickValues = [];\r\n\r\n if (!getValueFn)\r\n getValueFn = data => data;\r\n\r\n if (formatter) {\r\n axis.tickFormat(d => formatter.format(getValueFn(d, dataType)));\r\n formattedTickValues = tickValues.map(d => formatter.format(getValueFn(d, dataType)));\r\n }\r\n else {\r\n formattedTickValues = tickValues.map((d) => getValueFn(d, dataType));\r\n }\r\n\r\n return formattedTickValues;\r\n }\r\n\r\n export function getMinTickValueInterval(formatString: string, columnType: ValueType, is100Pct?: boolean): number {\r\n let isCustomFormat = formatString && !powerbi.NumberFormat.isStandardFormat(formatString);\r\n if (isCustomFormat) {\r\n let precision = powerbi.NumberFormat.getCustomFormatMetadata(formatString, true /*calculatePrecision*/).precision;\r\n if (formatString.indexOf('%') > -1)\r\n precision += 2; //percent values are multiplied by 100 during formatting\r\n return Math.pow(10, -precision);\r\n }\r\n else if (is100Pct)\r\n return 0.01;\r\n else if (columnType.integer)\r\n return 1;\r\n\r\n return 0;\r\n }\r\n\r\n function createScalarDomain(data: CartesianSeries[], userMin: DataViewPropertyValue, userMax: DataViewPropertyValue, axisType: ValueTypeDescriptor, ensureDomain?: NumberRange): number[] {\r\n debug.assertValue(data, 'data');\r\n if (data.length === 0) {\r\n return null;\r\n }\r\n\r\n let defaultMinX = <number>d3.min(data, (kv) => { return d3.min(kv.data, d => { return d.categoryValue; }); });\r\n let defaultMaxX = <number>d3.max(data, (kv) => { return d3.max(kv.data, d => { return d.categoryValue; }); });\r\n\r\n return combineDomain([userMin, userMax], [defaultMinX, defaultMaxX], ensureDomain);\r\n }\r\n\r\n /**\r\n * Creates a [min,max] from your Cartiesian data values.\r\n * \r\n * @param data The series array of CartesianDataPoints.\r\n * @param includeZero Columns and bars includeZero, line and scatter do not.\r\n */\r\n export function createValueDomain(data: CartesianSeries[], includeZero: boolean): number[] {\r\n debug.assertValue(data, 'data');\r\n if (data.length === 0)\r\n return null;\r\n\r\n let minY = <number>d3.min(data, (kv) => { return d3.min(kv.data, d => { return d.value; }); });\r\n let maxY = <number>d3.max(data, (kv) => { return d3.max(kv.data, d => { return d.value; }); });\r\n\r\n if (includeZero)\r\n return [Math.min(minY, 0), Math.max(maxY, 0)];\r\n return [minY, maxY];\r\n }\r\n\r\n function createOrdinalDomain(data: CartesianSeries[]): number[] {\r\n if (_.isEmpty(data))\r\n return [];\r\n\r\n // each series shares the same categories for oridinal axes (even if a series has some nulls)\r\n let domain = [];\r\n let firstSeries = data[0];\r\n for (let dp of firstSeries.data) {\r\n if (!dp.highlight)\r\n domain.push(dp.categoryIndex);\r\n }\r\n return domain;\r\n }\r\n\r\n export module LabelLayoutStrategy {\r\n export function willLabelsFit(\r\n axisProperties: IAxisProperties,\r\n availableWidth: number,\r\n textMeasurer: ITextAsSVGMeasurer,\r\n properties: TextProperties): boolean {\r\n\r\n let labels = axisProperties.values;\r\n if (labels.length === 0)\r\n return false;\r\n\r\n let labelMaxWidth = axisProperties.xLabelMaxWidth !== undefined\r\n ? axisProperties.xLabelMaxWidth\r\n : availableWidth / labels.length;\r\n\r\n return !labels.some(d => {\r\n properties.text = d;\r\n return textMeasurer(properties) > labelMaxWidth;\r\n });\r\n }\r\n\r\n export function willLabelsWordBreak(\r\n axisProperties: IAxisProperties,\r\n margin: IMargin,\r\n availableWidth: number,\r\n textWidthMeasurer: ITextAsSVGMeasurer,\r\n textHeightMeasurer: ITextAsSVGMeasurer,\r\n textTruncator: (properties: TextProperties, maxWidth: number) => string,\r\n properties: TextProperties) {\r\n let labels = axisProperties.values;\r\n let labelMaxWidth = axisProperties.xLabelMaxWidth !== undefined\r\n ? axisProperties.xLabelMaxWidth\r\n : availableWidth / labels.length;\r\n let maxRotatedLength = margin.bottom / DefaultRotation.sine;\r\n let height = textHeightMeasurer(properties);\r\n let maxNumLines = Math.max(1, Math.floor(margin.bottom / height)); // TODO: not taking axis label into account\r\n\r\n if (labels.length === 0)\r\n return false;\r\n\r\n // If no break character and exceeds max width, word breaking will not work, return false\r\n let mustRotate = labels.some(label => {\r\n // Detect must rotate and return immediately\r\n properties.text = label;\r\n return !jsCommon.WordBreaker.hasBreakers(label) && textWidthMeasurer(properties) > labelMaxWidth;\r\n });\r\n if (mustRotate)\r\n return false;\r\n\r\n let moreWordBreakChars = labels.filter((label, index: number) => {\r\n // ...otherwise compare rotation versus word breaking\r\n let allowedLengthProjectedOnXAxis =\r\n // Left margin is the width of Y axis.\r\n margin.left\r\n // There could be a padding before the first category.\r\n + axisProperties.outerPadding\r\n // Align the rotated text's top right corner to the middle of the corresponding category first.\r\n + axisProperties.categoryThickness * (index + 0.5)\r\n // Subtracting the left padding space from the allowed length\r\n - LeftPadding;\r\n let allowedLength = allowedLengthProjectedOnXAxis / DefaultRotation.cosine;\r\n let rotatedLength = Math.min(allowedLength, maxRotatedLength);\r\n \r\n // Which shows more characters? Rotated or maxNumLines truncated to labelMaxWidth?\r\n let wordBreakChars = jsCommon.WordBreaker.splitByWidth(label, properties, textWidthMeasurer, labelMaxWidth, maxNumLines, textTruncator).join(' ');\r\n properties.text = label;\r\n let rotateChars = textTruncator(properties, rotatedLength);\r\n\r\n // prefer word break (>=) as it takes up less plot area\r\n return TextUtil.removeEllipses(wordBreakChars).length >= TextUtil.removeEllipses(rotateChars).length;\r\n });\r\n\r\n // prefer word break (>=) as it takes up less plot area\r\n return moreWordBreakChars.length >= Math.floor(labels.length / 2);\r\n }\r\n\r\n export const DefaultRotation = {\r\n sine: Math.sin(Math.PI * (35 / 180)),\r\n cosine: Math.cos(Math.PI * (35 / 180)),\r\n tangent: Math.tan(Math.PI * (35 / 180)),\r\n transform: 'rotate(-35)',\r\n dy: '-0.5em',\r\n };\r\n\r\n export const DefaultRotationWithScrollbar = {\r\n sine: Math.sin(Math.PI * (90 / 180)),\r\n cosine: Math.cos(Math.PI * (90 / 180)),\r\n tangent: Math.tan(Math.PI * (90 / 180)),\r\n transform: 'rotate(-90)',\r\n dy: '-0.8em',\r\n };\r\n\r\n export function rotate(\r\n labelSelection: D3.Selection,\r\n maxBottomMargin: number,\r\n textTruncator: (properties: TextProperties, maxWidth: number) => string,\r\n textProperties: TextProperties,\r\n needRotate: boolean,\r\n needEllipsis: boolean,\r\n axisProperties: IAxisProperties,\r\n margin: IMargin,\r\n scrollbarVisible: boolean) {\r\n\r\n let rotatedLength;\r\n let defaultRotation: any;\r\n\r\n if (scrollbarVisible)\r\n defaultRotation = DefaultRotationWithScrollbar;\r\n else\r\n defaultRotation = DefaultRotation;\r\n\r\n if (needRotate) {\r\n rotatedLength = maxBottomMargin / defaultRotation.sine;\r\n }\r\n\r\n labelSelection.each(function () {\r\n let axisLabel = d3.select(this);\r\n let labelText = axisLabel.text();\r\n textProperties.text = labelText;\r\n if (needRotate) {\r\n let textContentIndex = axisProperties.values.indexOf(this.textContent);\r\n let allowedLengthProjectedOnXAxis =\r\n // Left margin is the width of Y axis.\r\n margin.left\r\n // There could be a padding before the first category.\r\n + axisProperties.outerPadding\r\n // Align the rotated text's top right corner to the middle of the corresponding category first.\r\n + axisProperties.categoryThickness * (textContentIndex + 0.5);\r\n\r\n // Subtracting the left padding space from the allowed length.\r\n if (!scrollbarVisible)\r\n allowedLengthProjectedOnXAxis -= LeftPadding;\r\n\r\n // Truncate if scrollbar is visible or rotatedLength exceeds allowedLength\r\n let allowedLength = allowedLengthProjectedOnXAxis / defaultRotation.cosine;\r\n if (scrollbarVisible || needEllipsis || (allowedLength < rotatedLength)) {\r\n labelText = textTruncator(textProperties, Math.min(allowedLength, rotatedLength));\r\n axisLabel.text(labelText);\r\n }\r\n\r\n axisLabel.style('text-anchor', 'end')\r\n .attr({\r\n 'dx': '-0.5em',\r\n 'dy': defaultRotation.dy,\r\n 'transform': defaultRotation.transform\r\n });\r\n } else {\r\n let newLabelText = textTruncator(textProperties, axisProperties.xLabelMaxWidth);\r\n if (newLabelText !== labelText)\r\n axisLabel.text(newLabelText);\r\n axisLabel.style('text-anchor', 'middle')\r\n .attr(\r\n {\r\n 'dx': '0em',\r\n 'dy': '1em',\r\n 'transform': 'rotate(0)'\r\n });\r\n }\r\n });\r\n }\r\n\r\n export function wordBreak(\r\n text: D3.Selection,\r\n axisProperties: IAxisProperties,\r\n maxHeight: number\r\n ) {\r\n let allowedLength = axisProperties.xLabelMaxWidth;\r\n\r\n text.each(function () {\r\n let node = d3.select(this);\r\n\r\n // Reset style of text node\r\n node\r\n .style('text-anchor', 'middle')\r\n .attr({\r\n 'dx': '0em',\r\n 'dy': '1em',\r\n 'transform': 'rotate(0)'\r\n });\r\n\r\n TextMeasurementService.wordBreak(this, allowedLength, maxHeight);\r\n });\r\n }\r\n\r\n export function clip(text: D3.Selection, availableWidth: number, svgEllipsis: (textElement: SVGTextElement, maxWidth: number) => void) {\r\n if (text.size() === 0)\r\n return;\r\n\r\n text.each(function () {\r\n let text = d3.select(this);\r\n svgEllipsis(text[0][0], availableWidth);\r\n });\r\n }\r\n }\r\n\r\n export function createOrdinalScale(pixelSpan: number, dataDomain: any[], outerPaddingRatio: number = 0): D3.Scale.OrdinalScale {\r\n debug.assert(outerPaddingRatio >= 0 && outerPaddingRatio < 4, 'outerPaddingRatio should be a value between zero and four');\r\n let scale = d3.scale.ordinal()\r\n /* Avoid using rangeRoundBands here as it is adding some extra padding to the axis*/\r\n .rangeBands([0, pixelSpan], CartesianChart.InnerPaddingRatio, outerPaddingRatio)\r\n .domain(dataDomain);\r\n return scale;\r\n }\r\n\r\n export function isLogScalePossible(domain: any[], axisType?: ValueType): boolean {\r\n if (domain == null)\r\n return false;\r\n if (isDateTime(axisType))\r\n return false;\r\n\r\n return (domain[0] > 0 && domain[1] > 0) || (domain[0] < 0 && domain[1] < 0);//doman must exclude 0\r\n }\r\n\r\n //this function can return different scales e.g. log, linear\r\n // NOTE: export only for testing, do not access directly\r\n export function createNumericalScale(\r\n axisScaleType: string,\r\n pixelSpan: number,\r\n dataDomain: any[],\r\n dataType: ValueType,\r\n outerPadding: number = 0,\r\n niceCount?: number,\r\n shouldClamp?: boolean): D3.Scale.GenericScale<any> {\r\n\r\n if (axisScaleType === axisScale.log && isLogScalePossible(dataDomain, dataType)) {\r\n return createLogScale(pixelSpan, dataDomain, outerPadding, niceCount);\r\n }\r\n else {\r\n return createLinearScale(pixelSpan, dataDomain, outerPadding, niceCount, shouldClamp);\r\n }\r\n }\r\n\r\n function createLogScale(pixelSpan: number, dataDomain: any[], outerPadding: number = 0, niceCount?: number): D3.Scale.LinearScale {\r\n debug.assert(isLogScalePossible(dataDomain), \"dataDomain cannot include 0\");\r\n let scale = d3.scale.log()\r\n .range([outerPadding, pixelSpan - outerPadding])\r\n .domain([dataDomain[0], dataDomain[1]])\r\n .clamp(true);\r\n\r\n if (niceCount) {\r\n scale.nice(niceCount);\r\n }\r\n\r\n return scale;\r\n }\r\n\r\n // NOTE: export only for testing, do not access directly\r\n export function createLinearScale(pixelSpan: number, dataDomain: any[], outerPadding: number = 0, niceCount?: number, shouldClamp?: boolean): D3.Scale.LinearScale {\r\n let scale = d3.scale.linear()\r\n .range([outerPadding, pixelSpan - outerPadding])\r\n .domain([dataDomain[0], dataDomain[1]])\r\n .clamp(shouldClamp);\r\n // .nice(undefined) still modifies the scale boundaries, and for datetime this messes things up.\r\n // we use millisecond ticks since epoch for datetime, so we don't want any \"nice\" with numbers like 17398203392.\r\n if (niceCount) {\r\n scale.nice(niceCount);\r\n }\r\n return scale;\r\n }\r\n\r\n export function getRangeForColumn(sizeColumn: DataViewValueColumn): NumberRange {\r\n let result: NumberRange = {};\r\n if (sizeColumn) {\r\n result.min = sizeColumn.min == null\r\n ? sizeColumn.minLocal == null ? d3.min(sizeColumn.values) : sizeColumn.minLocal\r\n : sizeColumn.min;\r\n result.max = sizeColumn.max == null\r\n ? sizeColumn.maxLocal == null ? d3.max(sizeColumn.values) : sizeColumn.maxLocal\r\n : sizeColumn.max;\r\n }\r\n return result;\r\n }\r\n \r\n /**\r\n * Set customized domain, but don't change when nothing is set\r\n */\r\n export function applyCustomizedDomain(customizedDomain, forcedDomain: any[]): any[] {\r\n let domain: any[] = [undefined, undefined];\r\n\r\n if (forcedDomain && forcedDomain.length === 2) {\r\n domain = [forcedDomain[0], forcedDomain[1]];\r\n }\r\n\r\n if (customizedDomain && customizedDomain.length === 2) {\r\n if (customizedDomain[0] != null) {\r\n domain[0] = customizedDomain[0];\r\n }\r\n if (customizedDomain[1] != null) {\r\n domain[1] = customizedDomain[1];\r\n }\r\n }\r\n\r\n if (domain[0] == null && domain[1] == null) {\r\n return forcedDomain;//return untouched object\r\n }\r\n\r\n //do extra check to see if the user input was valid with the merged axis values.\r\n if (domain[0] != null && domain[1] != null) {\r\n if (domain[0] > domain[1]) {\r\n return forcedDomain;\r\n }\r\n }\r\n\r\n return domain;\r\n }\r\n \r\n /**\r\n * Combine the forced domain with the actual domain if one of the values was set.\r\n * The forcedDomain is in 1st priority. Extends the domain if the any reference point requires it.\r\n */\r\n export function combineDomain(forcedDomain: any[], domain: any[], ensureDomain?: NumberRange): any[] {\r\n let combinedDomain: any[] = domain ? [domain[0], domain[1]] : [];\r\n\r\n if (ensureDomain) {\r\n if (combinedDomain[0] == null || ensureDomain.min < combinedDomain[0])\r\n combinedDomain[0] = ensureDomain.min;\r\n\r\n if (combinedDomain[1] == null || ensureDomain.max > combinedDomain[1])\r\n combinedDomain[1] = ensureDomain.max;\r\n }\r\n\r\n let domainBeforeForced: any[] = [combinedDomain[0], combinedDomain[1]];\r\n\r\n if (forcedDomain && forcedDomain.length === 2) {\r\n if (forcedDomain[0] != null) {\r\n combinedDomain[0] = forcedDomain[0];\r\n }\r\n if (forcedDomain[1] != null) {\r\n combinedDomain[1] = forcedDomain[1];\r\n }\r\n if (combinedDomain[0] > combinedDomain[1]) {\r\n combinedDomain = domainBeforeForced;//this is invalid, so take the original domain considering the values and the reference line\r\n }\r\n }\r\n return combinedDomain;\r\n }\r\n\r\n export function createAxisLabel(properties: DataViewObject, label: string, unitType: string, y2: boolean = false): string {\r\n let propertyName = y2 ? 'secAxisStyle' : 'axisStyle';\r\n if (!properties || !properties[propertyName]) {\r\n return label;\r\n }\r\n\r\n let modifiedLabel;\r\n if (properties[propertyName] === axisStyle.showBoth) {\r\n modifiedLabel = label + ' (' + unitType + ')';//todo: localize\r\n }\r\n else if (properties[propertyName] === axisStyle.showUnitOnly) {\r\n modifiedLabel = unitType;\r\n }\r\n else {\r\n modifiedLabel = label;\r\n }\r\n return modifiedLabel;\r\n }\r\n\r\n export function scaleShouldClamp(combinedDomain: any[], domain: any[]): boolean {\r\n if (!combinedDomain || !domain || combinedDomain.length < 2 || domain.length < 2)\r\n return false;\r\n //when the start or end is different, clamp it\r\n return combinedDomain[0] !== domain[0] || combinedDomain[1] !== domain[1];\r\n }\r\n\r\n export function normalizeNonFiniteNumber(value: number): number {\r\n if (isNaN(value))\r\n return null;\r\n else if (value === Number.POSITIVE_INFINITY)\r\n return Number.MAX_VALUE;\r\n else if (value === Number.NEGATIVE_INFINITY)\r\n return -Number.MAX_VALUE;\r\n\r\n return value;\r\n }\r\n\r\n /**\r\n * Indicates whether the number is power of 10.\r\n */\r\n export function powerOfTen(d: any): boolean {\r\n let value = Math.abs(d);\r\n // formula log2(Y)/log2(10) = log10(Y)\r\n // because double issues this won't return exact value\r\n // we need to ceil it to nearest number.\r\n let log10: number = Math.log(value) / Math.LN10;\r\n log10 = Math.ceil(log10 - 1e-12);\r\n return value / Math.pow(10, log10) === 1;\r\n }\r\n }\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.visuals {\r\n export module ShapeFactory {\r\n\r\n export module ShapeFactoryConsts {\r\n export const PaddingConstRatio: number = 0.01;\r\n export const TrianglePaddingConstRatio: number = 0.15;\r\n export const TriangleEndPaddingConstRatio: number = 0.85;\r\n export const ShapeConstRatio: number = 1.0 - (ShapeFactoryConsts.PaddingConstRatio * 2);\r\n export const SmallPaddingConstValue: number = 10;\r\n export const OvalRadiusConst: number = 2;\r\n export const OvalRadiusConstPadding: number = 0.2;\r\n export const ArrowLeftHeadPoint: Point = { x : 0.05, y : 0.42 };\r\n export const ArrowMiddleHeadPoint: Point = { x: 0.5, y: 0.016 };\r\n export const ArrowRightHeadPoint: Point = { x: 0.95, y: 0.42 };\r\n export const ArrowRightMiddleHeadPoint: Point = { x: 0.764, y: 0.42 };\r\n export const ArrowBottomRightPoint: Point = { x: 0.764, y: 0.993 }; \r\n export const ArrowBottomLeftPoint: Point = { x: 0.246, y: 0.993 };\r\n export const ArrowLeftMiddleHeadPoint: Point = { x: 0.246, y: 0.42 };\r\n }\r\n\r\n /** this function creates a rectangle svg */\r\n export function createRectangle(data: BasicShapeData, viewportHeight: number, viewportWidth: number, selectedElement: D3.Selection, degrees: number): void {\r\n let x = (viewportWidth * ShapeFactoryConsts.PaddingConstRatio) + (data.lineWeight / 2);\r\n let y = (viewportHeight * ShapeFactoryConsts.PaddingConstRatio) + (data.lineWeight / 2);\r\n let width = (viewportWidth * ShapeFactoryConsts.ShapeConstRatio) - (data.lineWeight);\r\n let height = (viewportHeight * ShapeFactoryConsts.ShapeConstRatio) - (data.lineWeight);\r\n let attrs = { x: x, y: y, width: width, height: height, rx: data.roundEdge, ry: data.roundEdge };\r\n let scale = getScale(width, height, degrees);\r\n\r\n createShape(data, viewportHeight, viewportWidth, selectedElement, degrees, scale, 'rect', attrs);\r\n }\r\n\r\n /** this function creates a oval svg */\r\n export function createOval(data: BasicShapeData, viewportHeight: number, viewportWidth: number, selectedElement: D3.Selection, degrees: number): void {\r\n let widthForCircle = (viewportWidth / ShapeFactoryConsts.OvalRadiusConst).toString();\r\n let heightForCircle = (viewportHeight / ShapeFactoryConsts.OvalRadiusConst).toString();\r\n let radiusXForCircle = ((viewportWidth / (ShapeFactoryConsts.OvalRadiusConst + ShapeFactoryConsts.OvalRadiusConstPadding)) - data.lineWeight);\r\n let radiusYForCircle = ((viewportHeight / (ShapeFactoryConsts.OvalRadiusConst + ShapeFactoryConsts.OvalRadiusConstPadding))- data.lineWeight);\r\n let attrs = { cx: widthForCircle, cy: heightForCircle, rx: radiusXForCircle, ry: radiusYForCircle };\r\n\r\n let scale = getScale(viewportWidth, viewportHeight, degrees);\r\n\r\n createShape(data, viewportHeight, viewportWidth, selectedElement, degrees, scale, 'ellipse', attrs);\r\n }\r\n\r\n /** this function creates a line svg */\r\n export function createLine(data: BasicShapeData, viewportHeight: number, viewportWidth: number, selectedElement: D3.Selection, degrees: number): void {\r\n let x1, y1, x2, y2;\r\n let width = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue) - ShapeFactoryConsts.SmallPaddingConstValue;\r\n let height = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) - ShapeFactoryConsts.SmallPaddingConstValue;\r\n\r\n let ratio;\r\n if (degrees <= 45) {\r\n ratio = degrees / 90;\r\n\r\n x1 = viewportWidth / 2 + width * ratio;\r\n y1 = ShapeFactoryConsts.SmallPaddingConstValue;\r\n x2 = viewportWidth / 2 - width * ratio;\r\n y2 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue);\r\n } else if (degrees <= 135) {\r\n ratio = (degrees - 45) / 90;\r\n\r\n x1 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue);\r\n y1 = ShapeFactoryConsts.SmallPaddingConstValue + height * ratio;\r\n x2 = ShapeFactoryConsts.SmallPaddingConstValue;\r\n y2 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) - height * ratio;\r\n } else if (degrees <= 225) {\r\n ratio = (degrees - 135) / 90;\r\n\r\n x1 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue) - width * ratio;\r\n y1 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue);\r\n x2 = ShapeFactoryConsts.SmallPaddingConstValue + width * ratio;\r\n y2 = ShapeFactoryConsts.SmallPaddingConstValue;\r\n } else if (degrees <= 315) {\r\n ratio = (degrees - 225) / 90;\r\n\r\n x1 = ShapeFactoryConsts.SmallPaddingConstValue;\r\n y1 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) - height * ratio;\r\n x2 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue);\r\n y2 = ShapeFactoryConsts.SmallPaddingConstValue + height * ratio;\r\n } else if (degrees <= 360) {\r\n ratio = (degrees - 315) / 90;\r\n\r\n x1 = ShapeFactoryConsts.SmallPaddingConstValue + width * ratio;\r\n y1 = ShapeFactoryConsts.SmallPaddingConstValue;\r\n x2 = (viewportWidth - ShapeFactoryConsts.SmallPaddingConstValue) - width * ratio;\r\n y2 = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue);\r\n }\r\n\r\n // create the inner path with the wanted shape\r\n selectedElement\r\n .append('svg')\r\n .attr({\r\n width: viewportWidth,\r\n height: viewportHeight\r\n })\r\n .append('line')\r\n .attr({\r\n x1: x1,\r\n y1: y1,\r\n x2: x2,\r\n y2: y2,\r\n })\r\n .style({\r\n 'vector-effect': 'non-scaling-stroke',\r\n 'stroke-width': data.lineWeight + 'px',\r\n 'stroke-opacity': (100 - data.lineTransparency) / 100,\r\n 'stroke': data.lineColor\r\n });\r\n }\r\n\r\n /** this function creates a arrow svg */\r\n export function createUpArrow(data: BasicShapeData, viewportHeight: number, viewportWidth: number, selectedElement: D3.Selection, degrees: number): void {\r\n let lineWeight = data.lineWeight;\r\n let viewportHeightWeight = viewportHeight - lineWeight;\r\n let viewportWidthWeight = viewportWidth - lineWeight;\r\n\r\n let arrowPoints = [\r\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowLeftHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowLeftHeadPoint.y).toString() },\r\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowMiddleHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowMiddleHeadPoint.y).toString() },\r\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowRightHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowRightHeadPoint.y).toString() },\r\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowRightMiddleHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowRightMiddleHeadPoint.y).toString() },\r\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowBottomRightPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowBottomRightPoint.y).toString() },\r\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowBottomLeftPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowBottomLeftPoint.y).toString() },\r\n { 'x': (viewportWidthWeight * ShapeFactoryConsts.ArrowLeftMiddleHeadPoint.x).toString(), 'y': (viewportHeightWeight * ShapeFactoryConsts.ArrowLeftMiddleHeadPoint.y).toString() },\r\n ];\r\n\r\n // create the inner path with the wanted shape\r\n createPathFromArray(data, arrowPoints, selectedElement, viewportHeight, viewportWidth, degrees);\r\n }\r\n\r\n /** this function creates a triangle svg */\r\n export function createTriangle(data: BasicShapeData, viewportHeight: number, viewportWidth: number, selectedElement: D3.Selection, degrees: number): void {\r\n let lineWeight = data.lineWeight;\r\n // remove the basic line weight\r\n if (lineWeight > 3) {\r\n lineWeight -= 3;\r\n }\r\n\r\n let firstPointX = ((viewportWidth + lineWeight) * ShapeFactoryConsts.TrianglePaddingConstRatio);\r\n let firstPointY = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue - lineWeight) < 0 ?\r\n (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) : (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue - lineWeight);\r\n let secondPointY = ((viewportHeight + lineWeight) * ShapeFactoryConsts.TrianglePaddingConstRatio);\r\n let thirdPointX = ((viewportWidth - lineWeight) * ShapeFactoryConsts.TriangleEndPaddingConstRatio) < 0 ?\r\n (viewportWidth * ShapeFactoryConsts.TriangleEndPaddingConstRatio) : ((viewportWidth - lineWeight) * ShapeFactoryConsts.TriangleEndPaddingConstRatio);\r\n let thirdPointY = (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue - lineWeight) < 0 ?\r\n (viewportHeight - ShapeFactoryConsts.SmallPaddingConstValue) : (viewportHeight - lineWeight - ShapeFactoryConsts.SmallPaddingConstValue);\r\n let secondPointX = ((firstPointX + thirdPointX) / 2);\r\n\r\n if (firstPointX < 10) {\r\n firstPointX = ShapeFactoryConsts.SmallPaddingConstValue;\r\n }\r\n\r\n if (secondPointY < 10) {\r\n secondPointY = ShapeFactoryConsts.SmallPaddingConstValue;\r\n }\r\n\r\n let trianglePoints = [\r\n { 'x': firstPointX, 'y': firstPointY },\r\n { 'x': secondPointX, 'y': secondPointY },\r\n { 'x': thirdPointX, 'y': thirdPointY },\r\n ];\r\n\r\n createPathFromArray(data, trianglePoints, selectedElement, viewportHeight, viewportWidth, degrees);\r\n }\r\n\r\n /** this funcion adds a path to an svg element from an array of points (x,y) */\r\n function createPathFromArray(data: BasicShapeData, points: Object[], selectedElement: D3.Selection, viewportHeight: number, viewportWidth: number, degrees: number): void {\r\n let lineFunction = d3.svg.line()\r\n .x(function (d) { return d.x; })\r\n .y(function (d) { return d.y; })\r\n .interpolate('linear');\r\n let attrs = { d: lineFunction(points) + ' Z' };\r\n\r\n let scale = getScale(viewportWidth, viewportHeight, degrees);\r\n\r\n createShape(data, viewportHeight, viewportWidth, selectedElement, degrees, scale, 'path', attrs);\r\n }\r\n\r\n function createShape(data: BasicShapeData, viewportHeight: number, viewportWidth: number, selectedElement: D3.Selection, degrees: number, scale: number, shapeType: string, shapeAttrs: Object): void {\r\n selectedElement\r\n .append('div')\r\n .style({\r\n 'transform': 'rotate(' + degrees + 'deg) scale(' + scale + ')',\r\n 'transform-origin': 'center',\r\n // for testing with phantomjs we need the webkit prefix\r\n '-webkit-transform': 'rotate(' + degrees + 'deg) scale(' + scale + ')',\r\n '-webkit-transform-origin': 'center',\r\n 'width': viewportWidth + 'px',\r\n 'height': viewportHeight + 'px'\r\n })\r\n .append('svg')\r\n .attr({\r\n width: viewportWidth,\r\n height: viewportHeight\r\n })\r\n .append(shapeType)\r\n .attr(shapeAttrs)\r\n .style({\r\n 'vector-effect': 'non-scaling-stroke',\r\n 'stroke-width': data.lineWeight + 'px',\r\n 'stroke': data.lineColor,\r\n 'stroke-opacity': (100 - data.lineTransparency) / 100,\r\n 'fill': data.fillColor,\r\n 'fill-opacity': data.showFill === true ? ((100 - data.shapeTransparency) / 100) : 0\r\n });\r\n }\r\n\r\n // this function return the scale to add to the shape. \r\n // it calculate it by the ratio of the original shape's diagonal and the shape's diagonal after rotate (the maximum diagonal that still fit to the container).\r\n // it calculate the shape's diagonal by the rotate angle.\r\n function getScale(width: number, height: number, degrees: number): number {\r\n let originalWidth = width;\r\n let originalHeight = height;\r\n let offsetAngle = Math.atan2(height, width);\r\n let originalFactor = Math.sqrt(Math.pow(height, 2) + Math.pow(width, 2));\r\n let radians = (degrees / 180) * Math.PI;\r\n\r\n if (width >= height) {\r\n if (degrees < 90) {\r\n radians += offsetAngle;\r\n } else if (degrees < 180) {\r\n radians -= offsetAngle;\r\n } else if (degrees < 270) {\r\n radians += offsetAngle;\r\n } else {\r\n radians -= offsetAngle;\r\n }\r\n\r\n return (originalHeight / Math.abs(Math.sin(radians))) / originalFactor;\r\n }\r\n else {\r\n if (degrees < 90) {\r\n radians -= offsetAngle;\r\n } else if (degrees < 180) {\r\n radians += offsetAngle;\r\n } else if (degrees < 270) {\r\n radians -= offsetAngle;\r\n } else {\r\n radians += offsetAngle;\r\n }\r\n\r\n return (originalWidth / Math.abs(Math.cos(radians))) / originalFactor;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module CartesianHelper {\r\n export function getCategoryAxisProperties(dataViewMetadata: DataViewMetadata, axisTitleOnByDefault?: boolean): DataViewObject {\r\n let toReturn: DataViewObject = {};\r\n if (!dataViewMetadata)\r\n return toReturn;\r\n\r\n let objects = dataViewMetadata.objects;\r\n\r\n if (objects) {\r\n let categoryAxisObject = objects['categoryAxis'];\r\n\r\n if (categoryAxisObject) {\r\n toReturn = {\r\n show: categoryAxisObject['show'],\r\n axisType: categoryAxisObject['axisType'],\r\n axisScale: categoryAxisObject['axisScale'],\r\n start: categoryAxisObject['start'],\r\n end: categoryAxisObject['end'],\r\n showAxisTitle: categoryAxisObject['showAxisTitle'] == null ? axisTitleOnByDefault : categoryAxisObject['showAxisTitle'],\r\n axisStyle: categoryAxisObject['axisStyle'],\r\n labelColor: categoryAxisObject['labelColor'],\r\n labelDisplayUnits: categoryAxisObject['labelDisplayUnits'],\r\n labelPrecision: categoryAxisObject['labelPrecision'],\r\n duration: categoryAxisObject['duration'],\r\n };\r\n }\r\n }\r\n return toReturn;\r\n }\r\n\r\n export function getValueAxisProperties(dataViewMetadata: DataViewMetadata, axisTitleOnByDefault?: boolean): DataViewObject {\r\n let toReturn: DataViewObject = {};\r\n if (!dataViewMetadata)\r\n return toReturn;\r\n\r\n let objects = dataViewMetadata.objects;\r\n\r\n if (objects) {\r\n let valueAxisObject = objects['valueAxis'];\r\n if (valueAxisObject) {\r\n toReturn = {\r\n show: valueAxisObject['show'],\r\n position: valueAxisObject['position'],\r\n axisScale: valueAxisObject['axisScale'],\r\n start: valueAxisObject['start'],\r\n end: valueAxisObject['end'],\r\n showAxisTitle: valueAxisObject['showAxisTitle'] == null ? axisTitleOnByDefault : valueAxisObject['showAxisTitle'],\r\n axisStyle: valueAxisObject['axisStyle'],\r\n labelColor: valueAxisObject['labelColor'],\r\n labelDisplayUnits: valueAxisObject['labelDisplayUnits'],\r\n labelPrecision: valueAxisObject['labelPrecision'],\r\n secShow: valueAxisObject['secShow'],\r\n secPosition: valueAxisObject['secPosition'],\r\n secAxisScale: valueAxisObject['secAxisScale'],\r\n secStart: valueAxisObject['secStart'],\r\n secEnd: valueAxisObject['secEnd'],\r\n secShowAxisTitle: valueAxisObject['secShowAxisTitle'],\r\n secAxisStyle: valueAxisObject['secAxisStyle'],\r\n secLabelColor: valueAxisObject['secLabelColor'],\r\n secLabelDisplayUnits: valueAxisObject['secLabelDisplayUnits'],\r\n secLabelPrecision: valueAxisObject['secLabelPrecision'],\r\n };\r\n }\r\n }\r\n return toReturn;\r\n } \r\n \r\n export function isScalar(isScalar: boolean, xAxisCardProperties: DataViewObject): boolean {\r\n if (isScalar) {\r\n //now check what the user wants\r\n isScalar = xAxisCardProperties && xAxisCardProperties['axisType'] ? xAxisCardProperties['axisType'] === axisType.scalar : true;\r\n }\r\n return isScalar;\r\n }\r\n\r\n export function getPrecision(precision: DataViewPropertyValue): number {\r\n if (precision != null) {\r\n if (precision < 0) {\r\n return 0;\r\n }\r\n return <number>precision;\r\n }\r\n return null;\r\n }\r\n\r\n export function lookupXValue(data: CartesianData, index: number, type: ValueType, isScalar: boolean): any {\r\n debug.assertValue(data, 'data');\r\n debug.assertValue(type, 'type');\r\n\r\n let isDateTime = AxisHelper.isDateTime(type);\r\n\r\n if (isScalar) {\r\n if (isDateTime)\r\n return new Date(index);\r\n\r\n // index is the numeric value\r\n return index;\r\n }\r\n\r\n if (type.text) {\r\n debug.assert(index < data.categories.length, 'category index out of range');\r\n return data.categories[index];\r\n }\r\n\r\n if (data && data.series && data.series.length > 0) {\r\n let firstSeries = data.series[0];\r\n if (firstSeries) {\r\n let seriesValues = firstSeries.data;\r\n if (seriesValues) {\r\n if (data.hasHighlights)\r\n index = index * 2;\r\n let dataAtIndex = seriesValues[index];\r\n if (dataAtIndex) {\r\n if (isDateTime && dataAtIndex.categoryValue != null)\r\n return new Date(dataAtIndex.categoryValue);\r\n return dataAtIndex.categoryValue;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return index;\r\n }\r\n\r\n export function findMaxCategoryIndex(series: CartesianSeries[]): number {\r\n if (_.isEmpty(series)) {\r\n return 0;\r\n }\r\n let maxCategoryIndex: number = 0;\r\n for (let singleSeries of series) {\r\n if (!_.isEmpty(singleSeries.data)) {\r\n let lastIndex = singleSeries.data[singleSeries.data.length - 1].categoryIndex;\r\n maxCategoryIndex = Math.max(lastIndex, maxCategoryIndex);\r\n }\r\n }\r\n return maxCategoryIndex;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import SQExprShortSerializer = data.SQExprShortSerializer;\r\n\r\n export class ColorHelper {\r\n private fillProp: DataViewObjectPropertyIdentifier;\r\n private defaultDataPointColor: string;\r\n private colors: IDataColorPalette;\r\n private defaultColorScale: IColorScale;\r\n\r\n constructor(colors: IDataColorPalette, fillProp?: DataViewObjectPropertyIdentifier, defaultDataPointColor?: string) {\r\n this.colors = colors;\r\n this.fillProp = fillProp;\r\n this.defaultDataPointColor = defaultDataPointColor;\r\n this.defaultColorScale = colors.getNewColorScale();\r\n }\r\n\r\n /**\r\n * Gets the color for the given series value.\r\n * If no explicit color or default color has been set then the color is\r\n * allocated from the color scale for this series.\r\n */\r\n public getColorForSeriesValue(objects: DataViewObjects, fieldIds: powerbi.data.ISQExpr[], value: string): string {\r\n return (this.fillProp && DataViewObjects.getFillColor(objects, this.fillProp))\r\n || this.defaultDataPointColor\r\n || this.getColorScaleForSeries(fieldIds).getColor(value).value;\r\n }\r\n\r\n /**\r\n * Gets the color scale for the given series.\r\n */\r\n public getColorScaleForSeries(fieldIds: powerbi.data.ISQExpr[]): IColorScale {\r\n return this.colors.getColorScaleByKey(SQExprShortSerializer.serializeArray(<data.SQExpr[]>fieldIds || []));\r\n }\r\n\r\n /** \r\n * Gets the color for the given measure.\r\n */\r\n public getColorForMeasure(objects: DataViewObjects, measureKey: any): string {\r\n // Note, this allocates the color from the scale regardless of if we use it or not which helps keep colors stable.\r\n let scaleColor = this.defaultColorScale.getColor(measureKey).value;\r\n\r\n return (this.fillProp && DataViewObjects.getFillColor(objects, this.fillProp))\r\n || this.defaultDataPointColor\r\n || scaleColor;\r\n }\r\n\r\n public static normalizeSelector(selector: data.Selector, isSingleSeries?: boolean): data.Selector {\r\n debug.assertAnyValue(selector, 'selector');\r\n\r\n // For dynamic series charts, colors are set per category. So, exclude any measure (metadata repetition) from the selector.\r\n if (selector && (isSingleSeries || selector.data))\r\n return { data: selector.data };\r\n\r\n return selector;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n\r\n const rectName = 'rect';\r\n\r\n export module ColumnUtil {\r\n export const DimmedOpacity = 0.4;\r\n export const DefaultOpacity = 1.0;\r\n\r\n export function applyUserMinMax(isScalar: boolean, dataView: DataViewCategorical, xAxisCardProperties: DataViewObject): DataViewCategorical {\r\n if (isScalar) {\r\n let min = xAxisCardProperties['start'];\r\n let max = xAxisCardProperties['end'];\r\n\r\n return ColumnUtil.transformDomain(dataView, min, max);\r\n }\r\n\r\n return dataView;\r\n }\r\n\r\n export function transformDomain(dataView: DataViewCategorical, min: DataViewPropertyValue, max: DataViewPropertyValue): DataViewCategorical {\r\n if (!dataView.categories || !dataView.values || dataView.categories.length === 0 || dataView.values.length === 0)\r\n return dataView;// no need to do something when there are no categories \r\n \r\n if (typeof min !== \"number\" && typeof max !== \"number\")\r\n return dataView;//user did not set min max, nothing to do here \r\n \r\n let category = dataView.categories[0];//at the moment we only support one category\r\n let categoryValues = category.values;\r\n let categoryObjects = category.objects;\r\n\r\n if (!categoryValues || !categoryObjects)\r\n return dataView;\r\n let newcategoryValues = [];\r\n let newValues = [];\r\n let newObjects = [];\r\n\r\n //get new min max\r\n if (typeof min !== \"number\") {\r\n min = categoryValues[0];\r\n }\r\n if (typeof max !== \"number\") {\r\n max = categoryValues[categoryValues.length - 1];\r\n }\r\n\r\n //don't allow this\r\n if (min > max)\r\n return dataView;\r\n\r\n //build measure array\r\n for (let j = 0, len = dataView.values.length; j < len; j++) {\r\n newValues.push([]);\r\n }\r\n\r\n for (let t = 0, len = categoryValues.length; t < len; t++) {\r\n if (categoryValues[t] >= min && categoryValues[t] <= max) {\r\n newcategoryValues.push(categoryValues[t]);\r\n if (categoryObjects) {\r\n newObjects.push(categoryObjects[t]);\r\n }\r\n \r\n //on each measure set the new range\r\n if (dataView.values) {\r\n for (let k = 0; k < dataView.values.length; k++) {\r\n newValues[k].push(dataView.values[k].values[t]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n //don't write directly to dataview\r\n let resultDataView = Prototype.inherit(dataView);\r\n let resultDataViewValues = resultDataView.values = Prototype.inherit(resultDataView.values);\r\n let resultDataViewCategories = resultDataView.categories = Prototype.inherit(dataView.categories);\r\n let resultDataViewCategories0 = resultDataView.categories[0] = Prototype.inherit(resultDataViewCategories[0]);\r\n\r\n resultDataViewCategories0.values = newcategoryValues;\r\n //only if we had objects, then you set the new objects\r\n if (resultDataViewCategories0.objects) {\r\n resultDataViewCategories0.objects = newObjects;\r\n }\r\n\r\n //update measure array\r\n for (let t = 0, len = dataView.values.length; t < len; t++) {\r\n let measureArray = resultDataViewValues[t] = Prototype.inherit(resultDataViewValues[t]);\r\n measureArray.values = newValues[t];\r\n }\r\n\r\n return resultDataView;\r\n }\r\n\r\n export function getCategoryAxis(\r\n data: ColumnChartData,\r\n size: number,\r\n layout: CategoryLayout,\r\n isVertical: boolean,\r\n forcedXMin?: DataViewPropertyValue,\r\n forcedXMax?: DataViewPropertyValue,\r\n axisScaleType?: string,\r\n axisDisplayUnits?: number,\r\n axisPrecision?: number,\r\n ensureXDomain?: NumberRange): IAxisProperties {\r\n\r\n let categoryThickness = layout.categoryThickness;\r\n let isScalar = layout.isScalar;\r\n let outerPaddingRatio = layout.outerPaddingRatio;\r\n let domain = AxisHelper.createDomain(data.series, data.categoryMetadata ? data.categoryMetadata.type : ValueType.fromDescriptor({ text: true }), isScalar, [forcedXMin, forcedXMax], ensureXDomain);\r\n\r\n let axisProperties = AxisHelper.createAxis({\r\n pixelSpan: size,\r\n dataDomain: domain,\r\n metaDataColumn: data.categoryMetadata,\r\n formatString: valueFormatter.getFormatString(data.categoryMetadata, columnChartProps.general.formatString),\r\n outerPadding: categoryThickness * outerPaddingRatio,\r\n isCategoryAxis: true,\r\n isScalar: isScalar,\r\n isVertical: isVertical,\r\n categoryThickness: categoryThickness,\r\n useTickIntervalForDisplayUnits: true,\r\n getValueFn: (index, type) => CartesianHelper.lookupXValue(data, index, type, isScalar),\r\n scaleType: axisScaleType,\r\n axisDisplayUnits: axisDisplayUnits,\r\n axisPrecision: axisPrecision\r\n });\r\n\r\n // intentionally updating the input layout by ref\r\n layout.categoryThickness = axisProperties.categoryThickness;\r\n\r\n return axisProperties;\r\n }\r\n\r\n export function applyInteractivity(columns: D3.Selection, onDragStart): void {\r\n debug.assertValue(columns, 'columns');\r\n\r\n if (onDragStart) {\r\n columns\r\n .attr('draggable', 'true')\r\n .on('dragstart', onDragStart);\r\n }\r\n }\r\n\r\n export function getFillOpacity(selected: boolean, highlight: boolean, hasSelection: boolean, hasPartialHighlights: boolean): number {\r\n if ((hasPartialHighlights && !highlight) || (hasSelection && !selected))\r\n return DimmedOpacity;\r\n return DefaultOpacity;\r\n }\r\n\r\n export function getClosestColumnIndex(coordinate: number, columnsCenters: number[]): number {\r\n let currentIndex = 0;\r\n let distance: number = Number.MAX_VALUE;\r\n for (let i = 0, ilen = columnsCenters.length; i < ilen; i++) {\r\n let currentDistance = Math.abs(coordinate - columnsCenters[i]);\r\n if (currentDistance < distance) {\r\n distance = currentDistance;\r\n currentIndex = i;\r\n }\r\n }\r\n\r\n return currentIndex;\r\n }\r\n\r\n export function setChosenColumnOpacity(mainGraphicsContext: D3.Selection, columnGroupSelector: string, selectedColumnIndex: number, lastColumnIndex: number): void {\r\n let series = mainGraphicsContext.selectAll(ColumnChart.SeriesClasses.selector);\r\n let lastColumnUndefined = typeof lastColumnIndex === 'undefined';\r\n // find all columns that do not belong to the selected column and set a dimmed opacity with a smooth animation to those columns\r\n series.selectAll(rectName + columnGroupSelector).filter((d: ColumnChartDataPoint) => {\r\n return (d.categoryIndex !== selectedColumnIndex) && (lastColumnUndefined || d.categoryIndex === lastColumnIndex);\r\n }).transition().style('fill-opacity', DimmedOpacity);\r\n\r\n // set the default opacity for the selected column\r\n series.selectAll(rectName + columnGroupSelector).filter((d: ColumnChartDataPoint) => {\r\n return d.categoryIndex === selectedColumnIndex;\r\n }).style('fill-opacity', DefaultOpacity);\r\n }\r\n\r\n export function drawSeries(data: ColumnChartData, graphicsContext: D3.Selection, axisOptions: ColumnAxisOptions): D3.UpdateSelection {\r\n let colGroupSelection = graphicsContext.selectAll(ColumnChart.SeriesClasses.selector);\r\n let series = colGroupSelection.data(data.series,(d: ColumnChartSeries) => d.key);\r\n\r\n series\r\n .enter()\r\n .append('g')\r\n .classed(ColumnChart.SeriesClasses.class, true);\r\n \r\n series\r\n .style({\r\n fill: (d: ColumnChartSeries) => d.color, \r\n });\r\n \r\n series\r\n .exit()\r\n .remove();\r\n\r\n return series;\r\n }\r\n\r\n export function drawDefaultShapes(data: ColumnChartData, series: D3.UpdateSelection, layout: IColumnLayout, itemCS: ClassAndSelector, filterZeros: boolean, hasSelection: boolean): D3.UpdateSelection {\r\n // We filter out invisible (0, null, etc.) values from the dataset\r\n // based on whether animations are enabled or not, Dashboard and\r\n // Exploration mode, respectively.\r\n let dataSelector: (d: ColumnChartSeries) => any[];\r\n if (filterZeros) {\r\n dataSelector = (d: ColumnChartSeries) => {\r\n let filteredData = _.filter(d.data,(datapoint: ColumnChartDataPoint) => !!datapoint.value);\r\n return filteredData;\r\n };\r\n }\r\n else {\r\n dataSelector = (d: ColumnChartSeries) => d.data;\r\n }\r\n\r\n let shapeSelection = series.selectAll(itemCS.selector);\r\n let shapes = shapeSelection.data(dataSelector, (d: ColumnChartDataPoint) => d.key);\r\n\r\n shapes.enter()\r\n .append(rectName)\r\n .attr(\"class\",(d: ColumnChartDataPoint) => itemCS.class.concat(d.highlight ? \" highlight\" : \"\"));\r\n\r\n shapes\r\n .style(\"fill-opacity\", (d: ColumnChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, data.hasHighlights))\r\n .style(\"fill\", (d: ColumnChartDataPoint) => d.color !== data.series[d.seriesIndex].color ? d.color : null) // PERF: Only set the fill color if it is different than series.\r\n .attr(layout.shapeLayout);\r\n\r\n shapes\r\n .exit()\r\n .remove();\r\n\r\n return shapes;\r\n }\r\n\r\n export function drawDefaultLabels(series: D3.UpdateSelection, context: D3.Selection, layout: ILabelLayout, viewPort: IViewport, isAnimator: boolean = false, animationDuration?: number): D3.UpdateSelection {\r\n if (series) {\r\n let seriesData = series.data();\r\n let dataPoints: ColumnChartDataPoint[] = [];\r\n\r\n for (let i = 0, len = seriesData.length; i < len; i++) {\r\n Array.prototype.push.apply(dataPoints, seriesData[i].data);\r\n }\r\n\r\n return dataLabelUtils.drawDefaultLabelsForDataPointChart(dataPoints, context, layout, viewPort, isAnimator, animationDuration);\r\n }\r\n else {\r\n dataLabelUtils.cleanDataLabels(context);\r\n }\r\n }\r\n\r\n export function normalizeInfinityInScale(scale: D3.Scale.GenericScale<any>): void {\r\n // When large values (eg Number.MAX_VALUE) are involved, a call to scale.nice occasionally\r\n // results in infinite values being included in the domain. To correct for that, we need to\r\n // re-normalize the domain now to not include infinities.\r\n let scaledDomain = scale.domain();\r\n for (let i = 0, len = scaledDomain.length; i < len; ++i) {\r\n if (scaledDomain[i] === Number.POSITIVE_INFINITY)\r\n scaledDomain[i] = Number.MAX_VALUE;\r\n else if (scaledDomain[i] === Number.NEGATIVE_INFINITY)\r\n scaledDomain[i] = -Number.MAX_VALUE;\r\n }\r\n\r\n scale.domain(scaledDomain);\r\n }\r\n\r\n export function calculatePosition(d: ColumnChartDataPoint, axisOptions: ColumnAxisOptions): number {\r\n let xScale = axisOptions.xScale;\r\n let yScale = axisOptions.yScale;\r\n let scaledY0 = yScale(0);\r\n let scaledX0 = xScale(0);\r\n switch (d.chartType) {\r\n case ColumnChartType.stackedBar:\r\n case ColumnChartType.hundredPercentStackedBar:\r\n return scaledX0 + Math.abs(AxisHelper.diffScaled(xScale, 0, d.valueAbsolute)) +\r\n AxisHelper.diffScaled(xScale, d.position - d.valueAbsolute, 0) + dataLabelUtils.defaultColumnLabelMargin;\r\n case ColumnChartType.clusteredBar:\r\n return scaledX0 + AxisHelper.diffScaled(xScale, Math.max(0, d.value), 0) + dataLabelUtils.defaultColumnLabelMargin;\r\n case ColumnChartType.stackedColumn:\r\n case ColumnChartType.hundredPercentStackedColumn:\r\n return scaledY0 + AxisHelper.diffScaled(yScale, d.position, 0) - dataLabelUtils.defaultColumnLabelMargin;\r\n case ColumnChartType.clusteredColumn:\r\n return scaledY0 + AxisHelper.diffScaled(yScale, Math.max(0, d.value), 0) - dataLabelUtils.defaultColumnLabelMargin;\r\n }\r\n\r\n }\r\n }\r\n\r\n export module ClusteredUtil {\r\n\r\n export function clearColumns(\r\n mainGraphicsContext: D3.Selection,\r\n itemCS: ClassAndSelector): void {\r\n\r\n debug.assertValue(mainGraphicsContext, 'mainGraphicsContext');\r\n debug.assertValue(itemCS, 'itemCS');\r\n\r\n let cols = mainGraphicsContext.selectAll(itemCS.selector)\r\n .data([]);\r\n\r\n cols.exit().remove();\r\n }\r\n }\r\n\r\n export interface ValueMultiplers {\r\n pos: number;\r\n neg: number;\r\n }\r\n\r\n export module StackedUtil {\r\n const PctRoundingError = 0.0001;\r\n\r\n export function getSize(scale: D3.Scale.GenericScale<any>, size: number, zeroVal: number = 0): number {\r\n return AxisHelper.diffScaled(scale, zeroVal, size);\r\n }\r\n\r\n export function calcValueDomain(data: ColumnChartSeries[], is100pct: boolean): NumberRange {\r\n let defaultNumberRange = {\r\n min: 0,\r\n max: 10\r\n };\r\n\r\n if (data.length === 0)\r\n return defaultNumberRange;\r\n\r\n // Can't use AxisHelper because Stacked layout has a slightly different calc, (position - valueAbs)\r\n let min = d3.min<ColumnChartSeries, number>(data, d => d3.min<ColumnChartDataPoint, number>(d.data, e => e.position - e.valueAbsolute));\r\n let max = d3.max<ColumnChartSeries, number>(data, d => d3.max<ColumnChartDataPoint, number>(d.data, e => e.position));\r\n\r\n if (is100pct) {\r\n min = Double.roundToPrecision(min, PctRoundingError);\r\n max = Double.roundToPrecision(max, PctRoundingError);\r\n }\r\n\r\n return {\r\n min: min,\r\n max: max,\r\n };\r\n }\r\n\r\n export function getStackedMultiplier(\r\n dataView: DataViewCategorical,\r\n rowIdx: number,\r\n seriesCount: number,\r\n categoryCount: number,\r\n converterStrategy: IColumnChartConverterStrategy): ValueMultiplers {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(rowIdx, 'rowIdx');\r\n\r\n let pos: number = 0,\r\n neg: number = 0;\r\n \r\n for (let i = 0; i < seriesCount; i++) {\r\n let value: number = converterStrategy.getValueBySeriesAndCategory(i, rowIdx);\r\n value = AxisHelper.normalizeNonFiniteNumber(value);\r\n\r\n if (value > 0)\r\n pos += value;\r\n else if (value < 0)\r\n neg -= value;\r\n }\r\n\r\n let absTotal = pos + neg;\r\n return {\r\n pos: pos ? (pos / absTotal) / pos : 1,\r\n neg: neg ? (neg / absTotal) / neg : 1,\r\n };\r\n }\r\n\r\n export function clearColumns(\r\n mainGraphicsContext: D3.Selection,\r\n itemCS: ClassAndSelector): void {\r\n\r\n debug.assertValue(mainGraphicsContext, 'mainGraphicsContext');\r\n debug.assertValue(itemCS, 'itemCS');\r\n\r\n let bars = mainGraphicsContext.selectAll(itemCS.selector)\r\n .data([]);\r\n\r\n bars.exit().remove();\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface PivotedCategoryInfo {\r\n categories?: any[];\r\n categoryFormatter?: IValueFormatter;\r\n categoryIdentities?: DataViewScopeIdentity[];\r\n categoryObjects?: DataViewObjects[];\r\n }\r\n\r\n export module converterHelper {\r\n export function categoryIsAlsoSeriesRole(dataView: DataViewCategorical, seriesRoleName: string, categoryRoleName: string): boolean {\r\n if (dataView.categories && dataView.categories.length > 0) {\r\n // Need to pivot data if our category soure is a series role\r\n let category = dataView.categories[0];\r\n return category.source &&\r\n DataRoleHelper.hasRole(category.source, seriesRoleName) &&\r\n DataRoleHelper.hasRole(category.source, categoryRoleName);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n export function getPivotedCategories(dataView: DataViewCategorical, formatStringProp: DataViewObjectPropertyIdentifier): PivotedCategoryInfo {\r\n if (dataView.categories && dataView.categories.length > 0) {\r\n let category = dataView.categories[0];\r\n let categoryValues = category.values;\r\n\r\n return category.values.length > 0\r\n ? {\r\n categories: categoryValues,\r\n categoryFormatter: valueFormatter.create({\r\n format: valueFormatter.getFormatString(category.source, formatStringProp),\r\n value: categoryValues[0],\r\n value2: categoryValues[categoryValues.length - 1],\r\n // Do not use display units such as K/M/bn etc. on the x-axis.\r\n // PowerView does not use units either as large ranges will make the x-axis indecipherable.\r\n displayUnitSystemType: DisplayUnitSystemType.Verbose,\r\n }),\r\n categoryIdentities: category.identity,\r\n categoryObjects: category.objects,\r\n }\r\n : {\r\n categories: [],\r\n categoryFormatter: { format: valueFormatter.format },\r\n };\r\n }\r\n\r\n // For cases where the category source is just a series role, we are pivoting the data on the role which means we\r\n // will have no categories.\r\n return defaultCategories();\r\n }\r\n\r\n export function getSeriesName(source: DataViewMetadataColumn): string {\r\n debug.assertValue(source, 'source');\r\n\r\n return (source.groupName !== undefined)\r\n ? source.groupName\r\n : source.queryName;\r\n }\r\n\r\n export function getFormattedLegendLabel(source: DataViewMetadataColumn, values: DataViewValueColumns, formatStringProp: DataViewObjectPropertyIdentifier): string {\r\n debug.assertValue(source, 'source');\r\n debug.assertValue(values, 'values');\r\n\r\n let sourceForFormat = source;\r\n let nameForFormat = source.displayName;\r\n if (source.groupName !== undefined) {\r\n sourceForFormat = values.source;\r\n nameForFormat = source.groupName;\r\n }\r\n\r\n return valueFormatter.format(nameForFormat, valueFormatter.getFormatString(sourceForFormat, formatStringProp));\r\n }\r\n\r\n function defaultCategories(): PivotedCategoryInfo {\r\n return {\r\n categories: [null],\r\n categoryFormatter: { format: valueFormatter.format },\r\n };\r\n }\r\n\r\n export function createAxesLabels(categoryAxisProperties: DataViewObject,\r\n valueAxisProperties: DataViewObject,\r\n category: DataViewMetadataColumn,\r\n values: DataViewMetadataColumn[]) {\r\n let xAxisLabel = null;\r\n let yAxisLabel = null;\r\n\r\n if (categoryAxisProperties) {\r\n\r\n // Take the value only if it's there\r\n if (category && category.displayName) {\r\n xAxisLabel = category.displayName;\r\n }\r\n }\r\n\r\n if (valueAxisProperties) {\r\n let valuesNames: string[] = [];\r\n \r\n if (values) {\r\n // Take the name from the values, and make it unique because there are sometimes duplications\r\n valuesNames = values.map(v => v ? v.displayName : '').filter((value, index, self) => value !== '' && self.indexOf(value) === index);\r\n yAxisLabel = valueFormatter.formatListAnd(valuesNames);\r\n }\r\n }\r\n return { xAxisLabel: xAxisLabel, yAxisLabel: yAxisLabel };\r\n }\r\n\r\n export function isImageUrlColumn(column: DataViewMetadataColumn): boolean {\r\n let misc = getMiscellaneousTypeDescriptor(column);\r\n return misc != null && misc.imageUrl === true;\r\n }\r\n\r\n export function isWebUrlColumn(column: DataViewMetadataColumn): boolean {\r\n let misc = getMiscellaneousTypeDescriptor(column);\r\n return misc != null && misc.webUrl === true;\r\n }\r\n\r\n function getMiscellaneousTypeDescriptor(column: DataViewMetadataColumn): MiscellaneousTypeDescriptor {\r\n return column\r\n && column.type\r\n && column.type.misc;\r\n }\r\n\r\n export function hasImageUrlColumn(dataView: DataView): boolean {\r\n if (!dataView || !dataView.metadata || _.isEmpty(dataView.metadata.columns))\r\n return false;\r\n\r\n return _.any(dataView.metadata.columns, column => isImageUrlColumn(column) === true);\r\n }\r\n\r\n export function formatFromMetadataColumn(value: any, column: DataViewMetadataColumn, formatStringProp: DataViewObjectPropertyIdentifier): string {\r\n debug.assertValue(column, 'column should exist');\r\n let formatString: string = valueFormatter.getFormatString(column, formatStringProp, true);\r\n if (!formatString && column) {\r\n formatString = column.format;\r\n }\r\n return valueFormatter.format(value, formatString);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import LabelStyle = labelStyle;\r\n\r\n export const enum PointLabelPosition {\r\n Above,\r\n Below,\r\n }\r\n\r\n export interface PointDataLabelsSettings extends VisualDataLabelsSettings {\r\n position: PointLabelPosition;\r\n }\r\n\r\n export interface LabelFormattedTextOptions {\r\n label: any;\r\n maxWidth?: number;\r\n format?: string;\r\n formatter?: IValueFormatter;\r\n fontSize?: number;\r\n }\r\n\r\n export interface VisualDataLabelsSettings {\r\n show: boolean;\r\n showLabelPerSeries?: boolean;\r\n isSeriesExpanded?: boolean;\r\n displayUnits?: number;\r\n showCategory?: boolean;\r\n position?: any;\r\n precision?: number;\r\n labelColor: string;\r\n categoryLabelColor?: string;\r\n fontSize?: number;\r\n labelStyle?: any;\r\n }\r\n\r\n /*\r\n Options for setting the labels card on the property pane\r\n */\r\n export interface VisualDataLabelsSettingsOptions {\r\n show: boolean;\r\n enumeration: ObjectEnumerationBuilder;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n displayUnits?: boolean;\r\n precision?: boolean;\r\n position?: boolean;\r\n positionObject?: string[];\r\n selector?: powerbi.data.Selector;\r\n fontSize?: boolean;\r\n showAll?: boolean;\r\n labelDensity?: boolean;\r\n labelStyle?: boolean;\r\n }\r\n\r\n export interface LabelEnabledDataPoint {\r\n //for collistion detection use\r\n labelX?: number;\r\n labelY?: number;\r\n //for overriding color from label settings\r\n labelFill?: string;\r\n //for display units and precision\r\n labeltext?: string;\r\n //taken from column metadata\r\n labelFormatString?: string;\r\n isLabelInside?: boolean;\r\n labelFontSize?: number;\r\n }\r\n\r\n export interface IColumnFormatterCache {\r\n [column: string]: IValueFormatter;\r\n defaultFormatter?: IValueFormatter;\r\n }\r\n\r\n export interface IColumnFormatterCacheManager {\r\n cache: IColumnFormatterCache;\r\n getOrCreate: (formatString: string, labelSetting: VisualDataLabelsSettings, value2?: number) => IValueFormatter;\r\n }\r\n\r\n export interface LabelPosition {\r\n y: (d: any, i: number) => number;\r\n x: (d: any, i: number) => number;\r\n }\r\n\r\n export interface ILabelLayout {\r\n labelText: (d: any) => string;\r\n labelLayout: LabelPosition;\r\n filter: (d: any) => boolean;\r\n style: {};\r\n }\r\n\r\n export interface DataLabelObject extends DataViewObject {\r\n show: boolean;\r\n color: Fill;\r\n labelDisplayUnits: number;\r\n labelPrecision?: number;\r\n labelPosition: any;\r\n fontSize?: number;\r\n showAll?: boolean;\r\n showSeries?: boolean;\r\n labelDensity?: number;\r\n labelStyle?: any;\r\n }\r\n\r\n export module dataLabelUtils {\r\n export const minLabelFontSize: number = 8;\r\n export const labelMargin: number = 8;\r\n export const maxLabelWidth: number = 50;\r\n export const defaultColumnLabelMargin: number = 5;\r\n export const defaultColumnHalfLabelHeight: number = 4;\r\n export const DefaultDy: string = '-0.15em';\r\n export const DefaultFontSizeInPt = 9;\r\n export const StandardFontFamily = 'wf_segoe-ui_normal';\r\n export const LabelTextProperties: TextProperties = {\r\n fontFamily: 'wf_standard-font',\r\n fontSize: PixelConverter.fromPoint(DefaultFontSizeInPt),\r\n fontWeight: 'normal',\r\n };\r\n export const defaultLabelColor = \"#777777\";\r\n export const defaultInsideLabelColor = \"#ffffff\";\r\n export const hundredPercentFormat = \"0.00 %;-0.00 %;0.00 %\";\r\n \r\n export const defaultLabelPrecision: number = undefined;\r\n const defaultCountLabelPrecision: number = 0;\r\n\r\n const labelGraphicsContextClass: ClassAndSelector = createClassAndSelector('labels');\r\n const linesGraphicsContextClass: ClassAndSelector = createClassAndSelector('lines');\r\n const labelsClass: ClassAndSelector = createClassAndSelector('data-labels');\r\n const lineClass: ClassAndSelector = createClassAndSelector('line-label');\r\n\r\n export function updateLabelSettingsFromLabelsObject(labelsObj: DataLabelObject, labelSettings: VisualDataLabelsSettings): void {\r\n if (labelsObj) {\r\n if (labelsObj.show !== undefined)\r\n labelSettings.show = labelsObj.show;\r\n if (labelsObj.showSeries !== undefined)\r\n labelSettings.show = labelsObj.showSeries;\r\n if (labelsObj.color !== undefined)\r\n labelSettings.labelColor = labelsObj.color.solid.color;\r\n if (labelsObj.labelDisplayUnits !== undefined)\r\n labelSettings.displayUnits = labelsObj.labelDisplayUnits;\r\n if (labelsObj.labelPrecision !== undefined)\r\n labelSettings.precision = (labelsObj.labelPrecision >= 0) ? labelsObj.labelPrecision : defaultLabelPrecision;\r\n if (labelsObj.fontSize !== undefined)\r\n labelSettings.fontSize = labelsObj.fontSize;\r\n if (labelsObj.showAll !== undefined)\r\n labelSettings.showLabelPerSeries = labelsObj.showAll;\r\n if (labelsObj.labelStyle !== undefined)\r\n labelSettings.labelStyle = labelsObj.labelStyle;\r\n }\r\n }\r\n\r\n export function updateLineChartLabelSettingsFromLabelsObject(labelsObj: DataLabelObject, labelSettings: LineChartDataLabelsSettings): void {\r\n\r\n updateLabelSettingsFromLabelsObject(labelsObj, labelSettings);\r\n\r\n if (labelsObj && labelsObj.labelDensity !== undefined)\r\n labelSettings.labelDensity = labelsObj.labelDensity;\r\n }\r\n\r\n export function getDefaultLabelSettings(show: boolean = false, labelColor?: string, fontSize?: number): VisualDataLabelsSettings {\r\n return {\r\n show: show,\r\n position: PointLabelPosition.Above,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: labelColor || defaultLabelColor,\r\n formatterOptions: null,\r\n fontSize: fontSize || DefaultFontSizeInPt,\r\n };\r\n }\r\n\r\n export function getDefaultCardLabelSettings(labelColor: string, categoryLabelColor: string, fontSize?: number): VisualDataLabelsSettings {\r\n let labelSettings = getDefaultLabelSettings(true, labelColor, fontSize);\r\n labelSettings.showCategory = true;\r\n labelSettings.categoryLabelColor = categoryLabelColor;\r\n return labelSettings;\r\n }\r\n\r\n export function getDefaultTreemapLabelSettings(): VisualDataLabelsSettings {\r\n return {\r\n show: false,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: defaultInsideLabelColor,\r\n showCategory: true,\r\n formatterOptions: null,\r\n };\r\n }\r\n\r\n export function getDefaultSunburstLabelSettings(): VisualDataLabelsSettings {\r\n return {\r\n show: false, \r\n labelColor: defaultInsideLabelColor,\r\n fontSize: DefaultFontSizeInPt,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n showCategory: true,\r\n };\r\n }\r\n\r\n export function getDefaultColumnLabelSettings(isLabelPositionInside: boolean): VisualDataLabelsSettings {\r\n let labelSettings = getDefaultLabelSettings(false, undefined);\r\n labelSettings.position = null;\r\n labelSettings.labelColor = undefined;\r\n return labelSettings;\r\n }\r\n\r\n export function getDefaultPointLabelSettings(): PointDataLabelsSettings {\r\n return {\r\n show: false,\r\n position: PointLabelPosition.Above,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: defaultLabelColor,\r\n formatterOptions: null,\r\n fontSize: DefaultFontSizeInPt,\r\n };\r\n }\r\n\r\n export function getDefaultLineChartLabelSettings(isComboChart?: boolean): LineChartDataLabelsSettings {\r\n return {\r\n show: false,\r\n position: PointLabelPosition.Above,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: defaultLabelColor,\r\n formatterOptions: null,\r\n fontSize: DefaultFontSizeInPt,\r\n labelDensity: isComboChart ? NewDataLabelUtils.LabelDensityMax : NewDataLabelUtils.LabelDensityMin,\r\n };\r\n }\r\n\r\n export function getDefaultMapLabelSettings(): PointDataLabelsSettings {\r\n return {\r\n show: false,\r\n showCategory: false,\r\n position: PointLabelPosition.Above,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: defaultInsideLabelColor,\r\n formatterOptions: null,\r\n fontSize: DefaultFontSizeInPt,\r\n };\r\n }\r\n\r\n export function getDefaultDonutLabelSettings(): VisualDataLabelsSettings {\r\n let labelSettings = dataLabelUtils.getDefaultLabelSettings(true, defaultLabelColor, DefaultFontSizeInPt);\r\n labelSettings.labelStyle = LabelStyle.category;\r\n return labelSettings;\r\n }\r\n\r\n export function getDefaultGaugeLabelSettings(): VisualDataLabelsSettings {\r\n return {\r\n show: true,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: null,\r\n position: null,\r\n fontSize: dataLabelUtils.minLabelFontSize,\r\n formatterOptions: null,\r\n };\r\n }\r\n\r\n export function getDefaultFunnelLabelSettings(): VisualDataLabelsSettings {\r\n return {\r\n show: true,\r\n position: powerbi.visuals.labelPosition.insideCenter,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: defaultLabelColor,\r\n formatterOptions: null,\r\n fontSize: DefaultFontSizeInPt,\r\n };\r\n }\r\n\r\n export function getDefaultKpiLabelSettings(): VisualDataLabelsSettings {\r\n return {\r\n show: false,\r\n displayUnits: 0,\r\n precision: defaultLabelPrecision,\r\n labelColor: defaultLabelColor,\r\n position: null,\r\n showCategory: true,\r\n formatterOptions: null,\r\n };\r\n }\r\n\r\n export function getLabelPrecision(precision: number, format: string): number {\r\n debug.assertAnyValue(format, 'format');\r\n\r\n if (precision !== defaultLabelPrecision)\r\n return precision;\r\n\r\n if (format === 'g' || format === 'G')\r\n return;\r\n\r\n if (format) {\r\n // Calculate precision from positive format by default\r\n let positiveFormat = format.split(\";\")[0];\r\n let formatMetadata = NumberFormat.getCustomFormatMetadata(positiveFormat, true /*calculatePrecision*/);\r\n if (formatMetadata.hasDots) {\r\n return formatMetadata.precision;\r\n }\r\n }\r\n\r\n // For count fields we do not want a precision by default\r\n return defaultCountLabelPrecision;\r\n }\r\n\r\n export function drawDefaultLabelsForDataPointChart(data: any[], context: D3.Selection, layout: ILabelLayout,\r\n viewport: IViewport, isAnimator: boolean = false, animationDuration?: number, hasSelection?: boolean): D3.UpdateSelection {\r\n debug.assertValue(data, 'data cannot be null or undefined');\r\n\r\n // Hide and reposition labels that overlap\r\n let dataLabelManager = new DataLabelManager();\r\n let filteredData = dataLabelManager.hideCollidedLabels(viewport, data, layout);\r\n\r\n let hasAnimation = isAnimator && !!animationDuration;\r\n let labels = selectLabels(filteredData, context, false, hasAnimation);\r\n\r\n if (!labels)\r\n return;\r\n\r\n if (hasAnimation) {\r\n labels\r\n .text((d: LabelEnabledDataPoint) => d.labeltext)\r\n .transition()\r\n .duration(animationDuration)\r\n .style(layout.style)\r\n .style('opacity', hasSelection ? (d: SelectableDataPoint) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false) : 1)\r\n .attr({ x: (d: LabelEnabledDataPoint) => d.labelX, y: (d: LabelEnabledDataPoint) => d.labelY });\r\n\r\n labels\r\n .exit()\r\n .transition()\r\n .duration(animationDuration)\r\n .style('opacity', 0) //fade out labels that are removed\r\n .remove();\r\n }\r\n else {\r\n labels\r\n .attr({ x: (d: LabelEnabledDataPoint) => d.labelX, y: (d: LabelEnabledDataPoint) => d.labelY })\r\n .text((d: LabelEnabledDataPoint) => d.labeltext)\r\n .style(layout.style);\r\n\r\n labels\r\n .exit()\r\n .remove();\r\n }\r\n\r\n return labels;\r\n }\r\n \r\n /**\r\n * Note: Funnel chart uses animation and does not use collision detection.\r\n */\r\n export function drawDefaultLabelsForFunnelChart(data: FunnelSlice[], context: D3.Selection, layout: ILabelLayout, isAnimator: boolean = false, animationDuration?: number): D3.UpdateSelection {\r\n debug.assertValue(data, 'data could not be null or undefined');\r\n\r\n let filteredData = data.filter(layout.filter);\r\n\r\n let labels = selectLabels(filteredData, context);\r\n\r\n if (!labels)\r\n return;\r\n\r\n labels\r\n .attr(layout.labelLayout)\r\n .text(layout.labelText)\r\n .style(layout.style);\r\n\r\n if (isAnimator && animationDuration) {\r\n labels.transition().duration(animationDuration);\r\n }\r\n\r\n labels\r\n .exit()\r\n .remove();\r\n\r\n return labels;\r\n }\r\n \r\n function selectLabels(filteredData: LabelEnabledDataPoint[], context: D3.Selection, isDonut: boolean = false, forAnimation: boolean = false): D3.UpdateSelection {\r\n\r\n // Check for a case where resizing leaves no labels - then we need to remove the labels 'g'\r\n if (filteredData.length === 0) {\r\n cleanDataLabels(context, true);\r\n return null;\r\n }\r\n\r\n if (context.select(labelGraphicsContextClass.selector).empty())\r\n context.append('g').classed(labelGraphicsContextClass.class, true);\r\n\r\n // line chart ViewModel has a special 'key' property for point identification since the 'identity' field is set to the series identity\r\n let hasKey: boolean = (<any>filteredData)[0].key != null;\r\n let hasDataPointIdentity: boolean = (<any>filteredData)[0].identity != null;\r\n let getIdentifier = hasKey ?\r\n (d: any) => d.key\r\n : hasDataPointIdentity ?\r\n (d: SelectableDataPoint) => d.identity.getKey()\r\n : undefined;\r\n\r\n let labels = isDonut ?\r\n context.select(labelGraphicsContextClass.selector).selectAll(labelsClass.selector).data(filteredData, (d: DonutArcDescriptor) => d.data.identity.getKey())\r\n : getIdentifier != null ?\r\n context.select(labelGraphicsContextClass.selector).selectAll(labelsClass.selector).data(filteredData, getIdentifier)\r\n : context.select(labelGraphicsContextClass.selector).selectAll(labelsClass.selector).data(filteredData);\r\n\r\n let newLabels = labels.enter()\r\n .append('text')\r\n .classed(labelsClass.class, true);\r\n if (forAnimation)\r\n newLabels.style('opacity', 0);\r\n\r\n return labels;\r\n }\r\n\r\n export function cleanDataLabels(context: D3.Selection, removeLines: boolean = false) {\r\n let empty = [];\r\n let labels = context.selectAll(labelsClass.selector).data(empty);\r\n labels.exit().remove();\r\n context.selectAll(labelGraphicsContextClass.selector).remove();\r\n if (removeLines) {\r\n let lines = context.selectAll(lineClass.selector).data(empty);\r\n lines.exit().remove();\r\n context.selectAll(linesGraphicsContextClass.selector).remove();\r\n }\r\n }\r\n\r\n export function setHighlightedLabelsOpacity(context: D3.Selection, hasSelection: boolean, hasHighlights: boolean) {\r\n context.selectAll(labelsClass.selector).style(\"fill-opacity\", (d: ColumnChartDataPoint) => {\r\n let labelOpacity = ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && hasHighlights) < 1 ? 0 : 1;\r\n return labelOpacity;\r\n });\r\n }\r\n\r\n export function getLabelFormattedText(options: LabelFormattedTextOptions): string {\r\n let properties: TextProperties = {\r\n text: options.formatter\r\n ? options.formatter.format(options.label)\r\n : formattingService.formatValue(options.label, options.format),\r\n fontFamily: LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(options.fontSize),\r\n fontWeight: LabelTextProperties.fontWeight,\r\n };\r\n return TextMeasurementService.getTailoredTextOrDefault(properties, options.maxWidth ? options.maxWidth : maxLabelWidth);\r\n }\r\n\r\n export function getLabelLayoutXYForWaterfall(xAxisProperties: IAxisProperties, categoryWidth: number, yAxisProperties: IAxisProperties, dataDomain: number[]): LabelPosition {\r\n return {\r\n x: (d: WaterfallChartDataPoint) => xAxisProperties.scale(d.categoryIndex) + (categoryWidth / 2),\r\n y: (d: WaterfallChartDataPoint) => getWaterfallLabelYPosition(yAxisProperties.scale, d, dataDomain)\r\n };\r\n }\r\n\r\n function getWaterfallLabelYPosition(scale: D3.Scale.GenericScale<any>, d: WaterfallChartDataPoint, dataDomain: number[]): number {\r\n\r\n let yValue = scale(0) - scale(Math.abs(d.value));\r\n let yPos = scale(d.position);\r\n let scaleMinDomain = scale(dataDomain[0]);\r\n let endPosition = scale(d.position + d.value);\r\n\r\n if (d.value < 0) {\r\n let properties: TextProperties = {\r\n text: d.labeltext,\r\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let outsideBelowPosition = yPos + yValue + TextMeasurementService.estimateSvgTextHeight(properties);\r\n // Try to honor the position, but if the label doesn't fit where specified, then swap the position.\r\n if (scaleMinDomain > outsideBelowPosition) {\r\n return outsideBelowPosition;\r\n }\r\n }\r\n else {\r\n let outsideAbovePosition = yPos - yValue - dataLabelUtils.labelMargin;\r\n // Try to honor the position, but if the label doesn't fit where specified, then swap the position.\r\n if (outsideAbovePosition > 0) {\r\n return outsideAbovePosition;\r\n }\r\n }\r\n d.isLabelInside = true;\r\n return getWaterfallInsideLabelYPosition(yPos, endPosition, scaleMinDomain);\r\n }\r\n\r\n function getWaterfallInsideLabelYPosition(startPosition: number, endPosition: number, scaleMinDomain: number): number {\r\n // Get the start and end position of the column\r\n // If the start or end is outside of the visual because of clipping - adjust the position\r\n startPosition = startPosition < 0 ? 0 : startPosition;\r\n startPosition = startPosition > scaleMinDomain ? scaleMinDomain : startPosition;\r\n\r\n endPosition = endPosition < 0 ? 0 : endPosition;\r\n endPosition = endPosition > scaleMinDomain ? scaleMinDomain : endPosition;\r\n\r\n return (Math.abs(endPosition - startPosition) / 2) + Math.min(startPosition, endPosition);\r\n }\r\n\r\n export function doesDataLabelFitInShape(d: WaterfallChartDataPoint, yAxisProperties: IAxisProperties, layout: WaterfallLayout): boolean {\r\n\r\n if (d == null || d.value === null)\r\n return false;\r\n\r\n let properties: TextProperties = {\r\n text: layout.labelText(d),\r\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n\r\n let outsidePosition = WaterfallChart.getRectTop(yAxisProperties.scale, d.position, d.value) - dataLabelUtils.labelMargin;\r\n\r\n // The shape is fit to be outside\r\n if (outsidePosition > 0)\r\n return true;\r\n\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties);\r\n\r\n let shapeWidth = layout.categoryWidth;\r\n let shapeHeight = Math.abs(AxisHelper.diffScaled(yAxisProperties.scale, Math.max(0, Math.abs(d.value)), 0));\r\n\r\n //checking that labels aren't greater than shape\r\n if ((textWidth > shapeWidth) || (textHeight > shapeHeight))\r\n return false;\r\n return true;\r\n }\r\n\r\n export function getMapLabelLayout(labelSettings: PointDataLabelsSettings): ILabelLayout {\r\n\r\n return {\r\n labelText: (d: MapVisualDataPoint) => {\r\n return getLabelFormattedText({\r\n label: d.labeltext,\r\n fontSize: labelSettings.fontSize\r\n });\r\n },\r\n labelLayout: {\r\n x: (d: MapVisualDataPoint) => d.x,\r\n y: (d: MapVisualDataPoint) => {\r\n let margin = d.radius + labelMargin;\r\n return labelSettings.position === PointLabelPosition.Above ? d.y - margin : d.y + margin;\r\n },\r\n },\r\n filter: (d: MapVisualDataPoint) => {\r\n return (d != null && d.labeltext != null);\r\n },\r\n style: {\r\n 'fill': (d: MapVisualDataPoint) => d.labelFill,\r\n 'font-size': PixelConverter.fromPoint(labelSettings.fontSize),\r\n },\r\n };\r\n }\r\n\r\n export function getColumnChartLabelLayout(\r\n data: ColumnChartData,\r\n labelLayoutXY: any,\r\n isColumn: boolean,\r\n isHundredPercent: boolean,\r\n axisFormatter: IValueFormatter,\r\n axisOptions: ColumnAxisOptions,\r\n interactivityService: IInteractivityService,\r\n visualWidth?: number): ILabelLayout {\r\n\r\n let formatOverride: string = (isHundredPercent) ? hundredPercentFormat : null;\r\n let formattersCache = createColumnFormatterCacheManager();\r\n let hasSelection = interactivityService ? interactivityService.hasSelection() : false;\r\n\r\n return {\r\n labelText: (d: ColumnChartDataPoint) => {\r\n let formatString = (formatOverride != null) ? formatOverride : d.labelFormatString;\r\n let value2: number = getDisplayUnitValueFromAxisFormatter(axisFormatter, d.labelSettings);\r\n let formatter = formattersCache.getOrCreate(formatString, d.labelSettings, value2);\r\n return getLabelFormattedText({\r\n label: formatter.format(d.value),\r\n maxWidth: maxLabelWidth\r\n });\r\n },\r\n labelLayout: labelLayoutXY,\r\n filter: (d: ColumnChartDataPoint) => dataLabelUtils.getColumnChartLabelFilter(d, hasSelection, data.hasHighlights, axisOptions, visualWidth),\r\n style: {\r\n 'fill': (d: ColumnChartDataPoint) => d.labelFill,\r\n 'text-anchor': isColumn ? 'middle' : 'start',\r\n },\r\n };\r\n }\r\n \r\n /**\r\n * Valide for stacked column/bar chart and 100% stacked column/bar chart,\r\n * that labels that should to be inside the shape aren't bigger then shapes.\r\n */\r\n function validateLabelsSize(d: ColumnChartDataPoint, axisOptions: ColumnAxisOptions, visualWidth?: number): boolean {\r\n let xScale = axisOptions.xScale;\r\n let yScale = axisOptions.yScale;\r\n let columnWidth = axisOptions.columnWidth;\r\n let properties: TextProperties = {\r\n text: d.labeltext,\r\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties);\r\n let shapeWidth, shapeHeight;\r\n let inside = false;\r\n let outsidePosition: number = ColumnUtil.calculatePosition(d, axisOptions);\r\n switch (d.chartType) {\r\n case ColumnChartType.stackedBar:\r\n case ColumnChartType.hundredPercentStackedBar:\r\n // if the series isn't last or the label doesn't fit where specified, then it should be inside \r\n if (!d.lastSeries || (outsidePosition + textWidth > visualWidth) || d.chartType === ColumnChartType.hundredPercentStackedBar) {\r\n shapeWidth = -StackedUtil.getSize(xScale, d.valueAbsolute);\r\n shapeHeight = columnWidth;\r\n inside = true;\r\n }\r\n break;\r\n case ColumnChartType.clusteredBar:\r\n \r\n // if the label doesn't fit where specified, then it should be inside \r\n if ((outsidePosition + textWidth) > visualWidth) {\r\n shapeWidth = Math.abs(AxisHelper.diffScaled(xScale, 0, d.value));\r\n shapeHeight = columnWidth;\r\n inside = true;\r\n }\r\n break;\r\n case ColumnChartType.stackedColumn:\r\n case ColumnChartType.hundredPercentStackedColumn:\r\n // if the series isn't last or the label doesn't fit where specified, then it should be inside \r\n if (!d.lastSeries || outsidePosition <= 0 || d.chartType === ColumnChartType.hundredPercentStackedColumn) {\r\n shapeWidth = columnWidth;\r\n shapeHeight = StackedUtil.getSize(yScale, d.valueAbsolute);\r\n inside = true;\r\n }\r\n break;\r\n case ColumnChartType.clusteredColumn:\r\n // if the label doesn't fit where specified, then it should be inside \r\n if (outsidePosition <= 0) {\r\n shapeWidth = columnWidth;\r\n shapeHeight = Math.abs(AxisHelper.diffScaled(yScale, 0, d.value));\r\n inside = true;\r\n }\r\n break;\r\n default:\r\n return true;\r\n }\r\n\r\n //checking that labels aren't greater than shape\r\n if (inside && ((textWidth > shapeWidth) || textHeight > shapeHeight)) return false;\r\n return true;\r\n }\r\n\r\n export function getColumnChartLabelFilter(d: ColumnChartDataPoint, hasSelection: boolean, hasHighlights: boolean, axisOptions: ColumnAxisOptions, visualWidth?: number): any {\r\n //labels of dimmed are hidden\r\n let shapesOpacity = hasSelection ? ColumnUtil.getFillOpacity(d.selected, d.highlight, !d.highlight && hasSelection, !d.selected && hasHighlights) :\r\n ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights);\r\n return (d != null && d.value != null && validateLabelsSize(d, axisOptions, visualWidth) && shapesOpacity === 1);\r\n }\r\n\r\n export function getScatterChartLabelLayout(xScale: D3.Scale.GenericScale<any>, yScale: D3.Scale.GenericScale<any>, labelSettings: PointDataLabelsSettings, viewport: IViewport, sizeRange: NumberRange): ILabelLayout {\r\n\r\n return {\r\n labelText: (d: ScatterChartDataPoint) => {\r\n return getLabelFormattedText({\r\n label: d.formattedCategory.getValue(),\r\n maxWidth: maxLabelWidth * 2.0\r\n });\r\n },\r\n labelLayout: {\r\n x: (d: ScatterChartDataPoint) => xScale(d.x),\r\n y: (d: ScatterChartDataPoint) => {\r\n let margin = ScatterChart.getBubbleRadius(d.radius, sizeRange, viewport) + labelMargin;\r\n return labelSettings.position === PointLabelPosition.Above ? yScale(d.y) - margin : yScale(d.y) + margin;\r\n },\r\n },\r\n filter: (d: ScatterChartDataPoint) => {\r\n return (d != null && d.formattedCategory.getValue() != null);\r\n },\r\n style: {\r\n 'fill': (d: ScatterChartDataPoint) => d.labelFill,\r\n },\r\n };\r\n }\r\n\r\n export function getLineChartLabelLayout(xScale: D3.Scale.GenericScale<any>, yScale: D3.Scale.GenericScale<any>, labelSettings: PointDataLabelsSettings, isScalar: boolean, axisFormatter: IValueFormatter): ILabelLayout {\r\n let formattersCache = createColumnFormatterCacheManager();\r\n\r\n return {\r\n labelText: (d: LineChartDataPoint) => {\r\n let value2: number = getDisplayUnitValueFromAxisFormatter(axisFormatter, d.labelSettings);\r\n let formatter = formattersCache.getOrCreate(d.labelFormatString, d.labelSettings, value2);\r\n return getLabelFormattedText({ label: formatter.format(d.value) });\r\n },\r\n labelLayout: {\r\n x: (d: LineChartDataPoint) => xScale(isScalar ? d.categoryValue : d.categoryIndex),\r\n y: (d: LineChartDataPoint) => { return labelSettings.position === PointLabelPosition.Above ? yScale(d.value) - labelMargin : yScale(d.value) + labelMargin; },\r\n },\r\n filter: (d: LineChartDataPoint) => {\r\n return (d != null && d.value != null);\r\n },\r\n style: {\r\n 'fill': (d: LineChartDataPoint) => d.labelFill,\r\n 'font-size': (d: LineChartDataPoint) => PixelConverter.fromPoint(d.labelSettings.fontSize),\r\n },\r\n };\r\n }\r\n \r\n export function getFunnelChartLabelLayout(\r\n data: FunnelData,\r\n axisOptions: FunnelAxisOptions,\r\n textMinimumPadding: number,\r\n labelSettings: VisualDataLabelsSettings,\r\n currentViewport: IViewport): ILabelLayout {\r\n\r\n let categoryScale = axisOptions.categoryScale;\r\n let valueScale = axisOptions.valueScale;\r\n let marginLeft = axisOptions.margin.left;\r\n let innerTextHeightRate = 0.7;\r\n let rangeBand = axisOptions.categoryScale.rangeBand();\r\n \r\n let pixelSpan = axisOptions.maxWidth / 2;\r\n let formatString = valueFormatter.getFormatString(data.valuesMetadata[0], funnelChartProps.general.formatString);\r\n let textMeasurer: ITextAsSVGMeasurer = TextMeasurementService.measureSvgTextWidth;\r\n\r\n let value2: number = null;\r\n if (labelSettings.displayUnits === 0) {\r\n let minY = <number>d3.min(data.slices, (d) => { return d.value; });\r\n let maxY = <number>d3.max(data.slices, (d) => { return d.value; });\r\n value2 = Math.max(Math.abs(minY), Math.abs(maxY));\r\n }\r\n\r\n let formattersCache = createColumnFormatterCacheManager();\r\n\r\n return {\r\n labelText: (d: FunnelSlice) => {\r\n let barWidth = Math.abs(categoryScale(d.value) - categoryScale(0));\r\n let insideAvailableSpace = Math.abs(categoryScale(d.value) - categoryScale(0)) - (textMinimumPadding * 2);\r\n let outsideAvailableSpace = pixelSpan - (barWidth / 2) - textMinimumPadding;\r\n let labelFormatString = (formatString != null) ? formatString : d.labelFormatString;\r\n\r\n let maximumTextSize = Math.max(insideAvailableSpace, outsideAvailableSpace);\r\n let formatter = formattersCache.getOrCreate(labelFormatString, labelSettings, value2);\r\n let labelText = formatter.format(FunnelChart.getFunnelSliceValue(d, true /* asOriginal */));\r\n return getLabelFormattedText({\r\n label: labelText,\r\n maxWidth: maximumTextSize,\r\n fontSize: labelSettings.fontSize\r\n });\r\n },\r\n labelLayout: {\r\n y: (d: FunnelSlice, i) => {\r\n let properties: TextProperties = {\r\n text: d.labeltext,\r\n fontFamily: LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\r\n fontWeight: LabelTextProperties.fontWeight,\r\n };\r\n //in order to make it center aligned we should 'correct' the height to not calculate text margin\r\n let labelHeight = TextMeasurementService.estimateSvgTextHeight(properties);\r\n return categoryScale(d.categoryOrMeasureIndex) + (rangeBand / 2) + (labelHeight / 2);\r\n },\r\n x: (d: FunnelSlice) => {\r\n let barWidth = Math.abs(valueScale(d.value) - valueScale(0));\r\n let insideAvailableSpace = Math.abs(valueScale(d.value) - valueScale(0)) - (textMinimumPadding * 2);\r\n let outsideAvailableSpace = pixelSpan - (barWidth / 2) - textMinimumPadding;\r\n let maximumTextSize = Math.max(insideAvailableSpace, outsideAvailableSpace);\r\n let labelFormatString = (formatString != null) ? formatString : d.labelFormatString;\r\n\r\n let formatter = formattersCache.getOrCreate(labelFormatString, labelSettings, value2);\r\n let labelText = formatter.format(FunnelChart.getFunnelSliceValue(d, true /* asOriginal */));\r\n let properties: TextProperties = {\r\n text: getLabelFormattedText({\r\n label: labelText,\r\n maxWidth: maximumTextSize\r\n }),\r\n fontFamily: LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\r\n fontWeight: LabelTextProperties.fontWeight,\r\n };\r\n\r\n let textLength = textMeasurer(properties);\r\n\r\n // Try to honor the position, but if the label doesn't fit where specified, then swap the position.\r\n let labelPositionValue = labelSettings.position;\r\n if ((labelPositionValue === labelPosition.outsideEnd && outsideAvailableSpace < textLength) || d.value === 0)\r\n labelPositionValue = labelPosition.insideCenter;\r\n else if (labelPositionValue === labelPosition.insideCenter && insideAvailableSpace < textLength) {\r\n labelPositionValue = labelPosition.outsideEnd;\r\n }\r\n\r\n switch (labelPositionValue) {\r\n case labelPosition.outsideEnd:\r\n return marginLeft + pixelSpan + (barWidth / 2) + textMinimumPadding + (textLength / 2);\r\n default:\r\n // Inside position, change color to white unless value is 0\r\n d.labelFill = d.value !== 0 ? defaultInsideLabelColor : d.labelFill;\r\n return marginLeft + pixelSpan;\r\n }\r\n },\r\n dy: '-0.15em',\r\n },\r\n filter: (d: FunnelSlice) => {\r\n if (!(d != null && d.value != null && data.hasHighlights === !!d.highlight))\r\n return false;\r\n\r\n let properties: TextProperties = {\r\n text: d.labeltext,\r\n fontFamily: LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\r\n fontWeight: LabelTextProperties.fontWeight,\r\n };\r\n\r\n let labelHeight = TextMeasurementService.estimateSvgTextHeight(properties) * innerTextHeightRate;\r\n return labelHeight < rangeBand;\r\n },\r\n style: {\r\n 'fill': (d: FunnelSlice) => d.labelFill,\r\n 'fill-opacity': (d: FunnelSlice) => ColumnUtil.getFillOpacity(d.selected, false, false, false),\r\n 'font-size': (d: FunnelSlice) => PixelConverter.fromPoint(labelSettings.fontSize),\r\n },\r\n };\r\n }\r\n\r\n export function enumerateDataLabels(\r\n options: VisualDataLabelsSettingsOptions): ObjectEnumerationBuilder {\r\n\r\n debug.assertValue(options, 'options');\r\n debug.assertValue(options.enumeration, 'enumeration');\r\n\r\n if (!options.dataLabelsSettings)\r\n return;\r\n\r\n let instance: VisualObjectInstance = {\r\n objectName: 'labels',\r\n selector: options.selector,\r\n properties: {},\r\n };\r\n\r\n if (options.show && options.selector) {\r\n instance.properties['showSeries'] = options.dataLabelsSettings.show;\r\n }\r\n else if (options.show) {\r\n instance.properties['show'] = options.dataLabelsSettings.show;\r\n }\r\n\r\n instance.properties['color'] = options.dataLabelsSettings.labelColor || defaultLabelColor;\r\n\r\n if (options.displayUnits) {\r\n instance.properties['labelDisplayUnits'] = options.dataLabelsSettings.displayUnits;\r\n }\r\n if (options.precision) {\r\n let precision = options.dataLabelsSettings.precision;\r\n instance.properties['labelPrecision'] = precision === defaultLabelPrecision ? null : precision;\r\n }\r\n if (options.position) {\r\n instance.properties['labelPosition'] = options.dataLabelsSettings.position;\r\n if (options.positionObject) {\r\n debug.assert(!instance.validValues, '!instance.validValues');\r\n\r\n instance.validValues = { 'labelPosition': options.positionObject };\r\n }\r\n }\r\n if (options.labelStyle)\r\n instance.properties['labelStyle'] = options.dataLabelsSettings.labelStyle;\r\n if (options.fontSize)\r\n instance.properties['fontSize'] = options.dataLabelsSettings.fontSize;\r\n if (options.labelDensity) {\r\n var lineChartSettings = <LineChartDataLabelsSettings> options.dataLabelsSettings;\r\n if (lineChartSettings)\r\n instance.properties['labelDensity'] = lineChartSettings.labelDensity;\r\n }\r\n //Keep show all as the last property of the instance.\r\n if (options.showAll)\r\n instance.properties['showAll'] = options.dataLabelsSettings.showLabelPerSeries;\r\n\r\n return options.enumeration.pushInstance(instance);\r\n }\r\n\r\n export function enumerateCategoryLabels(enumeration: ObjectEnumerationBuilder, dataLabelsSettings: VisualDataLabelsSettings, withFill: boolean, isShowCategory: boolean = false, fontSize?: number): void {\r\n let labelSettings = (dataLabelsSettings)\r\n ? dataLabelsSettings\r\n : getDefaultPointLabelSettings();\r\n\r\n let instance: VisualObjectInstance = {\r\n objectName: 'categoryLabels',\r\n selector: null,\r\n properties: {\r\n show: isShowCategory\r\n ? labelSettings.showCategory\r\n : labelSettings.show,\r\n fontSize: dataLabelsSettings ? dataLabelsSettings.fontSize : DefaultFontSizeInPt,\r\n },\r\n };\r\n\r\n if (withFill) {\r\n instance.properties['color'] = labelSettings.categoryLabelColor\r\n ? labelSettings.categoryLabelColor\r\n : labelSettings.labelColor;\r\n }\r\n\r\n if (fontSize) {\r\n instance.properties['fontSize'] = fontSize;\r\n }\r\n\r\n enumeration.pushInstance(instance);\r\n }\r\n\r\n function getDisplayUnitValueFromAxisFormatter(axisFormatter: IValueFormatter, labelSettings: VisualDataLabelsSettings): number {\r\n if (axisFormatter && axisFormatter.displayUnit && labelSettings.displayUnits === 0)\r\n return axisFormatter.displayUnit.value;\r\n return null;\r\n }\r\n\r\n export function createColumnFormatterCacheManager(): IColumnFormatterCacheManager {\r\n return <IColumnFormatterCacheManager> {\r\n\r\n cache: { defaultFormatter: null, },\r\n getOrCreate(formatString: string, labelSetting: VisualDataLabelsSettings, value2?: number) {\r\n if (formatString) {\r\n let cacheKeyObject = {\r\n formatString: formatString,\r\n displayUnits: labelSetting.displayUnits,\r\n precision: getLabelPrecision(labelSetting.precision, formatString),\r\n value2: value2\r\n };\r\n let cacheKey = JSON.stringify(cacheKeyObject);\r\n if (!this.cache[cacheKey])\r\n this.cache[cacheKey] = valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, cacheKeyObject.precision));\r\n return this.cache[cacheKey];\r\n }\r\n if (!this.cache.defaultFormatter) {\r\n this.cache.defaultFormatter = valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, labelSetting.precision));\r\n }\r\n return this.cache.defaultFormatter;\r\n }\r\n };\r\n }\r\n\r\n export function getOptionsForLabelFormatter(labelSetting: VisualDataLabelsSettings, formatString: string, value2?: number, precision?: number): ValueFormatterOptions {\r\n return {\r\n displayUnitSystemType: DisplayUnitSystemType.DataLabels,\r\n format: formatString,\r\n precision: precision,\r\n value: labelSetting.displayUnits,\r\n value2: value2,\r\n allowFormatBeautification: true,\r\n };\r\n }\r\n\r\n export function isTextWidthOverflows(textWidth, maxTextWidth): boolean {\r\n return textWidth > maxTextWidth;\r\n };\r\n\r\n export function isTextHeightOverflows(textHeight, innerChordLength): boolean {\r\n return textHeight > innerChordLength;\r\n };\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ISize = shapes.ISize;\r\n\r\n export module DonutLabelUtils {\r\n export const LineStrokeWidth: number = 1;\r\n export const DiagonalLineIndex: number = 0;\r\n export const HorizontalLineIndex: number = 1;\r\n\r\n export function getLabelLeaderLineForDonutChart(donutArcDescriptor: DonutArcDescriptor, donutProperties: DonutChartProperties,\r\n parentPoint: IPoint, sliceArc: number = 0): number[][] {\r\n let innerLinePointMultiplier = 2.05;\r\n let textPoint: number[];\r\n let midPoint: number[];\r\n let chartPoint: number[];\r\n // Label position has changed\r\n if (sliceArc) {\r\n let arc = sliceArc;\r\n let outerRadius = donutProperties.radius * donutProperties.outerArcRadiusRatio;\r\n let innerRadius = (donutProperties.radius / 2) * donutProperties.innerArcRadiusRatio;\r\n midPoint = [Math.cos(arc) * outerRadius, Math.sin(arc) * outerRadius];\r\n chartPoint = [Math.cos(arc) * innerRadius, Math.sin(arc) * innerRadius];\r\n }\r\n // Original label position\r\n else {\r\n midPoint = donutProperties.outerArc.centroid(donutArcDescriptor);\r\n chartPoint = donutProperties.arc.centroid(donutArcDescriptor);\r\n }\r\n let textPointX = parentPoint.x;\r\n let lineMargin = NewDataLabelUtils.maxLabelOffset / 2;\r\n textPointX += textPointX < 0 ? -lineMargin : lineMargin;\r\n textPoint = [textPointX, parentPoint.y];\r\n chartPoint[0] *= innerLinePointMultiplier;\r\n chartPoint[1] *= innerLinePointMultiplier;\r\n return [chartPoint, midPoint, textPoint];\r\n }\r\n\r\n /** We calculate the rectangles of the leader lines for collision detection \r\n *width: x2 - x1; height: y2 - y1 */\r\n export function getLabelLeaderLinesSizeForDonutChart(leaderLinePoints: number[][]): ISize[] {\r\n if (leaderLinePoints && leaderLinePoints.length > 2) {\r\n let diagonalLineSize: ISize = {\r\n width: Math.abs(leaderLinePoints[1][0] - leaderLinePoints[0][0]),\r\n height: Math.abs(leaderLinePoints[1][1] - leaderLinePoints[0][1]),\r\n };\r\n // For horizontal line we set 1 in the height\r\n let horizontalLineSize: ISize = {\r\n width: Math.abs(leaderLinePoints[2][0] - leaderLinePoints[1][0]),\r\n height: DonutLabelUtils.LineStrokeWidth,\r\n };\r\n return [diagonalLineSize, horizontalLineSize];\r\n }\r\n return null;\r\n }\r\n\r\n export function getXPositionForDonutLabel(textPointX: number): number {\r\n let margin = textPointX < 0 ? -NewDataLabelUtils.maxLabelOffset : NewDataLabelUtils.maxLabelOffset;\r\n return textPointX += margin;\r\n }\r\n\r\n export function getSpaceAvailableForDonutLabels(labelXPos: number, viewport: IViewport): number {\r\n return viewport.width / 2 - Math.abs(labelXPos) - NewDataLabelUtils.maxLabelOffset;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import ISize = shapes.ISize;\r\n\r\n export module NewDataLabelUtils {\r\n export const DefaultLabelFontSizeInPt = 9;\r\n export const MapPolylineOpacity = 0.5;\r\n export const LabelDensityBufferFactor = 3;\r\n export const LabelDensityPadding = 6;\r\n export const LabelDensityMin = 0;\r\n export const LabelDensityMax = 6;\r\n export let startingLabelOffset = 8;\r\n export let maxLabelOffset = 8;\r\n export let maxLabelWidth: number = 50;\r\n export let hundredPercentFormat = '0.00 %;-0.00 %;0.00 %';\r\n export let LabelTextProperties: TextProperties = {\r\n fontFamily: 'wf_standard-font',\r\n fontSize: PixelConverter.fromPoint(DefaultLabelFontSizeInPt),\r\n fontWeight: 'normal',\r\n };\r\n export let defaultLabelColor = \"#777777\";\r\n export let defaultInsideLabelColor = \"#ffffff\"; //white\r\n export const horizontalLabelBackgroundPadding = 4;\r\n export const verticalLabelBackgroundPadding = 2;\r\n \r\n let labelBackgroundRounding = 4;\r\n let defaultLabelPrecision: number = undefined;\r\n let defaultCountLabelPrecision: number = 0;\r\n\r\n export let labelGraphicsContextClass: ClassAndSelector = createClassAndSelector('labelGraphicsContext');\r\n export let labelBackgroundGraphicsContextClass: ClassAndSelector = createClassAndSelector('labelBackgroundGraphicsContext');\r\n let labelsClass: ClassAndSelector = createClassAndSelector('label');\r\n let secondLineLabelClass: ClassAndSelector = createClassAndSelector('label-second-line');\r\n\r\n const linesGraphicsContextClass: ClassAndSelector = createClassAndSelector('leader-lines');\r\n const lineClass: ClassAndSelector = createClassAndSelector('line-label');\r\n\r\n export function drawDefaultLabels(context: D3.Selection, dataLabels: Label[], numeric: boolean = false, twoRows: boolean = false, hasTooltip: boolean = false): D3.UpdateSelection {\r\n let filteredDataLabels = _.filter(dataLabels, (d: Label) => d.isVisible);\r\n let labels = context.selectAll(labelsClass.selector)\r\n .data(filteredDataLabels, labelKeyFunction);\r\n labels.enter()\r\n .append(\"text\")\r\n .classed(labelsClass.class, true);\r\n let labelAttr = {\r\n x: (d: Label) => {\r\n return (d.boundingBox.left + (d.boundingBox.width / 2));\r\n },\r\n y: (d: Label) => {\r\n if (d.hasBackground)\r\n return d.boundingBox.top + d.boundingBox.height - verticalLabelBackgroundPadding;\r\n else\r\n return d.boundingBox.top + d.boundingBox.height;\r\n },\r\n dy: \"-0.15em\",\r\n };\r\n if (numeric) { // For numeric labels, we use a tighter bounding box, so remove the dy because it doesn't need to be centered\r\n labelAttr.dy = undefined;\r\n }\r\n\r\n labels\r\n .text((d: Label) => d.text)\r\n .attr(labelAttr)\r\n .style({\r\n 'fill': (d: Label) => d.fill,\r\n 'font-size': (d: Label) => PixelConverter.fromPoint(d.fontSize || DefaultLabelFontSizeInPt),\r\n 'text-anchor': (d: Label) => d.textAnchor,\r\n });\r\n labels.exit()\r\n .remove();\r\n\r\n let filteredCategoryLabels = _.filter(twoRows ? dataLabels : [], (d: Label) => d.isVisible && !_.isEmpty(d.secondRowText));\r\n let secondLineLabels = context.selectAll(secondLineLabelClass.selector)\r\n .data(filteredCategoryLabels, (d: Label, index: number) => { return d.identity ? d.identity.getKeyWithoutHighlight() : index; });\r\n secondLineLabels.enter()\r\n .append(\"text\")\r\n .classed(secondLineLabelClass.class, true);\r\n\r\n labelAttr = {\r\n x: (d: Label) => {\r\n return (d.boundingBox.left + (d.boundingBox.width / 2));\r\n },\r\n y: (d: Label) => {\r\n let boundingBoxHeight = (d.text !== undefined) ? d.boundingBox.height / 2 : d.boundingBox.height;\r\n if (d.hasBackground)\r\n return d.boundingBox.top + boundingBoxHeight - verticalLabelBackgroundPadding;\r\n else\r\n return d.boundingBox.top + boundingBoxHeight;\r\n },\r\n dy: \"-0.15em\",\r\n };\r\n if (numeric) { // For numeric labels, we use a tighter bounding box, so remove the dy because it doesn't need to be centered\r\n labelAttr.dy = undefined;\r\n }\r\n secondLineLabels\r\n .text((d: Label) => d.secondRowText)\r\n .attr(labelAttr)\r\n .style({\r\n 'fill': (d: Label) => d.fill,\r\n 'font-size': (d: Label) => PixelConverter.fromPoint(d.fontSize || DefaultLabelFontSizeInPt),\r\n 'text-anchor': (d: Label) => d.textAnchor,\r\n });\r\n\r\n secondLineLabels.exit()\r\n .remove();\r\n\r\n if (hasTooltip) {\r\n labels.append('title').text((d: Label) => d.tooltip);\r\n secondLineLabels.append('title').text((d: Label) => d.tooltip);\r\n labels.style(\"pointer-events\", \"all\");\r\n secondLineLabels.style(\"pointer-events\", \"all\");\r\n }\r\n\r\n return labels;\r\n }\r\n\r\n export function animateDefaultLabels(context: D3.Selection, dataLabels: Label[], duration: number, numeric: boolean = false, easeType: string = 'cubic-in-out'): D3.UpdateSelection {\r\n let labels = context.selectAll(labelsClass.selector)\r\n .data(_.filter(dataLabels, (d: Label) => d.isVisible), labelKeyFunction);\r\n\r\n labels.enter()\r\n .append(\"text\")\r\n .classed(labelsClass.class, true)\r\n .style('opacity', 0);\r\n\r\n let labelAttr = {\r\n x: (d: Label) => {\r\n return (d.boundingBox.left + (d.boundingBox.width / 2));\r\n },\r\n y: (d: Label) => {\r\n return d.boundingBox.top + d.boundingBox.height;\r\n },\r\n dy: \"-0.15em\",\r\n };\r\n if (numeric) { // For numeric labels, we use a tighter bounding box, so remove the dy because it doesn't need to be centered\r\n labelAttr.dy = undefined;\r\n }\r\n\r\n labels.text((d: Label) => d.text)\r\n .style({\r\n 'fill': (d: Label) => d.fill,\r\n 'font-size': (d: Label) => PixelConverter.fromPoint(d.fontSize || DefaultLabelFontSizeInPt),\r\n })\r\n .transition()\r\n .ease(easeType)\r\n .duration(duration)\r\n .attr(labelAttr)\r\n .style('opacity', 1);\r\n\r\n labels.exit()\r\n .transition()\r\n .duration(duration)\r\n .style('opacity', 0)\r\n .remove();\r\n\r\n return labels;\r\n }\r\n\r\n /** Draws black rectangles based on the bounding bx of labels, to be used in debugging */\r\n export function drawLabelBackground(context: D3.Selection, dataLabels: Label[], fill?: string, fillOpacity?: number): D3.UpdateSelection {\r\n let labelRects = context.selectAll(\"rect\")\r\n .data(_.filter(dataLabels, (d: Label) => d.isVisible), labelKeyFunction);\r\n\r\n labelRects.enter()\r\n .append(\"rect\");\r\n\r\n labelRects\r\n .attr({\r\n x: (d: Label) => {\r\n return d.boundingBox.left - horizontalLabelBackgroundPadding;\r\n },\r\n y: (d: Label) => {\r\n return d.boundingBox.top - verticalLabelBackgroundPadding;\r\n },\r\n rx: labelBackgroundRounding,\r\n ry: labelBackgroundRounding,\r\n width: (d: Label) => {\r\n return d.boundingBox.width + 2 * horizontalLabelBackgroundPadding;\r\n },\r\n height: (d: Label) => {\r\n if (d.text === undefined && d.secondRowText === undefined) {\r\n return 0;\r\n }\r\n return d.boundingBox.height + 2 * verticalLabelBackgroundPadding;\r\n },\r\n })\r\n .style(\"fill\", fill ? fill : \"#000000\")\r\n .style(\"fill-opacity\", fillOpacity != null ? fillOpacity : 1);\r\n\r\n labelRects.exit()\r\n .remove();\r\n\r\n return labelRects;\r\n }\r\n\r\n export function drawLabelLeaderLines(context: D3.Selection, filteredDataLabels: Label[], key?: (data: any, index?: number) => any, leaderLineColor?: string) {\r\n if (context.select(linesGraphicsContextClass.selector).empty())\r\n context.append('g').classed(linesGraphicsContextClass.class, true);\r\n\r\n let lines = context.select(linesGraphicsContextClass.selector).selectAll('polyline')\r\n .data(filteredDataLabels, key);\r\n\r\n lines.enter()\r\n .append('polyline')\r\n .classed(lineClass.class, true);\r\n\r\n lines\r\n .attr('points', (d: Label) => {\r\n return d.leaderLinePoints;\r\n }).\r\n style({\r\n 'stroke': (d: Label) => leaderLineColor ? leaderLineColor : d.fill,\r\n 'stroke-width': DonutLabelUtils.LineStrokeWidth,\r\n });\r\n\r\n lines\r\n .exit()\r\n .remove();\r\n }\r\n\r\n export function getLabelFormattedText(label: string | number, format?: string, formatter?: IValueFormatter): string {\r\n return formatter ? formatter.format(label) : formattingService.formatValue(label, format);\r\n }\r\n\r\n export function getDisplayUnitValueFromAxisFormatter(axisFormatter: IValueFormatter, labelSettings: VisualDataLabelsSettings): number {\r\n if (axisFormatter && axisFormatter.displayUnit && labelSettings.displayUnits === 0)\r\n return axisFormatter.displayUnit.value;\r\n return null;\r\n }\r\n\r\n function getLabelPrecision(precision: number, format: string): number {\r\n debug.assertAnyValue(format, 'format');\r\n\r\n if (precision !== defaultLabelPrecision)\r\n return precision;\r\n\r\n if (format) {\r\n // Calculate precision from positive format by default\r\n let positiveFormat = format.split(\";\")[0];\r\n let formatMetadata = NumberFormat.getCustomFormatMetadata(positiveFormat, true /*calculatePrecision*/);\r\n if (formatMetadata.hasDots) {\r\n return formatMetadata.precision;\r\n }\r\n }\r\n // For count fields we do not want a precision by default\r\n return defaultCountLabelPrecision;\r\n }\r\n\r\n export function createColumnFormatterCacheManager(): IColumnFormatterCacheManager {\r\n return <IColumnFormatterCacheManager> {\r\n\r\n cache: { defaultFormatter: null, },\r\n getOrCreate(formatString: string, labelSetting: VisualDataLabelsSettings, value2?: number) {\r\n if (formatString) {\r\n let cacheKeyObject = {\r\n formatString: formatString,\r\n displayUnits: labelSetting.displayUnits,\r\n precision: getLabelPrecision(labelSetting.precision, formatString),\r\n value2: value2\r\n };\r\n let cacheKey = JSON.stringify(cacheKeyObject);\r\n if (!this.cache[cacheKey])\r\n this.cache[cacheKey] = valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, cacheKeyObject.precision));\r\n return this.cache[cacheKey];\r\n }\r\n if (!this.cache.defaultFormatter) {\r\n this.cache.defaultFormatter = valueFormatter.create(getOptionsForLabelFormatter(labelSetting, formatString, value2, labelSetting.precision));\r\n }\r\n return this.cache.defaultFormatter;\r\n }\r\n };\r\n }\r\n\r\n function getOptionsForLabelFormatter(labelSetting: VisualDataLabelsSettings, formatString: string, value2?: number, precision?: number): ValueFormatterOptions {\r\n return {\r\n displayUnitSystemType: DisplayUnitSystemType.DataLabels,\r\n format: formatString,\r\n precision: precision,\r\n value: labelSetting.displayUnits,\r\n value2: value2,\r\n allowFormatBeautification: true,\r\n };\r\n }\r\n\r\n export function removeDuplicates(labelDataPoints: LabelDataPoint[]): LabelDataPoint[] {\r\n let uniqueLabelDataPoints: LabelDataPoint[] = [];\r\n let labelDataPointMap = {};\r\n let sameParentIsInArray = (newValue: any, array: any[], parentIsRect: boolean) => {\r\n return array.some((arrayValue) => {\r\n if (parentIsRect) {\r\n return shapes.Rect.equals(newValue.parentShape.rect, arrayValue.rect);\r\n }\r\n else {\r\n return shapes.Point.equals(newValue.parentShape.point, arrayValue.point);\r\n }\r\n });\r\n };\r\n for (let dataPoint of labelDataPoints) {\r\n let parentIsRect = dataPoint.parentType === LabelDataPointParentType.Rectangle;\r\n let resultsFromMap = labelDataPointMap[dataPoint.text];\r\n if (!resultsFromMap) {\r\n uniqueLabelDataPoints.push(dataPoint);\r\n labelDataPointMap[dataPoint.text] = [dataPoint.parentShape];\r\n }\r\n else {\r\n if (!sameParentIsInArray(dataPoint, resultsFromMap, parentIsRect)) {\r\n uniqueLabelDataPoints.push(dataPoint);\r\n resultsFromMap.push(dataPoint.parentShape);\r\n }\r\n }\r\n }\r\n return uniqueLabelDataPoints;\r\n }\r\n \r\n export function getDataLabelLayoutOptions(type: CartesianChartType): DataLabelLayoutOptions {\r\n switch (type) {\r\n case CartesianChartType.Scatter:\r\n return {\r\n maximumOffset: ScatterChart.dataLabelLayoutMaximumOffset,\r\n startingOffset: ScatterChart.dataLabelLayoutStartingOffset,\r\n offsetIterationDelta: ScatterChart.dataLabelLayoutOffsetIterationDelta,\r\n allowLeaderLines: true,\r\n attemptToMoveLabelsIntoViewport: true,\r\n };\r\n default:\r\n return {\r\n maximumOffset: NewDataLabelUtils.maxLabelOffset,\r\n startingOffset: NewDataLabelUtils.startingLabelOffset,\r\n attemptToMoveLabelsIntoViewport: true,\r\n };\r\n }\r\n }\r\n\r\n export function getTextSize(text: string, fontSize: number): ISize {\r\n let labelTextProperties = NewDataLabelUtils.LabelTextProperties;\r\n let properties = {\r\n text: text,\r\n fontFamily: labelTextProperties.fontFamily,\r\n fontSize: jsCommon.PixelConverter.fromPoint(fontSize),\r\n fontWeight: labelTextProperties.fontWeight,\r\n };\r\n return {\r\n width: TextMeasurementService.measureSvgTextWidth(properties),\r\n height: TextMeasurementService.estimateSvgTextHeight(properties),\r\n };\r\n }\r\n\r\n /**\r\n * Obtains the key from the label. Index is required to use as a backup in cases\r\n * where labels have no key or identity.\r\n */\r\n function labelKeyFunction(label: Label, index: number): any {\r\n if (label.key) {\r\n return label.key;\r\n }\r\n if (label.identity) {\r\n return label.identity.getKeyWithoutHighlight();\r\n }\r\n return index;\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n export module KpiUtil {\r\n\r\n export const enum KpiImageSize {\r\n Small,\r\n Big,\r\n }\r\n\r\n export interface KpiImageMetadata {\r\n statusGraphic: string;\r\n caption: string;\r\n class: string;\r\n }\r\n\r\n export interface KPIGraphicClass {\r\n kpiIconClass: string;\r\n statusValues: string[];\r\n }\r\n\r\n const KPIImageClassName = 'powervisuals-glyph';\r\n const BigImageClassName = 'big-kpi';\r\n const RYGStatusIconClassNames = ['kpi-red', 'kpi-yellow', 'kpi-green'];\r\n\r\n const threeLights = {\r\n kpiIconClass: 'circle',\r\n statusValues: RYGStatusIconClassNames,\r\n };\r\n\r\n const roadSigns = {\r\n kpiIconClass: '',\r\n statusValues: ['circle-x kpi-red', 'circle-exclamation kpi-yellow', 'circle-checkmark kpi-green'],\r\n };\r\n\r\n const trafficLight = {\r\n kpiIconClass: 'traffic-light',\r\n statusValues: RYGStatusIconClassNames,\r\n };\r\n\r\n const shapes = {\r\n kpiIconClass: '',\r\n statusValues: ['rhombus kpi-red', 'triangle kpi-yellow', 'circle kpi-green'],\r\n };\r\n\r\n const gauge = {\r\n kpiIconClass: '',\r\n statusValues: ['circle-empty', 'circle-one-quarter', 'circle-half', 'circle-three-quarters', 'circle-full'],\r\n };\r\n\r\n const statusGraphicFormatStrings = {\r\n 'THREE CIRCLES COLORED': threeLights,\r\n 'TRAFFIC LIGHT - SINGLE': threeLights,\r\n\r\n 'THREE FLAGS COLORED': {\r\n kpiIconClass: 'flag',\r\n statusValues: RYGStatusIconClassNames,\r\n },\r\n\r\n 'ROAD SIGNS': roadSigns,\r\n 'THREE SYMBOLS CIRCLED COLORED': roadSigns,\r\n\r\n 'TRAFFIC LIGHT': trafficLight,\r\n 'THREE TRAFFIC LIGHTS RIMMED COLORED': trafficLight,\r\n\r\n 'THREE SYMBOLS UNCIRCLED COLORED': {\r\n kpiIconClass: '',\r\n statusValues: ['x kpi-red', 'exclamation kpi-yellow', 'checkmark kpi-green'],\r\n },\r\n\r\n 'SHAPES': shapes,\r\n 'SMILEY FACE': shapes,\r\n 'THERMOMETER': shapes,\r\n 'CYLINDER': shapes,\r\n 'THREE SIGNS COLORED': shapes,\r\n\r\n 'THREE STARS COLORED': {\r\n kpiIconClass: 'star-stacked',\r\n statusValues: ['star-empty', 'star-half-full', 'star-full'],\r\n },\r\n 'FIVE BARS COLORED': {\r\n kpiIconClass: 'bars-stacked',\r\n statusValues: ['bars-zero', 'bars-one', 'bars-two', 'bars-three', 'bars-four'],\r\n },\r\n 'FIVE BOXES COLORED': {\r\n kpiIconClass: 'boxes-stacked',\r\n statusValues: ['boxes-zero', 'boxes-one', 'boxes-two', 'boxes-three', 'boxes-four'],\r\n },\r\n\r\n 'FIVE QUARTERS COLORED': gauge,\r\n 'GAUGE - ASCENDING': gauge,\r\n 'GAUGE - DESCENDING': {\r\n kpiIconClass: '',\r\n statusValues: ['circle-full', 'circle-three-quarters', 'circle-half', 'circle-one-quarter', 'circle-empty'],\r\n },\r\n\r\n 'STANDARD ARROW': {\r\n kpiIconClass: '',\r\n statusValues: ['arrow-down', 'arrow-right-down', 'arrow-right', 'arrow-right-up', 'arrow-up'],\r\n },\r\n\r\n 'VARIANCE ARROW': {\r\n kpiIconClass: '',\r\n statusValues: ['arrow-down kpi-red', 'arrow-right kpi-yellow', 'arrow-up kpi-green'],\r\n },\r\n\r\n 'STATUS ARROW - ASCENDING': {\r\n kpiIconClass: '',\r\n statusValues: ['arrow-down kpi-red', 'arrow-right-down kpi-yellow', 'arrow-right kpi-yellow', 'arrow-right-up kpi-yellow', 'arrow-up kpi-green'],\r\n },\r\n 'STATUS ARROW - DESCENDING': {\r\n kpiIconClass: '',\r\n statusValues: ['arrow-up kpi-green', 'arrow-right-up kpi-yellow', 'arrow-right kpi-yellow', 'arrow-right-down kpi-yellow', 'arrow-down kpi-red'],\r\n },\r\n };\r\n\r\n function getKpiIcon(kpi: DataViewKpiColumnMetadata, value: string): string {\r\n let numValue = parseFloat(value);\r\n\r\n if (!kpi)\r\n return;\r\n\r\n let statusGraphicFormat = statusGraphicFormatStrings[kpi.graphic.toUpperCase()];\r\n\r\n if (!statusGraphicFormat || isNaN(numValue))\r\n return undefined;\r\n\r\n let statusValues = statusGraphicFormat.statusValues;\r\n\r\n // Normalize range of (-1, -0.5, 0, 0.5, 1) to (-2, -1, 0, 1, 2)\r\n if (kpi.normalizedFiveStateKpiRange && statusValues.length === 5)\r\n numValue = numValue * 2;\r\n\r\n // Convert values from the range of (-n/2, ..., 0, ..., n/2) to (0, 1, ..., n-1)\r\n let num = numValue + Math.floor(statusValues.length / 2);\r\n\r\n return [statusGraphicFormat.kpiIconClass, statusValues[num]].join(' ').trim();\r\n }\r\n\r\n function getKpiIconClassName(kpiIcon: string, kpiImageSize?: KpiImageSize): string {\r\n if (!kpiIcon)\r\n return undefined;\r\n\r\n if (kpiImageSize === KpiImageSize.Big)\r\n return [KPIImageClassName, BigImageClassName, kpiIcon].join(' ');\r\n else\r\n return [KPIImageClassName, kpiIcon].join(' ');\r\n }\r\n\r\n export function getClassForKpi(kpi: DataViewKpiColumnMetadata, value: string, kpiImageSize?: KpiImageSize): string {\r\n debug.assertValue(kpi, 'kpi');\r\n debug.assertValue(value, 'value');\r\n\r\n let kpiIcon: string = getKpiIcon(kpi, value);\r\n return getKpiIconClassName(kpiIcon, kpiImageSize);\r\n }\r\n\r\n export function getKpiImageMetadata(metaDataColumn: DataViewMetadataColumn, value: string, kpiImageSize?: KpiImageSize): KpiImageMetadata {\r\n let kpi: DataViewKpiColumnMetadata = metaDataColumn && metaDataColumn.kpi;\r\n\r\n if (kpi) {\r\n let kpiIcon = getKpiIcon(kpi, value);\r\n if (kpiIcon) {\r\n return {\r\n caption: kpiIcon,\r\n statusGraphic: kpi.graphic,\r\n class: getKpiIconClassName(kpiIcon, kpiImageSize),\r\n };\r\n }\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module ReferenceLineHelper {\r\n export const referenceLineProps = {\r\n show: 'show',\r\n lineColor: 'lineColor',\r\n transparency: 'transparency',\r\n value: 'value',\r\n style: 'style',\r\n position: 'position',\r\n dataLabelShow: 'dataLabelShow',\r\n dataLabelColor: 'dataLabelColor',\r\n dataLabelDecimalPoints: 'dataLabelDecimalPoints',\r\n dataLabelHorizontalPosition: 'dataLabelHorizontalPosition',\r\n dataLabelVerticalPosition: 'dataLabelVerticalPosition',\r\n dataLabelDisplayUnits: 'dataLabelDisplayUnits',\r\n };\r\n\r\n export function enumerateObjectInstances(enumeration: ObjectEnumerationBuilder, referenceLines: DataViewObjectMap, defaultColor: string, objectName: string): void {\r\n debug.assertValue(enumeration, 'enumeration');\r\n\r\n if (_.isEmpty(referenceLines)) {\r\n // NOTE: We do not currently have support for object maps in the property pane. For now we will generate a single reference line \r\n // object that the format pane can handle.In the future we will need property pane support for multiple reference lines. Also, we're\r\n // assuming that the user-defined IDs will be numeric strings, this may change in the future and will likley be controlled by the property pane.\r\n let instance: VisualObjectInstance = {\r\n selector: {\r\n id: '0'\r\n },\r\n properties: {\r\n show: false,\r\n value: '',\r\n lineColor: { solid: { color: defaultColor } },\r\n transparency: 50,\r\n style: lineStyle.dashed,\r\n position: referenceLinePosition.back,\r\n dataLabelShow: false,\r\n },\r\n objectName: objectName\r\n };\r\n\r\n enumeration.pushInstance(instance);\r\n\r\n return;\r\n }\r\n\r\n for (let referenceLine of referenceLines) {\r\n let referenceLineProperties = referenceLine.object;\r\n let show = DataViewObject.getValue(referenceLineProperties, referenceLineProps.show, false);\r\n let value = DataViewObject.getValue(referenceLineProperties, referenceLineProps.value);\r\n let lineColor = DataViewObject.getValue(referenceLineProperties, referenceLineProps.lineColor, { solid: { color: defaultColor } });\r\n let transparency = DataViewObject.getValue(referenceLineProperties, referenceLineProps.transparency, 50);\r\n let style = DataViewObject.getValue(referenceLineProperties, referenceLineProps.style, lineStyle.dashed);\r\n let position = DataViewObject.getValue(referenceLineProperties, referenceLineProps.position, referenceLinePosition.back);\r\n let dataLabelShow = DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelShow, false);\r\n\r\n let instance: VisualObjectInstance = {\r\n selector: {\r\n id: referenceLine.id\r\n },\r\n properties: {\r\n show: show,\r\n value: value,\r\n lineColor: lineColor,\r\n transparency: transparency,\r\n style: style,\r\n position: position,\r\n dataLabelShow: dataLabelShow,\r\n },\r\n objectName: objectName\r\n };\r\n\r\n // Show the data label properties only if the user chose to show the data label\r\n if (dataLabelShow) {\r\n let dataLabelColor = DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelColor, { solid: { color: defaultColor } });\r\n let dataLabelHorizontalPosition = DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelHorizontalPosition, referenceLineDataLabelHorizontalPosition.left);\r\n let dataLabelVerticalPosition = DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelVerticalPosition, referenceLineDataLabelVerticalPosition.above);\r\n let dataLabelDecimalPoints = DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelDecimalPoints, undefined) < 0\r\n ? undefined\r\n : DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelDecimalPoints, undefined);\r\n let dataLabelDisplayUnits = DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelDisplayUnits, 0);\r\n\r\n instance.properties[referenceLineProps.dataLabelColor] = dataLabelColor;\r\n instance.properties[referenceLineProps.dataLabelHorizontalPosition] = dataLabelHorizontalPosition;\r\n instance.properties[referenceLineProps.dataLabelVerticalPosition] = dataLabelVerticalPosition;\r\n instance.properties[referenceLineProps.dataLabelDecimalPoints] = dataLabelDecimalPoints;\r\n instance.properties[referenceLineProps.dataLabelDisplayUnits] = dataLabelDisplayUnits;\r\n }\r\n\r\n enumeration.pushInstance(instance);\r\n }\r\n }\r\n\r\n export function render(options: ReferenceLineOptions): void {\r\n let graphicContext = options.graphicContext;\r\n let axes = options.axes;\r\n let referenceLineProperties = options.referenceLineProperties;\r\n let isHorizontal = options.isHorizontal;\r\n let viewport = options.viewport;\r\n let classAndSelector = options.classAndSelector;\r\n\r\n let xScale = axes.x.scale;\r\n let yScale = axes.y1.scale;\r\n\r\n let refValue = DataViewObject.getValue(referenceLineProperties, referenceLineProps.value, 0);\r\n let lineColor = DataViewObject.getValue(referenceLineProperties, referenceLineProps.lineColor, { solid: { color: options.defaultColor } });\r\n let transparency = DataViewObject.getValue<number>(referenceLineProperties, referenceLineProps.transparency);\r\n let style = DataViewObject.getValue(referenceLineProperties, referenceLineProps.style, lineStyle.dashed);\r\n let position = DataViewObject.getValue(referenceLineProperties, referenceLineProps.position, referenceLinePosition.back);\r\n\r\n let refLine = graphicContext.select(classAndSelector.selector);\r\n \r\n let index = $(refLine[0]).index();\r\n let currentPosition = index > 1 ? referenceLinePosition.front : referenceLinePosition.back;\r\n let isRefLineExists = index !== -1; \r\n let isPositionChanged = currentPosition !== position;\r\n\r\n if (isRefLineExists && isPositionChanged) \r\n refLine.remove();\r\n \r\n if (!isRefLineExists || isPositionChanged) \r\n refLine = (position === referenceLinePosition.back) ? graphicContext.insert('line', \":first-child\") : graphicContext.append('line'); \r\n\r\n let refLineX1 = isHorizontal ? 0 : xScale(refValue);\r\n let refLineY1 = isHorizontal ? yScale(refValue) : 0;\r\n let refLineX2 = isHorizontal ? viewport.width : xScale(refValue);\r\n let refLineY2 = isHorizontal ? yScale(refValue) : viewport.height;\r\n\r\n refLine.attr({\r\n 'class': classAndSelector.class,\r\n x1: refLineX1,\r\n y1: refLineY1,\r\n x2: refLineX2,\r\n y2: refLineY2,\r\n })\r\n .style({\r\n 'stroke': lineColor.solid.color,\r\n });\r\n\r\n if (transparency != null) \r\n refLine.style('stroke-opacity', ((100 - transparency) / 100)); \r\n\r\n if (style === lineStyle.dashed) {\r\n refLine.style('stroke-dasharray', (\"5, 5\"));\r\n }\r\n else if (style === lineStyle.dotted) {\r\n refLine.style({\r\n 'stroke-dasharray': (\"1, 5\"),\r\n 'stroke-linecap': \"round\"\r\n });\r\n }\r\n else if (style === lineStyle.solid) {\r\n refLine.style({\r\n 'stroke-dasharray': null,\r\n 'stroke-linecap': null\r\n });\r\n }\r\n }\r\n\r\n export function createLabelDataPoint(options: ReferenceLineDataLabelOptions): LabelDataPoint {\r\n let offsetRefLine = 5;\r\n\r\n let axes = options.axes;\r\n let referenceLineProperties = options.referenceLineProperties;\r\n let isHorizontal = options.isHorizontal;\r\n let viewport = options.viewport;\r\n\r\n let xScale = axes.x.scale;\r\n let yScale = axes.y1.scale;\r\n\r\n // Get the data label properties \r\n let refValue = DataViewObject.getValue(referenceLineProperties, referenceLineProps.value, 0);\r\n let color = DataViewObject.getValue<Fill>(referenceLineProperties, referenceLineProps.dataLabelColor, { solid: { color: options.defaultColor } });\r\n let decimalPoints: number = <number>(referenceLineProperties[referenceLineProps.dataLabelDecimalPoints] < 0 ? undefined : referenceLineProperties[referenceLineProps.dataLabelDecimalPoints]);\r\n let horizontalPosition = referenceLineProperties[referenceLineProps.dataLabelHorizontalPosition] || referenceLineDataLabelHorizontalPosition.left;\r\n let verticalPosition = referenceLineProperties[referenceLineProps.dataLabelVerticalPosition] || referenceLineDataLabelVerticalPosition.above;\r\n let displayUnits = DataViewObject.getValue(referenceLineProperties, referenceLineProps.dataLabelDisplayUnits, 0);\r\n\r\n // Format the reference line data label text according to the matching axis formatter\r\n // When options is null default formatter is used either boolean, numeric, or text\r\n let axisFormatter = isHorizontal ? axes.y1.formatter : axes.x.formatter;\r\n let formatterForReferenceLineDataLabel = axisFormatter;\r\n\r\n if (axisFormatter.options != null) {\r\n let formatterOptions = Prototype.inherit(axisFormatter.options);\r\n formatterOptions.precision = decimalPoints;\r\n formatterOptions.value = displayUnits;\r\n formatterOptions.detectAxisPrecision = false;\r\n formatterForReferenceLineDataLabel = valueFormatter.create(formatterOptions);\r\n }\r\n\r\n let text: string = NewDataLabelUtils.getLabelFormattedText(formatterForReferenceLineDataLabel.format(<number>refValue));\r\n\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n\r\n // Get the height and with of the text element that will be created in order to place it correctly\r\n let rectWidth: number = TextMeasurementService.measureSvgTextWidth(properties);\r\n let rectHeight: number = TextMeasurementService.estimateSvgTextHeight(properties);\r\n\r\n let dataLabelX: number;\r\n let dataLabelY: number;\r\n\r\n let x1 = isHorizontal ? 0 : xScale(refValue);\r\n let y1 = isHorizontal ? yScale(refValue) : 0;\r\n let x2 = isHorizontal ? viewport.width : xScale(refValue);\r\n let y2 = isHorizontal ? yScale(refValue) : viewport.height;\r\n let validPositions = [NewPointLabelPosition.Above];\r\n\r\n if (isHorizontal) {\r\n // Horizontal line. y1 = y2\r\n dataLabelX = (horizontalPosition === referenceLineDataLabelHorizontalPosition.left) ? x1 + offsetRefLine : x2 - (rectWidth / 2) - offsetRefLine;\r\n dataLabelY = y1;\r\n validPositions = (verticalPosition === referenceLineDataLabelVerticalPosition.above) ? [NewPointLabelPosition.Above] : [NewPointLabelPosition.Below];\r\n }\r\n else {\r\n // Vertical line. x1 = x2 \r\n dataLabelX = x1;\r\n dataLabelY = (verticalPosition === referenceLineDataLabelVerticalPosition.above) ? y1 + (rectHeight / 2) + offsetRefLine : y2 - (rectHeight / 2) - offsetRefLine;\r\n validPositions = (horizontalPosition === referenceLineDataLabelHorizontalPosition.left) ? [NewPointLabelPosition.Left] : [NewPointLabelPosition.Right];\r\n }\r\n\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\r\n let parentShape: LabelParentPoint;\r\n\r\n parentShape = {\r\n point: {\r\n x: dataLabelX,\r\n y: dataLabelY,\r\n },\r\n radius: 0,\r\n validPositions: validPositions,\r\n };\r\n \r\n return {\r\n isPreferred: true,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: color.solid.color,\r\n insideFill: null,\r\n parentShape: parentShape,\r\n parentType: LabelDataPointParentType.Point,\r\n fontSize: 9,\r\n identity: null,\r\n secondRowText: null,\r\n key: options.key,\r\n };\r\n }\r\n\r\n export function extractReferenceLineValue(referenceLineProperties: DataViewObject): number {\r\n let referenceLineValue: number = null;\r\n\r\n if (referenceLineProperties && DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.show, false))\r\n referenceLineValue = DataViewObject.getValue(referenceLineProperties, ReferenceLineHelper.referenceLineProps.value, null);\r\n\r\n return referenceLineValue;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module InteractivityUtils {\r\n export function getPositionOfLastInputEvent(): IPoint {\r\n return {\r\n x: d3.event.clientX,\r\n y: d3.event.clientY\r\n };\r\n }\r\n\r\n export function registerStandardInteractivityHandlers(selection: D3.Selection, selectionHandler: ISelectionHandler): void {\r\n registerStandardSelectionHandler(selection, selectionHandler);\r\n registerStandardContextMenuHandler(selection, selectionHandler);\r\n }\r\n\r\n export function registerStandardSelectionHandler(selection: D3.Selection, selectionHandler: ISelectionHandler): void {\r\n selection.on('click', (d: SelectableDataPoint) => handleSelection(d, selectionHandler));\r\n }\r\n\r\n export function registerStandardContextMenuHandler(selection: D3.Selection, selectionHandler: ISelectionHandler): void {\r\n selection.on('contextmenu', (d: SelectableDataPoint) => handleContextMenu(d, selectionHandler));\r\n }\r\n\r\n export function registerGroupInteractivityHandlers(group: D3.Selection, selectionHandler: ISelectionHandler): void {\r\n registerGroupSelectionHandler(group, selectionHandler);\r\n registerGroupContextMenuHandler(group, selectionHandler);\r\n }\r\n\r\n export function registerGroupSelectionHandler(group: D3.Selection, selectionHandler: ISelectionHandler): void {\r\n group.on('click', () => {\r\n let target = d3.event.target;\r\n let d = <SelectableDataPoint>d3.select(target).datum();\r\n handleSelection(d, selectionHandler);\r\n });\r\n }\r\n\r\n export function registerGroupContextMenuHandler(group: D3.Selection, selectionHandler: ISelectionHandler): void {\r\n group.on('contextmenu', () => {\r\n let target = d3.event.target;\r\n let d = <SelectableDataPoint>d3.select(target).datum();\r\n handleContextMenu(d, selectionHandler);\r\n });\r\n }\r\n\r\n function handleContextMenu(d: SelectableDataPoint, selectionHandler: ISelectionHandler): void {\r\n if (d3.event.ctrlKey)\r\n return;\r\n\r\n d3.event.preventDefault();\r\n let position = InteractivityUtils.getPositionOfLastInputEvent();\r\n selectionHandler.handleContextMenu(d, position);\r\n }\r\n\r\n function handleSelection(d: SelectableDataPoint, selectionHandler: ISelectionHandler): void {\r\n selectionHandler.handleSelection(d, d3.event.ctrlKey);\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import DataView = powerbi.DataView;\r\n\r\n export function getInvalidValueWarnings(\r\n dataViews: DataView[],\r\n supportsNaN: boolean,\r\n supportsNegativeInfinity: boolean,\r\n supportsPositiveInfinity: boolean): IVisualWarning[] {\r\n\r\n let checker: InvalidDataValuesChecker = new InvalidDataValuesChecker(\r\n supportsNaN /*supportsNaN*/,\r\n supportsNegativeInfinity /*supportsNegativeInfinity*/,\r\n supportsPositiveInfinity /*supportsPositiveInfinity*/);\r\n\r\n // Show a warning if necessary.\r\n return checker.getWarningMessages(dataViews);\r\n }\r\n\r\n class InvalidDataValuesChecker {\r\n private supportsNaN: boolean;\r\n private supportsNegativeInfinity: boolean;\r\n private supportsPositiveInfinity: boolean;\r\n\r\n private hasNaN: boolean;\r\n private hasNegativeInfinity: boolean;\r\n private hasPositiveInfinity: boolean;\r\n private hasOutOfRange: boolean;\r\n\r\n constructor(supportsNaN: boolean, supportsNegativeInfinity: boolean, supportsPositiveInfinity: boolean) {\r\n this.supportsNaN = supportsNaN;\r\n this.supportsNegativeInfinity = supportsNegativeInfinity;\r\n this.supportsPositiveInfinity = supportsPositiveInfinity;\r\n }\r\n\r\n public getWarningMessages(dataViews: DataView[]): IVisualWarning[] {\r\n this.loadWarningStatus(dataViews);\r\n\r\n let warnings: IVisualWarning[] = [];\r\n if (this.hasNaN && !this.supportsNaN) {\r\n warnings.push(new NaNNotSupportedWarning());\r\n }\r\n\r\n if ((this.hasNegativeInfinity && !this.supportsNegativeInfinity)\r\n || (this.hasPositiveInfinity && !this.supportsPositiveInfinity)) {\r\n warnings.push(new InfinityValuesNotSupportedWarning());\r\n }\r\n\r\n if (this.hasOutOfRange) {\r\n warnings.push(new ValuesOutOfRangeWarning());\r\n }\r\n\r\n return warnings;\r\n }\r\n\r\n private loadWarningStatus(dataViews: DataView[]) {\r\n this.hasNaN = false;\r\n this.hasNegativeInfinity = false;\r\n this.hasOutOfRange = false;\r\n this.hasPositiveInfinity = false;\r\n\r\n for (let k: number = 0; k < dataViews.length; k++) {\r\n let dataView = dataViews[k];\r\n let values = dataView && dataView.categorical && dataView.categorical.values\r\n ? dataView.categorical.values\r\n : null;\r\n\r\n if (!values)\r\n return;\r\n\r\n let valueLength = values.length;\r\n for (let i: number = 0; i < valueLength; i++) {\r\n let value = values[i];\r\n\r\n if (value.values) {\r\n let valueValueLength = value.values.length;\r\n for (let j: number = 0; j < valueValueLength; j++) {\r\n let v = value.values[j];\r\n\r\n if (isNaN(v))\r\n this.hasNaN = true;\r\n else if (v === Number.POSITIVE_INFINITY)\r\n this.hasPositiveInfinity = true;\r\n else if (v === Number.NEGATIVE_INFINITY)\r\n this.hasNegativeInfinity = true;\r\n else if (v < -1e300 || v > 1e300)\r\n this.hasOutOfRange = true;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n export interface IListView {\r\n data(data: any[], dataIdFunction: (d) => {}, dataAppended: boolean): IListView;\r\n rowHeight(rowHeight: number): IListView;\r\n viewport(viewport: IViewport): IListView;\r\n render(): void;\r\n empty(): void;\r\n }\r\n\r\n export module ListViewFactory {\r\n export function createListView(options): IListView {\r\n return new ListView(options);\r\n }\r\n }\r\n\r\n export interface ListViewOptions {\r\n enter: (selection: D3.Selection) => void;\r\n exit: (selection: D3.Selection) => void;\r\n update: (selection: D3.Selection) => void;\r\n loadMoreData: () => void;\r\n baseContainer: D3.Selection;\r\n rowHeight: number;\r\n viewport: IViewport;\r\n scrollEnabled: boolean;\r\n isReadMode: () => boolean;\r\n }\r\n\r\n /**\r\n * A UI Virtualized List, that uses the D3 Enter, Update & Exit pattern to update rows.\r\n * It can create lists containing either HTML or SVG elements.\r\n */\r\n class ListView implements IListView {\r\n private getDatumIndex: (d: any) => {};\r\n private _data: any[];\r\n private _totalRows: number;\r\n\r\n private options: ListViewOptions;\r\n private visibleGroupContainer: D3.Selection;\r\n private scrollContainer: D3.Selection;\r\n private scrollbarInner: D3.Selection;\r\n private cancelMeasurePass: () => void;\r\n private renderTimeoutId: number;\r\n \r\n /**\r\n * The value indicates the percentage of data already shown\r\n * in the list view that triggers a loadMoreData call.\r\n */\r\n private static loadMoreDataThreshold = 0.8;\r\n private static defaultRowHeight = 1;\r\n\r\n public constructor(options: ListViewOptions) {\r\n // make a copy of options so that it is not modified later by caller\r\n this.options = $.extend(true, {}, options);\r\n\r\n this.scrollbarInner = options.baseContainer\r\n .append('div')\r\n .classed('scrollbar-inner', true)\r\n .on('scroll', () => this.renderImpl(this.options.rowHeight));\r\n\r\n this.scrollContainer = this.scrollbarInner\r\n .append('div')\r\n .classed('scrollRegion', true)\r\n .on('touchstart', () => this.stopTouchPropagation())\r\n .on('touchmove', () => this.stopTouchPropagation());\r\n\r\n this.visibleGroupContainer = this.scrollContainer\r\n .append('div')\r\n .classed('visibleGroup', true);\r\n\r\n $(options.baseContainer.node()).find('.scroll-element').attr('drag-resize-disabled', 'true');\r\n\r\n ListView.SetDefaultOptions(options);\r\n }\r\n\r\n private static SetDefaultOptions(options: ListViewOptions) {\r\n options.rowHeight = options.rowHeight || ListView.defaultRowHeight;\r\n }\r\n\r\n public rowHeight(rowHeight: number): ListView {\r\n this.options.rowHeight = Math.ceil(rowHeight);\r\n return this;\r\n }\r\n\r\n public data(data: any[], getDatumIndex: (d) => {}, dataReset: boolean = false): IListView {\r\n this._data = data;\r\n this.getDatumIndex = getDatumIndex;\r\n this.setTotalRows();\r\n if (dataReset)\r\n $(this.scrollbarInner.node()).scrollTop(0);\r\n\r\n this.render();\r\n return this;\r\n }\r\n\r\n public viewport(viewport: IViewport): IListView {\r\n this.options.viewport = viewport;\r\n this.render();\r\n return this;\r\n }\r\n\r\n public empty(): void {\r\n this._data = [];\r\n this.render();\r\n }\r\n\r\n public render(): void {\r\n if (this.renderTimeoutId)\r\n window.clearTimeout(this.renderTimeoutId);\r\n\r\n this.renderTimeoutId = window.setTimeout(() => {\r\n this.getRowHeight().then((rowHeight: number) => {\r\n this.renderImpl(rowHeight);\r\n });\r\n this.renderTimeoutId = undefined;\r\n },0);\r\n }\r\n\r\n private renderImpl(rowHeight: number): void {\r\n let totalHeight = this.options.scrollEnabled ? Math.max(0, (this._totalRows * rowHeight)) : this.options.viewport.height;\r\n this.scrollContainer\r\n .style('height', totalHeight + \"px\")\r\n .attr('height', totalHeight);\r\n\r\n this.scrollToFrame(true /*loadMoreData*/);\r\n }\r\n\r\n /*\r\n * This method is called in order to prevent a bug found in the Interact.js.\r\n * The bug is caused when finishing a scroll outside the scroll area.\r\n * In that case the Interact doesn't process a touchcancel event and thinks a touch point still exists.\r\n * since the Interact listens on the visualContainer, by stoping the propagation we prevent the bug from taking place.\r\n */\r\n private stopTouchPropagation(): void {\r\n //Stop the propagation only in read mode so the drag won't be affected.\r\n if (this.options.isReadMode()) {\r\n if (d3.event.type === \"touchstart\") {\r\n let event: TouchEvent = <any>d3.event;\r\n //If there is another touch point outside this visual than the event should be propagated.\r\n //This way the pinch to zoom will not be affected.\r\n if (event.touches && event.touches.length === 1) {\r\n d3.event.stopPropagation();\r\n }\r\n }\r\n if (d3.event.type === \"touchmove\") {\r\n d3.event.stopPropagation();\r\n }\r\n }\r\n }\r\n\r\n private scrollToFrame(loadMoreData: boolean): void {\r\n let options = this.options;\r\n let visibleGroupContainer = this.visibleGroupContainer;\r\n let totalRows = this._totalRows;\r\n let rowHeight = options.rowHeight || ListView.defaultRowHeight;\r\n let visibleRows = this.getVisibleRows() || 1;\r\n let scrollTop: number = this.scrollbarInner.node().scrollTop;\r\n let scrollPosition = (scrollTop === 0) ? 0 : Math.floor(scrollTop / rowHeight);\r\n let transformAttr = SVGUtil.translateWithPixels(0, scrollPosition * rowHeight);\r\n\r\n visibleGroupContainer.style({\r\n //order matters for proper overriding\r\n 'transform': d => transformAttr,\r\n '-webkit-transform': transformAttr\r\n });\r\n\r\n let position0 = Math.max(0, Math.min(scrollPosition, totalRows - visibleRows + 1)),\r\n position1 = position0 + visibleRows;\r\n \r\n if (this.options.scrollEnabled) {\r\n\r\n // Subtract the amount of height of the top row that's hidden when it's partially visible.\r\n let topRowHiddenHeight = scrollTop - (scrollPosition * rowHeight);\r\n let halfRowHeight = rowHeight * 0.5;\r\n\r\n // If more than half the top row is hidden, we'll need to render an extra item at the bottom\r\n if (topRowHiddenHeight > halfRowHeight) {\r\n position1++; // Add 1 to handle when rows are partially visible (when scrolling)\r\n }\r\n }\r\n \r\n let rowSelection = visibleGroupContainer.selectAll(\".row\")\r\n .data(this._data.slice(position0, Math.min(position1, totalRows)), this.getDatumIndex);\r\n\r\n rowSelection\r\n .enter()\r\n .append('div')\r\n .classed('row', true)\r\n .call(d => options.enter(d));\r\n rowSelection.order();\r\n\r\n let rowUpdateSelection = visibleGroupContainer.selectAll('.row:not(.transitioning)');\r\n\r\n rowUpdateSelection.call(d => options.update(d));\r\n\r\n rowSelection\r\n .exit()\r\n .call(d => options.exit(d))\r\n .remove();\r\n\r\n if (loadMoreData && visibleRows !== totalRows && position1 >= totalRows * ListView.loadMoreDataThreshold)\r\n options.loadMoreData();\r\n }\r\n\r\n private setTotalRows(): void {\r\n let data = this._data;\r\n this._totalRows = data ? data.length : 0;\r\n }\r\n\r\n private getVisibleRows(): number {\r\n const minimumVisibleRows = 1;\r\n let rowHeight = this.options.rowHeight;\r\n let viewportHeight = this.options.viewport.height;\r\n\r\n if (!rowHeight || rowHeight < 1)\r\n return minimumVisibleRows;\r\n \r\n if (this.options.scrollEnabled)\r\n return Math.min(Math.ceil(viewportHeight / rowHeight), this._totalRows) || minimumVisibleRows;\r\n\r\n return Math.min(Math.floor(viewportHeight / rowHeight), this._totalRows) || minimumVisibleRows;\r\n }\r\n\r\n private getRowHeight(): JQueryPromise<number> {\r\n let deferred = $.Deferred<number>();\r\n let listView = this;\r\n let options = listView.options;\r\n if (this.cancelMeasurePass)\r\n this.cancelMeasurePass();\r\n\r\n // if there is no data, resolve and return\r\n if (!(this._data && this._data.length && options)) {\r\n listView.rowHeight(ListView.defaultRowHeight);\r\n return deferred.resolve(options.rowHeight).promise();\r\n }\r\n\r\n //render the first item to calculate the row height\r\n this.scrollToFrame(false /*loadMoreData*/);\r\n let requestAnimationFrameId = window.requestAnimationFrame(() => {\r\n //measure row height\r\n let rows = listView.visibleGroupContainer.select(\".row\");\r\n if (!rows.empty()) {\r\n let firstRow = rows.node();\r\n // If the container (child) has margins amd the row (parent) doesn't, the child's margins will collapse into the parent.\r\n // outerHeight doesn't report the correct height for the parent in this case, but it does measure the child properly.\r\n // Fix for #7497261 Measures both and take the max to work around this issue.\r\n let rowHeight: number = Math.max($(firstRow).outerHeight(true), $(firstRow).children().first().outerHeight(true));\r\n listView.rowHeight(rowHeight);\r\n deferred.resolve(rowHeight);\r\n }\r\n\r\n listView.cancelMeasurePass = undefined;\r\n window.cancelAnimationFrame(requestAnimationFrameId);\r\n });\r\n\r\n this.cancelMeasurePass = () => {\r\n window.cancelAnimationFrame(requestAnimationFrameId);\r\n deferred.reject();\r\n };\r\n\r\n return deferred.promise();\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n const defaultLevelOfDetail = 11;\r\n\r\n export module MapUtil {\r\n export interface IPixelArrayResult {\r\n array: Float64Array;\r\n arrayString: string;\r\n }\r\n\r\n export const Settings = {\r\n /** Maximum Bing requests at once. The Bing have limit how many request at once you can do per socket. */\r\n MaxBingRequest: 6,\r\n\r\n /** Maximum cache size of cached geocode data. */\r\n MaxCacheSize: 3000,\r\n\r\n /** Maximum cache overflow of cached geocode data to kick the cache reducing. */\r\n MaxCacheSizeOverflow: 100,\r\n\r\n // Bing Keys and URL\r\n BingKey: \"insert your key\",\r\n BingUrl: \"https://dev.virtualearth.net/REST/v1/Locations\",\r\n BingUrlGeodata: \"https://platform.bing.com/geo/spatial/v1/public/Geodata?\",\r\n\r\n /** Switch the data result for geodata polygons to by double array instead locations array */\r\n UseDoubleArrayGeodataResult: true,\r\n UseDoubleArrayDequeueTimeout: 0,\r\n };\r\n\r\n // Bing map min/max boundaries\r\n export const MinAllowedLatitude = -85.05112878;\r\n export const MaxAllowedLatitude = 85.05112878;\r\n export const MinAllowedLongitude = -180;\r\n export const MaxAllowedLongitude = 180;\r\n export const TileSize = 256;\r\n export const MaxLevelOfDetail = 23;\r\n export const MinLevelOfDetail = 1;\r\n export const MaxAutoZoomLevel = 5;\r\n export const DefaultLevelOfDetail = 11;\r\n export const WorkerErrorName = \"___error___\";\r\n\r\n export const CategoryTypes = {\r\n Address: \"Address\",\r\n City: \"City\",\r\n Continent: \"Continent\",\r\n CountryRegion: \"Country\", // The text has to stay \"Country\" because it is used as a key in the geocoding caching dictionary\r\n County: \"County\",\r\n Longitude: \"Longitude\",\r\n Latitude: \"Latitude\",\r\n Place: \"Place\",\r\n PostalCode: \"PostalCode\",\r\n StateOrProvince: \"StateOrProvince\"\r\n };\r\n\r\n const safeCharacters: string = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-\";\r\n\r\n export function clip(n: number, minValue: number, maxValue: number): number {\r\n return Math.min(Math.max(n, minValue), maxValue);\r\n }\r\n\r\n export function getMapSize(levelOfDetail: number): number {\r\n if (levelOfDetail === 23)\r\n return 2147483648; //256 << 23 overflow the integer and return a negative value\r\n\r\n if (Math.floor(levelOfDetail) === levelOfDetail)\r\n return 256 << levelOfDetail;\r\n\r\n return 256 * Math.pow(2, levelOfDetail);\r\n }\r\n\r\n /**\r\n * pointArrayChunkLength Motivation: \r\n * When the number is too small (e.g. less than 1000) the tile is rendering but VERY SLOW, \r\n * when it's too high there is a risk to get \"stack overflow\" error on mobile (while joining).\r\n * this is the lowest number I managed to get without any noticeable slowness.\r\n */\r\n const pointArrayChunkLength = 15000;\r\n\r\n /**\r\n * @param latLongArray - is a Float64Array as [lt0, lon0, lat1, long1, lat2, long2,....]\r\n * @param buildString - optional, if true returns also a string as \"x0 y0 x1 y1 x2 y2 ....\"\r\n * @returns IPixelArrayResult with Float64Array as [x0, y0, x1, y1, x2, y2,....]\r\n */\r\n export function latLongToPixelXYArray(latLongArray: Float64Array, levelOfDetail: number, buildString: boolean = false): IPixelArrayResult {\r\n let helperArray: number[] = [];\r\n let result: IPixelArrayResult = {\r\n array: new Float64Array(latLongArray.length),\r\n arrayString: \"\"\r\n };\r\n\r\n for (let i = 0; i < latLongArray.length; i += 2) {\r\n let latitude = clip(latLongArray[i], MinAllowedLatitude, MaxAllowedLatitude);\r\n let longitude = clip(latLongArray[i + 1], MinAllowedLongitude, MaxAllowedLongitude);\r\n\r\n let x: number = (longitude + 180) / 360;\r\n let sinLatitude: number = Math.sin(latitude * Math.PI / 180);\r\n let y: number = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);\r\n\r\n let mapSize: number = getMapSize(levelOfDetail);\r\n result.array[i] = clip(x * mapSize + 0.5, 0.0, mapSize - 1);\r\n result.array[i + 1] = clip(y * mapSize + 0.5, 0.0, mapSize - 1);\r\n\r\n if (buildString) {\r\n helperArray.push(result.array[i], result.array[i + 1]);\r\n if (helperArray.length >= pointArrayChunkLength) {\r\n result.arrayString += helperArray.join(\" \") + \" \";\r\n helperArray = [];\r\n }\r\n }\r\n }\r\n\r\n if (buildString) {\r\n result.arrayString += helperArray.join(\" \") + \" \";\r\n }\r\n return result;\r\n }\r\n\r\n export function getLocationBoundaries(latLongArray: Float64Array): Microsoft.Maps.LocationRect {\r\n const northWest = {\r\n latitude: -90, longitude: 180\r\n };\r\n const southEast = {\r\n latitude: 90, longitude: -180\r\n };\r\n\r\n for (let i = 0; i < latLongArray.length; i += 2) {\r\n northWest.latitude = Math.max(latLongArray[i], northWest.latitude);\r\n northWest.longitude = Math.min(latLongArray[i + 1], northWest.longitude);\r\n southEast.latitude = Math.min(latLongArray[i], southEast.latitude);\r\n southEast.longitude = Math.max(latLongArray[i + 1], southEast.longitude);\r\n }\r\n\r\n northWest.longitude = clip(northWest.longitude, -180, 180);\r\n southEast.longitude = clip(southEast.longitude, -180, 180);\r\n\r\n return Microsoft.Maps.LocationRect.fromCorners(\r\n new Microsoft.Maps.Location(northWest.latitude, northWest.longitude),\r\n new Microsoft.Maps.Location(southEast.latitude, southEast.longitude));\r\n }\r\n\r\n /**\r\n * Note: this code is taken from Bing.\r\n * see Point Compression Algorithm http://msdn.microsoft.com/en-us/library/jj158958.aspx\r\n * see Decompression Algorithm in http://msdn.microsoft.com/en-us/library/dn306801.aspx\r\n */\r\n export function parseEncodedSpatialValueArray(value): Float64Array {\r\n let list: number[] = [];\r\n let index = 0;\r\n let xsum = 0;\r\n let ysum = 0;\r\n let max = 4294967296;\r\n\r\n while (index < value.length) {\r\n let n = 0;\r\n let k = 0;\r\n\r\n while (1) {\r\n\r\n if (index >= value.length) {\r\n return null;\r\n }\r\n\r\n let b = safeCharacters.indexOf(value.charAt(index++));\r\n if (b === -1) {\r\n return null;\r\n }\r\n\r\n let tmp = ((b & 31) * (Math.pow(2, k)));\r\n\r\n let ht = tmp / max;\r\n let lt = tmp % max;\r\n\r\n let hn = n / max;\r\n let ln = n % max;\r\n\r\n let nl = (lt | ln) >>> 0;\r\n n = (ht | hn) * max + nl;\r\n k += 5;\r\n if (b < 32) break;\r\n }\r\n\r\n let diagonal = Math.floor((Math.sqrt(8 * n + 5) - 1) / 2);\r\n n -= diagonal * (diagonal + 1) / 2;\r\n let ny = Math.floor(n);\r\n let nx = diagonal - ny;\r\n nx = (nx >> 1) ^ -(nx & 1);\r\n ny = (ny >> 1) ^ -(ny & 1);\r\n xsum += nx;\r\n ysum += ny;\r\n let lat = ysum * 0.00001;\r\n let lon = xsum * 0.00001;\r\n\r\n list.push(lat);\r\n list.push(lon);\r\n }\r\n return new Float64Array(list);\r\n }\r\n\r\n export function calcGeoData(data: IGeocodeBoundaryCoordinate) {\r\n let locations = data.locations;\r\n\r\n for (let i = 0; i < locations.length; i++) {\r\n let location = locations[i];\r\n if (!location.geographic) {\r\n location.geographic = MapUtil.parseEncodedSpatialValueArray(location.nativeBing);\r\n }\r\n let polygon = location.geographic;\r\n if (polygon) {\r\n if (!location.absolute) {\r\n let result = MapUtil.latLongToPixelXYArray(polygon, MapUtil.DefaultLevelOfDetail, true);\r\n location.absolute = result.array;\r\n location.absoluteString = result.arrayString;\r\n\r\n let geographicBounds = MapUtil.getLocationBoundaries(polygon);\r\n location.absoluteBounds = MapUtil.locationRectToRectXY(geographicBounds, MapUtil.DefaultLevelOfDetail);\r\n }\r\n }\r\n }\r\n }\r\n\r\n export function locationToPixelXY(location: Microsoft.Maps.Location, levelOfDetail: number): powerbi.visuals.Point {\r\n return latLongToPixelXY(location.latitude, location.longitude, levelOfDetail);\r\n }\r\n\r\n export function locationRectToRectXY(locationRect: Microsoft.Maps.LocationRect, levelOfDetail: number): powerbi.visuals.Rect {\r\n let topleft = locationToPixelXY(locationRect.getNorthwest(), levelOfDetail);\r\n let bottomRight = locationToPixelXY(locationRect.getSoutheast(), levelOfDetail);\r\n return new powerbi.visuals.Rect(topleft.x, topleft.y, bottomRight.x - topleft.x, bottomRight.y - topleft.y);\r\n }\r\n\r\n export function latLongToPixelXY(latitude: number, longitude: number, levelOfDetail: number): powerbi.visuals.Point {\r\n let array: Float64Array = latLongToPixelXYArray(new Float64Array([latitude, longitude]), levelOfDetail).array;\r\n return new powerbi.visuals.Point(array[0], array[1]);\r\n }\r\n\r\n export function pixelXYToLocation(pixelX: number, pixelY: number, levelOfDetail: number): Microsoft.Maps.Location {\r\n let mapSize = getMapSize(levelOfDetail);\r\n let x = (clip(pixelX, 0, mapSize - 1) / mapSize) - 0.5;\r\n let y = 0.5 - (clip(pixelY, 0, mapSize - 1) / mapSize);\r\n let latitude = 90 - 360 * Math.atan(Math.exp(-y * 2 * Math.PI)) / Math.PI;\r\n let longitude = 360 * x;\r\n return new Microsoft.Maps.Location(latitude, longitude);\r\n }\r\n\r\n export module CurrentLocation {\r\n\r\n export function createPushpin(location: Microsoft.Maps.Location): Microsoft.Maps.Pushpin {\r\n let template = '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">'\r\n + '<circle fill=\"#FF5F00\" cx=\"12\" cy=\"12\" r=\"6\"/>'\r\n + '<circle fill=\"none\" stroke=\"#FF5F00\" stroke-width=\"2\" cx=\"12\" cy=\"12\" r=\"10\"/>'\r\n + '</svg>';\r\n\r\n let options: Microsoft.Maps.PushpinOptions = {\r\n draggable: false,\r\n htmlContent: template,\r\n height: 24,\r\n width: 24\r\n };\r\n\r\n return new Microsoft.Maps.Pushpin(location, options);\r\n }\r\n }\r\n }\r\n\r\n export class MapPolygonInfo {\r\n private _locationRect: Microsoft.Maps.LocationRect;\r\n private _baseRect: Rect;\r\n private _currentRect: Rect;\r\n\r\n constructor() {\r\n this._locationRect = new Microsoft.Maps.LocationRect(new Microsoft.Maps.Location(30, -30), 60, 60);\r\n }\r\n\r\n public reCalc(mapControl: Microsoft.Maps.Map, width: number, height: number) {\r\n let baseLocations = [this._locationRect.getNorthwest(), this._locationRect.getSoutheast()];\r\n width = width / 2.00;\r\n height = height / 2.00;\r\n\r\n if (!this._baseRect) {\r\n let l0 = MapUtil.locationToPixelXY(this._locationRect.getNorthwest(), defaultLevelOfDetail);\r\n let l1 = MapUtil.locationToPixelXY(this._locationRect.getSoutheast(), defaultLevelOfDetail);\r\n this._baseRect = new Rect(l0.x, l0.y, l1.x - l0.x, l1.y - l0.y);\r\n }\r\n\r\n let l = mapControl.tryLocationToPixel(baseLocations);\r\n this._currentRect = new Rect(l[0].x + width, l[0].y + height, l[1].x - l[0].x, l[1].y - l[0].y);\r\n }\r\n\r\n public get scale(): number {\r\n if (this._baseRect) {\r\n return this._currentRect.width / this._baseRect.width;\r\n }\r\n return 1.0;\r\n }\r\n\r\n public get transform(): Transform {\r\n let base = this._baseRect;\r\n let current = this._currentRect;\r\n let transform = new Transform();\r\n transform.translate(current.left, current.top);\r\n transform.scale((current.width / base.width), (current.height / base.height));\r\n transform.translate(-base.left, -base.top);\r\n return transform;\r\n }\r\n\r\n public get outherTransform() {\r\n let base = this._baseRect;\r\n let current = this._currentRect;\r\n let transform = new Transform();\r\n transform.translate(current.left, current.top);\r\n let scale = Math.sqrt(current.width / base.width);\r\n transform.scale(scale, scale);\r\n return transform;\r\n }\r\n\r\n public setViewBox(svg: SVGSVGElement) {\r\n let rect = svg.getBoundingClientRect();\r\n let current = this._currentRect;\r\n svg.setAttribute(\"viewBox\", [-current.left, -current.top, rect.width, rect.height].join(\" \"));\r\n }\r\n\r\n public get innerTransform() {\r\n let base = this._baseRect;\r\n let current = this._currentRect;\r\n let transform = new Transform();\r\n let scale = current.width / base.width;\r\n transform.scale(scale, scale);\r\n transform.translate(-base.left, -base.top);\r\n return transform;\r\n }\r\n\r\n public transformToString(transform: Transform) {\r\n let m = transform.matrix;\r\n return \"matrix(\" + m.m00 + \" \" + m.m10 + \" \" + m.m01 + \" \" + m.m11 + \" \" + m.m02 + \" \" + m.m12 + \")\";\r\n }\r\n }\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n\r\nmodule powerbi.visuals.utility {\r\n export interface SelectionManagerOptions{\r\n hostServices: IVisualHostServices;\r\n };\r\n\r\n export class SelectionManager {\r\n private selectedIds: SelectionId[];\r\n private hostServices: IVisualHostServices;\r\n\r\n public constructor(options: SelectionManagerOptions) {\r\n this.hostServices = options.hostServices;\r\n this.selectedIds = [];\r\n }\r\n\r\n public select(selectionId: SelectionId, multiSelect: boolean = false): JQueryDeferred<SelectionId[]> {\r\n let deferred: JQueryDeferred<data.Selector[]> = $.Deferred();\r\n\r\n if (this.hostServices.shouldRetainSelection()) {\r\n this.sendSelectionToHost([selectionId]);\r\n }\r\n else {\r\n this.selectInternal(selectionId, multiSelect);\r\n this.sendSelectionToHost(this.selectedIds);\r\n }\r\n\r\n deferred.resolve(this.selectedIds);\r\n return deferred;\r\n }\r\n\r\n public showContextMenu(selectionId: SelectionId, position?: Point): JQueryDeferred<{}> {\r\n let deferred: JQueryDeferred<{}> = $.Deferred();\r\n\r\n position = position || InteractivityUtils.getPositionOfLastInputEvent();\r\n this.sendContextMenuToHost(selectionId, position);\r\n\r\n deferred.resolve();\r\n return deferred;\r\n }\r\n\r\n public hasSelection(): boolean {\r\n return this.selectedIds.length > 0;\r\n }\r\n\r\n public clear(): JQueryDeferred<{}> {\r\n let deferred = $.Deferred();\r\n this.selectedIds = [];\r\n this.sendSelectionToHost([]);\r\n deferred.resolve();\r\n return deferred;\r\n }\r\n\r\n public getSelectionIds(): SelectionId[] {\r\n return this.selectedIds;\r\n }\r\n\r\n private sendSelectionToHost(ids: SelectionId[]) {\r\n let selectArgs: SelectEventArgs = {\r\n data: ids\r\n .filter((value: SelectionId) => value.hasIdentity())\r\n .map((value: SelectionId) => value.getSelector())\r\n };\r\n\r\n let data2 = this.getSelectorsByColumn(ids);\r\n\r\n if (!_.isEmpty(data2))\r\n selectArgs.data2 = data2;\r\n\r\n this.hostServices.onSelect(selectArgs);\r\n }\r\n\r\n private sendContextMenuToHost(selectionId: SelectionId, position: IPoint): void {\r\n let selectors = this.getSelectorsByColumn([selectionId]);\r\n if (_.isEmpty(selectors))\r\n return;\r\n\r\n let args: ContextMenuArgs = {\r\n data: selectors,\r\n position: position\r\n };\r\n\r\n this.hostServices.onContextMenu(args);\r\n }\r\n\r\n private getSelectorsByColumn(selectionIds: SelectionId[]): SelectorsByColumn[] {\r\n return _(selectionIds)\r\n .filter(value => value.hasIdentity)\r\n .map(value => value.getSelectorsByColumn())\r\n .compact()\r\n .value();\r\n }\r\n\r\n private selectInternal(selectionId: SelectionId, multiSelect: boolean) {\r\n if (SelectionManager.containsSelection(this.selectedIds, selectionId)) {\r\n this.selectedIds = multiSelect\r\n ? this.selectedIds.filter(d => !data.Selector.equals(d, selectionId))\r\n : this.selectedIds.length > 1\r\n ? [selectionId] : [];\r\n } else {\r\n if (multiSelect)\r\n this.selectedIds.push(selectionId);\r\n else\r\n this.selectedIds = [selectionId];\r\n }\r\n }\r\n\r\n public static containsSelection(list: SelectionId[], id: SelectionId) {\r\n return list.some(d => data.Selector.equals(d.getSelector(), id.getSelector()));\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n \"use strict\";\r\n\r\n export module shapes {\r\n import Utility = jsCommon.Utility;\r\n\r\n export class Polygon {\r\n\r\n private _absoluteCentroid: IPoint;\r\n private _absoluteBoundingRect: Rect;\r\n public polygonPoints: IPoint[];\r\n public pixelBoundingRect: Rect;\r\n\r\n constructor(absolutePoints: Float64Array) {\r\n this.polygonPoints = this.convertArrayPathToPoints(absolutePoints);\r\n }\r\n\r\n public absoluteCentroid(): IPoint {\r\n if (this._absoluteCentroid == null) {\r\n this._absoluteCentroid = this.calculatePolygonCentroid();\r\n }\r\n return this._absoluteCentroid;\r\n }\r\n\r\n public absoluteBoundingRect(): Rect {\r\n if (this._absoluteBoundingRect == null) {\r\n this._absoluteBoundingRect = this.calculateBoundingRect();\r\n }\r\n return this._absoluteBoundingRect;\r\n } \r\n\r\n /**\r\n * Check if label text contain in polygon shape.\r\n * \r\n * @return true/false is the label fit in polygon.\r\n * measure if rects points are inside the polygon shape\r\n * return true if there is at least 3 point inside the polygon\r\n */\r\n public contains(rect: IRect): boolean {\r\n let topLeft: IPoint = { x: rect.left, y: rect.top };\r\n let topRight: IPoint = { x: rect.left + rect.width, y: rect.top };\r\n let bottomLeft: IPoint = { x: rect.left, y: rect.top + rect.height };\r\n let bottomRight: IPoint = { x: rect.left + rect.width, y: rect.top + rect.height };\r\n\r\n return (this.inside(topLeft)\r\n && this.inside(topRight)\r\n && this.inside(bottomLeft)\r\n && this.inside(bottomRight));\r\n }\r\n\r\n /**\r\n * Check if label text is outside of polygon shape.\r\n * It checks 8 points in the label. TopLeft, TopCenter, TopRight, MiddleLeft, MiddleRight, BottomLeft, BottomMiddle, BottomRight\r\n * @return true/false is there is any conflict (at least one point inside the shape).\r\n */\r\n public conflicts(rect: IRect): boolean {\r\n if (!this.isConflictWithBoundingBox(rect)) {\r\n return false;\r\n }\r\n let topLeft: IPoint = { x: rect.left, y: rect.top };\r\n let topCenter: IPoint = { x: rect.left + rect.width/2, y: rect.top };\r\n let topRight: IPoint = { x: rect.left + rect.width, y: rect.top };\r\n let bottomLeft: IPoint = { x: rect.left, y: rect.top + rect.height };\r\n let bottomCenter: IPoint = { x: rect.left + rect.width/2, y: rect.top + rect.height };\r\n let bottomRight: IPoint = { x: rect.left + rect.width, y: rect.top + rect.height };\r\n let middleLeft: IPoint = { x: rect.left, y: rect.top + rect.height / 2};\r\n let middleRight: IPoint = { x: rect.left + rect.width, y: rect.top + rect.height/2 };\r\n\r\n return (this.inside(topLeft)\r\n || this.inside(topCenter)\r\n || this.inside(topRight)\r\n || this.inside(bottomLeft)\r\n || this.inside(bottomCenter)\r\n || this.inside(bottomRight)\r\n || this.inside(middleLeft)\r\n || this.inside(middleRight));\r\n }\r\n\r\n /**\r\n * returns intersection point of a line (depicted by two points) and a polygon.\r\n * \r\n * @return the point of intersection or null if there is no intersection.\r\n */\r\n public lineIntersectionPoint(p0: IPoint, p1: IPoint): IPoint {\r\n for (var i = 0; i < this.polygonPoints.length; i++) {\r\n let p2: IPoint = this.polygonPoints[i];\r\n let p3: IPoint = (i === this.polygonPoints.length - 1 ? this.polygonPoints[0] : this.polygonPoints[i + 1]);\r\n\r\n let intersection = this.getLineIntersection(p0, p1, p2, p3);\r\n\r\n if (intersection !== null) {\r\n return intersection;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * calculate Polygon Area.\r\n *\r\n * @return the area of the polygon (as number).\r\n */\r\n public static calculateAbsolutePolygonArea(polygonPoints: IPoint[]): number {\r\n let i, j = 1;\r\n let area = 0.0;\r\n\r\n for (i = 0; i < polygonPoints.length; i++) {\r\n area += polygonPoints[i].x * polygonPoints[j].y - polygonPoints[j].x * polygonPoints[i].y;\r\n j = (j + 1) % polygonPoints.length;\r\n }\r\n area *= 0.5;\r\n return area;\r\n }\r\n\r\n /**\r\n * Check if label text is outside of polygon bounding box.\r\n * \r\n * @return true/false is there is any conflict (at least one point inside the shape).\r\n */\r\n private isConflictWithBoundingBox(rect: IRect): boolean {\r\n return Rect.isIntersecting(this.absoluteBoundingRect(), rect);\r\n }\r\n\r\n /**\r\n * Calculate Polygon Centroid.\r\n *\r\n * @return 'center' point of the polygon.\r\n * calculate the polygon area\r\n * calculate the average points of the polygon by x & y axis. \r\n * divided the average point by the area\r\n */\r\n private calculatePolygonCentroid(): IPoint {\r\n let area, tempPoint, cx, cy, i, j: number;\r\n \r\n /* First calculate the polygon's signed area A */\r\n area = Polygon.calculateAbsolutePolygonArea(this.polygonPoints);\r\n\r\n /* Now calculate the centroid coordinates Cx and Cy */\r\n cx = cy = 0.0;\r\n j = 1;\r\n for (i = 0; i < this.polygonPoints.length; i++) {\r\n tempPoint = this.polygonPoints[i].x * this.polygonPoints[j].y - this.polygonPoints[j].x * this.polygonPoints[i].y;\r\n cx += (this.polygonPoints[i].x + this.polygonPoints[j].x) * tempPoint;\r\n cy += (this.polygonPoints[i].y + this.polygonPoints[j].y) * tempPoint;\r\n j = (j + 1) % this.polygonPoints.length;\r\n }\r\n cx = cx / (6.0 * area);\r\n cy = cy / (6.0 * area);\r\n\r\n return {\r\n x: cx,\r\n y: cy,\r\n };\r\n }\r\n\r\n private calculateBoundingRect(): Rect {\r\n let minX: number = Number.POSITIVE_INFINITY;\r\n let minY: number = Number.POSITIVE_INFINITY;\r\n let maxX: number = Number.NEGATIVE_INFINITY;\r\n let maxY: number = Number.NEGATIVE_INFINITY;\r\n\r\n for (let i = 0; i < this.polygonPoints.length; i++) {\r\n if (this.polygonPoints[i].x < minX) {\r\n minX = this.polygonPoints[i].x;\r\n } else if (this.polygonPoints[i].x > maxX) {\r\n maxX = this.polygonPoints[i].x;\r\n }\r\n\r\n if (this.polygonPoints[i].y < minY) {\r\n minY = this.polygonPoints[i].y;\r\n } else if (this.polygonPoints[i].y > maxY) {\r\n maxY = this.polygonPoints[i].y;\r\n }\r\n }\r\n\r\n return {\r\n left: minX,\r\n top: minY,\r\n width: maxX - minX,\r\n height: maxY - minY\r\n };\r\n }\r\n\r\n /**\r\n * Check if point exist inside polygon shape.\r\n * \r\n * @return true/false if point exist inside shape.\r\n * ray-casting algorithm based on:\r\n * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\r\n */\r\n private inside(point: IPoint): boolean {\r\n var x = point.x, y = point.y;\r\n\r\n var insideVar: boolean = false;\r\n for (var i = 0, j = this.polygonPoints.length - 1; i < this.polygonPoints.length; j = i++) {\r\n var xi = this.polygonPoints[i].x, yi = this.polygonPoints[i].y;\r\n var xj = this.polygonPoints[j].x, yj = this.polygonPoints[j].y;\r\n\r\n var intersect: boolean = ((yi > y) !== (yj > y))\r\n && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);\r\n if (intersect) {\r\n insideVar = !insideVar;\r\n }\r\n }\r\n return insideVar;\r\n };\r\n\r\n /**\r\n * Checks if a line (presented as two points) intersects with a another line\r\n */\r\n private getLineIntersection(line0p1: IPoint, line0p2: IPoint, line1p1: IPoint, line1p2: IPoint): IPoint {\r\n let p0_x: number = line0p1.x;\r\n let p0_y: number = line0p1.y;\r\n let p1_x: number = line0p2.x;\r\n let p1_y: number = line0p2.y;\r\n let p2_x: number = line1p1.x;\r\n let p2_y: number = line1p1.y;\r\n let p3_x: number = line1p2.x;\r\n let p3_y: number = line1p2.y;\r\n\r\n let s1_x: number = p1_x - p0_x;\r\n let s1_y: number = p1_y - p0_y;\r\n let s2_x: number = p3_x - p2_x;\r\n let s2_y: number = p3_y - p2_y;\r\n\r\n //Calculating collisions using cross products\r\n let s: number = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);\r\n let t: number = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);\r\n\r\n // 0<=s<=1 and 0<=t<=1 ensures that the collision is part of the original line\r\n if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {\r\n // Collision detected\r\n return { x: (p0_x + (t * s1_x)), y: (p0_y + (t * s1_y)) };\r\n }\r\n\r\n return null; // No collision\r\n }\r\n\r\n private convertArrayPathToPoints(path: Float64Array): IPoint[] {\r\n let pointsRes: IPoint[] = [];\r\n\r\n for (var i = 0; i < path.length; i += 2) {\r\n let x = path[i];\r\n let y = path[i + 1];\r\n let newPoint = {\r\n x: x,\r\n y: y,\r\n };\r\n pointsRes.push(newPoint);\r\n }\r\n return pointsRes;\r\n }\r\n }\r\n\r\n export module Point {\r\n\r\n export function offset(point: IPoint, offsetX: number, offsetY: number): IPoint {\r\n let newPointX = ((point.x + offsetX) >= 0) ? (point.x + offsetX) : 0;\r\n let newPointY = ((point.y + offsetY) >= 0) ? (point.y + offsetY) : 0;\r\n return { x: newPointX, y: newPointY };\r\n }\r\n\r\n export function equals(point: IPoint, other: IPoint): boolean {\r\n return point !== undefined && point !== null && other !== undefined && other !== null && point.x === other.x && point.y === other.y;\r\n }\r\n\r\n export function clone(point: IPoint): IPoint {\r\n return (point !== null) ? { x: point.x, y: point.y } : null;\r\n }\r\n\r\n export function toString(point: IPoint): string {\r\n return \"{x:\" + point.x + \", y:\" + point.y + \"}\";\r\n }\r\n\r\n export function serialize(point: IPoint): string {\r\n return point.x + \",\" + point.y;\r\n }\r\n\r\n export function getDistance(point: IPoint, other: IPoint): number {\r\n if ((point === null) || (other) === null) {\r\n return null;\r\n }\r\n let diffX = other.x - point.x;\r\n let diffY = other.y - point.y;\r\n return Math.sqrt(diffX * diffX + diffY * diffY);\r\n }\r\n\r\n export function equalWithPrecision(point1: IPoint, point2: IPoint): boolean {\r\n return point1 === point2 ||\r\n (point1 !== undefined && point2 !== undefined && Double.equalWithPrecision(point1.x, point2.x) && Double.equalWithPrecision(point1.y, point2.y));\r\n }\r\n\r\n export function parsePoint(value: any, defaultValue?: IPoint): IPoint {\r\n if (value === null) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else if (value === undefined) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else {\r\n if (value.length === 2) {\r\n return { x: Utility.parseNumber(value[0]), y: Utility.parseNumber(value[1]) };\r\n } else if (typeof value === \"string\") {\r\n let parts = (<string>value).split(\",\");\r\n if (parts.length !== 2) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n }\r\n return { x: Utility.parseNumber(parts[0]), y: Utility.parseNumber(parts[1]) };\r\n } else if ((value.length !== 2) && (typeof value !== \"string\")) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n }\r\n else {\r\n return { x: Utility.parseNumber(value.x), y: Utility.parseNumber(value.y) };\r\n }\r\n }\r\n }\r\n }\r\n\r\n export module Size {\r\n\r\n export function isEmpty(size: ISize): boolean {\r\n return size.width === 0 && size.height === 0;\r\n }\r\n\r\n export function equals(size: ISize, other: ISize): boolean {\r\n return size !== undefined && size !== null && other !== undefined && other !== null && size.width === other.width && size.height === other.height;\r\n }\r\n\r\n export function clone(size: ISize): ISize {\r\n return (size !== null) ? { width: size.width, height: size.height } : null;\r\n }\r\n\r\n export function inflate(size: ISize, padding: IThickness): ISize {\r\n let result = clone(size);\r\n if (padding) {\r\n result.width += padding.left + padding.right;\r\n result.height += padding.top + padding.bottom;\r\n }\r\n return result;\r\n }\r\n\r\n export function deflate(size: ISize, padding: IThickness): ISize {\r\n let result = clone(size);\r\n if (padding) {\r\n result.width = result.width - padding.left - padding.right;\r\n if (result.width < 0) {\r\n result.width = 0;\r\n }\r\n result.height = result.height - padding.top - padding.bottom;\r\n if (result.height < 0) {\r\n result.height = 0;\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n export function combine(size: ISize, other: ISize): ISize {\r\n if (other) {\r\n size.width = Math.max(size.width, other.width);\r\n size.height = Math.max(size.height, other.height);\r\n }\r\n return size;\r\n }\r\n\r\n export function toRect(size: ISize): IRect {\r\n return { left: 0, top: 0, width: size.width, height: size.height };\r\n }\r\n\r\n export function toString(size: ISize): string {\r\n return \"{width:\" + size.width + \", height:\" + size.height + \"}\";\r\n }\r\n\r\n export function equal(size1: ISize, size2: ISize): boolean {\r\n return size1 === size2 ||\r\n (size1 !== undefined && size2 !== undefined && size1.width === size2.width && size1.height === size2.height);\r\n }\r\n\r\n export function equalWithPrecision(size1: ISize, size2: ISize): boolean {\r\n return size1 === size2 ||\r\n (size1 !== undefined && size2 !== undefined && Double.equalWithPrecision(size1.width, size2.width) && Double.equalWithPrecision(size1.height, size2.height));\r\n }\r\n\r\n export function parseSize(value: any, defaultValue?: ISize): ISize {\r\n if (value === null) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else if (value === undefined) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else {\r\n if (value.length === 2) {\r\n return { width: Utility.parseNumber(value[0]), height: Utility.parseNumber(value[1]) };\r\n } else if (typeof value === \"string\") {\r\n let parts = (<string>value).split(\",\");\r\n if (parts.length !== 2) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n }\r\n return { width: Utility.parseNumber(parts[0]), height: Utility.parseNumber(parts[1]) };\r\n }\r\n else if ((value.length !== 2) && (typeof value !== \"string\")) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else {\r\n return { width: Utility.parseNumber(value.width), height: Utility.parseNumber(value.height) };\r\n }\r\n }\r\n }\r\n }\r\n\r\n export module Rect {\r\n\r\n export function getOffset(rect: IRect): IPoint {\r\n return { x: rect.left, y: rect.top };\r\n }\r\n\r\n export function getSize(rect: IRect): ISize {\r\n return { width: rect.width, height: rect.height };\r\n }\r\n\r\n export function setSize(rect: IRect, value: ISize): void {\r\n rect.width = value.width;\r\n rect.height = value.height;\r\n }\r\n\r\n export function right(rect: IRect): number {\r\n return rect.left + rect.width;\r\n }\r\n\r\n export function bottom(rect: IRect): number {\r\n return rect.top + rect.height;\r\n }\r\n\r\n export function topLeft(rect: IRect): IPoint {\r\n return { x: rect.left, y: rect.top };\r\n }\r\n\r\n export function topRight(rect: IRect): IPoint {\r\n return { x: rect.left + rect.width, y: rect.top };\r\n }\r\n\r\n export function bottomLeft(rect: IRect): IPoint {\r\n return { x: rect.left, y: rect.top + rect.height };\r\n }\r\n\r\n export function bottomRight(rect: IRect): IPoint {\r\n return { x: rect.left + rect.width, y: rect.top + rect.height };\r\n }\r\n\r\n export function equals(rect: IRect, other: IRect): boolean {\r\n return other !== undefined && other !== null &&\r\n rect.left === other.left && rect.top === other.top && rect.width === other.width && rect.height === other.height;\r\n }\r\n\r\n export function clone(rect: IRect): IRect {\r\n return (rect !== null) ? { left: rect.left, top: rect.top, width: rect.width, height: rect.height } : null;\r\n }\r\n\r\n export function toString(rect: IRect): string {\r\n return \"{left:\" + rect.left + \", top:\" + rect.top + \", width:\" + rect.width + \", height:\" + rect.height + \"}\";\r\n }\r\n\r\n export function offset(rect: IRect, offsetX: number, offsetY: number): IRect {\r\n let newLeft = ((rect.left + offsetX) >= 0) ? rect.left + offsetX : 0;\r\n let newTop = ((rect.top + offsetY) >= 0) ? rect.top + offsetY : 0;\r\n\r\n return { left: newLeft, top: newTop, width: rect.width, height: rect.height };\r\n }\r\n\r\n export function inflate(rect: IRect, padding: IThickness): IRect {\r\n let result = clone(rect);\r\n if (padding) {\r\n result.left -= padding.left;\r\n result.top -= padding.top;\r\n result.width += padding.left + padding.right;\r\n result.height += padding.top + padding.bottom;\r\n }\r\n return result;\r\n }\r\n\r\n export function deflate(rect: IRect, padding: IThickness): IRect {\r\n let result = clone(rect);\r\n if (padding) {\r\n result.left += padding.left;\r\n result.top += padding.top;\r\n result.width -= padding.left + padding.right;\r\n result.height -= padding.top + padding.bottom;\r\n }\r\n return result;\r\n }\r\n\r\n export function inflateBy(rect: IRect, padding: number): IRect {\r\n return { left: rect.left - padding, top: rect.top - padding, width: rect.width + padding + padding, height: rect.height + padding + padding };\r\n }\r\n\r\n export function deflateBy(rect: IRect, padding: number): IRect {\r\n return { left: rect.left + padding, top: rect.top + padding, width: rect.width - padding - padding, height: rect.height - padding - padding };\r\n }\r\n \r\n /**\r\n * Get closest point.\r\n * \r\n * @return the closest point on the rect to the (x,y) point given.\r\n * In case the (x,y) given is inside the rect, (x,y) will be returned.\r\n * Otherwise, a point on a border will be returned.\r\n */\r\n export function getClosestPoint(rect: IRect, x: number, y: number): IPoint {\r\n return {\r\n x: Math.min(Math.max(rect.left, x), rect.left + rect.width),\r\n y: Math.min(Math.max(rect.top, y), rect.top + rect.height)\r\n };\r\n }\r\n\r\n export function equal(rect1: IRect, rect2: IRect): boolean {\r\n return rect1 === rect2 ||\r\n (rect1 !== undefined && rect2 !== undefined && rect1.left === rect2.left && rect1.top === rect2.top && rect1.width === rect2.width && rect1.height === rect2.height);\r\n }\r\n\r\n export function equalWithPrecision(rect1: IRect, rect2: IRect): boolean {\r\n return rect1 === rect2 ||\r\n (rect1 !== undefined && rect2 !== undefined &&\r\n Double.equalWithPrecision(rect1.left, rect2.left) && Double.equalWithPrecision(rect1.top, rect2.top) &&\r\n Double.equalWithPrecision(rect1.width, rect2.width) && Double.equalWithPrecision(rect1.height, rect2.height));\r\n }\r\n\r\n export function isEmpty(rect: IRect): boolean {\r\n return rect === undefined || rect === null || (rect.width === 0 && rect.height === 0);\r\n }\r\n\r\n export function containsPoint(rect: IRect, point: IPoint): boolean {\r\n if ((rect === null) || (point === null)) {\r\n return false;\r\n }\r\n return Double.lessOrEqualWithPrecision(rect.left, point.x) &&\r\n Double.lessOrEqualWithPrecision(point.x, rect.left + rect.width) &&\r\n Double.lessOrEqualWithPrecision(rect.top, point.y) &&\r\n Double.lessOrEqualWithPrecision(point.y, rect.top + rect.height);\r\n }\r\n\r\n export function isIntersecting(rect1: IRect, rect2: IRect): boolean {\r\n if (!rect1 || !rect2) {\r\n return false;\r\n }\r\n let left = Math.max(rect1.left, rect2.left);\r\n let right = Math.min(rect1.left + rect1.width, rect2.left + rect2.width);\r\n if (left > right) {\r\n return false;\r\n }\r\n let top = Math.max(rect1.top, rect2.top);\r\n let bottom = Math.min(rect1.top + rect1.height, rect2.top + rect2.height);\r\n return top <= bottom;\r\n }\r\n\r\n export function intersect(rect1: IRect, rect2: IRect): IRect {\r\n if (!rect1) {\r\n return rect2;\r\n }\r\n if (!rect2) {\r\n return rect1;\r\n }\r\n let left = Math.max(rect1.left, rect2.left);\r\n let top = Math.max(rect1.top, rect2.top);\r\n let right = Math.min(rect1.left + rect1.width, rect2.left + rect2.width);\r\n let bottom = Math.min(rect1.top + rect1.height, rect2.top + rect2.height);\r\n if (left <= right && top <= bottom) {\r\n return { left: left, top: top, width: right - left, height: bottom - top };\r\n } else {\r\n return { left: 0, top: 0, width: 0, height: 0 };\r\n }\r\n }\r\n\r\n export function combine(rect1: IRect, rect2: IRect): IRect {\r\n if (!rect1) {\r\n return rect2;\r\n }\r\n if (!rect2) {\r\n return rect1;\r\n }\r\n let left = Math.min(rect1.left, rect2.left);\r\n let top = Math.min(rect1.top, rect2.top);\r\n let right = Math.max(rect1.left + rect1.width, rect2.left + rect2.width);\r\n let bottom = Math.max(rect1.top + rect1.height, rect2.top + rect2.height);\r\n\r\n return { left: left, top: top, width: right - left, height: bottom - top };\r\n }\r\n\r\n export function parseRect(value: any, defaultValue?: IRect): IRect {\r\n if (value === null) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else if (value === undefined) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else {\r\n if (value.length === 4) {\r\n return { left: Utility.parseNumber(value[0]), top: Utility.parseNumber(value[1]), width: Utility.parseNumber(value[2]), height: Utility.parseNumber(value[3]) };\r\n } else if (typeof value === \"string\") {\r\n let parts = (<string>value).split(\",\");\r\n if (parts.length !== 4) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n }\r\n return {\r\n left: Utility.parseNumber(parts[0]), top: Utility.parseNumber(parts[1]), width: Utility.parseNumber(parts[2]), height: Utility.parseNumber(parts[3])\r\n };\r\n }\r\n else if ((value.length !== 4) && (typeof value !== \"string\")) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n }\r\n else {\r\n return { left: Utility.parseNumber(value.left), top: Utility.parseNumber(value.top), width: Utility.parseNumber(value.width), height: Utility.parseNumber(value.height) };\r\n }\r\n }\r\n }\r\n }\r\n\r\n export module Thickness {\r\n\r\n export function inflate(thickness: IThickness, other: IThickness): IThickness {\r\n let result = clone(thickness);\r\n if (other) {\r\n result.left = thickness.left + other.left;\r\n result.right = thickness.right + other.right;\r\n result.bottom = thickness.bottom + other.bottom;\r\n result.top = thickness.top + other.top;\r\n }\r\n return result;\r\n }\r\n\r\n export function getWidth(thickness: IThickness): number {\r\n return thickness.left + thickness.right;\r\n }\r\n\r\n export function getHeight(thickness: IThickness): number {\r\n return thickness.top + thickness.bottom;\r\n }\r\n\r\n export function clone(thickness: IThickness): IThickness {\r\n return (thickness !== null) ? { left: thickness.left, top: thickness.top, right: thickness.right, bottom: thickness.bottom } : null;\r\n }\r\n\r\n export function equals(thickness: IThickness, other: IThickness): boolean {\r\n return thickness !== undefined && thickness !== null && other !== undefined && other !== null && thickness.left === other.left && thickness.bottom === other.bottom && thickness.right === other.right && thickness.top === other.top;\r\n }\r\n\r\n export function flipHorizontal(thickness: IThickness): void {\r\n let temp = thickness.right;\r\n thickness.right = thickness.left;\r\n thickness.left = temp;\r\n }\r\n\r\n export function flipVertical(thickness: IThickness): void {\r\n let top = thickness.top;\r\n thickness.top = thickness.bottom;\r\n thickness.bottom = top;\r\n }\r\n\r\n export function toString(thickness: IThickness): string {\r\n return \"{top:\" + thickness.top + \", left:\" + thickness.left + \", right:\" + thickness.right + \", bottom:\" + thickness.bottom + \"}\";\r\n }\r\n\r\n export function toCssString(thickness: IThickness): string {\r\n return thickness.top + \"px \" + thickness.right + \"px \" + thickness.bottom + \"px \" + thickness.left + \"px\";\r\n }\r\n\r\n export function isEmpty(thickness: IThickness): boolean {\r\n return thickness.left === 0 && thickness.top === 0 && thickness.right === 0 && thickness.bottom === 0;\r\n }\r\n\r\n export function equal(thickness1: IThickness, thickness2: IThickness): boolean {\r\n return thickness1 === thickness2 ||\r\n (thickness1 !== undefined && thickness2 !== undefined && thickness1.left === thickness2.left && thickness1.top === thickness2.top && thickness1.right === thickness2.right && thickness1.bottom === thickness2.bottom);\r\n }\r\n\r\n export function equalWithPrecision(thickness1: IThickness, thickness2: IThickness): boolean {\r\n return thickness1 === thickness2 ||\r\n (thickness1 !== undefined && thickness2 !== undefined &&\r\n Double.equalWithPrecision(thickness1.left, thickness2.left) && Double.equalWithPrecision(thickness1.top, thickness2.top) &&\r\n Double.equalWithPrecision(thickness1.right, thickness2.right) && Double.equalWithPrecision(thickness1.bottom, thickness2.bottom));\r\n }\r\n\r\n export function parseThickness(value: any, defaultValue?: IThickness, resetValue?: any): IThickness {\r\n if (value === null) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else if (value === undefined) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n } else {\r\n if (value.length === 4) {\r\n return { left: Utility.parseNumber(value[0]), top: Utility.parseNumber(value[1]), right: Utility.parseNumber(value[2]), bottom: Utility.parseNumber(value[3]) };\r\n } else if (typeof value === \"string\") {\r\n let parts = (<string>value).split(\",\");\r\n if (parts.length !== 4) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n }\r\n return { left: Utility.parseNumber(parts[0]), top: Utility.parseNumber(parts[1]), right: Utility.parseNumber(parts[2]), bottom: Utility.parseNumber(parts[3]) };\r\n } else if ((value.length !== 4) && (typeof value !== \"string\")) {\r\n return (defaultValue === undefined) ? null : defaultValue;\r\n }\r\n else {\r\n return { left: Utility.parseNumber(value.left), top: Utility.parseNumber(value.top), right: Utility.parseNumber(value.right), bottom: Utility.parseNumber(value.bottom) };\r\n }\r\n }\r\n }\r\n }\r\n\r\n export module Vector {\r\n\r\n export function isEmpty(vector: IVector): boolean {\r\n return vector.x === 0 && vector.y === 0;\r\n }\r\n\r\n export function equals(vector: IVector, other: IPoint): boolean {\r\n return vector !== undefined && vector !== null && other !== undefined && other !== null && vector.x === other.x && vector.y === other.y;\r\n }\r\n\r\n export function clone(vector: IVector): IVector {\r\n return (vector !== null) ? { x: vector.x, y: vector.y } : null;\r\n }\r\n\r\n export function toString(vector: IVector): string {\r\n return \"{x:\" + vector.x + \", y:\" + vector.y + \"}\";\r\n }\r\n\r\n export function getLength(vector: IVector): number {\r\n return Math.sqrt(vector.x * vector.x + vector.y * vector.y);\r\n }\r\n\r\n export function getLengthSqr(vector: IVector): number {\r\n return vector.x * vector.x + vector.y * vector.y;\r\n }\r\n\r\n export function scale(vector: IVector, scalar: number): IVector {\r\n return { x: vector.x * scalar, y: vector.y * scalar };\r\n }\r\n\r\n export function normalize(vector: IVector): IVector {\r\n return !isEmpty(vector) ? scale(vector, 1 / getLength(vector)) : vector;\r\n }\r\n\r\n export function rotate90DegCW(vector: IVector): IVector {\r\n return { x: vector.y, y: -vector.x };\r\n }\r\n\r\n export function rotate90DegCCW(vector: IVector): IVector {\r\n return { x: -vector.y, y: vector.x };\r\n }\r\n\r\n export function rotate(vector: IVector, angle: number): IVector {\r\n let newX = vector.x * Math.cos(angle) - vector.y * Math.sin(angle);\r\n let newY = vector.x * Math.sin(angle) + vector.y * Math.cos(angle);\r\n return { x: newX, y: newY };\r\n }\r\n\r\n export function equal(vector1: IVector, vector2: IVector): boolean {\r\n return vector1 === vector2 ||\r\n (vector1 !== undefined && vector2 !== undefined && vector1.x === vector2.x && vector1.y === vector2.y);\r\n }\r\n\r\n export function equalWithPrecision(vector1: IVector, vector2: IVector): boolean {\r\n return vector1 === vector2 ||\r\n (vector1 !== undefined && vector2 !== undefined && Double.equalWithPrecision(vector1.x, vector2.x) && Double.equalWithPrecision(vector1.y, vector2.y));\r\n }\r\n\r\n export function add(vect1: IVector, vect2: IVector): IVector {\r\n if (!vect1 || !vect2) {\r\n return undefined;\r\n }\r\n return { x: vect1.x + vect2.x, y: vect1.y + vect2.y };\r\n }\r\n\r\n export function subtract(vect1: IVector, vect2: IVector): IVector {\r\n if (!vect1 || !vect2) {\r\n return undefined;\r\n }\r\n return { x: vect1.x - vect2.x, y: vect1.y - vect2.y };\r\n }\r\n\r\n export function dotProduct(vect1: IVector, vect2: IVector): number {\r\n if (!vect1 || !vect2) {\r\n return undefined;\r\n }\r\n return vect1.x * vect2.x + vect1.y * vect2.y;\r\n }\r\n\r\n export function getDeltaVector(p0: IPoint, p1: IPoint): IVector {\r\n if (!p0 || !p1) {\r\n return undefined;\r\n }\r\n return { x: p1.x - p0.x, y: p1.y - p0.y };\r\n }\r\n }\r\n\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import PixelConverter = jsCommon.PixelConverter;\r\n\r\n /** Utility class for slicer*/\r\n export module SlicerUtil {\r\n /** CSS selectors for slicer elements. */\r\n export module Selectors {\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n export const HeaderContainer = createClassAndSelector('headerContainer');\r\n export const Header = createClassAndSelector('slicerHeader');\r\n export const HeaderText = createClassAndSelector('headerText');\r\n export const Body = createClassAndSelector('slicerBody');\r\n export const Label = createClassAndSelector('slicerLabel');\r\n export const LabelText = createClassAndSelector('slicerText');\r\n export const LabelImage = createClassAndSelector('slicerImage');\r\n export const CountText = createClassAndSelector('slicerCountText');\r\n export const Clear = createClassAndSelector('clear');\r\n export const MultiSelectEnabled = createClassAndSelector('isMultiSelectEnabled');\r\n }\r\n\r\n /** Const declarations*/\r\n export module DisplayNameKeys {\r\n export const Clear = 'Slicer_Clear';\r\n export const SelectAll = 'Slicer_SelectAll';\r\n }\r\n\r\n /** Helper class for slicer settings */\r\n export module SettingsHelper {\r\n export function areSettingsDefined(data: SlicerData): boolean {\r\n return data != null && data.slicerSettings != null;\r\n }\r\n }\r\n\r\n /** Helper class for handling slicer default value */\r\n export module DefaultValueHandler {\r\n export function getIdentityFields(dataView: DataView): data.SQExpr[] {\r\n if (!dataView)\r\n return;\r\n\r\n let dataViewCategorical = dataView.categorical;\r\n if (!dataViewCategorical || _.isEmpty(dataViewCategorical.categories))\r\n return;\r\n\r\n return <data.SQExpr[]>dataViewCategorical.categories[0].identityFields;\r\n }\r\n }\r\n\r\n // Compare the sqExpr of the scopeId with sqExprs of the retained values. \r\n // If match found, remove the item from the retainedValues list, and return true, \r\n // otherwise return false.\r\n export function tryRemoveValueFromRetainedList(value: DataViewScopeIdentity, selectedScopeIds: DataViewScopeIdentity[], caseInsensitive?: boolean): boolean {\r\n if (!value || _.isEmpty(selectedScopeIds))\r\n return false;\r\n\r\n for (let i = 0, len = selectedScopeIds.length; i < len; i++) {\r\n let retainedValueScopeId = selectedScopeIds[i];\r\n if (DataViewScopeIdentity.equals(value, retainedValueScopeId, caseInsensitive)) {\r\n selectedScopeIds.splice(i, 1);\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /** Helper class for creating and measuring slicer DOM elements */\r\n export class DOMHelper {\r\n public createSlicerHeader(hostServices: IVisualHostServices): HTMLElement {\r\n let slicerHeaderDiv = document.createElement('div');\r\n slicerHeaderDiv.className = Selectors.Header.class;\r\n\r\n let slicerHeader: D3.Selection = d3.select(slicerHeaderDiv);\r\n slicerHeader.append('span')\r\n .classed(Selectors.Clear.class, true)\r\n .attr('title', hostServices.getLocalizedString(DisplayNameKeys.Clear));\r\n slicerHeader.append('div').classed(Selectors.HeaderText.class, true);\r\n\r\n return slicerHeaderDiv;\r\n }\r\n\r\n public getHeaderTextProperties(settings: SlicerSettings): TextProperties {\r\n let headerTextProperties: TextProperties = {\r\n fontFamily: 'wf_segoe-ui_normal',\r\n fontSize: '10px'\r\n };\r\n if (settings.header.show) {\r\n headerTextProperties.fontSize = PixelConverter.fromPoint(settings.header.textSize);\r\n }\r\n return headerTextProperties;\r\n }\r\n\r\n public getSlicerBodyViewport(currentViewport: IViewport, settings: SlicerSettings, headerTextProperties: TextProperties): IViewport {\r\n let headerHeight = (settings.header.show) ? this.getHeaderHeight(settings, headerTextProperties) : 0;\r\n let slicerBodyHeight = currentViewport.height - (headerHeight + settings.header.borderBottomWidth);\r\n return {\r\n height: slicerBodyHeight,\r\n width: currentViewport.width\r\n };\r\n }\r\n\r\n public updateSlicerBodyDimensions(currentViewport: IViewport, slicerBody: D3.Selection, settings: SlicerSettings): void {\r\n let slicerViewport = this.getSlicerBodyViewport(currentViewport, settings, this.getHeaderTextProperties(settings));\r\n slicerBody.style({\r\n 'height': PixelConverter.toString(slicerViewport.height),\r\n 'width': PixelConverter.toString(slicerViewport.width),\r\n });\r\n }\r\n\r\n public getHeaderHeight(settings: SlicerSettings, textProperties: TextProperties): number {\r\n return TextMeasurementService.estimateSvgTextHeight(this.getTextProperties(settings.header.textSize, textProperties)) + settings.general.outlineWeight;\r\n }\r\n\r\n public getRowHeight(settings: SlicerSettings, textProperties: TextProperties): number {\r\n return TextMeasurementService.estimateSvgTextHeight(this.getTextProperties(settings.slicerText.textSize, textProperties)) + this.getRowsOutlineWidth(settings.slicerText.outline, settings.general.outlineWeight);\r\n }\r\n\r\n public styleSlicerHeader(slicerHeader: D3.Selection, settings: SlicerSettings, headerText: string): void {\r\n if (settings.header.show) {\r\n slicerHeader.style('display', 'block');\r\n let headerTextElement = slicerHeader.select(Selectors.HeaderText.selector)\r\n .text(headerText);\r\n this.setSlicerHeaderTextStyle(headerTextElement, settings);\r\n }\r\n else {\r\n slicerHeader.style('display', 'none');\r\n }\r\n }\r\n\r\n public setSlicerTextStyle(slicerText: D3.Selection, settings: SlicerSettings): void {\r\n slicerText\r\n .style({\r\n 'color': settings.slicerText.color,\r\n 'background-color': settings.slicerText.background,\r\n 'border-style': 'solid',\r\n 'border-color': settings.general.outlineColor,\r\n 'border-width': VisualBorderUtil.getBorderWidth(settings.slicerText.outline, settings.general.outlineWeight),\r\n 'font-size': PixelConverter.fromPoint(settings.slicerText.textSize),\r\n });\r\n }\r\n\r\n public getRowsOutlineWidth(outlineElement: string, outlineWeight: number): number {\r\n switch (outlineElement) {\r\n case outline.none:\r\n case outline.leftRight:\r\n return 0;\r\n case outline.bottomOnly:\r\n case outline.topOnly:\r\n return outlineWeight;\r\n case outline.topBottom:\r\n case outline.frame:\r\n return outlineWeight * 2;\r\n default:\r\n return 0;\r\n }\r\n }\r\n\r\n private setSlicerHeaderTextStyle(slicerHeader: D3.Selection, settings: SlicerSettings): void {\r\n slicerHeader\r\n .style({\r\n 'border-style': 'solid',\r\n 'border-color': settings.general.outlineColor,\r\n 'border-width': VisualBorderUtil.getBorderWidth(settings.header.outline, settings.general.outlineWeight),\r\n 'color': settings.header.fontColor,\r\n 'background-color': settings.header.background,\r\n 'font-size': PixelConverter.fromPoint(settings.header.textSize),\r\n });\r\n }\r\n\r\n private getTextProperties(textSize: number, textProperties: TextProperties): TextProperties {\r\n textProperties.fontSize = PixelConverter.fromPoint(textSize);\r\n return textProperties;\r\n }\r\n }\r\n }\r\n}","module powerbi.visuals {\r\n /**\r\n * Contains functions/constants to aid in adding tooltips. \r\n */\r\n export module tooltipUtils {\r\n\r\n export function tooltipUpdate(selection: D3.Selection, tooltips: string[]): void {\r\n if (tooltips.length === 0)\r\n return;\r\n\r\n debug.assert(selection.length === tooltips.length || selection[0].length === tooltips.length, 'data length should match dom element count');\r\n let titles = selection.selectAll('title');\r\n let titlesUpdate = titles.data((d, i) => [tooltips[i]]);\r\n\r\n titlesUpdate.enter().append('title');\r\n titlesUpdate.exit().remove();\r\n titlesUpdate.text((d) => d);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n /**\r\n * Contains functions/constants to aid in SVG manupilation. \r\n */\r\n export module SVGUtil {\r\n /** \r\n * Very small values, when stringified, may be converted to scientific notation and cause a temporarily \r\n * invalid attribute or style property value.\r\n * For example, the number 0.0000001 is converted to the string \"1e-7\". \r\n * This is particularly noticeable when interpolating opacity values.\r\n * To avoid scientific notation, start or end the transition at 1e-6,\r\n * which is the smallest value that is not stringified in exponential notation.\r\n */\r\n export const AlmostZero = 1e-6;\r\n\r\n /**\r\n * Creates a translate string for use with the SVG transform call.\r\n */\r\n export function translate(x: number, y: number): string {\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n return 'translate(' + x + ',' + y + ')';\r\n }\r\n\r\n /**\r\n * Creates a translateX string for use with the SVG transform call.\r\n */\r\n export function translateXWithPixels(x: number): string {\r\n debug.assertValue(x, 'x');\r\n return 'translateX(' + x + 'px)';\r\n }\r\n\r\n export function translateWithPixels(x: number, y: number): string {\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n return 'translate(' + x + 'px,' + y + 'px)';\r\n }\r\n\r\n /**\r\n * Creates a translate + rotate string for use with the SVG transform call.\r\n */\r\n export function translateAndRotate(x: number, y: number, px: number, py: number, angle: number): string {\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n debug.assertValue(px, 'px');\r\n debug.assertValue(py, 'py');\r\n debug.assertValue(angle, 'angle');\r\n\r\n return 'transform', \"translate(\"\r\n + x + \",\" + y + \")\"\r\n + \" rotate(\" + angle + \",\" + px + \",\" + py + \")\";\r\n }\r\n\r\n /**\r\n * Creates a scale string for use in a CSS transform property.\r\n */\r\n export function scale(scale: number): string {\r\n debug.assertValue(scale, 'scale');\r\n\r\n return `scale(${scale})`;\r\n }\r\n\r\n /**\r\n * Creates a translate + scale string for use with the SVG transform call.\r\n */\r\n export function translateAndScale(x: number, y: number, ratio: number): string {\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n debug.assertValue(ratio, 'ratio');\r\n\r\n return 'transform', \"translate(\"\r\n + x + \",\" + y + \")\"\r\n + \" scale(\" + ratio + \")\";\r\n }\r\n\r\n /**\r\n * Creates a transform origin string for use in a CSS transform-origin property.\r\n */\r\n export function transformOrigin(xOffset: string, yOffset: string): string {\r\n debug.assertValue(xOffset, 'xOffset');\r\n debug.assertValue(yOffset, 'yOffset');\r\n\r\n return `${xOffset} ${yOffset}`;\r\n }\r\n\r\n /**\r\n * Forces all D3 transitions to complete.\r\n * Normally, zero-delay transitions are executed after an instantaneous delay (<10ms). \r\n * This can cause a brief flicker if the browser renders the page twice: once at the end of the first event loop, \r\n * then again immediately on the first timer callback. By flushing the timer queue at the end of the first event loop,\r\n * you can run any zero-delay transitions immediately and avoid the flicker.\r\n * \r\n * These flickers are noticable on IE, and with a large number of webviews(not recommend you ever do this) on iOS.\r\n */\r\n export function flushAllD3Transitions() {\r\n let now = Date.now;\r\n Date.now = function () { return Infinity; };\r\n d3.timer.flush();\r\n Date.now = now;\r\n }\r\n\r\n /**\r\n * Wrapper for flushAllD3Transitions.\r\n */\r\n export function flushAllD3TransitionsIfNeeded(options: VisualInitOptions | AnimationOptions) {\r\n if (!options)\r\n return;\r\n\r\n let animationOptions: AnimationOptions = <AnimationOptions>options;\r\n\r\n let asVisualInitOptions = <VisualInitOptions>options;\r\n if (asVisualInitOptions.animation)\r\n animationOptions = asVisualInitOptions.animation;\r\n\r\n if (animationOptions && animationOptions.transitionImmediate) {\r\n flushAllD3Transitions();\r\n }\r\n }\r\n\r\n /**\r\n * There is a known bug in IE10 that causes cryptic crashes for SVG elements with a null 'd' attribute:\r\n * https://github.com/mbostock/d3/issues/1737\r\n */\r\n export function ensureDAttribute(pathElement: D3.D3Element) {\r\n if (!pathElement.getAttribute('d')) {\r\n pathElement.setAttribute('d', '');\r\n }\r\n }\r\n\r\n /**\r\n * In IE10, it is possible to return SVGPoints with NaN members.\r\n */\r\n export function ensureValidSVGPoint(point: SVGPoint) {\r\n if (isNaN(point.x)) {\r\n point.x = 0;\r\n }\r\n if (isNaN(point.y)) {\r\n point.y = 0;\r\n }\r\n }\r\n\r\n /**\r\n * Parse the Transform string with value 'translate(x,y)'.\r\n * In Chrome for the translate(position) string the delimiter \r\n * is a comma and in IE it is a spaceso checking for both.\r\n */\r\n export function parseTranslateTransform(input: string): { x: string; y: string } {\r\n if (!input || input.length === 0) { // Interpet falsy and empty string as a no-op translate\r\n return {\r\n x: \"0\",\r\n y: \"0\",\r\n };\r\n }\r\n let translateCoordinates = input.split(/[\\s,]+/);\r\n\r\n debug.assertValue(translateCoordinates, 'translateCoordinates');\r\n debug.assert(translateCoordinates.length > 0, 'translate array must atleast have one value');\r\n\r\n let yValue = '0';\r\n let xValue: string;\r\n let xCoord = translateCoordinates[0];\r\n\r\n // Y coordinate is ommited in I.E if it is 0, so need to check against that\r\n if (translateCoordinates.length === 1) {\r\n // 10 refers to the length of 'translate('\r\n xValue = xCoord.substring(10, xCoord.length - 1);\r\n } else {\r\n let yCoord = translateCoordinates[1];\r\n yValue = yCoord.substring(0, yCoord.length - 1);\r\n // 10 refers to the length of 'translate('\r\n xValue = xCoord.substring(10, xCoord.length);\r\n }\r\n\r\n return {\r\n x: xValue,\r\n y: yValue\r\n };\r\n }\r\n\r\n /**\r\n * Create an arrow.\r\n */\r\n export function createArrow(width: number, height: number, rotate: number): { path: string; transform: string } {\r\n let transform = \"rotate(\" + rotate + \" \" + width / 2 + \" \" + height / 2 + \")\";\r\n let path = \"M0 0\";\r\n path += \"L0 \" + height;\r\n path += \"L\" + width + \" \" + height / 2 + \" Z\";\r\n return {\r\n path: path,\r\n transform: transform\r\n };\r\n }\r\n\r\n /**\r\n * Use the ratio of the scaled bounding rect and the SVG DOM bounding box to get the x and y transform scale values\r\n * @deprecated This function is unreliable across browser implementations, prefer to use SVGScaleDetector if needed.\r\n */\r\n export function getTransformScaleRatios(svgElement: SVGSVGElement): Point {\r\n debug.assertFail('deprecated');\r\n\r\n if (svgElement != null) {\r\n let scaledRect = svgElement.getBoundingClientRect();\r\n let domRect = svgElement.getBBox();\r\n if (domRect.height > 0 && domRect.width > 0) {\r\n return {\r\n x: scaledRect.width / domRect.width,\r\n y: scaledRect.height / domRect.height\r\n };\r\n }\r\n }\r\n return { x: 1, y: 1 };\r\n }\r\n }\r\n\r\n export class SVGScaleDetector {\r\n private scaleDetectorElement: SVGRectElement;\r\n\r\n constructor(svgElement: D3.Selection) {\r\n this.scaleDetectorElement = <SVGRectElement>svgElement\r\n .append('rect') // Using a <rect> which should have a reliable bounding box across browser implementations.\r\n .classed('scale-detector', true)\r\n .attr({\r\n width: 1,\r\n height: 1,\r\n 'stroke-width': '0px',\r\n fill: 'none',\r\n })\r\n .node();\r\n }\r\n\r\n public getScale(): Point {\r\n let scaledRect = this.scaleDetectorElement.getBoundingClientRect();\r\n let domRect = this.scaleDetectorElement.getBBox();\r\n if (domRect.height > 0 && domRect.width > 0) {\r\n return {\r\n x: scaledRect.width / domRect.width,\r\n y: scaledRect.height / domRect.height\r\n };\r\n }\r\n\r\n return {\r\n x: 1,\r\n y: 1\r\n };\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n /**\r\n * Contains functions/constants to aid in text manupilation. \r\n */\r\n export module TextUtil {\r\n \r\n /**\r\n * Remove breaking spaces from given string and replace by none breaking space (&nbsp).\r\n */\r\n export function removeBreakingSpaces(str: string): string {\r\n return str.toString().replace(new RegExp(' ', 'g'), '&nbsp');\r\n }\r\n\r\n /**\r\n * Remove ellipses from a given string\r\n */\r\n export function removeEllipses(str: string): string {\r\n return str.replace(/…/g, '');\r\n }\r\n\r\n /**\r\n * Replace every whitespace (0x20) with Non-Breaking Space (0xA0)\r\n * @param {string} txt String to replace White spaces\r\n * @returns Text after replcing white spaces\r\n */\r\n export function replaceSpaceWithNBSP(txt: string): string {\r\n if (txt != null)\r\n return txt.replace(/ /g, \"\\xA0\");\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface GradientSettings {\r\n diverging: boolean;\r\n minColor: any;\r\n midColor?: any;\r\n maxColor: any;\r\n minValue?: number;\r\n midValue?: number;\r\n maxValue?: number;\r\n };\r\n\r\n interface GradientColors {\r\n minColor: string;\r\n midColor?: string;\r\n maxColor: string;\r\n }\r\n\r\n export module GradientUtils {\r\n\r\n import SQExprBuilder = powerbi.data.SQExprBuilder;\r\n import DataViewObjectPropertyDefinition = powerbi.data.DataViewObjectPropertyDefinition;\r\n const DefaultMidColor: string = \"#ffffff\";\r\n const DataPointPropertyIdentifier: string = \"dataPoint\";\r\n const FillRulePropertyIdentifier: string = \"fillRule\";\r\n\r\n export function getFillRuleRole(objectDescs: powerbi.data.DataViewObjectDescriptors): string {\r\n if (!objectDescs)\r\n return;\r\n\r\n for (let objectName in objectDescs) {\r\n let objectDesc = objectDescs[objectName];\r\n for (let propertyName in objectDesc.properties) {\r\n let propertyDesc = objectDesc.properties[propertyName];\r\n if (propertyDesc.type && propertyDesc.type[FillRulePropertyIdentifier]) {\r\n return propertyDesc.rule.inputRole;\r\n }\r\n }\r\n }\r\n }\r\n\r\n export function shouldShowGradient(visualConfig): boolean {\r\n let isShowGradienCard: boolean = visualConfig && visualConfig.query && visualConfig.query.projections && visualConfig.query.projections['Gradient'] ? true : false;\r\n return isShowGradienCard;\r\n }\r\n\r\n export function getUpdatedGradientSettings(gradientObject: data.DataViewObjectDefinitions): GradientSettings {\r\n let gradientSettings: GradientSettings;\r\n\r\n if (gradientObject && !$.isEmptyObject(gradientObject)) {\r\n\r\n gradientSettings = getDefaultGradientSettings();\r\n\r\n for (let propertyName in gradientSettings) {\r\n let hasProperty: boolean = (<Object>gradientObject).hasOwnProperty(propertyName);\r\n if (hasProperty) {\r\n let value: any = gradientObject[propertyName];\r\n\r\n if (value && value.solid && value.solid.color) {\r\n value = value.solid.color;\r\n }\r\n\r\n gradientSettings[propertyName] = value;\r\n }\r\n }\r\n }\r\n\r\n return gradientSettings;\r\n }\r\n\r\n export function getGradientMeasureIndex(dataViewCategorical: DataViewCategorical): number {\r\n if (dataViewCategorical && dataViewCategorical.values && dataViewCategorical.values.grouped) {\r\n let grouped = dataViewCategorical.values.grouped();\r\n return DataRoleHelper.getMeasureIndexOfRole(grouped, 'Gradient');\r\n }\r\n return -1;\r\n }\r\n\r\n export function getGradientValueColumn(dataViewCategorical: DataViewCategorical): DataViewValueColumn {\r\n if (dataViewCategorical == null) return null;\r\n // check for gradient measure index\r\n let gradientMeasureIndex: number = GradientUtils.getGradientMeasureIndex(dataViewCategorical);\r\n let gradientValueColumn: DataViewValueColumn = gradientMeasureIndex === - 1 ? null : dataViewCategorical.values[gradientMeasureIndex];\r\n return gradientValueColumn;\r\n }\r\n\r\n export function hasGradientRole(dataViewCategorical: DataViewCategorical): boolean {\r\n let gradientMeasureIndex = getGradientMeasureIndex(dataViewCategorical);\r\n return gradientMeasureIndex >= 0;\r\n }\r\n\r\n export function getDefaultGradientSettings(): GradientSettings {\r\n\r\n let colors: GradientColors = getDefaultColors();\r\n let gradientSettings: GradientSettings = {\r\n diverging: false,\r\n minColor: colors.minColor,\r\n midColor: DefaultMidColor,\r\n maxColor: colors.maxColor,\r\n minValue: undefined,\r\n midValue: undefined,\r\n maxValue: undefined,\r\n };\r\n\r\n return gradientSettings;\r\n }\r\n\r\n export function getDefaultFillRuleDefinition(): DataViewObjectPropertyDefinition {\r\n return getLinearGradien2FillRuleDefinition();\r\n }\r\n\r\n export function updateFillRule(propertyName: string, propertyValue: any, definitions: powerbi.data.DataViewObjectDefinitions): void {\r\n\r\n let dataPointObjectDefinition: data.DataViewObjectDefinition = data.DataViewObjectDefinitions.ensure(definitions, DataPointPropertyIdentifier, null);\r\n let fillRule: FillRuleDefinition = getFillRule(definitions);\r\n let numericValueExpr: data.SQConstantExpr;\r\n let colorValueExpr: data.SQExpr;\r\n\r\n if (!fillRule) {\r\n return;\r\n }\r\n\r\n if ($.isNumeric(propertyValue)) {\r\n numericValueExpr = propertyValue !== undefined ? SQExprBuilder.double(+propertyValue) : undefined;;\r\n }\r\n\r\n if (propertyName === \"minColor\" || propertyName === \"midColor\" || propertyName === \"maxColor\") {\r\n colorValueExpr = getColorExpressionValue(fillRule, propertyName, propertyValue);\r\n }\r\n\r\n if (propertyName === \"minColor\") {\r\n updateMinColor(fillRule, colorValueExpr);\r\n }\r\n else if (propertyName === \"midColor\") {\r\n updateMidColor(fillRule, colorValueExpr);\r\n }\r\n else if (propertyName === \"maxColor\") {\r\n updateMaxColor(fillRule, colorValueExpr);\r\n }\r\n else if (propertyName === \"minValue\") {\r\n updateMinValue(fillRule, numericValueExpr);\r\n }\r\n else if (propertyName === \"midValue\") {\r\n updateMidValue(fillRule, numericValueExpr);\r\n }\r\n else if (propertyName === \"maxValue\") {\r\n updateMaxValue(fillRule, numericValueExpr);\r\n }\r\n else if (propertyName === \"diverging\") {\r\n if (propertyValue) {\r\n fillRule = getLinearGradien3FillRuleDefinition(fillRule);\r\n }\r\n else {\r\n fillRule = getLinearGradien2FillRuleDefinition(fillRule);\r\n }\r\n dataPointObjectDefinition.properties[FillRulePropertyIdentifier] = fillRule;\r\n }\r\n else if (propertyName === \"revertToDefault\") {\r\n fillRule = this.getDefaultFillRuleDefinition();\r\n dataPointObjectDefinition.properties[FillRulePropertyIdentifier] = fillRule;\r\n }\r\n }\r\n\r\n export function getGradientSettings(baseFillRule: FillRuleDefinition): GradientSettings {\r\n if (baseFillRule) {\r\n return getGradientSettingsFromRule(baseFillRule);\r\n }\r\n else {\r\n return getDefaultGradientSettings();\r\n }\r\n }\r\n\r\n export function getFillRule(objectDefinitions: data.DataViewObjectDefinitions): FillRuleDefinition {\r\n let fillRuleDefinition: FillRuleDefinition = data.DataViewObjectDefinitions.getValue(objectDefinitions, { objectName: DataPointPropertyIdentifier, propertyName: FillRulePropertyIdentifier }, null);\r\n return fillRuleDefinition;\r\n }\r\n\r\n function getDefaultColors(): GradientColors {\r\n\r\n let dataColors: IDataColorPalette = new powerbi.visuals.DataColorPalette();\r\n let maxColorInfo: IColorInfo = dataColors.getColorByIndex(0);\r\n let colors = d3.scale.linear()\r\n .domain([0, 100])\r\n .range([\"#ffffff\", maxColorInfo.value]);\r\n let maxColor: string = maxColorInfo.value;\r\n let minColor: string = <any>colors(20);\r\n let midColor: string = DefaultMidColor;\r\n\r\n return {\r\n minColor: minColor,\r\n midColor: midColor,\r\n maxColor: maxColor,\r\n };\r\n }\r\n\r\n export function getGradientSettingsFromRule(fillRule: FillRuleDefinition): GradientSettings {\r\n let maxColor: string;\r\n let minColor: string;\r\n let midColor: string = DefaultMidColor;\r\n let maxValue: number;\r\n let midValue: number;\r\n let minValue: number;\r\n let diverging: boolean = fillRule.linearGradient3 !== undefined;\r\n\r\n if (fillRule.linearGradient2) {\r\n let maxColorExpr: any = fillRule.linearGradient2.max.color;\r\n let minColorExpr: any = fillRule.linearGradient2.min.color;\r\n let maxValueExpr: any = fillRule.linearGradient2.max.value;\r\n let minValueExpr: any = fillRule.linearGradient2.min.value;\r\n maxColor = maxColorExpr.value;\r\n minColor = minColorExpr.value;\r\n if (maxValueExpr) {\r\n maxValue = <number>maxValueExpr.value;\r\n }\r\n if (minValueExpr) {\r\n minValue = <number>minValueExpr.value;\r\n }\r\n }\r\n else if (fillRule.linearGradient3) {\r\n let maxColorExpr: any = fillRule.linearGradient3.max.color;\r\n let midColorExpr: any = fillRule.linearGradient3.mid.color;\r\n let minColorExpr: any = fillRule.linearGradient3.min.color;\r\n let maxValueExpr: any = fillRule.linearGradient3.max.value;\r\n let midValueExpr: any = fillRule.linearGradient3.mid.value;\r\n let minValueExpr: any = fillRule.linearGradient3.min.value;\r\n maxColor = maxColorExpr.value;\r\n midColor = midColorExpr.value;\r\n minColor = minColorExpr.value;\r\n if (maxValueExpr) {\r\n maxValue = <number>maxValueExpr.value;\r\n }\r\n if (midValueExpr) {\r\n midValue = <number>midValueExpr.value;\r\n }\r\n if (minValueExpr) {\r\n minValue = <number>minValueExpr.value;\r\n }\r\n }\r\n\r\n return {\r\n diverging: diverging,\r\n minColor: minColor,\r\n midColor: midColor,\r\n maxColor: maxColor,\r\n minValue: minValue,\r\n midValue: midValue,\r\n maxValue: maxValue,\r\n };\r\n }\r\n\r\n /** Returns a string representing the gradient to be used for the GradientBar directive. */\r\n export function getGradientBarColors(gradientSettings: GradientSettings): string {\r\n let colors: string[] = [];\r\n colors.push(gradientSettings.minColor);\r\n if (gradientSettings.diverging) {\r\n colors.push(gradientSettings.midColor);\r\n }\r\n colors.push(gradientSettings.maxColor);\r\n return colors.join(\",\");\r\n }\r\n\r\n function getLinearGradien2FillRuleDefinition(baseFillRule?: FillRuleDefinition): DataViewObjectPropertyDefinition {\r\n let gradientSettings: GradientSettings = getGradientSettings(baseFillRule);\r\n let fillRuleDefinition: FillRuleDefinition = {\r\n linearGradient2: {\r\n max: { color: SQExprBuilder.text(gradientSettings.maxColor) },\r\n min: { color: SQExprBuilder.text(gradientSettings.minColor) },\r\n }\r\n };\r\n\r\n return fillRuleDefinition;\r\n }\r\n\r\n function getLinearGradien3FillRuleDefinition(baseFillRule?: FillRuleDefinition): DataViewObjectPropertyDefinition {\r\n let gradientSettings: GradientSettings = getGradientSettings(baseFillRule);\r\n let fillRuleDefinition: FillRuleDefinition = {\r\n linearGradient3: {\r\n max: { color: SQExprBuilder.text(gradientSettings.maxColor) },\r\n mid: { color: SQExprBuilder.text(gradientSettings.midColor) },\r\n min: { color: SQExprBuilder.text(gradientSettings.minColor) },\r\n }\r\n };\r\n\r\n return fillRuleDefinition;\r\n }\r\n\r\n function getDefaultColorExpression(fillRule: FillRuleDefinition, propertyName: string): data.SQExpr {\r\n let defaultColor: data.SQExpr;\r\n let defaultFillRule: FillRuleDefinition;\r\n\r\n if (fillRule.linearGradient3) {\r\n defaultFillRule = getLinearGradien3FillRuleDefinition();\r\n if (propertyName === \"minColor\") {\r\n defaultColor = defaultFillRule.linearGradient3.min.color;\r\n }\r\n else if (propertyName === \"midColor\") {\r\n defaultColor = defaultFillRule.linearGradient3.mid.color;\r\n }\r\n else if (propertyName === \"maxColor\") {\r\n defaultColor = defaultFillRule.linearGradient3.max.color;\r\n }\r\n }\r\n else if (fillRule.linearGradient2) {\r\n defaultFillRule = getLinearGradien2FillRuleDefinition();\r\n if (propertyName === \"minColor\") {\r\n defaultColor = defaultFillRule.linearGradient2.min.color;\r\n }\r\n else if (propertyName === \"maxColor\") {\r\n defaultColor = defaultFillRule.linearGradient2.max.color;\r\n }\r\n }\r\n\r\n return defaultColor;\r\n }\r\n\r\n function getColorExpressionValue(fillRule: FillRuleDefinition, propertyName: string, propertyValue: string): data.SQExpr {\r\n let colorExpressionValue: data.SQExpr;\r\n if (propertyValue) {\r\n colorExpressionValue = SQExprBuilder.text(propertyValue);\r\n }\r\n else {\r\n colorExpressionValue = getDefaultColorExpression(fillRule, propertyName);\r\n }\r\n return colorExpressionValue;\r\n }\r\n\r\n function updateMinColor(fillRule: FillRuleDefinition, colorExpressionValue: data.SQExpr) {\r\n if (fillRule.linearGradient2) {\r\n fillRule.linearGradient2.min.color = colorExpressionValue;\r\n }\r\n else if (fillRule.linearGradient3) {\r\n fillRule.linearGradient3.min.color = colorExpressionValue;\r\n }\r\n }\r\n\r\n function updateMidColor(fillRule: FillRuleDefinition, colorExpressionValue: data.SQExpr) {\r\n if (fillRule.linearGradient3) {\r\n fillRule.linearGradient3.mid.color = colorExpressionValue;\r\n }\r\n }\r\n\r\n function updateMaxColor(fillRule: FillRuleDefinition, colorExpressionValue: data.SQExpr) {\r\n if (fillRule.linearGradient2) {\r\n fillRule.linearGradient2.max.color = colorExpressionValue;\r\n }\r\n else if (fillRule.linearGradient3) {\r\n fillRule.linearGradient3.max.color = colorExpressionValue;\r\n }\r\n }\r\n\r\n function updateMinValue(fillRule: FillRuleDefinition, value: data.SQConstantExpr) {\r\n if (fillRule.linearGradient2) {\r\n fillRule.linearGradient2.min.value = value;\r\n }\r\n else if (fillRule.linearGradient3) {\r\n fillRule.linearGradient3.min.value = value;\r\n }\r\n }\r\n\r\n function updateMidValue(fillRule: FillRuleDefinition, value: data.SQConstantExpr) {\r\n if (fillRule.linearGradient3) {\r\n fillRule.linearGradient3.mid.value = value;\r\n }\r\n }\r\n\r\n function updateMaxValue(fillRule: FillRuleDefinition, value: data.SQConstantExpr) {\r\n if (fillRule.linearGradient2) {\r\n fillRule.linearGradient2.max.value = value;\r\n }\r\n else if (fillRule.linearGradient3) {\r\n fillRule.linearGradient3.max.value = value;\r\n }\r\n }\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface VisualBackground {\r\n image?: ImageValue;\r\n transparency?: number;\r\n }\r\n\r\n export module visualBackgroundHelper {\r\n export function getDefaultColor(): string {\r\n return '#FFF';\r\n }\r\n\r\n export function getDefaultTransparency(): number {\r\n return 50;\r\n }\r\n\r\n export function getDefaultShow(): boolean {\r\n return false;\r\n }\r\n\r\n export function getDefaultValues() {\r\n return {\r\n color: getDefaultColor(),\r\n transparency: getDefaultTransparency(),\r\n show: getDefaultShow()\r\n };\r\n }\r\n\r\n export function enumeratePlot(enumeration: ObjectEnumerationBuilder, background: VisualBackground): void {\r\n let transparency = (background && background.transparency);\r\n if (transparency == null)\r\n transparency = getDefaultTransparency();\r\n\r\n let backgroundObject: VisualObjectInstance = {\r\n selector: null,\r\n properties: {\r\n transparency: transparency,\r\n image: (background && background.image)\r\n },\r\n objectName: 'plotArea',\r\n };\r\n\r\n enumeration.pushInstance(backgroundObject);\r\n }\r\n\r\n export function renderBackgroundImage(\r\n background: VisualBackground,\r\n visualElement: JQuery,\r\n layout: Rect): void {\r\n let image = background && background.image;\r\n let imageUrl = image && image.url;\r\n let imageFit = image && image.scaling;\r\n let imageTransparency = background && background.transparency;\r\n let backgroundImage = visualElement.children('.background-image');\r\n\r\n // If there were image and it was removed\r\n if (!imageUrl) {\r\n if (backgroundImage.length !== 0)\r\n backgroundImage.remove();\r\n return;\r\n }\r\n\r\n // If this is the first edit of the image\r\n if (backgroundImage.length === 0) {\r\n // Place the div only if the image exists in order to keep the html as clean as possible\r\n visualElement.prepend('<div class=\"background-image\"></div>');\r\n backgroundImage = visualElement.children('.background-image');\r\n\r\n // the div should be positioned absolute in order to get on top of the sibling svg\r\n backgroundImage.css('position', 'absolute');\r\n }\r\n\r\n // Get the size and margins from the visual for the div will placed inside the plot area\r\n backgroundImage.css({\r\n 'width': layout.width,\r\n 'height': layout.height,\r\n 'margin-left': layout.left,\r\n 'margin-top': layout.top,\r\n });\r\n\r\n // Background properties\r\n backgroundImage.css({\r\n 'background-image': 'url(' + imageUrl + ')',\r\n 'background-repeat': 'no-repeat',\r\n 'opacity': (100 - imageTransparency) / 100,\r\n });\r\n\r\n switch (imageFit) {\r\n // The image will be centered in its initial size\r\n case visuals.imageScalingType.normal: {\r\n backgroundImage.css({\r\n 'background-size': '',\r\n 'background-position': '50% 50%',\r\n });\r\n break;\r\n }\r\n // The image will be streched all over the background\r\n case visuals.imageScalingType.fit: {\r\n backgroundImage.css({\r\n 'background-size': '100% 100%',\r\n 'background-position': '',\r\n });\r\n break;\r\n }\r\n // The image will stretch on the width and the height will scale accordingly\r\n case visuals.imageScalingType.fill: {\r\n backgroundImage.css({\r\n 'background-size': '100%',\r\n 'background-position': '50% 50%',\r\n });\r\n break;\r\n }\r\n default: {\r\n backgroundImage.css({\r\n 'background-size': '',\r\n 'background-position': '50% 50%',\r\n });\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import Selector = powerbi.data.Selector;\r\n\r\n /**\r\n * A helper class for building a VisualObjectInstanceEnumerationObject:\r\n * - Allows call chaining (e.g., builder.pushInstance({...}).pushInstance({...})\r\n * - Allows creating of containers (via pushContainer/popContainer)\r\n */\r\n export class ObjectEnumerationBuilder {\r\n private instances: VisualObjectInstance[];\r\n private containers: VisualObjectInstanceContainer[];\r\n private containerIdx: number;\r\n\r\n public pushInstance(instance: VisualObjectInstance): ObjectEnumerationBuilder {\r\n debug.assertValue(instance, 'instance');\r\n\r\n let instances = this.instances;\r\n if (!instances) {\r\n instances = this.instances = [];\r\n }\r\n\r\n let containerIdx = this.containerIdx;\r\n if (containerIdx != null) {\r\n instance.containerIdx = containerIdx;\r\n }\r\n\r\n // Attempt to merge with an existing item if possible.\r\n for (let existingInstance of instances) {\r\n if (this.canMerge(existingInstance, instance)) {\r\n this.extend(existingInstance, instance, 'properties');\r\n this.extend(existingInstance, instance, 'validValues');\r\n\r\n return this;\r\n }\r\n }\r\n\r\n instances.push(instance);\r\n\r\n return this;\r\n }\r\n\r\n public pushContainer(container: VisualObjectInstanceContainer): ObjectEnumerationBuilder {\r\n debug.assertValue(container, 'container');\r\n\r\n let containers = this.containers;\r\n if (!containers) {\r\n containers = this.containers = [];\r\n }\r\n\r\n let updatedLen = containers.push(container);\r\n this.containerIdx = updatedLen - 1;\r\n\r\n return this;\r\n }\r\n\r\n public popContainer(): ObjectEnumerationBuilder {\r\n this.containerIdx = undefined;\r\n\r\n return this;\r\n }\r\n\r\n public complete(): VisualObjectInstanceEnumerationObject {\r\n if (!this.instances)\r\n return;\r\n\r\n let result: VisualObjectInstanceEnumerationObject = {\r\n instances: this.instances,\r\n };\r\n\r\n let containers = this.containers;\r\n if (containers) {\r\n result.containers = containers;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private canMerge(x: VisualObjectInstance, y: VisualObjectInstance): boolean {\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n\r\n return x.objectName === y.objectName &&\r\n x.containerIdx === y.containerIdx &&\r\n Selector.equals(x.selector, y.selector);\r\n }\r\n\r\n private extend(target: VisualObjectInstance, source: VisualObjectInstance, propertyName: string): void {\r\n debug.assertValue(target, 'target');\r\n debug.assertValue(source, 'source');\r\n debug.assertValue(propertyName, 'propertyName');\r\n\r\n let sourceValues = source[propertyName];\r\n if (!sourceValues)\r\n return;\r\n\r\n let targetValues = target[propertyName];\r\n if (!targetValues)\r\n targetValues = target[propertyName] = {};\r\n\r\n for (let valuePropertyName in sourceValues) {\r\n if (targetValues[valuePropertyName]) {\r\n // Properties have first-writer-wins semantics.\r\n continue;\r\n }\r\n\r\n targetValues[valuePropertyName] = sourceValues[valuePropertyName];\r\n }\r\n }\r\n\r\n public static merge(x: VisualObjectInstanceEnumeration, y: VisualObjectInstanceEnumeration): VisualObjectInstanceEnumerationObject {\r\n let xNormalized = ObjectEnumerationBuilder.normalize(x);\r\n let yNormalized = ObjectEnumerationBuilder.normalize(y);\r\n\r\n if (!xNormalized || !yNormalized)\r\n return xNormalized || yNormalized;\r\n\r\n debug.assertValue(xNormalized, 'xNormalized');\r\n debug.assertValue(yNormalized, 'yNormalized');\r\n\r\n let xCategoryCount = xNormalized.containers ? xNormalized.containers.length : 0;\r\n\r\n for (let yInstance of yNormalized.instances) {\r\n xNormalized.instances.push(yInstance);\r\n\r\n if (yInstance.containerIdx != null)\r\n yInstance.containerIdx += xCategoryCount;\r\n }\r\n\r\n let yContainers = yNormalized.containers;\r\n if (!_.isEmpty(yContainers)) {\r\n if (xNormalized.containers)\r\n Array.prototype.push.apply(xNormalized.containers, yContainers);\r\n else\r\n xNormalized.containers = yContainers;\r\n }\r\n\r\n return xNormalized;\r\n }\r\n\r\n public static normalize(x: VisualObjectInstanceEnumeration): VisualObjectInstanceEnumerationObject {\r\n debug.assertAnyValue(x, 'x');\r\n\r\n if (_.isArray(x)) {\r\n return { instances: <VisualObjectInstance[]>x };\r\n }\r\n\r\n return <VisualObjectInstanceEnumerationObject>x;\r\n }\r\n\r\n public static getContainerForInstance(enumeration: VisualObjectInstanceEnumerationObject, instance: VisualObjectInstance): VisualObjectInstanceContainer {\r\n debug.assertValue(enumeration, \"enumeration\");\r\n debug.assertValue(instance, \"instance\");\r\n debug.assertValue(enumeration.containers, \"containers\");\r\n debug.assert(enumeration.containers.length > instance.containerIdx, \"no container found in containers collection\");\r\n\r\n return enumeration.containers[instance.containerIdx];\r\n }\r\n \r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n /** Helper class for Visual border styles */\r\n export module VisualBorderUtil {\r\n /**\r\n * Gets The Boder Width string (e.g. 0px 1px 2px 3px)\r\n * @param {OutlineType} string Type of the Outline, one of Visuals.outline.<XX> const strings\r\n * @param {number} outlineWeight Weight of the outline in pixels\r\n * @returns String representing the Border Width\r\n */\r\n export function getBorderWidth(outlineType: string, outlineWeight: number): string {\r\n switch (outlineType) {\r\n case outline.none:\r\n return '0px';\r\n case outline.bottomOnly:\r\n return '0px 0px ' + outlineWeight + 'px 0px';\r\n case outline.topOnly:\r\n return outlineWeight + 'px 0px 0px 0px';\r\n case outline.leftOnly:\r\n return '0px 0px 0px ' + outlineWeight + 'px';\r\n case outline.rightOnly:\r\n return '0px ' + outlineWeight + 'px 0px 0px';\r\n case outline.topBottom:\r\n return outlineWeight + 'px 0px';\r\n case outline.leftRight:\r\n return '0px ' + outlineWeight + 'px';\r\n case outline.frame:\r\n return outlineWeight + 'px';\r\n default:\r\n debug.assertFail('Unexpected OutlineType value: ' + outlineType);\r\n return '0px';\r\n }\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface I2DTransformMatrix {\r\n m00: number;\r\n m01: number;\r\n m02: number;\r\n\r\n m10: number;\r\n m11: number;\r\n m12: number;\r\n // 3rd row not used so we don't declare it\r\n }\r\n\r\n /** Transformation matrix math wrapper */\r\n export class Transform {\r\n\r\n // Fields\r\n private _inverse: Transform;\r\n public matrix: I2DTransformMatrix;\r\n\r\n // Constructor\r\n constructor(m?: I2DTransformMatrix) {\r\n this.matrix = m || {\r\n m00: 1, m01: 0, m02: 0,\r\n m10: 0, m11: 1, m12: 0,\r\n };\r\n }\r\n\r\n // Methods\r\n public applyToPoint(point: IPoint): IPoint {\r\n if (!point) {\r\n return point;\r\n }\r\n let m = this.matrix;\r\n return {\r\n x: m.m00 * point.x + m.m01 * point.y + m.m02,\r\n y: m.m10 * point.x + m.m11 * point.y + m.m12,\r\n };\r\n }\r\n\r\n public applyToRect(rect: Rect): IRect {\r\n if (!rect) {\r\n return rect;\r\n }\r\n\r\n let x0 = rect.left;\r\n let y0 = rect.top;\r\n\r\n let m = this.matrix;\r\n let isScaled = m.m00 !== 1 || m.m11 !== 1;\r\n let isRotated = m.m01 !== 0 || m.m10 !== 0;\r\n if (!isRotated && !isScaled) {\r\n // Optimize for the translation only case\r\n return { left: x0 + m.m02, top: y0 + m.m12, width: rect.width, height: rect.height };\r\n }\r\n\r\n let x1 = rect.left + rect.width;\r\n let y1 = rect.top + rect.height;\r\n\r\n let minX: number;\r\n let maxX: number;\r\n let minY: number;\r\n let maxY: number;\r\n\r\n if (isRotated) {\r\n let p0x = m.m00 * x0 + m.m01 * y0 + m.m02;\r\n let p0y = m.m10 * x0 + m.m11 * y0 + m.m12;\r\n let p1x = m.m00 * x0 + m.m01 * y1 + m.m02;\r\n let p1y = m.m10 * x0 + m.m11 * y1 + m.m12;\r\n let p2x = m.m00 * x1 + m.m01 * y0 + m.m02;\r\n let p2y = m.m10 * x1 + m.m11 * y0 + m.m12;\r\n let p3x = m.m00 * x1 + m.m01 * y1 + m.m02;\r\n let p3y = m.m10 * x1 + m.m11 * y1 + m.m12;\r\n minX = Math.min(p0x, p1x, p2x, p3x);\r\n maxX = Math.max(p0x, p1x, p2x, p3x);\r\n minY = Math.min(p0y, p1y, p2y, p3y);\r\n maxY = Math.max(p0y, p1y, p2y, p3y);\r\n } else {\r\n let p0x = m.m00 * x0 + m.m02;\r\n let p0y = m.m11 * y0 + m.m12;\r\n let p3x = m.m00 * x1 + m.m02;\r\n let p3y = m.m11 * y1 + m.m12;\r\n minX = Math.min(p0x, p3x);\r\n maxX = Math.max(p0x, p3x);\r\n minY = Math.min(p0y, p3y);\r\n maxY = Math.max(p0y, p3y);\r\n }\r\n\r\n return { left: minX, top: minY, width: maxX - minX, height: maxY - minY };\r\n }\r\n\r\n public translate(xOffset: number, yOffset: number): void {\r\n if (xOffset !== 0 || yOffset !== 0) {\r\n let m = createTranslateMatrix(xOffset, yOffset);\r\n this.matrix = multiplyMatrices(this.matrix, m);\r\n this._inverse = null;\r\n }\r\n }\r\n\r\n public scale(xScale: number, yScale: number): void {\r\n if (xScale !== 1 || yScale !== 1) {\r\n let m = createScaleMatrix(xScale, yScale);\r\n this.matrix = multiplyMatrices(this.matrix, m);\r\n this._inverse = null;\r\n }\r\n }\r\n\r\n public rotate(angleInRadians: number): void {\r\n if (angleInRadians !== 0) {\r\n let m = createRotationMatrix(angleInRadians);\r\n this.matrix = multiplyMatrices(this.matrix, m);\r\n this._inverse = null;\r\n }\r\n }\r\n\r\n public add(other: Transform): void {\r\n if (other) {\r\n this.matrix = multiplyMatrices(this.matrix, other.matrix);\r\n this._inverse = null;\r\n }\r\n }\r\n\r\n public getInverse(): Transform {\r\n if (!this._inverse) {\r\n this._inverse = new Transform(createInverseMatrix(this.matrix));\r\n }\r\n return this._inverse;\r\n }\r\n }\r\n\r\n export function createTranslateMatrix(xOffset: number, yOffset: number): I2DTransformMatrix {\r\n return {\r\n m00: 1, m01: 0, m02: xOffset,\r\n m10: 0, m11: 1, m12: yOffset,\r\n };\r\n }\r\n\r\n export function createScaleMatrix(xScale: number, yScale: number): I2DTransformMatrix {\r\n return {\r\n m00: xScale, m01: 0, m02: 0,\r\n m10: 0, m11: yScale, m12: 0\r\n };\r\n }\r\n\r\n export function createRotationMatrix(angleInRads: number): I2DTransformMatrix {\r\n let a = angleInRads;\r\n let sinA = Math.sin(a);\r\n let cosA = Math.cos(a);\r\n return {\r\n m00: cosA, m01: -sinA, m02: 0,\r\n m10: sinA, m11: cosA, m12: 0,\r\n };\r\n }\r\n\r\n export function createInverseMatrix(m: I2DTransformMatrix): I2DTransformMatrix {\r\n let determinant = m.m00 * m.m11 - m.m01 * m.m10;\r\n let invdet = 1 / determinant;\r\n return {\r\n m00: m.m11 * invdet,\r\n m01: - m.m01 * invdet,\r\n m02: (m.m01 * m.m12 - m.m02 * m.m11) * invdet,\r\n\r\n m10: -m.m10 * invdet,\r\n m11: m.m00 * invdet,\r\n m12: - (m.m00 * m.m12 - m.m10 * m.m02) * invdet\r\n };\r\n }\r\n\r\n function multiplyMatrices(a: I2DTransformMatrix, b: I2DTransformMatrix): I2DTransformMatrix {\r\n return {\r\n m00: a.m00 * b.m00 + a.m01 * b.m10,\r\n m01: a.m00 * b.m01 + a.m01 * b.m11,\r\n m02: a.m00 * b.m02 + a.m01 * b.m12 + a.m02,\r\n m10: a.m10 * b.m00 + a.m11 * b.m10,\r\n m11: a.m10 * b.m01 + a.m11 * b.m11,\r\n m12: a.m10 * b.m02 + a.m11 * b.m12 + a.m12,\r\n };\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import Color = jsCommon.Color;\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface TrendLine {\r\n points: IPoint[];\r\n show: boolean;\r\n lineColor: Fill;\r\n transparency: number;\r\n style: string;\r\n combineSeries: boolean;\r\n useHighlightValues: boolean;\r\n y2Axis: boolean;\r\n }\r\n\r\n export module TrendLineHelper {\r\n const trendLinePropertyNames = {\r\n show: 'show',\r\n lineColor: 'lineColor',\r\n transparency: 'transparency',\r\n style: 'style',\r\n combineSeries: 'combineSeries',\r\n useHighlightValues: 'useHighlightValues',\r\n };\r\n const trendObjectName = 'trend';\r\n\r\n export const defaults = {\r\n lineColor: <Fill>{ solid: { color: '#000' } },\r\n lineStyle: lineStyle.dashed,\r\n transparency: 0,\r\n combineSeries: true,\r\n useHighlightValues: true,\r\n };\r\n const TrendLineClassSelector: jsCommon.CssConstants.ClassAndSelector = jsCommon.CssConstants.createClassAndSelector('trend-line');\r\n const TrendLineLayerClassSelector: jsCommon.CssConstants.ClassAndSelector = jsCommon.CssConstants.createClassAndSelector('trend-line-layer');\r\n\r\n export function enumerateObjectInstances(enumeration: ObjectEnumerationBuilder, trendLines: TrendLine[]): void {\r\n debug.assertValue(enumeration, 'enumeration');\r\n\r\n if (_.isEmpty(trendLines)) {\r\n enumeration.pushInstance({\r\n selector: null,\r\n properties: {\r\n show: false,\r\n lineColor: defaults.lineColor,\r\n transparency: defaults.transparency,\r\n style: defaults.lineStyle,\r\n combineSeries: defaults.combineSeries,\r\n },\r\n objectName: trendObjectName,\r\n });\r\n\r\n return;\r\n }\r\n\r\n let trendLine = trendLines[0];\r\n let properties: { [propertyName: string]: DataViewPropertyValue } = {};\r\n properties['show'] = trendLine.show;\r\n\r\n if (trendLine.combineSeries)\r\n properties['lineColor'] = trendLine.lineColor;\r\n\r\n properties['transparency'] = trendLine.transparency;\r\n properties['style'] = trendLine.style;\r\n properties['combineSeries'] = trendLine.combineSeries;\r\n properties['useHighlightValues'] = trendLine.useHighlightValues;\r\n\r\n enumeration.pushInstance({\r\n selector: null,\r\n properties: properties,\r\n objectName: trendObjectName,\r\n });\r\n }\r\n\r\n export function isDataViewForRegression(dataView: DataView): boolean {\r\n return DataRoleHelper.hasRoleInDataView(dataView, 'regression.X');\r\n }\r\n\r\n export function readDataView(dataView: DataView, sourceDataView: DataView, y2: boolean, colors: IDataColorPalette): TrendLine[] {\r\n if (!dataView || !dataView.categorical)\r\n return;\r\n\r\n let categorical = dataView.categorical;\r\n if (_.isEmpty(categorical.categories) || _.isEmpty(categorical.values))\r\n return;\r\n\r\n let categories = categorical.categories[0].values;\r\n let groups = categorical.values.grouped();\r\n if (!categories || !groups)\r\n return;\r\n\r\n let trendProperties = DataViewObjects.getObject(dataView.metadata.objects, trendObjectName, {});\r\n let show = DataViewObject.getValue<boolean>(trendProperties, trendLinePropertyNames.show, false);\r\n let lineColor = DataViewObject.getValue<Fill>(trendProperties, trendLinePropertyNames.lineColor);\r\n let transparency = DataViewObject.getValue<number>(trendProperties, trendLinePropertyNames.transparency, defaults.transparency);\r\n let style = DataViewObject.getValue<string>(trendProperties, trendLinePropertyNames.style, defaults.lineStyle);\r\n let combineSeries = DataViewObject.getValue<boolean>(trendProperties, trendLinePropertyNames.combineSeries, defaults.combineSeries);\r\n let useHighlightValues = DataViewObject.getValue<boolean>(trendProperties, trendLinePropertyNames.useHighlightValues, defaults.useHighlightValues);\r\n\r\n // Trend lines generated by Insights will be putting line color here, we should convert the Insights code to create\r\n // \"trend\" objects like above and write the upgrade code to handle pinned tiles with trend lines before removing any feature switch.\r\n let legacyColor = DataViewObjects.getValue<Fill>(categorical.values[0].source.objects, lineChartProps.dataPoint.fill);\r\n if (legacyColor)\r\n lineColor = legacyColor;\r\n\r\n let objects = sourceDataView.metadata.objects;\r\n let defaultColor = DataViewObjects.getFillColor(objects, { objectName: 'dataPoint', propertyName: 'defaultColor' });\r\n let colorHelper = new ColorHelper(colors, { objectName: 'dataPoint', propertyName: 'fill' }, defaultColor);\r\n\r\n let trendLines: TrendLine[] = [];\r\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\r\n let group = groups[groupIndex];\r\n\r\n let points: IPoint[] = [];\r\n for (let i = 0; i < categories.length; i++) {\r\n let x = AxisHelper.normalizeNonFiniteNumber(categories[i]);\r\n\r\n // There is a assumption here that the group only has 1 set of values in it. Once we add more things like confidence bands,\r\n // this assumption will not be true. This assumption comes from the way dataViewRegresion generates the dataView\r\n let valueColumn = group.values[0];\r\n\r\n let values: any[];\r\n if (useHighlightValues && valueColumn.highlights) {\r\n values = valueColumn.highlights;\r\n }\r\n else {\r\n values = valueColumn.values;\r\n }\r\n let y = AxisHelper.normalizeNonFiniteNumber(values[i]);\r\n\r\n if (x != null && y != null) {\r\n points.push({\r\n x: x,\r\n y: y,\r\n });\r\n }\r\n }\r\n\r\n let seriesLineColor: Fill;\r\n if (combineSeries) {\r\n seriesLineColor = lineColor || defaults.lineColor;\r\n }\r\n else {\r\n // TODO: This should likely be delegated to the layer which knows how to choose the correct color for any given situation.\r\n if (sourceDataView.categorical.values.source) {\r\n // Dynamic series\r\n let sourceGroups = sourceDataView.categorical.values.grouped();\r\n let color = colorHelper.getColorForSeriesValue(sourceGroups[groupIndex].objects, sourceDataView.categorical.values.identityFields, group.name);\r\n color = darkenTrendLineColor(color);\r\n seriesLineColor = { solid: { color: color } };\r\n }\r\n else {\r\n // Static series\r\n let matchingMeasure = sourceDataView.categorical.values[groupIndex];\r\n let color = colorHelper.getColorForMeasure(matchingMeasure.source.objects, group.name);\r\n color = darkenTrendLineColor(color);\r\n seriesLineColor = { solid: { color: color } };\r\n }\r\n }\r\n\r\n trendLines.push({\r\n points: points,\r\n show: show,\r\n lineColor: seriesLineColor,\r\n transparency: transparency,\r\n style: style,\r\n combineSeries: combineSeries,\r\n useHighlightValues: useHighlightValues,\r\n y2Axis: y2,\r\n });\r\n }\r\n return trendLines;\r\n }\r\n\r\n export function darkenTrendLineColor(color: string): string {\r\n let rgb = Color.parseColorString(color);\r\n rgb = Color.darken(rgb, 20);\r\n return Color.rgbString(rgb);\r\n }\r\n\r\n export function render(trendLines: TrendLine[], graphicsContext: D3.Selection, axes: CartesianAxisProperties, viewport: IViewport): void {\r\n let layer = graphicsContext.select(TrendLineLayerClassSelector.selector);\r\n if (layer.empty()) {\r\n layer = graphicsContext.append('svg').classed(TrendLineLayerClassSelector.class, true);\r\n }\r\n\r\n layer.attr({\r\n height: viewport.height,\r\n width: viewport.width\r\n });\r\n\r\n let lines = layer.selectAll(TrendLineClassSelector.selector).data(trendLines || []);\r\n lines.enter().append('path').classed(TrendLineClassSelector.class, true);\r\n\r\n lines\r\n .attr('d', (d: TrendLine) => {\r\n let xScale = axes.x.scale;\r\n let yScale = (d.y2Axis && axes.y2) ? axes.y2.scale : axes.y1.scale;\r\n\r\n let pathGen = d3.svg.line()\r\n .x((point: IPoint) => xScale(point.x))\r\n .y((point: IPoint) => yScale(point.y));\r\n\r\n return pathGen(_.filter(d.points, (point) => point.x != null && point.y != null));\r\n });\r\n\r\n lines.each(function (d: TrendLine) {\r\n let line = d3.select(this);\r\n let style: any = {};\r\n\r\n style.stroke = d.lineColor.solid.color;\r\n\r\n if (d.transparency != null) {\r\n style['stroke-opacity'] = (100 - d.transparency) / 100;\r\n }\r\n\r\n if (d.style === lineStyle.dashed) {\r\n style['stroke-dasharray'] = \"5, 5\";\r\n }\r\n else if (d.style === lineStyle.dotted) {\r\n style['stroke-dasharray'] = \"1, 5\";\r\n style['stroke-linecap'] = \"round\";\r\n }\r\n else if (d.style === lineStyle.solid) {\r\n style['stroke-dasharray'] = null;\r\n style['stroke-linecap'] = null;\r\n }\r\n\r\n line.style(style);\r\n });\r\n\r\n lines.exit().remove();\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module visibilityHelper {\r\n /** Helper method that uses jQuery :visible selector to determine if visual is visible.\r\n Elements are considered visible if they consume space in the document. Visible elements have a width or height that is greater than zero.\r\n Elements with visibility: hidden or opacity: 0 are considered visible, since they still consume space in the layout.\r\n */\r\n export function partiallyVisible(element: JQuery): boolean {\r\n return element.is(\":visible\");\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import Selector = data.Selector;\r\n\r\n export module VisualObjectRepetition {\r\n /** Determines whether two repetitions are equal. */\r\n export function equals(x: VisualObjectRepetition, y: VisualObjectRepetition): boolean {\r\n // Normalize falsy to null\r\n x = x || null;\r\n y = y || null;\r\n\r\n if (x === y)\r\n return true;\r\n\r\n if (!x !== !y)\r\n return false;\r\n\r\n debug.assertValue(x, 'x');\r\n debug.assertValue(y, 'y');\r\n\r\n if (!Selector.equals(x.selector, y.selector))\r\n return false;\r\n\r\n return _.isEqual(x.objects, y.objects);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import SemanticFilter = powerbi.data.SemanticFilter;\r\n import UrlUtils = jsCommon.UrlUtils;\r\n\r\n /** Helper module for converting a DataView into SlicerData. */\r\n export module DataConversion {\r\n export function convert(dataView: DataView, localizedSelectAllText: string, interactivityService: IInteractivityService | ISelectionHandler, hostServices: IVisualHostServices): SlicerData {\r\n debug.assertValue(hostServices, 'hostServices');\r\n if (!dataView || !dataView.categorical || _.isEmpty(dataView.categorical.categories))\r\n return;\r\n\r\n let identityFields = dataView.categorical.categories[0].identityFields;\r\n\r\n if (!identityFields)\r\n return;\r\n\r\n let filter: SemanticFilter = <SemanticFilter>(\r\n dataView.metadata &&\r\n dataView.metadata.objects &&\r\n DataViewObjects.getValue(dataView.metadata.objects, visuals.slicerProps.filterPropertyIdentifier));\r\n\r\n let analyzer = hostServices.analyzeFilter({\r\n dataView: dataView,\r\n defaultValuePropertyId: slicerProps.defaultValue,\r\n filter: filter,\r\n fieldSQExprs: identityFields\r\n });\r\n if (!analyzer)\r\n return;\r\n \r\n let analyzedSemanticFilter = <SemanticFilter>analyzer.filter;\r\n if (analyzedSemanticFilter && !SemanticFilter.isSameFilter(analyzedSemanticFilter, filter)) {\r\n (<ISelectionHandler>interactivityService).handleClearSelection();\r\n let filterPropertyIdentifier = slicerProps.filterPropertyIdentifier;\r\n let properties: { [propertyName: string]: DataViewPropertyValue } = {};\r\n properties[filterPropertyIdentifier.propertyName] = analyzer.filter;\r\n let instance = {\r\n objectName: filterPropertyIdentifier.objectName,\r\n selector: undefined,\r\n properties: properties\r\n };\r\n\r\n let changes: VisualObjectInstancesToPersist = {\r\n merge: [instance]\r\n };\r\n hostServices.persistProperties(changes);\r\n }\r\n\r\n let slicerData = getSlicerData(analyzer, dataView.metadata, dataView.categorical, localizedSelectAllText, <IInteractivityService>interactivityService, hostServices);\r\n return slicerData;\r\n }\r\n\r\n function getSlicerData(\r\n analyzer: AnalyzedFilter,\r\n dataViewMetadata: DataViewMetadata,\r\n categorical: DataViewCategorical,\r\n localizedSelectAllText: string, interactivityService: IInteractivityService, hostServices: IVisualHostServices): SlicerData {\r\n let isInvertedSelectionMode: boolean = interactivityService && interactivityService.isSelectionModeInverted();\r\n let selectedScopeIds = analyzer.selectedIdentities;\r\n\r\n let hasSelectionOverride = !_.isEmpty(selectedScopeIds) || isInvertedSelectionMode === true;\r\n if (!isInvertedSelectionMode && analyzer.filter)\r\n isInvertedSelectionMode = analyzer.isNotFilter;\r\n\r\n if (interactivityService) {\r\n // To indicate whether the selection is Not selected items\r\n interactivityService.setSelectionModeInverted(isInvertedSelectionMode);\r\n\r\n // defaultValueMode will be used when determine show/hide clear button.\r\n interactivityService.setDefaultValueMode(SemanticFilter.isDefaultFilter(<SemanticFilter>analyzer.filter));\r\n }\r\n\r\n let category = categorical.categories[0];\r\n let categoryValuesLen: number = category && category.values ? category.values.length : 0;\r\n let slicerDataPoints: SlicerDataPoint[] = [];\r\n let formatString = valueFormatter.getFormatString(category.source, slicerProps.formatString);\r\n let numOfSelected: number = 0;\r\n let valueCounts = categorical.values && categorical.values[0] && categorical.values[0].values;\r\n if (valueCounts && _.isEmpty(valueCounts))\r\n valueCounts = undefined;\r\n\r\n debug.assert(!valueCounts || valueCounts.length === categoryValuesLen, \"valueCounts doesn't match values\");\r\n let isImageData = dataViewMetadata &&\r\n !_.isEmpty(dataViewMetadata.columns) && converterHelper.isImageUrlColumn(dataViewMetadata.columns[0]);\r\n let displayNameIdentityPairs: DisplayNameIdentityPair[] = [];\r\n for (let i = 0; i < categoryValuesLen; i++) {\r\n let scopeId = category.identity && category.identity[i];\r\n let value = category.values && category.values[i];\r\n let count = valueCounts && valueCounts[i];\r\n\r\n let isRetained = hasSelectionOverride ? SlicerUtil.tryRemoveValueFromRetainedList(scopeId, selectedScopeIds) : false;\r\n let label: string = valueFormatter.format(value, formatString);\r\n let isImage = isImageData === true && UrlUtils.isValidImageUrl(label);\r\n let slicerData: SlicerDataPoint = {\r\n value: label,\r\n tooltip: label,\r\n identity: SelectionId.createWithId(scopeId),\r\n selected: isRetained,\r\n count: <number>count,\r\n isImage: isImage,\r\n };\r\n\r\n if (isRetained) {\r\n let displayNameIdentityPair: DisplayNameIdentityPair = {\r\n displayName: label,\r\n identity: scopeId\r\n };\r\n displayNameIdentityPairs.push(displayNameIdentityPair);\r\n }\r\n\r\n slicerDataPoints.push(slicerData);\r\n if (slicerData.selected)\r\n numOfSelected++;\r\n }\r\n\r\n if (!_.isEmpty(displayNameIdentityPairs))\r\n hostServices.setIdentityDisplayNames(displayNameIdentityPairs);\r\n\r\n // Add retained values that are not in the returned dataview to the value list.\r\n if (hasSelectionOverride && !_.isEmpty(selectedScopeIds)) {\r\n \r\n let displayNamesIdentityPairs = hostServices.getIdentityDisplayNames(selectedScopeIds);\r\n if (!_.isEmpty(displayNamesIdentityPairs)) {\r\n for (let pair of displayNamesIdentityPairs) {\r\n // When there is no valueCounts, set count to be undefined, otherwise use 0 as the count for retained values\r\n let slicerData: SlicerDataPoint = {\r\n value: pair.displayName,\r\n tooltip: pair.displayName,\r\n identity: SelectionId.createWithId(pair.identity),\r\n selected: true,\r\n count: valueCounts != null ? 0 : undefined,\r\n };\r\n\r\n slicerDataPoints.push(slicerData);\r\n numOfSelected++;\r\n }\r\n }\r\n }\r\n\r\n let defaultSettings = createDefaultSettings(dataViewMetadata);\r\n if (defaultSettings.selection.selectAllCheckboxEnabled) {\r\n //If selectAllCheckboxEnabled, and all the items are selected and there is no more data to request, then unselect all and toggle the invertedSelectionMode\r\n if (numOfSelected > 0 && !dataViewMetadata.segment && numOfSelected === slicerDataPoints.length) {\r\n isInvertedSelectionMode = !isInvertedSelectionMode;\r\n interactivityService.setSelectionModeInverted(isInvertedSelectionMode);\r\n for (let item of slicerDataPoints) {\r\n item.selected = false;\r\n }\r\n hasSelectionOverride = false;\r\n numOfSelected = 0;\r\n }\r\n\r\n slicerDataPoints.unshift({\r\n value: localizedSelectAllText,\r\n tooltip: localizedSelectAllText,\r\n identity: SelectionId.createWithMeasure(localizedSelectAllText),\r\n selected: !!isInvertedSelectionMode && numOfSelected === 0,\r\n isSelectAllDataPoint: true,\r\n count: undefined,\r\n });\r\n }\r\n\r\n let slicerData: SlicerData = {\r\n categorySourceName: category.source.displayName,\r\n slicerSettings: defaultSettings,\r\n slicerDataPoints: slicerDataPoints,\r\n hasSelectionOverride: hasSelectionOverride,\r\n defaultValue: analyzer.defaultValue,\r\n };\r\n\r\n return slicerData;\r\n }\r\n\r\n function createDefaultSettings(dataViewMetadata: DataViewMetadata): SlicerSettings {\r\n let defaultSettings = Slicer.DefaultStyleProperties();\r\n let objects = dataViewMetadata.objects;\r\n let forceSingleSelect = dataViewMetadata.columns && _.some(dataViewMetadata.columns, (column) => column.discourageAggregationAcrossGroups);\r\n\r\n if (objects) {\r\n defaultSettings.general.outlineColor = DataViewObjects.getFillColor(objects, slicerProps.general.outlineColor, defaultSettings.general.outlineColor);\r\n defaultSettings.general.outlineWeight = DataViewObjects.getValue<number>(objects, slicerProps.general.outlineWeight, defaultSettings.general.outlineWeight);\r\n defaultSettings.general.orientation = DataViewObjects.getValue<slicerOrientation.Orientation>(objects, slicerProps.general.orientation, defaultSettings.general.orientation);\r\n\r\n defaultSettings.header.show = DataViewObjects.getValue<boolean>(objects, slicerProps.header.show, defaultSettings.header.show);\r\n defaultSettings.header.fontColor = DataViewObjects.getFillColor(objects, slicerProps.header.fontColor, defaultSettings.header.fontColor);\r\n let headerBackground = DataViewObjects.getFillColor(objects, slicerProps.header.background);\r\n if (headerBackground)\r\n defaultSettings.header.background = headerBackground;\r\n defaultSettings.header.outline = DataViewObjects.getValue<string>(objects, slicerProps.header.outline, defaultSettings.header.outline);\r\n defaultSettings.header.textSize = DataViewObjects.getValue<number>(objects, slicerProps.header.textSize, defaultSettings.header.textSize);\r\n\r\n defaultSettings.slicerText.color = DataViewObjects.getFillColor(objects, slicerProps.items.fontColor, defaultSettings.slicerText.color);\r\n let textBackground = DataViewObjects.getFillColor(objects, slicerProps.items.background);\r\n if (textBackground)\r\n defaultSettings.slicerText.background = textBackground;\r\n\r\n defaultSettings.slicerText.outline = DataViewObjects.getValue<string>(objects, slicerProps.items.outline, defaultSettings.slicerText.outline);\r\n defaultSettings.slicerText.textSize = DataViewObjects.getValue<number>(objects, slicerProps.items.textSize, defaultSettings.slicerText.textSize);\r\n\r\n defaultSettings.selection.selectAllCheckboxEnabled = !forceSingleSelect && DataViewObjects.getValue<boolean>(objects, slicerProps.selection.selectAllCheckboxEnabled, defaultSettings.selection.selectAllCheckboxEnabled);\r\n defaultSettings.selection.singleSelect = forceSingleSelect || DataViewObjects.getValue<boolean>(objects, slicerProps.selection.singleSelect, defaultSettings.selection.singleSelect);\r\n }\r\n\r\n return defaultSettings;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n import shapes = powerbi.visuals.shapes;\r\n import IRect = powerbi.visuals.IRect;\r\n import IThickness = visuals.shapes.IThickness;\r\n\r\n /** Defines possible content positions. */\r\n export const enum ContentPositions {\r\n\r\n /** Content position is not defined. */\r\n None = 0,\r\n\r\n /** Content aligned top left. */\r\n TopLeft = 1,\r\n\r\n /** Content aligned top center. */\r\n TopCenter = 2,\r\n\r\n /** Content aligned top right. */\r\n TopRight = 4,\r\n\r\n /** Content aligned middle left. */\r\n MiddleLeft = 8,\r\n\r\n /** Content aligned middle center. */\r\n MiddleCenter = 16,\r\n\r\n /** Content aligned middle right. */\r\n MiddleRight = 32,\r\n\r\n /** Content aligned bottom left. */\r\n BottomLeft = 64,\r\n\r\n /** Content aligned bottom center. */\r\n BottomCenter = 128,\r\n\r\n /** Content aligned bottom right. */\r\n BottomRight = 256,\r\n\r\n /** Content is placed inside the bounding rectangle in the center. */\r\n InsideCenter = 512,\r\n\r\n /** Content is placed inside the bounding rectangle at the base. */\r\n InsideBase = 1024,\r\n\r\n /** Content is placed inside the bounding rectangle at the end. */\r\n InsideEnd = 2048,\r\n\r\n /** Content is placed outside the bounding rectangle at the base. */\r\n OutsideBase = 4096,\r\n\r\n /** Content is placed outside the bounding rectangle at the end. */\r\n OutsideEnd = 8192,\r\n\r\n /** Content supports all possible positions. */\r\n All =\r\n TopLeft |\r\n TopCenter |\r\n TopRight |\r\n MiddleLeft |\r\n MiddleCenter |\r\n MiddleRight |\r\n BottomLeft |\r\n BottomCenter |\r\n BottomRight |\r\n InsideCenter |\r\n InsideBase |\r\n InsideEnd |\r\n OutsideBase |\r\n OutsideEnd,\r\n }\r\n\r\n /**\r\n * Rectangle orientation. Rectangle orientation is used to define vertical or horizontal orientation \r\n * and starting/ending side of the rectangle.\r\n */\r\n export enum RectOrientation {\r\n /** Rectangle with no specific orientation. */\r\n None,\r\n\r\n /** Vertical rectangle with base at the bottom. */\r\n VerticalBottomTop,\r\n\r\n /** Vertical rectangle with base at the top. */\r\n VerticalTopBottom,\r\n\r\n /** Horizontal rectangle with base at the left. */\r\n HorizontalLeftRight,\r\n\r\n /** Horizontal rectangle with base at the right. */\r\n HorizontalRightLeft,\r\n }\r\n\r\n /**\r\n * Defines if panel elements are allowed to be positioned \r\n * outside of the panel boundaries.\r\n */\r\n export enum OutsidePlacement {\r\n /** Elements can be positioned outside of the panel. */\r\n Allowed,\r\n\r\n /** Elements can not be positioned outside of the panel. */\r\n Disallowed,\r\n\r\n /** Elements can be partially outside of the panel. */\r\n Partial\r\n }\r\n\r\n /**\r\n * Defines an interface for information needed for default label positioning. Used in DataLabelsPanel.\r\n * Note the question marks: none of the elements are mandatory.\r\n */\r\n export interface IDataLabelSettings {\r\n /** Distance from the anchor point. */\r\n anchorMargin?: number;\r\n\r\n /** Orientation of the anchor rectangle. */\r\n anchorRectOrientation?: RectOrientation;\r\n\r\n /** Preferable position for the label. */\r\n contentPosition?: ContentPositions;\r\n\r\n /** Defines the rules if the elements can be positioned outside panel bounds. */\r\n outsidePlacement?: OutsidePlacement;\r\n\r\n /** Defines the valid positions if repositionOverlapped is true. */\r\n validContentPositions?: ContentPositions;\r\n\r\n /** Defines maximum moving distance to reposition an element. */\r\n minimumMovingDistance?: number;\r\n\r\n /** Defines minimum moving distance to reposition an element. */\r\n maximumMovingDistance?: number;\r\n\r\n /** Opacity effect of the label. Use it for dimming. */\r\n opacity?: number;\r\n }\r\n\r\n /**\r\n * Defines an interface for information needed for label positioning. \r\n * None of the elements are mandatory, but at least anchorPoint OR anchorRect is needed.\r\n */\r\n export interface IDataLabelInfo extends IDataLabelSettings {\r\n\r\n /** The point to which label is anchored. */\r\n anchorPoint?: shapes.IPoint;\r\n\r\n /** The rectangle to which label is anchored. */\r\n anchorRect?: IRect;\r\n\r\n /** Disable label rendering and processing. */\r\n hideLabel?: boolean;\r\n\r\n /**\r\n * Defines the visibility rank. This will not be processed by arrange phase, \r\n * but can be used for preprocessing the hideLabel value.\r\n */\r\n visibilityRank?: number;\r\n\r\n /** Defines the starting offset from AnchorRect. */\r\n offset?: number;\r\n\r\n /** Defines the callout line data. It is calculated and used during processing. */\r\n callout?: { start: shapes.IPoint; end: shapes.IPoint; };\r\n\r\n /** Source of the label. */\r\n source?: any;\r\n\r\n size?: shapes.ISize;\r\n }\r\n\r\n /** Interface for label rendering. */\r\n export interface IDataLabelRenderer {\r\n renderLabelArray(labels: IArrangeGridElementInfo[]): void;\r\n }\r\n\r\n /** Interface used in internal arrange structures. */\r\n export interface IArrangeGridElementInfo {\r\n element: IDataLabelInfo;\r\n rect: IRect;\r\n }\r\n\r\n /**\r\n * Arranges label elements using the anchor point or rectangle. Collisions\r\n * between elements can be automatically detected and as a result elements \r\n * can be repositioned or get hidden.\r\n */\r\n export class DataLabelManager {\r\n\r\n public movingStep: number = 3;\r\n public hideOverlapped: boolean = true;\r\n public static DefaultAnchorMargin: number = 0; // For future use\r\n public static DefaultMaximumMovingDistance: number = 12;\r\n public static DefaultMinimumMovingDistance: number = 3;\r\n public static InflateAmount: number = 5;\r\n\r\n // The global settings for all labels. \r\n // They can be oweridden by each label we add into the panel, because contains same properties.\r\n private defaultDataLabelSettings: IDataLabelSettings = {\r\n anchorMargin: DataLabelManager.DefaultAnchorMargin,\r\n anchorRectOrientation: RectOrientation.None,\r\n contentPosition: ContentPositions.BottomCenter,\r\n outsidePlacement: OutsidePlacement.Disallowed,\r\n maximumMovingDistance: DataLabelManager.DefaultMaximumMovingDistance,\r\n minimumMovingDistance: DataLabelManager.DefaultMinimumMovingDistance,\r\n validContentPositions: ContentPositions.BottomCenter,\r\n opacity: 1\r\n };\r\n\r\n public get defaultSettings(): IDataLabelSettings {\r\n return this.defaultDataLabelSettings;\r\n }\r\n\r\n /** Arranges the lables position and visibility*/\r\n public hideCollidedLabels(viewport: IViewport, data: any[], layout: any, addTransform: boolean = false): powerbi.visuals.LabelEnabledDataPoint[] {\r\n\r\n // Split size into a grid\r\n let arrangeGrid = new DataLabelArrangeGrid(viewport, data, layout);\r\n let filteredData = [];\r\n let transform: shapes.IVector = { x: 0, y: 0 };\r\n\r\n if (addTransform) {\r\n transform.x = viewport.width / 2;\r\n transform.y = viewport.height / 2;\r\n }\r\n\r\n for (let i = 0, len = data.length; i < len; i++) {\r\n\r\n // Filter unwanted data points\r\n if (!layout.filter(data[i]))\r\n continue;\r\n\r\n // Set default values where properties values are undefined\r\n let info = this.getLabelInfo(data[i]);\r\n\r\n info.anchorPoint = {\r\n x: layout.labelLayout.x(data[i]) + transform.x,\r\n y: layout.labelLayout.y(data[i]) + transform.y,\r\n };\r\n\r\n let position: IRect = this.calculateContentPosition(info, info.contentPosition, data[i].size, info.anchorMargin);\r\n\r\n if (DataLabelManager.isValid(position) && !this.hasCollisions(arrangeGrid, info, position, viewport)) {\r\n data[i].labelX = position.left - transform.x;\r\n data[i].labelY = position.top - transform.y;\r\n\r\n // Keep track of all panel elements positions.\r\n arrangeGrid.add(info, position);\r\n\r\n // Save all data points to display\r\n filteredData.push(data[i]);\r\n }\r\n }\r\n\r\n return filteredData;\r\n }\r\n\r\n /**\r\n * Merges the label element info with the panel element info and returns correct label info.\r\n * @param source The label info.\r\n */\r\n public getLabelInfo(source: IDataLabelInfo): IDataLabelInfo {\r\n\r\n let settings = this.defaultDataLabelSettings;\r\n source.anchorMargin = source.anchorMargin !== undefined ? source.anchorMargin : settings.anchorMargin;\r\n source.anchorRectOrientation = source.anchorRectOrientation !== undefined ? source.anchorRectOrientation : settings.anchorRectOrientation;\r\n source.contentPosition = source.contentPosition !== undefined ? source.contentPosition : settings.contentPosition;\r\n source.maximumMovingDistance = source.maximumMovingDistance !== undefined ? source.maximumMovingDistance : settings.maximumMovingDistance;\r\n source.minimumMovingDistance = source.minimumMovingDistance !== undefined ? source.minimumMovingDistance : settings.minimumMovingDistance;\r\n source.outsidePlacement = source.outsidePlacement !== undefined ? source.outsidePlacement : settings.outsidePlacement;\r\n source.validContentPositions = source.validContentPositions !== undefined ? source.validContentPositions : settings.validContentPositions;\r\n source.opacity = source.opacity !== undefined ? source.opacity : settings.opacity;\r\n source.maximumMovingDistance += source.anchorMargin;\r\n return source;\r\n }\r\n\r\n /**\r\n * (Private) Calculates element position using anchor point..\r\n */\r\n private calculateContentPositionFromPoint(anchorPoint: shapes.IPoint, contentPosition: ContentPositions, contentSize: shapes.ISize, offset: number): IRect {\r\n let position: shapes.IPoint = { x: 0, y: 0 };\r\n if (anchorPoint) {\r\n\r\n if (anchorPoint.x !== undefined && isFinite(anchorPoint.x)) {\r\n position.x = anchorPoint.x;\r\n switch (contentPosition) {\r\n // D3 positions the label in the middle by default.\r\n // The algorithem asumed the label was positioned in right so this is why we add/substract half width\r\n case ContentPositions.TopLeft:\r\n case ContentPositions.MiddleLeft:\r\n case ContentPositions.BottomLeft:\r\n position.x -= contentSize.width / 2.0;\r\n break;\r\n\r\n case ContentPositions.TopRight:\r\n case ContentPositions.MiddleRight:\r\n case ContentPositions.BottomRight:\r\n position.x += contentSize.width / 2.0;\r\n break;\r\n }\r\n }\r\n\r\n if (anchorPoint.y !== undefined && isFinite(anchorPoint.y)) {\r\n position.y = anchorPoint.y;\r\n switch (contentPosition) {\r\n case ContentPositions.MiddleLeft:\r\n case ContentPositions.MiddleCenter:\r\n case ContentPositions.MiddleRight:\r\n position.y -= contentSize.height / 2.0;\r\n break;\r\n case ContentPositions.TopRight:\r\n case ContentPositions.TopLeft:\r\n case ContentPositions.TopCenter:\r\n position.y -= contentSize.height;\r\n break;\r\n }\r\n }\r\n\r\n if (offset !== undefined && isFinite(offset)) {\r\n switch (contentPosition) {\r\n case ContentPositions.TopLeft:\r\n position.x -= offset;\r\n position.y -= offset;\r\n break;\r\n case ContentPositions.MiddleLeft:\r\n position.x -= offset;\r\n break;\r\n case ContentPositions.BottomLeft:\r\n position.x -= offset;\r\n position.y += offset;\r\n break;\r\n case ContentPositions.TopCenter:\r\n position.y -= offset;\r\n break;\r\n case ContentPositions.MiddleCenter:\r\n // Offset is not applied\r\n break;\r\n case ContentPositions.BottomCenter:\r\n position.y += offset;\r\n break;\r\n case ContentPositions.TopRight:\r\n position.x += offset;\r\n position.y -= offset;\r\n break;\r\n case ContentPositions.MiddleRight:\r\n position.x += offset;\r\n break;\r\n case ContentPositions.BottomRight:\r\n position.x += offset;\r\n position.y += offset;\r\n break;\r\n default:\r\n debug.assertFail(\"Unsupported content position.\");\r\n break;\r\n }\r\n }\r\n }\r\n return { left: position.x, top: position.y, width: contentSize.width, height: contentSize.height };\r\n }\r\n\r\n /** (Private) Calculates element position using anchor rect. */\r\n private calculateContentPositionFromRect(anchorRect: IRect, anchorRectOrientation: RectOrientation, contentPosition: ContentPositions, contentSize: shapes.ISize, offset: number): IRect {\r\n\r\n switch (contentPosition) {\r\n case ContentPositions.InsideCenter:\r\n return this.handleInsideCenterPosition(anchorRectOrientation, contentSize, anchorRect, offset);\r\n case ContentPositions.InsideEnd:\r\n return this.handleInsideEndPosition(anchorRectOrientation, contentSize, anchorRect, offset);\r\n case ContentPositions.InsideBase:\r\n return this.handleInsideBasePosition(anchorRectOrientation, contentSize, anchorRect, offset);\r\n case ContentPositions.OutsideEnd:\r\n return this.handleOutsideEndPosition(anchorRectOrientation, contentSize, anchorRect, offset);\r\n case ContentPositions.OutsideBase:\r\n return this.handleOutsideBasePosition(anchorRectOrientation, contentSize, anchorRect, offset);\r\n default:\r\n debug.assertFail(\"Unsupported ContentPosition.\");\r\n }\r\n\r\n return { left: 0, top: 0, width: -1, height: -1 };\r\n }\r\n\r\n /** (Private) Calculates element inside center position using anchor rect. */\r\n private handleInsideCenterPosition(anchorRectOrientation: RectOrientation, contentSize: shapes.ISize, anchorRect: IRect, offset: number): IRect {\r\n switch (anchorRectOrientation) {\r\n case RectOrientation.VerticalBottomTop:\r\n case RectOrientation.VerticalTopBottom:\r\n return LocationConverter.middleVertical(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalLeftRight:\r\n case RectOrientation.HorizontalRightLeft:\r\n default:\r\n return LocationConverter.middleHorizontal(contentSize, anchorRect, offset);\r\n }\r\n }\r\n\r\n /** (Private) Calculates element inside end position using anchor rect. */\r\n private handleInsideEndPosition(anchorRectOrientation: RectOrientation, contentSize: shapes.ISize, anchorRect: IRect, offset: number): IRect {\r\n switch (anchorRectOrientation) {\r\n case RectOrientation.VerticalBottomTop:\r\n return LocationConverter.topInside(contentSize, anchorRect, offset);\r\n case RectOrientation.VerticalTopBottom:\r\n return LocationConverter.bottomInside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalRightLeft:\r\n return LocationConverter.leftInside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalLeftRight:\r\n default:\r\n return LocationConverter.rightInside(contentSize, anchorRect, offset);\r\n }\r\n }\r\n\r\n /** (Private) Calculates element inside base position using anchor rect. */\r\n private handleInsideBasePosition(anchorRectOrientation: RectOrientation, contentSize: shapes.ISize, anchorRect: IRect, offset: number): IRect {\r\n switch (anchorRectOrientation) {\r\n case RectOrientation.VerticalBottomTop:\r\n return LocationConverter.bottomInside(contentSize, anchorRect, offset);\r\n case RectOrientation.VerticalTopBottom:\r\n return LocationConverter.topInside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalRightLeft:\r\n return LocationConverter.rightInside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalLeftRight:\r\n default:\r\n return LocationConverter.leftInside(contentSize, anchorRect, offset);\r\n }\r\n }\r\n\r\n /** (Private) Calculates element outside end position using anchor rect. */\r\n private handleOutsideEndPosition(anchorRectOrientation: RectOrientation, contentSize: shapes.ISize, anchorRect: IRect, offset: number): IRect {\r\n switch (anchorRectOrientation) {\r\n case RectOrientation.VerticalBottomTop:\r\n return LocationConverter.topOutside(contentSize, anchorRect, offset);\r\n case RectOrientation.VerticalTopBottom:\r\n return LocationConverter.bottomOutside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalRightLeft:\r\n return LocationConverter.leftOutside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalLeftRight:\r\n default:\r\n return LocationConverter.rightOutside(contentSize, anchorRect, offset);\r\n }\r\n }\r\n\r\n /** (Private) Calculates element outside base position using anchor rect. */\r\n private handleOutsideBasePosition(anchorRectOrientation: RectOrientation, contentSize: shapes.ISize, anchorRect: IRect, offset: number): IRect {\r\n switch (anchorRectOrientation) {\r\n case RectOrientation.VerticalBottomTop:\r\n return LocationConverter.bottomOutside(contentSize, anchorRect, offset);\r\n case RectOrientation.VerticalTopBottom:\r\n return LocationConverter.topOutside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalRightLeft:\r\n return LocationConverter.rightOutside(contentSize, anchorRect, offset);\r\n case RectOrientation.HorizontalLeftRight:\r\n default:\r\n return LocationConverter.leftOutside(contentSize, anchorRect, offset);\r\n }\r\n }\r\n\r\n /** (Private) Calculates element position. */\r\n private calculateContentPosition(anchoredElementInfo: IDataLabelInfo, contentPosition: ContentPositions, contentSize: shapes.ISize, offset: number): IRect {\r\n\r\n if (contentPosition !== ContentPositions.InsideEnd &&\r\n contentPosition !== ContentPositions.InsideCenter &&\r\n contentPosition !== ContentPositions.InsideBase &&\r\n contentPosition !== ContentPositions.OutsideBase &&\r\n contentPosition !== ContentPositions.OutsideEnd) {\r\n // Determine position using anchor point.\r\n return this.calculateContentPositionFromPoint(\r\n anchoredElementInfo.anchorPoint,\r\n contentPosition,\r\n contentSize,\r\n offset);\r\n }\r\n\r\n // Determine position using anchor rectangle.\r\n return this.calculateContentPositionFromRect(\r\n anchoredElementInfo.anchorRect,\r\n anchoredElementInfo.anchorRectOrientation,\r\n contentPosition,\r\n contentSize,\r\n offset);\r\n }\r\n\r\n /** (Private) Check for collisions. */\r\n private hasCollisions(arrangeGrid: DataLabelArrangeGrid, info: IDataLabelInfo, position: IRect, size: shapes.ISize): boolean {\r\n let rect = shapes.Rect;\r\n\r\n if (arrangeGrid.hasConflict(position)) {\r\n return true;\r\n }\r\n // Since we divide the height by 2 we add it back to the top of the view port so labels won't be cut off\r\n let intersection = { left: 0, top: position.height / 2, width: size.width, height: size.height };\r\n intersection = rect.inflate(intersection, { left: DataLabelManager.InflateAmount, top: 0, right: DataLabelManager.InflateAmount, bottom: 0 });\r\n\r\n intersection = rect.intersect(intersection, position);\r\n\r\n if (rect.isEmpty(intersection))\r\n // Empty rectangle means there is a collision\r\n return true;\r\n\r\n let lessWithPrecision = powerbi.Double.lessWithPrecision;\r\n\r\n switch (info.outsidePlacement) {\r\n // D3 positions the label in the middle by default.\r\n // The algorithem asumed the label was positioned in right so this is why we devide by 2 or 4\r\n case OutsidePlacement.Disallowed:\r\n return lessWithPrecision(intersection.width, position.width) ||\r\n lessWithPrecision(intersection.height, position.height / 2);\r\n\r\n case OutsidePlacement.Partial:\r\n return lessWithPrecision(intersection.width, position.width / 2) ||\r\n lessWithPrecision(intersection.height, position.height / 4);\r\n }\r\n return false;\r\n }\r\n\r\n public static isValid(rect: IRect): boolean {\r\n return !shapes.Rect.isEmpty(rect) && (rect.width > 0 && rect.height > 0);\r\n }\r\n }\r\n\r\n /**\r\n * Utility class to speed up the conflict detection by collecting the arranged items in the DataLabelsPanel. \r\n */\r\n export class DataLabelArrangeGrid {\r\n\r\n private grid: IArrangeGridElementInfo[][][] = [];\r\n //size of a grid cell \r\n private cellSize: shapes.ISize;\r\n private rowCount: number;\r\n private colCount: number;\r\n\r\n private static ARRANGEGRID_MIN_COUNT = 1;\r\n private static ARRANGEGRID_MAX_COUNT = 100;\r\n\r\n /**\r\n * Creates new ArrangeGrid.\r\n * @param size The available size\r\n */\r\n constructor(size: shapes.ISize, elements: any[], layout: powerbi.visuals.ILabelLayout) {\r\n if (size.width === 0 || size.height === 0) {\r\n this.cellSize = size;\r\n this.rowCount = this.colCount = 0;\r\n }\r\n\r\n let baseProperties: TextProperties = {\r\n fontFamily: powerbi.visuals.dataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: powerbi.visuals.dataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: powerbi.visuals.dataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n\r\n //sets the cell size to be twice of the Max with and Max height of the elements \r\n this.cellSize = { width: 0, height: 0 };\r\n for (let i = 0, len = elements.length; i < len; i++) {\r\n let child = elements[i];\r\n\r\n // Fill label field\r\n child.labeltext = layout.labelText(child);\r\n\r\n let properties: TextProperties = Prototype.inherit(baseProperties);\r\n properties.text = child.labeltext;\r\n properties.fontSize = (child.data) ? child.data.labelFontSize :\r\n child.labelFontSize ? child.labelFontSize : powerbi.visuals.dataLabelUtils.LabelTextProperties.fontSize;\r\n\r\n child.size = {\r\n width: TextMeasurementService.measureSvgTextWidth(properties),\r\n height: TextMeasurementService.estimateSvgTextHeight(properties),\r\n };\r\n\r\n let w = child.size.width * 2;\r\n let h = child.size.height * 2;\r\n if (w > this.cellSize.width)\r\n this.cellSize.width = w;\r\n if (h > this.cellSize.height)\r\n this.cellSize.height = h;\r\n }\r\n\r\n if (this.cellSize.width === 0)\r\n this.cellSize.width = size.width;\r\n if (this.cellSize.height === 0)\r\n this.cellSize.height = size.height;\r\n\r\n this.colCount = this.getGridRowColCount(this.cellSize.width, size.width, DataLabelArrangeGrid.ARRANGEGRID_MIN_COUNT, DataLabelArrangeGrid.ARRANGEGRID_MAX_COUNT);\r\n this.rowCount = this.getGridRowColCount(this.cellSize.height, size.height, DataLabelArrangeGrid.ARRANGEGRID_MIN_COUNT, DataLabelArrangeGrid.ARRANGEGRID_MAX_COUNT);\r\n this.cellSize.width = size.width / this.colCount;\r\n this.cellSize.height = size.height / this.rowCount;\r\n\r\n let grid = this.grid;\r\n for (let x = 0; x < this.colCount; x++) {\r\n grid[x] = [];\r\n for (let y = 0; y < this.rowCount; y++) {\r\n grid[x][y] = [];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Register a new label element.\r\n * @param element The label element to register.\r\n * @param rect The label element position rectangle.\r\n */\r\n public add(element: IDataLabelInfo, rect: IRect) {\r\n let indexRect = this.getGridIndexRect(rect);\r\n let grid = this.grid;\r\n for (let x = indexRect.left; x < indexRect.right; x++) {\r\n for (let y = indexRect.top; y < indexRect.bottom; y++) {\r\n grid[x][y].push({ element: element, rect: rect });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks for conflict of given rectangle in registered elements.\r\n * @param rect The rectengle to check.\r\n * @return True if conflict is detected.\r\n */\r\n public hasConflict(rect: IRect): boolean {\r\n let indexRect = this.getGridIndexRect(rect);\r\n let grid = this.grid;\r\n let isIntersecting = shapes.Rect.isIntersecting;\r\n\r\n for (let x = indexRect.left; x < indexRect.right; x++) {\r\n for (let y = indexRect.top; y < indexRect.bottom; y++) {\r\n for (let z = 0; z < grid[x][y].length; z++) {\r\n let item = grid[x][y][z];\r\n if (isIntersecting(item.rect, rect)) {\r\n return true;\r\n }\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Calculates the number of rows or columns in a grid\r\n * @param step is the largest label size (width or height)\r\n * @param length is the grid size (width or height)\r\n * @param minCount is the minimum allowed size\r\n * @param maxCount is the maximum allowed size\r\n * @return the number of grid rows or columns\r\n */\r\n private getGridRowColCount(step: number, length: number, minCount: number, maxCount: number): number {\r\n return Math.min(Math.max(Math.ceil(length / step), minCount), maxCount);\r\n }\r\n\r\n /**\r\n * Returns the grid index of a given recangle\r\n * @param rect The rectengle to check.\r\n * @return grid index as a thickness object.\r\n */\r\n private getGridIndexRect(rect: IRect): IThickness {\r\n let restrict = (n, min, max) => Math.min(Math.max(n, min), max);\r\n return {\r\n left: restrict(Math.floor(rect.left / this.cellSize.width), 0, this.colCount),\r\n top: restrict(Math.floor(rect.top / this.cellSize.height), 0, this.rowCount),\r\n right: restrict(Math.ceil((rect.left + rect.width) / this.cellSize.width), 0, this.colCount),\r\n bottom: restrict(Math.ceil((rect.top + rect.height) / this.cellSize.height), 0, this.rowCount)\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * (Private) Contains methods for calculating the top-left coordinate of rectangle based on content size and anchor rect. \r\n */\r\n module LocationConverter {\r\n\r\n export function topInside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\r\n top: rect.top + offset,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function bottomInside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\r\n top: (rect.top + rect.height) - size.height - offset,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function rightInside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: (rect.left + rect.width) - size.width - offset,\r\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function leftInside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left + offset,\r\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function topOutside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\r\n top: rect.top - size.height - offset,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function bottomOutside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\r\n top: (rect.top + rect.height) + offset,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function rightOutside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: (rect.left + rect.width) + offset,\r\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function leftOutside(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left - size.width - offset,\r\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function middleHorizontal(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left + rect.width / 2.0 - size.width / 2.0 + offset,\r\n top: rect.top + rect.height / 2.0 - size.height / 2.0,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n\r\n export function middleVertical(size: shapes.ISize, rect: IRect, offset: number): IRect {\r\n return {\r\n left: rect.left + rect.width / 2.0 - size.width / 2.0,\r\n top: rect.top + rect.height / 2.0 - size.height / 2.0 + offset,\r\n width: size.width,\r\n height: size.height\r\n };\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n import shapes = powerbi.visuals.shapes;\r\n import ISize = shapes.ISize;\r\n import IRect = powerbi.visuals.IRect;\r\n import IPoint = shapes.IPoint;\r\n import SelectableDataPoint = powerbi.visuals.SelectableDataPoint;\r\n import Rect = powerbi.visuals.shapes.Rect;\r\n import NewDataLabelUtils = powerbi.visuals.NewDataLabelUtils;\r\n\r\n /**\r\n * Defines possible data label positions relative to rectangles\r\n */\r\n export const enum RectLabelPosition {\r\n\r\n /** Position is not defined. */\r\n None = 0,\r\n \r\n /** Content is placed inside the parent rectangle in the center. */\r\n InsideCenter = 1,\r\n\r\n /** Content is placed inside the parent rectangle at the base. */\r\n InsideBase = 2,\r\n\r\n /** Content is placed inside the parent rectangle at the end. */\r\n InsideEnd = 4,\r\n\r\n /** Content is placed outside the parent rectangle at the base. */\r\n OutsideBase = 8,\r\n\r\n /** Content is placed outside the parent rectangle at the end. */\r\n OutsideEnd = 16,\r\n\r\n /** Content supports all possible positions. */\r\n All =\r\n InsideCenter |\r\n InsideBase |\r\n InsideEnd |\r\n OutsideBase |\r\n OutsideEnd,\r\n\r\n /** Content supports positions inside the rectangle */\r\n InsideAll =\r\n InsideCenter |\r\n InsideBase |\r\n InsideEnd,\r\n }\r\n \r\n /**\r\n * Defines possible data label positions relative to points or circles\r\n */\r\n export const enum NewPointLabelPosition {\r\n /** Position is not defined. */\r\n None = 0,\r\n\r\n Above = 1 << 0,\r\n\r\n Below = 1 << 1,\r\n\r\n Left = 1 << 2,\r\n\r\n Right = 1 << 3,\r\n\r\n BelowRight = 1 << 4,\r\n\r\n BelowLeft = 1 << 5,\r\n\r\n AboveRight = 1 << 6,\r\n\r\n AboveLeft = 1 << 7,\r\n\r\n Center = 1 << 8,\r\n\r\n All =\r\n Above |\r\n Below |\r\n Left |\r\n Right |\r\n BelowRight |\r\n BelowLeft |\r\n AboveRight |\r\n AboveLeft |\r\n Center,\r\n }\r\n \r\n /**\r\n * Rectangle orientation, defined by vertical vs horizontal and which direction\r\n * the \"base\" is at.\r\n */\r\n export const enum NewRectOrientation {\r\n /** Rectangle with no specific orientation. */\r\n None,\r\n\r\n /** Vertical rectangle with base at the bottom. */\r\n VerticalBottomBased,\r\n\r\n /** Vertical rectangle with base at the top. */\r\n VerticalTopBased,\r\n\r\n /** Horizontal rectangle with base at the left. */\r\n HorizontalLeftBased,\r\n\r\n /** Horizontal rectangle with base at the right. */\r\n HorizontalRightBased,\r\n }\r\n\r\n export const enum LabelDataPointParentType {\r\n /* parent shape of data label is a point*/\r\n Point,\r\n \r\n /* parent shape of data label is a rectangle*/\r\n Rectangle,\r\n \r\n /* parent shape of data label is a polygon*/\r\n Polygon\r\n }\r\n\r\n export interface LabelParentRect {\r\n /** The rectangle this data label belongs to */\r\n rect: IRect;\r\n\r\n /** The orientation of the parent rectangle */\r\n orientation: NewRectOrientation;\r\n\r\n /** Valid positions to place the label ordered by preference */\r\n validPositions: RectLabelPosition[];\r\n }\r\n\r\n export interface LabelParentPoint {\r\n /** The point this data label belongs to */\r\n point: IPoint;\r\n\r\n /** The radius of the point to be added to the offset (for circular geometry) */\r\n radius: number;\r\n \r\n /** Valid positions to place the label ordered by preference */\r\n validPositions: NewPointLabelPosition[];\r\n }\r\n\r\n export interface LabelDataPoint {\r\n // Layout members; used by the layout system to position labels\r\n\r\n /** The measured size of the text */\r\n textSize: ISize;\r\n\r\n /** Is data label preferred? Preferred labels will be rendered first */\r\n isPreferred: boolean;\r\n\r\n /** Whether the parent type is a rectangle, point or polygon */\r\n parentType: LabelDataPointParentType;\r\n\r\n /** The parent geometry for the data label */\r\n parentShape: LabelParentRect | LabelParentPoint | LabelParentPolygon;\r\n\r\n /** Whether or not the label has a background */\r\n hasBackground?: boolean;\r\n\r\n // Rendering members that are simply passed through to the label for rendering purposes\r\n\r\n /** Text to be displayed in the label */\r\n text: string;\r\n\r\n /** A text that represent the label tooltip */\r\n tooltip?: string;\r\n\r\n /** Color to use for the data label if drawn inside */\r\n insideFill: string;\r\n\r\n /** Color to use for the data label if drawn outside */\r\n outsideFill: string;\r\n\r\n /** The identity of the data point associated with the data label */\r\n identity: powerbi.visuals.SelectionId;\r\n\r\n /** The key of the data point associated with the data label (used if identity is not unique to each expected label) */\r\n key?: string;\r\n\r\n /** The font size of the data point associated with the data label */\r\n fontSize?: number;\r\n\r\n /** Second row of text to be displayed in the label, for additional information */\r\n secondRowText?: string;\r\n\r\n /** The calculated weight of the data point associated with the data label */\r\n weight?: number;\r\n \r\n // Temporary state used internally by the Label Layout system\r\n\r\n /** Whether or not the data label has been rendered */\r\n hasBeenRendered?: boolean;\r\n\r\n /** Size of the label adjusted for the background, if necessary */\r\n labelSize?: ISize;\r\n }\r\n\r\n export interface LabelDataPointsGroup {\r\n labelDataPoints: LabelDataPoint[];\r\n maxNumberOfLabels: number;\r\n }\r\n\r\n export interface Label extends SelectableDataPoint {\r\n /** Text to be displayed in the label */\r\n text: string;\r\n\r\n /** Second row of text to be displayed in the label */\r\n secondRowText?: string;\r\n\r\n /** The bounding box for the label */\r\n boundingBox: IRect;\r\n\r\n /** Whether or not the data label should be rendered */\r\n isVisible: boolean;\r\n\r\n /** The fill color of the data label */\r\n fill: string;\r\n\r\n /** A unique key for data points (used if key cannot be obtained from the identity) */\r\n key?: string;\r\n\r\n /** The text size of the data label */\r\n fontSize?: number;\r\n\r\n /** A text anchor used to override the default label text-anchor (middle) */\r\n textAnchor?: string; \r\n\r\n /** points for reference line rendering */\r\n leaderLinePoints?: number[][];\r\n\r\n /** Whether or not the label has a background (and text position needs to be adjusted to take that into account) */\r\n hasBackground: boolean;\r\n\r\n /** A text that represent the label tooltip */\r\n tooltip?: string;\r\n }\r\n\r\n export interface GridSubsection {\r\n xMin: number;\r\n xMax: number;\r\n yMin: number;\r\n yMax: number;\r\n }\r\n\r\n export class LabelArrangeGrid {\r\n private grid: IRect[][][];\r\n private viewport: IViewport;\r\n private cellSize: ISize;\r\n private columnCount: number;\r\n private rowCount: number;\r\n\r\n /** \r\n * A multiplier applied to the largest width height to attempt to balance # of\r\n * labels in each cell and number of cells each label belongs to\r\n */\r\n private static cellSizeMultiplier = 2;\r\n\r\n constructor(labelDataPointsGroups: LabelDataPointsGroup[], viewport: IViewport) {\r\n this.viewport = viewport;\r\n\r\n let maxLabelWidth = 0;\r\n let maxLabelHeight = 0;\r\n\r\n for (let labelDataPointsGroup of labelDataPointsGroups) {\r\n for (let labelDataPoint of labelDataPointsGroup.labelDataPoints) {\r\n if (labelDataPoint.isPreferred) {\r\n let dataLabelSize: ISize = labelDataPoint.labelSize;\r\n if (dataLabelSize.width > maxLabelWidth) {\r\n maxLabelWidth = dataLabelSize.width;\r\n }\r\n if (dataLabelSize.height > maxLabelHeight) {\r\n maxLabelHeight = dataLabelSize.height;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (maxLabelWidth === 0) {\r\n maxLabelWidth = viewport.width;\r\n }\r\n if (maxLabelHeight === 0) {\r\n maxLabelHeight = viewport.height;\r\n }\r\n let cellSize = this.cellSize = { width: maxLabelWidth * LabelArrangeGrid.cellSizeMultiplier, height: maxLabelHeight * LabelArrangeGrid.cellSizeMultiplier };\r\n this.columnCount = LabelArrangeGrid.getCellCount(cellSize.width, viewport.width, 1, 100);\r\n this.rowCount = LabelArrangeGrid.getCellCount(cellSize.height, viewport.height, 1, 100);\r\n let grid: IRect[][][] = [];\r\n for (let i = 0, ilen = this.columnCount; i < ilen; i++) {\r\n grid[i] = [];\r\n for (let j = 0, jlen = this.rowCount; j < jlen; j++) {\r\n grid[i][j] = [];\r\n }\r\n }\r\n this.grid = grid;\r\n }\r\n\r\n /**\r\n * Add a rectangle to check collision against\r\n */\r\n public add(rect: IRect): void {\r\n let containingIndexRect = this.getContainingGridSubsection(rect);\r\n\r\n for (let x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\r\n for (let y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\r\n this.grid[x][y].push(rect);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Check whether the rect conflicts with the grid, either bleeding outside the\r\n * viewport or colliding with another rect added to the grid.\r\n */\r\n public hasConflict(rect: IRect): boolean {\r\n if (!this.isWithinGridViewport(rect)) {\r\n return true;\r\n }\r\n\r\n return this.hasCollision(rect);\r\n }\r\n\r\n /**\r\n * Attempt to position the given rect within the viewport. Returns\r\n * the adjusted rectangle or null if the rectangle couldn't fit, \r\n * conflicts with the viewport, or is too far outside the viewport\r\n */\r\n public tryPositionInViewport(rect: IRect): IRect {\r\n // If it's too far outside the viewport, return null\r\n if (!this.isCloseToGridViewport(rect)) {\r\n return;\r\n }\r\n\r\n if (!this.isWithinGridViewport(rect)) {\r\n rect = this.tryMoveInsideViewport(rect);\r\n }\r\n\r\n if (rect && !this.hasCollision(rect)) {\r\n return rect;\r\n }\r\n }\r\n \r\n /**\r\n * Checks for a collision between the given rect and others in the grid.\r\n * Returns true if there is a collision.\r\n */\r\n private hasCollision(rect: IRect): boolean {\r\n let containingIndexRect = this.getContainingGridSubsection(rect);\r\n let grid = this.grid;\r\n let isIntersecting = shapes.Rect.isIntersecting;\r\n for (let x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\r\n for (let y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\r\n for (let currentGridRect of grid[x][y]) {\r\n if (isIntersecting(currentGridRect, rect)) {\r\n return true;\r\n }\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n \r\n /**\r\n * Check to see if the given rect is inside the grid's viewport\r\n */\r\n private isWithinGridViewport(rect: IRect): boolean {\r\n return rect.left >= 0 &&\r\n rect.top >= 0 &&\r\n rect.left + rect.width <= this.viewport.width &&\r\n rect.top + rect.height <= this.viewport.height;\r\n }\r\n\r\n /**\r\n * Checks to see if the rect is close enough to the viewport to be moved inside.\r\n * \"Close\" here is determined by the distance between the edge of the viewport\r\n * and the closest edge of the rect; if that distance is less than the appropriate\r\n * dimension of the rect, we will reposition the rect.\r\n */\r\n private isCloseToGridViewport(rect: IRect): boolean {\r\n return rect.left + rect.width >= 0 - rect.width &&\r\n rect.top + rect.height >= -rect.height &&\r\n rect.left <= this.viewport.width + rect.width &&\r\n rect.top <= this.viewport.height + rect.height;\r\n }\r\n\r\n /**\r\n * Attempt to move the rect inside the grid's viewport. Returns the resulting\r\n * rectangle with the same width/height adjusted to be inside the viewport or\r\n * null if it couldn't fit regardless.\r\n */\r\n private tryMoveInsideViewport(rect: IRect): IRect {\r\n let result: IRect = Rect.clone(rect);\r\n let viewport = this.viewport;\r\n\r\n // Return null if it's too big to fit regardless of positioning\r\n if (rect.width > viewport.width || rect.height > viewport.height) {\r\n return;\r\n }\r\n \r\n // Only one movement should be made in each direction, because we are only moving it inside enough for it to fit; there should be no overshooting.\r\n // Outside to the left\r\n if (rect.left < 0) {\r\n result.left = 0;\r\n }\r\n // Outside to the right\r\n else if (rect.left + rect.width > viewport.width) {\r\n result.left -= (rect.left + rect.width) - viewport.width;\r\n }\r\n // Outside above\r\n if (rect.top < 0) {\r\n result.top = 0;\r\n }\r\n // Outside below\r\n else if (rect.top + rect.height > viewport.height) {\r\n result.top -= (rect.top + rect.height) - viewport.height;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private getContainingGridSubsection(rect: IRect): GridSubsection {\r\n return {\r\n xMin: LabelArrangeGrid.bound(Math.floor(rect.left / this.cellSize.width), 0, this.columnCount),\r\n xMax: LabelArrangeGrid.bound(Math.ceil((rect.left + rect.width) / this.cellSize.width), 0, this.columnCount),\r\n yMin: LabelArrangeGrid.bound(Math.floor(rect.top / this.cellSize.height), 0, this.rowCount),\r\n yMax: LabelArrangeGrid.bound(Math.ceil((rect.top + rect.height) / this.cellSize.height), 0, this.rowCount),\r\n };\r\n }\r\n\r\n private static getCellCount(step: number, length: number, minCount: number, maxCount: number): number {\r\n return LabelArrangeGrid.bound(Math.ceil(length / step), minCount, maxCount);\r\n }\r\n\r\n private static bound(value: number, min: number, max: number): number {\r\n return Math.max(Math.min(value, max), min);\r\n }\r\n }\r\n\r\n export interface DataLabelLayoutOptions {\r\n /** The amount of offset to start with when the data label is not centered */\r\n startingOffset: number;\r\n /** Maximum distance labels will be offset by */\r\n maximumOffset: number;\r\n /** The amount to increase the offset each attempt while laying out labels */\r\n offsetIterationDelta?: number;\r\n /** Horizontal padding used for checking whether a label is inside a parent shape */\r\n horizontalPadding?: number;\r\n /** Vertical padding used for checking whether a label is inside a parent shape */\r\n verticalPadding?: number;\r\n /** Should we draw reference lines in case the label offset is greater then the default */\r\n allowLeaderLines?: boolean;\r\n /** Should the layout system attempt to move the label inside the viewport when it outside, but close */\r\n attemptToMoveLabelsIntoViewport?: boolean;\r\n }\r\n\r\n export class LabelLayout {\r\n /** Maximum distance labels will be offset by */\r\n private maximumOffset: number;\r\n /** The amount to increase the offset each attempt while laying out labels */\r\n private offsetIterationDelta: number;\r\n /** The amount of offset to start with when the data label is not centered */\r\n private startingOffset: number;\r\n /** Padding used for checking whether a label is inside a parent shape */\r\n private horizontalPadding: number;\r\n /** Padding used for checking whether a label is inside a parent shape */\r\n private verticalPadding: number;\r\n /** Should we draw leader lines in case the label offset is greater then the default */\r\n private allowLeaderLines: boolean;\r\n /** Should the layout system attempt to move the label inside the viewport when it outside, but close */\r\n private attemptToMoveLabelsIntoViewport: boolean;\r\n\r\n // Default values\r\n private static defaultOffsetIterationDelta = 2;\r\n private static defaultHorizontalPadding = 2;\r\n private static defaultVerticalPadding = 2;\r\n\r\n constructor(options: DataLabelLayoutOptions) {\r\n this.startingOffset = options.startingOffset;\r\n this.maximumOffset = options.maximumOffset;\r\n if (options.offsetIterationDelta != null) {\r\n debug.assert(options.offsetIterationDelta > 0, \"label offset delta must be greater than 0\");\r\n this.offsetIterationDelta = options.offsetIterationDelta;\r\n }\r\n else {\r\n this.offsetIterationDelta = LabelLayout.defaultOffsetIterationDelta;\r\n }\r\n if (options.horizontalPadding != null) {\r\n this.horizontalPadding = options.horizontalPadding;\r\n }\r\n else {\r\n this.horizontalPadding = LabelLayout.defaultHorizontalPadding;\r\n }\r\n if (options.verticalPadding != null) {\r\n this.verticalPadding = options.verticalPadding;\r\n }\r\n else {\r\n this.verticalPadding = LabelLayout.defaultVerticalPadding;\r\n }\r\n this.allowLeaderLines = !!options.allowLeaderLines;\r\n this.attemptToMoveLabelsIntoViewport = !!options.attemptToMoveLabelsIntoViewport;\r\n }\r\n\r\n /**\r\n * Arrange takes a set of data labels and lays them out in order, assuming that\r\n * the given array has already been sorted with the most preferred labels at the\r\n * front, taking into considiration a maximum number of labels that are alowed\r\n * to display.\r\n * \r\n * Details:\r\n * - We iterate over offsets from the target position, increasing from 0 while\r\n * verifiying the maximum number of labels to display hasn't been reached\r\n * - For each offset, we iterate over each data label\r\n * - For each data label, we iterate over each position that is valid for\r\n * both the specific label and this layout\r\n * - When a valid position is found, we position the label there and no longer\r\n * reposition it.\r\n * - This prioritizes the earlier labels to be positioned closer to their\r\n * target points in the position they prefer.\r\n * - This prioritizes putting data labels close to a valid position over\r\n * placing them at their preferred position (it will place it at a less\r\n * preferred position if it will be a smaller offset)\r\n */\r\n public layout(labelDataPointsGroups: LabelDataPointsGroup[], viewport: IViewport): Label[] {\r\n // Clear data labels for a new layout\r\n for (let labelDataPointsGroup of labelDataPointsGroups) {\r\n for (let labelPoint of labelDataPointsGroup.labelDataPoints) {\r\n labelPoint.hasBeenRendered = false;\r\n if (labelPoint.hasBackground) {\r\n labelPoint.labelSize = {\r\n width: labelPoint.textSize.width + 2 * NewDataLabelUtils.horizontalLabelBackgroundPadding,\r\n height: labelPoint.textSize.height + 2 * NewDataLabelUtils.verticalLabelBackgroundPadding,\r\n };\r\n }\r\n else {\r\n labelPoint.labelSize = labelPoint.textSize;\r\n }\r\n }\r\n }\r\n\r\n let resultingDataLabels: Label[] = [];\r\n let grid = new LabelArrangeGrid(labelDataPointsGroups, viewport);\r\n\r\n // Iterates on every series\r\n for (let labelDataPointsGroup of labelDataPointsGroups) {\r\n let maxLabelsToRender = labelDataPointsGroup.maxNumberOfLabels;\r\n // NOTE: we create a copy and modify the copy to keep track of preferred vs. non-preferred labels.\r\n let labelDataPoints = _.clone(labelDataPointsGroup.labelDataPoints);\r\n let preferredLabels: LabelDataPoint[] = [];\r\n \r\n // Exclude preferred labels\r\n for (let j = labelDataPoints.length - 1, localMax = maxLabelsToRender; j >= 0 && localMax > 0; j--) {\r\n let labelPoint = labelDataPoints[j];\r\n if (labelPoint.isPreferred) {\r\n preferredLabels.unshift(labelDataPoints.splice(j, 1)[0]);\r\n localMax--;\r\n }\r\n }\r\n\r\n // First iterate all the preferred labels\r\n if (preferredLabels.length > 0) {\r\n let positionedLabels = this.positionDataLabels(preferredLabels, viewport, grid, maxLabelsToRender);\r\n maxLabelsToRender -= positionedLabels.length;\r\n resultingDataLabels = resultingDataLabels.concat(positionedLabels);\r\n }\r\n \r\n // While there are invisible not preferred labels and label distance is less than the max\r\n // allowed distance\r\n if (labelDataPoints.length > 0) {\r\n let labels = this.positionDataLabels(labelDataPoints, viewport, grid, maxLabelsToRender);\r\n resultingDataLabels = resultingDataLabels.concat(labels);\r\n }\r\n // TODO: Add reference lines if we want them\r\n }\r\n return resultingDataLabels;\r\n }\r\n\r\n private positionDataLabels(labelDataPoints: LabelDataPoint[], viewport: IViewport, grid: LabelArrangeGrid, maxLabelsToRender: number): Label[] {\r\n let resultingDataLabels: Label[] = [];\r\n let offsetDelta = this.offsetIterationDelta;\r\n let currentOffset = this.startingOffset;\r\n let currentCenteredOffset = 0;\r\n let drawLeaderLinesOnIteration: boolean;\r\n\r\n while (currentOffset <= this.maximumOffset && maxLabelsToRender > 0) {\r\n drawLeaderLinesOnIteration = this.allowLeaderLines && currentOffset > this.startingOffset;\r\n for (let labelPoint of labelDataPoints) {\r\n // Check if maximum number of labels to display has been reached\r\n if (maxLabelsToRender === 0)\r\n break;\r\n\r\n if (labelPoint.hasBeenRendered) {\r\n continue;\r\n }\r\n let dataLabel;\r\n if (labelPoint.parentType === LabelDataPointParentType.Rectangle) {\r\n dataLabel = this.tryPositionForRectPositions(labelPoint, grid, currentOffset, currentCenteredOffset);\r\n }\r\n else {\r\n dataLabel = this.tryPositionForPointPositions(labelPoint, grid, currentOffset, drawLeaderLinesOnIteration);\r\n }\r\n\r\n if (dataLabel) {\r\n resultingDataLabels.push(dataLabel);\r\n maxLabelsToRender--;\r\n }\r\n }\r\n currentOffset += offsetDelta;\r\n currentCenteredOffset += offsetDelta;\r\n }\r\n\r\n return resultingDataLabels;\r\n }\r\n\r\n private tryPositionForRectPositions(labelPoint: LabelDataPoint, grid: LabelArrangeGrid, currentLabelOffset: number, currentCenteredLabelOffset: number): Label {\r\n // Function declared and reused to reduce code duplication\r\n let tryPosition = (position: RectLabelPosition, adjustForViewport: boolean) => {\r\n let isPositionInside = position & RectLabelPosition.InsideAll;\r\n if (isPositionInside && !DataLabelRectPositioner.canFitWithinParent(labelPoint, this.horizontalPadding, this.verticalPadding)) {\r\n return;\r\n }\r\n\r\n let resultingBoundingBox = LabelLayout.tryPositionRect(grid, position, labelPoint, currentLabelOffset, currentCenteredLabelOffset, adjustForViewport);\r\n if (resultingBoundingBox) {\r\n if (isPositionInside && !DataLabelRectPositioner.isLabelWithinParent(resultingBoundingBox, labelPoint, this.horizontalPadding, this.verticalPadding)) {\r\n return;\r\n }\r\n grid.add(resultingBoundingBox);\r\n labelPoint.hasBeenRendered = true;\r\n return {\r\n boundingBox: resultingBoundingBox,\r\n text: labelPoint.text,\r\n tooltip: labelPoint.tooltip,\r\n isVisible: true,\r\n fill: isPositionInside ? labelPoint.insideFill : labelPoint.outsideFill,\r\n identity: labelPoint.identity,\r\n key: labelPoint.key,\r\n fontSize: labelPoint.fontSize,\r\n selected: false,\r\n hasBackground: !!labelPoint.hasBackground,\r\n };\r\n }\r\n };\r\n\r\n // Iterate over all positions that are valid for the data point\r\n for (let position of (<LabelParentRect>labelPoint.parentShape).validPositions) {\r\n let label = tryPosition(position, false /* adjustForViewport */);\r\n if (label)\r\n return label;\r\n }\r\n // If no position has been found and the option is enabled, try any outside positions while moving the label inside the viewport\r\n if (this.attemptToMoveLabelsIntoViewport) {\r\n for (let position of (<LabelParentRect>labelPoint.parentShape).validPositions) {\r\n let label = tryPosition(position, true /* adjustForViewport */);\r\n if (label)\r\n return label;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Tests a particular position/offset combination for the given data label.\r\n * If the label can be placed, returns the resulting bounding box for the data\r\n * label. If not, returns null.\r\n */\r\n private static tryPositionRect(grid: LabelArrangeGrid, position: RectLabelPosition, labelDataPoint: LabelDataPoint, offset: number, centerOffset: number, adjustForViewport: boolean): IRect {\r\n let offsetForPosition = offset;\r\n if (position & RectLabelPosition.InsideCenter) {\r\n offsetForPosition = centerOffset;\r\n }\r\n let labelRect = DataLabelRectPositioner.getLabelRect(labelDataPoint, position, offsetForPosition);\r\n\r\n if (position !== RectLabelPosition.InsideCenter || (<LabelParentRect>labelDataPoint.parentShape).orientation === NewRectOrientation.None) {\r\n if (!grid.hasConflict(labelRect)) {\r\n return labelRect;\r\n }\r\n if (adjustForViewport) {\r\n return grid.tryPositionInViewport(labelRect);\r\n }\r\n }\r\n else {\r\n // If the position is centered, attempt to offset in both a positive and negative direction\r\n if (!grid.hasConflict(labelRect)) {\r\n return labelRect;\r\n }\r\n labelRect = DataLabelRectPositioner.getLabelRect(labelDataPoint, position, -offsetForPosition);\r\n if (!grid.hasConflict(labelRect)) {\r\n return labelRect;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private tryPositionForPointPositions(labelPoint: LabelDataPoint, grid: LabelArrangeGrid, currentLabelOffset: number, drawLeaderLines: boolean): Label {\r\n // Function declared and reused to reduce code duplication\r\n let tryPosition = (position: NewPointLabelPosition, parentShape: LabelParentPoint, adjustForViewport: boolean) => {\r\n let resultingBoundingBox = LabelLayout.tryPositionPoint(grid, position, labelPoint, currentLabelOffset, adjustForViewport);\r\n if (resultingBoundingBox) {\r\n grid.add(resultingBoundingBox);\r\n labelPoint.hasBeenRendered = true;\r\n return {\r\n boundingBox: resultingBoundingBox,\r\n text: labelPoint.text,\r\n tooltip: labelPoint.tooltip,\r\n isVisible: true,\r\n fill: position === NewPointLabelPosition.Center ? labelPoint.insideFill : labelPoint.outsideFill, // If we ever support \"inside\" for point-based labels, this needs to be updated\r\n isInsideParent: position === NewPointLabelPosition.Center,\r\n identity: labelPoint.identity,\r\n key: labelPoint.key,\r\n fontSize: labelPoint.fontSize,\r\n selected: false,\r\n leaderLinePoints: drawLeaderLines ? DataLabelPointPositioner.getLabelLeaderLineEndingPoint(resultingBoundingBox, position, parentShape) : null,\r\n hasBackground: !!labelPoint.hasBackground,\r\n };\r\n }\r\n };\r\n\r\n // Iterate over all positions that are valid for the data point\r\n let parentShape = (<LabelParentPoint>labelPoint.parentShape);\r\n let validPositions = parentShape.validPositions;\r\n for (let position of validPositions) {\r\n let label = tryPosition(position, parentShape, false /* adjustForViewport */);\r\n if (label)\r\n return label;\r\n }\r\n // Attempt to position at the most preferred position by simply moving it inside the viewport\r\n if (this.attemptToMoveLabelsIntoViewport && !_.isEmpty(validPositions)) {\r\n let label = tryPosition(validPositions[0], parentShape, true /* adjustForViewport */);\r\n if (label)\r\n return label;\r\n }\r\n return null;\r\n }\r\n\r\n private static tryPositionPoint(grid: LabelArrangeGrid, position: NewPointLabelPosition, labelDataPoint: LabelDataPoint, offset: number, adjustForViewport: boolean): IRect {\r\n let labelRect = DataLabelPointPositioner.getLabelRect(labelDataPoint.labelSize, <LabelParentPoint>labelDataPoint.parentShape, position, offset);\r\n\r\n if (!grid.hasConflict(labelRect)) {\r\n return labelRect;\r\n }\r\n if (adjustForViewport) {\r\n return grid.tryPositionInViewport(labelRect);\r\n }\r\n\r\n return null;\r\n }\r\n }\r\n \r\n /**\r\n * (Private) Contains methods for calculating the bounding box of a data label\r\n */\r\n export module DataLabelRectPositioner {\r\n\r\n export function getLabelRect(labelDataPoint: LabelDataPoint, position: RectLabelPosition, offset: number): IRect {\r\n let parentRect: LabelParentRect = <LabelParentRect>labelDataPoint.parentShape;\r\n if (parentRect != null) {\r\n // Each combination of position and orientation results in a different actual positioning, which is then called.\r\n switch (position) {\r\n case RectLabelPosition.InsideCenter:\r\n switch (parentRect.orientation) {\r\n case NewRectOrientation.VerticalBottomBased:\r\n case NewRectOrientation.VerticalTopBased:\r\n return DataLabelRectPositioner.middleVertical(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalLeftBased:\r\n case NewRectOrientation.HorizontalRightBased:\r\n return DataLabelRectPositioner.middleHorizontal(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.None:\r\n // TODO: which of the above cases should we default to for rects with no orientation?\r\n }\r\n case RectLabelPosition.InsideBase:\r\n switch (parentRect.orientation) {\r\n case NewRectOrientation.VerticalBottomBased:\r\n return DataLabelRectPositioner.bottomInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.VerticalTopBased:\r\n return DataLabelRectPositioner.topInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalLeftBased:\r\n return DataLabelRectPositioner.leftInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalRightBased:\r\n return DataLabelRectPositioner.rightInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.None:\r\n // TODO: which of the above cases should we default to for rects with no orientation?\r\n }\r\n case RectLabelPosition.InsideEnd:\r\n switch (parentRect.orientation) {\r\n case NewRectOrientation.VerticalBottomBased:\r\n return DataLabelRectPositioner.topInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.VerticalTopBased:\r\n return DataLabelRectPositioner.bottomInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalLeftBased:\r\n return DataLabelRectPositioner.rightInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalRightBased:\r\n return DataLabelRectPositioner.leftInside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.None:\r\n // TODO: which of the above cases should we default to for rects with no orientation?\r\n }\r\n case RectLabelPosition.OutsideBase:\r\n switch (parentRect.orientation) {\r\n case NewRectOrientation.VerticalBottomBased:\r\n return DataLabelRectPositioner.bottomOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.VerticalTopBased:\r\n return DataLabelRectPositioner.topOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalLeftBased:\r\n return DataLabelRectPositioner.leftOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalRightBased:\r\n return DataLabelRectPositioner.rightOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.None:\r\n // TODO: which of the above cases should we default to for rects with no orientation?\r\n }\r\n case RectLabelPosition.OutsideEnd:\r\n switch (parentRect.orientation) {\r\n case NewRectOrientation.VerticalBottomBased:\r\n return DataLabelRectPositioner.topOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.VerticalTopBased:\r\n return DataLabelRectPositioner.bottomOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalLeftBased:\r\n return DataLabelRectPositioner.rightOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.HorizontalRightBased:\r\n return DataLabelRectPositioner.leftOutside(labelDataPoint.labelSize, parentRect.rect, offset);\r\n case NewRectOrientation.None:\r\n // TODO: which of the above cases should we default to for rects with no orientation?\r\n }\r\n default:\r\n debug.assertFail(\"Unsupported label position\");\r\n }\r\n }\r\n else {\r\n // TODO: Data labels for non-rectangular visuals (line chart)\r\n }\r\n return null;\r\n }\r\n\r\n export function canFitWithinParent(labelDataPoint: LabelDataPoint, horizontalPadding: number, verticalPadding: number): boolean {\r\n return (labelDataPoint.labelSize.width + 2 * horizontalPadding < (<LabelParentRect>labelDataPoint.parentShape).rect.width) ||\r\n (labelDataPoint.labelSize.height + 2 * verticalPadding < (<LabelParentRect>labelDataPoint.parentShape).rect.height);\r\n }\r\n\r\n export function isLabelWithinParent(labelRect: IRect, labelPoint: LabelDataPoint, horizontalPadding: number, verticalPadding: number): boolean {\r\n let parentRect = (<LabelParentRect>labelPoint.parentShape).rect;\r\n let labelRectWithPadding = shapes.Rect.inflate(labelRect, { left: horizontalPadding, right: horizontalPadding, top: verticalPadding, bottom: verticalPadding });\r\n return shapes.Rect.containsPoint(parentRect, {\r\n x: labelRectWithPadding.left,\r\n y: labelRectWithPadding.top,\r\n }) && shapes.Rect.containsPoint(parentRect, {\r\n x: labelRectWithPadding.left + labelRectWithPadding.width,\r\n y: labelRectWithPadding.top + labelRectWithPadding.height,\r\n });\r\n }\r\n\r\n export function topInside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\r\n top: parentRect.top + offset,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function bottomInside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\r\n top: (parentRect.top + parentRect.height) - offset - labelSize.height,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function rightInside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: (parentRect.left + parentRect.width) - labelSize.width - offset,\r\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function leftInside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left + offset,\r\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function topOutside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\r\n top: parentRect.top - labelSize.height - offset,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function bottomOutside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\r\n top: (parentRect.top + parentRect.height) + offset,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function rightOutside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: (parentRect.left + parentRect.width) + offset,\r\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function leftOutside(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left - labelSize.width - offset,\r\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function middleHorizontal(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0 + offset,\r\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function middleVertical(labelSize: ISize, parentRect: IRect, offset: number): IRect {\r\n return {\r\n left: parentRect.left + parentRect.width / 2.0 - labelSize.width / 2.0,\r\n top: parentRect.top + parentRect.height / 2.0 - labelSize.height / 2.0 + offset,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n }\r\n\r\n export module DataLabelPointPositioner {\r\n export const cos45 = Math.cos(45);\r\n export const sin45 = Math.sin(45);\r\n\r\n export function getLabelRect(labelSize: ISize, parentPoint: LabelParentPoint, position: NewPointLabelPosition, offset: number): IRect {\r\n switch (position) {\r\n case NewPointLabelPosition.Above: {\r\n return DataLabelPointPositioner.above(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.Below: {\r\n return DataLabelPointPositioner.below(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.Left: {\r\n return DataLabelPointPositioner.left(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.Right: {\r\n return DataLabelPointPositioner.right(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.BelowLeft: {\r\n return DataLabelPointPositioner.belowLeft(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.BelowRight: {\r\n return DataLabelPointPositioner.belowRight(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.AboveLeft: {\r\n return DataLabelPointPositioner.aboveLeft(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.AboveRight: {\r\n return DataLabelPointPositioner.aboveRight(labelSize, parentPoint.point, parentPoint.radius + offset);\r\n }\r\n case NewPointLabelPosition.Center: {\r\n return DataLabelPointPositioner.center(labelSize, parentPoint.point);\r\n }\r\n default: {\r\n debug.assertFail(\"Unsupported label position\");\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n export function above(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x - (labelSize.width / 2),\r\n top: parentPoint.y - offset - labelSize.height,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function below(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x - (labelSize.width / 2),\r\n top: parentPoint.y + offset,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function left(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x - offset - labelSize.width,\r\n top: parentPoint.y - (labelSize.height / 2),\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function right(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x + offset,\r\n top: parentPoint.y - (labelSize.height / 2),\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function belowLeft(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x - (sin45 * offset) - labelSize.width,\r\n top: parentPoint.y + (cos45 * offset),\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function belowRight(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x + (sin45 * offset),\r\n top: parentPoint.y + (cos45 * offset),\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function aboveLeft(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x - (sin45 * offset) - labelSize.width,\r\n top: parentPoint.y - (cos45 * offset) - labelSize.height,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function aboveRight(labelSize: ISize, parentPoint: IPoint, offset: number): IRect {\r\n return {\r\n left: parentPoint.x + (sin45 * offset),\r\n top: parentPoint.y - (cos45 * offset) - labelSize.height,\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n export function center(labelSize: ISize, parentPoint: IPoint): IRect {\r\n return {\r\n left: parentPoint.x - (labelSize.width / 2),\r\n top: parentPoint.y - (labelSize.height / 2),\r\n width: labelSize.width,\r\n height: labelSize.height\r\n };\r\n }\r\n\r\n export function getLabelLeaderLineEndingPoint(boundingBox: IRect, position: NewPointLabelPosition, parentShape: LabelParentPoint): number[][] {\r\n let x = boundingBox.left;\r\n let y = boundingBox.top;\r\n switch (position) {\r\n case NewPointLabelPosition.Above:\r\n x += (boundingBox.width / 2);\r\n y += boundingBox.height;\r\n break;\r\n case NewPointLabelPosition.Below:\r\n x += (boundingBox.width / 2);\r\n break;\r\n case NewPointLabelPosition.Left:\r\n x += boundingBox.width;\r\n y += ((boundingBox.height * 2) / 3);\r\n break;\r\n case NewPointLabelPosition.Right:\r\n y += ((boundingBox.height * 2) / 3);\r\n break;\r\n case NewPointLabelPosition.BelowLeft:\r\n x += boundingBox.width;\r\n y += (boundingBox.height / 2);\r\n break;\r\n case NewPointLabelPosition.BelowRight:\r\n y += (boundingBox.height / 2);\r\n break;\r\n case NewPointLabelPosition.AboveLeft:\r\n x += boundingBox.width;\r\n y += boundingBox.height;\r\n break;\r\n case NewPointLabelPosition.AboveRight:\r\n y += boundingBox.height;\r\n break;\r\n }\r\n\r\n return [[parentShape.point.x, parentShape.point.y], [x, y]];\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n import ISize = powerbi.visuals.shapes.ISize;\r\n import IVector = powerbi.visuals.shapes.IVector;\r\n import IRect = powerbi.visuals.IRect;\r\n import VisualDataLabelsSettings = powerbi.visuals.VisualDataLabelsSettings;\r\n import DonutArcDescriptor = powerbi.visuals.DonutArcDescriptor;\r\n import NewDataLabelUtils = powerbi.visuals.NewDataLabelUtils;\r\n import labelStyle = powerbi.visuals.labelStyle;\r\n import DonutLabelUtils = powerbi.visuals.DonutLabelUtils;\r\n\r\n export interface DonutChartProperties {\r\n viewport: IViewport;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n radius: number;\r\n arc: D3.Svg.Arc;\r\n outerArc: D3.Svg.Arc;\r\n outerArcRadiusRatio: number;\r\n innerArcRadiusRatio: number;\r\n }\r\n\r\n export interface DonutLabelDataPoint extends LabelDataPoint {\r\n dataLabel: string;\r\n dataLabelSize: ISize;\r\n categoryLabel: string;\r\n categoryLabelSize: ISize;\r\n donutArcDescriptor: DonutArcDescriptor;\r\n alternativeScale: number;\r\n angle: number;\r\n linesSize: ISize[];\r\n leaderLinePoints: number[][];\r\n }\r\n\r\n interface LabelCandidate {\r\n angle: number;\r\n point: LabelParentPoint;\r\n score: number;\r\n labelRects: DonutLabelRect;\r\n labelDataPoint?: DonutLabelDataPoint;\r\n }\r\n\r\n export interface DonutLabelRect {\r\n textRect: IRect;\r\n diagonalLineRect: IRect;\r\n horizontalLineRect: IRect;\r\n }\r\n\r\n export class DonutLabelLayout {\r\n\r\n /** Maximum distance labels will be offset by */\r\n private maximumOffset: number;\r\n /** The amount to increase the offset each attempt while laying out labels */\r\n private offsetIterationDelta: number;\r\n /** The amount of offset to start with when the data label is not centered */\r\n private startingOffset: number;\r\n\r\n private donutChartProperties: DonutChartProperties;\r\n private center: IVector;\r\n private outerRadius: number;\r\n private innerRadius: number;\r\n private additionalCharsWidth: number;\r\n\r\n constructor(options: DataLabelLayoutOptions, donutChartProperties: DonutChartProperties) {\r\n this.startingOffset = options.startingOffset;\r\n this.maximumOffset = options.maximumOffset;\r\n if (options.offsetIterationDelta != null) {\r\n debug.assert(options.offsetIterationDelta > 0, \"label offset delta must be greater than 0\");\r\n this.offsetIterationDelta = options.offsetIterationDelta;\r\n }\r\n\r\n this.donutChartProperties = donutChartProperties;\r\n this.center = {\r\n x: donutChartProperties.viewport.width / 2,\r\n y: donutChartProperties.viewport.height / 2,\r\n };\r\n this.outerRadius = this.donutChartProperties.radius * this.donutChartProperties.outerArcRadiusRatio;\r\n this.innerRadius = (this.donutChartProperties.radius / 2) * this.donutChartProperties.innerArcRadiusRatio;\r\n this.additionalCharsWidth = TextMeasurementService.measureSvgTextWidth({\r\n text: \" ()\",\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: jsCommon.PixelConverter.fromPoint(donutChartProperties.dataLabelsSettings.fontSize),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n });\r\n }\r\n\r\n /**\r\n * Arrange takes a set of data labels and lays them out them in order, assuming that\r\n * the given array has already been sorted with the most preferred labels at the\r\n * front.\r\n * \r\n * Details:\r\n * - We iterate over offsets from the target position, increasing from 0\r\n * - For each offset, we iterate over each data label\r\n * - For each data label, we iterate over each position that is valid for\r\n * both the specific label and this layout\r\n * - When a valid position is found, we position the label there and no longer\r\n * reposition it.\r\n * - This prioritizes the earlier labels to be positioned closer to their\r\n * target points in the position they prefer.\r\n * - This prioritizes putting data labels close to a valid position over\r\n * placing them at their preferred position (it will place it at a less\r\n * preferred position if it will be a smaller offset)\r\n */\r\n public layout(labelDataPoints: DonutLabelDataPoint[]): Label[] {\r\n // Clear data labels for a new layout\r\n for (let donutLabel of labelDataPoints) {\r\n donutLabel.hasBeenRendered = false;\r\n donutLabel.labelSize = donutLabel.textSize;\r\n }\r\n\r\n let resultingLabels: Label[] = [];\r\n let preferredLabels: DonutLabelDataPoint[] = [];\r\n let viewport = this.donutChartProperties.viewport;\r\n let labelDataPointsGroup: LabelDataPointsGroup = {\r\n labelDataPoints: labelDataPoints,\r\n maxNumberOfLabels: labelDataPoints.length\r\n };\r\n let grid = new LabelArrangeGrid([labelDataPointsGroup], viewport);\r\n for (let i = labelDataPoints.length - 1; i >= 0; i--) {\r\n let labelPoint = labelDataPoints[i];\r\n if (labelPoint.isPreferred) {\r\n let label = labelDataPoints.splice(i, 1);\r\n preferredLabels = label.concat(preferredLabels);\r\n }\r\n }\r\n\r\n // first iterate all the preferred labels\r\n if (preferredLabels.length > 0)\r\n resultingLabels = this.positionLabels(preferredLabels, grid);\r\n \r\n // While there are invisible not preferred labels and label distance is less than the max\r\n // allowed distance\r\n if (labelDataPoints.length > 0) {\r\n let labels = this.positionLabels(labelDataPoints, grid);\r\n resultingLabels = resultingLabels.concat(labels);\r\n }\r\n\r\n return resultingLabels;\r\n }\r\n\r\n private positionLabels(labelDataPoints: DonutLabelDataPoint[], grid: LabelArrangeGrid): Label[] {\r\n let resultingLabels: Label[] = [];\r\n let offsetDelta = this.offsetIterationDelta;\r\n let currentOffset = this.startingOffset;\r\n let currentCenteredOffset = 0;\r\n\r\n while (currentOffset <= this.maximumOffset) {\r\n for (let labelPoint of labelDataPoints) {\r\n if (labelPoint.hasBeenRendered)\r\n continue;\r\n let label = this.tryPositionForDonut(labelPoint, grid, currentOffset);\r\n if (label)\r\n resultingLabels.push(label);\r\n }\r\n\r\n currentOffset += offsetDelta;\r\n currentCenteredOffset += offsetDelta;\r\n }\r\n\r\n return resultingLabels;\r\n }\r\n\r\n /**\r\n * We try to move the label 25% up/down if the label is truncated or it collides with other labels.\r\n * after we moved it once we check that the new position doesn't failed (collides with other labels).\r\n */\r\n private tryPositionForDonut(labelPoint: DonutLabelDataPoint, grid: LabelArrangeGrid, currentLabelOffset: number): Label {\r\n let parentShape: LabelParentPoint = <LabelParentPoint>labelPoint.parentShape;\r\n if (_.isEmpty(parentShape.validPositions) || parentShape.validPositions[0] === NewPointLabelPosition.None)\r\n return;\r\n\r\n let defaultPosition: NewPointLabelPosition = parentShape.validPositions[0];\r\n\r\n let bestCandidate = this.tryAllPositions(labelPoint, grid, defaultPosition, currentLabelOffset);\r\n\r\n if (bestCandidate && bestCandidate.score === 0) {\r\n return this.buildLabel(bestCandidate, grid);\r\n }\r\n // If we haven't found a non-truncated label, try to split into 2 lines.\r\n if (this.donutChartProperties.dataLabelsSettings.labelStyle === labelStyle.both) {\r\n // Try to split the label to two lines if both data and category label are on\r\n let splitLabelDataPoint = this.splitDonutDataPoint(labelPoint);\r\n let bestSplitCandidate = this.tryAllPositions(splitLabelDataPoint, grid, defaultPosition, currentLabelOffset);\r\n // If the best candidate with a split line is better than the best candidate with a single line, return the former.\r\n if (bestSplitCandidate && (!bestCandidate || (bestSplitCandidate.score < bestCandidate.score))) {\r\n return this.buildLabel(bestSplitCandidate, grid);\r\n }\r\n }\r\n\r\n // We didn't find a better candidate by splitting the label lines, so return our best single-line candidate.\r\n if (bestCandidate) {\r\n return this.buildLabel(bestCandidate, grid);\r\n }\r\n }\r\n\r\n private generateCandidate(labelDataPoint: DonutLabelDataPoint, candidatePosition: NewPointLabelPosition, grid: LabelArrangeGrid, currentLabelOffset: number): LabelCandidate {\r\n let angle = this.generateCandidateAngleForPosition(labelDataPoint.donutArcDescriptor, candidatePosition);\r\n let parentShape = this.getPointPositionForAngle(angle);\r\n let parentPoint = parentShape.point;\r\n let score = this.score(labelDataPoint, parentPoint);\r\n let leaderLinePoints = DonutLabelUtils.getLabelLeaderLineForDonutChart(labelDataPoint.donutArcDescriptor, this.donutChartProperties, parentPoint, angle);\r\n let leaderLinesSize: ISize[] = DonutLabelUtils.getLabelLeaderLinesSizeForDonutChart(leaderLinePoints);\r\n\r\n let newLabelDataPoint = _.clone(labelDataPoint);\r\n newLabelDataPoint.angle = angle;\r\n newLabelDataPoint.parentShape = parentShape;\r\n newLabelDataPoint.leaderLinePoints = leaderLinePoints;\r\n newLabelDataPoint.linesSize = leaderLinesSize;\r\n\r\n let boundingBoxs: DonutLabelRect = DonutLabelLayout.tryPositionPoint(grid, parentShape.validPositions[0], newLabelDataPoint, currentLabelOffset, this.center, this.donutChartProperties.viewport);\r\n\r\n return {\r\n angle: angle,\r\n point: parentShape,\r\n score: score,\r\n labelRects: boundingBoxs,\r\n labelDataPoint: newLabelDataPoint,\r\n };\r\n }\r\n\r\n private tryAllPositions(labelDataPoint: DonutLabelDataPoint, grid: LabelArrangeGrid, defaultPosition: NewPointLabelPosition, currentLabelOffset: number): LabelCandidate {\r\n let boundingBoxs = DonutLabelLayout.tryPositionPoint(grid, defaultPosition, labelDataPoint, currentLabelOffset, this.center, this.donutChartProperties.viewport);\r\n\r\n let originalPoint: LabelParentPoint = <LabelParentPoint>labelDataPoint.parentShape;\r\n let originalCandidate: LabelCandidate = {\r\n point: originalPoint,\r\n angle: labelDataPoint.angle,\r\n score: this.score(labelDataPoint, originalPoint.point),\r\n labelRects: boundingBoxs,\r\n labelDataPoint: labelDataPoint,\r\n };\r\n\r\n if (boundingBoxs && boundingBoxs.textRect && originalCandidate.score === 0) {\r\n return originalCandidate;\r\n }\r\n\r\n let positions: NewPointLabelPosition[] = [];\r\n let bestCandidate: LabelCandidate;\r\n if (boundingBoxs && boundingBoxs.textRect) {\r\n // We have a truncated label here, otherwised we would have returned already\r\n positions = this.getLabelPointPositions(labelDataPoint, /* isTruncated */ true);\r\n bestCandidate = originalCandidate;\r\n }\r\n else {\r\n positions = this.getLabelPointPositions(labelDataPoint, /* isTruncated */ false);\r\n }\r\n\r\n // Try to reposition the label if necessary\r\n for (let position of positions) {\r\n let candidate = this.generateCandidate(labelDataPoint, position, grid, currentLabelOffset);\r\n if (candidate.labelRects && candidate.labelRects.textRect) {\r\n if (bestCandidate == null || candidate.score < bestCandidate.score) {\r\n bestCandidate = candidate;\r\n if (bestCandidate.score === 0)\r\n return bestCandidate;\r\n }\r\n }\r\n }\r\n\r\n return bestCandidate;\r\n }\r\n\r\n private buildLabel(labelLayout: LabelCandidate, grid: LabelArrangeGrid): Label {\r\n let resultingBoundingBox = labelLayout.labelRects.textRect;\r\n let labelPoint = labelLayout.labelDataPoint;\r\n\r\n grid.add(resultingBoundingBox);\r\n grid.add(labelLayout.labelRects.horizontalLineRect);\r\n grid.add(labelLayout.labelRects.diagonalLineRect);\r\n labelPoint.hasBeenRendered = true;\r\n let left = resultingBoundingBox.left - this.center.x;\r\n //We need to add or subtract half resultingBoundingBox.width because Donut chart labels get text anchor start/end\r\n if (left < 0)\r\n left += resultingBoundingBox.width / 2;\r\n else\r\n left -= resultingBoundingBox.width / 2;\r\n let textAnchor = labelPoint.parentShape.validPositions[0] === NewPointLabelPosition.Right ? 'start' : 'end';\r\n let boundingBox: IRect = {\r\n left: left,\r\n top: resultingBoundingBox.top - this.center.y,\r\n height: resultingBoundingBox.height,\r\n width: resultingBoundingBox.width,\r\n };\r\n\r\n // After repositioning the label we need to recalculate its size and format it according to the current available space\r\n let labelSettingsStyle = this.donutChartProperties.dataLabelsSettings.labelStyle;\r\n let spaceAvailableForLabels = DonutLabelUtils.getSpaceAvailableForDonutLabels((<LabelParentPoint>labelPoint.parentShape).point.x, this.donutChartProperties.viewport);\r\n let formattedDataLabel: string;\r\n let formattedCategoryLabel: string;\r\n let text: string;\r\n let getLabelFormattedText = powerbi.visuals.dataLabelUtils.getLabelFormattedText;\r\n let fontSize = labelPoint.fontSize;\r\n let hasOneLabelRow = labelSettingsStyle === labelStyle.both && labelPoint.secondRowText == null;\r\n\r\n // Giving 50/50 space when both category and measure are on\r\n if (hasOneLabelRow) {\r\n labelPoint.dataLabel = \" (\" + labelPoint.dataLabel + \")\";\r\n spaceAvailableForLabels /= 2;\r\n }\r\n\r\n if (labelSettingsStyle === labelStyle.both || labelSettingsStyle === labelStyle.data) {\r\n formattedDataLabel = getLabelFormattedText({\r\n label: labelPoint.dataLabel,\r\n maxWidth: spaceAvailableForLabels,\r\n fontSize: fontSize\r\n });\r\n }\r\n\r\n if (labelSettingsStyle === labelStyle.both || labelSettingsStyle === labelStyle.category) {\r\n formattedCategoryLabel = getLabelFormattedText({\r\n label: labelPoint.categoryLabel,\r\n maxWidth: spaceAvailableForLabels,\r\n fontSize: fontSize\r\n });\r\n }\r\n\r\n switch (labelSettingsStyle) {\r\n case labelStyle.both:\r\n if (labelPoint.secondRowText == null) {\r\n text = formattedCategoryLabel + formattedDataLabel;\r\n }\r\n else {\r\n text = formattedDataLabel;\r\n labelPoint.secondRowText = formattedCategoryLabel; \r\n }\r\n break;\r\n case labelStyle.data:\r\n text = formattedDataLabel;\r\n break;\r\n case labelStyle.category:\r\n text = formattedCategoryLabel;\r\n break;\r\n }\r\n\r\n // Limit text size width for correct leader line calculation\r\n labelPoint.textSize.width = Math.min(labelPoint.textSize.width, hasOneLabelRow ? spaceAvailableForLabels * 2 : spaceAvailableForLabels);\r\n\r\n return {\r\n boundingBox: boundingBox,\r\n text: text,\r\n tooltip: labelPoint.tooltip,\r\n isVisible: true,\r\n fill: labelPoint.outsideFill,\r\n identity: labelPoint.identity,\r\n fontSize: fontSize,\r\n selected: false,\r\n textAnchor: textAnchor,\r\n leaderLinePoints: labelPoint.leaderLinePoints,\r\n hasBackground: false,\r\n secondRowText: labelPoint.secondRowText,\r\n };\r\n }\r\n\r\n private static tryPositionPoint(grid: LabelArrangeGrid, position: NewPointLabelPosition, labelDataPoint: DonutLabelDataPoint, offset: number, center: IVector, viewport: IViewport): DonutLabelRect {\r\n let parentPoint: LabelParentPoint = <LabelParentPoint>labelDataPoint.parentShape;\r\n \r\n // Limit label width to fit the availabe space for labels\r\n let textSize: ISize = _.clone(labelDataPoint.textSize);\r\n textSize.width = Math.min(textSize.width, DonutLabelUtils.getSpaceAvailableForDonutLabels(parentPoint.point.x, viewport));\r\n\r\n // Create label rectangle\r\n let labelRect = DataLabelPointPositioner.getLabelRect(textSize, parentPoint, position, offset);\r\n\r\n // Create label diagonal line rectangle\r\n let diagonalLineParentPoint: LabelParentPoint = {\r\n point: {\r\n x: labelDataPoint.leaderLinePoints[0][0],\r\n y: labelDataPoint.leaderLinePoints[0][1] < 0 ? labelDataPoint.leaderLinePoints[1][1] : labelDataPoint.leaderLinePoints[0][1]\r\n },\r\n radius: 0,\r\n validPositions: null\r\n };\r\n let diagonalLineRect = DataLabelPointPositioner.getLabelRect(labelDataPoint.linesSize[DonutLabelUtils.DiagonalLineIndex], diagonalLineParentPoint, position, offset);\r\n\r\n // Create label horizontal line rectangle\r\n let horizontalLineParentPoint: LabelParentPoint = {\r\n point: {\r\n x: labelDataPoint.leaderLinePoints[1][0],\r\n y: labelDataPoint.leaderLinePoints[1][1]\r\n },\r\n radius: 0,\r\n validPositions: null\r\n };\r\n let horizontalLineRect = DataLabelPointPositioner.getLabelRect(labelDataPoint.linesSize[DonutLabelUtils.HorizontalLineIndex], horizontalLineParentPoint, position, offset);\r\n\r\n if (!labelRect || !diagonalLineRect || !horizontalLineRect)\r\n return;\r\n\r\n labelRect.left += center.x;\r\n labelRect.top += center.y;\r\n let centerForLinesWidth = center.x - labelRect.width / 2;\r\n diagonalLineRect.left += centerForLinesWidth;\r\n diagonalLineRect.top += center.y;\r\n horizontalLineRect.left += centerForLinesWidth;\r\n horizontalLineRect.top += center.y;\r\n\r\n if (!grid.hasConflict(labelRect) && !grid.hasConflict(diagonalLineRect) && !grid.hasConflict(horizontalLineRect))\r\n return { textRect: labelRect, diagonalLineRect: diagonalLineRect, horizontalLineRect: horizontalLineRect };\r\n }\r\n\r\n /**\r\n * Returns an array of valid positions for hidden and truncated labels.\r\n * For truncated labels will return positions with more available space. \r\n * For hidden labels will return all possible positions by the order we draw labels (clockwise) \r\n */\r\n private getLabelPointPositions(labelPoint: DonutLabelDataPoint, isTruncated: boolean): NewPointLabelPosition[] {\r\n let parentShape: LabelParentPoint = <LabelParentPoint>labelPoint.parentShape;\r\n let position = parentShape.validPositions[0];\r\n\r\n if (!isTruncated) {\r\n return position === NewPointLabelPosition.Left\r\n ? [NewPointLabelPosition.AboveLeft, NewPointLabelPosition.BelowLeft]\r\n : [NewPointLabelPosition.BelowRight, NewPointLabelPosition.AboveRight];\r\n }\r\n\r\n if (parentShape.point.y < 0) {\r\n return position === NewPointLabelPosition.Right\r\n ? [NewPointLabelPosition.AboveRight]\r\n : [NewPointLabelPosition.AboveLeft];\r\n }\r\n else {\r\n return position === NewPointLabelPosition.Right\r\n ? [NewPointLabelPosition.BelowRight]\r\n : [NewPointLabelPosition.BelowLeft];\r\n }\r\n }\r\n\r\n /**\r\n * Returns a new DonutLabelDataPoint after splitting it into two lines\r\n */\r\n private splitDonutDataPoint(labelPoint: DonutLabelDataPoint): DonutLabelDataPoint {\r\n let textSize: ISize = {\r\n width: Math.max(labelPoint.categoryLabelSize.width, labelPoint.dataLabelSize.width),\r\n height: labelPoint.dataLabelSize.height * 2,\r\n };\r\n\r\n let newLabelPoint: DonutLabelDataPoint = _.clone(labelPoint);\r\n newLabelPoint.textSize = textSize;\r\n newLabelPoint.secondRowText = labelPoint.categoryLabel;\r\n return newLabelPoint;\r\n }\r\n\r\n private generateCandidateAngleForPosition(d: DonutArcDescriptor, position: NewPointLabelPosition): number {\r\n let midAngle = d.startAngle + ((d.endAngle - d.startAngle) / 2);\r\n\r\n switch (position) {\r\n case NewPointLabelPosition.AboveRight:\r\n case NewPointLabelPosition.BelowLeft:\r\n return ((d.startAngle + midAngle) - Math.PI) / 2;\r\n case NewPointLabelPosition.AboveLeft:\r\n case NewPointLabelPosition.BelowRight:\r\n return ((midAngle + d.endAngle) - Math.PI) / 2;\r\n default:\r\n debug.assertFail(\"Unsupported label position\");\r\n }\r\n }\r\n\r\n private getPointPositionForAngle(angle: number): LabelParentPoint {\r\n // Calculate the new label coordinates\r\n let labelX = DonutLabelUtils.getXPositionForDonutLabel(Math.cos(angle) * this.outerRadius);\r\n let labelY = Math.sin(angle) * this.outerRadius;\r\n\r\n let newPosition = labelX < 0 ? NewPointLabelPosition.Left : NewPointLabelPosition.Right;\r\n let pointPosition: LabelParentPoint = {\r\n point: {\r\n x: labelX,\r\n y: labelY,\r\n },\r\n validPositions: [newPosition],\r\n radius: 0,\r\n };\r\n return pointPosition;\r\n }\r\n\r\n private score(labelPoint: DonutLabelDataPoint, point: powerbi.visuals.shapes.IPoint): number {\r\n let spaceAvailableForLabels = DonutLabelUtils.getSpaceAvailableForDonutLabels(point.x, this.donutChartProperties.viewport);\r\n let textWidth: number;\r\n\r\n // Check if we show category and data labels in one row\r\n if (this.donutChartProperties.dataLabelsSettings.labelStyle === labelStyle.both && labelPoint.secondRowText == null) {\r\n // Each of the labels gets half of the available space for labels so we take this into consideration in the score\r\n textWidth = Math.max(labelPoint.categoryLabelSize.width, labelPoint.dataLabelSize.width + this.additionalCharsWidth);\r\n spaceAvailableForLabels /= 2;\r\n }\r\n else {\r\n textWidth = labelPoint.textSize.width;\r\n }\r\n\r\n return Math.max(textWidth - spaceAvailableForLabels, 0);\r\n }\r\n\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi {\r\n\r\n import ISize = powerbi.visuals.shapes.ISize;\r\n import IPoint = powerbi.visuals.IPoint;\r\n import IRect = powerbi.visuals.IRect;\r\n import Polygon = powerbi.visuals.shapes.Polygon;\r\n import Transform = powerbi.visuals.Transform;\r\n import NewDataLabelUtils = powerbi.visuals.NewDataLabelUtils;\r\n\r\n const DefaultCentroidOffset = 5;\r\n const OffsetDelta = 10;\r\n const MaximumOffset = 60;\r\n const stemExtension = 5;\r\n\r\n export interface LabelParentPolygon {\r\n /** The point this data label belongs to */\r\n polygon: Polygon;\r\n\r\n /** Valid positions to place the label ordered by preference */\r\n validPositions: NewPointLabelPosition[];\r\n }\r\n\r\n export interface FilledMapLabel extends Label {\r\n absoluteBoundingBoxCenter: IPoint;\r\n originalPixelOffset: number;\r\n originalPosition?: NewPointLabelPosition;\r\n originalAbsoluteCentroid?: IPoint;\r\n absoluteStemSource?: IPoint;\r\n isPlacedInsidePolygon: boolean;\r\n }\r\n\r\n export class FilledMapLabelLayout {\r\n private labels: FilledMapLabel[];\r\n\r\n public layout(labelDataPoints: LabelDataPoint[], viewport: IViewport, polygonInfoTransform: Transform, redrawDataLabels: boolean): Label[] {\r\n if (redrawDataLabels || this.labels === undefined) {\r\n let labelDataPointsGroup: LabelDataPointsGroup = {\r\n labelDataPoints: labelDataPoints,\r\n maxNumberOfLabels: labelDataPoints.length\r\n };\r\n\r\n for (let labelPoint of labelDataPoints) {\r\n labelPoint.labelSize = {\r\n width: labelPoint.textSize.width + 2 * NewDataLabelUtils.horizontalLabelBackgroundPadding,\r\n height: labelPoint.textSize.height + 2 * NewDataLabelUtils.verticalLabelBackgroundPadding,\r\n };\r\n }\r\n\r\n let grid = new LabelArrangeGrid([labelDataPointsGroup], viewport);\r\n let resultingDataLabels: FilledMapLabel[] = [];\r\n let allPolygons: Polygon[] = [];\r\n\r\n for (let labelPoint of labelDataPoints) {\r\n let polygon = (<LabelParentPolygon>labelPoint.parentShape).polygon;\r\n allPolygons.push(polygon);\r\n polygon.pixelBoundingRect = polygonInfoTransform.applyToRect(polygon.absoluteBoundingRect());\r\n }\r\n\r\n let shapesgrid = new LabelPolygonArrangeGrid(allPolygons, viewport);\r\n\r\n for (let labelPoint of labelDataPoints) {\r\n let dataLabel = this.getLabelByPolygonPositions(labelPoint, polygonInfoTransform, grid, shapesgrid);\r\n if (dataLabel != null) {\r\n resultingDataLabels.push(dataLabel);\r\n }\r\n }\r\n this.labels = resultingDataLabels;\r\n }\r\n else {\r\n this.updateLabelOffsets(polygonInfoTransform);\r\n }\r\n return this.labels;\r\n }\r\n\r\n public getLabelPolygon(mapDataPoint: LabelDataPoint, position: NewPointLabelPosition, pointPosition: IPoint, offset: number): IRect {\r\n let dataPointSize: ISize = {\r\n width: mapDataPoint.textSize.width,\r\n height: (mapDataPoint.textSize.height)\r\n };\r\n\r\n return this.getLabelBoundingBox(dataPointSize, position, pointPosition, offset);\r\n }\r\n\r\n private getLabelBoundingBox(dataPointSize: ISize, position: NewPointLabelPosition, pointPosition: IPoint, offset: number): IRect {\r\n switch (position) {\r\n case NewPointLabelPosition.Above: {\r\n return DataLabelPointPositioner.above(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.Below: {\r\n return DataLabelPointPositioner.below(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.Left: {\r\n return DataLabelPointPositioner.left(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.Right: {\r\n return DataLabelPointPositioner.right(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.AboveLeft: {\r\n return DataLabelPointPositioner.aboveLeft(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.AboveRight: {\r\n return DataLabelPointPositioner.aboveRight(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.BelowLeft: {\r\n return DataLabelPointPositioner.belowLeft(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.BelowRight: {\r\n return DataLabelPointPositioner.belowRight(dataPointSize, pointPosition, offset);\r\n }\r\n case NewPointLabelPosition.Center: {\r\n return DataLabelPointPositioner.center(dataPointSize, pointPosition);\r\n }\r\n default: {\r\n debug.assertFail(\"Unsupported label position\");\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private getLabelByPolygonPositions(labelPoint: LabelDataPoint, polygonInfoTransform: Transform, grid: LabelArrangeGrid, shapesGrid: LabelPolygonArrangeGrid): FilledMapLabel {\r\n let offset: number = 0;\r\n let inverseTransorm = polygonInfoTransform.getInverse();\r\n for (let i: number = 0; i < 2; i++) {\r\n if (i === 1) {\r\n offset = DefaultCentroidOffset;\r\n }\r\n for (let position of (<LabelParentPolygon>labelPoint.parentShape).validPositions) {\r\n let resultingAbsoluteBoundingBox = this.tryPositionForPolygonPosition(position, labelPoint, polygonInfoTransform, offset, inverseTransorm);\r\n if (position === NewPointLabelPosition.Center && i !== 0) {\r\n continue;\r\n }\r\n if (resultingAbsoluteBoundingBox) {\r\n let resultingBoundingBox = polygonInfoTransform.applyToRect(resultingAbsoluteBoundingBox);\r\n let dataLabel: FilledMapLabel = {\r\n text: labelPoint.text,\r\n secondRowText: labelPoint.secondRowText,\r\n boundingBox: resultingBoundingBox,\r\n isVisible: true,\r\n fill: labelPoint.insideFill,\r\n identity: null,\r\n selected: false,\r\n hasBackground: true,\r\n textAnchor: \"middle\",\r\n originalPixelOffset: offset,\r\n isPlacedInsidePolygon: true,\r\n absoluteBoundingBoxCenter: {\r\n x: resultingAbsoluteBoundingBox.left + resultingAbsoluteBoundingBox.width / 2,\r\n y: resultingAbsoluteBoundingBox.top + resultingAbsoluteBoundingBox.height / 2\r\n }\r\n };\r\n\r\n return dataLabel;\r\n }\r\n }\r\n }\r\n\r\n let currentOffset = 6;\r\n\r\n while (currentOffset <= MaximumOffset) {\r\n for (let position of (<powerbi.LabelParentPolygon>labelPoint.parentShape).validPositions) {\r\n if (position === NewPointLabelPosition.Center) {\r\n continue;\r\n }\r\n let polygon = (<LabelParentPolygon>labelPoint.parentShape).polygon;\r\n let pixelCentroid = polygonInfoTransform.applyToPoint(polygon.absoluteCentroid());\r\n let resultingAbsolutBoundingBox = this.tryPlaceLabelOutsidePolygon(grid, position, labelPoint, currentOffset, pixelCentroid, shapesGrid, inverseTransorm);\r\n\r\n if (resultingAbsolutBoundingBox) {\r\n let resultingBoundingBox = polygonInfoTransform.applyToRect(resultingAbsolutBoundingBox);\r\n let dataLabel: FilledMapLabel = {\r\n text: labelPoint.text,\r\n secondRowText: labelPoint.secondRowText,\r\n boundingBox: resultingBoundingBox,\r\n isVisible: true,\r\n fill: labelPoint.insideFill,\r\n identity: null,\r\n selected: false,\r\n hasBackground: true,\r\n isPlacedInsidePolygon: false,\r\n textAnchor: \"middle\",\r\n originalPixelOffset: currentOffset,\r\n originalPosition: position,\r\n originalAbsoluteCentroid: polygon.absoluteCentroid(),\r\n absoluteBoundingBoxCenter: {\r\n x: resultingAbsolutBoundingBox.left + resultingAbsolutBoundingBox.width / 2,\r\n y: resultingAbsolutBoundingBox.top + resultingAbsolutBoundingBox.height / 2\r\n }\r\n };\r\n\r\n let pixelStemSource = this.calculateStemSource(polygonInfoTransform, inverseTransorm, polygon, resultingBoundingBox, position, pixelCentroid);\r\n\r\n dataLabel.leaderLinePoints = this.setLeaderLinePoints(pixelStemSource, this.calculateStemDestination(resultingBoundingBox, position));\r\n\r\n dataLabel.absoluteStemSource = inverseTransorm.applyToPoint(pixelStemSource);\r\n\r\n grid.add(resultingBoundingBox);\r\n return dataLabel;\r\n }\r\n }\r\n currentOffset += OffsetDelta;\r\n }\r\n return null;\r\n }\r\n\r\n private setLeaderLinePoints(stemSource: IPoint, stemDestination: IPoint): number[][] {\r\n return [[stemSource.x, stemSource.y], [stemDestination.x, stemDestination.y]];\r\n }\r\n\r\n private calculateStemSource(polygonInfoTransform: Transform, inverseTransorm: Transform, polygon: Polygon, labelBoundingBox: IRect, position: NewPointLabelPosition, pixelCentroid: IPoint): IPoint {\r\n let absoluteStemSource = polygon.lineIntersectionPoint(polygon.absoluteCentroid(),\r\n inverseTransorm.applyToPoint({ x: labelBoundingBox.left + labelBoundingBox.width / 2, y: labelBoundingBox.top + labelBoundingBox.height / 2 }));\r\n\r\n if (absoluteStemSource == null) {\r\n return pixelCentroid;\r\n }\r\n\r\n let stemSource = polygonInfoTransform.applyToPoint(absoluteStemSource);\r\n\r\n switch (position) {\r\n case NewPointLabelPosition.Above: {\r\n stemSource.y += stemExtension;\r\n break;\r\n }\r\n case NewPointLabelPosition.Below: {\r\n stemSource.y -= stemExtension;\r\n break;\r\n }\r\n case NewPointLabelPosition.Left: {\r\n stemSource.x += stemExtension;\r\n break;\r\n }\r\n case NewPointLabelPosition.Right: {\r\n stemSource.x -= stemExtension;\r\n break;\r\n }\r\n case NewPointLabelPosition.AboveLeft: {\r\n stemSource.x += (stemExtension / DataLabelPointPositioner.cos45);\r\n stemSource.y += (stemExtension / DataLabelPointPositioner.sin45);\r\n break;\r\n }\r\n case NewPointLabelPosition.AboveRight: {\r\n stemSource.x -= (stemExtension / DataLabelPointPositioner.cos45);\r\n stemSource.y += (stemExtension / DataLabelPointPositioner.sin45);\r\n break;\r\n }\r\n case NewPointLabelPosition.BelowLeft: {\r\n stemSource.x += (stemExtension / DataLabelPointPositioner.cos45);\r\n stemSource.y -= (stemExtension / DataLabelPointPositioner.sin45);\r\n break;\r\n }\r\n case NewPointLabelPosition.BelowRight: {\r\n stemSource.x -= (stemExtension / DataLabelPointPositioner.cos45);\r\n stemSource.y -= (stemExtension / DataLabelPointPositioner.sin45);\r\n break;\r\n }\r\n case NewPointLabelPosition.Center: {\r\n break;\r\n }\r\n default: {\r\n debug.assertFail(\"Unsupported label position\");\r\n }\r\n }\r\n\r\n return stemSource;\r\n }\r\n\r\n private calculateStemDestination(labelBoundingBox: IRect, position: NewPointLabelPosition): IPoint {\r\n let x: number;\r\n let y: number;\r\n switch (position) {\r\n case NewPointLabelPosition.Above: {\r\n x = labelBoundingBox.left + labelBoundingBox.width / 2;\r\n y = labelBoundingBox.top + labelBoundingBox.height;\r\n break;\r\n }\r\n case NewPointLabelPosition.Below: {\r\n x = labelBoundingBox.left + labelBoundingBox.width / 2;\r\n y = labelBoundingBox.top;\r\n break;\r\n }\r\n case NewPointLabelPosition.Left: {\r\n x = labelBoundingBox.left + labelBoundingBox.width;\r\n y = labelBoundingBox.top + labelBoundingBox.height / 2;\r\n break;\r\n }\r\n case NewPointLabelPosition.Right: {\r\n x = labelBoundingBox.left;\r\n y = labelBoundingBox.top + labelBoundingBox.height / 2;\r\n break;\r\n }\r\n case NewPointLabelPosition.AboveLeft: {\r\n x = labelBoundingBox.left + labelBoundingBox.width;\r\n y = labelBoundingBox.top + labelBoundingBox.height;\r\n break;\r\n }\r\n case NewPointLabelPosition.AboveRight: {\r\n x = labelBoundingBox.left;\r\n y = labelBoundingBox.top + labelBoundingBox.height;\r\n break;\r\n }\r\n case NewPointLabelPosition.BelowLeft: {\r\n x = labelBoundingBox.left + labelBoundingBox.width;\r\n y = labelBoundingBox.top;\r\n break;\r\n }\r\n case NewPointLabelPosition.BelowRight: {\r\n x = labelBoundingBox.left;\r\n y = labelBoundingBox.top;\r\n break;\r\n }\r\n case NewPointLabelPosition.Center: {\r\n break;\r\n }\r\n default: {\r\n debug.assertFail(\"Unsupported label position\");\r\n }\r\n }\r\n\r\n return { x: x, y: y };\r\n }\r\n\r\n private tryPositionForPolygonPosition(position: NewPointLabelPosition, labelDataPoint: LabelDataPoint, polygonInfoTransform: Transform, offset: number, inverseTransorm: Transform) {\r\n let polygon = (<LabelParentPolygon>labelDataPoint.parentShape).polygon;\r\n let pixelCentroid = polygonInfoTransform.applyToPoint(polygon.absoluteCentroid());\r\n let labelRect = this.getLabelPolygon(labelDataPoint, position, pixelCentroid, offset);\r\n let absoluteLabelRect = this.getAbsoluteRectangle(inverseTransorm, labelRect);\r\n\r\n return polygon.contains(absoluteLabelRect) ? absoluteLabelRect : null;\r\n }\r\n\r\n /**\r\n * Tests a particular position/offset combination for the given data label.\r\n * If the label can be placed, returns the resulting bounding box for the data\r\n * label. If not, returns null.\r\n */\r\n private tryPlaceLabelOutsidePolygon(grid: LabelArrangeGrid, position: NewPointLabelPosition, labelDataPoint: LabelDataPoint, offset: number, pixelCentroid: IPoint, shapesGrid: LabelPolygonArrangeGrid, inverseTransform: powerbi.visuals.Transform): IRect {\r\n let offsetForPosition = offset;\r\n let labelRect = this.getLabelPolygon(labelDataPoint, position, pixelCentroid, offsetForPosition);\r\n\r\n let otherLabelsConflict = grid.hasConflict(labelRect);\r\n\r\n if (!otherLabelsConflict) {\r\n let absoluteLabelRect = this.getAbsoluteRectangle(inverseTransform, labelRect);\r\n\r\n if (!shapesGrid.hasConflict(absoluteLabelRect, labelRect))\r\n return absoluteLabelRect;\r\n }\r\n return null;\r\n }\r\n\r\n private updateLabelOffsets(polygonInfoTransform: Transform): void {\r\n for (let label of this.labels) {\r\n if (!label.isVisible)\r\n continue;\r\n\r\n if (label.isPlacedInsidePolygon) {\r\n var newOffset = polygonInfoTransform.applyToPoint(label.absoluteBoundingBoxCenter);\r\n\r\n let xDelta = (label.boundingBox.left + label.boundingBox.width / 2) - newOffset.x;\r\n let yDelta = (label.boundingBox.top + label.boundingBox.height / 2) - newOffset.y;\r\n\r\n label.boundingBox.top -= yDelta;\r\n label.boundingBox.left -= xDelta;\r\n } else {\r\n var stemSourcePoint = polygonInfoTransform.applyToPoint(label.absoluteStemSource);\r\n var pixelCentroid = polygonInfoTransform.applyToPoint(label.originalAbsoluteCentroid);\r\n label.boundingBox = this.getLabelBoundingBox({ width: label.boundingBox.width, height: label.boundingBox.height }, label.originalPosition, pixelCentroid, label.originalPixelOffset);\r\n\r\n if (label.leaderLinePoints !== undefined)\r\n label.leaderLinePoints = this.setLeaderLinePoints(stemSourcePoint, this.calculateStemDestination(label.boundingBox, label.originalPosition));\r\n }\r\n }\r\n }\r\n\r\n private getAbsoluteRectangle(inverseTransorm: Transform, rect: IRect) {\r\n return inverseTransorm.applyToRect(rect);\r\n }\r\n }\r\n\r\n export class LabelPolygonArrangeGrid {\r\n private grid: Polygon[][][];\r\n private viewport: IViewport;\r\n private cellSize: ISize;\r\n private columnCount: number;\r\n private rowCount: number;\r\n\r\n /** \r\n * A multiplier applied to the largest width height to attempt to balance # of\r\n * polygons in each cell and number of cells each polygon belongs to\r\n */\r\n private static cellSizeMultiplier = 2;\r\n\r\n constructor(polygons: Polygon[], viewport: IViewport) {\r\n this.viewport = viewport;\r\n let maxPolygonWidth = 0;\r\n let maxPolygonHeight = 0;\r\n\r\n for (let polygon of polygons) {\r\n let polygonSize: ISize = polygon.pixelBoundingRect;\r\n if (polygonSize.width > maxPolygonWidth) {\r\n maxPolygonWidth = polygonSize.width;\r\n }\r\n if (polygonSize.height > maxPolygonHeight) {\r\n maxPolygonHeight = polygonSize.height;\r\n }\r\n }\r\n\r\n if (maxPolygonWidth === 0) {\r\n maxPolygonWidth = viewport.width;\r\n }\r\n if (maxPolygonHeight === 0) {\r\n maxPolygonHeight = viewport.height;\r\n }\r\n\r\n let cellSize = this.cellSize = { width: maxPolygonWidth * LabelPolygonArrangeGrid.cellSizeMultiplier, height: maxPolygonHeight * LabelPolygonArrangeGrid.cellSizeMultiplier };\r\n this.columnCount = LabelPolygonArrangeGrid.getCellCount(cellSize.width, viewport.width, 1, 100);\r\n this.rowCount = LabelPolygonArrangeGrid.getCellCount(cellSize.height, viewport.height, 1, 100);\r\n let grid: Polygon[][][] = [];\r\n for (let i = 0, ilen = this.columnCount; i < ilen; i++) {\r\n grid[i] = [];\r\n for (let j = 0, jlen = this.rowCount; j < jlen; j++) {\r\n grid[i][j] = [];\r\n }\r\n }\r\n\r\n this.grid = grid;\r\n\r\n for (let polygon of polygons) {\r\n this.add(polygon);\r\n }\r\n\r\n }\r\n\r\n public hasConflict(absolutLabelRect: IRect, pixelLabelRect: IRect): boolean {\r\n let containingIndexRect = this.getContainingGridSubsection(pixelLabelRect);\r\n let grid = this.grid;\r\n for (let x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\r\n for (let y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\r\n for (let currentPolygon of grid[x][y]) {\r\n if (currentPolygon.conflicts(absolutLabelRect)) {\r\n return true;\r\n }\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n private add(polygon: Polygon): void {\r\n let containingIndexRect = this.getContainingGridSubsection(polygon.pixelBoundingRect);\r\n for (let x = containingIndexRect.xMin; x < containingIndexRect.xMax; x++) {\r\n for (let y = containingIndexRect.yMin; y < containingIndexRect.yMax; y++) {\r\n this.grid[x][y].push(polygon);\r\n }\r\n }\r\n }\r\n\r\n private getContainingGridSubsection(rect: IRect): GridSubsection {\r\n return {\r\n xMin: LabelPolygonArrangeGrid.bound(Math.floor(rect.left / this.cellSize.width), 0, this.columnCount),\r\n xMax: LabelPolygonArrangeGrid.bound(Math.ceil((rect.left + rect.width) / this.cellSize.width), 0, this.columnCount),\r\n yMin: LabelPolygonArrangeGrid.bound(Math.floor(rect.top / this.cellSize.height), 0, this.rowCount),\r\n yMax: LabelPolygonArrangeGrid.bound(Math.ceil((rect.top + rect.height) / this.cellSize.height), 0, this.rowCount),\r\n };\r\n }\r\n\r\n private static getCellCount(step: number, length: number, minCount: number, maxCount: number): number {\r\n return LabelPolygonArrangeGrid.bound(Math.ceil(length / step), minCount, maxCount);\r\n }\r\n\r\n private static bound(value: number, min: number, max: number): number {\r\n return Math.max(Math.min(value, max), min);\r\n }\r\n\r\n }\r\n\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export function createColorAllocatorFactory(): IColorAllocatorFactory {\r\n return new ColorAllocatorFactory();\r\n }\r\n\r\n class ColorAllocatorFactory implements IColorAllocatorFactory {\r\n public linearGradient2(options: LinearGradient2): IColorAllocator {\r\n return new LinearGradient2Allocator(options);\r\n }\r\n\r\n public linearGradient3(options: LinearGradient3, splitScales: boolean): IColorAllocator {\r\n if (splitScales)\r\n return new LinearGradient3AllocatorWithSplittedScales(options);\r\n return new LinearGradient3Allocator(options);\r\n }\r\n }\r\n\r\n class LinearGradient2Allocator implements IColorAllocator {\r\n private options: LinearGradient2;\r\n private scale: D3.Scale.LinearScale;\r\n \r\n constructor(options: LinearGradient2) {\r\n debug.assertValue(options, 'options');\r\n\r\n this.options = options;\r\n\r\n let min = options.min,\r\n max = options.max;\r\n this.scale = d3.scale.linear()\r\n .domain([min.value, max.value])\r\n .range([min.color, max.color])\r\n .clamp(true); // process a value outside of the domain - set to extremum values\r\n }\r\n\r\n public color(value: number): string {\r\n let min = this.options.min,\r\n max = this.options.max;\r\n if (min.value === max.value) {\r\n if (value >= max.value)\r\n return max.color;\r\n return min.color;\r\n }\r\n return <any>this.scale(value);\r\n }\r\n }\r\n\r\n class LinearGradient3Allocator implements IColorAllocator {\r\n private options: LinearGradient3;\r\n private scale: D3.Scale.LinearScale;\r\n\r\n constructor(options: LinearGradient3) {\r\n debug.assertValue(options, 'options');\r\n\r\n this.options = options;\r\n\r\n let min = options.min,\r\n mid = options.mid,\r\n max = options.max;\r\n this.scale = d3.scale.linear()\r\n .domain([min.value, mid.value, max.value])\r\n .range([min.color, mid.color, max.color])\r\n .clamp(true); // process a value outside of the domain- set to extremum values\r\n }\r\n\r\n public color(value: number): string {\r\n let min = this.options.min,\r\n mid = this.options.mid,\r\n max = this.options.max;\r\n\r\n if (max.value === mid.value || mid.value === min.value || (max.value === mid.value && max.value === min.value)) {\r\n if (value >= max.value)\r\n return max.color;\r\n else if (value >= mid.value)\r\n return mid.color;\r\n return min.color;\r\n }\r\n return <any>this.scale(value);\r\n }\r\n }\r\n\r\n class LinearGradient3AllocatorWithSplittedScales implements IColorAllocator {\r\n private options: LinearGradient3;\r\n private scale1: D3.Scale.LinearScale;\r\n private scale2: D3.Scale.LinearScale;\r\n\r\n constructor(options: LinearGradient3) {\r\n debug.assertValue(options, 'options');\r\n\r\n this.options = options;\r\n\r\n let min = options.min,\r\n mid = options.mid,\r\n max = options.max;\r\n /*\r\n If the center value is overridden, but the max and min remain automatic,\r\n colors are then assigned on a scale between the overridden center value and the max/min values in the data.\r\n Each side of the center value is assigned separately, independent of the relative scales.\r\n */\r\n this.scale1 = d3.scale.linear()\r\n .domain([min.value, mid.value])\r\n .range([min.color, mid.color])\r\n .clamp(true); // process a value outside of the domain- set to extremum values\r\n this.scale2 = d3.scale.linear()\r\n .domain([mid.value, max.value])\r\n .range([mid.color, max.color])\r\n .clamp(true); // process a value outside of the domain- set to extremum values\r\n }\r\n\r\n public color(value: number): string {\r\n let min = this.options.min,\r\n mid = this.options.mid,\r\n max = this.options.max;\r\n\r\n if (max.value === mid.value || mid.value === min.value || (max.value === mid.value && max.value === min.value)) {\r\n if (value >= max.value)\r\n return max.color;\r\n else if (value >= mid.value)\r\n return mid.color;\r\n return min.color;\r\n }\r\n else if (value <= mid.value) {\r\n return <any>this.scale1(value);\r\n }\r\n return <any>this.scale2(value);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n const BeautifiedFormat: { [x: string]: string } = {\r\n '0.00 %;-0.00 %;0.00 %': 'Percentage',\r\n '0.0 %;-0.0 %;0.0 %': 'Percentage1',\r\n };\r\n\r\n const defaultLocalizedStrings = {\r\n 'NullValue': '(Blank)',\r\n 'BooleanTrue': 'True',\r\n 'BooleanFalse': 'False',\r\n 'NaNValue': 'NaN',\r\n 'InfinityValue': '+Infinity',\r\n 'NegativeInfinityValue': '-Infinity',\r\n 'Restatement_Comma': '{0}, {1}',\r\n 'Restatement_CompoundAnd': '{0} and {1}',\r\n 'DisplayUnitSystem_EAuto_Title': 'Auto',\r\n 'DisplayUnitSystem_E0_Title': 'None',\r\n 'DisplayUnitSystem_E3_LabelFormat': '{0}K',\r\n 'DisplayUnitSystem_E3_Title': 'Thousands',\r\n 'DisplayUnitSystem_E6_LabelFormat': '{0}M',\r\n 'DisplayUnitSystem_E6_Title': 'Millions',\r\n 'DisplayUnitSystem_E9_LabelFormat': '{0}bn',\r\n 'DisplayUnitSystem_E9_Title': 'Billions',\r\n 'DisplayUnitSystem_E12_LabelFormat': '{0}T',\r\n 'DisplayUnitSystem_E12_Title': 'Trillions',\r\n 'Percentage': '#,0.##%',\r\n 'Percentage1': '#,0.#%',\r\n 'RichTextbox_Link_DefaultText': 'Link',\r\n 'TableTotalLabel': 'Total',\r\n 'Tooltip_HighlightedValueDisplayName': 'Highlighted',\r\n 'Funnel_PercentOfFirst': 'Percent of first',\t\r\n 'Funnel_PercentOfPrevious': 'Percent of previous',\r\n 'Funnel_PercentOfFirst_Highlight': 'Percent of first (highlighted)',\r\n 'Funnel_PercentOfPrevious_Highlight': 'Percent of previous (highlighted)',\r\n // Geotagging strings\r\n 'GeotaggingString_Continent': 'continent',\r\n 'GeotaggingString_Continents': 'continents',\r\n 'GeotaggingString_Country': 'country',\r\n 'GeotaggingString_Countries': 'countries',\r\n 'GeotaggingString_State': 'state',\r\n 'GeotaggingString_States': 'states',\r\n 'GeotaggingString_City': 'city',\r\n 'GeotaggingString_Cities': 'cities',\r\n 'GeotaggingString_Town': 'town',\r\n 'GeotaggingString_Towns': 'towns',\r\n 'GeotaggingString_Province': 'province',\r\n 'GeotaggingString_Provinces': 'provinces',\r\n 'GeotaggingString_County': 'county',\r\n 'GeotaggingString_Counties': 'counties',\r\n 'GeotaggingString_Village': 'village',\r\n 'GeotaggingString_Villages': 'villages',\r\n 'GeotaggingString_Post': 'post',\r\n 'GeotaggingString_Zip': 'zip',\r\n 'GeotaggingString_Code': 'code',\r\n 'GeotaggingString_Place': 'place',\r\n 'GeotaggingString_Places': 'places',\r\n 'GeotaggingString_Address': 'address',\r\n 'GeotaggingString_Addresses': 'addresses',\r\n 'GeotaggingString_Street': 'street',\r\n 'GeotaggingString_Streets': 'streets',\r\n 'GeotaggingString_Longitude': 'longitude',\r\n 'GeotaggingString_Longitude_Short': 'lon',\r\n 'GeotaggingString_Latitude': 'latitude',\r\n 'GeotaggingString_Latitude_Short': 'lat',\r\n 'GeotaggingString_PostalCode': 'postal code',\r\n 'GeotaggingString_PostalCodes': 'postal codes',\r\n 'GeotaggingString_ZipCode': 'zip code',\r\n 'GeotaggingString_ZipCodes': 'zip codes',\r\n 'GeotaggingString_Territory': 'territory',\r\n 'GeotaggingString_Territories': 'territories',\r\n 'Waterfall_IncreaseLabel': 'Increase',\r\n 'Waterfall_DecreaseLabel': 'Decrease',\r\n 'Waterfall_TotalLabel': 'Total',\r\n 'Slicer_SelectAll': 'Select All',\r\n };\r\n\r\n export class DefaultVisualHostServices implements IVisualHostServices {\r\n // TODO: Add locale-awareness to this host service. Currently default/english functionality only.\r\n public static initialize(): void {\r\n visuals.valueFormatter.setLocaleOptions(DefaultVisualHostServices.createLocaleOptions());\r\n visuals.TooltipManager.setLocalizedStrings(DefaultVisualHostServices.createTooltipLocaleOptions());\r\n }\r\n \r\n /**\r\n * Create locale options.\r\n * \r\n * Note: Public for testability.\r\n */\r\n public static createLocaleOptions(): visuals.ValueFormatterLocalizationOptions {\r\n return {\r\n null: defaultLocalizedStrings['NullValue'],\r\n true: defaultLocalizedStrings['BooleanTrue'],\r\n false: defaultLocalizedStrings['BooleanFalse'],\r\n NaN: defaultLocalizedStrings['NaNValue'],\r\n infinity: defaultLocalizedStrings['InfinityValue'],\r\n negativeInfinity: defaultLocalizedStrings['NegativeInfinityValue'],\r\n beautify: format => DefaultVisualHostServices.beautify(format),\r\n describe: exponent => DefaultVisualHostServices.describeUnit(exponent),\r\n restatementComma: defaultLocalizedStrings['Restatement_Comma'],\r\n restatementCompoundAnd: defaultLocalizedStrings['Restatement_CompoundAnd'],\r\n restatementCompoundOr: defaultLocalizedStrings['Restatement_CompoundOr']\r\n };\r\n }\r\n\r\n public static createTooltipLocaleOptions(): powerbi.visuals.TooltipLocalizationOptions {\r\n return {\r\n highlightedValueDisplayName: defaultLocalizedStrings['Tooltip_HighlightedValueDisplayName']\r\n };\r\n }\r\n\r\n public getLocalizedString(stringId: string): string {\r\n return defaultLocalizedStrings[stringId];\r\n }\r\n\r\n // NO-OP IHostServices methods\r\n public onDragStart(): void { }\r\n public canSelect(): boolean { return false; }\r\n public onSelect(): void { }\r\n public onContextMenu(): void { }\r\n public loadMoreData(): void { }\r\n public persistProperties(changes: VisualObjectInstance[] | VisualObjectInstancesToPersist): void { }\r\n public onCustomSort(args: CustomSortEventArgs) { }\r\n public getViewMode(): powerbi.ViewMode { return ViewMode.View; }\r\n public setWarnings(warnings: IVisualWarning[]): void { }\r\n public setToolbar($toolbar: JQuery): void { }\r\n public shouldRetainSelection(): boolean { return false; }\r\n public geocoder(): IGeocoder { return services.createGeocoder(); }\r\n public geolocation(): IGeolocation { return services.createGeolocation(); }\r\n public promiseFactory(): IPromiseFactory { return createJQueryPromiseFactory(); }\r\n public analyzeFilter(options: FilterAnalyzerOptions): AnalyzedFilter {\r\n return {\r\n isNotFilter: false,\r\n selectedIdentities: [],\r\n filter: undefined,\r\n defaultValue: undefined,\r\n };\r\n }\r\n public getIdentityDisplayNames(dentities: DataViewScopeIdentity[]): DisplayNameIdentityPair[] { return; } \r\n public setIdentityDisplayNames(displayNamesIdentityPairs: DisplayNameIdentityPair[]): void { }\r\n\r\n private static beautify(format: string): string {\r\n let key = BeautifiedFormat[format];\r\n if (key)\r\n return defaultLocalizedStrings[key] || format;\r\n return format;\r\n }\r\n\r\n private static describeUnit(exponent: number): DisplayUnitSystemNames {\r\n let exponentLookup = (exponent === -1) ? 'Auto' : exponent.toString();\r\n\r\n let title: string = defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_Title\"];\r\n let format: string = (exponent <= 0) ? '{0}' : defaultLocalizedStrings[\"DisplayUnitSystem_E\" + exponentLookup + \"_LabelFormat\"];\r\n\r\n if (title || format)\r\n return { title: title, format: format };\r\n }\r\n }\r\n\r\n export const defaultVisualHostServices: IVisualHostServices = new DefaultVisualHostServices();\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n\r\n export interface SelectableDataPoint {\r\n selected: boolean;\r\n identity: SelectionId;\r\n }\r\n\r\n /**\r\n * Factory method to create an IInteractivityService instance.\r\n */\r\n export function createInteractivityService(hostServices: IVisualHostServices): IInteractivityService {\r\n return new InteractivityService(hostServices);\r\n }\r\n\r\n /**\r\n * Creates a clear an svg rect to catch clear clicks.\r\n */\r\n export function appendClearCatcher(selection: D3.Selection): D3.Selection {\r\n return selection\r\n .append(\"rect\")\r\n .classed(\"clearCatcher\", true)\r\n .attr({ width: \"100%\", height: \"100%\" });\r\n }\r\n\r\n export function isCategoryColumnSelected(propertyId: DataViewObjectPropertyIdentifier, categories: DataViewCategoricalColumn, idx: number): boolean {\r\n return categories.objects != null\r\n && categories.objects[idx]\r\n && DataViewObjects.getValue<boolean>(categories.objects[idx], propertyId);\r\n }\r\n\r\n export function dataHasSelection(data: SelectableDataPoint[]): boolean {\r\n for (let i = 0, ilen = data.length; i < ilen; i++) {\r\n if (data[i].selected)\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n export interface IInteractiveBehavior {\r\n bindEvents(behaviorOptions: any, selectionHandler: ISelectionHandler): void;\r\n renderSelection(hasSelection: boolean): void;\r\n }\r\n\r\n /**\r\n * An optional options bag for binding to the interactivityService\r\n */\r\n export interface InteractivityServiceOptions {\r\n isLegend?: boolean;\r\n isLabels?: boolean;\r\n overrideSelectionFromData?: boolean;\r\n hasSelectionOverride?: boolean;\r\n slicerDefaultValueHandler?: SlicerDefaultValueHandler;\r\n }\r\n\r\n /**\r\n * Responsible for managing interactivity between the hosting visual and its peers\r\n */\r\n export interface IInteractivityService {\r\n /** Binds the visual to the interactivityService */\r\n bind(dataPoints: SelectableDataPoint[], behavior: IInteractiveBehavior, behaviorOptions: any, iteractivityServiceOptions?: InteractivityServiceOptions);\r\n\r\n /** Clears the selection */\r\n clearSelection(): void;\r\n\r\n /** Sets the selected state on the given data points. */\r\n applySelectionStateToData(dataPoints: SelectableDataPoint[]): boolean;\r\n\r\n /** Checks whether there is at least one item selected */\r\n hasSelection(): boolean;\r\n\r\n /** Checks whether there is at least one item selected within the legend */\r\n legendHasSelection(): boolean;\r\n\r\n /** Checks whether the selection mode is inverted or normal */\r\n isSelectionModeInverted(): boolean;\r\n\r\n /** Sets whether the selection mode is inverted or normal */\r\n setSelectionModeInverted(inverted: boolean): void;\r\n\r\n setDefaultValueMode(useDefaultValue: boolean): void;\r\n\r\n isDefaultValueEnabled(): boolean;\r\n }\r\n\r\n export interface ISelectionHandler {\r\n /** Handles a selection event by selecting the given data point */\r\n handleSelection(dataPoint: SelectableDataPoint, multiSelect: boolean): void;\r\n\r\n /** Handles a request for a context menu. */\r\n handleContextMenu(dataPoint: SelectableDataPoint, position: IPoint): void;\r\n\r\n /** Handles a selection clear, clearing all selection state */\r\n handleClearSelection(): void;\r\n\r\n /** Toggles the selection mode between normal and inverted; returns true if the new mode is inverted */\r\n toggleSelectionModeInversion(): boolean;\r\n\r\n /** Sends the selection state to the host */\r\n persistSelectionFilter(filterPropertyIdentifier: DataViewObjectPropertyIdentifier): void;\r\n }\r\n\r\n export class InteractivityService implements IInteractivityService, ISelectionHandler {\r\n // References\r\n private hostService: IVisualHostServices;\r\n private renderSelectionInVisual = _.noop;\r\n private renderSelectionInLegend = _.noop;\r\n private renderSelectionInLabels = _.noop;\r\n\r\n // Selection state\r\n private selectedIds: SelectionId[] = [];\r\n private isInvertedSelectionMode: boolean = false;\r\n private hasSelectionOverride: boolean;\r\n private behavior: any;\r\n private slicerDefaultValueHandler: SlicerDefaultValueHandler;\r\n\r\n // undefined means no default value is set\r\n // True: apply default value. False: apply AnyValue.\r\n private useDefaultValue: boolean;\r\n\r\n public selectableDataPoints: SelectableDataPoint[];\r\n public selectableLegendDataPoints: SelectableDataPoint[];\r\n public selectableLabelsDataPoints: SelectableDataPoint[];\r\n\r\n constructor(hostServices: IVisualHostServices) {\r\n debug.assertValue(hostServices, 'hostServices');\r\n\r\n this.hostService = hostServices;\r\n }\r\n\r\n // IInteractivityService Implementation\r\n\r\n /** Binds the vsiual to the interactivityService */\r\n public bind(dataPoints: SelectableDataPoint[], behavior: IInteractiveBehavior, behaviorOptions: any, options?: InteractivityServiceOptions): void {\r\n // Bind the data\r\n if (options && options.overrideSelectionFromData) {\r\n // Override selection state from data points if needed\r\n this.takeSelectionStateFromDataPoints(dataPoints);\r\n }\r\n if (options){\r\n if (options.isLegend) {\r\n // Bind to legend data instead of normal data if isLegend\r\n this.selectableLegendDataPoints = dataPoints;\r\n this.renderSelectionInLegend = () => behavior.renderSelection(this.legendHasSelection());\r\n }\r\n else if (options.isLabels) {\r\n //Bind to label data instead of normal data if isLabels\r\n this.selectableLabelsDataPoints = dataPoints;\r\n this.renderSelectionInLabels = () => behavior.renderSelection(this.labelsHasSelection());\r\n }\r\n else {\r\n this.selectableDataPoints = dataPoints;\r\n this.renderSelectionInVisual = () => behavior.renderSelection(this.hasSelection());\r\n }\r\n if (options.hasSelectionOverride != null) {\r\n this.hasSelectionOverride = options.hasSelectionOverride;\r\n }\r\n if (options.slicerDefaultValueHandler) {\r\n this.slicerDefaultValueHandler = options.slicerDefaultValueHandler;\r\n }\r\n } \r\n else {\r\n this.selectableDataPoints = dataPoints;\r\n this.renderSelectionInVisual = () => behavior.renderSelection(this.hasSelection());\r\n }\r\n\r\n // Bind to the behavior\r\n this.behavior = behavior;\r\n behavior.bindEvents(behaviorOptions, this);\r\n // Sync data points with current selection state\r\n this.syncSelectionState();\r\n }\r\n\r\n /**\r\n * Sets the selected state of all selectable data points to false and invokes the behavior's select command.\r\n */\r\n public clearSelection(): void {\r\n // if default value is already applied, don't clear the default selection\r\n if (this.slicerDefaultValueHandler && this.slicerDefaultValueHandler.getDefaultValue() && this.useDefaultValue) {\r\n this.isInvertedSelectionMode = false;\r\n return;\r\n }\r\n\r\n this.hasSelectionOverride = undefined;\r\n ArrayExtensions.clear(this.selectedIds);\r\n this.isInvertedSelectionMode = false;\r\n this.applyToAllSelectableDataPoints((dataPoint: SelectableDataPoint) => dataPoint.selected = false);\r\n this.renderAll();\r\n }\r\n\r\n public applySelectionStateToData(dataPoints: SelectableDataPoint[]): boolean {\r\n for (let dataPoint of dataPoints) {\r\n dataPoint.selected = InteractivityService.checkDatapointAgainstSelectedIds(dataPoint, this.selectedIds);\r\n }\r\n\r\n return this.hasSelection();\r\n }\r\n\r\n /**\r\n * Checks whether there is at least one item selected.\r\n */\r\n public hasSelection(): boolean {\r\n return this.selectedIds.length > 0;\r\n }\r\n\r\n public legendHasSelection(): boolean {\r\n return this.selectableLegendDataPoints ? dataHasSelection(this.selectableLegendDataPoints) : false;\r\n }\r\n\r\n public labelsHasSelection(): boolean {\r\n return this.selectableLabelsDataPoints ? dataHasSelection(this.selectableLabelsDataPoints) : false;\r\n }\r\n\r\n public isSelectionModeInverted(): boolean {\r\n return this.isInvertedSelectionMode;\r\n }\r\n\r\n public setSelectionModeInverted(inverted: boolean): void {\r\n this.isInvertedSelectionMode = inverted;\r\n }\r\n\r\n // ISelectionHandler Implementation\r\n\r\n public handleSelection(dataPoint: SelectableDataPoint, multiSelect: boolean): void {\r\n // defect 7067397: should not happen so assert but also don't continue as it's\r\n // causing a lot of error telemetry in desktop.\r\n debug.assertValue(dataPoint, 'dataPoint');\r\n if (!dataPoint)\r\n return;\r\n\r\n this.useDefaultValue = false;\r\n this.select(dataPoint, multiSelect);\r\n this.sendSelectionToHost();\r\n this.renderAll();\r\n }\r\n\r\n public handleContextMenu(dataPoint: SelectableDataPoint, point: IPoint): void {\r\n this.sendContextMenuToHost(dataPoint, point);\r\n }\r\n\r\n public handleClearSelection(): void {\r\n this.useDefaultValue = true;\r\n this.clearSelection();\r\n this.sendSelectionToHost();\r\n }\r\n\r\n public toggleSelectionModeInversion(): boolean {\r\n this.useDefaultValue = false;\r\n this.isInvertedSelectionMode = !this.isInvertedSelectionMode;\r\n ArrayExtensions.clear(this.selectedIds);\r\n this.applyToAllSelectableDataPoints((dataPoint: SelectableDataPoint) => dataPoint.selected = false);\r\n this.sendSelectionToHost();\r\n this.isInvertedSelectionMode ? this.syncSelectionStateInverted() : this.syncSelectionState();\r\n this.renderAll();\r\n return this.isInvertedSelectionMode;\r\n }\r\n\r\n public persistSelectionFilter(filterPropertyIdentifier: DataViewObjectPropertyIdentifier): void {\r\n this.hostService.persistProperties(this.createChangeForFilterProperty(filterPropertyIdentifier));\r\n }\r\n\r\n public setDefaultValueMode(useDefaultValue: boolean): void {\r\n this.useDefaultValue = useDefaultValue;\r\n }\r\n\r\n public isDefaultValueEnabled(): boolean {\r\n return this.useDefaultValue;\r\n }\r\n\r\n // Private utility methods\r\n\r\n private renderAll(): void {\r\n this.renderSelectionInVisual();\r\n this.renderSelectionInLegend();\r\n this.renderSelectionInLabels();\r\n }\r\n\r\n /** Marks a data point as selected and syncs selection with the host. */\r\n private select(d: SelectableDataPoint, multiSelect: boolean): void {\r\n // If we're in inverted mode, use the invertedSelect instead\r\n if (this.isInvertedSelectionMode) {\r\n return this.selectInverted(d, multiSelect);\r\n }\r\n\r\n // For highlight data points we actually want to select the non-highlight data point\r\n if (d.identity.highlight) {\r\n d = _.find(this.selectableDataPoints, (dp: SelectableDataPoint) => !dp.identity.highlight && d.identity.includes(dp.identity, /* ignoreHighlight */ true));\r\n debug.assertValue(d, 'Expected to find a non-highlight data point');\r\n }\r\n\r\n let id = d.identity;\r\n\r\n if (!id)\r\n return;\r\n\r\n let selected = !d.selected || (!multiSelect && this.selectedIds.length > 1);\r\n\r\n // If we have a multiselect flag, we attempt a multiselect\r\n if (multiSelect) {\r\n if (selected) {\r\n d.selected = true;\r\n this.selectedIds.push(id);\r\n if (id.hasIdentity()) {\r\n this.removeSelectionIdsWithOnlyMeasures();\r\n }\r\n else {\r\n this.removeSelectionIdsExceptOnlyMeasures();\r\n }\r\n }\r\n else {\r\n d.selected = false;\r\n this.removeId(id);\r\n }\r\n }\r\n // We do a single select if we didn't do a multiselect or if we find out that the multiselect is invalid.\r\n if (!multiSelect || !this.hostService.canSelect({ data: this.selectedIds.map((value: SelectionId) => value.getSelector()) })) {\r\n this.clearSelection();\r\n if (selected) {\r\n d.selected = true;\r\n this.selectedIds.push(id);\r\n }\r\n }\r\n\r\n this.syncSelectionState();\r\n }\r\n\r\n private selectInverted(d: SelectableDataPoint, multiSelect: boolean): void {\r\n let wasSelected = d.selected;\r\n let id = d.identity;\r\n debug.assert(!!multiSelect, \"inverted selections are only supported in multiselect mode\");\r\n\r\n // the current datapoint state has to be inverted\r\n d.selected = !wasSelected;\r\n\r\n if (wasSelected) {\r\n this.removeId(id);\r\n }\r\n else {\r\n this.selectedIds.push(id);\r\n if (id.hasIdentity()) {\r\n this.removeSelectionIdsWithOnlyMeasures();\r\n }\r\n else {\r\n this.removeSelectionIdsExceptOnlyMeasures();\r\n }\r\n }\r\n\r\n this.syncSelectionStateInverted();\r\n }\r\n\r\n private removeId(toRemove: SelectionId): void {\r\n let selectedIds = this.selectedIds;\r\n for (let i = selectedIds.length - 1; i > -1; i--) {\r\n let currentId = selectedIds[i];\r\n\r\n if (toRemove.includes(currentId))\r\n selectedIds.splice(i, 1);\r\n }\r\n }\r\n\r\n /** Note: Public for UnitTesting */\r\n public createChangeForFilterProperty(filterPropertyIdentifier: DataViewObjectPropertyIdentifier): VisualObjectInstancesToPersist {\r\n let properties: { [propertyName: string]: DataViewPropertyValue } = {};\r\n let selectors: data.Selector[] = [];\r\n\r\n if (this.selectedIds.length > 0) {\r\n selectors = _.chain(this.selectedIds)\r\n .filter((value: SelectionId) => value.hasIdentity())\r\n .map((value: SelectionId) => value.getSelector())\r\n .value();\r\n }\r\n\r\n let instance = {\r\n objectName: filterPropertyIdentifier.objectName,\r\n selector: undefined,\r\n properties: properties\r\n };\r\n\r\n let filter = powerbi.data.Selector.filterFromSelector(selectors, this.isInvertedSelectionMode);\r\n\r\n if (this.slicerDefaultValueHandler && this.slicerDefaultValueHandler.getDefaultValue()) {\r\n // we explicitly check for true/false because undefine means no default value\r\n if (this.useDefaultValue === true)\r\n filter = powerbi.data.SemanticFilter.getDefaultValueFilter(this.slicerDefaultValueHandler.getIdentityFields());\r\n else if (_.isEmpty(selectors))\r\n filter = powerbi.data.SemanticFilter.getAnyValueFilter(this.slicerDefaultValueHandler.getIdentityFields());\r\n }\r\n\r\n if (filter == null) {\r\n properties[filterPropertyIdentifier.propertyName] = {};\r\n return <VisualObjectInstancesToPersist> {\r\n remove: [instance]\r\n };\r\n }\r\n else {\r\n properties[filterPropertyIdentifier.propertyName] = filter;\r\n return <VisualObjectInstancesToPersist> {\r\n merge: [instance]\r\n };\r\n }\r\n }\r\n\r\n private sendContextMenuToHost(dataPoint: SelectableDataPoint, position: IPoint): void {\r\n let host = this.hostService;\r\n if (!host.onContextMenu)\r\n return;\r\n\r\n let selectors = this.getSelectorsByColumn([dataPoint.identity]);\r\n if (_.isEmpty(selectors))\r\n return;\r\n\r\n let args: ContextMenuArgs = {\r\n data: selectors,\r\n position: position\r\n };\r\n\r\n host.onContextMenu(args);\r\n }\r\n\r\n private sendSelectionToHost() {\r\n let host = this.hostService;\r\n if (host.onSelect) {\r\n let selectArgs: SelectEventArgs = {\r\n data: this.selectedIds.filter((value: SelectionId) => value.hasIdentity()).map((value: SelectionId) => value.getSelector())\r\n };\r\n\r\n let data2 = this.getSelectorsByColumn(this.selectedIds);\r\n\r\n if (!_.isEmpty(data2))\r\n selectArgs.data2 = data2;\r\n\r\n host.onSelect(selectArgs);\r\n }\r\n }\r\n\r\n private getSelectorsByColumn(selectionIds: SelectionId[]): SelectorsByColumn[] {\r\n return _(selectionIds)\r\n .filter(value => value.hasIdentity)\r\n .map(value => value.getSelectorsByColumn())\r\n .compact()\r\n .value();\r\n }\r\n\r\n private takeSelectionStateFromDataPoints(dataPoints: SelectableDataPoint[]): void {\r\n debug.assertValue(dataPoints, \"dataPoints\");\r\n\r\n let selectedIds: SelectionId[] = this.selectedIds;\r\n\r\n // Replace the existing selectedIds rather than merging.\r\n ArrayExtensions.clear(selectedIds);\r\n\r\n for (let dataPoint of dataPoints) {\r\n if (dataPoint.selected)\r\n selectedIds.push(dataPoint.identity);\r\n }\r\n }\r\n\r\n /**\r\n * Syncs the selection state for all data points that have the same category. Returns\r\n * true if the selection state was out of sync and corrections were made; false if\r\n * the data is already in sync with the service.\r\n *\r\n * If the data is not compatible with the current service's current selection state,\r\n * the state is cleared and the cleared selection is sent to the host.\r\n * \r\n * Ignores series for now, since we don't support series selection at the moment.\r\n */\r\n private syncSelectionState(): void {\r\n if (this.isInvertedSelectionMode) {\r\n return this.syncSelectionStateInverted();\r\n }\r\n\r\n let selectedIds = this.selectedIds;\r\n let selectableDataPoints = this.selectableDataPoints;\r\n let selectableLegendDataPoints = this.selectableLegendDataPoints;\r\n let selectableLabelsDataPoints = this.selectableLabelsDataPoints;\r\n let foundMatchingId = false; // Checked only against the visual's data points; it's possible to have stuff selected in the visual that's not in the legend, but not vice-verse\r\n\r\n if (!selectableDataPoints && !selectableLegendDataPoints)\r\n return;\r\n\r\n if (selectableDataPoints) {\r\n if (InteractivityService.updateSelectableDataPointsBySelectedIds(selectableDataPoints, selectedIds))\r\n foundMatchingId = true;\r\n }\r\n\r\n if (selectableLegendDataPoints) {\r\n if (InteractivityService.updateSelectableDataPointsBySelectedIds(selectableLegendDataPoints, selectedIds))\r\n foundMatchingId = true;\r\n }\r\n\r\n if (selectableLabelsDataPoints) {\r\n let labelsDataPoint: SelectableDataPoint;\r\n for (let i = 0, ilen = selectableLabelsDataPoints.length; i < ilen; i++) {\r\n labelsDataPoint = selectableLabelsDataPoints[i];\r\n if (selectedIds.some((value: SelectionId) => value.includes(labelsDataPoint.identity)))\r\n labelsDataPoint.selected = true;\r\n else\r\n labelsDataPoint.selected = false;\r\n }\r\n }\r\n\r\n if (!foundMatchingId && selectedIds.length > 0) {\r\n this.clearSelection();\r\n this.sendSelectionToHost();\r\n }\r\n }\r\n\r\n private syncSelectionStateInverted(): void {\r\n let selectedIds = this.selectedIds;\r\n let selectableDataPoints = this.selectableDataPoints;\r\n if (!selectableDataPoints)\r\n return;\r\n\r\n if (selectedIds.length === 0) {\r\n for (let dataPoint of selectableDataPoints) {\r\n dataPoint.selected = false;\r\n }\r\n }\r\n else {\r\n for (var dataPoint of selectableDataPoints) {\r\n if (selectedIds.some((value: SelectionId) => value.includes(dataPoint.identity)))\r\n dataPoint.selected = true;\r\n else if (dataPoint.selected)\r\n dataPoint.selected = false;\r\n }\r\n }\r\n }\r\n\r\n private applyToAllSelectableDataPoints(action: (selectableDataPoint: SelectableDataPoint) => void) {\r\n let selectableDataPoints = this.selectableDataPoints;\r\n let selectableLegendDataPoints = this.selectableLegendDataPoints;\r\n let selectableLabelsDataPoints = this.selectableLabelsDataPoints;\r\n if (selectableDataPoints) {\r\n for (let dataPoint of selectableDataPoints) {\r\n action(dataPoint);\r\n }\r\n }\r\n\r\n if (selectableLegendDataPoints) {\r\n for (let dataPoint of selectableLegendDataPoints) {\r\n action(dataPoint);\r\n }\r\n }\r\n\r\n if (selectableLabelsDataPoints) {\r\n for (let dataPoint of selectableLabelsDataPoints) {\r\n action(dataPoint);\r\n }\r\n }\r\n }\r\n\r\n private static updateSelectableDataPointsBySelectedIds(selectableDataPoints: SelectableDataPoint[], selectedIds: SelectionId[]): boolean {\r\n let foundMatchingId = false;\r\n\r\n for (let datapoint of selectableDataPoints) {\r\n datapoint.selected = InteractivityService.checkDatapointAgainstSelectedIds(datapoint, selectedIds);\r\n\r\n if (datapoint.selected)\r\n foundMatchingId = true;\r\n }\r\n\r\n return foundMatchingId;\r\n }\r\n\r\n private static checkDatapointAgainstSelectedIds(datapoint: SelectableDataPoint, selectedIds: SelectionId[]): boolean {\r\n return selectedIds.some((value: SelectionId) => value.includes(datapoint.identity));\r\n }\r\n\r\n private removeSelectionIdsWithOnlyMeasures() {\r\n this.selectedIds = _.filter(this.selectedIds, (identity) => identity.hasIdentity());\r\n }\r\n\r\n private removeSelectionIdsExceptOnlyMeasures() {\r\n this.selectedIds = _.filter(this.selectedIds, (identity) => !identity.hasIdentity());\r\n }\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.services {\r\n import CategoryTypes = MapUtil.CategoryTypes;\r\n import Settings = MapUtil.Settings;\r\n\r\n export function createGeocoder(): IGeocoder {\r\n return {\r\n geocode: geocode,\r\n geocodeBoundary: geocodeBoundary,\r\n geocodePoint: geocodePoint,\r\n tryGeocodeImmediate: tryGeocodeImmediate,\r\n tryGeocodeBoundaryImmediate: tryGeocodeBoundaryImmediate,\r\n };\r\n }\r\n\r\n export interface BingAjaxService {\r\n (url: string, settings: JQueryAjaxSettings): any;\r\n }\r\n export const safeCharacters: string = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-\";\r\n \r\n /** Note: Used for test mockup */\r\n export let BingAjaxCall: BingAjaxService = $.ajax;\r\n\r\n export const CategoryTypeArray = [\r\n \"Address\",\r\n \"City\",\r\n \"Continent\",\r\n \"Country\",\r\n \"County\",\r\n \"Longitude\",\r\n \"Latitude\",\r\n \"Place\",\r\n \"PostalCode\",\r\n \"StateOrProvince\"\r\n ];\r\n\r\n export function isCategoryType(value: string): boolean {\r\n return CategoryTypeArray.indexOf(value) > -1;\r\n }\r\n\r\n export const BingEntities = {\r\n Continent: \"Continent\",\r\n Sovereign: \"Sovereign\",\r\n CountryRegion: \"CountryRegion\",\r\n AdminDivision1: \"AdminDivision1\",\r\n AdminDivision2: \"AdminDivision2\",\r\n PopulatedPlace: \"PopulatedPlace\",\r\n Postcode: \"Postcode\",\r\n Postcode1: \"Postcode1\",\r\n Neighborhood: \"Neighborhood\",\r\n Address: \"Address\",\r\n };\r\n\r\n export interface ILocation {\r\n latitude: number;\r\n longitude: number;\r\n }\r\n\r\n export interface ILocationRect {\r\n northWest: ILocation;\r\n southEast: ILocation;\r\n }\r\n\r\n export interface GeocodeCallback {\r\n (error: Error, coordinate: IGeocodeCoordinate): void;\r\n }\r\n\r\n export interface IGeocodeQuery {\r\n query: string;\r\n category: string;\r\n levelOfDetail?: number;\r\n longitude?: number;\r\n latitude?: number;\r\n }\r\n\r\n interface IGeocodeQueueItem {\r\n query: GeocodeQuery;\r\n deferred: any;\r\n }\r\n\r\n // Static variables for caching, maps, etc.\r\n let geocodeQueue: IGeocodeQueueItem[];\r\n let activeRequests;\r\n let categoryToBingEntity: { [key: string]: string; };\r\n let categoryToBingEntityGeodata: { [key: string]: string; };\r\n let geocodingCache: IGeocodingCache;\r\n\r\n export class GeocodeQuery implements IGeocodeQuery {\r\n public query: string;\r\n public category: string;\r\n public key: string;\r\n\r\n constructor(query: string, category: string) {\r\n this.query = query != null ? query : \"\";\r\n this.category = category != null ? category : \"\";\r\n this.key = (this.query + \"/\" + this.category).toLowerCase();\r\n if (!geocodingCache) {\r\n geocodingCache = createGeocodingCache(Settings.MaxCacheSize, Settings.MaxCacheSizeOverflow);\r\n }\r\n }\r\n\r\n public getBingEntity(): string {\r\n let category = this.category.toLowerCase();\r\n if (!categoryToBingEntity) {\r\n categoryToBingEntity = {};\r\n categoryToBingEntity[CategoryTypes.Continent.toLowerCase()] = BingEntities.Continent;\r\n categoryToBingEntity[CategoryTypes.CountryRegion.toLowerCase()] = BingEntities.Sovereign;\r\n categoryToBingEntity[CategoryTypes.StateOrProvince.toLowerCase()] = BingEntities.AdminDivision1;\r\n categoryToBingEntity[CategoryTypes.County.toLowerCase()] = BingEntities.AdminDivision2;\r\n categoryToBingEntity[CategoryTypes.City.toLowerCase()] = BingEntities.PopulatedPlace;\r\n categoryToBingEntity[CategoryTypes.PostalCode.toLowerCase()] = BingEntities.Postcode;\r\n categoryToBingEntity[CategoryTypes.Address.toLowerCase()] = BingEntities.Address;\r\n }\r\n return categoryToBingEntity[category] || \"\";\r\n }\r\n\r\n public getUrl(): string {\r\n let url = Settings.BingUrl + \"?key=\" + Settings.BingKey;\r\n let entityType = this.getBingEntity();\r\n let queryAdded = false;\r\n if (entityType) {\r\n if (entityType === BingEntities.Postcode) {\r\n url += \"&includeEntityTypes=Postcode,Postcode1,Postcode2,Postcode3,Postcode4\";\r\n }\r\n else if (this.query.indexOf(\",\") === -1 && (entityType === BingEntities.AdminDivision1 || entityType === BingEntities.AdminDivision2)) {\r\n queryAdded = true;\r\n try {\r\n url += \"&adminDistrict=\" + decodeURIComponent(this.query);\r\n } catch (e) {\r\n return null;\r\n }\r\n }\r\n else {\r\n url += \"&includeEntityTypes=\" + entityType;\r\n }\r\n }\r\n\r\n if (!queryAdded) {\r\n try {\r\n url += \"&q=\" + decodeURIComponent(this.query);\r\n } catch (e) {\r\n return null;\r\n }\r\n }\r\n\r\n let cultureName = navigator.userLanguage || navigator[\"language\"];\r\n cultureName = mapLocalesForBing(cultureName);\r\n if (cultureName) {\r\n url += \"&c=\" + cultureName;\r\n }\r\n\r\n url += \"&maxRes=20\";\r\n\r\n // If the query is of length 2, request the ISO 2-letter country code to be returned with the result to be compared against the query so that such results can be preferred.\r\n if (this.query.length === 2 && this.category === CategoryTypes.CountryRegion) {\r\n url += \"&include=ciso2\";\r\n }\r\n\r\n return url;\r\n }\r\n }\r\n\r\n export class GeocodePointQuery extends GeocodeQuery {\r\n public latitude: number;\r\n public longitude: number;\r\n \r\n constructor(latitude: number, longitude: number) {\r\n super([latitude, longitude].join(), \"Point\");\r\n this.latitude = latitude;\r\n this.longitude = longitude;\r\n } \r\n\r\n public getUrl(): string {\r\n let url = Settings.BingUrl + \"/\" +\r\n [this.latitude, this.longitude].join() + \"?\" +\r\n \"key=\" + Settings.BingKey +\r\n \"&includeEntityTypes=\" + [\r\n BingEntities.Address,\r\n BingEntities.Neighborhood,\r\n BingEntities.PopulatedPlace,\r\n BingEntities.Postcode1,\r\n BingEntities.AdminDivision1,\r\n BingEntities.AdminDivision2,\r\n BingEntities.CountryRegion].join() +\r\n \"&include=ciso2\"; \r\n return url;\r\n }\r\n }\r\n\r\n export class GeocodeBoundaryQuery extends GeocodeQuery {\r\n public latitude: number;\r\n public longitude: number;\r\n public levelOfDetail: number;\r\n public maxGeoData: number;\r\n\r\n constructor(latitude: number, longitude: number, category, levelOfDetail, maxGeoData = 3) {\r\n super([latitude, longitude, levelOfDetail, maxGeoData].join(\",\"), category);\r\n this.latitude = latitude;\r\n this.longitude = longitude;\r\n this.levelOfDetail = levelOfDetail;\r\n this.maxGeoData = maxGeoData;\r\n }\r\n\r\n public getBingEntity(): string {\r\n let category = this.category.toLowerCase();\r\n if (!categoryToBingEntityGeodata) {\r\n categoryToBingEntityGeodata = {};\r\n categoryToBingEntityGeodata[CategoryTypes.CountryRegion.toLowerCase()] = BingEntities.CountryRegion;\r\n categoryToBingEntityGeodata[CategoryTypes.StateOrProvince.toLowerCase()] = BingEntities.AdminDivision1;\r\n categoryToBingEntityGeodata[CategoryTypes.County.toLowerCase()] = BingEntities.AdminDivision2;\r\n categoryToBingEntityGeodata[CategoryTypes.City.toLowerCase()] = BingEntities.PopulatedPlace;\r\n categoryToBingEntityGeodata[CategoryTypes.PostalCode.toLowerCase()] = BingEntities.Postcode1;\r\n }\r\n return categoryToBingEntityGeodata[category] || \"\";\r\n }\r\n\r\n public getUrl(): string {\r\n let url = Settings.BingUrlGeodata + \"key=\" + Settings.BingKey + \"&$format=json\";\r\n let entityType = this.getBingEntity();\r\n if (!entityType) {\r\n return null;\r\n }\r\n\r\n let cultureName = navigator.userLanguage || navigator[\"language\"];\r\n cultureName = mapLocalesForBing(cultureName);\r\n let cultures = cultureName.split(\"-\");\r\n let data = [this.latitude, this.longitude, this.levelOfDetail, \"'\" + entityType + \"'\", 1, 0, \"'\" + cultureName + \"'\"];\r\n if (cultures.length > 1) {\r\n data.push(\"'\" + cultures[1] + \"'\");\r\n }\r\n return url + \"&SpatialFilter=GetBoundary(\" + data.join(\", \") + \")\";\r\n }\r\n }\r\n\r\n /**\r\n * Map locales that cause failures to similar locales that work\r\n */\r\n function mapLocalesForBing(locale: string): string {\r\n switch (locale.toLowerCase()) {\r\n case 'fr': // Bing gives a 404 error when this language code is used (fr is only obtained from Chrome). Use fr-FR for a near-identical version that works. Defect # 255717 opened with Bing.\r\n return 'fr-FR';\r\n default:\r\n return locale;\r\n }\r\n }\r\n\r\n function tryGeocodeImmediate(query: string, category?: string): IGeocodeCoordinate {\r\n let result = geocodingCache ? geocodingCache.getCoordinates(new GeocodeQuery(query, category).key) : undefined;\r\n return result;\r\n }\r\n\r\n function tryGeocodeBoundaryImmediate(latitude: number, longitude: number, category: string, levelOfDetail?: number, maxGeoData: number = 3): IGeocodeBoundaryCoordinate {\r\n let result = geocodingCache ? geocodingCache.getCoordinates(new GeocodeBoundaryQuery(latitude, longitude, category, levelOfDetail, maxGeoData).key) : undefined;\r\n return <IGeocodeBoundaryCoordinate>result;\r\n }\r\n\r\n export function geocodeCore(geocodeQuery: GeocodeQuery): any {\r\n let result = geocodingCache ? geocodingCache.getCoordinates(geocodeQuery.key) : undefined;\r\n let deferred = $.Deferred();\r\n\r\n if (result) {\r\n deferred.resolve(result);\r\n } else {\r\n geocodeQueue.push({ query: geocodeQuery, deferred: deferred });\r\n dequeue();\r\n }\r\n return deferred;\r\n }\r\n\r\n export function geocode(query: string, category: string = \"\"): any {\r\n return geocodeCore(new GeocodeQuery(query, category));\r\n }\r\n\r\n export function geocodeBoundary(latitude: number, longitude: number, category: string = \"\", levelOfDetail: number = 2, maxGeoData: number = 3): any {\r\n return geocodeCore(new GeocodeBoundaryQuery(latitude, longitude, category, levelOfDetail, maxGeoData));\r\n }\r\n\r\n export function geocodePoint(latitude: number, longitude: number): any {\r\n return geocodeCore(new GeocodePointQuery(latitude, longitude));\r\n }\r\n\r\n function dequeue(decrement: number = 0) {\r\n activeRequests -= decrement;\r\n while (activeRequests < Settings.MaxBingRequest) {\r\n\r\n if (geocodeQueue.length === 0) {\r\n break;\r\n }\r\n\r\n activeRequests++;\r\n makeRequest(geocodeQueue.shift());\r\n }\r\n }\r\n\r\n function makeRequest(item: IGeocodeQueueItem) {\r\n\r\n // Check again if we already got the coordinate;\r\n let result = geocodingCache ? geocodingCache.getCoordinates(item.query.key) : undefined;\r\n if (result) {\r\n setTimeout(() => dequeue(1));\r\n item.deferred.resolve(result);\r\n return;\r\n }\r\n\r\n // Unfortunately the Bing service doesn't support CORS, only jsonp. This issue must be raised and revised.\r\n // VSTS: 1396088 - Tracking: Ask: Bing geocoding to support CORS\r\n let config: JQueryAjaxSettings = {\r\n type: \"GET\",\r\n dataType: \"jsonp\",\r\n jsonp: \"jsonp\"\r\n };\r\n\r\n let url = item.query.getUrl();\r\n if (!url) {\r\n completeRequest(item, new Error(\"Unsupported query. \" + item.query.query));\r\n }\r\n\r\n BingAjaxCall(url, config).then(\r\n (data) => {\r\n try {\r\n if (item.query instanceof GeocodeBoundaryQuery) {\r\n let result = data;\r\n if (result && result.d && Array.isArray(result.d.results) && result.d.results.length > 0) {\r\n let entity = result.d.results[0];\r\n let primitives = entity.Primitives;\r\n if (primitives && primitives.length > 0) {\r\n let coordinates: IGeocodeBoundaryCoordinate = {\r\n latitude: (<GeocodeBoundaryQuery>item.query).latitude,\r\n longitude: (<GeocodeBoundaryQuery>item.query).longitude,\r\n locations: []\r\n };\r\n\r\n primitives.sort((a, b) => {\r\n if (a.Shape.length < b.Shape.length) {\r\n return 1;\r\n }\r\n if (a.Shape.length > b.Shape.length) {\r\n return -1;\r\n }\r\n return 0;\r\n });\r\n\r\n let maxGeoData = Math.min(primitives.length, (<GeocodeBoundaryQuery>item.query).maxGeoData);\r\n\r\n for (let i = 0; i < maxGeoData; i++) {\r\n let ringStr = primitives[i].Shape;\r\n let ringArray = ringStr.split(\",\");\r\n\r\n for (let j = 1; j < ringArray.length; j++) {\r\n coordinates.locations.push({ nativeBing: ringArray[j] });\r\n }\r\n }\r\n\r\n completeRequest(item, null, coordinates);\r\n }\r\n else {\r\n completeRequest(item, new Error(\"Geocode result is empty.\"));\r\n }\r\n }\r\n else {\r\n completeRequest(item, new Error(\"Geocode result is empty.\"));\r\n }\r\n }\r\n else if (item.query instanceof GeocodePointQuery){\r\n let resources = data.resourceSets[0].resources;\r\n if (Array.isArray(resources) && resources.length > 0) {\r\n let index = getBestResultIndex(resources, item.query);\r\n let pointData = resources[index].point.coordinates;\r\n let addressData = resources[index].address;\r\n let coordinates: IGeocodeResource = {\r\n latitude: parseFloat(pointData[0]),\r\n longitude: parseFloat(pointData[1]),\r\n addressLine: addressData.addressLine,\r\n locality: addressData.locality,\r\n neighborhood: addressData.neighborhood,\r\n adminDistrict: addressData.adminDistrict, \r\n adminDistrict2: addressData.adminDistrict2, \r\n formattedAddress: addressData.formattedAddress, \r\n postalCode: addressData.postalCode,\r\n countryRegionIso2: addressData.countryRegionIso2, \r\n countryRegion: addressData.countryRegion, \r\n landmark: addressData.landmark, \r\n };\r\n completeRequest(item, null, coordinates);\r\n }\r\n else {\r\n completeRequest(item, new Error(\"Geocode result is empty.\"));\r\n }\r\n }\r\n else {\r\n let resources = data.resourceSets[0].resources;\r\n if (Array.isArray(resources) && resources.length > 0) {\r\n let index = getBestResultIndex(resources, item.query);\r\n let pointData = resources[index].point.coordinates;\r\n let coordinates: IGeocodeCoordinate = {\r\n latitude: parseFloat(pointData[0]),\r\n longitude: parseFloat(pointData[1])\r\n };\r\n completeRequest(item, null, coordinates);\r\n }\r\n else {\r\n completeRequest(item, new Error(\"Geocode result is empty.\"));\r\n }\r\n }\r\n }\r\n catch (error) {\r\n completeRequest(item, error);\r\n }\r\n },\r\n (error) => {\r\n completeRequest(item, error);\r\n });\r\n }\r\n\r\n let dequeueTimeoutId;\r\n\r\n function completeRequest(item: IGeocodeQueueItem, error: Error, coordinate: IGeocodeCoordinate | IGeocodeBoundaryCoordinate = null) {\r\n dequeueTimeoutId = setTimeout(() => dequeue(1), Settings.UseDoubleArrayGeodataResult ? Settings.UseDoubleArrayDequeueTimeout : 0);\r\n\r\n if (error) {\r\n item.deferred.reject(error);\r\n }\r\n else {\r\n if (geocodingCache && !(item.query instanceof GeocodePointQuery))\r\n geocodingCache.registerCoordinates(item.query.key, coordinate);\r\n item.deferred.resolve(coordinate);\r\n }\r\n }\r\n\r\n function getBestResultIndex(resources: any[], query: GeocodeQuery) {\r\n let queryString = query.query.toLowerCase();\r\n // If string is of length 2 and is a country, check against the ISO country code of results, prefering exact matches\r\n if (queryString.length === 2 && query.category === CategoryTypes.CountryRegion) {\r\n for (let index = 0; index < resources.length; index++) {\r\n let iso2: string = resources[index].address && resources[index].address.countryRegionIso2;\r\n if (iso2 && queryString === iso2.toLowerCase()) {\r\n return index;\r\n }\r\n }\r\n }\r\n // Prefer results that match the targetEntity (geotagged category) on the query\r\n let targetEntity = query.getBingEntity().toLowerCase();\r\n for (let index = 0; index < resources.length; index++) {\r\n let resultEntity = (resources[index].entityType || \"\").toLowerCase();\r\n if (resultEntity === targetEntity) {\r\n return index;\r\n }\r\n }\r\n return 0;\r\n }\r\n\r\n export function reset(): void {\r\n geocodeQueue = [];\r\n activeRequests = 0;\r\n categoryToBingEntity = null;\r\n clearTimeout(dequeueTimeoutId);\r\n }\r\n\r\n reset();\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.services {\r\n interface GeocodeCacheEntry {\r\n coordinate: IGeocodeCoordinate;\r\n hitCount: number;\r\n }\r\n\r\n export interface IGeocodingCache {\r\n getCoordinates(key: string): IGeocodeCoordinate;\r\n registerCoordinates(key: string, coordinate: IGeocodeCoordinate): void;\r\n registerCoordinates(key: string, coordinate: IGeocodeBoundaryCoordinate): void;\r\n }\r\n\r\n export function createGeocodingCache(maxCacheSize: number, maxCacheSizeOverflow: number, localStorageService?: IStorageService): IGeocodingCache {\r\n if (!localStorageService)\r\n localStorageService = powerbi.localStorageService;\r\n return new GeocodingCache(maxCacheSize, maxCacheSizeOverflow, localStorageService);\r\n }\r\n\r\n class GeocodingCache implements IGeocodingCache {\r\n private geocodeCache: _.Dictionary<GeocodeCacheEntry>;\r\n private geocodeCacheCount: number;\r\n private maxCacheSize: number;\r\n private maxCacheSizeOverflow: number;\r\n private localStorageService: IStorageService;\r\n\r\n constructor(maxCacheSize: number, maxCacheSizeOverflow: number, localStorageService: IStorageService) {\r\n this.geocodeCache = {};\r\n this.geocodeCacheCount = 0;\r\n this.maxCacheSize = maxCacheSize;\r\n this.maxCacheSizeOverflow = maxCacheSizeOverflow;\r\n this.localStorageService = localStorageService;\r\n }\r\n \r\n /**\r\n * Retrieves the coordinate for the key from the cache, returning undefined on a cache miss.\r\n */\r\n public getCoordinates(key: string): IGeocodeCoordinate {\r\n // Check in-memory cache\r\n let pair = this.geocodeCache[key];\r\n if (pair) {\r\n ++pair.hitCount;\r\n return pair.coordinate;\r\n }\r\n // Check local storage cache\r\n pair = this.localStorageService.getData(key);\r\n if (pair) {\r\n this.registerInMemory(key, pair.coordinate);\r\n return pair.coordinate;\r\n }\r\n return undefined;\r\n }\r\n \r\n /**\r\n * Registers the query and coordinate to the cache.\r\n */\r\n public registerCoordinates(key: string, coordinate: IGeocodeCoordinate): void {\r\n this.registerInMemory(key, coordinate);\r\n this.registerInStorage(key, coordinate);\r\n }\r\n\r\n private registerInMemory(key: string, coordinate: IGeocodeCoordinate): void {\r\n let geocodeCache = this.geocodeCache;\r\n let maxCacheSize = this.maxCacheSize;\r\n let maxCacheCount = maxCacheSize + this.maxCacheSizeOverflow;\r\n\r\n // are we about to exceed the maximum?\r\n if (this.geocodeCacheCount >= maxCacheCount) {\r\n let keys = Object.keys(geocodeCache);\r\n let cacheSize = keys.length;\r\n\r\n // sort keys in *descending* hitCount order\r\n keys.sort((a: string, b: string) => {\r\n let cachedA = geocodeCache[a];\r\n let cachedB = geocodeCache[b];\r\n let ca = cachedA ? cachedA.hitCount : 0;\r\n let cb = cachedB ? cachedB.hitCount : 0;\r\n return ca < cb ? 1 : (ca > cb ? -1 : 0);\r\n });\r\n\r\n // whack ones with the lower hitCounts.\r\n // - while # whacked keys is small, do a quick wipe\r\n // - after awhile we get lots of keys whose cached value is undefined. \r\n // when there are \"too many,\" make a whole new memory cache.\r\n if (cacheSize < 2 * maxCacheCount) {\r\n for (let i = maxCacheSize; i < cacheSize; i++)\r\n geocodeCache[keys[i]] = undefined;\r\n }\r\n else {\r\n let newGeocodeCache: _.Dictionary<GeocodeCacheEntry> = {};\r\n for (let i = 0; i < maxCacheSize; ++i)\r\n newGeocodeCache[keys[i]] = geocodeCache[keys[i]];\r\n\r\n geocodeCache = this.geocodeCache = newGeocodeCache;\r\n }\r\n\r\n this.geocodeCacheCount = maxCacheSize;\r\n }\r\n\r\n geocodeCache[key] = { key: key, coordinate: coordinate, hitCount: 1 };\r\n ++this.geocodeCacheCount;\r\n }\r\n\r\n private registerInStorage(key: string, coordinate: IGeocodeCoordinate): void {\r\n this.localStorageService.setData(key, { coordinate: coordinate });\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.services {\r\n\r\n export function createGeolocation(): IGeolocation {\r\n return new GeolocationService();\r\n }\r\n\r\n /**\r\n * HTML5 Implementation of IGeolocation\r\n */\r\n class GeolocationService implements IGeolocation {\r\n private webGeolocation: Geolocation;\r\n \r\n constructor() {\r\n this.webGeolocation = navigator.geolocation;\r\n }\r\n \r\n public watchPosition(successCallback: IPositionCallback, errorCallback?: IPositionErrorCallback): number {\r\n return this.webGeolocation.watchPosition(\r\n (position: Position) => {\r\n successCallback(position);\r\n },\r\n (error: PositionError) => {\r\n if (errorCallback != null) {\r\n errorCallback(error);\r\n }\r\n }\r\n );\r\n }\r\n\r\n public clearWatch(watchId: number): void {\r\n this.webGeolocation.clearWatch(watchId);\r\n }\r\n\r\n public getCurrentPosition(successCallback: IPositionCallback, errorCallback?: IPositionErrorCallback): void {\r\n this.webGeolocation.getCurrentPosition(\r\n (position: Position) => {\r\n successCallback(position);\r\n },\r\n (error: PositionError) => {\r\n if (errorCallback != null) {\r\n errorCallback(error);\r\n }\r\n }\r\n );\r\n }\r\n\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n const unsupportedVisuals: string[] = ['play', 'subview', 'smallMultiple'];\r\n\r\n export interface IVisualPluginService {\r\n getPlugin(type: string): IVisualPlugin;\r\n getVisuals(): IVisualPlugin[];\r\n capabilities(type: string): VisualCapabilities;\r\n removeAnyCustomVisuals(): void;\r\n requireSandbox(plugin: IVisualPlugin): boolean;\r\n isCustomVisual(visual: string): boolean;\r\n isScriptVisual(type: string): boolean;\r\n // VSTS 6217994 - [R Viz] Remove temporary DataViewAnalysis validation workaround of static R Script Visual mappings\r\n isScriptVisualQueryable(): boolean;\r\n shouldDisableVisual(type: string, mapDisabled: boolean): boolean;\r\n getInteractivityOptions(visualType: string): InteractivityOptions;\r\n }\r\n\r\n export interface MinervaVisualFeatureSwitches {\r\n /**\r\n * This feature switch enables the data-dot & column combo charts.\r\n */\r\n dataDotChartEnabled?: boolean;\r\n\r\n /**\r\n * Visual should prefer to request a higher volume of data.\r\n */\r\n preferHigherDataVolume?: boolean;\r\n\r\n sandboxVisualsEnabled?: boolean;\r\n\r\n /**\r\n * R visual is enabled for consumption.\r\n * When turned on, R script will be executed against local R (for PBID) or AML (for PBI.com).\r\n * When turned off, R script will not be executed and the visual is treated as a static image visual.\r\n */\r\n scriptVisualEnabled?: boolean;\r\n\r\n /**\r\n * R visual is enabled for authoring.\r\n * When turned on, R visual will appear in the visual gallery.\r\n */\r\n scriptVisualAuthoringEnabled?: boolean;\r\n\r\n isLabelInteractivityEnabled?: boolean;\r\n\r\n sunburstVisualEnabled?: boolean;\r\n\r\n filledMapDataLabelsEnabled?: boolean;\r\n\r\n lineChartLabelDensityEnabled?: boolean;\r\n\r\n /**\r\n * Enables button to center map to the current location\r\n */\r\n mapCurrentLocationEnabled?: boolean;\r\n\r\n /**\r\n * Enables conditional formatting of the background color of cells for table visuals.\r\n */\r\n conditionalFormattingEnabled?: boolean;\r\n }\r\n\r\n export interface SmallViewPortProperties {\r\n cartesianSmallViewPortProperties: CartesianSmallViewPortProperties;\r\n gaugeSmallViewPortProperties: GaugeSmallViewPortProperties;\r\n funnelSmallViewPortProperties: FunnelSmallViewPortProperties;\r\n DonutSmallViewPortProperties: DonutSmallViewPortProperties;\r\n }\r\n\r\n export interface CreateDashboardOptions {\r\n tooltipsEnabled: boolean;\r\n }\r\n\r\n export module visualPluginFactory {\r\n export class VisualPluginService implements IVisualPluginService {\r\n private plugins: jsCommon.IStringDictionary<IVisualPlugin>;\r\n protected featureSwitches: MinervaVisualFeatureSwitches;\r\n\r\n public constructor(featureSwitches: MinervaVisualFeatureSwitches) {\r\n this.plugins = <any>powerbi.visuals.plugins;\r\n this.featureSwitches = featureSwitches;\r\n }\r\n\r\n /**\r\n * Gets metadata for all registered.\r\n */\r\n public getVisuals(): IVisualPlugin[] {\r\n let registry = this.plugins,\r\n names: string[] = Object.keys(registry);\r\n\r\n return names.map(name => registry[name]);\r\n }\r\n\r\n public getPlugin(type: string): IVisualPlugin {\r\n if (!type) {\r\n return;\r\n }\r\n\r\n let plugin: IVisualPlugin = this.plugins[type];\r\n if (!plugin) {\r\n return;\r\n }\r\n\r\n return plugin;\r\n }\r\n\r\n public capabilities(type: string): VisualCapabilities {\r\n let plugin = this.getPlugin(type);\r\n if (plugin)\r\n return plugin.capabilities;\r\n }\r\n\r\n public requireSandbox(plugin: IVisualPlugin): boolean {\r\n return plugin && plugin.custom;\r\n }\r\n\r\n public removeAnyCustomVisuals() {\r\n let plugins = powerbi.visuals.plugins;\r\n for (let key in plugins) {\r\n let p: IVisualPlugin = plugins[key];\r\n if (p.custom) {\r\n delete plugins[key];\r\n }\r\n }\r\n }\r\n\r\n public isCustomVisual(visual: string): boolean {\r\n if (visual) {\r\n\r\n if (this.plugins[visual]) {\r\n return this.plugins[visual].custom === true;\r\n }\r\n else if (_.include(unsupportedVisuals, visual)) {\r\n /*use the hardcoded unsupported visual list to distinguish unsupported visual with custom visual when the plugin object is not in memory*/\r\n return false;\r\n }\r\n else {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n public isScriptVisual(type: string): boolean{\r\n let visualCapabilities = this.capabilities(type);\r\n if (visualCapabilities && visualCapabilities.dataViewMappings && ScriptResultUtil.findScriptResult(visualCapabilities.dataViewMappings)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n public shouldDisableVisual(type: string, mapDisabled: boolean): boolean {\r\n return (type === plugins.map.name || type === plugins.filledMap.name) && mapDisabled;\r\n }\r\n\r\n public isScriptVisualQueryable(): boolean {\r\n // Feature switch determines if Script visuals are query visuals - currently non-query in PBI site\r\n return (this.featureSwitches !== undefined && this.featureSwitches.scriptVisualEnabled);\r\n }\r\n\r\n public getInteractivityOptions(visualType: string): InteractivityOptions {\r\n let interactivityOptions: InteractivityOptions = {\r\n overflow: 'hidden',\r\n };\r\n return interactivityOptions;\r\n }\r\n }\r\n\r\n export function createPlugin(\r\n visualPlugins: jsCommon.IStringDictionary<IVisualPlugin>,\r\n base: IVisualPlugin,\r\n create: IVisualFactoryMethod,\r\n modifyPluginFn?: (plugin: IVisualPlugin) => void): void {\r\n\r\n let visualPlugin = Prototype.inherit(base);\r\n visualPlugin.create = create;\r\n if (modifyPluginFn) {\r\n modifyPluginFn(visualPlugin);\r\n }\r\n visualPlugins[base.name] = visualPlugin;\r\n }\r\n\r\n function createDashboardPlugins(plugins: jsCommon.IStringDictionary<IVisualPlugin>, options: CreateDashboardOptions, featureSwitches?: MinervaVisualFeatureSwitches) {\r\n let tooltipsOnDashboard: boolean = options.tooltipsEnabled;\r\n let lineChartLabelDensityEnabled: boolean = featureSwitches && featureSwitches.lineChartLabelDensityEnabled;\r\n\r\n // Bar Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.barChart, () => new CartesianChart({\r\n chartType: CartesianChartType.StackedBar,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Clustered Bar Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.clusteredBarChart, () => new CartesianChart({\r\n chartType: CartesianChartType.ClusteredBar,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Clustered Column Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.clusteredColumnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.ClusteredColumn,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Column Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.columnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.StackedColumn,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Data Dot Clustered Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.dataDotClusteredColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.DataDotClusteredColumnCombo,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Data Dot Stacked Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.dataDotStackedColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.DataDotStackedColumnCombo,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Donut Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.donutChart, () => new DonutChart({\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Funnel Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.funnel, () => new FunnelChart({\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Gauge\r\n createPlugin(plugins, powerbi.visuals.plugins.gauge, () => new Gauge({\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Hundred Percent Stacked Bar Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedBarChart, () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedBar,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Hundred Percent Stacked Column Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedColumn,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Line Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.lineChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Line,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\r\n }));\r\n // Area Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.areaChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Area,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\r\n }));\r\n // Stacked Area Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.stackedAreaChart, () => new CartesianChart({\r\n chartType: CartesianChartType.StackedArea,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\r\n }));\r\n // Line Clustered Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.lineClusteredColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.LineClusteredColumnCombo,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Line Stacked Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.lineStackedColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.LineStackedColumnCombo,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Pie Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.pieChart, () => new DonutChart({\r\n sliceWidthRatio: 0,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Scatter Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.scatterChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Scatter,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Treemap\r\n createPlugin(plugins, powerbi.visuals.plugins.treemap, () => new Treemap({\r\n isScrollable: false,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Waterfall Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.waterfallChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Waterfall,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n }));\r\n // Map\r\n createPlugin(plugins, powerbi.visuals.plugins.map, () => new Map({\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n disableZooming: true,\r\n disablePanning: true,\r\n }));\r\n // Filled Map\r\n createPlugin(plugins, powerbi.visuals.plugins.filledMap, () => new Map({\r\n filledMap: true,\r\n tooltipsEnabled: tooltipsOnDashboard,\r\n disableZooming: true,\r\n disablePanning: true,\r\n }));\r\n // Matrix\r\n createPlugin(plugins, powerbi.visuals.plugins.matrix, () => new Matrix({\r\n }));\r\n // Table\r\n createPlugin(plugins, powerbi.visuals.plugins.table, () => new Table({\r\n isConditionalFormattingEnabled: false,\r\n }));\r\n }\r\n\r\n function createMinervaPlugins(plugins: jsCommon.IStringDictionary<IVisualPlugin>, featureSwitches?: MinervaVisualFeatureSwitches) {\r\n let scriptVisualEnabled: boolean = featureSwitches ? featureSwitches.scriptVisualEnabled : false;\r\n let scriptVisualAuthoringEnabled: boolean = featureSwitches ? featureSwitches.scriptVisualAuthoringEnabled : false;\r\n let isLabelInteractivityEnabled: boolean = featureSwitches ? featureSwitches.isLabelInteractivityEnabled : false;\r\n let conditionalFormattingEnabled = featureSwitches ? featureSwitches.conditionalFormattingEnabled : false;\r\n let fillMapDataLabelsEnabled: boolean = featureSwitches ? featureSwitches.filledMapDataLabelsEnabled : false;\r\n let lineChartLabelDensityEnabled: boolean = featureSwitches ? featureSwitches.lineChartLabelDensityEnabled : false;\r\n\r\n // Bar Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.barChart, () => new CartesianChart({\r\n chartType: CartesianChartType.StackedBar,\r\n isScrollable: true, animator: new WebColumnChartAnimator(),\r\n tooltipsEnabled: true,\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Card\r\n createPlugin(plugins, powerbi.visuals.plugins.card, () => new Card({\r\n isScrollable: true,\r\n animator: new BaseAnimator(),\r\n }));\r\n // Clustered Bar Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.clusteredBarChart, () => new CartesianChart({\r\n chartType: CartesianChartType.ClusteredBar,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Clustered Column Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.clusteredColumnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.ClusteredColumn,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Column Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.columnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.StackedColumn,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Data Dot Clustered Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.dataDotClusteredColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.DataDotClusteredColumnCombo,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior(), new DataDotChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Data Dot Stacked Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.dataDotStackedColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.DataDotStackedColumnCombo,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior(), new DataDotChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Donut Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.donutChart, () => new DonutChart({\r\n animator: new WebDonutChartAnimator(),\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n behavior: new DonutChartWebBehavior(),\r\n }));\r\n // Funnel Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.funnel, () => new FunnelChart({\r\n animator: new WebFunnelAnimator(),\r\n behavior: new FunnelWebBehavior(),\r\n tooltipsEnabled: true,\r\n }));\r\n // Gauge\r\n createPlugin(plugins, powerbi.visuals.plugins.gauge, () => new Gauge({\r\n animator: new BaseAnimator(),\r\n tooltipsEnabled: true,\r\n }));\r\n // Hundred Percent Stacked Bar Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedBarChart, () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedBar,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Hundred Percent Stacked Column Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedColumn,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Line Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.lineChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Line,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new BaseAnimator(),\r\n behavior: new CartesianChartBehavior([new LineChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\r\n }));\r\n // Area Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.areaChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Area,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new BaseAnimator(),\r\n behavior: new CartesianChartBehavior([new LineChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\r\n }));\r\n // Stacked Area Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.stackedAreaChart, () => new CartesianChart({\r\n chartType: CartesianChartType.StackedArea,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new BaseAnimator(),\r\n behavior: new CartesianChartBehavior([new LineChartWebBehavior()]),\r\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\r\n }));\r\n // Line Clustered Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.lineClusteredColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.LineClusteredColumnCombo,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior(), new LineChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Line Stacked Combo Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.lineStackedColumnComboChart, () => new CartesianChart({\r\n chartType: CartesianChartType.LineStackedColumnCombo,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new WebColumnChartAnimator(),\r\n behavior: new CartesianChartBehavior([new ColumnChartWebBehavior(), new LineChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Pie Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.pieChart, () => new DonutChart({\r\n sliceWidthRatio: 0,\r\n animator: new WebDonutChartAnimator(),\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n behavior: new DonutChartWebBehavior(),\r\n }));\r\n // Scatter Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.scatterChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Scatter,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n animator: new BaseAnimator(),\r\n behavior: new CartesianChartBehavior([new ScatterChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Treemap\r\n createPlugin(plugins, powerbi.visuals.plugins.treemap, () => new Treemap({\r\n animator: new WebTreemapAnimator,\r\n isScrollable: true,\r\n behavior: new TreemapWebBehavior(),\r\n tooltipsEnabled: true,\r\n }));\r\n // Waterfall Chart\r\n createPlugin(plugins, powerbi.visuals.plugins.waterfallChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Waterfall,\r\n isScrollable: true,\r\n tooltipsEnabled: true,\r\n behavior: new CartesianChartBehavior([new WaterfallChartWebBehavior()]),\r\n isLabelInteractivityEnabled: isLabelInteractivityEnabled,\r\n }));\r\n // Map\r\n createPlugin(plugins, powerbi.visuals.plugins.map, () => new Map({\r\n behavior: new MapBehavior(),\r\n tooltipsEnabled: true,\r\n isLegendScrollable: true,\r\n }));\r\n // Filled Map\r\n createPlugin(plugins, powerbi.visuals.plugins.filledMap, () => new Map({\r\n filledMap: true,\r\n behavior: new MapBehavior,\r\n tooltipsEnabled: true,\r\n filledMapDataLabelsEnabled: fillMapDataLabelsEnabled,\r\n isLegendScrollable: true,\r\n }));\r\n // Slicer\r\n createPlugin(plugins, powerbi.visuals.plugins.slicer, () => new Slicer({\r\n behavior: new SlicerWebBehavior(),\r\n }));\r\n // Matrix\r\n createPlugin(plugins, powerbi.visuals.plugins.matrix, () => new Matrix({\r\n }));\r\n // Table\r\n createPlugin(plugins, powerbi.visuals.plugins.table, () => new Table({\r\n isConditionalFormattingEnabled: conditionalFormattingEnabled,\r\n }));;\r\n\r\n if (scriptVisualEnabled && scriptVisualAuthoringEnabled) {\r\n // R visual\r\n createPlugin(\r\n plugins,\r\n powerbi.visuals.plugins.scriptVisual,\r\n () => new ScriptVisual({ canRefresh: true }));\r\n }\r\n }\r\n\r\n export class PlaygroundVisualPluginService extends VisualPluginService {\r\n private visualPlugins: jsCommon.IStringDictionary<IVisualPlugin>;\r\n\r\n public constructor() {\r\n super(undefined);\r\n\r\n this.visualPlugins = <any>powerbi.visuals.plugins;\r\n\r\n createMinervaPlugins(this.visualPlugins, null);\r\n }\r\n\r\n public getVisuals(): IVisualPlugin[] {\r\n let registry = this.visualPlugins,\r\n names: string[] = Object.keys(registry);\r\n\r\n return names.map(name => registry[name]);\r\n }\r\n\r\n public getPlugin(type: string): IVisualPlugin {\r\n if (!type) {\r\n return;\r\n }\r\n\r\n let plugin: IVisualPlugin = this.visualPlugins[type];\r\n if (!plugin) {\r\n return;\r\n }\r\n\r\n return plugin;\r\n }\r\n\r\n public capabilities(type: string): VisualCapabilities {\r\n let plugin = this.getPlugin(type);\r\n if (plugin) {\r\n return plugin.capabilities;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * This plug-in service is used when displaying visuals on the dashboard.\r\n */\r\n export class DashboardPluginService extends VisualPluginService {\r\n private visualPlugins: jsCommon.IStringDictionary<IVisualPlugin>;\r\n\r\n public constructor(featureSwitches: MinervaVisualFeatureSwitches, options: CreateDashboardOptions) {\r\n super(featureSwitches);\r\n\r\n debug.assertValue(featureSwitches, 'featureSwitches');\r\n\r\n this.visualPlugins = {};\r\n\r\n createDashboardPlugins(this.visualPlugins, options, this.featureSwitches);\r\n }\r\n\r\n public getPlugin(type: string): IVisualPlugin {\r\n\r\n if (this.visualPlugins[type]) {\r\n return this.visualPlugins[type];\r\n }\r\n\r\n return super.getPlugin(type);\r\n }\r\n\r\n public requireSandbox(plugin: IVisualPlugin): boolean {\r\n return (this.featureSwitches.sandboxVisualsEnabled) && (!plugin || (plugin && plugin.custom));\r\n }\r\n }\r\n\r\n // This plug-in service is used when displaying visuals for insights.\r\n export class InsightsPluginService extends VisualPluginService {\r\n private visualPlugins: jsCommon.IStringDictionary<IVisualPlugin>;\r\n\r\n public constructor(featureSwitches: MinervaVisualFeatureSwitches) {\r\n super(featureSwitches);\r\n\r\n debug.assertValue(featureSwitches, 'featureSwitches');\r\n\r\n this.visualPlugins = {};\r\n\r\n // Clustered Bar Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.clusteredBarChart, () => new CartesianChart({\r\n chartType: CartesianChartType.ClusteredBar,\r\n animator: new WebColumnChartAnimator(),\r\n tooltipsEnabled: true\r\n }));\r\n\r\n // Column Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.columnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.StackedColumn,\r\n animator: new WebColumnChartAnimator(),\r\n tooltipsEnabled: true\r\n }));\r\n\r\n // Donut Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.donutChart, () => new DonutChart({\r\n animator: new WebDonutChartAnimator(),\r\n tooltipsEnabled: true,\r\n }));\r\n\r\n // Hundred Percent Stacked Bar Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedBarChart, () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedBar,\r\n animator: new WebColumnChartAnimator(),\r\n tooltipsEnabled: true\r\n }));\r\n\r\n // Hundred Percent Stacked Column Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart, () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedColumn,\r\n animator: new WebColumnChartAnimator(),\r\n tooltipsEnabled: true\r\n }));\r\n\r\n // Line Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Line,\r\n animator: new BaseAnimator(),\r\n tooltipsEnabled: true,\r\n }));\r\n\r\n // Area Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.areaChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Area,\r\n animator: new BaseAnimator(),\r\n tooltipsEnabled: true,\r\n }));\r\n\r\n // Pie Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.pieChart, () => new DonutChart({\r\n sliceWidthRatio: 0,\r\n animator: new WebDonutChartAnimator(),\r\n tooltipsEnabled: true,\r\n }));\r\n\r\n // Scatter Chart\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.scatterChart, () => new CartesianChart({\r\n chartType: CartesianChartType.Scatter,\r\n animator: new BaseAnimator(),\r\n tooltipsEnabled: true,\r\n }), undefined);\r\n }\r\n\r\n public getPlugin(type: string): IVisualPlugin {\r\n if (this.visualPlugins[type]) {\r\n return this.visualPlugins[type];\r\n }\r\n\r\n return super.getPlugin(type);\r\n }\r\n\r\n public requireSandbox(plugin: IVisualPlugin): boolean {\r\n return (this.featureSwitches.sandboxVisualsEnabled) && (!plugin || (plugin && plugin.custom));\r\n }\r\n }\r\n\r\n export class MobileVisualPluginService extends VisualPluginService {\r\n private visualPlugins: jsCommon.IStringDictionary<IVisualPlugin>;\r\n private smallViewPortProperties;\r\n public static MinHeightLegendVisible = 125;\r\n public static MinHeightAxesVisible = 125;\r\n public static MinHeightGaugeSideNumbersVisible = 80;\r\n public static GaugeMarginsOnSmallViewPort = 10;\r\n public static MinHeightFunnelCategoryLabelsVisible = 80;\r\n public static MaxHeightToScaleDonutLegend = 300;\r\n\r\n public constructor(smallViewPortProperties?: SmallViewPortProperties, featureSwitches?: MinervaVisualFeatureSwitches) {\r\n super(featureSwitches);\r\n\r\n this.smallViewPortProperties = smallViewPortProperties || {\r\n CartesianSmallViewPortProperties: {\r\n hideAxesOnSmallViewPort: true,\r\n hideLegendOnSmallViewPort: true,\r\n MinHeightLegendVisible: MobileVisualPluginService.MinHeightLegendVisible,\r\n MinHeightAxesVisible: MobileVisualPluginService.MinHeightAxesVisible,\r\n },\r\n GaugeSmallViewPortProperties: {\r\n hideGaugeSideNumbersOnSmallViewPort: true,\r\n smallGaugeMarginsOnSmallViewPort: true,\r\n MinHeightGaugeSideNumbersVisible: MobileVisualPluginService.MinHeightGaugeSideNumbersVisible,\r\n GaugeMarginsOnSmallViewPort: MobileVisualPluginService.GaugeMarginsOnSmallViewPort,\r\n },\r\n FunnelSmallViewPortProperties: {\r\n hideFunnelCategoryLabelsOnSmallViewPort: true,\r\n minHeightFunnelCategoryLabelsVisible: MobileVisualPluginService.MinHeightFunnelCategoryLabelsVisible,\r\n },\r\n DonutSmallViewPortProperties: {\r\n maxHeightToScaleDonutLegend: MobileVisualPluginService.MaxHeightToScaleDonutLegend,\r\n },\r\n };\r\n\r\n // Disable tooltips for mobile\r\n TooltipManager.ShowTooltips = false;\r\n\r\n // Don't trim overflow data on mobile\r\n let trimOrdinalDataOnOverflow = false;\r\n\r\n let mapThrottleInterval: number = this.getMapThrottleInterval();\r\n\r\n this.visualPlugins = {};\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.areaChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.Area,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.barChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.StackedBar,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.clusteredBarChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.ClusteredBar,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.clusteredColumnChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.ClusteredColumn,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.columnChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.StackedColumn,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.comboChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.ComboChart,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.dataDotChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.DataDot,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.dataDotClusteredColumnComboChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.DataDotClusteredColumnCombo,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.dataDotStackedColumnComboChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.DataDotStackedColumnCombo,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedBarChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedBar,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.hundredPercentStackedColumnChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.HundredPercentStackedColumn,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.stackedAreaChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.StackedArea,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.waterfallChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.Waterfall,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.Line,\r\n cartesianSmallViewPortProperties: this.smallViewPortProperties.CartesianSmallViewPortProperties,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineClusteredColumnComboChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.LineClusteredColumnCombo,\r\n cartesianSmallViewPortProperties: this.smallViewPortProperties.CartesianSmallViewPortProperties,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.lineStackedColumnComboChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.LineStackedColumnCombo,\r\n cartesianSmallViewPortProperties: this.smallViewPortProperties.CartesianSmallViewPortProperties,\r\n trimOrdinalDataOnOverflow: trimOrdinalDataOnOverflow\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.scatterChart,\r\n () => new CartesianChart({\r\n chartType: CartesianChartType.Scatter,\r\n cartesianSmallViewPortProperties: this.smallViewPortProperties.CartesianSmallViewPortProperties,\r\n behavior: new CartesianChartBehavior([new ScatterChartMobileBehavior()])\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.gauge,\r\n () => new Gauge({\r\n gaugeSmallViewPortProperties: this.smallViewPortProperties.GaugeSmallViewPortProperties\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.funnel,\r\n () => new FunnelChart({\r\n animator: null,\r\n funnelSmallViewPortProperties: this.smallViewPortProperties.FunnelSmallViewPortProperties\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.donutChart,\r\n () => new DonutChart({\r\n disableGeometricCulling: true,\r\n smallViewPortProperties: this.smallViewPortProperties.DonutSmallViewPortProperties\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.pieChart,\r\n () => new DonutChart({\r\n sliceWidthRatio: 0,\r\n disableGeometricCulling: true,\r\n smallViewPortProperties: this.smallViewPortProperties.DonutSmallViewPortProperties\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.matrix,\r\n () => new Matrix({\r\n isTouchEnabled: true\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.table,\r\n () => new Table({\r\n isTouchEnabled: true\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.map,\r\n () => new Map({\r\n viewChangeThrottleInterval: mapThrottleInterval,\r\n enableCurrentLocation: featureSwitches ? featureSwitches.mapCurrentLocationEnabled : false\r\n }));\r\n createPlugin(this.visualPlugins, powerbi.visuals.plugins.filledMap,\r\n () => new Map({\r\n filledMap: true,\r\n viewChangeThrottleInterval: mapThrottleInterval\r\n }));\r\n }\r\n\r\n public getPlugin(type: string): IVisualPlugin {\r\n if (this.visualPlugins[type])\r\n return this.visualPlugins[type];\r\n\r\n return super.getPlugin(type);\r\n }\r\n\r\n public requireSandbox(plugin: IVisualPlugin): boolean {\r\n if (this.featureSwitches)\r\n return (this.featureSwitches.sandboxVisualsEnabled) && (!plugin || (plugin && plugin.custom));\r\n else\r\n return super.requireSandbox(plugin);\r\n }\r\n\r\n // Windows phone webView chokes when zooming on heavy maps,\r\n // this is a workaround to allow a relatively smooth pinch to zoom experience.\r\n private getMapThrottleInterval(): number {\r\n const windowsPhoneThrottleInterval = 100;\r\n let userAgentLowerCase = navigator.userAgent.toLowerCase();\r\n if (userAgentLowerCase.indexOf('windows phone') !== -1) {\r\n return windowsPhoneThrottleInterval;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n public getInteractivityOptions(visualType: string): InteractivityOptions {\r\n let mobileOptions: InteractivityOptions = {\r\n overflow: this.getMobileOverflowString(visualType),\r\n isInteractiveLegend: this.isChartSupportInteractivity(visualType),\r\n selection: true,\r\n };\r\n\r\n return mobileOptions;\r\n }\r\n\r\n private getMobileOverflowString(visualType: string): string {\r\n switch (visualType) {\r\n case 'multiRowCard':\r\n return 'visible';\r\n\r\n default:\r\n return 'hidden';\r\n }\r\n }\r\n\r\n private isChartSupportInteractivity(visualType: string): boolean {\r\n switch (visualType) {\r\n case 'areaChart':\r\n case 'barChart':\r\n case 'clusteredBarChart':\r\n case 'clusteredColumnChart':\r\n case 'columnChart':\r\n case 'donutChart':\r\n case 'hundredPercentStackedBarChart':\r\n case 'hundredPercentStackedColumnChart':\r\n case 'lineChart':\r\n case 'pieChart':\r\n case 'scatterChart':\r\n case 'table':\r\n case 'matrix':\r\n case 'multiRowCard':\r\n return true;\r\n\r\n default:\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n // this function is called by tests\r\n export function create(): IVisualPluginService {\r\n return new VisualPluginService(undefined);\r\n }\r\n\r\n export function createVisualPluginService(featureSwitch: MinervaVisualFeatureSwitches): IVisualPluginService {\r\n return new VisualPluginService(featureSwitch);\r\n }\r\n\r\n export function createDashboard(featureSwitches: MinervaVisualFeatureSwitches, options: CreateDashboardOptions): IVisualPluginService {\r\n return new DashboardPluginService(featureSwitches, options);\r\n }\r\n\r\n export function createInsights(featureSwitches: MinervaVisualFeatureSwitches): IVisualPluginService {\r\n return new InsightsPluginService(featureSwitches);\r\n }\r\n\r\n export function createMobile(smallViewPortProperties?: SmallViewPortProperties, featureSwitches?: MinervaVisualFeatureSwitches): IVisualPluginService {\r\n return new MobileVisualPluginService(smallViewPortProperties, featureSwitches);\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls {\r\n\r\n const UNSELECTABLE_CLASS_NAME = \"unselectable\";\r\n\r\n export function fire(eventHandlers, eventArgs) {\r\n if (eventHandlers) {\r\n for (let i = 0; i < eventHandlers.length; i++) {\r\n let h = eventHandlers[i];\r\n h(eventArgs);\r\n }\r\n }\r\n }\r\n\r\n export class ScrollbarButton {\r\n // Const\r\n // TODO: Move to style\r\n static MIN_WIDTH = 26;\r\n static ARROW_COLOR: string = \"#404040\";\r\n\r\n // Fields\r\n private _element: HTMLDivElement;\r\n private _polygon: SVGElement;\r\n private _svg: HTMLElement;\r\n private _owner: Scrollbar;\r\n private _direction: number;\r\n private _timerHandle: number;\r\n private _mouseUpWrapper: any;\r\n\r\n // Constructor\r\n constructor(owner: Scrollbar, direction: number) {\r\n this._owner = owner;\r\n this._direction = direction;\r\n this._timerHandle = undefined;\r\n this.createView();\r\n let that = this;\r\n this._element.addEventListener(\"mousedown\", function (e) { that.onMouseDown(<MouseEvent>e); });\r\n $(this._element).addClass(UNSELECTABLE_CLASS_NAME);\r\n $(this._svg).addClass(UNSELECTABLE_CLASS_NAME);\r\n $(this._polygon).addClass(UNSELECTABLE_CLASS_NAME);\r\n }\r\n\r\n // Properties\r\n public get element(): HTMLDivElement {\r\n return this._element;\r\n }\r\n\r\n // Methods\r\n private createView(): void {\r\n let svgns = \"http://www.w3.org/2000/svg\";\r\n\r\n this._polygon = <SVGElement>document.createElementNS(svgns, \"polygon\");\r\n this._polygon.setAttributeNS(null, \"points\", \"3,3 6,3 13,8 6,13 3,13 10,8\");\r\n this._polygon.setAttributeNS(null, \"fill\", ScrollbarButton.ARROW_COLOR);\r\n\r\n this._svg = <HTMLElement>document.createElementNS(svgns, \"svg\");\r\n let svgStyle = this._svg.style;\r\n svgStyle.position = \"absolute\";\r\n svgStyle.left = \"0px\";\r\n svgStyle.top = \"0px\";\r\n this._svg.appendChild(this._polygon);\r\n\r\n this._element = <HTMLDivElement>document.createElement(\"div\");\r\n this._element.className = Scrollbar.arrowClassName;\r\n this._element.appendChild(this._svg);\r\n\r\n this._owner.element.appendChild(this._element);\r\n }\r\n\r\n private onMouseDown(event: MouseEvent): void {\r\n let that = this;\r\n clearTimeout(this._timerHandle);\r\n if (!this._mouseUpWrapper) {\r\n event.cancelBubble = true;\r\n let that = this;\r\n this._mouseUpWrapper = function (event) { that.onMouseUp(event); };\r\n Scrollbar.addDocumentMouseUpEvent(this._mouseUpWrapper);\r\n }\r\n this._owner._scrollSmallIncrement(this._direction);\r\n this._owner.refresh();\r\n this._timerHandle = setTimeout(function () { that.onMouseDown(event); }, 100);\r\n if (event.preventDefault) {\r\n event.preventDefault(); // prevent dragging\r\n }\r\n }\r\n\r\n private onMouseUp(event: MouseEvent): void {\r\n clearTimeout(this._timerHandle);\r\n Scrollbar.removeDocumentMouseUpEvent(this._mouseUpWrapper);\r\n this._mouseUpWrapper = undefined;\r\n }\r\n\r\n public arrange(width: number, height: number, angle: number): void {\r\n let size = Math.min(width, height);\r\n let scale = size / 16;\r\n let x = (width - size) / 2;\r\n let y = (height - size) / 2;\r\n this._polygon.setAttributeNS(null, \"transform\", \"translate(\" + x + \", \" + y + \") scale(\" + scale + \") rotate(\" + angle + \",8,8)\");\r\n this._svg.setAttributeNS(null, \"width\", width + \"px\");\r\n this._svg.setAttributeNS(null, \"height\", height + \"px\");\r\n\r\n HTMLElementUtils.setElementWidth(this._element, width);\r\n HTMLElementUtils.setElementHeight(this._element, height);\r\n }\r\n }\r\n\r\n /** Scrollbar base class */\r\n export class Scrollbar {\r\n public static DefaultScrollbarWidth = \"15px\"; // protected\r\n private static ScrollbarBackgroundFirstTimeMousedownHoldDelay = 500;\r\n private static ScrollbarBackgroundMousedownHoldDelay = 50;\r\n private static MouseWheelRange = 120;\r\n\r\n static className = \"scroll-bar-div\";\r\n static barClassName = \"scroll-bar-part-bar\";\r\n static arrowClassName = \"scroll-bar-part-arrow\";\r\n\r\n public MIN_BAR_SIZE = 10;\r\n\r\n public min: number = 0;\r\n public max: number = 10;\r\n public viewMin: number = 0;\r\n public viewSize: number = 2;\r\n public smallIncrement: number = 1;\r\n\r\n public _onscroll: any[] = [];\r\n\r\n private _actualWidth: number;\r\n private _actualHeight: number;\r\n private _actualButtonWidth: number;\r\n private _actualButtonHeight: number;\r\n\r\n private _width: string;\r\n private _height: string;\r\n private _visible: boolean;\r\n \r\n private _element: HTMLDivElement;\r\n private _minButton: ScrollbarButton;\r\n private _maxButton: ScrollbarButton;\r\n private _middleBar: HTMLDivElement;\r\n\r\n private _timerHandle: number;\r\n private _screenToOffsetScale: number = 1.0;\r\n\r\n private _screenPrevMousePos: { x: number; y: number; };\r\n private _screenMinMousePos: number;\r\n private _screenMaxMousePos: number;\r\n\r\n private _backgroundMouseUpWrapper: any;\r\n private _middleBarMouseMoveWrapper: any;\r\n private _middleBarMouseUpWrapper: any;\r\n\r\n // Touch memmbers\r\n private _touchPanel: HTMLElement;\r\n private _offsetTouchStartPos: { x: number; y: number; };\r\n private _offsetTouchPrevPos: { x: number; y: number; };\r\n private _touchStarted: boolean;\r\n private _allowMouseDrag: boolean;\r\n\r\n constructor(parentElement: HTMLElement, layoutKind: TablixLayoutKind) {\r\n this.createView(parentElement, layoutKind);\r\n let that = this;\r\n this._element.addEventListener(\"mousedown\", function (e) { that.onBackgroundMouseDown(<MouseEvent>e); });\r\n this._middleBar.addEventListener(\"mousedown\", function (e) { that.onMiddleBarMouseDown(<MouseEvent>e); });\r\n this._timerHandle = undefined;\r\n this._visible = true;\r\n this.element[\"winControl\"] = this;\r\n $(this._touchPanel).addClass(UNSELECTABLE_CLASS_NAME);\r\n }\r\n\r\n public scrollBy(delta: number) {\r\n this.scrollTo(this.viewMin + delta);\r\n }\r\n\r\n public scrollUp(): void {\r\n this.scrollBy(-this.smallIncrement);\r\n }\r\n\r\n public scrollDown(): void {\r\n this.scrollBy(this.smallIncrement);\r\n }\r\n\r\n public scrollPageUp(): void {\r\n this.scrollBy(-this.viewSize);\r\n }\r\n\r\n public scrollPageDown(): void {\r\n this.scrollBy(this.viewSize);\r\n }\r\n\r\n public set width(value: string) {\r\n this._width = value;\r\n this._element.style.width = value;\r\n this.invalidateArrange();\r\n }\r\n\r\n public get width(): string {\r\n return this._width;\r\n }\r\n\r\n public set height(value: string) {\r\n this._height = value;\r\n this._element.style.height = value;\r\n this.invalidateArrange();\r\n }\r\n\r\n public get height(): string {\r\n return this._height;\r\n }\r\n\r\n public refresh(): void {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar.refresh()\");\r\n }\r\n\r\n public get element(): HTMLDivElement {\r\n return this._element;\r\n }\r\n\r\n public get maxButton(): ScrollbarButton {\r\n return this._maxButton;\r\n }\r\n\r\n public get middleBar(): HTMLDivElement {\r\n return this._middleBar;\r\n }\r\n\r\n public _scrollSmallIncrement(direction): void { // intent to be internal\r\n this.scrollBy(this.smallIncrement * direction);\r\n }\r\n\r\n public get visible(): boolean {\r\n return this._visible;\r\n }\r\n\r\n public get isInMouseCapture(): boolean {\r\n return this._timerHandle !== undefined;\r\n }\r\n\r\n public show(value: boolean): void {\r\n this._visible = value;\r\n this.element.style.visibility = value ? \"visible\" : \"hidden\";\r\n this.invalidateArrange();\r\n }\r\n\r\n public _getMouseOffset(event: MouseEvent): { x: number; y: number; } { // protected\r\n if (event.offsetX !== undefined)\r\n return { x: event.offsetX, y: event.offsetY };\r\n if (event.layerX !== undefined)\r\n return { x: event.layerX, y: event.layerY };\r\n return { x: event.screenX, y: event.screenY };\r\n }\r\n\r\n public _getOffsetXDelta(event: MouseEvent): number { // protected\r\n return (event.screenX - this._screenPrevMousePos.x) / this._screenToOffsetScale;\r\n }\r\n\r\n public _getOffsetYDelta(event: MouseEvent): number { // protected\r\n return (event.screenY - this._screenPrevMousePos.y) / this._screenToOffsetScale;\r\n }\r\n\r\n public _getOffsetXTouchDelta(event: MouseEvent): number { // protected\r\n return this._getMouseOffset(event).x - this._offsetTouchPrevPos.x;\r\n }\r\n\r\n public _getOffsetYTouchDelta(event: MouseEvent): number { // protected\r\n return this._getMouseOffset(event).y - this._offsetTouchPrevPos.y;\r\n }\r\n\r\n public initTouch(panel: HTMLElement, allowMouseDrag?: boolean): void {\r\n this._touchPanel = panel;\r\n this._allowMouseDrag = allowMouseDrag === undefined ? true : allowMouseDrag;\r\n if (\"ontouchmove\" in panel) {\r\n panel.addEventListener(\"touchstart\", e => this.onTouchStart(e));\r\n panel.addEventListener(\"touchmove\", e => this.onTouchMove(e));\r\n panel.addEventListener(\"touchend\", e => this.onTouchEnd(e));\r\n }\r\n else {\r\n panel.addEventListener(\"mousedown\", e => this.onTouchMouseDown(<MouseEvent>e));\r\n panel.addEventListener(\"mousemove\", e => this.onTouchMouseMove(<MouseEvent>e));\r\n panel.addEventListener(\"mouseup\", e => this.onTouchMouseUp(<MouseEvent>e));\r\n }\r\n }\r\n\r\n public onTouchStart(e: any) {\r\n if (e.touches.length === 1) {\r\n this.onTouchMouseDown(e.touches[0]);\r\n }\r\n }\r\n\r\n public onTouchMove(e: any) {\r\n if (e.touches.length === 1) {\r\n if (e.preventDefault)\r\n e.preventDefault();\r\n this.onTouchMouseMove(e.touches[0]);\r\n }\r\n }\r\n\r\n public onTouchEnd(e: any) {\r\n this.onTouchMouseUp(e.touches.length === 1 ? e.touches[0] : e, true);\r\n }\r\n\r\n public onTouchMouseDown(e: MouseEvent) {\r\n // except IE touch cancels mouse so not need for detection. For IE touch and mouse difference is detected by a flag.\r\n if (!this._allowMouseDrag &&\r\n e[\"pointerType\"] === (<MSPointerEventExtension>MSPointerEvent).MSPOINTER_TYPE_MOUSE) {\r\n return;\r\n }\r\n if (\"setCapture\" in this._touchPanel) {\r\n this._touchPanel.setCapture(true);\r\n }\r\n this._offsetTouchPrevPos = this._offsetTouchStartPos = null;\r\n this._touchStarted = true;\r\n }\r\n\r\n public _getOffsetTouchDelta(e: MouseEvent): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getOffsetTouchDelta()\");\r\n return null;\r\n }\r\n\r\n public onTouchMouseMove(e: MouseEvent) {\r\n if (this._touchStarted) {\r\n if (!this._offsetTouchStartPos) {\r\n this._offsetTouchPrevPos = this._offsetTouchStartPos = this._getMouseOffset(e);\r\n }\r\n\r\n let delta = this._getOffsetTouchDelta(e);\r\n if (delta !== 0) {\r\n this.scrollBy(-delta / this._getRunningSize(false) * this.viewSize);\r\n this._offsetTouchPrevPos = this._getMouseOffset(e);\r\n }\r\n if (e.preventDefault)\r\n e.preventDefault();\r\n\r\n e.cancelBubble = true;\r\n }\r\n }\r\n\r\n public onTouchMouseUp(e: MouseEvent, bubble?: boolean) {\r\n if (this._touchStarted) {\r\n if (this._offsetTouchStartPos) {\r\n let end = this._getMouseOffset(e);\r\n if (!bubble && (Math.abs(this._offsetTouchStartPos.x - end.x) > 3 || Math.abs(this._offsetTouchStartPos.y - end.y) > 3)) {\r\n if (e.preventDefault)\r\n e.preventDefault();\r\n\r\n e.cancelBubble = true;\r\n }\r\n }\r\n }\r\n if (\"releaseCapture\" in this._touchPanel) {\r\n this._touchPanel.releaseCapture();\r\n }\r\n this._touchStarted = false;\r\n }\r\n\r\n public registerElementForMouseWheelScrolling(element: HTMLElement): void {\r\n element.addEventListener(\"mousewheel\",(e) => { this.onMouseWheel(<MouseWheelEvent>e); });\r\n element.addEventListener(\"DOMMouseScroll\",(e) => { this.onFireFoxMouseWheel(<MouseWheelEvent>e); });\r\n }\r\n\r\n private createView(parentElement: HTMLElement, layoutKind: TablixLayoutKind): void {\r\n this._element = <HTMLDivElement>document.createElement(\"div\");\r\n this._element.className = Scrollbar.className;\r\n this._element.setAttribute(\"drag-resize-disabled\", \"true\");\r\n\r\n if (layoutKind === TablixLayoutKind.Canvas)\r\n parentElement.appendChild(this._element);\r\n\r\n this._minButton = new ScrollbarButton(this, -1);\r\n this._maxButton = new ScrollbarButton(this, 1);\r\n\r\n this._middleBar = <HTMLDivElement>document.createElement(\"div\");\r\n this._middleBar.className = Scrollbar.barClassName;\r\n this._element.appendChild(this._middleBar);\r\n }\r\n\r\n private scrollTo(pos: number): void {\r\n let viewMin = Math.min(this.max - this.viewSize, Math.max(this.min, pos));\r\n if (viewMin !== this.viewMin) {\r\n this.viewMin = viewMin;\r\n fire(this._onscroll, null);\r\n }\r\n }\r\n\r\n public _scrollByPage(event: MouseEvent): void {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._scrollByPage()\");\r\n }\r\n\r\n public _getRunningSize(net: boolean): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getRunningSize()\");\r\n return null;\r\n }\r\n\r\n public _getOffsetDelta(event: MouseEvent): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getOffsetDelta()\");\r\n return null;\r\n }\r\n\r\n private scroll(event: MouseEvent): void {\r\n let delta: number = this._getOffsetDelta(event) / this._getRunningSize(true) * (this.max - this.min);\r\n\r\n if (delta < 0) {\r\n if (this._getScreenMousePos(event) >= this._screenMaxMousePos) {\r\n return;\r\n }\r\n }\r\n else if (delta > 0) {\r\n if (this._getScreenMousePos(event) <= this._screenMinMousePos) {\r\n return;\r\n }\r\n }\r\n\r\n this.scrollBy(delta);\r\n }\r\n\r\n public get actualWidth(): number {\r\n if (this._actualWidth === undefined) {\r\n this.arrange();\r\n }\r\n return this._actualWidth;\r\n }\r\n\r\n public get actualHeight(): number {\r\n if (!this._actualHeight === undefined) {\r\n this.arrange();\r\n }\r\n return this._actualHeight;\r\n }\r\n\r\n public get actualButtonWidth(): number {\r\n if (!this._actualButtonWidth === undefined) {\r\n this.arrange();\r\n }\r\n return this._actualButtonWidth;\r\n }\r\n\r\n public get actualButtonHeight(): number {\r\n if (!this._actualButtonHeight === undefined) {\r\n this.arrange();\r\n }\r\n return this._actualButtonHeight;\r\n }\r\n\r\n public arrange(): void {\r\n if (!this._actualWidth) {\r\n this._actualWidth = this._element.offsetWidth;\r\n this._actualHeight = this._element.offsetHeight;\r\n this._actualButtonWidth = this._calculateButtonWidth();\r\n this._actualButtonHeight = this._calculateButtonHeight();\r\n this._minButton.arrange(this._actualButtonWidth, this._actualButtonHeight, this._getMinButtonAngle());\r\n this._maxButton.arrange(this._actualButtonWidth, this._actualButtonHeight, this._getMaxButtonAngle());\r\n this._setMaxButtonPosition();\r\n }\r\n }\r\n\r\n public _calculateButtonWidth(): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._calculateButtonWidth()\");\r\n return null;\r\n }\r\n\r\n public _calculateButtonHeight(): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._calculateButtonHeight()\");\r\n return null;\r\n }\r\n\r\n public _getMinButtonAngle(): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getMinButtonAngle()\");\r\n return null;\r\n }\r\n\r\n public _getMaxButtonAngle(): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getMaxButtonAngle()\");\r\n return null;\r\n }\r\n\r\n public _setMaxButtonPosition() {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._setMaxButtonPosition()\");\r\n }\r\n\r\n public invalidateArrange() {\r\n this._actualWidth = undefined;\r\n this._actualHeight = undefined;\r\n this._actualButtonWidth = undefined;\r\n this._actualButtonHeight = undefined;\r\n }\r\n\r\n private onHoldBackgroundMouseDown(event: MouseEvent): void {\r\n let holdDelay = this._timerHandle ?\r\n Scrollbar.ScrollbarBackgroundMousedownHoldDelay :\r\n Scrollbar.ScrollbarBackgroundFirstTimeMousedownHoldDelay;\r\n this._timerHandle = setTimeout(() => {\r\n this.onBackgroundMouseDown(event);\r\n }, holdDelay);\r\n }\r\n\r\n private onBackgroundMouseDown(event: MouseEvent): void {\r\n let that = this;\r\n clearTimeout(this._timerHandle);\r\n if (!this._backgroundMouseUpWrapper) {\r\n event.cancelBubble = true;\r\n this._backgroundMouseUpWrapper = function (event) { that.onBackgroundMouseUp(event); };\r\n Scrollbar.addDocumentMouseUpEvent(this._backgroundMouseUpWrapper);\r\n }\r\n this._scrollByPage(event);\r\n this.refresh();\r\n this.onHoldBackgroundMouseDown(event);\r\n if (event.preventDefault)\r\n event.preventDefault(); // prevent dragging\r\n }\r\n\r\n private onBackgroundMouseUp(event: MouseEvent): void {\r\n clearTimeout(this._timerHandle);\r\n this._timerHandle = undefined;\r\n Scrollbar.removeDocumentMouseUpEvent(this._backgroundMouseUpWrapper);\r\n this._backgroundMouseUpWrapper = undefined;\r\n }\r\n\r\n private getPinchZoomY(): number {\r\n return document.documentElement.clientHeight / window.innerHeight;\r\n }\r\n\r\n private onMiddleBarMouseDown(event: MouseEvent): void {\r\n event.cancelBubble = true;\r\n this._screenPrevMousePos = { x: event.screenX, y: event.screenY };\r\n this._screenMinMousePos = this._getScreenMousePos(event) - (this._getScreenContextualLeft(this._middleBar) - this._getScreenContextualRight(this._minButton.element));\r\n this._screenMaxMousePos = this._getScreenMousePos(event) + (this._getScreenContextualLeft(this._maxButton.element) - this._getScreenContextualRight(this._middleBar));\r\n this._screenToOffsetScale = HTMLElementUtils.getAccumulatedScale(this.element) * this.getPinchZoomY();\r\n let that = this;\r\n this._middleBarMouseMoveWrapper = function (e) { that.onMiddleBarMouseMove(e); };\r\n Scrollbar.addDocumentMouseMoveEvent(this._middleBarMouseMoveWrapper);\r\n this._middleBarMouseUpWrapper = function (e) { that.onMiddleBarMouseUp(e); };\r\n Scrollbar.addDocumentMouseUpEvent(this._middleBarMouseUpWrapper);\r\n if (event.preventDefault)\r\n event.preventDefault(); // prevent dragging\r\n }\r\n\r\n private onMiddleBarMouseMove(event: MouseEvent): void {\r\n if (!this._screenPrevMousePos) {\r\n return;\r\n }\r\n this.scroll(event);\r\n this.refresh();\r\n this._screenPrevMousePos = { x: event.screenX, y: event.screenY };\r\n }\r\n\r\n private onMiddleBarMouseUp(event: MouseEvent): void {\r\n this._screenPrevMousePos = undefined;\r\n Scrollbar.removeDocumentMouseMoveEvent(this._middleBarMouseMoveWrapper);\r\n this._middleBarMouseMoveWrapper = undefined;\r\n Scrollbar.removeDocumentMouseUpEvent(this._middleBarMouseUpWrapper);\r\n this._middleBarMouseUpWrapper = undefined;\r\n if (event.preventDefault)\r\n event.preventDefault(); // prevent other events\r\n }\r\n\r\n public _getScreenContextualLeft(element: HTMLElement): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getScreenContextualLeft()\");\r\n return null;\r\n }\r\n\r\n public _getScreenContextualRight(element: HTMLElement): number {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getScreenContextualRight()\");\r\n return null;\r\n }\r\n\r\n public onMouseWheel(e: MouseWheelEvent): void {\r\n if (e.wheelDelta) {\r\n this.mouseWheel(e.wheelDelta);\r\n }\r\n\r\n e.preventDefault();\r\n }\r\n\r\n public onFireFoxMouseWheel(e: MouseWheelEvent): void {\r\n if (e.detail) {\r\n this.mouseWheel(-e.detail);\r\n }\r\n\r\n e.preventDefault();\r\n }\r\n\r\n private mouseWheel(delta: number): void {\r\n if (this.visible) {\r\n if (delta < 0) { // fix for issue 786411 (Some machines won't have the delta as multiple of 120)\r\n delta = Math.min(-Scrollbar.MouseWheelRange, delta);\r\n }\r\n else if (delta > 0) {\r\n delta = Math.max(Scrollbar.MouseWheelRange, delta);\r\n }\r\n\r\n this.scrollBy(-delta / Scrollbar.MouseWheelRange * this.smallIncrement);\r\n }\r\n }\r\n\r\n public _getScreenMousePos(event: MouseEvent) {\r\n debug.assertFail(\"PureVirtualMethod: Scrollbar._getScreenMousePos()\");\r\n return null;\r\n }\r\n\r\n static addDocumentMouseUpEvent(func: any): void {\r\n document.addEventListener(\"mouseup\", func);\r\n }\r\n\r\n static removeDocumentMouseUpEvent(func: any): void {\r\n document.removeEventListener(\"mouseup\", func);\r\n }\r\n\r\n static addDocumentMouseMoveEvent(func): void {\r\n document.addEventListener(\"mousemove\", func);\r\n }\r\n\r\n static removeDocumentMouseMoveEvent(func): void {\r\n document.removeEventListener(\"mousemove\", func);\r\n }\r\n }\r\n\r\n /** Horizontal Scrollbar */\r\n export class HorizontalScrollbar extends Scrollbar {\r\n constructor(parentElement: HTMLElement, layoutKind: TablixLayoutKind) {\r\n super(parentElement, layoutKind);\r\n this.height = Scrollbar.DefaultScrollbarWidth;\r\n }\r\n\r\n public _calculateButtonWidth() {\r\n return Math.min(this.actualWidth / 2, Math.max(this.actualHeight, ScrollbarButton.MIN_WIDTH));\r\n }\r\n\r\n public _calculateButtonHeight() {\r\n return this.actualHeight;\r\n }\r\n\r\n public _getMinButtonAngle(): number {\r\n return -180;\r\n }\r\n\r\n public _getMaxButtonAngle(): number {\r\n return 0;\r\n }\r\n\r\n public _setMaxButtonPosition() {\r\n HTMLElementUtils.setElementLeft(this.maxButton.element, this.actualWidth - this.actualButtonWidth);\r\n }\r\n\r\n public refresh(): void {\r\n this.arrange();\r\n let runningSize = this.actualWidth - this.actualButtonWidth * 2 - 2;\r\n let barSize = this.viewSize / (this.max - this.min) * runningSize;\r\n if (barSize < this.MIN_BAR_SIZE) {\r\n runningSize -= this.MIN_BAR_SIZE - barSize;\r\n barSize = this.MIN_BAR_SIZE;\r\n }\r\n if (runningSize < 0) {\r\n runningSize = 0;\r\n barSize = 0;\r\n }\r\n barSize = Math.min(barSize, runningSize);\r\n let barPos = this.viewMin / (this.max - this.min) * runningSize;\r\n HTMLElementUtils.setElementWidth(this.middleBar, barSize);\r\n HTMLElementUtils.setElementHeight(this.middleBar, this.actualHeight);\r\n HTMLElementUtils.setElementLeft(this.middleBar, this.actualButtonWidth + 1 + barPos);\r\n }\r\n\r\n public show(visible: boolean): void {\r\n if (visible === this.visible)\r\n return;\r\n\r\n super.show(visible);\r\n if (visible) {\r\n this.element.style.height = this.height;\r\n }\r\n else {\r\n HTMLElementUtils.setElementHeight(this.element, 0);\r\n }\r\n }\r\n\r\n public _scrollByPage(event: MouseEvent): void {\r\n let left = this.middleBar.offsetLeft;\r\n let right = left + this.middleBar.offsetWidth;\r\n let x = (event.offsetX === undefined) ? event.layerX : event.offsetX;\r\n if (x > right) {\r\n this.scrollPageDown();\r\n } else if (x < left) {\r\n this.scrollPageUp();\r\n }\r\n }\r\n\r\n public _getRunningSize(net: boolean): number {\r\n let result = this.actualWidth;\r\n if (net) {\r\n let barMinPos = this.actualButtonWidth + 1;\r\n result -= barMinPos * 2;\r\n let barSize = result * (this.viewSize / (this.max - this.min));\r\n if (barSize < this.MIN_BAR_SIZE)\r\n result -= this.MIN_BAR_SIZE - barSize;\r\n }\r\n return result;\r\n }\r\n\r\n public _getOffsetDelta(event: MouseEvent): number {\r\n return this._getOffsetXDelta(event);\r\n }\r\n\r\n public _getOffsetTouchDelta(e: MouseEvent): number {\r\n return this._getOffsetXTouchDelta(e);\r\n }\r\n\r\n public _getScreenContextualLeft(element: HTMLElement): number {\r\n return element.getBoundingClientRect().left;\r\n }\r\n\r\n public _getScreenContextualRight(element: HTMLElement): number {\r\n return element.getBoundingClientRect().right;\r\n }\r\n\r\n public _getScreenMousePos(event: MouseEvent) {\r\n return event.screenX;\r\n }\r\n }\r\n\r\n /** Vertical Scrollbar */\r\n export class VerticalScrollbar extends Scrollbar {\r\n constructor(parentElement: HTMLElement, layoutKind: TablixLayoutKind) {\r\n super(parentElement, layoutKind);\r\n this.width = Scrollbar.DefaultScrollbarWidth;\r\n }\r\n\r\n public _calculateButtonWidth() {\r\n return this.actualWidth;\r\n }\r\n\r\n public _calculateButtonHeight() {\r\n return Math.min(this.actualHeight / 2, Math.max(this.actualWidth, ScrollbarButton.MIN_WIDTH));\r\n }\r\n\r\n public _getMinButtonAngle(): number {\r\n return -90;\r\n }\r\n\r\n public _getMaxButtonAngle(): number {\r\n return 90;\r\n }\r\n\r\n public _setMaxButtonPosition() {\r\n HTMLElementUtils.setElementTop(this.maxButton.element, this.actualHeight - this.actualButtonHeight);\r\n }\r\n\r\n public refresh(): void {\r\n this.arrange();\r\n let runningSize = this.actualHeight - this.actualButtonHeight * 2 - 2;\r\n let barSize = this.viewSize / (this.max - this.min) * runningSize;\r\n if (barSize < this.MIN_BAR_SIZE) {\r\n runningSize -= this.MIN_BAR_SIZE - barSize;\r\n barSize = this.MIN_BAR_SIZE;\r\n }\r\n if (runningSize < 0) {\r\n runningSize = 0;\r\n barSize = 0;\r\n }\r\n let barPos = this.viewMin / (this.max - this.min) * runningSize;\r\n HTMLElementUtils.setElementWidth(this.middleBar, this.actualWidth);\r\n HTMLElementUtils.setElementHeight(this.middleBar, barSize);\r\n HTMLElementUtils.setElementTop(this.middleBar, this.actualButtonHeight + 1 + barPos);\r\n }\r\n\r\n public show(visible: boolean): void {\r\n if (visible === this.visible)\r\n return;\r\n\r\n super.show(visible);\r\n if (visible) {\r\n this.element.style.width = this.width;\r\n }\r\n else {\r\n HTMLElementUtils.setElementWidth(this.element, 0);\r\n }\r\n }\r\n\r\n public _scrollByPage(event: MouseEvent): void {\r\n let top = this.middleBar.offsetTop;\r\n let bottom = top + this.middleBar.offsetHeight;\r\n let y = (event.offsetY === undefined) ? event.layerY : event.offsetY;\r\n if (y > bottom) {\r\n this.scrollPageDown();\r\n } else if (y < top) {\r\n this.scrollPageUp();\r\n }\r\n }\r\n\r\n public _getRunningSize(net: boolean): number {\r\n let result = this.actualHeight;\r\n if (net) {\r\n let barMinPos = this.actualButtonHeight + 1;\r\n result -= barMinPos * 2;\r\n let barSize = result * (this.viewSize / (this.max - this.min));\r\n if (barSize < this.MIN_BAR_SIZE)\r\n result -= this.MIN_BAR_SIZE - barSize;\r\n }\r\n return result;\r\n }\r\n\r\n public _getOffsetDelta(event: MouseEvent): number {\r\n return this._getOffsetYDelta(event);\r\n }\r\n\r\n public _getOffsetTouchDelta(e: MouseEvent): number {\r\n return this._getOffsetYTouchDelta(e);\r\n }\r\n\r\n public _getScreenContextualLeft(element: HTMLElement): number {\r\n return element.getBoundingClientRect().top;\r\n }\r\n\r\n public _getScreenContextualRight(element: HTMLElement): number {\r\n return element.getBoundingClientRect().bottom;\r\n }\r\n\r\n public _getScreenMousePos(event: MouseEvent) {\r\n return event.screenY;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls.internal {\r\n\r\n const UNSELECTABLE_CLASS_NAME = \"unselectable\";\r\n\r\n /** This class is responsible for tablix header resizing */\r\n export class TablixResizer {\r\n private _element: HTMLElement;\r\n private _handler: ITablixResizeHandler;\r\n private _elementMouseDownWrapper: any;\r\n private _elementMouseMoveWrapper: any;\r\n private _elementMouseOutWrapper: any;\r\n private _elementMouseDoubleClickOutWrapper: any;\r\n private _documentMouseMoveWrapper: any;\r\n private _documentMouseUpWrapper: any;\r\n private _startMousePosition: { x: number; y: number; };\r\n private _originalCursor: string;\r\n\r\n static resizeHandleSize = 4;\r\n static resizeCursor = \"e-resize\";\r\n\r\n constructor(element: HTMLElement, handler: ITablixResizeHandler) {\r\n this._element = element;\r\n this._handler = handler;\r\n this._elementMouseDownWrapper = null;\r\n this._elementMouseMoveWrapper = null;\r\n this._elementMouseOutWrapper = null;\r\n this._documentMouseMoveWrapper = null;\r\n this._documentMouseUpWrapper = null;\r\n this._startMousePosition = null;\r\n this._originalCursor = null;\r\n }\r\n\r\n static addDocumentMouseUpEvent(listener: EventListener): void {\r\n document.addEventListener(\"mouseup\", listener);\r\n }\r\n\r\n static removeDocumentMouseUpEvent(listener: EventListener): void {\r\n document.removeEventListener(\"mouseup\", listener);\r\n }\r\n\r\n static addDocumentMouseMoveEvent(listener: EventListener): void {\r\n document.addEventListener(\"mousemove\", listener);\r\n }\r\n\r\n static removeDocumentMouseMoveEvent(listener: EventListener): void {\r\n document.removeEventListener(\"mousemove\", listener);\r\n }\r\n\r\n static getMouseCoordinates(event: MouseEvent): { x: number; y: number; } {\r\n return { x: event.pageX, y: event.pageY };\r\n }\r\n\r\n static getMouseCoordinateDelta(previous: { x: number; y: number; }, current: { x: number; y: number; }): { x: number; y: number; } {\r\n return { x: current.x - previous.x, y: current.y - previous.y };\r\n }\r\n\r\n public initialize(): void {\r\n this._elementMouseDownWrapper = e => this.onElementMouseDown(<MouseEvent>e);\r\n this._element.addEventListener(\"mousedown\", this._elementMouseDownWrapper);\r\n this._elementMouseMoveWrapper = e => this.onElementMouseMove(<MouseEvent>e);\r\n this._element.addEventListener(\"mousemove\", this._elementMouseMoveWrapper);\r\n this._elementMouseOutWrapper = e => this.onElementMouseOut(<MouseEvent>e);\r\n this._element.addEventListener(\"mouseout\", this._elementMouseOutWrapper);\r\n this._elementMouseDoubleClickOutWrapper = e => this.onElementMouseDoubleClick(<MouseEvent>e);\r\n this._element.addEventListener(\"dblclick\", this._elementMouseDoubleClickOutWrapper);\r\n }\r\n\r\n public uninitialize(): void {\r\n this._element.removeEventListener(\"mousedown\", this._elementMouseDownWrapper);\r\n this._elementMouseDownWrapper = null;\r\n this._element.removeEventListener(\"mousemove\", this._elementMouseMoveWrapper);\r\n this._elementMouseMoveWrapper = null;\r\n this._element.removeEventListener(\"mouseout\", this._elementMouseOutWrapper);\r\n this._elementMouseOutWrapper = null;\r\n this._element.removeEventListener(\"dblclick\", this._elementMouseDoubleClickOutWrapper);\r\n this._elementMouseDoubleClickOutWrapper = null;\r\n }\r\n\r\n public get cell(): TablixCell {\r\n // abstract\r\n debug.assertFail(\"PureVirtualMethod: TablixResizer.cell\");\r\n return null;\r\n }\r\n\r\n public get element(): HTMLElement {\r\n return this._element;\r\n }\r\n\r\n // Protected\r\n public _hotSpot(position: { x: number; y: number; }) {\r\n // abstract\r\n debug.assertFail(\"PureVirtualMethod: TablixResizer._hotSpot\");\r\n return false;\r\n }\r\n\r\n private onElementMouseDown(event: MouseEvent): void {\r\n let position = TablixResizer.getMouseCoordinates(event);\r\n if (!this._hotSpot(position))\r\n return;\r\n\r\n if (\"setCapture\" in this._element) {\r\n this._element.setCapture();\r\n }\r\n\r\n event.cancelBubble = true;\r\n this._startMousePosition = position;\r\n this._documentMouseMoveWrapper = e => this.onDocumentMouseMove(e);\r\n TablixResizer.addDocumentMouseMoveEvent(this._documentMouseMoveWrapper);\r\n this._documentMouseUpWrapper = e => this.onDocumentMouseUp(e);\r\n TablixResizer.addDocumentMouseUpEvent(this._documentMouseUpWrapper);\r\n\r\n if (document.documentElement) {\r\n this._originalCursor = document.documentElement.style.cursor;\r\n document.documentElement.style.cursor = TablixResizer.resizeCursor;\r\n }\r\n\r\n this._handler.onStartResize(this.cell, this._startMousePosition.x, this._startMousePosition.y);\r\n }\r\n\r\n private onElementMouseMove(event: MouseEvent) {\r\n if (!this._startMousePosition) {\r\n if (this._hotSpot(TablixResizer.getMouseCoordinates(event))) {\r\n if (this._originalCursor === null) {\r\n this._originalCursor = this._element.style.cursor;\r\n this._element.style.cursor = TablixResizer.resizeCursor;\r\n }\r\n } else {\r\n if (this._originalCursor !== null) {\r\n this._element.style.cursor = this._originalCursor;\r\n this._originalCursor = null;\r\n }\r\n }\r\n }\r\n }\r\n\r\n private onElementMouseOut(event: MouseEvent) {\r\n if (!this._startMousePosition) {\r\n if (this._originalCursor !== null) {\r\n this._element.style.cursor = this._originalCursor;\r\n this._originalCursor = null;\r\n }\r\n }\r\n }\r\n\r\n private onElementMouseDoubleClick(event: MouseEvent) {\r\n if (!this._hotSpot(TablixResizer.getMouseCoordinates(event)))\r\n return;\r\n\r\n this._handler.onReset(this.cell);\r\n }\r\n\r\n private onDocumentMouseMove(event: MouseEvent): void {\r\n if (!this._startMousePosition)\r\n return;\r\n\r\n let delta = TablixResizer.getMouseCoordinateDelta(this._startMousePosition, TablixResizer.getMouseCoordinates(event));\r\n this._handler.onResize(this.cell, delta.x, delta.y);\r\n // Need to prevent default to prevent mouse move from triggering other effects (VSTS 6720639)\r\n event.preventDefault();\r\n }\r\n\r\n private onDocumentMouseUp(event: MouseEvent): void {\r\n this._startMousePosition = null;\r\n\r\n if (\"releaseCapture\" in this._element) {\r\n this._element.releaseCapture();\r\n }\r\n\r\n TablixResizer.removeDocumentMouseMoveEvent(this._documentMouseMoveWrapper);\r\n this._documentMouseMoveWrapper = null;\r\n\r\n TablixResizer.removeDocumentMouseUpEvent(this._documentMouseUpWrapper);\r\n this._documentMouseUpWrapper = null;\r\n\r\n if (document.documentElement)\r\n document.documentElement.style.cursor = this._originalCursor;\r\n\r\n if (event.preventDefault)\r\n event.preventDefault(); // prevent other events\r\n\r\n this._handler.onEndResize(this.cell);\r\n }\r\n }\r\n\r\n export class TablixDomResizer extends TablixResizer {\r\n private _cell: TablixCell;\r\n constructor(cell: TablixCell, element: HTMLElement, handler: ITablixResizeHandler) {\r\n super(element, handler);\r\n this._cell = cell;\r\n }\r\n\r\n public get cell(): TablixCell {\r\n return this._cell;\r\n }\r\n\r\n // Protected\r\n public _hotSpot(position: { x: number; y: number; }) {\r\n return position.x >= this.element.getBoundingClientRect().right - TablixResizer.resizeHandleSize;\r\n }\r\n }\r\n\r\n export class TablixCellPresenter {\r\n // Attribute used to disable dragging in order to have cell resizing work.\r\n static _dragResizeDisabledAttributeName = \"drag-resize-disabled\";\r\n\r\n private _owner: TablixCell;\r\n\r\n private _tableCell: HTMLTableCellElement;\r\n /** Outer DIV */\r\n private _contentElement: HTMLDivElement;\r\n /** Inner DIV */\r\n private _contentHost: HTMLDivElement;\r\n\r\n private _resizer: TablixResizer;\r\n\r\n public layoutKind: TablixLayoutKind;\r\n\r\n constructor(fitProportionally: boolean, layoutKind: TablixLayoutKind) {\r\n // Table cell will be created once needed\r\n this._tableCell = null; \r\n\r\n // Content element\r\n this._contentElement = TablixUtils.createDiv();\r\n\r\n // Content Host\r\n this._contentHost = TablixUtils.createDiv();\r\n\r\n this.layoutKind = layoutKind;\r\n\r\n this._contentElement.appendChild(this._contentHost);\r\n\r\n this._resizer = null;\r\n }\r\n\r\n public initialize(owner: TablixCell) {\r\n this._owner = owner;\r\n }\r\n\r\n public get owner(): TablixCell {\r\n return this._owner;\r\n }\r\n\r\n public registerTableCell(tableCell: HTMLTableCellElement) {\r\n this._tableCell = tableCell;\r\n\r\n tableCell.appendChild(this._contentElement);\r\n }\r\n\r\n public get tableCell(): HTMLTableCellElement {\r\n return this._tableCell;\r\n }\r\n\r\n /**\r\n * Outer DIV\r\n */\r\n public get contentElement(): HTMLElement {\r\n return this._contentElement;\r\n }\r\n\r\n /**\r\n * Inner DIV\r\n */\r\n public get contentHost(): HTMLElement {\r\n return this._contentHost;\r\n }\r\n\r\n public registerClickHandler(handler: (e: MouseEvent) => any): void {\r\n this._contentElement.onclick = handler;\r\n }\r\n\r\n public unregisterClickHandler(): void {\r\n this._contentElement.onclick = null;\r\n }\r\n\r\n public onContainerWidthChanged(value: number): void {\r\n HTMLElementUtils.setElementWidth(this._contentElement, value);\r\n }\r\n\r\n public onContinerHeightChanged(height: number): void {\r\n HTMLElementUtils.setElementHeight(this._contentElement, height);\r\n }\r\n\r\n public onColumnSpanChanged(value: number): void {\r\n this._tableCell.colSpan = value;\r\n }\r\n\r\n public onRowSpanChanged(value: number): void {\r\n this._tableCell.rowSpan = value;\r\n }\r\n\r\n public onTextAlignChanged(value: string): void {\r\n this._tableCell.style.textAlign = value;\r\n }\r\n\r\n public onClear(): void {\r\n this._contentHost.className = \"\";\r\n this._tableCell.className = \"\";\r\n }\r\n\r\n public onHorizontalScroll(width: number, offset: number): void {\r\n HTMLElementUtils.setElementLeft(this._contentHost, offset);\r\n HTMLElementUtils.setElementWidth(this._contentHost, width);\r\n }\r\n\r\n public onVerticalScroll(height: number, offset: number): void {\r\n HTMLElementUtils.setElementTop(this._contentHost, offset);\r\n HTMLElementUtils.setElementHeight(this._contentHost, height);\r\n }\r\n\r\n public onInitializeScrolling(): void {\r\n HTMLElementUtils.setElementLeft(this._contentHost, 0);\r\n HTMLElementUtils.setElementTop(this._contentHost, 0);\r\n HTMLElementUtils.setElementWidth(this._contentHost, -1);\r\n HTMLElementUtils.setElementHeight(this._contentHost, -1);\r\n }\r\n\r\n public enableHorizontalResize(enable: boolean, handler: ITablixResizeHandler): void {\r\n if (enable === (this._resizer !== null))\r\n return;\r\n\r\n if (enable) {\r\n this._resizer = new TablixDomResizer(this._owner, this._tableCell, handler);\r\n this._resizer.initialize();\r\n } else {\r\n this._resizer.uninitialize();\r\n this._resizer = null;\r\n }\r\n }\r\n\r\n /**\r\n * In order to allow dragging of the tableCell we need to\r\n * disable dragging of the container of the cell in IE.\r\n */\r\n public disableDragResize() {\r\n this._tableCell.setAttribute(TablixCellPresenter._dragResizeDisabledAttributeName, \"true\");\r\n }\r\n }\r\n\r\n export class TablixRowPresenter {\r\n private _row: TablixRow;\r\n private _tableRow: HTMLTableRowElement;\r\n private _fitProportionally: boolean;\r\n\r\n constructor(fitProportionally: boolean) {\r\n // Table row will be created once needed\r\n this._tableRow = null;\r\n this._fitProportionally = fitProportionally;\r\n }\r\n\r\n public initialize(row: TablixRow) {\r\n this._row = row;\r\n }\r\n\r\n public createCellPresenter(layoutKind: controls.TablixLayoutKind): TablixCellPresenter {\r\n return new TablixCellPresenter(this._fitProportionally, layoutKind);\r\n }\r\n\r\n public registerRow(tableRow: HTMLTableRowElement) {\r\n this._tableRow = tableRow;\r\n }\r\n\r\n public onAppendCell(cell: TablixCell): void {\r\n let presenter = cell._presenter;\r\n\r\n if (presenter.tableCell === null) {\r\n // For performance reason we use InsertCell() to create new table cells instead of AppendChild()\r\n // We use -1 to insert at the end (that's the cross-browser way of doing it)\r\n let tableCell = this._tableRow.insertCell(-1);\r\n presenter.registerTableCell(<HTMLTableCellElement>tableCell);\r\n }\r\n else {\r\n this._tableRow.appendChild(presenter.tableCell);\r\n }\r\n }\r\n\r\n public onInsertCellBefore(cell: TablixCell, refCell: TablixCell): void {\r\n debug.assertValue(refCell._presenter.tableCell, 'refTableCell');\r\n\r\n let presenter = cell._presenter;\r\n\r\n if (presenter.tableCell === null) {\r\n // For performance reasons we use InsertCell() to create new table cells instead of AppendChild()\r\n let tableCell = this._tableRow.insertCell(Math.max(0, refCell._presenter.tableCell.cellIndex - 1));\r\n presenter.registerTableCell(<HTMLTableCellElement>tableCell);\r\n }\r\n else {\r\n this._tableRow.insertBefore(cell._presenter.tableCell, refCell._presenter.tableCell);\r\n }\r\n }\r\n\r\n public onRemoveCell(cell: TablixCell): void {\r\n this._tableRow.removeChild(cell._presenter.tableCell);\r\n }\r\n\r\n public getHeight(): number {\r\n return this.getCellHeight(this._row.getTablixCell());\r\n }\r\n\r\n public getCellHeight(cell: ITablixCell): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixRowPresenter.getCellHeight\");\r\n return -1;\r\n }\r\n\r\n public getCellContentHeight(cell: ITablixCell): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixRowPresenter.getCellHeight\");\r\n return -1;\r\n }\r\n\r\n public get tableRow(): HTMLTableRowElement {\r\n return this._tableRow;\r\n }\r\n }\r\n\r\n export class DashboardRowPresenter extends TablixRowPresenter {\r\n private _gridPresenter: DashboardTablixGridPresenter;\r\n\r\n constructor(gridPresenter: DashboardTablixGridPresenter, fitProportionally: boolean) {\r\n super(fitProportionally);\r\n\r\n this._gridPresenter = gridPresenter;\r\n }\r\n\r\n public getCellHeight(cell: ITablixCell): number {\r\n return cell.containerHeight;\r\n }\r\n\r\n public getCellContentHeight(cell: ITablixCell): number {\r\n return cell.contentHeight;\r\n }\r\n\r\n }\r\n\r\n export class CanvasRowPresenter extends TablixRowPresenter {\r\n public getCellHeight(cell: ITablixCell): number {\r\n return cell.containerHeight;\r\n }\r\n\r\n public getCellContentHeight(cell: ITablixCell): number {\r\n return cell.contentHeight;\r\n }\r\n\r\n }\r\n\r\n export class TablixColumnPresenter {\r\n protected _column: TablixColumn;\r\n\r\n public initialize(column: TablixColumn) {\r\n this._column = column;\r\n }\r\n\r\n public getWidth(): number {\r\n return this.getCellWidth(this._column.getTablixCell());\r\n }\r\n\r\n public getCellWidth(cell: ITablixCell): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixColumnPresenter.getCellWidth\");\r\n return -1;\r\n }\r\n\r\n public getCellContentWidth(cell: ITablixCell): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixColumnPresenter.getCellContentWidth\");\r\n return -1;\r\n }\r\n }\r\n\r\n export class DashboardColumnPresenter extends TablixColumnPresenter {\r\n private _gridPresenter: DashboardTablixGridPresenter;\r\n\r\n constructor(gridPresenter: DashboardTablixGridPresenter) {\r\n super();\r\n\r\n this._gridPresenter = gridPresenter;\r\n }\r\n\r\n public getCellWidth(cell: ITablixCell): number {\r\n return this._gridPresenter.sizeComputationManager.cellWidth;\r\n }\r\n\r\n public getCellContentWidth(cell: ITablixCell): number {\r\n return this._gridPresenter.sizeComputationManager.contentWidth;\r\n }\r\n }\r\n\r\n export class CanvasColumnPresenter extends TablixColumnPresenter {\r\n private _gridPresenter: CanvasTablixGridPresenter;\r\n private _columnIndex: number;\r\n\r\n constructor(gridPresenter: CanvasTablixGridPresenter, index: number) {\r\n super();\r\n this._gridPresenter = gridPresenter;\r\n this._columnIndex = index;\r\n }\r\n public getCellWidth(cell: ITablixCell): number {\r\n let persistedWidth = this._gridPresenter.getPersistedCellWidth(this._columnIndex);\r\n\r\n // Because persistedWidth could be 0 check specifically for null or undefined \r\n if (_.isNumber(persistedWidth))\r\n return persistedWidth;\r\n\r\n if (!(<TablixCell>cell)._presenter)\r\n return 0;\r\n\r\n return HTMLElementUtils.getElementWidth((<TablixCell>cell)._presenter.tableCell);\r\n }\r\n\r\n public getCellContentWidth(cell: ITablixCell): number {\r\n let persistedWidth = this._gridPresenter.getPersistedCellWidth(this._columnIndex);\r\n\r\n // Because persistedWidth could be 0 check specifically for null or undefined \r\n if (_.isNumber(persistedWidth))\r\n return persistedWidth;\r\n\r\n if (!(<TablixCell>cell)._presenter)\r\n return 0;\r\n\r\n let requiredWidth = HTMLElementUtils.getElementWidth((<TablixCell>cell)._presenter.contentElement);\r\n if (requiredWidth > 0 && cell.colSpan === 1) // Doing this only for single-column-span cells\r\n requiredWidth += 1; // Adding 1px because offsetWidth returns floored number, may risk getting ellipsis\r\n\r\n return requiredWidth; \r\n }\r\n }\r\n\r\n export class TablixGridPresenter {\r\n protected _table: HTMLTableElement;\r\n protected _owner: TablixGrid;\r\n\r\n private _footerTable: HTMLTableElement;\r\n private _columnWidthManager: TablixColumnWidthManager;\r\n\r\n constructor(columnWidthManager?: TablixColumnWidthManager) {\r\n // Main Table\r\n this._table = TablixUtils.createTable();\r\n this._table.className = UNSELECTABLE_CLASS_NAME;\r\n\r\n // Footer Table\r\n this._footerTable = TablixUtils.createTable();\r\n this._footerTable.className = UNSELECTABLE_CLASS_NAME;\r\n\r\n // ColumnWidthManager\r\n this._columnWidthManager = columnWidthManager;\r\n }\r\n\r\n public initialize(owner: TablixGrid, gridHost: HTMLElement, footerHost: HTMLElement, control: TablixControl) {\r\n this._owner = owner;\r\n gridHost.appendChild(this._table);\r\n footerHost.appendChild(this._footerTable);\r\n }\r\n\r\n public getWidth(): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.getWidth\");\r\n return -1;\r\n }\r\n\r\n public getHeight(): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.getHeight\");\r\n return -1;\r\n }\r\n\r\n public getScreenToCssRatioX(): number {\r\n return 1;\r\n }\r\n\r\n public getScreenToCssRatioY(): number {\r\n return 1;\r\n }\r\n\r\n public createRowPresenter(): TablixRowPresenter {\r\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.createRowPresenter\");\r\n return null;\r\n }\r\n\r\n public createColumnPresenter(index: number): TablixColumnPresenter {\r\n debug.assertFail(\"PureVirtualMethod: TablixGridPresenter.createColumnPresenter\");\r\n return null;\r\n }\r\n\r\n public onAppendRow(row: TablixRow): void {\r\n let presenter = row.presenter;\r\n\r\n if (presenter.tableRow === null) {\r\n // For performance reason we use InsertRow() to create new table cells instead of AppendChild()\r\n // We use -1 to insert at the end (that's the cross-browser way of doing it)\r\n let tableRow = this._table.insertRow(-1);\r\n presenter.registerRow(<HTMLTableRowElement>tableRow);\r\n }\r\n else {\r\n this._table.tBodies[0].appendChild(row.presenter.tableRow);\r\n }\r\n }\r\n\r\n public onInsertRowBefore(row: TablixRow, refRow: TablixRow): void {\r\n debug.assertValue(refRow.presenter.tableRow, 'refTableRow');\r\n\r\n let presenter = row.presenter;\r\n\r\n if (presenter.tableRow === null) {\r\n // For performance reason we use InsertRow() to create new table cells instead of AppendChild()\r\n let tableRow = this._table.insertRow(Math.max(0, refRow.presenter.tableRow.rowIndex - 1));\r\n presenter.registerRow(<HTMLTableRowElement>tableRow);\r\n }\r\n else {\r\n this._table.tBodies[0].insertBefore(row.presenter.tableRow, refRow.presenter.tableRow);\r\n }\r\n }\r\n\r\n public onRemoveRow(row: TablixRow): void {\r\n this._table.tBodies[0].removeChild(row.presenter.tableRow);\r\n }\r\n\r\n public onAddFooterRow(row: TablixRow): void {\r\n let presenter = row.presenter;\r\n\r\n if (presenter.tableRow === null) {\r\n // For performance reason we use InsertRow() to create new table cells instead of AppendChild()\r\n // We use -1 to insert at the end (that's the cross-browser way of doing it)\r\n let tableRow = this._footerTable.insertRow(-1);\r\n presenter.registerRow(<HTMLTableRowElement>tableRow);\r\n }\r\n else {\r\n this._footerTable.tBodies[0].appendChild(row.presenter.tableRow);\r\n }\r\n }\r\n\r\n public onClear(): void {\r\n HTMLElementUtils.clearChildren(this._table);\r\n HTMLElementUtils.clearChildren(this._footerTable);\r\n }\r\n\r\n public onFillColumnsProportionallyChanged(value: boolean): void {\r\n if (value) {\r\n this._table.style.width = \"100%\";\r\n this._footerTable.style.width = \"100%\";\r\n }\r\n else {\r\n this._table.style.width = \"auto\";\r\n this._footerTable.style.width = \"auto\";\r\n }\r\n }\r\n\r\n public invokeColumnResizeEndCallback(columnIndex: number, width: number): void {\r\n if (this._columnWidthManager)\r\n this._columnWidthManager.onColumnWidthChanged(columnIndex, width);\r\n }\r\n\r\n public getPersistedCellWidth(columnIndex: number): number {\r\n if (this._columnWidthManager)\r\n return this._columnWidthManager.getPersistedColumnWidth(columnIndex);\r\n }\r\n }\r\n\r\n export class DashboardTablixGridPresenter extends TablixGridPresenter {\r\n private _sizeComputationManager: SizeComputationManager;\r\n\r\n constructor(sizeComputationManager: SizeComputationManager) {\r\n super();\r\n\r\n this._sizeComputationManager = sizeComputationManager;\r\n }\r\n\r\n public createRowPresenter(): TablixRowPresenter {\r\n return new DashboardRowPresenter(this, this._owner.fillColumnsProportionally);\r\n }\r\n\r\n public createColumnPresenter(index: number): TablixColumnPresenter {\r\n return new DashboardColumnPresenter(this);\r\n }\r\n\r\n public get sizeComputationManager(): SizeComputationManager {\r\n return this._sizeComputationManager;\r\n }\r\n\r\n public getWidth(): number {\r\n return this._sizeComputationManager.gridWidth;\r\n }\r\n\r\n public getHeight(): number {\r\n return this._sizeComputationManager.gridHeight;\r\n }\r\n }\r\n\r\n export class CanvasTablixGridPresenter extends TablixGridPresenter {\r\n\r\n constructor(columnWidthManager: TablixColumnWidthManager) {\r\n super(columnWidthManager);\r\n }\r\n\r\n public createRowPresenter(): TablixRowPresenter {\r\n return new CanvasRowPresenter(this._owner.fillColumnsProportionally);\r\n }\r\n\r\n public createColumnPresenter(index: number): TablixColumnPresenter {\r\n return new CanvasColumnPresenter(this, index);\r\n }\r\n\r\n public getWidth(): number {\r\n return HTMLElementUtils.getElementWidth(this._table);\r\n }\r\n\r\n public getHeight(): number {\r\n return HTMLElementUtils.getElementHeight(this._table);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls.internal {\r\n\r\n /**\r\n * Base class for Tablix realization manager.\r\n */\r\n export class TablixDimensionRealizationManager {\r\n private _realizedLeavesCount: number;\r\n private _adjustmentFactor: number;\r\n private _itemsToRealizeCount: number;\r\n private _itemsEstimatedContextualWidth: number;\r\n private _binder: ITablixBinder;\r\n\r\n constructor(binder: ITablixBinder) {\r\n this._binder = binder;\r\n this._adjustmentFactor = 1;\r\n }\r\n\r\n public _getOwner(): DimensionLayoutManager {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.getOwner\");\r\n return null;\r\n }\r\n\r\n public get binder(): ITablixBinder {\r\n return this._binder;\r\n }\r\n\r\n public get adjustmentFactor(): number {\r\n return this._adjustmentFactor;\r\n }\r\n\r\n public get itemsToRealizeCount(): number {\r\n return this._itemsToRealizeCount;\r\n }\r\n\r\n public set itemsToRealizeCount(count: number) {\r\n this._itemsToRealizeCount = count;\r\n }\r\n\r\n public get itemsEstimatedContextualWidth(): number {\r\n return this._itemsEstimatedContextualWidth;\r\n }\r\n\r\n public set itemsEstimatedContextualWidth(contextualWidth: number) {\r\n this._itemsEstimatedContextualWidth = contextualWidth;\r\n }\r\n\r\n public onStartRenderingIteration(): void {\r\n let owner = this._getOwner();\r\n if (owner.measureEnabled && !owner.done) {\r\n this._getEstimatedItemsToRealizeCount();\r\n }\r\n this._realizedLeavesCount = 0;\r\n }\r\n\r\n public onEndRenderingIteration(gridContextualWidth: number, filled: boolean): void {\r\n if (!filled && !this._getOwner().allItemsRealized)\r\n this._adjustmentFactor *= this._getSizeAdjustment(gridContextualWidth);\r\n }\r\n\r\n public onEndRenderingSession(): void {\r\n this._adjustmentFactor = 1;\r\n }\r\n\r\n public onCornerCellRealized(item: any, cell: ITablixCell): void {\r\n }\r\n \r\n public onHeaderRealized(item: any, cell: ITablixCell, leaf: boolean): void {\r\n if (leaf) {\r\n this._realizedLeavesCount++;\r\n }\r\n }\r\n\r\n public get needsToRealize(): boolean {\r\n return this._realizedLeavesCount < this._itemsToRealizeCount;\r\n }\r\n\r\n public _getEstimatedItemsToRealizeCount(): void {\r\n debug.assertFail(\"PureVirtualMethod: TablixDimensionRealizationManager._calculateItemsToRealize\");\r\n }\r\n\r\n public _getSizeAdjustment(gridContextualWidth: number): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixDimensionRealizationManager._getSizeAdjustment\");\r\n return 1;\r\n }\r\n }\r\n\r\n /** \r\n * DOM implementation for Row Tablix realization manager.\r\n */\r\n export class RowRealizationManager extends TablixDimensionRealizationManager {\r\n private _owner: RowLayoutManager;\r\n\r\n public set owner(owner: RowLayoutManager) {\r\n this._owner = owner;\r\n }\r\n\r\n public _getOwner(): DimensionLayoutManager {\r\n return this._owner;\r\n }\r\n\r\n public _getEstimatedItemsToRealizeCount(): void {\r\n this.estimateRowsToRealizeCount();\r\n }\r\n\r\n private estimateRowsToRealizeCount(): void {\r\n debug.assertValue(this._owner, '_owner');\r\n\r\n if (!this._owner.dimension.model) {\r\n this.itemsToRealizeCount = 0;\r\n return;\r\n }\r\n\r\n if (this._owner.alignToEnd)\r\n this.itemsToRealizeCount = this._owner.dimension.getItemsCount() - this._owner.dimension.getIntegerScrollOffset() + 1;\r\n else\r\n this.itemsToRealizeCount = Math.ceil((this._owner.contextualWidthToFill / (this._owner.owner.getEstimatedRowHeight() * this.adjustmentFactor)) + this._owner.dimension.getFractionScrollOffset()) - this._owner.otherLayoutManager.dimension.getDepth() + 1;\r\n }\r\n\r\n public getEstimatedRowHierarchyWidth(): number {\r\n if (!this._owner.dimension.model || this._owner.dimension.getItemsCount() === 0)\r\n return 0;\r\n\r\n let levels: RowWidths = new RowWidths();\r\n this.updateRowHiearchyEstimatedWidth(this._owner.dimension.model, this._owner.dimension._hierarchyNavigator.getIndex(this._owner.dimension.getFirstVisibleItem(0)), levels);\r\n\r\n let levelsArray: RowWidth[] = levels.items;\r\n let levelCount: number = levelsArray.length;\r\n\r\n let width = 0;\r\n\r\n for (let i = 0; i < levelCount; i++) {\r\n let level = levelsArray[i];\r\n\r\n if (level.maxNonLeafWidth !== 0)\r\n width += level.maxNonLeafWidth;\r\n else\r\n width += level.maxLeafWidth;\r\n }\r\n\r\n return width;\r\n }\r\n\r\n private updateRowHiearchyEstimatedWidth(items: any, firstVisibleIndex: number, levels: RowWidths) {\r\n let hierarchyNavigator: ITablixHierarchyNavigator = this._owner.owner.owner.hierarchyNavigator;\r\n let binder: ITablixBinder = this.binder;\r\n let length = hierarchyNavigator.getCount(items);\r\n\r\n for (let i = firstVisibleIndex; i < length; i++) {\r\n if (levels.leafCount === this.itemsToRealizeCount)\r\n return;\r\n let item: any = hierarchyNavigator.getAt(items, i);\r\n let label = binder.getHeaderLabel(item);\r\n let itemWidth = this._owner.getEstimatedHeaderWidth(label, firstVisibleIndex);\r\n let isLeaf: boolean = hierarchyNavigator.isLeaf(item);\r\n let l: number = hierarchyNavigator.getLevel(item);\r\n\r\n let level = levels.items[l];\r\n if (!level) {\r\n level = new RowWidth();\r\n levels.items[l] = level;\r\n }\r\n\r\n if (isLeaf) {\r\n level.maxLeafWidth = Math.max(level.maxLeafWidth, itemWidth);\r\n levels.leafCount = levels.leafCount + 1;\r\n }\r\n else {\r\n level.maxNonLeafWidth = Math.max(level.maxNonLeafWidth, itemWidth);\r\n this.updateRowHiearchyEstimatedWidth(hierarchyNavigator.getChildren(item), this._owner.dimension.getFirstVisibleChildIndex(item), levels);\r\n }\r\n }\r\n }\r\n\r\n public _getSizeAdjustment(gridContextualWidth: number): number {\r\n return gridContextualWidth / ((this._owner.getRealizedItemsCount() - this._owner.dimension.getFractionScrollOffset()) * this._owner.owner.getEstimatedRowHeight());\r\n }\r\n }\r\n\r\n /**\r\n * DOM implementation for Column Tablix realization manager.\r\n */\r\n export class ColumnRealizationManager extends TablixDimensionRealizationManager {\r\n private _owner: ColumnLayoutManager;\r\n\r\n public set owner(owner: ColumnLayoutManager) {\r\n this._owner = owner;\r\n }\r\n\r\n public _getOwner(): DimensionLayoutManager {\r\n return this._owner;\r\n }\r\n\r\n public _getEstimatedItemsToRealizeCount(): void {\r\n this.estimateColumnsToRealizeCount(this.getEstimatedRowHierarchyWidth());\r\n }\r\n\r\n private get rowRealizationManager(): RowRealizationManager {\r\n return <RowRealizationManager>this._owner.otherLayoutManager.realizationManager;\r\n }\r\n\r\n private getEstimatedRowHierarchyWidth(): number {\r\n if (this._owner.otherLayoutManager.done)\r\n return this._owner.getOtherHierarchyContextualHeight();\r\n\r\n return this.rowRealizationManager.getEstimatedRowHierarchyWidth() * this.adjustmentFactor;\r\n }\r\n\r\n private estimateColumnsToRealizeCount(rowHierarchyWidth: number): void {\r\n let widthToFill: number = this._owner.contextualWidthToFill - rowHierarchyWidth;\r\n\r\n if (!this._owner.dimension.model || Double.lessOrEqualWithPrecision(widthToFill, 0, DimensionLayoutManager._pixelPrecision)) {\r\n this.itemsToRealizeCount = 0;\r\n return;\r\n }\r\n\r\n let binder: ITablixBinder = this.binder;\r\n let hierarchyNavigator: ITablixHierarchyNavigator = this._owner.owner.owner.hierarchyNavigator;\r\n\r\n let startColumnIndex: number = this._owner.dimension.getIntegerScrollOffset();\r\n let endColumnIndex: number = this._owner.dimension.getItemsCount();\r\n let columnCount = endColumnIndex - startColumnIndex;\r\n\r\n let startRowIndex: number = this._owner.otherLayoutManager.dimension.getIntegerScrollOffset();\r\n let endRowIndex = this._owner.otherLayoutManager.dimension.getItemsCount();\r\n\r\n this.itemsEstimatedContextualWidth = 0;\r\n\r\n if (this._owner.alignToEnd) {\r\n this.itemsToRealizeCount = columnCount;\r\n return;\r\n }\r\n\r\n for (let i = startColumnIndex; i < endColumnIndex; i++) {\r\n if (Double.greaterOrEqualWithPrecision(this.itemsEstimatedContextualWidth, widthToFill, DimensionLayoutManager._pixelPrecision)) {\r\n this.itemsToRealizeCount = i - startColumnIndex;\r\n return;\r\n }\r\n\r\n let maxWidth = 0;\r\n let visibleSizeRatio;\r\n\r\n if (i === startColumnIndex) {\r\n visibleSizeRatio = this._owner.getVisibleSizeRatio();\r\n }\r\n else {\r\n visibleSizeRatio = 1;\r\n }\r\n\r\n let columnMember: any = hierarchyNavigator.getLeafAt(this._owner.dimension.model, i);\r\n let label = binder.getHeaderLabel(columnMember);\r\n maxWidth = Math.max(maxWidth, this._owner.getEstimatedHeaderWidth(label, i));\r\n\r\n for (let j = startRowIndex; j < endRowIndex; j++) {\r\n let intersection = hierarchyNavigator.getIntersection(hierarchyNavigator.getLeafAt(this._owner.otherLayoutManager.dimension.model, j), columnMember);\r\n label = binder.getCellContent(intersection);\r\n maxWidth = Math.max(maxWidth, this._owner.getEstimatedBodyCellWidth(label));\r\n }\r\n\r\n this.itemsEstimatedContextualWidth += maxWidth * visibleSizeRatio * this.adjustmentFactor;\r\n }\r\n\r\n this.itemsToRealizeCount = columnCount;\r\n }\r\n\r\n public _getSizeAdjustment(gridContextualWidth: number): number {\r\n return gridContextualWidth / (this.getEstimatedRowHierarchyWidth() + this.itemsEstimatedContextualWidth);\r\n }\r\n }\r\n\r\n export class RowWidths {\r\n public items: RowWidth[];\r\n public leafCount;\r\n\r\n constructor() {\r\n this.items = [];\r\n this.leafCount = 0;\r\n }\r\n }\r\n\r\n export class RowWidth {\r\n public maxLeafWidth: number = 0;\r\n public maxNonLeafWidth: number = 0;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls.internal {\r\n\r\n export interface ITablixResizeHandler {\r\n onStartResize(cell: TablixCell, currentX: number, currentY: number): void;\r\n onResize(cell: TablixCell, deltaX: number, deltaY: number): void;\r\n onEndResize(cell: TablixCell);\r\n onReset(cell: TablixCell);\r\n }\r\n\r\n /** \r\n * Internal interface to abstract the tablix row/column.\r\n */\r\n export interface ITablixGridItem {\r\n calculateSize(): number;\r\n onResize(size: number): void;\r\n onResizeEnd(size: number): void;\r\n fixSize(): void;\r\n \r\n /**\r\n * In case the parent column/row header size is bigger than the sum of the children,\r\n * the size of the last item is adjusted to compensate the difference.\r\n */\r\n setAligningContextualWidth(size: number): void;\r\n getAligningContextualWidth(): number;\r\n\r\n getContextualWidth(): number;\r\n getContentContextualWidth(): number;\r\n\r\n getIndex(grid: TablixGrid): number;\r\n\r\n getHeaders(): TablixCell[];\r\n getOtherDimensionHeaders(): TablixCell[];\r\n\r\n getOtherDimensionOwner(cell: TablixCell): ITablixGridItem;\r\n\r\n getCellIContentContextualWidth(cell: TablixCell): number;\r\n getCellContextualSpan(cell: TablixCell): number;\r\n }\r\n\r\n export class TablixCell implements ITablixCell {\r\n private _horizontalOffset: number;\r\n private _verticalOffset: number;\r\n private _colSpan: number;\r\n private _rowSpan: number;\r\n private _textAlign: string;\r\n private _containerWidth: number;\r\n private _containerHeight: number;\r\n private _scrollable = false;\r\n\r\n public _column: TablixColumn; // internal\r\n public _row: TablixRow; // internal\r\n\r\n public type: TablixCellType;\r\n public item: any;\r\n\r\n public _presenter: TablixCellPresenter; // internal\r\n public extension: TablixCellPresenter;\r\n\r\n public position: internal.TablixUtils.CellPosition;\r\n\r\n // Height of the content, set in Binder\r\n public contentHeight: number;\r\n\r\n // Width of the content, set in Binder\r\n public contentWidth: number;\r\n\r\n constructor(presenter: TablixCellPresenter, extension: TablixCellPresenter, row: TablixRow) {\r\n this._presenter = presenter;\r\n this.extension = extension;\r\n this._presenter.initialize(this);\r\n this._row = row;\r\n this.item = null;\r\n this.type = null;\r\n this._horizontalOffset = 0;\r\n this._verticalOffset = 0;\r\n this._colSpan = 1;\r\n this._rowSpan = 1;\r\n this._containerWidth = -1;\r\n this._containerHeight = -1;\r\n this.contentHeight = this.contentWidth = 0;\r\n this.position = new internal.TablixUtils.CellPosition();\r\n }\r\n\r\n public unfixRowHeight() {\r\n this._row.unfixSize();\r\n }\r\n\r\n public get colSpan(): number {\r\n return this._colSpan;\r\n }\r\n\r\n public set colSpan(value: number) {\r\n if (this._colSpan !== value) {\r\n this._presenter.onColumnSpanChanged(value);\r\n this._colSpan = value;\r\n }\r\n }\r\n\r\n public get rowSpan(): number {\r\n return this._rowSpan;\r\n }\r\n\r\n public set rowSpan(value: number) {\r\n if (this._rowSpan !== value) {\r\n this._presenter.onRowSpanChanged(value);\r\n this._rowSpan = value;\r\n this._row.unfixSize();\r\n }\r\n }\r\n\r\n public getCellSpanningHeight(): number {\r\n return this._row.getCellSpanningHeight(this);\r\n }\r\n\r\n public get textAlign(): string {\r\n return this._textAlign;\r\n }\r\n\r\n public set textAlign(value: string) {\r\n if (value !== this._textAlign) {\r\n this._presenter.onTextAlignChanged(value);\r\n this._textAlign = value;\r\n }\r\n }\r\n\r\n public get horizontalOffset(): number {\r\n return this._horizontalOffset;\r\n }\r\n\r\n public get verticalOffset(): number {\r\n return this._verticalOffset;\r\n }\r\n\r\n private isScrollable(): boolean {\r\n return this._scrollable;\r\n }\r\n\r\n public clear(): void {\r\n if (this.isScrollable()) {\r\n this.initializeScrolling();\r\n }\r\n\r\n this._presenter.onClear();\r\n this.setContainerWidth(-1);\r\n this.setContainerHeight(-1);\r\n this.contentHeight = this.contentWidth = 0;\r\n }\r\n\r\n private initializeScrolling() {\r\n this._presenter.onInitializeScrolling();\r\n this._horizontalOffset = 0;\r\n this._verticalOffset = 0;\r\n if (this.colSpan === 1)\r\n this.setContainerWidth(-1);\r\n if (this.rowSpan === 1)\r\n this.setContainerHeight(-1);\r\n }\r\n\r\n public prepare(scrollable: boolean): void {\r\n if (this.isScrollable())\r\n this.initializeScrolling();\r\n\r\n this._scrollable = scrollable;\r\n }\r\n\r\n public scrollVertically(height: number, offset: number): void {\r\n // Ceiling the offset because setting a fraction Width on the TD will ceil it\r\n // We need to let the TD and the OuterDiv to align in order for Borders to touch\r\n let offsetInPixels = Math.ceil(- height * offset);\r\n this._verticalOffset = offsetInPixels;\r\n\r\n if (this.isScrollable()) {\r\n this._presenter.onVerticalScroll(height, offsetInPixels);\r\n this.setContainerHeight(height + offsetInPixels);\r\n }\r\n else {\r\n this.setContainerHeight(this._row.getCellSpanningHeight(this) + offsetInPixels);\r\n }\r\n }\r\n\r\n public scrollHorizontally(width: number, offset: number) {\r\n if (!this.isScrollable()) {\r\n return;\r\n }\r\n\r\n // Ceiling the offset because setting a fraction Width on the TD will ceil it\r\n // We need to let the TD and the OuterDiv to align in order for Borders to touch\r\n let offsetInPixels = Math.ceil(- width * offset);\r\n this._horizontalOffset = offsetInPixels;\r\n this._presenter.onHorizontalScroll(width, offsetInPixels);\r\n this.setContainerWidth(width + offsetInPixels);\r\n }\r\n\r\n public setContainerWidth(value: number): void {\r\n if (value === this._containerWidth)\r\n return;\r\n\r\n this._containerWidth = value;\r\n this._presenter.onContainerWidthChanged(value);\r\n }\r\n\r\n public get containerWidth(): number {\r\n return this._containerWidth;\r\n }\r\n\r\n public setContainerHeight(value: number): void {\r\n if (value < 0)\r\n value = -1;\r\n\r\n if (value === this._containerHeight)\r\n return;\r\n\r\n this._containerHeight = value;\r\n this._presenter.onContinerHeightChanged(value);\r\n }\r\n\r\n public get containerHeight(): number {\r\n return this._containerHeight;\r\n }\r\n\r\n public applyStyle(style: TablixUtils.CellStyle): void {\r\n if (style) {\r\n style.applyStyle(this);\r\n this.contentHeight += style.getExtraBottom() + style.getExtraTop();\r\n this.contentWidth += style.getExtraLeft() + style.getExtraRight();\r\n }\r\n }\r\n\r\n public enableHorizontalResize(enable: boolean, handler: ITablixResizeHandler): void {\r\n this._presenter.enableHorizontalResize(enable, handler);\r\n }\r\n }\r\n\r\n export class TablixColumn implements ITablixGridItem {\r\n public _realizedColumnHeaders: TablixCell[]; // internal\r\n public _realizedCornerCells: TablixCell[]; // internal\r\n public _realizedRowHeaders: TablixCell[]; // internal\r\n public _realizedBodyCells: TablixCell[]; // internal\r\n private _items: any[];\r\n private _itemType: TablixCellType;\r\n private _footerCell: TablixCell;\r\n\r\n private _containerWidth: number;\r\n private _width: number;\r\n private _sizeFixed: boolean;\r\n\r\n private _aligningWidth: number;\r\n private _fixedToAligningWidth: boolean; // move to base class to have it for both rows and columns\r\n\r\n private _presenter: TablixColumnPresenter;\r\n private _owner: TablixGrid;\r\n private _columnIndex: number;\r\n\r\n constructor(presenter: TablixColumnPresenter, columnIndex: number) {\r\n this._presenter = presenter;\r\n this._presenter.initialize(this);\r\n this._containerWidth = -1;\r\n this._width = -1;\r\n this._sizeFixed = false;\r\n this._aligningWidth = -1;\r\n this._fixedToAligningWidth = false;\r\n this._items = [];\r\n this._itemType = null;\r\n this._footerCell = null;\r\n this._columnIndex = columnIndex;\r\n }\r\n\r\n public initialize(owner: TablixGrid): void {\r\n this._owner = owner;\r\n this._realizedRowHeaders = [];\r\n this._realizedColumnHeaders = [];\r\n this._realizedCornerCells = [];\r\n this._realizedBodyCells = [];\r\n }\r\n\r\n public get owner(): TablixGrid {\r\n return this._owner;\r\n }\r\n\r\n private getType(): TablixCellType {\r\n if (this._realizedCornerCells.length > 0)\r\n return TablixCellType.CornerCell;\r\n\r\n return TablixCellType.ColumnHeader;\r\n }\r\n\r\n private getColumnHeadersOrCorners(): TablixCell[] {\r\n if (this._realizedCornerCells.length > 0)\r\n return this._realizedCornerCells;\r\n\r\n return this._realizedColumnHeaders;\r\n }\r\n\r\n private columnHeadersOrCornersEqual(newType: TablixCellType, headers: TablixCell[], hierarchyNavigator: ITablixHierarchyNavigator): boolean {\r\n if (this._items.length !== headers.length)\r\n return false;\r\n\r\n let count = this._items.length;\r\n\r\n for (let i = 0; i < count; i++) {\r\n if (!this.columnHeaderOrCornerEquals(this._itemType, this._items[i], newType, headers[i].item, hierarchyNavigator))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n public get itemType(): TablixCellType {\r\n return this._itemType;\r\n }\r\n\r\n public getLeafItem(): any {\r\n if (this._items.length === 0)\r\n return null;\r\n\r\n return this._items[this._items.length - 1];\r\n }\r\n\r\n public columnHeaderOrCornerEquals(type1: TablixCellType, item1: any, type2: TablixCellType, item2: any, hierarchyNavigator: ITablixHierarchyNavigator): boolean {\r\n if (type1 !== type2)\r\n return false;\r\n\r\n if (type1 === TablixCellType.CornerCell) {\r\n if (!hierarchyNavigator.cornerCellItemEquals(item1, item2))\r\n return false;\r\n } else {\r\n if (!hierarchyNavigator.headerItemEquals(item1, item2))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n public OnLeafRealized(hierarchyNavigator: ITablixHierarchyNavigator): void {\r\n // if the headers/corner have changed we should clear the column size to accomodate for the new content\r\n let type = this.getType();\r\n let columnHeadersOrCorners = this.getColumnHeadersOrCorners();\r\n\r\n if (this.columnHeadersOrCornersEqual(type, columnHeadersOrCorners, hierarchyNavigator)) {\r\n this.clearSpanningCellsWidth(this._realizedColumnHeaders);\r\n }\r\n else {\r\n let count = columnHeadersOrCorners.length;\r\n this._items = [];\r\n\r\n for (let i = 0; i < count; i++) {\r\n this._items.push(columnHeadersOrCorners[i].item);\r\n }\r\n\r\n this._itemType = type;\r\n this.clearSize();\r\n }\r\n }\r\n\r\n private clearSpanningCellsWidth(cells: TablixCell[]): void {\r\n for (let i = 0; i < cells.length; i++) {\r\n let cell = cells[i];\r\n if (cell.colSpan > 1) {\r\n cell.setContainerWidth(-1);\r\n }\r\n }\r\n }\r\n\r\n public addCornerCell(cell: TablixCell) {\r\n cell._column = this;\r\n this._realizedCornerCells.push(cell);\r\n cell.setContainerWidth(this._containerWidth);\r\n }\r\n\r\n public addRowHeader(cell: TablixCell) {\r\n cell._column = this;\r\n this._realizedRowHeaders.push(cell);\r\n cell.setContainerWidth(this._containerWidth);\r\n }\r\n\r\n public addColumnHeader(cell: TablixCell, isLeaf: boolean) {\r\n cell._column = this;\r\n this._realizedColumnHeaders.push(cell);\r\n if (isLeaf) {\r\n cell.setContainerWidth(this._containerWidth);\r\n }\r\n }\r\n\r\n public addBodyCell(cell: TablixCell) {\r\n cell._column = this;\r\n this._realizedBodyCells.push(cell);\r\n cell.setContainerWidth(this._containerWidth);\r\n }\r\n\r\n public set footer(footerCell: TablixCell) {\r\n this._footerCell = footerCell;\r\n footerCell._column = this;\r\n footerCell.setContainerWidth(this._containerWidth);\r\n }\r\n\r\n public get footer(): TablixCell {\r\n return this._footerCell;\r\n }\r\n\r\n public onResize(width: number): void {\r\n if (width === this.getContentContextualWidth())\r\n return;\r\n\r\n this._containerWidth = width;\r\n this.setContainerWidth(this._containerWidth);\r\n this._sizeFixed = true;\r\n this._fixedToAligningWidth = false;\r\n this._aligningWidth = -1;\r\n }\r\n\r\n public onResizeEnd(width: number): void {\r\n // Invoke resize callback\r\n let gridPresenter = this.owner._presenter;\r\n if (gridPresenter)\r\n gridPresenter.invokeColumnResizeEndCallback(this._columnIndex, width);\r\n }\r\n\r\n public fixSize(): void {\r\n let shouldAlign: boolean = this._aligningWidth !== -1;\r\n let switched: boolean = shouldAlign !== this._fixedToAligningWidth;\r\n\r\n if ((this._sizeFixed && !switched && !shouldAlign))\r\n return;\r\n\r\n if (this._aligningWidth === -1) {\r\n this.setContainerWidth(this._containerWidth);\r\n }\r\n else {\r\n this.setContainerWidth(this._aligningWidth);\r\n }\r\n\r\n this._sizeFixed = true;\r\n this._fixedToAligningWidth = this._aligningWidth !== -1;\r\n }\r\n\r\n public clearSize(): void {\r\n this._containerWidth = -1;\r\n this.setContainerWidth(this._containerWidth);\r\n this._sizeFixed = false;\r\n }\r\n\r\n public getContentContextualWidth(): number {\r\n return this._containerWidth;\r\n }\r\n\r\n public getCellIContentContextualWidth(cell: TablixCell): number {\r\n return this._presenter.getCellContentWidth(cell);\r\n }\r\n\r\n public getCellSpanningWidthWithScrolling(cell: ITablixCell, tablixGrid: TablixGrid): number {\r\n let width = this.getContextualWidth() + this.getScrollingOffset();\r\n\r\n if (cell.colSpan > 1) {\r\n let index = this.getIndex(tablixGrid);\r\n let columns = tablixGrid.realizedColumns;\r\n for (let i = 1; i < cell.colSpan; i++)\r\n width += columns[i + index].getContextualWidth();\r\n }\r\n\r\n return width;\r\n }\r\n\r\n public getScrollingOffset(): number {\r\n let offset = 0;\r\n\r\n if (this._realizedColumnHeaders.length > 0)\r\n offset = this._realizedColumnHeaders[this._realizedColumnHeaders.length - 1].horizontalOffset;\r\n\r\n return offset;\r\n }\r\n\r\n public getContextualWidth(): number {\r\n if (this._width === -1 || this._containerWidth === -1)\r\n this._width = this._presenter.getWidth();\r\n\r\n return this._width;\r\n }\r\n\r\n public calculateSize(): number {\r\n if (this._sizeFixed)\r\n return this._containerWidth;\r\n\r\n let contentWidth: number = 0;\r\n\r\n for (let cell of this._realizedColumnHeaders){\r\n if (cell.colSpan === 1)\r\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\r\n }\r\n\r\n for (let cell of this._realizedRowHeaders) {\r\n if (cell.colSpan === 1)\r\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\r\n }\r\n\r\n for (let cell of this._realizedCornerCells) {\r\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\r\n }\r\n\r\n for (let cell of this._realizedBodyCells) {\r\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(cell));\r\n }\r\n\r\n if (this._footerCell !== null) {\r\n if (this._footerCell.colSpan === 1)\r\n contentWidth = Math.max(contentWidth, this._presenter.getCellContentWidth(this._footerCell));\r\n }\r\n\r\n return this._containerWidth = contentWidth;\r\n }\r\n\r\n public setAligningContextualWidth(size: number): void {\r\n this._aligningWidth = size;\r\n }\r\n\r\n public getAligningContextualWidth(): number {\r\n return this._aligningWidth;\r\n }\r\n\r\n private setContainerWidth(value: number): void {\r\n for (let cell of this._realizedColumnHeaders) {\r\n if (cell.colSpan === 1)\r\n cell.setContainerWidth(value);\r\n }\r\n\r\n for (let cell of this._realizedRowHeaders) {\r\n if (cell.colSpan === 1)\r\n cell.setContainerWidth(value);\r\n }\r\n\r\n for (let cell of this._realizedCornerCells) {\r\n cell.setContainerWidth(value);\r\n }\r\n\r\n for (let cell of this._realizedBodyCells) {\r\n cell.setContainerWidth(value);\r\n }\r\n\r\n if (this._footerCell !== null) {\r\n if (this._footerCell.colSpan === 1)\r\n this._footerCell.setContainerWidth(value);\r\n }\r\n\r\n this._width = value; // set cell width to new value\r\n }\r\n\r\n public getTablixCell(): TablixCell {\r\n let realizedCells: TablixCell[] = this._realizedColumnHeaders.length > 0 ? this._realizedColumnHeaders : this._realizedCornerCells;\r\n //Debug.assert(realizedCells.length !== 0, \"At least on header should have been realized\");\r\n return realizedCells[realizedCells.length - 1];\r\n }\r\n\r\n public getIndex(grid: TablixGrid): number {\r\n return grid.realizedColumns.indexOf(this);\r\n }\r\n\r\n public getHeaders(): TablixCell[] {\r\n return this._realizedColumnHeaders;\r\n }\r\n\r\n public getOtherDimensionHeaders(): TablixCell[] {\r\n return this._realizedRowHeaders;\r\n }\r\n\r\n public getCellContextualSpan(cell: TablixCell): number {\r\n return cell.colSpan;\r\n }\r\n\r\n public getOtherDimensionOwner(cell: TablixCell): ITablixGridItem {\r\n return cell._row;\r\n }\r\n }\r\n\r\n export class TablixRow implements ITablixGridItem {\r\n private _allocatedCells: TablixCell[];\r\n\r\n public _realizedRowHeaders: TablixCell[]; // internal\r\n public _realizedColumnHeaders: TablixCell[]; // internal\r\n public _realizedBodyCells: TablixCell[]; // internal\r\n public _realizedCornerCells: TablixCell[]; // internal\r\n\r\n private _realizedCellsCount: number;\r\n private _heightFixed: boolean;\r\n private _containerHeight = -1;\r\n private _height: number;\r\n\r\n private _presenter: TablixRowPresenter;\r\n private _owner: TablixGrid;\r\n\r\n constructor(presenter: TablixRowPresenter) {\r\n this._presenter = presenter;\r\n this._presenter.initialize(this);\r\n this._allocatedCells = [];\r\n this._heightFixed = false;\r\n this._containerHeight = -1;\r\n this._height = -1;\r\n }\r\n\r\n public initialize(owner: TablixGrid): void {\r\n this._owner = owner;\r\n this._realizedRowHeaders = [];\r\n this._realizedBodyCells = [];\r\n this._realizedCornerCells = [];\r\n this._realizedColumnHeaders = [];\r\n this._realizedCellsCount = 0;\r\n }\r\n\r\n public get presenter(): TablixRowPresenter {\r\n return this._presenter;\r\n }\r\n\r\n public get owner(): TablixGrid {\r\n return this._owner;\r\n }\r\n\r\n public releaseUnusedCells(owner: TablixControl) {\r\n this.releaseCells(owner, this._realizedCellsCount);\r\n }\r\n\r\n public releaseAllCells(owner: TablixControl) {\r\n this.releaseCells(owner, 0);\r\n }\r\n\r\n private releaseCells(owner: TablixControl, startIndex: number): void {\r\n let cells: TablixCell[] = this._allocatedCells;\r\n let length = cells.length;\r\n\r\n for (let i = startIndex; i < length; i++) {\r\n let cell = cells[i];\r\n owner._unbindCell(cell);\r\n cell.clear();\r\n }\r\n }\r\n\r\n public moveScrollableCellsToEnd(count: number): void {\r\n let frontIndex: number = Math.max(this._realizedRowHeaders.length, this._realizedCornerCells.length);\r\n\r\n for (let i = frontIndex; i < frontIndex + count; i++) {\r\n let cell = this._allocatedCells[i];\r\n this._presenter.onRemoveCell(cell);\r\n this._presenter.onAppendCell(cell);\r\n this._allocatedCells.push(cell);\r\n }\r\n\r\n this._allocatedCells.splice(frontIndex, count);\r\n }\r\n\r\n public moveScrollableCellsToStart(count: number): void {\r\n let frontIndex: number = Math.max(this._realizedRowHeaders.length, this._realizedCornerCells.length);\r\n\r\n for (let i = frontIndex; i < frontIndex + count; i++) {\r\n let cell = this._allocatedCells.pop();\r\n this._presenter.onRemoveCell(cell);\r\n this._presenter.onInsertCellBefore(cell, this._allocatedCells[frontIndex]);\r\n this._allocatedCells.splice(frontIndex, 0, cell);\r\n }\r\n }\r\n\r\n public getOrCreateCornerCell(column: TablixColumn): TablixCell {\r\n let cell: TablixCell = this.getOrCreateCell();\r\n cell.prepare(false);\r\n column.addCornerCell(cell);\r\n this._realizedCornerCells.push(cell);\r\n cell.setContainerHeight(this._containerHeight);\r\n return cell;\r\n }\r\n\r\n public getOrCreateRowHeader(column: TablixColumn, scrollable: boolean, leaf: boolean): TablixCell {\r\n let cell: TablixCell = this.getOrCreateCell();\r\n cell.prepare(scrollable);\r\n column.addRowHeader(cell);\r\n this._realizedRowHeaders.push(cell);\r\n if (leaf)\r\n cell.setContainerHeight(this._containerHeight);\r\n return cell;\r\n }\r\n\r\n public getOrCreateColumnHeader(column: TablixColumn, scrollable: boolean, leaf: boolean): TablixCell {\r\n let cell: TablixCell = this.getOrCreateCell();\r\n cell.prepare(scrollable);\r\n column.addColumnHeader(cell, leaf);\r\n this._realizedColumnHeaders.push(cell);\r\n cell.setContainerHeight(this._containerHeight);\r\n return cell;\r\n }\r\n\r\n public getOrCreateBodyCell(column: TablixColumn, scrollable: boolean): TablixCell {\r\n let cell: TablixCell = this.getOrCreateCell();\r\n cell.prepare(scrollable);\r\n column.addBodyCell(cell);\r\n this._realizedBodyCells.push(cell);\r\n cell.setContainerHeight(this._containerHeight);\r\n return cell;\r\n }\r\n\r\n public getOrCreateFooterRowHeader(column: TablixColumn): TablixCell {\r\n let cell: TablixCell = this.getOrCreateCell();\r\n cell.prepare(false);\r\n column.footer = cell;\r\n this._realizedRowHeaders.push(cell);\r\n cell.setContainerHeight(this._containerHeight);\r\n return cell;\r\n }\r\n\r\n public getOrCreateFooterBodyCell(column: TablixColumn, scrollable: boolean): TablixCell {\r\n let cell: TablixCell = this.getOrCreateCell();\r\n cell.prepare(scrollable);\r\n column.footer = cell;\r\n this._realizedBodyCells.push(cell);\r\n cell.setContainerHeight(this._containerHeight);\r\n return cell;\r\n }\r\n\r\n public getRowHeaderLeafIndex(): number {\r\n let index = -1;\r\n let count = this._allocatedCells.length;\r\n for (let i = 0; i < count; i++) {\r\n if (this._allocatedCells[i].type !== TablixCellType.RowHeader)\r\n break;\r\n index++;\r\n }\r\n\r\n return index;\r\n }\r\n\r\n public getAllocatedCellAt(index: number) {\r\n return this._allocatedCells[index];\r\n }\r\n\r\n public moveCellsBy(delta: number) {\r\n if (this._allocatedCells.length === 0)\r\n return;\r\n\r\n if (delta > 0) {\r\n let refCell = this._allocatedCells[0];\r\n for (let i = 0; i < delta; i++) {\r\n let cell: TablixCell = this.createCell(this);\r\n this._presenter.onInsertCellBefore(cell, refCell);\r\n this._allocatedCells.unshift(cell);\r\n refCell = cell;\r\n }\r\n }\r\n else {\r\n delta = -delta;\r\n for (let i = 0; i < delta; i++) {\r\n this._presenter.onRemoveCell(this._allocatedCells[i]);\r\n }\r\n this._allocatedCells.splice(0, delta);\r\n }\r\n }\r\n\r\n public getRealizedCellCount() {\r\n return this._realizedCellsCount;\r\n }\r\n\r\n public getRealizedHeadersCount(): number {\r\n return this._realizedRowHeaders.length;\r\n }\r\n\r\n public getRealizedHeaderAt(index: number) {\r\n return this._realizedRowHeaders[index];\r\n }\r\n\r\n public getTablixCell(): TablixCell {\r\n let realizedCells: TablixCell[];\r\n\r\n if (this._realizedRowHeaders.length > 0) {\r\n realizedCells = this._realizedRowHeaders;\r\n } else if (this._realizedCornerCells.length > 0) {\r\n realizedCells = this._realizedCornerCells;\r\n } else {\r\n realizedCells = this._realizedColumnHeaders;\r\n }\r\n\r\n //Debug.assert(realizedCells.length !== 0, \"At least on header should have been realized\");\r\n return realizedCells[realizedCells.length - 1];\r\n }\r\n\r\n public getOrCreateEmptySpaceCell(): TablixCell {\r\n let cell: TablixCell = this._allocatedCells[this._realizedCellsCount];\r\n if (cell === undefined) {\r\n cell = this.createCell(this);\r\n this._allocatedCells[this._realizedCellsCount] = cell;\r\n this._presenter.onAppendCell(cell);\r\n }\r\n return cell;\r\n }\r\n\r\n private createCell(row: TablixRow): TablixCell {\r\n let presenter = this._presenter.createCellPresenter(this._owner.owner.layoutManager.getLayoutKind());\r\n return new TablixCell(presenter, presenter, this);\r\n }\r\n\r\n private getOrCreateCell(): TablixCell {\r\n let cell: TablixCell = this._allocatedCells[this._realizedCellsCount];\r\n if (cell === undefined) {\r\n cell = this.createCell(this);\r\n this._allocatedCells[this._realizedCellsCount] = cell;\r\n this._presenter.onAppendCell(cell);\r\n } else {\r\n cell.colSpan = 1;\r\n cell.rowSpan = 1;\r\n }\r\n\r\n this._realizedCellsCount = this._realizedCellsCount + 1;\r\n return cell;\r\n }\r\n\r\n public onResize(height: number): void {\r\n if (height === this.getContentContextualWidth())\r\n return;\r\n\r\n this._containerHeight = height;\r\n this.setContentHeight();\r\n this._heightFixed = true;\r\n this.setAligningContextualWidth(-1);\r\n }\r\n\r\n public onResizeEnd(height: number): void { }\r\n\r\n public fixSize(): void {\r\n if (this.sizeFixed())\r\n return;\r\n\r\n this.setContentHeight();\r\n\r\n this._heightFixed = true;\r\n }\r\n\r\n public unfixSize(): void {\r\n this._heightFixed = false;\r\n this._height = -1;\r\n }\r\n\r\n public getContentContextualWidth(): number {\r\n return this._containerHeight;\r\n }\r\n\r\n public getCellIContentContextualWidth(cell: TablixCell): number {\r\n return this.presenter.getCellContentHeight(cell);\r\n }\r\n\r\n public getCellSpanningHeight(cell: ITablixCell): number {\r\n let height = this.getContextualWidth();\r\n\r\n if (cell.rowSpan > 1) {\r\n let index = this.getIndex(this.owner);\r\n let rows = this.owner.realizedRows;\r\n for (let i = 1; i < cell.rowSpan; i++)\r\n height += rows[i + index].getContextualWidth();\r\n }\r\n\r\n return height;\r\n }\r\n\r\n public getContextualWidth(): number {\r\n if (this._height === -1 || this._containerHeight === -1)\r\n this._height = this._presenter.getHeight();\r\n\r\n return this._height;\r\n }\r\n\r\n public sizeFixed(): boolean {\r\n return this._heightFixed;\r\n }\r\n\r\n public calculateSize(): number {\r\n if (this._heightFixed)\r\n return this._containerHeight;\r\n\r\n let contentHeight: number = 0;\r\n\r\n let count = this._realizedRowHeaders.length;\r\n for (let i = 0; i < count; i++) {\r\n let cell: TablixCell = this._realizedRowHeaders[i];\r\n if (cell.rowSpan === 1)\r\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(cell));\r\n }\r\n\r\n count = this._realizedCornerCells.length;\r\n for (let i = 0; i < count; i++) {\r\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(this._realizedCornerCells[i]));\r\n }\r\n\r\n count = this._realizedColumnHeaders.length;\r\n for (let i = 0; i < count; i++) {\r\n let cell: TablixCell = this._realizedColumnHeaders[i];\r\n if (cell.rowSpan === 1)\r\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(cell));\r\n }\r\n\r\n count = this._realizedBodyCells.length;\r\n for (let i = 0; i < count; i++) {\r\n contentHeight = Math.max(contentHeight, this._presenter.getCellContentHeight(this._realizedBodyCells[i]));\r\n }\r\n\r\n return this._containerHeight = contentHeight;\r\n }\r\n\r\n public setAligningContextualWidth(size: number): void {\r\n // TODO should be implemented when we support variable row heights\r\n }\r\n\r\n public getAligningContextualWidth(): number {\r\n // TODO should be implemented when we support variable row heights\r\n return -1;\r\n }\r\n\r\n private setContentHeight(): void {\r\n let count = this._realizedRowHeaders.length;\r\n // Need to do them in reverse order so that leaf headers are set first\r\n for (let i = count-1; i >= 0; i--) {\r\n let cell: TablixCell = this._realizedRowHeaders[i];\r\n cell.setContainerHeight(this._containerHeight);\r\n if (cell.rowSpan > 1)\r\n cell.setContainerHeight(this.getCellSpanningHeight(cell));\r\n }\r\n\r\n count = this._realizedCornerCells.length;\r\n for (let i = 0; i < count; i++) {\r\n this._realizedCornerCells[i].setContainerHeight(this._containerHeight);\r\n }\r\n\r\n count = this._realizedColumnHeaders.length;\r\n for (let i = 0; i < count; i++) {\r\n let cell: TablixCell = this._realizedColumnHeaders[i];\r\n cell.setContainerHeight(this._containerHeight);\r\n if (cell.rowSpan > 1)\r\n cell.setContainerHeight(this.getCellSpanningHeight(cell));\r\n }\r\n\r\n count = this._realizedBodyCells.length;\r\n for (let i = 0; i < count; i++) {\r\n this._realizedBodyCells[i].setContainerHeight(this._containerHeight);\r\n }\r\n\r\n this._height = -1;\r\n }\r\n\r\n public getIndex(grid: TablixGrid): number {\r\n return grid.realizedRows.indexOf(this);\r\n }\r\n\r\n public getHeaders(): TablixCell[] {\r\n return this._realizedRowHeaders;\r\n }\r\n\r\n public getOtherDimensionHeaders(): TablixCell[] {\r\n return this._realizedColumnHeaders;\r\n }\r\n\r\n public getCellContextualSpan(cell: TablixCell): number {\r\n return cell.rowSpan;\r\n }\r\n\r\n public getOtherDimensionOwner(cell: TablixCell): ITablixGridItem {\r\n return cell._column;\r\n }\r\n }\r\n\r\n export class TablixGrid {\r\n private _owner: TablixControl;\r\n\r\n private _rows: TablixRow[];\r\n private _realizedRows: TablixRow[];\r\n\r\n private _columns: TablixColumn[];\r\n private _realizedColumns: TablixColumn[];\r\n\r\n private _footerRow: TablixRow;\r\n\r\n private _emptySpaceHeaderCell: TablixCell;\r\n private _emptyFooterSpaceCell: TablixCell;\r\n\r\n public _presenter: TablixGridPresenter; // internal\r\n\r\n private _fillColumnsProportionally: boolean;\r\n\r\n constructor(presenter: TablixGridPresenter) {\r\n this._presenter = presenter;\r\n this._footerRow = null;\r\n }\r\n\r\n public initialize(owner: TablixControl, gridHost: HTMLElement, footerHost: HTMLElement) {\r\n this._owner = owner;\r\n this._presenter.initialize(this, gridHost, footerHost, owner);\r\n\r\n this.fillColumnsProportionally = false;\r\n this._realizedRows = [];\r\n this._realizedColumns = [];\r\n this._emptySpaceHeaderCell = null;\r\n this._emptyFooterSpaceCell = null;\r\n }\r\n\r\n public get owner(): TablixControl {\r\n return this._owner;\r\n }\r\n\r\n public set fillColumnsProportionally(value: boolean) {\r\n if (this._fillColumnsProportionally === value)\r\n return;\r\n\r\n this._fillColumnsProportionally = value;\r\n this._presenter.onFillColumnsProportionallyChanged(value);\r\n }\r\n\r\n public get fillColumnsProportionally(): boolean {\r\n return this._fillColumnsProportionally;\r\n }\r\n\r\n public get realizedColumns(): TablixColumn[] {\r\n return this._realizedColumns;\r\n }\r\n\r\n public set realizedColumns(columns: TablixColumn[]) {\r\n this._realizedColumns = columns;\r\n }\r\n\r\n public get realizedRows(): TablixRow[] {\r\n return this._realizedRows;\r\n }\r\n\r\n public set realizedRows(rows: TablixRow[]) {\r\n this._realizedRows = rows;\r\n }\r\n\r\n public get footerRow(): TablixRow {\r\n return this._footerRow;\r\n }\r\n\r\n public get emptySpaceHeaderCell(): TablixCell {\r\n return this._emptySpaceHeaderCell;\r\n }\r\n\r\n public get emptySpaceFooterCell(): TablixCell {\r\n return this._emptyFooterSpaceCell;\r\n }\r\n\r\n public ShowEmptySpaceCells(rowSpan: number, width: number): void {\r\n if (this._realizedRows.length === 0)\r\n return;\r\n\r\n if (this._realizedRows.length !== 0 && !this._emptySpaceHeaderCell) {\r\n this._emptySpaceHeaderCell = this._realizedRows[0].getOrCreateEmptySpaceCell();\r\n this._emptySpaceHeaderCell.rowSpan = rowSpan;\r\n this._emptySpaceHeaderCell.colSpan = 1;\r\n this._emptySpaceHeaderCell.setContainerWidth(width);\r\n }\r\n\r\n if (this._footerRow && (this._emptyFooterSpaceCell === null)) {\r\n this._emptyFooterSpaceCell = this._footerRow.getOrCreateEmptySpaceCell();\r\n this._emptyFooterSpaceCell.rowSpan = 1;\r\n this._emptyFooterSpaceCell.colSpan = 1;\r\n this._emptyFooterSpaceCell.setContainerWidth(width);\r\n }\r\n }\r\n\r\n public HideEmptySpaceCells(): void {\r\n if (this._emptySpaceHeaderCell) {\r\n this._emptySpaceHeaderCell.clear();\r\n this._emptySpaceHeaderCell = null;\r\n }\r\n\r\n if (this._emptyFooterSpaceCell) {\r\n this._emptyFooterSpaceCell.clear();\r\n this._emptyFooterSpaceCell = null;\r\n }\r\n }\r\n\r\n public onStartRenderingSession(clear: boolean): void {\r\n if (clear) {\r\n this.clearRows();\r\n this.clearColumns();\r\n }\r\n }\r\n\r\n public onStartRenderingIteration(): void {\r\n this.initializeRows();\r\n this.initializeColumns();\r\n }\r\n\r\n public onEndRenderingIteration(): void {\r\n let rows: TablixRow[] = this._rows;\r\n if (rows !== undefined) {\r\n let rowCount = rows.length;\r\n for (let i = 0; i < rowCount; i++) {\r\n rows[i].releaseUnusedCells(this._owner);\r\n }\r\n }\r\n\r\n if (this._footerRow) {\r\n this._footerRow.releaseUnusedCells(this._owner);\r\n }\r\n }\r\n\r\n public getOrCreateRow(rowIndex: number): TablixRow {\r\n let currentRow: TablixRow = this._rows[rowIndex];\r\n if (currentRow === undefined) {\r\n currentRow = new TablixRow(this._presenter.createRowPresenter());\r\n currentRow.initialize(this);\r\n this._presenter.onAppendRow(currentRow);\r\n this._rows[rowIndex] = currentRow;\r\n }\r\n\r\n if (this._realizedRows[rowIndex] === undefined) {\r\n this._realizedRows[rowIndex] = currentRow;\r\n }\r\n\r\n return currentRow;\r\n }\r\n\r\n public getOrCreateFootersRow(): TablixRow {\r\n if (this._footerRow === null) {\r\n this._footerRow = new TablixRow(this._presenter.createRowPresenter());\r\n this._footerRow.initialize(this);\r\n this._presenter.onAddFooterRow(this._footerRow);\r\n }\r\n return this._footerRow;\r\n }\r\n\r\n public moveRowsToEnd(moveFromIndex: number, count: number) {\r\n for (let i = 0; i < count; i++) {\r\n let row = this._rows[i + moveFromIndex];\r\n debug.assertValue(row, \"Invalid Row Index\");\r\n row.unfixSize();\r\n this._presenter.onRemoveRow(row);\r\n this._presenter.onAppendRow(row);\r\n this._rows.push(row);\r\n }\r\n\r\n this._rows.splice(moveFromIndex, count);\r\n }\r\n\r\n public moveRowsToStart(moveToIndex: number, count: number) {\r\n let refRow = this._rows[moveToIndex];\r\n debug.assertValue(refRow, \"Invalid Row Index\");\r\n\r\n for (let i = 0; i < count; i++) {\r\n let row = this._rows.pop();\r\n row.unfixSize();\r\n this._presenter.onRemoveRow(row);\r\n this._presenter.onInsertRowBefore(row, refRow);\r\n this._rows.splice(moveToIndex + i, 0, row);\r\n }\r\n }\r\n\r\n public moveColumnsToEnd(moveFromIndex: number, count: number) {\r\n let firstCol: number = this._rows[0]._realizedCornerCells.length;\r\n let leafStartDepth: number = Math.max(this._columns[firstCol]._realizedColumnHeaders.length - 1, 0);\r\n\r\n for (let i = leafStartDepth; i < this._rows.length; i++) {\r\n this._rows[i].moveScrollableCellsToEnd(count);\r\n }\r\n\r\n for (let i = 0; i < count; i++) {\r\n let column = this._columns[i + moveFromIndex];\r\n //Debug.assertValue(column, \"Invalid Column Index\");\r\n this._columns.push(column);\r\n }\r\n\r\n this._columns.splice(moveFromIndex, count);\r\n }\r\n\r\n public moveColumnsToStart(moveToIndex: number, count: number) {\r\n let firstCol: number = this._rows[0]._realizedCornerCells.length;\r\n let leafStartDepth: number = Math.max(this._columns[firstCol]._realizedColumnHeaders.length - 1, 0);\r\n\r\n for (let i = leafStartDepth; i < this._rows.length; i++) {\r\n this._rows[i].moveScrollableCellsToStart(count);\r\n }\r\n\r\n for (let i = 0; i < count; i++) {\r\n let column = this._columns.pop();\r\n this._columns.splice(moveToIndex + i, 0, column);\r\n }\r\n }\r\n\r\n public getOrCreateColumn(columnIndex: number): TablixColumn {\r\n let currentColumn: TablixColumn = this._columns[columnIndex];\r\n if (currentColumn === undefined) {\r\n currentColumn = new TablixColumn(this._presenter.createColumnPresenter(columnIndex), columnIndex);\r\n currentColumn.initialize(this);\r\n this._columns[columnIndex] = currentColumn;\r\n }\r\n\r\n if (this._realizedColumns[columnIndex] === undefined) {\r\n this._realizedColumns[columnIndex] = currentColumn;\r\n }\r\n\r\n return currentColumn;\r\n }\r\n\r\n private initializeColumns(): void {\r\n if (!this._columns)\r\n this._columns = [];\r\n\r\n let length: number = this._columns.length;\r\n\r\n for (let i = 0; i < length; i++) {\r\n this._columns[i].initialize(this);\r\n }\r\n\r\n this._realizedColumns = [];\r\n }\r\n\r\n private clearColumns() {\r\n this._columns = null;\r\n this._realizedColumns = null;\r\n }\r\n\r\n private initializeRows(): void {\r\n // make sure rowDimension confirms it and it's not null in the grid\r\n let hasFooter: boolean = this._owner.rowDimension.hasFooter() && (this._footerRow !== null);\r\n\r\n this._realizedRows = [];\r\n\r\n if (!this._rows) {\r\n this._rows = [];\r\n }\r\n\r\n let rows: TablixRow[] = this._rows;\r\n let length: number = rows.length;\r\n\r\n for (let i = 0; i < length; i++) {\r\n rows[i].initialize(this);\r\n }\r\n\r\n if (hasFooter) {\r\n if (!this._footerRow) {\r\n this.getOrCreateFootersRow();\r\n }\r\n this._footerRow.initialize(this);\r\n }\r\n }\r\n\r\n private clearRows() {\r\n let rows: TablixRow[] = this._rows;\r\n if (rows) {\r\n let length = rows.length;\r\n for (let i = 0; i < length; i++) {\r\n rows[i].releaseAllCells(this._owner);\r\n }\r\n\r\n if (this._footerRow)\r\n this._footerRow.releaseAllCells(this._owner);\r\n\r\n this._presenter.onClear();\r\n this._footerRow = null;\r\n this._rows = null;\r\n this._realizedRows = null;\r\n }\r\n }\r\n\r\n public getWidth(): number {\r\n return this._presenter.getWidth();\r\n }\r\n\r\n public getHeight(): number {\r\n return this._presenter.getHeight();\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls.internal {\r\n import PixelConverter = jsCommon.PixelConverter;\r\n\r\n /**\r\n * This class is used for layouts that don't or cannot\r\n * rely on DOM measurements. Instead they compute all required\r\n * widths and heights and store it in this structure.\r\n */\r\n export class SizeComputationManager {\r\n // Minimum size for a column, used to calculate layout\r\n private static TablixMinimumColumnWidth = 75;\r\n\r\n private _viewport: IViewport;\r\n private _columnCount: number;\r\n private _cellWidth: number;\r\n private _cellHeight: number;\r\n private _scalingFactor: number;\r\n\r\n public hasImageContent: boolean;\r\n\r\n public get visibleWidth(): number {\r\n return this._viewport ? this._viewport.width : 0;\r\n }\r\n\r\n public get visibleHeight(): number {\r\n return this._viewport ? this._viewport.height : 0;\r\n }\r\n\r\n public get gridWidth(): number {\r\n return this.visibleWidth;\r\n }\r\n\r\n public get gridHeight(): number {\r\n return this.visibleHeight;\r\n }\r\n\r\n public get rowHeight(): number {\r\n return this._cellHeight;\r\n }\r\n\r\n public get cellWidth(): number {\r\n return this._cellWidth;\r\n }\r\n\r\n public get cellHeight(): number {\r\n return this._cellHeight;\r\n }\r\n\r\n public get contentWidth(): number {\r\n return this._cellWidth;\r\n }\r\n\r\n public get contentHeight(): number {\r\n return this._cellHeight;\r\n }\r\n\r\n public updateColumnCount(columnCount: number): void {\r\n this._columnCount = columnCount;\r\n }\r\n\r\n public updateRowHeight(rowHeight: number): void {\r\n this._cellHeight = rowHeight;\r\n }\r\n\r\n public updateScalingFactor(scalingFactor: number): void {\r\n this._scalingFactor = scalingFactor;\r\n this._cellWidth = this.computeColumnWidth(this._columnCount);\r\n }\r\n\r\n public updateViewport(viewport: IViewport): void {\r\n this._viewport = viewport;\r\n\r\n this._cellWidth = this.computeColumnWidth(this._columnCount);\r\n this._cellHeight = this.computeColumnHeight();\r\n }\r\n\r\n private computeColumnWidth(totalColumnCount: number): number {\r\n let scalingFactor = this._scalingFactor;\r\n\r\n if (!scalingFactor)\r\n scalingFactor = 1;\r\n\r\n let minimumColumnWidth = scalingFactor * SizeComputationManager.TablixMinimumColumnWidth;\r\n let maxAllowedColumns = Math.floor(this._viewport.width / minimumColumnWidth);\r\n\r\n return this.fitToColumnCount(maxAllowedColumns, totalColumnCount);\r\n }\r\n\r\n private computeColumnHeight(): number {\r\n if (!this.hasImageContent)\r\n return this._cellHeight;\r\n\r\n let width = this._viewport.width;\r\n if (width <= 250) {\r\n // Small\r\n return 20;\r\n }\r\n else if (width <= 510) {\r\n // Medium\r\n return 51;\r\n }\r\n else if (width <= 770) {\r\n // Large\r\n return 52;\r\n }\r\n\r\n debug.assertFail(\"Fixed size is only for viewport up to 770px width.\");\r\n }\r\n\r\n private fitToColumnCount(maxAllowedColumnCount: number, totalColumnCount: number): number {\r\n let columnsToFit = Math.min(maxAllowedColumnCount, totalColumnCount);\r\n return Math.floor(this._viewport.width / columnsToFit);\r\n }\r\n }\r\n\r\n export class DimensionLayoutManager implements IDimensionLayoutManager {\r\n public static _pixelPrecision = 1.0001;\r\n public static _scrollOffsetPrecision = 0.01;\r\n\r\n public _grid: TablixGrid; // internal\r\n public _gridOffset: number; // internal\r\n\r\n protected _contextualWidthToFill: number;\r\n\r\n private _owner: TablixLayoutManager;\r\n private _realizationManager: TablixDimensionRealizationManager;\r\n private _alignToEnd: boolean;\r\n private _lastScrollOffset: number;\r\n private _isScrolling: boolean;\r\n private _fixedSizeEnabled: boolean;\r\n private _done: boolean;\r\n private _measureEnabled: boolean;\r\n\r\n constructor(owner: TablixLayoutManager, grid: TablixGrid, realizationManager: TablixDimensionRealizationManager) {\r\n //debug.assertValue(realizationManager, \"Realization Manager must be defined\");\r\n\r\n this._owner = owner;\r\n this._grid = grid;\r\n this._lastScrollOffset = null;\r\n this._isScrolling = false;\r\n this._fixedSizeEnabled = true;\r\n this._done = false;\r\n\r\n this._realizationManager = realizationManager;\r\n }\r\n\r\n public get owner(): TablixLayoutManager {\r\n return this._owner;\r\n }\r\n\r\n public set owner(owner: TablixLayoutManager) {\r\n this._owner = owner;\r\n }\r\n\r\n public get realizationManager(): TablixDimensionRealizationManager {\r\n return this._realizationManager;\r\n }\r\n\r\n public get fixedSizeEnabled(): boolean {\r\n return this._fixedSizeEnabled;\r\n }\r\n\r\n public set fixedSizeEnabled(enable: boolean) {\r\n this._fixedSizeEnabled = enable;\r\n }\r\n\r\n public onCornerCellRealized(item: any, cell: ITablixCell, leaf: boolean): void {\r\n this._realizationManager.onCornerCellRealized(item, cell);\r\n }\r\n\r\n public onHeaderRealized(item: any, cell: ITablixCell, leaf): void {\r\n this._realizationManager.onHeaderRealized(item, cell, leaf);\r\n }\r\n\r\n public get needsToRealize(): boolean {\r\n return this._realizationManager.needsToRealize;\r\n }\r\n\r\n public getVisibleSizeRatio(): number {\r\n return 1 - this.dimension.getFractionScrollOffset();\r\n }\r\n\r\n public get alignToEnd(): boolean {\r\n return this._alignToEnd;\r\n }\r\n\r\n public get done(): boolean {\r\n return this._done;\r\n }\r\n\r\n public _requiresMeasure(): boolean {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._requiresMeasure\");\r\n return true;\r\n }\r\n\r\n public startScrollingSession(): void {\r\n this._isScrolling = true;\r\n }\r\n\r\n public endScrollingSession(): void {\r\n this._isScrolling = false;\r\n }\r\n\r\n public isScrolling(): boolean {\r\n return this._isScrolling;\r\n }\r\n\r\n public isResizing(): boolean {\r\n return false;\r\n }\r\n\r\n public getOtherHierarchyContextualHeight(): number {\r\n let otherDimension = this.dimension.otherDimension;\r\n let count = otherDimension.getDepth();\r\n\r\n let contextualHeight = 0;\r\n let items = this._getRealizedItems();\r\n\r\n if (items.length > 0) {\r\n for (let i = 0; i < count; i++) {\r\n contextualHeight += items[i].getContextualWidth();\r\n }\r\n }\r\n\r\n return contextualHeight;\r\n }\r\n\r\n public _isAutoSized(): boolean {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._isAutoSized\");\r\n return false;\r\n }\r\n\r\n public onStartRenderingSession() {\r\n this._measureEnabled = this._requiresMeasure();\r\n this._gridOffset = this.dimension.otherDimension.getDepth();\r\n }\r\n\r\n public onEndRenderingSession() {\r\n this._realizationManager.onEndRenderingSession();\r\n this._alignToEnd = false;\r\n this._done = false;\r\n this._measureEnabled = true;\r\n this._sendDimensionsToControl();\r\n }\r\n\r\n /**\r\n * Implementing classes must override this to send dimentions to TablixControl.\r\n */\r\n public _sendDimensionsToControl(): void { // extending class overrides this\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._sendDimensionsToControl\");\r\n }\r\n\r\n public get measureEnabled() {\r\n return this._measureEnabled;\r\n }\r\n\r\n public getFooterContextualWidth(): number {\r\n return 0;\r\n }\r\n\r\n public onStartRenderingIteration(clear: boolean, contextualWidth: number) {\r\n if (this._measureEnabled && !this._done) {\r\n this._contextualWidthToFill = (contextualWidth - this.otherScrollbarContextualWidth) * this.getGridScale() - this.getFooterContextualWidth();\r\n }\r\n\r\n this._realizationManager.onStartRenderingIteration();\r\n\r\n if (clear) {\r\n this._lastScrollOffset = null;\r\n }\r\n else if (this._lastScrollOffset !== null) {\r\n this.swapElements();\r\n }\r\n }\r\n\r\n public get allItemsRealized(): boolean {\r\n return this.getRealizedItemsCount() - this._gridOffset === this.dimension.getItemsCount() || this.dimension.getItemsCount() === 0;\r\n }\r\n\r\n public onEndRenderingIteration(): void {\r\n if (this._done) {\r\n return;\r\n }\r\n\r\n if (!this._measureEnabled) {\r\n this._lastScrollOffset = this.dimension.scrollOffset;\r\n this._done = true;\r\n return;\r\n }\r\n\r\n let gridContextualWidth: number = this.getGridContextualWidth();\r\n\r\n let filled: boolean = Double.greaterOrEqualWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\r\n let allRealized = this.allItemsRealized;\r\n\r\n let newScrollOffset;\r\n\r\n if (filled) {\r\n newScrollOffset = this.scrollForwardToAlignEnd(gridContextualWidth);\r\n }\r\n else {\r\n newScrollOffset = this.scrollBackwardToFill(gridContextualWidth);\r\n }\r\n\r\n this._realizationManager.onEndRenderingIteration(gridContextualWidth, filled);\r\n\r\n let originalScrollbarVisible: boolean = this.dimension.scrollbar.visible;\r\n\r\n this.updateScrollbar(gridContextualWidth);\r\n\r\n this._done = (filled || allRealized) &&\r\n this.dimension.scrollbar.visible === originalScrollbarVisible &&\r\n Double.equalWithPrecision(newScrollOffset, this.dimension.scrollOffset, DimensionLayoutManager._scrollOffsetPrecision);\r\n\r\n this.dimension.scrollOffset = newScrollOffset;\r\n this._lastScrollOffset = this.dimension.scrollOffset;\r\n }\r\n\r\n private getScrollDeltaWithinPage(): number {\r\n if (this._lastScrollOffset !== null) {\r\n let delta = this.dimension.getIntegerScrollOffset() - Math.floor(this._lastScrollOffset);\r\n if (Math.abs(delta) < this.getRealizedItemsCount() - this.dimension.otherDimension.getDepth()) {\r\n return delta;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private swapElements() {\r\n let delta = this.getScrollDeltaWithinPage();\r\n if (delta !== null) {\r\n let otherHierarchyDepth = this.dimension.otherDimension.getDepth();\r\n\r\n if (Math.abs(delta) < this.getRealizedItemsCount() - otherHierarchyDepth) {\r\n if (delta > 0) {\r\n this._moveElementsToBottom(otherHierarchyDepth, delta);\r\n }\r\n else if (delta < 0) {\r\n this._moveElementsToTop(otherHierarchyDepth, -delta);\r\n }\r\n }\r\n }\r\n }\r\n\r\n public _getRealizedItems(): ITablixGridItem[] {\r\n // abstract\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._getRealizedItems\");\r\n return null;\r\n }\r\n\r\n public getRealizedItemsCount(): number {\r\n let realizedItems = this._getRealizedItems();\r\n return realizedItems.length;\r\n }\r\n\r\n public _moveElementsToBottom(moveFromIndex: number, count): void {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._moveElementsToBottom\");\r\n }\r\n\r\n public _moveElementsToTop(moveToIndex: number, count): void {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._moveElementsToTop\");\r\n }\r\n\r\n public isScrollingWithinPage(): boolean {\r\n return this.getScrollDeltaWithinPage() !== null;\r\n }\r\n\r\n public getGridContextualWidth(): number {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.getGridContextualWidth\");\r\n return 0;\r\n }\r\n\r\n private updateScrollbar(gridContextualWidth: number): void {\r\n let scrollbar = this.dimension.scrollbar;\r\n scrollbar.viewMin = this.dimension.scrollOffset;\r\n scrollbar.min = 0;\r\n scrollbar.max = this.dimension.getItemsCount();\r\n scrollbar.viewSize = this.getViewSize(gridContextualWidth);\r\n this.dimension.scrollbar.show(this.canScroll(gridContextualWidth));\r\n }\r\n\r\n public getViewSize(gridContextualWidth: number): number {\r\n let count: number = this.getRealizedItemsCount();\r\n if (count === 0)\r\n return 0;\r\n\r\n let startIndex = this._gridOffset;\r\n let sizeInItems = 0;\r\n let sizeInPixels = 0;\r\n\r\n let widthToFill: number = this._contextualWidthToFill;\r\n let scrollableArea = widthToFill - this.getOtherHierarchyContextualHeight();\r\n\r\n let error = this.getMeaurementError(gridContextualWidth);\r\n\r\n for (let i = startIndex; i < count; i++) {\r\n let visibleRatio;\r\n if (i === startIndex) {\r\n visibleRatio = this.getVisibleSizeRatio();\r\n }\r\n else\r\n visibleRatio = 1;\r\n\r\n let itemContextualWidth = this.getItemContextualWidthWithScrolling(i) * error;\r\n\r\n sizeInPixels += itemContextualWidth;\r\n sizeInItems += visibleRatio;\r\n\r\n if (Double.greaterWithPrecision(sizeInPixels, scrollableArea, DimensionLayoutManager._pixelPrecision)) {\r\n sizeInItems -= ((sizeInPixels - scrollableArea) / itemContextualWidth) * visibleRatio;\r\n break;\r\n }\r\n }\r\n\r\n return sizeInItems;\r\n }\r\n\r\n public isScrollableHeader(item: any, items: any, index: number): boolean {\r\n if (index !== 0 || this.dimension.getFractionScrollOffset() === 0) {\r\n return false;\r\n }\r\n\r\n let hierarchyNavigator: ITablixHierarchyNavigator = this.dimension._hierarchyNavigator;\r\n\r\n if (hierarchyNavigator.isLeaf(item)) {\r\n return true;\r\n }\r\n\r\n let currentItem: any = item;\r\n let currentItems: any[] = items;\r\n\r\n do {\r\n currentItems = hierarchyNavigator.getChildren(currentItem);\r\n currentItem = this.dimension.getFirstVisibleItem(hierarchyNavigator.getLevel(currentItem) + 1);\r\n\r\n if (currentItem === undefined) {\r\n break;\r\n }\r\n\r\n if (!hierarchyNavigator.isLastItem(currentItem, currentItems)) {\r\n return false;\r\n }\r\n\r\n } while (!hierarchyNavigator.isLeaf(currentItem));\r\n\r\n return true;\r\n }\r\n\r\n public reachedEnd(): boolean {\r\n return this.dimension.getIntegerScrollOffset() + (this.getRealizedItemsCount() - this._gridOffset) >= this.dimension.getItemsCount();\r\n }\r\n\r\n public scrollBackwardToFill(gridContextualWidth: number): number {\r\n let newScrollOffset = this.dimension.scrollOffset;\r\n if (this.reachedEnd()) {\r\n let widthToFill = this._contextualWidthToFill - gridContextualWidth;\r\n if (this.dimension.getItemsCount() > 0) {\r\n let averageColumnwidth = gridContextualWidth / (this.getRealizedItemsCount() - this.dimension.getFractionScrollOffset());\r\n newScrollOffset = this.dimension.getValidScrollOffset(Math.floor(this.dimension.scrollOffset - (widthToFill / averageColumnwidth)));\r\n }\r\n this._alignToEnd = !Double.equalWithPrecision(newScrollOffset, this.dimension.scrollOffset, DimensionLayoutManager._scrollOffsetPrecision); // this is an aproximate scrolling back, we have to ensure it is aligned to the end of the control\r\n }\r\n return newScrollOffset;\r\n }\r\n\r\n private getItemContextualWidth(index: number): number {\r\n let realizedItems = this._getRealizedItems();\r\n if (index >= realizedItems.length)\r\n return null;\r\n\r\n return realizedItems[index].getContextualWidth();\r\n }\r\n\r\n private getItemContextualWidthWithScrolling(index: number): number {\r\n return this.getSizeWithScrolling(this.getItemContextualWidth(index), index);\r\n }\r\n\r\n public getSizeWithScrolling(size: number, index: number): number {\r\n let ratio;\r\n\r\n if (this._gridOffset === index) {\r\n ratio = this.getVisibleSizeRatio();\r\n }\r\n else {\r\n ratio = 1;\r\n }\r\n\r\n return size * ratio;\r\n }\r\n\r\n public getGridContextualWidthFromItems(): number {\r\n let count = this.getRealizedItemsCount();\r\n let contextualWidth = 0;\r\n for (let i = 0; i < count; i++) {\r\n contextualWidth += this.getItemContextualWidthWithScrolling(i);\r\n }\r\n return contextualWidth;\r\n }\r\n\r\n private getMeaurementError(gridContextualWidth: number): number {\r\n return gridContextualWidth / this.getGridContextualWidthFromItems();\r\n }\r\n\r\n private scrollForwardToAlignEnd(gridContextualWidth: number): number {\r\n let newScrollOffset = this.dimension.scrollOffset;\r\n if (this._alignToEnd) {\r\n let withinThreshold = Double.equalWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\r\n if (!withinThreshold) { // if it is within the threshold we consider it aligned, skip aliging algorithm\r\n let count: number = this.getRealizedItemsCount();\r\n let startIndex = this._gridOffset;\r\n let widthToScroll = gridContextualWidth - this._contextualWidthToFill;\r\n\r\n let error = this.getMeaurementError(gridContextualWidth);\r\n\r\n for (let i = startIndex; i < count; i++) {\r\n let itemContextualWidth = this.getItemContextualWidth(i) * error;\r\n if (Double.lessWithPrecision(itemContextualWidth, widthToScroll, DimensionLayoutManager._pixelPrecision)) {\r\n widthToScroll -= itemContextualWidth;\r\n }\r\n else {\r\n let visibleRatio = startIndex === i ? 1 - this.dimension.getFractionScrollOffset() : 1;\r\n newScrollOffset = this.dimension.getValidScrollOffset(this.dimension.scrollOffset + (i - startIndex) + (widthToScroll * visibleRatio / itemContextualWidth));\r\n break;\r\n }\r\n }\r\n }\r\n this._alignToEnd = !withinThreshold;\r\n }\r\n return newScrollOffset;\r\n }\r\n\r\n public get dimension(): TablixDimension {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.dimension\");\r\n return null;\r\n }\r\n\r\n public get otherLayoutManager(): DimensionLayoutManager {\r\n return <DimensionLayoutManager>this.dimension.otherDimension.layoutManager;\r\n }\r\n\r\n public get contextualWidthToFill(): number {\r\n return this._contextualWidthToFill;\r\n }\r\n\r\n public getGridScale(): number {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.getGridScale\");\r\n return 0;\r\n }\r\n\r\n public get otherScrollbarContextualWidth(): number {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.otherScrollbarContextualWidth\");\r\n return 0;\r\n }\r\n\r\n public getActualContextualWidth(gridContextualWidth: number): number {\r\n if (this._isAutoSized() && !this.canScroll(gridContextualWidth))\r\n return gridContextualWidth;\r\n\r\n return this._contextualWidthToFill;\r\n }\r\n\r\n protected canScroll(gridContextualWidth: number): boolean {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager.canScroll\");\r\n return false;\r\n }\r\n\r\n public calculateSizes(): void {\r\n if (this.fixedSizeEnabled) {\r\n this.calculateContextualWidths();\r\n this.calculateSpans();\r\n }\r\n }\r\n\r\n protected _calculateSize(item: ITablixGridItem): number {\r\n debug.assertFail(\"PureVirtualMethod: DimensionLayoutManager._calculateSize\");\r\n return null;\r\n }\r\n\r\n public calculateContextualWidths(): void {\r\n let items: ITablixGridItem[] = this._getRealizedItems();\r\n let count = items.length;\r\n\r\n for (let i = 0; i < count; i++) {\r\n let item: ITablixGridItem = items[i];\r\n\r\n if (this.measureEnabled)\r\n item.setAligningContextualWidth(-1);\r\n\r\n this._calculateSize(item);\r\n }\r\n }\r\n\r\n public calculateSpans(): void {\r\n if (this.measureEnabled) {\r\n this.updateNonScrollableItemsSpans();\r\n this.updateScrollableItemsSpans();\r\n }\r\n\r\n // TODO override in row layout manager to add footer to calculation, this is required for Matrix\r\n }\r\n\r\n public updateNonScrollableItemsSpans(): void {\r\n let otherDimensionItems = this.otherLayoutManager._getRealizedItems();\r\n let otherDimensionItemsCount = otherDimensionItems.length;\r\n let startIndex = this.dimension.getDepth();\r\n for (let i = startIndex; i < otherDimensionItemsCount; i++) {\r\n let otherDimensionItem = otherDimensionItems[i];\r\n this.updateSpans(otherDimensionItem, otherDimensionItem.getHeaders());\r\n }\r\n }\r\n\r\n public updateScrollableItemsSpans(): void {\r\n let otherRealizedItems = this.otherLayoutManager._getRealizedItems();\r\n let otherRealizedItemsCount = Math.min(this.dimension.getDepth(), otherRealizedItems.length);\r\n for (let i = 0; i < otherRealizedItemsCount; i++) {\r\n let otherRealizedItem = otherRealizedItems[i];\r\n this.updateSpans(otherRealizedItem, otherRealizedItem.getOtherDimensionHeaders());\r\n }\r\n }\r\n\r\n public fixSizes(): void {\r\n if (this.fixedSizeEnabled) {\r\n let items: ITablixGridItem[] = this._getRealizedItems();\r\n let count = items.length;\r\n for (let i = count - 1; i >= 0; i--) {\r\n items[i].fixSize();\r\n }\r\n }\r\n }\r\n\r\n private updateSpans(otherRealizedItem: ITablixGridItem, cells: TablixCell[]): void {\r\n let realizedItems = this._getRealizedItems();\r\n let cellCount = cells.length;\r\n for (let j = 0; j < cellCount; j++) {\r\n let cell = cells[j];\r\n let owner = otherRealizedItem.getOtherDimensionOwner(cell);\r\n let span = owner.getCellContextualSpan(cell);\r\n if (span > 1) {\r\n let totalSizeInSpan = 0;\r\n let startIndex = owner.getIndex(this._grid);\r\n for (let k = 0; k < span; k++) {\r\n let item = realizedItems[k + startIndex];\r\n totalSizeInSpan += item.getContentContextualWidth();\r\n if (k === span - 1)\r\n this.updateLastChildSize(cell, item, totalSizeInSpan);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private updateLastChildSize(spanningCell: TablixCell, item: ITablixGridItem, totalSpanSize: number): void {\r\n let delta = item.getCellIContentContextualWidth(spanningCell) - totalSpanSize;\r\n if (delta > 0) // the parent width is wider than the sum of the children, stretch the last child to compensate the difference\r\n item.setAligningContextualWidth(Math.max(item.getAligningContextualWidth(), delta + item.getContentContextualWidth()));\r\n }\r\n }\r\n\r\n export class ResizeState {\r\n public item: any;\r\n public itemType: TablixCellType;\r\n public column: TablixColumn;\r\n public startColumnWidth: number;\r\n public resizingDelta: number;\r\n public animationFrame: number;\r\n public scale: number;\r\n\r\n constructor(column: TablixColumn, width: number, scale: number) {\r\n this.column = column;\r\n this.item = column.getLeafItem();\r\n this.itemType = column.itemType;\r\n this.startColumnWidth = width;\r\n this.resizingDelta = 0;\r\n this.animationFrame = null;\r\n this.scale = scale;\r\n }\r\n\r\n public getNewSize(): number {\r\n return this.startColumnWidth + this.resizingDelta;\r\n }\r\n }\r\n\r\n export class ColumnLayoutManager extends DimensionLayoutManager implements ITablixResizeHandler {\r\n static minColumnWidth = 10;\r\n private _resizeState: ResizeState;\r\n\r\n constructor(owner: TablixLayoutManager, grid: TablixGrid, realizationManager: ColumnRealizationManager) {\r\n super(owner, grid, realizationManager);\r\n\r\n realizationManager.owner = this;\r\n\r\n this.fillProportionally = false;\r\n this._resizeState = null;\r\n }\r\n\r\n public get dimension(): TablixDimension {\r\n return this.owner.owner.columnDimension;\r\n }\r\n\r\n public isResizing(): boolean {\r\n return this._resizeState !== null;\r\n }\r\n\r\n public set fillProportionally(value: boolean) {\r\n this._grid.fillColumnsProportionally = value;\r\n }\r\n\r\n public get fillProportionally(): boolean {\r\n return this._grid.fillColumnsProportionally;\r\n }\r\n\r\n public getGridScale(): number {\r\n return this._grid._presenter.getScreenToCssRatioX();\r\n }\r\n\r\n public get otherScrollbarContextualWidth(): number {\r\n if (this.dimension.otherDimension.scrollbar.visible) {\r\n return HTMLElementUtils.getElementWidth(this.dimension.otherDimension.scrollbar.element);\r\n }\r\n return 0;\r\n }\r\n\r\n public _getRealizedItems(): ITablixGridItem[] {\r\n if (!this._grid.realizedColumns) {\r\n this._grid.realizedColumns = [];\r\n }\r\n\r\n return this._grid.realizedColumns;\r\n }\r\n\r\n public _moveElementsToBottom(moveFromIndex: number, count): void {\r\n this._grid.moveColumnsToEnd(moveFromIndex, count);\r\n }\r\n\r\n public _moveElementsToTop(moveToIndex: number, count): void {\r\n this._grid.moveColumnsToStart(moveToIndex, count);\r\n }\r\n\r\n public _requiresMeasure(): boolean {\r\n // if the control is not scrolling in either dimension or is scrolling or is resizing\r\n return (!this.isScrolling() && !this.otherLayoutManager.isScrolling()) || this.isScrolling() || this.isResizing();\r\n }\r\n\r\n public getGridContextualWidth(): number {\r\n return this._grid.getWidth();\r\n }\r\n\r\n private getFirstVisibleColumn(): TablixColumn {\r\n return this._grid.realizedColumns[this._gridOffset];\r\n }\r\n\r\n public _isAutoSized(): boolean {\r\n return this.owner.owner.autoSizeWidth;\r\n }\r\n\r\n public applyScrolling() {\r\n let columnOffset: number = this.dimension.getFractionScrollOffset();\r\n let firstVisibleColumnWidth: number = 0;\r\n\r\n if (columnOffset !== 0) {\r\n let firstVisibleColumn: TablixColumn = this.getFirstVisibleColumn();\r\n if (firstVisibleColumn !== undefined) {\r\n firstVisibleColumnWidth = firstVisibleColumn.getContextualWidth();\r\n this.scroll(firstVisibleColumn, firstVisibleColumnWidth, columnOffset);\r\n }\r\n }\r\n }\r\n\r\n private scroll(firstVisibleColumn: TablixColumn, width: number, offset: number) {\r\n this.scrollCells(firstVisibleColumn._realizedColumnHeaders, width, offset);\r\n this.scrollBodyCells(this._grid.realizedRows, width, offset);\r\n\r\n if (firstVisibleColumn.footer !== null) {\r\n firstVisibleColumn.footer.scrollHorizontally(width, offset);\r\n }\r\n }\r\n\r\n private scrollCells(cells: TablixCell[], width: number, offset: number): void {\r\n let length: number = cells.length;\r\n for (let i = 0; i < length; i++) {\r\n cells[i].scrollHorizontally(width, offset);\r\n }\r\n }\r\n\r\n private scrollBodyCells(rows: TablixRow[], width: number, offset: number): void {\r\n let length: number = rows.length;\r\n let cells: TablixCell[];\r\n let cell: TablixCell;\r\n for (let i = 0; i < length; i++) {\r\n cells = rows[i]._realizedBodyCells;\r\n if (cells !== undefined) {\r\n cell = cells[0];\r\n if (cell !== undefined) {\r\n cell.scrollHorizontally(width, offset);\r\n }\r\n }\r\n }\r\n }\r\n\r\n public onStartResize(cell: TablixCell, currentX: number, currentY: number): void {\r\n this._resizeState = new ResizeState(cell._column, cell._column.getContentContextualWidth(), HTMLElementUtils.getAccumulatedScale(this.owner.owner.container));\r\n }\r\n\r\n public onResize(cell: TablixCell, deltaX: number, deltaY: number): void {\r\n if (this.isResizing()) {\r\n this._resizeState.resizingDelta = Math.round(Math.max(deltaX / this._resizeState.scale, ColumnLayoutManager.minColumnWidth - this._resizeState.startColumnWidth));\r\n if (this._resizeState.animationFrame === null)\r\n this._resizeState.animationFrame = requestAnimationFrame(() => this.performResizing());\r\n }\r\n }\r\n\r\n public onEndResize(cell: TablixCell): void {\r\n if (this.isResizing() && this._resizeState.animationFrame !== null) {\r\n this.performResizing(); // if we reached the end and we are still waiting for the last animation frame, perform the pending resizing and clear the state \r\n }\r\n\r\n this.endResizing();\r\n\r\n this._resizeState = null;\r\n }\r\n\r\n public onReset(cell: TablixCell) {\r\n this._resizeState = new ResizeState(cell._column, -1, 1);\r\n cell._column.clearSize();\r\n this.endResizing();\r\n this.owner.owner.refresh(false);\r\n this._resizeState = null;\r\n }\r\n\r\n public updateItemToResizeState(realizedColumns: TablixColumn[]): void {\r\n if (this._resizeState === null)\r\n return;\r\n\r\n let columnCount: number = realizedColumns.length;\r\n\r\n let hierarchyNavigator: ITablixHierarchyNavigator = this.owner.owner.hierarchyNavigator;\r\n\r\n // Only iterate over the columns that belong to column hierachy (i.e. skip the row hierarchy rows)\r\n // as this post-rendering adjustment only applies to them.\r\n let startIndex = this.otherLayoutManager.dimension.getDepth();\r\n for (let i = startIndex; i < columnCount; i++) {\r\n let column: TablixColumn = realizedColumns[i];\r\n\r\n if (!column.columnHeaderOrCornerEquals(this._resizeState.itemType, this._resizeState.item, column.itemType, column.getLeafItem(), hierarchyNavigator))\r\n continue;\r\n\r\n if (column !== this._resizeState.column) { // we moved the item of the column that is being resized to another one \r\n this._resizeState.column = column;\r\n column.onResize(this._resizeState.getNewSize());\r\n break;\r\n }\r\n }\r\n }\r\n\r\n private performResizing(): void {\r\n if (this._resizeState === null) // in case of FireFox we cannot cancel the animation frame request\r\n return;\r\n this._resizeState.animationFrame = null;\r\n let newSize = this._resizeState.getNewSize();\r\n this._resizeState.column.onResize(newSize);\r\n this.owner.owner.refresh(false);\r\n }\r\n\r\n private endResizing(): void {\r\n if (this._resizeState === null) // in case of FireFox we cannot cancel the animation frame request\r\n return;\r\n\r\n let newSize = this._resizeState.getNewSize();\r\n this._resizeState.column.onResizeEnd(newSize);\r\n }\r\n\r\n /**\r\n * Sends column related data (pixel size, column count, etc) to TablixControl.\r\n */\r\n public _sendDimensionsToControl(): void {\r\n let gridContextualWidth: number = this.getGridContextualWidth();\r\n let widthToFill: number = this.getActualContextualWidth(gridContextualWidth);\r\n let otherContextualHeight = this.getOtherHierarchyContextualHeight();\r\n let scale = this.getGridScale(); // in case of canvas we have to convert the size from device pixel to css pixel\r\n this.owner.owner.updateColumnDimensions(otherContextualHeight / scale,\r\n (widthToFill - otherContextualHeight) / scale,\r\n this.getViewSize(gridContextualWidth));\r\n }\r\n\r\n public getEstimatedHeaderWidth(label: string, headerIndex: number): number {\r\n debug.assertFail(\"PureVirtualMethod: ColumnLayoutManager.getEstimatedHeaderWidth\");\r\n return -1;\r\n }\r\n\r\n public getEstimatedBodyCellWidth(content: string): number {\r\n debug.assertFail(\"PureVirtualMethod: ColumnLayoutManager.getEstimatedBodyCellWidth\");\r\n return -1;\r\n }\r\n }\r\n\r\n export class DashboardColumnLayoutManager extends ColumnLayoutManager {\r\n public getEstimatedHeaderWidth(label: string, headerIndex: number): number {\r\n if (this.ignoreColumn(headerIndex))\r\n return 0;\r\n\r\n // for dashboard layout it does not matter whether we pass an actual cell or not\r\n return this.owner.getCellWidth(undefined);\r\n }\r\n\r\n public getEstimatedBodyCellWidth(content: string): number {\r\n // for dashboard layout it does not matter whether we pass an actual cell or not\r\n return this.owner.getCellWidth(undefined);\r\n }\r\n\r\n protected canScroll(gridContextualWidth: number): boolean {\r\n return false;\r\n }\r\n\r\n protected _calculateSize(item: ITablixGridItem): number {\r\n let headerIndex = item.getIndex(this._grid);\r\n let computedSize = 0;\r\n\r\n if (!this.ignoreColumn(headerIndex)) {\r\n // for dashboard layout it does not matter whether we pass an actual cell or not\r\n computedSize = this.owner.getContentWidth(undefined);\r\n }\r\n\r\n item.onResize(computedSize);\r\n item.onResizeEnd(computedSize);\r\n return computedSize;\r\n }\r\n\r\n private ignoreColumn(headerIndex: number): boolean {\r\n // On the dashboard, we need to return 0 if the row header is static\r\n // (a table or a matrix without row groups)\r\n return headerIndex === 0 && !this.owner.binder.hasRowGroups();\r\n }\r\n }\r\n\r\n export class CanvasColumnLayoutManager extends ColumnLayoutManager {\r\n public getEstimatedHeaderWidth(label: string, headerIndex: number): number {\r\n // On the canvas the header width depends on the size of the content\r\n return this.owner.getEstimatedTextWidth(label);\r\n }\r\n\r\n public getEstimatedBodyCellWidth(content: string): number {\r\n return this.owner.getEstimatedTextWidth(content);\r\n }\r\n\r\n public calculateContextualWidths(): void {\r\n let items: ITablixGridItem[] = this._getRealizedItems();\r\n let columnWidths: number[] = [];\r\n\r\n for (let item of items) {\r\n if (this.measureEnabled)\r\n item.setAligningContextualWidth(-1);\r\n\r\n columnWidths.push(this._calculateSize(item));\r\n }\r\n \r\n // Save all column widths. Needed when user turns off auto-sizing for column widths.\r\n this.owner.columnWidthsToPersist = columnWidths;\r\n }\r\n\r\n protected canScroll(gridContextualWidth: number): boolean {\r\n return !Double.equalWithPrecision(this.dimension.scrollOffset, 0, DimensionLayoutManager._scrollOffsetPrecision) ||\r\n (((this.getRealizedItemsCount() - this._gridOffset) < this.dimension.getItemsCount()) && this._contextualWidthToFill > 0) ||\r\n Double.greaterWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\r\n }\r\n\r\n protected _calculateSize(item: ITablixGridItem): number {\r\n return item.calculateSize();\r\n }\r\n }\r\n\r\n export class RowLayoutManager extends DimensionLayoutManager {\r\n constructor(owner: TablixLayoutManager, grid: TablixGrid, realizationManager: RowRealizationManager) {\r\n super(owner, grid, realizationManager);\r\n\r\n realizationManager.owner = this;\r\n }\r\n\r\n public get dimension(): TablixDimension {\r\n return this.owner.owner.rowDimension;\r\n }\r\n\r\n public getGridScale(): number {\r\n return this._grid._presenter.getScreenToCssRatioY();\r\n }\r\n\r\n public get otherScrollbarContextualWidth(): number {\r\n if (this.dimension.otherDimension.scrollbar.visible) {\r\n return HTMLElementUtils.getElementHeight(this.dimension.otherDimension.scrollbar.element);\r\n }\r\n return 0;\r\n }\r\n\r\n public startScrollingSession(): void {\r\n super.startScrollingSession();\r\n }\r\n\r\n public _getRealizedItems(): ITablixGridItem[] {\r\n if (!this._grid.realizedRows) {\r\n this._grid.realizedRows = [];\r\n }\r\n\r\n return this._grid.realizedRows;\r\n }\r\n\r\n public _moveElementsToBottom(moveFromIndex: number, count): void {\r\n this._grid.moveRowsToEnd(moveFromIndex, count);\r\n }\r\n\r\n public _moveElementsToTop(moveToIndex: number, count): void {\r\n this._grid.moveRowsToStart(moveToIndex, count);\r\n }\r\n\r\n public _requiresMeasure(): boolean {\r\n // if the control is not scrolling in either dimension and the column dimension is not resizing or row dimension is scrolling and reaching the end while scrolling \r\n return (!this.isScrolling() && !this.otherLayoutManager.isScrolling() && !this.otherLayoutManager.isResizing())\r\n || (this.isScrolling() && (this.dimension.getIntegerScrollOffset() + (this.getRealizedItemsCount() - this._gridOffset) >= this.dimension.getItemsCount()));\r\n }\r\n\r\n public getGridContextualWidth(): number {\r\n return this._grid.getHeight();\r\n }\r\n\r\n private getFirstVisibleRow(): TablixRow {\r\n return this._grid.realizedRows[this._gridOffset];\r\n }\r\n\r\n public _isAutoSized(): boolean {\r\n return this.owner.owner.autoSizeHeight;\r\n }\r\n\r\n public applyScrolling() {\r\n let rowOffset: number = this.dimension.getFractionScrollOffset();\r\n let firstVisibleRowHeight: number = 0;\r\n\r\n if (rowOffset !== 0) {\r\n let firstVisibleRow: TablixRow = this.getFirstVisibleRow();\r\n if (firstVisibleRow) {\r\n firstVisibleRowHeight = firstVisibleRow.getContextualWidth();\r\n this.scroll(firstVisibleRow, firstVisibleRowHeight, rowOffset);\r\n }\r\n }\r\n }\r\n\r\n private scroll(firstVisibleRow: TablixRow, height: number, offset: number) {\r\n this.scrollCells(firstVisibleRow._realizedRowHeaders, height, offset);\r\n this.scrollCells(firstVisibleRow._realizedBodyCells, height, offset);\r\n }\r\n\r\n private scrollCells(cells: TablixCell[], height: number, offset: number): void {\r\n let length: number = cells.length;\r\n for (let i = 0; i < length; i++) {\r\n cells[i].scrollVertically(height, offset);\r\n }\r\n }\r\n\r\n public getFooterContextualWidth(): number {\r\n if (this.owner.owner.rowDimension.hasFooter()) {\r\n if (this.owner.grid.footerRow) {\r\n return this.owner.grid.footerRow.getContextualWidth();\r\n }\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n public calculateContextualWidths(): void {\r\n super.calculateContextualWidths();\r\n if (this.fixedSizeEnabled) {\r\n let footerRow: TablixRow = this._grid.footerRow;\r\n if (footerRow) {\r\n this._calculateSize(footerRow);\r\n }\r\n }\r\n }\r\n\r\n public fixSizes(): void {\r\n super.fixSizes();\r\n if (this.fixedSizeEnabled) {\r\n if (this._grid.footerRow) {\r\n this._grid.footerRow.fixSize();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Sends row related data (pixel size, column count, etc) to TablixControl.\r\n */\r\n public _sendDimensionsToControl(): void {\r\n let gridContextualWidth: number = this.getGridContextualWidth();\r\n let widthToFill: number = this.getActualContextualWidth(gridContextualWidth);\r\n let otherContextualHeight = this.getOtherHierarchyContextualHeight();\r\n let scale = this.getGridScale();\r\n this.owner.owner.updateRowDimensions(otherContextualHeight / scale,\r\n (widthToFill - otherContextualHeight) / scale,\r\n gridContextualWidth / scale,\r\n this.getViewSize(gridContextualWidth),\r\n (this._grid.footerRow ? this._grid.footerRow.getContextualWidth() / scale : 0));\r\n }\r\n\r\n public getEstimatedHeaderWidth(label: string, headerIndex: number): number {\r\n debug.assertFail(\"PureVirtualMethod: RowLayoutManager.getEstimatedHeaderWidth\");\r\n return -1;\r\n }\r\n }\r\n\r\n export class DashboardRowLayoutManager extends RowLayoutManager {\r\n public getEstimatedHeaderWidth(label: string, headerIndex: number): number {\r\n return this.getHeaderWidth(headerIndex);\r\n }\r\n\r\n protected canScroll(gridContextualWidth: number): boolean {\r\n return false;\r\n }\r\n\r\n protected _calculateSize(item: ITablixGridItem): number {\r\n return item.calculateSize();\r\n }\r\n\r\n private getHeaderWidth(headerIndex: number): number {\r\n // On the dashboard, we need to return 0 if the row header is static\r\n // (a table or a matrix without row groups)\r\n if (headerIndex === 0 && !this.owner.binder.hasRowGroups())\r\n return 0;\r\n\r\n // for dashboard layout it does not matter whether we pass an actual text or not\r\n return this.owner.getEstimatedTextWidth(undefined);\r\n }\r\n }\r\n\r\n export class CanvasRowLayoutManager extends RowLayoutManager {\r\n public getEstimatedHeaderWidth(label: string, headerIndex: number): number {\r\n // On the canvas the header width depends on the size of the content\r\n return this.owner.getEstimatedTextWidth(label);\r\n }\r\n\r\n protected canScroll(gridContextualWidth: number): boolean {\r\n return !Double.equalWithPrecision(this.dimension.scrollOffset, 0, DimensionLayoutManager._scrollOffsetPrecision) ||\r\n (((this.getRealizedItemsCount() - this._gridOffset) < this.dimension.getItemsCount()) && this._contextualWidthToFill > 0) ||\r\n Double.greaterWithPrecision(gridContextualWidth, this._contextualWidthToFill, DimensionLayoutManager._pixelPrecision);\r\n }\r\n\r\n protected _calculateSize(item: ITablixGridItem): number {\r\n return item.calculateSize();\r\n }\r\n }\r\n\r\n export class TablixLayoutManager {\r\n protected _owner: TablixControl;\r\n protected _container: HTMLElement;\r\n protected _columnLayoutManager: ColumnLayoutManager;\r\n protected _rowLayoutManager: RowLayoutManager;\r\n private _binder: ITablixBinder;\r\n\r\n private _scrollingDimension: TablixDimension;\r\n private _gridHost: HTMLElement;\r\n private _footersHost: HTMLElement;\r\n private _grid: internal.TablixGrid;\r\n private _allowHeaderResize: boolean = true;\r\n private _columnWidthsToPersist: number[];\r\n\r\n constructor(\r\n binder: ITablixBinder,\r\n grid: TablixGrid,\r\n columnLayoutManager: ColumnLayoutManager,\r\n rowLayoutManager: RowLayoutManager) {\r\n this._binder = binder;\r\n this._grid = grid;\r\n this._columnLayoutManager = columnLayoutManager;\r\n this._rowLayoutManager = rowLayoutManager;\r\n this._columnWidthsToPersist = [];\r\n }\r\n\r\n public initialize(owner: TablixControl): void {\r\n this._owner = owner;\r\n this._container = owner.container;\r\n this._gridHost = owner.contentHost;\r\n this._footersHost = owner.footerHost;\r\n this._grid.initialize(owner, this._gridHost, this._footersHost);\r\n }\r\n\r\n public get owner(): TablixControl {\r\n return this._owner;\r\n }\r\n\r\n public get binder(): ITablixBinder {\r\n return this._binder;\r\n }\r\n\r\n public get columnWidthsToPersist(): number[] {\r\n return this._columnWidthsToPersist;\r\n }\r\n\r\n public set columnWidthsToPersist(columnWidths: number[]) {\r\n this._columnWidthsToPersist = columnWidths;\r\n }\r\n\r\n public getTablixClassName(): string {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getTablixClassName\");\r\n return null;\r\n }\r\n\r\n public getLayoutKind(): TablixLayoutKind {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getLayoutKind\");\r\n\r\n // TODO ckerer: this method should not be necessary when we are done refactoring!\r\n return null;\r\n }\r\n\r\n public getOrCreateColumnHeader(item: any, items: any, rowIndex: number, columnIndex: number): ITablixCell {\r\n let hierarchyNav = this.owner.hierarchyNavigator;\r\n let row: TablixRow = this._grid.getOrCreateRow(rowIndex);\r\n let column: TablixColumn = this._grid.getOrCreateColumn(columnIndex + this._columnLayoutManager._gridOffset);\r\n let isLeaf = hierarchyNav.isLeaf(item);\r\n let cell: TablixCell = row.getOrCreateColumnHeader(column, this._columnLayoutManager.isScrollableHeader(item, items, columnIndex), isLeaf);\r\n\r\n let rowIdx = hierarchyNav.getLevel(item);\r\n cell.position.row.index = cell.position.row.indexInSiblings = rowIdx;\r\n cell.position.row.isFirst = rowIdx === 0;\r\n cell.position.row.isLast = isLeaf;\r\n\r\n let colIdx = hierarchyNav.getIndex(item);\r\n cell.position.column.index = cell.position.row.indexInSiblings = colIdx;\r\n cell.position.column.isFirst = hierarchyNav.areAllParentsFirst(item, items);\r\n cell.position.column.isLast = hierarchyNav.areAllParentsLast(item, items);\r\n\r\n this.enableCellHorizontalResize(isLeaf, cell);\r\n return cell;\r\n }\r\n\r\n public getOrCreateRowHeader(item: any, items: any, rowIndex: number, columnIndex: number): ITablixCell {\r\n let hierarchyNav = this.owner.hierarchyNavigator;\r\n let row: TablixRow = this._grid.getOrCreateRow(rowIndex + this._rowLayoutManager._gridOffset);\r\n let column: TablixColumn = this._grid.getOrCreateColumn(columnIndex);\r\n let isLeaf = hierarchyNav.isLeaf(item);\r\n let scrollable: boolean = this._rowLayoutManager.isScrollableHeader(item, items, rowIndex);\r\n\r\n if (row.getRealizedCellCount() === 0) {\r\n this.alignRowHeaderCells(item, row);\r\n }\r\n\r\n let cell: TablixCell = row.getOrCreateRowHeader(column, scrollable, hierarchyNav.isLeaf(item));\r\n let rowIdx = hierarchyNav.getIndex(item);\r\n cell.position.row.index = cell.position.row.indexInSiblings = rowIdx;\r\n cell.position.row.isFirst = hierarchyNav.areAllParentsFirst(item, items);\r\n cell.position.row.isLast = hierarchyNav.areAllParentsLast(item, items);\r\n\r\n let colIdx = hierarchyNav.getLevel(item);\r\n cell.position.column.index = cell.position.column.indexInSiblings = colIdx;\r\n cell.position.column.isFirst = colIdx === 0;\r\n cell.position.column.isLast = isLeaf;\r\n\r\n cell.enableHorizontalResize(false, this._columnLayoutManager);\r\n return cell;\r\n }\r\n\r\n public getOrCreateCornerCell(item: any, rowLevel: number, columnLevel: number): ITablixCell {\r\n let row: TablixRow = this._grid.getOrCreateRow(columnLevel);\r\n let column: TablixColumn = this._grid.getOrCreateColumn(rowLevel);\r\n\r\n let columnDepth = this._columnLayoutManager.dimension.getDepth();\r\n let isLeaf = columnLevel === (columnDepth - 1);\r\n\r\n let cell: TablixCell = row.getOrCreateCornerCell(column);\r\n let rowIdx = columnLevel;\r\n cell.position.row.index = cell.position.row.indexInSiblings = rowIdx;\r\n cell.position.row.isFirst = rowIdx === 0;\r\n cell.position.row.isLast = isLeaf;\r\n\r\n let colIdx = rowLevel;\r\n cell.position.column.index = cell.position.column.indexInSiblings = colIdx;\r\n cell.position.column.isFirst = colIdx === 0;\r\n cell.position.column.isLast = colIdx === this._rowLayoutManager.dimension.getDepth() - 1;\r\n\r\n this.enableCellHorizontalResize(isLeaf, cell);\r\n return cell;\r\n }\r\n\r\n public getOrCreateBodyCell(cellItem: any, rowItem: any, rowItems: any, rowIndex: number, columnIndex: number): ITablixCell {\r\n let scrollable: boolean;\r\n let row: TablixRow = this._grid.getOrCreateRow(rowIndex + this._rowLayoutManager._gridOffset);\r\n let column: TablixColumn = this._grid.getOrCreateColumn(columnIndex + this._columnLayoutManager._gridOffset);\r\n\r\n if (row._realizedBodyCells.length === 0 && this._owner.columnDimension.getFractionScrollOffset() !== 0) {\r\n scrollable = true;\r\n }\r\n else {\r\n scrollable = this._rowLayoutManager.isScrollableHeader(rowItem, rowItems, rowIndex);\r\n }\r\n\r\n let cell: TablixCell = row.getOrCreateBodyCell(column, scrollable);\r\n cell.position = cellItem.position;\r\n cell.enableHorizontalResize(false, this._columnLayoutManager);\r\n return cell;\r\n }\r\n\r\n public getOrCreateFooterBodyCell(cellItem: any, columnIndex: number): ITablixCell {\r\n let scrollable: boolean;\r\n let row: TablixRow = this._grid.getOrCreateFootersRow();\r\n let column: TablixColumn = this._grid.getOrCreateColumn(columnIndex + this._columnLayoutManager._gridOffset);\r\n\r\n scrollable = (row._realizedBodyCells.length === 0 && this._owner.columnDimension.getFractionScrollOffset() !== 0);\r\n\r\n let cell: TablixCell = row.getOrCreateFooterBodyCell(column, scrollable);\r\n cell.position = cellItem.position;\r\n cell.enableHorizontalResize(false, this._columnLayoutManager);\r\n return cell;\r\n }\r\n\r\n public getOrCreateFooterRowHeader(item: any, items: any): ITablixCell {\r\n let row: TablixRow = this._grid.getOrCreateFootersRow();\r\n let column: TablixColumn = this._grid.getOrCreateColumn(0);\r\n\r\n //debug.assert(this.owner.hierarchyNavigator.isLeaf(item), \"Leaf item expected\");\r\n\r\n let cell: TablixCell = row.getOrCreateFooterRowHeader(column);\r\n cell.position = undefined;\r\n cell.enableHorizontalResize(false, this._columnLayoutManager);\r\n return cell;\r\n }\r\n\r\n public getVisibleWidth(): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getVisibleWidth\");\r\n return -1;\r\n }\r\n\r\n public getVisibleHeight(): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getVisibleHeight\");\r\n return -1;\r\n }\r\n\r\n public updateColumnCount(rowDimension: TablixRowDimension, columnDimension: TablixColumnDimension) {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.updateColumnCount\");\r\n }\r\n\r\n public updateViewport(viewport: IViewport) {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.updateViewport\");\r\n }\r\n\r\n public getEstimatedRowHeight(): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getEstimatedRowHeight\");\r\n return -1;\r\n }\r\n\r\n public getCellWidth(cell: ITablixCell): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getCellWidth\");\r\n return -1;\r\n }\r\n\r\n public getContentWidth(cell: ITablixCell): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getContentWidth\");\r\n return -1;\r\n }\r\n\r\n public adjustContentSize(hasImage: boolean): void {\r\n // default implementation has no adjustment\r\n }\r\n\r\n /**\r\n * This call makes room for parent header cells where neccessary.\r\n * Since HTML cells that span vertically displace other rows,\r\n * room has to be made for spanning headers that leave an exiting \r\n * row to enter the new row that it starts from and removed when\r\n * returning to an entering row.\r\n */\r\n private alignRowHeaderCells(item: any, currentRow: TablixRow): void {\r\n let index = currentRow.getRowHeaderLeafIndex();\r\n\r\n if (index === -1) {\r\n return;\r\n }\r\n\r\n let rowDimension: TablixRowDimension = this._owner.rowDimension;\r\n let leaf = rowDimension.getFirstVisibleChildLeaf(item);\r\n\r\n if (!this.owner.hierarchyNavigator.headerItemEquals(leaf, currentRow.getAllocatedCellAt(index).item)) {\r\n return;\r\n }\r\n\r\n currentRow.moveCellsBy(this.owner.hierarchyNavigator.getLevel(leaf) - this.owner.hierarchyNavigator.getLevel(item) - index);\r\n }\r\n\r\n public get grid(): TablixGrid {\r\n return this._grid;\r\n }\r\n\r\n public get rowLayoutManager(): DimensionLayoutManager {\r\n return this._rowLayoutManager;\r\n }\r\n\r\n public get columnLayoutManager(): DimensionLayoutManager {\r\n return this._columnLayoutManager;\r\n }\r\n\r\n protected showEmptySpaceHeader(): boolean {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.showEmptySpaceHeader\");\r\n return false;\r\n }\r\n\r\n public onStartRenderingSession(scrollingDimension: TablixDimension, parentElement: HTMLElement, clear: boolean): void {\r\n if (this.showEmptySpaceHeader()) {\r\n let cell: ITablixCell = this._grid.emptySpaceHeaderCell;\r\n if (cell) {\r\n this._binder.unbindEmptySpaceHeaderCell(cell);\r\n }\r\n\r\n cell = this._grid.emptySpaceFooterCell;\r\n if (cell) {\r\n this._binder.unbindEmptySpaceFooterCell(cell);\r\n }\r\n\r\n this._grid.HideEmptySpaceCells();\r\n }\r\n\r\n this._scrollingDimension = scrollingDimension;\r\n\r\n if (this._scrollingDimension) {\r\n (<DimensionLayoutManager>this._scrollingDimension.layoutManager).startScrollingSession();\r\n }\r\n\r\n this._rowLayoutManager.onStartRenderingSession();\r\n this._columnLayoutManager.onStartRenderingSession();\r\n this._grid.onStartRenderingSession(clear);\r\n\r\n let measureEnabled = this._columnLayoutManager.measureEnabled || this._rowLayoutManager.measureEnabled;\r\n if (measureEnabled)\r\n this.measureSampleText(parentElement);\r\n }\r\n\r\n public onEndRenderingSession(): void {\r\n this._rowLayoutManager.onEndRenderingSession();\r\n this._columnLayoutManager.onEndRenderingSession();\r\n\r\n if (this._scrollingDimension) {\r\n (<DimensionLayoutManager>this._scrollingDimension.layoutManager).endScrollingSession();\r\n }\r\n\r\n this._scrollingDimension = null;\r\n\r\n if (this.showEmptySpaceHeader()) {\r\n let emptySpace = this._columnLayoutManager.contextualWidthToFill - this._columnLayoutManager.getGridContextualWidth();\r\n if (emptySpace > 0) {\r\n this._grid.ShowEmptySpaceCells(this._owner.columnDimension.getDepth(), emptySpace);\r\n\r\n let cell: ITablixCell = this._grid.emptySpaceHeaderCell;\r\n if (cell) {\r\n this._binder.bindEmptySpaceHeaderCell(cell);\r\n }\r\n cell = this._grid.emptySpaceFooterCell;\r\n if (cell) {\r\n this._binder.bindEmptySpaceFooterCell(cell);\r\n }\r\n }\r\n }\r\n }\r\n\r\n public onStartRenderingIteration(clear: boolean): void {\r\n this._rowLayoutManager.onStartRenderingIteration(clear, this.getVisibleHeight());\r\n this._columnLayoutManager.onStartRenderingIteration(clear, this.getVisibleWidth());\r\n this._grid.onStartRenderingIteration();\r\n }\r\n\r\n public onEndRenderingIteration(): boolean {\r\n this._grid.onEndRenderingIteration();\r\n\r\n // ANDREMI: Comment out for static tablix\r\n this._columnLayoutManager.calculateSizes(); // calculate the entire grid first without altering the tree to avoid multiple measure pass invoking\r\n this._rowLayoutManager.calculateSizes();\r\n this._columnLayoutManager.fixSizes(); // now assign the sizes\r\n this._rowLayoutManager.fixSizes();\r\n\r\n this._columnLayoutManager.updateItemToResizeState(this._grid.realizedColumns); // if we are in a middle of a resize, the column to resize might have been swaped during the render, restore its resize state\r\n\r\n this._columnLayoutManager.applyScrolling();\r\n this._rowLayoutManager.applyScrolling();\r\n this._columnLayoutManager.onEndRenderingIteration();\r\n this._rowLayoutManager.onEndRenderingIteration();\r\n\r\n return this._columnLayoutManager.done && this._rowLayoutManager.done;\r\n }\r\n\r\n public onCornerCellRealized(item: any, cell: ITablixCell): void {\r\n let columnLeaf: boolean = this.owner.hierarchyNavigator.isColumnHierarchyLeaf(item);\r\n let rowLeaf: boolean = this.owner.hierarchyNavigator.isRowHierarchyLeaf(item);\r\n if (columnLeaf)\r\n (<TablixCell>cell)._column.OnLeafRealized(this._owner.hierarchyNavigator);\r\n this._columnLayoutManager.onCornerCellRealized(item, cell, columnLeaf);\r\n this._rowLayoutManager.onCornerCellRealized(item, cell, rowLeaf);\r\n }\r\n\r\n public onRowHeaderRealized(item: any, cell: ITablixCell): void {\r\n let hierarchyNavigator: ITablixHierarchyNavigator = this._owner.hierarchyNavigator;\r\n let leaf = hierarchyNavigator.isLeaf(item);\r\n let tablixCell = (<TablixCell>cell);\r\n if (tablixCell.colSpan > 1)\r\n tablixCell.setContainerWidth(-1);\r\n this._rowLayoutManager.onHeaderRealized(item, cell, leaf);\r\n }\r\n\r\n public onRowHeaderFooterRealized(item: any, cell: ITablixCell): void {\r\n }\r\n\r\n public onColumnHeaderRealized(item: any, cell: ITablixCell): void {\r\n let hierarchyNavigator: ITablixHierarchyNavigator = this._owner.hierarchyNavigator;\r\n let leaf = hierarchyNavigator.isLeaf(item);\r\n if (leaf)\r\n (<TablixCell>cell)._column.OnLeafRealized(this._owner.hierarchyNavigator);\r\n this._columnLayoutManager.onHeaderRealized(item, cell, leaf);\r\n }\r\n\r\n public onBodyCellRealized(item: any, cell: ITablixCell): void {\r\n }\r\n\r\n public onBodyCellFooterRealized(item: any, cell: ITablixCell): void {\r\n }\r\n\r\n public setAllowHeaderResize(value: boolean) {\r\n this._allowHeaderResize = value;\r\n }\r\n\r\n public enableCellHorizontalResize(isLeaf: boolean, cell: TablixCell) {\r\n let enableCellHorizontalResize = isLeaf && this._allowHeaderResize;\r\n cell.enableHorizontalResize(enableCellHorizontalResize, this._columnLayoutManager);\r\n }\r\n\r\n public getEstimatedTextWidth(label: string): number {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.getEstimatedTextWidth\");\r\n return -1;\r\n }\r\n\r\n public measureSampleText(parentElement: HTMLElement): void {\r\n debug.assertFail(\"PureVirtualMethod: TablixLayoutManager.measureSampleText\");\r\n }\r\n }\r\n\r\n export class DashboardTablixLayoutManager extends TablixLayoutManager {\r\n private _characterHeight: number;\r\n private _sizeComputationManager: SizeComputationManager;\r\n\r\n constructor(\r\n binder: ITablixBinder,\r\n sizeComputationManager: SizeComputationManager,\r\n grid: TablixGrid,\r\n rowRealizationManager: RowRealizationManager,\r\n columnRealizationManager: ColumnRealizationManager) {\r\n\r\n let dashboardColumnLayoutManager = new DashboardColumnLayoutManager(null, grid, columnRealizationManager);\r\n let dashboardRowLayoutManager = new DashboardRowLayoutManager(null, grid, rowRealizationManager);\r\n\r\n super(binder, grid, dashboardColumnLayoutManager, dashboardRowLayoutManager);\r\n\r\n dashboardColumnLayoutManager.owner = this;\r\n dashboardRowLayoutManager.owner = this;\r\n\r\n this._sizeComputationManager = sizeComputationManager;\r\n }\r\n\r\n public static createLayoutManager(binder: ITablixBinder): DashboardTablixLayoutManager {\r\n // computed sizes are shared between layout manager and grid presenter\r\n let sizeComputationManager = new SizeComputationManager();\r\n return new DashboardTablixLayoutManager(\r\n binder,\r\n sizeComputationManager,\r\n new TablixGrid(new DashboardTablixGridPresenter(sizeComputationManager)),\r\n new RowRealizationManager(binder),\r\n new ColumnRealizationManager(binder));\r\n }\r\n\r\n public getTablixClassName(): string {\r\n return \"tablixDashboard\";\r\n }\r\n\r\n public getLayoutKind(): TablixLayoutKind {\r\n return TablixLayoutKind.DashboardTile;\r\n }\r\n\r\n protected showEmptySpaceHeader(): boolean {\r\n return false;\r\n }\r\n\r\n public measureSampleText(parentElement: HTMLElement): void {\r\n let textProperties = TextMeasurementService.getSvgMeasurementProperties(<any>parentElement);\r\n this._characterHeight = TextMeasurementService.estimateSvgTextHeight(textProperties);\r\n\r\n this._sizeComputationManager.updateRowHeight(this._characterHeight);\r\n\r\n let actualTextSize = PixelConverter.toPoint(parseFloat(textProperties.fontSize));\r\n let scalingFactor = actualTextSize / controls.TablixDefaultTextSize;\r\n\r\n this._sizeComputationManager.updateScalingFactor(Double.toIncrement(scalingFactor, 0.05));\r\n }\r\n\r\n public getVisibleWidth(): number {\r\n return this._sizeComputationManager.visibleWidth;\r\n }\r\n\r\n public getVisibleHeight(): number {\r\n return this._sizeComputationManager.visibleHeight;\r\n }\r\n\r\n public getCellWidth(cell: ITablixCell): number {\r\n return this._sizeComputationManager.cellWidth;\r\n }\r\n\r\n public getContentWidth(cell: ITablixCell): number {\r\n return this._sizeComputationManager.contentWidth;\r\n }\r\n\r\n public getEstimatedTextWidth(label: string): number {\r\n // On the dashboard it does not matter what text we render, \r\n // we always use the same content width\r\n return this._sizeComputationManager.contentWidth;\r\n }\r\n\r\n public adjustContentSize(hasImage: boolean): void {\r\n this._sizeComputationManager.hasImageContent = hasImage;\r\n }\r\n\r\n public updateColumnCount(rowDimension: TablixRowDimension, columnDimension: TablixColumnDimension): void {\r\n // The total number of columns is the number (depth) of row groups + the number of (leaf) column group instances\r\n let rowDimensionDepth = rowDimension ? rowDimension.getDepth() : 0;\r\n let columnInstances = columnDimension ? columnDimension.getItemsCount() : 0;\r\n let totalColumnCount = rowDimensionDepth + columnInstances;\r\n\r\n // Adjust the column count by the static row header (if any)\r\n if (!this.binder.hasRowGroups())\r\n totalColumnCount--;\r\n\r\n this._sizeComputationManager.updateColumnCount(totalColumnCount);\r\n }\r\n\r\n public updateViewport(viewport: IViewport) {\r\n this._sizeComputationManager.updateViewport(viewport);\r\n }\r\n\r\n public getEstimatedRowHeight(): number {\r\n return this._characterHeight;\r\n }\r\n }\r\n\r\n export class CanvasTablixLayoutManager extends TablixLayoutManager {\r\n private characterWidth: number;\r\n private characterHeight: number;\r\n\r\n constructor(\r\n binder: ITablixBinder,\r\n grid: TablixGrid,\r\n rowRealizationManager: RowRealizationManager,\r\n columnRealizationManager: ColumnRealizationManager) {\r\n\r\n let canvasColumnLayoutManager = new CanvasColumnLayoutManager(null, grid, columnRealizationManager);\r\n let canvasRowLayoutManager = new CanvasRowLayoutManager(null, grid, rowRealizationManager);\r\n\r\n super(binder, grid, canvasColumnLayoutManager, canvasRowLayoutManager);\r\n\r\n canvasColumnLayoutManager.owner = this;\r\n canvasRowLayoutManager.owner = this;\r\n }\r\n\r\n public static createLayoutManager(binder: ITablixBinder, columnWidthManager: TablixColumnWidthManager): CanvasTablixLayoutManager {\r\n return new CanvasTablixLayoutManager(\r\n binder,\r\n new TablixGrid(new controls.internal.CanvasTablixGridPresenter(columnWidthManager)),\r\n new RowRealizationManager(binder),\r\n new ColumnRealizationManager(binder));\r\n }\r\n\r\n public getTablixClassName(): string {\r\n return \"tablixCanvas\";\r\n }\r\n\r\n public getLayoutKind(): TablixLayoutKind {\r\n return TablixLayoutKind.Canvas;\r\n }\r\n\r\n public measureSampleText(parentElement: HTMLElement): void {\r\n // TODO: Use TextMeasurementService once the DOM methods are fixed (they are not working right now)\r\n let textDiv = controls.internal.TablixUtils.createDiv();\r\n textDiv.style.cssFloat = 'left';\r\n textDiv.style.whiteSpace = 'nowrap';\r\n textDiv.style.overflow = 'hidden';\r\n textDiv.style.lineHeight = 'normal';\r\n parentElement.appendChild(textDiv);\r\n\r\n let textNode = document.createTextNode(\"a\");\r\n textDiv.appendChild(textNode);\r\n\r\n this.characterWidth = controls.HTMLElementUtils.getElementWidth(textDiv);\r\n this.characterHeight = controls.HTMLElementUtils.getElementHeight(textDiv);\r\n\r\n textDiv.removeChild(textNode);\r\n parentElement.removeChild(textDiv);\r\n }\r\n\r\n protected showEmptySpaceHeader(): boolean {\r\n return !this._columnLayoutManager.fillProportionally;\r\n }\r\n\r\n public getVisibleWidth(): number {\r\n if (this._columnLayoutManager.measureEnabled) {\r\n if (this._owner.autoSizeWidth && this._owner.maxWidth) {\r\n return this._owner.maxWidth;\r\n } else {\r\n return HTMLElementUtils.getElementWidth(this._container);\r\n }\r\n }\r\n\r\n return -1;\r\n }\r\n\r\n public getVisibleHeight(): number {\r\n if (this._rowLayoutManager.measureEnabled) {\r\n if (this._owner.autoSizeHeight && this._owner.maxHeight) {\r\n return this._owner.maxHeight;\r\n } else {\r\n return HTMLElementUtils.getElementHeight(this._container);\r\n }\r\n }\r\n\r\n return -1;\r\n }\r\n\r\n public getCellWidth(cell: ITablixCell): number {\r\n return HTMLElementUtils.getElementWidth((<TablixCell>cell)._presenter.tableCell);\r\n }\r\n\r\n public getContentWidth(cell: ITablixCell): number {\r\n return HTMLElementUtils.getElementWidth((<TablixCell>cell)._presenter.contentElement);\r\n }\r\n\r\n public getEstimatedTextWidth(text: string): number {\r\n return text ? text.length * this.characterWidth : 0;\r\n }\r\n\r\n public updateColumnCount(rowDimension: TablixRowDimension, columnDimension: TablixColumnDimension) {\r\n // We currently only need to update model information when using dashboard layouts\r\n }\r\n\r\n public updateViewport(viewport: IViewport) {\r\n // We currently only need to update model information when using dashboard layouts\r\n }\r\n\r\n public getEstimatedRowHeight(): number {\r\n return this.characterHeight;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls {\r\n export module HTMLElementUtils {\r\n export function clearChildren(element: HTMLElement): void {\r\n if (!element) {\r\n return;\r\n }\r\n\r\n while (element.hasChildNodes()) {\r\n element.removeChild(element.firstChild);\r\n }\r\n }\r\n\r\n export function setElementTop(element: HTMLElement, top: number): void {\r\n element.style.top = top + \"px\";\r\n }\r\n\r\n export function setElementLeft(element: HTMLElement, left: number): void {\r\n element.style.left = left + \"px\";\r\n }\r\n\r\n export function setElementHeight(element: HTMLElement, height: number): void {\r\n if (HTMLElementUtils.isAutoSize(height))\r\n element.style.height = \"\";\r\n else\r\n element.style.height = height + \"px\";\r\n }\r\n\r\n export function setElementWidth(element: HTMLElement, width: number): void {\r\n if (HTMLElementUtils.isAutoSize(width))\r\n element.style.width = \"\";\r\n else\r\n element.style.width = width + \"px\";\r\n }\r\n\r\n export function getElementWidth(element: HTMLElement): number {\r\n return element.offsetWidth;\r\n }\r\n\r\n export function getElementHeight(element: HTMLElement): number {\r\n return element.offsetHeight;\r\n }\r\n\r\n export function isAutoSize(size: number): boolean {\r\n return size === -1;\r\n }\r\n\r\n export function getAccumulatedScale(element: HTMLElement): number {\r\n let scale: number = 1;\r\n while (element) {\r\n scale *= HTMLElementUtils.getScale(element);\r\n element = element.parentElement;\r\n }\r\n\r\n return scale;\r\n }\r\n\r\n /**\r\n * Get scale of element, return 1 when not scaled.\r\n */\r\n export function getScale(element: any): number {\r\n element = $(element);\r\n\r\n let str = element.css('-webkit-transform') ||\r\n element.css('-moz-transform') ||\r\n element.css('-ms-transform') ||\r\n element.css('-o-transform') ||\r\n element.css('transform');\r\n\r\n return (str && (\r\n str.match(/\\d*\\.\\d*/) && Number(str.match(/\\d*\\.\\d*/)[0]) ||\r\n str.match(/\\d+/) && Number(str.match(/\\d+/)[0]))\r\n ) || 1;\r\n }\r\n }\r\n}\r\n\r\nmodule powerbi.visuals.controls.internal {\r\n import DomFactory = InJs.DomFactory;\r\n import DataViewObjectDefinitions = powerbi.data.DataViewObjectDefinitions;\r\n import DataViewRoleWildCard = data.DataViewRoleWildcard;\r\n\r\n export module TablixObjects {\r\n export const ObjectGeneral: string = \"general\";\r\n export const ObjectGrid: string = \"grid\";\r\n export const ObjectColumnHeaders: string = \"columnHeaders\";\r\n export const ObjectRowHeaders: string = \"rowHeaders\";\r\n export const ObjectValues: string = \"values\";\r\n export const ObjectTotal: string = \"total\";\r\n export const ObjectSubTotals: string = \"subTotals\";\r\n\r\n export interface ObjectValueGetterFunction {\r\n <T>(objects: DataViewObjects, propertyId: DataViewObjectPropertyIdentifier, defaultValue?: T): T;\r\n }\r\n\r\n /**\r\n * Represents a DataViewObjects property related to the Tablix\r\n */\r\n export class TablixProperty {\r\n public objectName: string;\r\n public propertyName: string;\r\n public defaultValue: any;\r\n private getterFuntion: ObjectValueGetterFunction;\r\n\r\n /**\r\n * Creates a new TablixProperty\r\n * @param {string} objectName Object Name\r\n * @param {string} propertyName Property Name\r\n * @param {any} defaultValue Default value of the Property\r\n * @param {ObjectValueGetterFunction} getterFuntion Function used to get the Property value from the Objects\r\n */\r\n constructor(objectName: string, propertyName: string, defaultValue: any, getterFuntion: ObjectValueGetterFunction) {\r\n this.objectName = objectName;\r\n this.propertyName = propertyName;\r\n this.defaultValue = defaultValue;\r\n this.getterFuntion = getterFuntion;\r\n }\r\n\r\n /**\r\n * Gets the PropertyIdentifier for the Property\r\n * @returns PropertyIdentifier for the Property\r\n */\r\n public getPropertyID(): DataViewObjectPropertyIdentifier {\r\n return { objectName: this.objectName, propertyName: this.propertyName };\r\n }\r\n\r\n /**\r\n * Gets the value of the Property from the Objects\r\n * @param {DataViewObjects} objects DataView Objects to get the value from\r\n * @param {boolean} useDefault True to fall back to the Default value if the Property is missing from the objects. False to return undefined\r\n * @returns Value of the property\r\n */\r\n public getValue<T>(objects: DataViewObjects): T {\r\n // We use this when we intend to have undefined for missing properties. Useful in letting styles fallback to CSS if not defined\r\n return this.getterFuntion<T>(objects, this.getPropertyID(), this.defaultValue);\r\n }\r\n }\r\n\r\n // Per Column\r\n export const PropColumnFormatString = new TablixProperty(ObjectGeneral, 'formatString', undefined, DataViewObjects.getValue);\r\n\r\n // General\r\n export const PropGeneralAutoSizeColumns = new TablixProperty(ObjectGeneral, 'autoSizeColumnWidth', true, DataViewObjects.getValue);\r\n export const PropGeneralTextSize = new TablixProperty(ObjectGeneral, 'textSize', 8, DataViewObjects.getValue);\r\n export const PropGeneralTableTotals = new TablixProperty(ObjectGeneral, 'totals', true, DataViewObjects.getValue);\r\n export const PropGeneralMatrixRowSubtotals = new TablixProperty(ObjectGeneral, 'rowSubtotals', true, DataViewObjects.getValue);\r\n export const PropGeneralMatrixColumnSubtotals = new TablixProperty(ObjectGeneral, 'columnSubtotals', true, DataViewObjects.getValue);\r\n\r\n //Grid\r\n export const PropGridVertical = new TablixProperty(ObjectGrid, 'gridVertical', false, DataViewObjects.getValue);\r\n export const PropGridVerticalColor = new TablixProperty(ObjectGrid, 'gridVerticalColor', \"#E8E8E8\", DataViewObjects.getFillColor);\r\n export const PropGridVerticalWeight = new TablixProperty(ObjectGrid, 'gridVerticalWeight', 1, DataViewObjects.getValue);\r\n export const PropGridHorizontalTable = new TablixProperty(ObjectGrid, 'gridHorizontal', true, DataViewObjects.getValue);\r\n export const PropGridHorizontalMatrix = new TablixProperty(ObjectGrid, 'gridHorizontal', false, DataViewObjects.getValue);\r\n export const PropGridHorizontalColor = new TablixProperty(ObjectGrid, 'gridHorizontalColor', \"#E8E8E8\", DataViewObjects.getFillColor);\r\n export const PropGridHorizontalWeight = new TablixProperty(ObjectGrid, 'gridHorizontalWeight', 1, DataViewObjects.getValue);\r\n export const PropGridRowPadding = new TablixProperty(ObjectGrid, 'rowPadding', 0, DataViewObjects.getValue);\r\n export const PropGridOutlineColor = new TablixProperty(ObjectGrid, 'outlineColor', \"#CCC\", DataViewObjects.getFillColor);\r\n export const PropGridOutlineWeight = new TablixProperty(ObjectGrid, 'outlineWeight', 1, DataViewObjects.getValue);\r\n export const PropGridImageHeight = new TablixProperty(ObjectGrid, 'imageHeight', 75, DataViewObjects.getValue);\r\n\r\n // Column Headers\r\n export const PropColumnsFontColor = new TablixProperty(ObjectColumnHeaders, 'fontColor', \"#666\", DataViewObjects.getFillColor);\r\n export const PropColumnsBackColor = new TablixProperty(ObjectColumnHeaders, 'backColor', undefined, DataViewObjects.getFillColor);\r\n export const PropColumnsOutline = new TablixProperty(ObjectColumnHeaders, 'outline', \"BottomOnly\", DataViewObjects.getValue);\r\n\r\n // Row Headers\r\n export const PropRowsFontColor = new TablixProperty(ObjectRowHeaders, 'fontColor', \"#666\", DataViewObjects.getFillColor);\r\n export const PropRowsBackColor = new TablixProperty(ObjectRowHeaders, 'backColor', undefined, DataViewObjects.getFillColor);\r\n export const PropRowsOutline = new TablixProperty(ObjectRowHeaders, 'outline', \"RightOnly\", DataViewObjects.getValue);\r\n\r\n // Values\r\n export const PropValuesBackColor = new TablixProperty(ObjectValues, 'backColor', undefined, DataViewObjects.getFillColor);\r\n export const PropValuesFontColorPrimary = new TablixProperty(ObjectValues, 'fontColorPrimary', \"#333\", DataViewObjects.getFillColor);\r\n export const PropValuesBackColorPrimary = new TablixProperty(ObjectValues, 'backColorPrimary', undefined, DataViewObjects.getFillColor);\r\n export const PropValuesFontColorSecondary = new TablixProperty(ObjectValues, 'fontColorSecondary', \"#333\", DataViewObjects.getFillColor);\r\n export const PropValuesBackColorSecondary = new TablixProperty(ObjectValues, 'backColorSecondary', undefined, DataViewObjects.getFillColor);\r\n export const PropValuesOutline = new TablixProperty(ObjectValues, 'outline', \"None\", DataViewObjects.getValue);\r\n export const PropValuesUrlIconProp = new TablixProperty(ObjectValues, 'urlIcon', false, DataViewObjects.getValue);\r\n\r\n // Total\r\n export const PropTotalFontColor = new TablixProperty(ObjectTotal, 'fontColor', \"#333\", DataViewObjects.getFillColor);\r\n export const PropTotalBackColor = new TablixProperty(ObjectTotal, 'backColor', undefined, DataViewObjects.getFillColor);\r\n export const PropTotalOutline = new TablixProperty(ObjectTotal, 'outline', \"TopOnly\", DataViewObjects.getValue);\r\n\r\n // SubTotals\r\n export const PropSubTotalsFontColor = new TablixProperty(ObjectSubTotals, 'fontColor', \"#333\", DataViewObjects.getFillColor);\r\n export const PropSubTotalsBackColor = new TablixProperty(ObjectSubTotals, 'backColor', undefined, DataViewObjects.getFillColor);\r\n export const PropSubTotalsOutline = new TablixProperty(ObjectSubTotals, 'outline', \"TopOnly\", DataViewObjects.getValue);\r\n\r\n /**\r\n * Get the DataViewObject from the DataView\r\n * @param {DataView} dataview The DataView\r\n * @returns DataViewObjects (dataView.metadata.objects)\r\n */\r\n export function getMetadadataObjects(dataview: DataView): DataViewObjects {\r\n if (dataview && dataview.metadata)\r\n return dataview.metadata.objects;\r\n\r\n return null;\r\n }\r\n\r\n export function enumerateObjectRepetition(enumeration: VisualObjectRepetition[], dataView: DataView, tablixType: TablixType): void {\r\n debug.assertValue(enumeration, 'enumeration should be defined');\r\n debug.assertValue(dataView, \"dataView can't be undefined\");\r\n\r\n // We currently only support Table\r\n if (tablixType !== TablixType.Table)\r\n return;\r\n\r\n let columns = getTableColumnMetadata(dataView);\r\n for (let column of columns) {\r\n let repetition: VisualObjectRepetition = {\r\n selector: {\r\n data: [DataViewRoleWildCard.fromRoles(['Values'])],\r\n metadata: column.queryName,\r\n },\r\n objects: {\r\n [TablixObjects.ObjectValues]: {\r\n formattingProperties: [TablixObjects.PropValuesBackColor.propertyName]\r\n },\r\n }\r\n };\r\n\r\n enumeration.push(repetition);\r\n }\r\n }\r\n\r\n export function enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions, enumeration: ObjectEnumerationBuilder, dataView: DataView, tablixType: TablixType): void {\r\n debug.assertValue(dataView, \"dataView can't be undefined\");\r\n\r\n let objects = getMetadadataObjects(dataView);\r\n\r\n let totalsShown: boolean = true;\r\n\r\n if (tablixType === TablixType.Table) {\r\n totalsShown = shouldShowTableTotalsOption(dataView) && shouldShowTableTotals(objects);\r\n }\r\n else {\r\n totalsShown =\r\n (shouldShowColumnSubtotalsOption(dataView) && shouldShowColumnSubtotals(objects)) ||\r\n (shouldShowRowSubtotalsOption(dataView) && shouldShowRowSubtotals(objects));\r\n }\r\n\r\n switch (options.objectName) {\r\n case TablixObjects.ObjectGeneral:\r\n enumerateGeneralOptions(enumeration, objects, tablixType, dataView);\r\n break;\r\n case TablixObjects.ObjectGrid:\r\n enumerateGridOptions(enumeration, objects, tablixType);\r\n break;\r\n case TablixObjects.ObjectColumnHeaders:\r\n enumerateColumnHeadersOptions(enumeration, objects);\r\n break;\r\n case TablixObjects.ObjectRowHeaders:\r\n enumerateRowHeadersOptions(enumeration, objects);\r\n break;\r\n case TablixObjects.ObjectValues:\r\n enumerateValuesOptions(enumeration, objects, tablixType);\r\n break;\r\n case TablixObjects.ObjectTotal:\r\n if (totalsShown)\r\n enumerateTotalOptions(enumeration, objects);\r\n break;\r\n case TablixObjects.ObjectSubTotals:\r\n if (totalsShown)\r\n enumerateSubTotalsOptions(enumeration, objects);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n export function enumerateGeneralOptions(enumeration: ObjectEnumerationBuilder, objects: DataViewObjects, tablixType: TablixType, dataView: DataView): void {\r\n let visualObjectinstance: VisualObjectInstance = {\r\n selector: null,\r\n objectName: TablixObjects.ObjectGeneral,\r\n properties: {\r\n autoSizeColumnWidth: TablixObjects.PropGeneralAutoSizeColumns.getValue(objects),\r\n textSize: TablixObjects.PropGeneralTextSize.getValue<number>(objects),\r\n }\r\n };\r\n\r\n let properties = visualObjectinstance.properties;\r\n\r\n // Total and SubTotals\r\n switch (tablixType) {\r\n case TablixType.Table:\r\n if (shouldShowTableTotalsOption(dataView))\r\n properties[TablixObjects.PropGeneralTableTotals.propertyName] = shouldShowTableTotals(objects);\r\n break;\r\n\r\n case TablixType.Matrix:\r\n if (shouldShowRowSubtotalsOption(dataView))\r\n properties[TablixObjects.PropGeneralMatrixRowSubtotals.propertyName] = shouldShowRowSubtotals(objects);\r\n if (shouldShowColumnSubtotalsOption(dataView))\r\n properties[TablixObjects.PropGeneralMatrixColumnSubtotals.propertyName] = shouldShowColumnSubtotals(objects);\r\n break;\r\n }\r\n\r\n enumeration.pushInstance(visualObjectinstance);\r\n }\r\n\r\n export function enumerateGridOptions(enumeration: ObjectEnumerationBuilder, objects: DataViewObjects, tablixType: TablixType): void {\r\n let visualObjectinstance: VisualObjectInstance = {\r\n selector: null,\r\n objectName: TablixObjects.ObjectGeneral,\r\n properties: {}\r\n };\r\n let properties = visualObjectinstance.properties;\r\n\r\n // Vertical Grid\r\n let verticalGridEnabled = TablixObjects.PropGridVertical.getValue<boolean>(objects);\r\n properties[TablixObjects.PropGridVertical.propertyName] = verticalGridEnabled;\r\n if (verticalGridEnabled) {\r\n properties[TablixObjects.PropGridVerticalColor.propertyName] = TablixObjects.PropGridVerticalColor.getValue<string>(objects);\r\n properties[TablixObjects.PropGridVerticalWeight.propertyName] = TablixObjects.PropGridVerticalWeight.getValue<number>(objects);\r\n }\r\n\r\n // Horizontal Grid\r\n let horizontalGridEnabled = (tablixType === TablixType.Table ? TablixObjects.PropGridHorizontalTable : TablixObjects.PropGridHorizontalMatrix).getValue<boolean>(objects);\r\n properties[(tablixType === TablixType.Table ? TablixObjects.PropGridHorizontalTable : TablixObjects.PropGridHorizontalMatrix).propertyName] = horizontalGridEnabled;\r\n if (horizontalGridEnabled) {\r\n properties[TablixObjects.PropGridHorizontalColor.propertyName] = TablixObjects.PropGridHorizontalColor.getValue<string>(objects);\r\n properties[TablixObjects.PropGridHorizontalWeight.propertyName] = TablixObjects.PropGridHorizontalWeight.getValue<number>(objects);\r\n }\r\n\r\n // Row Padding\r\n properties[TablixObjects.PropGridRowPadding.propertyName] = TablixObjects.PropGridRowPadding.getValue<number>(objects);\r\n\r\n // Outline\r\n properties[TablixObjects.PropGridOutlineColor.propertyName] = TablixObjects.PropGridOutlineColor.getValue<string>(objects);\r\n properties[TablixObjects.PropGridOutlineWeight.propertyName] = TablixObjects.PropGridOutlineWeight.getValue<number>(objects);\r\n\r\n // Image Height\r\n properties[TablixObjects.PropGridImageHeight.propertyName] = TablixObjects.PropGridImageHeight.getValue<number>(objects);\r\n\r\n enumeration.pushInstance(visualObjectinstance);\r\n }\r\n\r\n export function enumerateColumnHeadersOptions(enumeration: ObjectEnumerationBuilder, objects: DataViewObjects): void {\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: TablixObjects.ObjectColumnHeaders,\r\n properties: {\r\n fontColor: TablixObjects.PropColumnsFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropColumnsBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropColumnsOutline.getValue<string>(objects),\r\n }\r\n });\r\n }\r\n\r\n export function enumerateRowHeadersOptions(enumeration: ObjectEnumerationBuilder, objects: DataViewObjects): void {\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: TablixObjects.ObjectRowHeaders,\r\n properties: {\r\n fontColor: TablixObjects.PropRowsFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropRowsBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropRowsOutline.getValue<string>(objects),\r\n }\r\n });\r\n }\r\n\r\n export function enumerateValuesOptions(enumeration: ObjectEnumerationBuilder, objects: DataViewObjects, tablixType: TablixType): void {\r\n let instance: VisualObjectInstance = {\r\n selector: null,\r\n objectName: TablixObjects.ObjectValues,\r\n properties: {\r\n fontColorPrimary: TablixObjects.PropValuesFontColorPrimary.getValue<string>(objects),\r\n backColorPrimary: TablixObjects.PropValuesBackColorPrimary.getValue<string>(objects),\r\n fontColorSecondary: TablixObjects.PropValuesFontColorSecondary.getValue<string>(objects),\r\n backColorSecondary: TablixObjects.PropValuesBackColorSecondary.getValue<string>(objects),\r\n outline: TablixObjects.PropValuesOutline.getValue<string>(objects),\r\n }\r\n };\r\n\r\n if (tablixType === TablixType.Table)\r\n instance.properties[TablixObjects.PropValuesUrlIconProp.propertyName] = TablixObjects.PropValuesUrlIconProp.getValue<boolean>(objects);\r\n\r\n enumeration.pushInstance(instance);\r\n }\r\n\r\n export function enumerateTotalOptions(enumeration: ObjectEnumerationBuilder, objects: DataViewObjects): void {\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: TablixObjects.ObjectTotal,\r\n properties: {\r\n fontColor: TablixObjects.PropTotalFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropTotalBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropTotalOutline.getValue<string>(objects),\r\n }\r\n });\r\n }\r\n\r\n export function enumerateSubTotalsOptions(enumeration: ObjectEnumerationBuilder, objects: DataViewObjects): void {\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: TablixObjects.ObjectSubTotals,\r\n properties: {\r\n fontColor: TablixObjects.PropSubTotalsFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropSubTotalsBackColor.getValue<string>(objects),\r\n }\r\n });\r\n }\r\n\r\n export function getTableObjects(dataView: DataView): TablixFormattingPropertiesTable {\r\n let objects = getMetadadataObjects(dataView);\r\n\r\n let formattingProperties: TablixFormattingPropertiesTable = {\r\n\r\n general: {\r\n autoSizeColumnWidth: TablixObjects.PropGeneralAutoSizeColumns.getValue<boolean>(objects),\r\n textSize: TablixObjects.PropGeneralTextSize.getValue<number>(objects),\r\n totals: shouldShowTableTotals(objects),\r\n },\r\n };\r\n\r\n formattingProperties.grid = {\r\n gridVertical: TablixObjects.PropGridVertical.getValue<boolean>(objects),\r\n gridVerticalColor: TablixObjects.PropGridVerticalColor.getValue<string>(objects),\r\n gridVerticalWeight: TablixObjects.PropGridVerticalWeight.getValue<number>(objects),\r\n gridHorizontal: TablixObjects.PropGridHorizontalTable.getValue<boolean>(objects),\r\n gridHorizontalColor: TablixObjects.PropGridHorizontalColor.getValue<string>(objects),\r\n gridHorizontalWeight: TablixObjects.PropGridHorizontalWeight.getValue<number>(objects),\r\n outlineColor: TablixObjects.PropGridOutlineColor.getValue<string>(objects),\r\n outlineWeight: TablixObjects.PropGridOutlineWeight.getValue<number>(objects),\r\n rowPadding: TablixObjects.PropGridRowPadding.getValue<number>(objects),\r\n imageHeight: TablixObjects.PropGridImageHeight.getValue<number>(objects),\r\n };\r\n\r\n formattingProperties.columnHeaders = {\r\n fontColor: TablixObjects.PropColumnsFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropColumnsBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropColumnsOutline.getValue<string>(objects),\r\n };\r\n\r\n formattingProperties.values = {\r\n fontColorPrimary: TablixObjects.PropValuesFontColorPrimary.getValue<string>(objects),\r\n backColorPrimary: TablixObjects.PropValuesBackColorPrimary.getValue<string>(objects),\r\n fontColorSecondary: TablixObjects.PropValuesFontColorSecondary.getValue<string>(objects),\r\n backColorSecondary: TablixObjects.PropValuesBackColorSecondary.getValue<string>(objects),\r\n outline: TablixObjects.PropValuesOutline.getValue<string>(objects),\r\n urlIcon: TablixObjects.PropValuesUrlIconProp.getValue<boolean>(objects),\r\n };\r\n\r\n formattingProperties.total = {\r\n fontColor: TablixObjects.PropTotalFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropTotalBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropTotalOutline.getValue<string>(objects),\r\n };\r\n\r\n return formattingProperties;\r\n }\r\n\r\n export function getMatrixObjects(dataView: DataView): TablixFormattingPropertiesMatrix {\r\n let objects = getMetadadataObjects(dataView);\r\n\r\n let formattingProperties: TablixFormattingPropertiesMatrix = {\r\n general: {\r\n autoSizeColumnWidth: TablixObjects.PropGeneralAutoSizeColumns.getValue<boolean>(objects),\r\n textSize: TablixObjects.PropGeneralTextSize.getValue<number>(objects),\r\n rowSubtotals: shouldShowRowSubtotals(objects),\r\n columnSubtotals: shouldShowColumnSubtotals(objects),\r\n },\r\n };\r\n\r\n formattingProperties.grid = {\r\n gridVertical: TablixObjects.PropGridVertical.getValue<boolean>(objects),\r\n gridVerticalColor: TablixObjects.PropGridVerticalColor.getValue<string>(objects),\r\n gridVerticalWeight: TablixObjects.PropGridVerticalWeight.getValue<number>(objects),\r\n gridHorizontal: TablixObjects.PropGridHorizontalMatrix.getValue<boolean>(objects),\r\n gridHorizontalColor: TablixObjects.PropGridHorizontalColor.getValue<string>(objects),\r\n gridHorizontalWeight: TablixObjects.PropGridHorizontalWeight.getValue<number>(objects),\r\n outlineColor: TablixObjects.PropGridOutlineColor.getValue<string>(objects),\r\n outlineWeight: TablixObjects.PropGridOutlineWeight.getValue<number>(objects),\r\n rowPadding: TablixObjects.PropGridRowPadding.getValue<number>(objects),\r\n imageHeight: TablixObjects.PropGridImageHeight.getValue<number>(objects),\r\n };\r\n\r\n formattingProperties.columnHeaders = {\r\n fontColor: TablixObjects.PropColumnsFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropColumnsBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropColumnsOutline.getValue<string>(objects),\r\n };\r\n\r\n formattingProperties.rowHeaders = {\r\n fontColor: TablixObjects.PropRowsFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropRowsBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropRowsOutline.getValue<string>(objects),\r\n };\r\n\r\n formattingProperties.values = {\r\n fontColorPrimary: TablixObjects.PropValuesFontColorPrimary.getValue<string>(objects),\r\n backColorPrimary: TablixObjects.PropValuesBackColorPrimary.getValue<string>(objects),\r\n fontColorSecondary: TablixObjects.PropValuesFontColorSecondary.getValue<string>(objects),\r\n backColorSecondary: TablixObjects.PropValuesBackColorSecondary.getValue<string>(objects),\r\n outline: TablixObjects.PropValuesOutline.getValue<string>(objects),\r\n };\r\n\r\n formattingProperties.subtotals = {\r\n fontColor: TablixObjects.PropSubTotalsFontColor.getValue<string>(objects),\r\n backColor: TablixObjects.PropSubTotalsBackColor.getValue<string>(objects),\r\n outline: TablixObjects.PropSubTotalsOutline.getValue<string>(objects),\r\n };\r\n\r\n return formattingProperties;\r\n }\r\n\r\n /**\r\n * Generate default objects for the Table/Matrix to set default styling\r\n * @param {TablixType} tablixType Tablix Type: table | matrix\r\n * @returns DataViewObjects that can be attached to the DataViewMetadata\r\n */\r\n export function generateTablixDefaultObjects(tablixType: TablixType): data.DataViewObjectDefinitions {\r\n return {\r\n general: [{\r\n selector: null,\r\n properties: {\r\n textSize: DataViewObjectDefinitions.encodePropertyValue(12, { numeric: true }),\r\n totals: DataViewObjectDefinitions.encodePropertyValue(false, { bool: true }),\r\n }\r\n }],\r\n };\r\n }\r\n\r\n export function getTextSizeInPx(textSize: number): string {\r\n return jsCommon.PixelConverter.fromPoint(textSize);\r\n }\r\n\r\n export function shouldShowTableTotals(objects: DataViewObjects): boolean {\r\n return TablixObjects.PropGeneralTableTotals.getValue<boolean>(objects);\r\n }\r\n\r\n function shouldShowTableTotalsOption(dataView: DataView): boolean {\r\n if (dataView && dataView.table && !_.isEmpty(dataView.table.columns)) {\r\n let columns = dataView.table.columns;\r\n if (_.some(columns, (column) => column.discourageAggregationAcrossGroups))\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n function getTableColumnMetadata(dataView: DataView): DataViewMetadataColumn[] {\r\n if (!dataView || !dataView.table || _.isEmpty(dataView.table.columns))\r\n return;\r\n\r\n return dataView.table.columns;\r\n }\r\n\r\n export function shouldShowRowSubtotals(objects: DataViewObjects): boolean {\r\n return TablixObjects.PropGeneralMatrixRowSubtotals.getValue<boolean>(objects);\r\n }\r\n\r\n function shouldShowRowSubtotalsOption(dataView: DataView): boolean {\r\n return !(dataView &&\r\n dataView.matrix &&\r\n dataView.matrix.rows &&\r\n isDiscourageAggregationAcrossGroups(dataView.matrix.rows.levels));\r\n }\r\n\r\n export function shouldShowColumnSubtotals(objects: DataViewObjects): boolean {\r\n return TablixObjects.PropGeneralMatrixColumnSubtotals.getValue<boolean>(objects);\r\n }\r\n\r\n export function shouldShowColumnSubtotalsOption(dataView: DataView): boolean {\r\n return !(dataView &&\r\n dataView.matrix &&\r\n dataView.matrix.columns &&\r\n isDiscourageAggregationAcrossGroups(dataView.matrix.columns.levels));\r\n }\r\n\r\n export function isDiscourageAggregationAcrossGroups(levels: DataViewHierarchyLevel[]): boolean {\r\n let lastLevel = _.last(levels);\r\n // If the last item is not Aggregatable, disable totals option since there will be no totals at all to display\r\n // However, if the non-aggregatable filed is in the middle, there are totals showing up in matrix.\r\n // Therefore, we still allow users to turn it off\r\n return lastLevel && _.some(lastLevel.sources, source => source.discourageAggregationAcrossGroups);\r\n }\r\n }\r\n\r\n export module TablixUtils {\r\n export const CssClassTablixDiv = \"tablixDiv\"; // Any DIV inside the table (outer and inner)\r\n export const CssClassContentElement = \"tablixCellContentElement\"; // Outer DIV\r\n export const CssClassContentHost = \"tablixCellContentHost\"; // Inner DIV\r\n\r\n export const CssClassTablixHeader = \"tablixHeader\"; // Any Header in the Table/Matrix\r\n export const CssClassTablixColumnHeaderLeaf = \"tablixColumnHeaderLeaf\"; // Leaf Column Headers\r\n\r\n export const CssClassTablixValueNumeric = \"tablixValueNumeric\"; // Numeric cells, will also be applied to all Matrix body cells\r\n export const CssClassTablixValueTotal = \"tablixValueTotal\"; // Total cells, will also be applied to subtotal Matrix body cells\r\n export const CssClassValueURLIcon: string = \"powervisuals-glyph url-icon tablixUrlIconGlyph\"; // Any <a> Tag\r\n export const CssClassValueURLIconContainer: string = \"tablixValueUrlIcon\"; // Container for the <a> tag\r\n\r\n export const CssClassMatrixRowHeaderLeaf = \"matrixRowHeaderLeaf\"; // Matrix Leaf Row Headers\r\n export const CssClassMatrixRowHeaderSubTotal = \"matrixRowHeaderSubTotal\"; // Matrix SubTotal Row Headers\r\n\r\n export const CssClassTableFooter = 'tableFooterCell'; // Any cell in the Footer area\r\n export const CssClassTableBodyCell = 'tableBodyCell'; // Any cell in the Table Body\r\n export const CssClassTableBodyCellBottom = 'tableBodyCellBottom'; // Bottom-Most Body cell\r\n\r\n export const StringNonBreakingSpace = '&nbsp;';\r\n\r\n export const UnitOfMeasurement: string = 'px';\r\n const SortIconContainerClassName: string = \"tablixSortIconContainer\";\r\n export const CellPaddingLeft: number = 10;\r\n export const CellPaddingRight: number = 5;\r\n export const CellPaddingLeftMatrixTotal: number = 5;\r\n export const FontFamilyCell: string = \"'Segoe UI','wf_segoe-ui_normal', helvetica, arial, sans-serif\";\r\n export const FontFamilyHeader: string = \"'Segoe UI','wf_segoe-ui_normal', helvetica, arial, sans-serif\";\r\n export const FontFamilyTotal: string = \"'Segoe UI Bold','wf_segoe-ui_bold', helvetica, arial, sans-serif\";\r\n export const FontColorCells: string = \"#333\";\r\n export const FontColorHeaders: string = \"#666\";\r\n\r\n export interface Surround<T> {\r\n top?: T;\r\n right?: T;\r\n bottom?: T;\r\n left?: T;\r\n }\r\n\r\n export class EdgeSettings {\r\n /**\r\n * Weight in pixels. 0 to remove border. Undefined to fall back to CSS\r\n */\r\n public weight: number;\r\n public color: string;\r\n\r\n constructor(weight?: number, color?: string) {\r\n this.applyParams(true, weight, color);\r\n }\r\n\r\n public applyParams(shown: boolean, weight: number, color?: string) {\r\n if (shown) {\r\n this.weight = weight == null ? 0 : weight;\r\n this.color = color == null ? 'black' : color;\r\n }\r\n else {\r\n this.weight = 0;\r\n this.color = 'black';\r\n }\r\n }\r\n\r\n public getCSS(): string {\r\n let css: string[] = [];\r\n\r\n if (_.isNumber(this.weight)) {\r\n css.push(this.weight + UnitOfMeasurement);\r\n if (this.color)\r\n css.push(this.color);\r\n\r\n css.push('solid');\r\n }\r\n\r\n return css.join(' ');\r\n }\r\n }\r\n\r\n /**\r\n * Style parameters for each Cell\r\n */\r\n export class CellStyle {\r\n /**\r\n * Font family of the cell. If undefined, it will be cleared to fall back to table font family\r\n */\r\n public fontFamily: string;\r\n /**\r\n * Font color of the cell. If undefined, it will be cleared to fall back to table font color\r\n */\r\n public fontColor: string;\r\n /**\r\n * Background color of the cell. If undefined, it will be cleared to fall back to default (transparent)\r\n */\r\n public backColor: string;\r\n /**\r\n * Indicates whether the Cell contains an Image or not. Affecting cell height.\r\n */\r\n public hasImage: boolean;\r\n /**\r\n * Settings for Borders\r\n */\r\n public borders: Surround<EdgeSettings>;\r\n\r\n /**\r\n * Settings for Padding\r\n */\r\n public paddings: Surround<number>;\r\n\r\n constructor() {\r\n this.borders = {};\r\n this.paddings = { top: 0, left: TablixUtils.CellPaddingLeft, bottom: 0, right: TablixUtils.CellPaddingRight };\r\n\r\n // Initializing values with empty string would cause CSS attributes to not be set if they are undefined\r\n this.fontFamily = \"\";\r\n\r\n this.fontColor = \"\";\r\n this.backColor = \"\";\r\n\r\n this.hasImage = false;\r\n }\r\n\r\n /**\r\n * Sets the Inline style for the Cell\r\n * @param {ITablixCell} cell Cell to set style to\r\n */\r\n public applyStyle(cell: ITablixCell): void {\r\n let div = cell.extension.contentHost;\r\n let style = div.style;\r\n\r\n style.fontFamily = this.fontFamily;\r\n\r\n style.color = this.fontColor;\r\n style.backgroundColor = this.backColor;\r\n\r\n /**\r\n * We are setting the borders as inset shadow\r\n * This way we can control how intersecting borders would look like when they have different colors\r\n */\r\n let borderShadow: string[] = [];\r\n\r\n style.border = \"none\";\r\n\r\n if (this.borders.left) {\r\n borderShadow.push(\"inset \" + this.borders.left.weight + UnitOfMeasurement + \" 0 0 0 \" + this.borders.left.color);\r\n }\r\n\r\n if (this.borders.right) {\r\n borderShadow.push(\"inset -\" + this.borders.right.weight + UnitOfMeasurement + \" 0 0 0 \" + this.borders.right.color);\r\n }\r\n\r\n if (this.borders.top) {\r\n borderShadow.push(\"inset 0 \" + this.borders.top.weight + UnitOfMeasurement + \" 0 0 \" + this.borders.top.color);\r\n }\r\n\r\n if (this.borders.bottom) {\r\n borderShadow.push(\"inset 0 -\" + this.borders.bottom.weight + UnitOfMeasurement + \" 0 0 \" + this.borders.bottom.color);\r\n }\r\n\r\n style.boxShadow = borderShadow.join(', ');\r\n\r\n style.paddingTop = ((this.paddings.top == null ? 0 : this.paddings.top) + (this.borders.top == null ? 0 : this.borders.top.weight)) + UnitOfMeasurement;\r\n style.paddingRight = ((this.paddings.right == null ? CellPaddingRight : this.paddings.right) + (this.borders.right == null ? 0 : this.borders.right.weight)) + UnitOfMeasurement;\r\n style.paddingBottom = ((this.paddings.bottom == null ? 0 : this.paddings.bottom) + (this.borders.bottom == null ? 0 : this.borders.bottom.weight)) + UnitOfMeasurement;\r\n style.paddingLeft = ((this.paddings.left == null ? CellPaddingLeft : this.paddings.left) + (this.borders.left == null ? 0 : this.borders.left.weight)) + UnitOfMeasurement;\r\n }\r\n\r\n public getExtraTop(): number {\r\n let extra = 0;\r\n\r\n if (this.paddings.top)\r\n extra += this.paddings.top;\r\n if (this.borders.top)\r\n extra += this.borders.top.weight;\r\n\r\n return extra;\r\n }\r\n\r\n public getExtraBottom(): number {\r\n let extra = 0;\r\n\r\n if (this.paddings.bottom)\r\n extra += this.paddings.bottom;\r\n if (this.borders.bottom)\r\n extra += this.borders.bottom.weight;\r\n\r\n return extra;\r\n }\r\n\r\n public getExtraRight(): number {\r\n let extra = 0;\r\n\r\n if (this.paddings.right)\r\n extra += this.paddings.right;\r\n if (this.borders.right)\r\n extra += this.borders.right.weight;\r\n\r\n return extra;\r\n }\r\n\r\n public getExtraLeft(): number {\r\n let extra = 0;\r\n\r\n if (this.paddings.left)\r\n extra += this.paddings.left;\r\n if (this.borders.left)\r\n extra += this.borders.left.weight;\r\n\r\n return extra;\r\n }\r\n }\r\n\r\n /**\r\n * Index within a dimension (row/column)\r\n */\r\n export class DimensionPosition {\r\n /**\r\n * Global index within all leaf nodes\r\n */\r\n public index: number;\r\n /**\r\n * Index within siblings for same parent\r\n */\r\n public indexInSiblings: number;\r\n /**\r\n * Is last globally\r\n */\r\n public isLast: boolean;\r\n /**\r\n * Is first globally\r\n */\r\n public isFirst: boolean;\r\n }\r\n /**\r\n * Poistion information about the cell\r\n */\r\n export class CellPosition {\r\n public row: DimensionPosition;\r\n public column: DimensionPosition;\r\n\r\n constructor() {\r\n this.row = new DimensionPosition();\r\n this.column = new DimensionPosition();\r\n }\r\n\r\n public isMatch(position: CellPosition) {\r\n return this.column.index === position.column.index &&\r\n this.row.index === position.row.index;\r\n }\r\n }\r\n\r\n export class TablixVisualCell {\r\n public dataPoint: any;\r\n public position: TablixUtils.CellPosition;\r\n public columnMetadata: DataViewMetadataColumn;\r\n public isTotal: boolean;\r\n public backColor: string;\r\n private formatter: ICustomValueColumnFormatter;\r\n\r\n constructor(dataPoint: any, isTotal: boolean, columnMetadata: DataViewMetadataColumn, formatter: ICustomValueColumnFormatter) {\r\n this.dataPoint = dataPoint;\r\n this.columnMetadata = columnMetadata;\r\n this.formatter = formatter;\r\n this.isTotal = isTotal;\r\n\r\n this.position = new TablixUtils.CellPosition();\r\n }\r\n\r\n public get textContent(): string {\r\n if (this.dataPoint == null)\r\n return '';\r\n\r\n if (this.formatter)\r\n return this.formatter(this.dataPoint, this.columnMetadata, TablixObjects.PropColumnFormatString.getPropertyID());\r\n else\r\n return this.dataPoint;\r\n };\r\n\r\n public get domContent(): JQuery {\r\n if (this.columnMetadata && isValidStatusGraphic(this.columnMetadata.kpi, this.textContent))\r\n return createKpiDom(this.columnMetadata.kpi, this.textContent);\r\n };\r\n\r\n public get isNumeric(): boolean {\r\n if (this.columnMetadata)\r\n return this.columnMetadata.type.numeric && !this.columnMetadata.kpi;\r\n };\r\n\r\n public get isUrl(): boolean {\r\n if (this.columnMetadata)\r\n return converterHelper.isWebUrlColumn(this.columnMetadata);\r\n };\r\n\r\n public get isImage(): boolean {\r\n if (this.columnMetadata)\r\n return converterHelper.isImageUrlColumn(this.columnMetadata);\r\n }\r\n\r\n public get isValidUrl(): boolean {\r\n return jsCommon.UrlUtils.isValidImageUrl(this.textContent);\r\n };\r\n\r\n public isMatch(item: TablixVisualCell) {\r\n return this.position.isMatch(item.position) && this.backColor === item.backColor;\r\n }\r\n }\r\n\r\n export function createTable(): HTMLTableElement {\r\n return <HTMLTableElement>document.createElement(\"table\");\r\n }\r\n\r\n export function createDiv(): HTMLDivElement {\r\n let div: HTMLDivElement = <HTMLDivElement>document.createElement(\"div\");\r\n div.className = \"tablixDiv\";\r\n return div;\r\n }\r\n\r\n export function resetCellCssClass(cell: controls.ITablixCell) {\r\n cell.extension.contentElement.className = TablixUtils.CssClassTablixDiv + \" \" + TablixUtils.CssClassContentElement;\r\n cell.extension.contentHost.className = TablixUtils.CssClassTablixDiv + \" \" + TablixUtils.CssClassContentHost;\r\n }\r\n\r\n export function addCellCssClass(cell: controls.ITablixCell, style: string): void {\r\n cell.extension.contentHost.className += \" \" + style;\r\n }\r\n\r\n /**\r\n * Clears all inline styles (border, fontColor, background) and resets CSS classes\r\n * Performed with unbind-<Cell>\r\n */\r\n export function clearCellStyle(cell: controls.ITablixCell): void {\r\n cell.extension.contentHost.className = \"\";\r\n cell.extension.contentHost.style.cssText = \"\";\r\n }\r\n\r\n export function clearCellTextAndTooltip(cell: controls.ITablixCell): void {\r\n cell.extension.contentHost.textContent = '';\r\n cell.extension.contentHost.removeAttribute('title');\r\n cell.contentHeight = cell.contentWidth = 0;\r\n HTMLElementUtils.clearChildren(cell.extension.contentHost);\r\n }\r\n\r\n export function setCellTextAndTooltip(cell: controls.ITablixCell, text: string): void {\r\n let val = TextUtil.replaceSpaceWithNBSP(text);\r\n cell.extension.contentHost.textContent = val;\r\n cell.extension.contentHost.title = val;\r\n }\r\n\r\n export function isValidSortClick(e: MouseEvent) {\r\n let colHeader = <HTMLElement>e.target;\r\n let x = e.offsetX;\r\n return x >= 0 && x < colHeader.offsetWidth - TablixResizer.resizeHandleSize;\r\n }\r\n\r\n export function appendATagToBodyCell(value: string, cell: controls.ITablixCell, urlIcon?: boolean): void {\r\n let element = <HTMLElement>cell.extension.contentHost;\r\n let atag: HTMLAnchorElement = null;\r\n if (element.childElementCount === 0) {\r\n atag = document.createElement('a');\r\n element.appendChild(atag);\r\n }\r\n else {\r\n atag = <HTMLAnchorElement>element.children[0];\r\n }\r\n\r\n atag.href = value;\r\n atag.target = '_blank';\r\n atag.title = value;\r\n\r\n if (urlIcon === true) {\r\n atag.className = CssClassValueURLIcon;\r\n element.className = CssClassValueURLIconContainer;\r\n }\r\n else {\r\n atag.innerText = value;\r\n }\r\n }\r\n\r\n export function appendImgTagToBodyCell(value: string, cell: controls.ITablixCell, imageHeight: number): void {\r\n let element = <HTMLElement>cell.extension.contentHost;\r\n let imgContainer: HTMLDivElement = TablixUtils.createDiv();\r\n let imgTag: HTMLImageElement = document.createElement('img');\r\n\r\n imgContainer.style.height = imageHeight + \"px\";\r\n imgContainer.style.width = \"100%\";\r\n imgContainer.style.textAlign = \"center\";\r\n imgTag.src = value;\r\n imgTag.style.maxHeight = \"100%\";\r\n imgTag.style.maxWidth = \"100%\";\r\n imgContainer.appendChild(imgTag);\r\n element.appendChild(imgContainer);\r\n }\r\n\r\n export function createKpiDom(kpi: DataViewKpiColumnMetadata, kpiValue: string): JQuery {\r\n debug.assertValue(kpi, 'kpi');\r\n debug.assertValue(kpiValue, 'kpiValue');\r\n let className: string = KpiUtil.getClassForKpi(kpi, kpiValue) || '';\r\n return DomFactory.div()\r\n .addClass(className)\r\n .css({\r\n 'display': 'inline-block',\r\n 'vertical-align': 'bottom',\r\n 'margin': '0',\r\n });\r\n }\r\n\r\n export function isValidStatusGraphic(kpi: DataViewKpiColumnMetadata, kpiValue: string): boolean {\r\n if (!kpi || kpiValue === undefined) {\r\n return false;\r\n }\r\n\r\n return !!KpiUtil.getClassForKpi(kpi, kpiValue);\r\n }\r\n\r\n export function getCustomSortEventArgs(queryName: string, sortDirection: SortDirection): CustomSortEventArgs {\r\n let sortDescriptors: SortableFieldDescriptor[] = [{\r\n queryName: queryName,\r\n sortDirection: sortDirection\r\n }];\r\n return { sortDescriptors: sortDescriptors };\r\n }\r\n\r\n export function reverseSort(sortDirection: SortDirection): SortDirection {\r\n return sortDirection === SortDirection.Descending ? SortDirection.Ascending : SortDirection.Descending;\r\n }\r\n\r\n export function createColumnHeaderWithSortIcon(item: DataViewMetadataColumn, cell: controls.ITablixCell): void {\r\n let colHeaderContainer: HTMLDivElement = TablixUtils.createDiv();\r\n\r\n if (item.sort) {\r\n let itemSort = item.sort;\r\n colHeaderContainer.appendChild(createSortIcon(itemSort, true));\r\n colHeaderContainer.appendChild(createSortIcon(reverseSort(itemSort), false));\r\n }\r\n else {\r\n colHeaderContainer.appendChild(createSortIcon(SortDirection.Descending, false));\r\n }\r\n\r\n let colHeaderTitle: HTMLDivElement = TablixUtils.createDiv();\r\n // Preserving trailing and leading spaces\r\n let title = item ? TextUtil.replaceSpaceWithNBSP(item.displayName) : '';\r\n colHeaderTitle.textContent = title;\r\n colHeaderContainer.appendChild(colHeaderTitle);\r\n cell.extension.contentHost.title = title;\r\n cell.extension.contentHost.appendChild(colHeaderContainer);\r\n }\r\n\r\n function createSortIcon(sort: SortDirection, isSorted: boolean): HTMLElement {\r\n let imgSort: HTMLPhraseElement = <HTMLPhraseElement>document.createElement('i');\r\n imgSort.className = SortIconContainerClassName +\r\n \" \" + (isSorted ? \"sorted\" : \"future\") +\r\n \" \" + (sort === SortDirection.Ascending ? \"powervisuals-glyph caret-up\" : \"powervisuals-glyph caret-down\");\r\n return imgSort;\r\n }\r\n\r\n function checkSortIconExists(cell: controls.ITablixCell): boolean {\r\n for (let i = 0, len = cell.extension.contentElement.childElementCount; i < len; i++) {\r\n let element = cell.extension.contentElement.children.item(i);\r\n if (element.classList.contains(SortIconContainerClassName))\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n export function removeSortIcons(cell: controls.ITablixCell): void {\r\n if (!checkSortIconExists(cell))\r\n return;\r\n $((<HTMLElement>cell.extension.contentElement)).find('.' + SortIconContainerClassName).remove();\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls {\r\n export const TablixDefaultTextSize = jsCommon.TextSizeDefaults.TextSizeMin;\r\n\r\n export interface TablixRenderArgs {\r\n rowScrollOffset?: number;\r\n columnScrollOffset?: number;\r\n scrollingDimension?: TablixDimension;\r\n }\r\n\r\n export interface GridDimensions {\r\n rowCount?: number;\r\n columnCount?: number;\r\n rowHierarchyWidth?: number;\r\n rowHierarchyHeight?: number;\r\n rowHierarchyContentHeight?: number;\r\n columnHierarchyWidth?: number;\r\n columnHierarchyHeight?: number;\r\n footerHeight?: number;\r\n }\r\n\r\n export const enum TablixLayoutKind {\r\n /**\r\n * The default layout is based on DOM measurements and used on the canvas.\r\n */\r\n Canvas,\r\n \r\n /**\r\n * The DashboardTile layout must not rely on any kind of DOM measurements\r\n * since the tiles are created when the dashboard is not visible and the\r\n * visual is not rendered; thus no measurements are available.\r\n */\r\n DashboardTile,\r\n }\r\n\r\n export interface TablixOptions {\r\n interactive?: boolean;\r\n enableTouchSupport?: boolean;\r\n layoutKind?: TablixLayoutKind;\r\n fontSize?: string;\r\n }\r\n\r\n export class TablixControl {\r\n private static UnitOfMeasurement = 'px';\r\n private static TablixContainerClassName = 'tablixContainer';\r\n private static TablixTableAreaClassName = \"tablixTableArea\";\r\n private static TablixFooterClassName = \"tableFooterArea\";\r\n private static DefaultFontSize = jsCommon.PixelConverter.fromPoint(controls.TablixDefaultTextSize);\r\n /*\r\n * This is workaround for the infinite loop in rendering\r\n * BugID: 6518621\r\n * ToDo: Investigate the underlying cause for rendering to never report completion\r\n * Rendering typically require 3-5 iterations to complete, so 10 is enough\r\n */\r\n private static MaxRenderIterationCount = 10;\r\n\r\n private hierarchyTablixNavigator: ITablixHierarchyNavigator;\r\n private binder: ITablixBinder;\r\n\r\n private columnDim: TablixColumnDimension;\r\n private rowDim: TablixRowDimension;\r\n private controlLayoutManager: internal.TablixLayoutManager;\r\n\r\n private containerElement: HTMLDivElement;\r\n private mainDiv: HTMLDivElement;\r\n private footerDiv: HTMLDivElement;\r\n\r\n private scrollBarElementWidth = 9;\r\n\r\n private touchManager: TouchUtils.TouchManager;\r\n private columnTouchDelegate: ColumnTouchDelegate;\r\n private rowTouchDelegate: RowTouchDelegate;\r\n private bodyTouchDelegate: BodyTouchDelegate;\r\n private footerTouchDelegate: ColumnTouchDelegate;\r\n private touchInterpreter: TouchUtils.TouchEventInterpreter;\r\n private footerTouchInterpreter: TouchUtils.TouchEventInterpreter;\r\n\r\n private gridDimensions: GridDimensions;\r\n private lastRenderingArgs: TablixRenderArgs;\r\n\r\n /* tslint:disable:no-underscore-prefix-for-variables*/\r\n private _autoSizeWidth: boolean;\r\n private _autoSizeHeight: boolean;\r\n /* tslint:enable:no-underscore-prefix-for-variables*/\r\n private viewPort: IViewport;\r\n private maximumWidth: number;\r\n private maximumHeight: number;\r\n private minimumWidth: number;\r\n private minimumHeight: number;\r\n private textFontSize: string;\r\n private textFontFamily: string;\r\n private textFontColor: string;\r\n\r\n private options: TablixOptions;\r\n private isTouchEnabled: boolean;\r\n\r\n private renderIterationCount: number;\r\n\r\n constructor(\r\n hierarchyNavigator: ITablixHierarchyNavigator,\r\n layoutManager: internal.TablixLayoutManager,\r\n binder: ITablixBinder,\r\n parentDomElement: HTMLElement,\r\n options: TablixOptions) {\r\n\r\n // Options (fontSize set after container initialized)\r\n this.options = options;\r\n let isInteractive = options.interactive;\r\n this.isTouchEnabled = isInteractive && options.enableTouchSupport;\r\n\r\n // Main Div\r\n this.mainDiv = internal.TablixUtils.createDiv();\r\n this.mainDiv.classList.add(TablixControl.TablixTableAreaClassName);\r\n\r\n // Footer Div\r\n this.footerDiv = internal.TablixUtils.createDiv();\r\n this.footerDiv.classList.add(TablixControl.TablixFooterClassName);\r\n\r\n if (this.isTouchEnabled)\r\n this.InitializeTouchSupport();\r\n\r\n this.gridDimensions = {};\r\n\r\n this.containerElement = internal.TablixUtils.createDiv();\r\n this.className = layoutManager.getTablixClassName();\r\n this.autoSizeWidth = false;\r\n this.autoSizeHeight = false;\r\n this.fontFamily = internal.TablixUtils.FontFamilyCell;\r\n this.fontColor = internal.TablixUtils.FontColorCells;\r\n this.fontSize = options.fontSize;\r\n\r\n parentDomElement.className = TablixControl.TablixContainerClassName;\r\n parentDomElement.appendChild(this.containerElement);\r\n\r\n this.containerElement.addEventListener(\"mousewheel\", (e) => { this.onMouseWheel(<MouseWheelEvent>e); });\r\n this.containerElement.addEventListener(\"DOMMouseScroll\", (e) => { this.onFireFoxMouseWheel(<MouseWheelEvent>e); });\r\n this.containerElement.appendChild(this.mainDiv);\r\n this.containerElement.appendChild(this.footerDiv);\r\n\r\n if (this.isTouchEnabled) {\r\n this.touchInterpreter.initTouch(this.mainDiv, null, false);\r\n this.footerTouchInterpreter.initTouch(this.footerDiv, this.mainDiv, false);\r\n }\r\n\r\n this.controlLayoutManager = layoutManager;\r\n this.controlLayoutManager.initialize(this);\r\n\r\n this.hierarchyTablixNavigator = hierarchyNavigator;\r\n this.binder = binder;\r\n\r\n this.columnDim = new TablixColumnDimension(this);\r\n this.rowDim = new TablixRowDimension(this);\r\n this.columnDim._otherDimension = this.rowDimension;\r\n this.rowDim._otherDimension = this.columnDimension;\r\n\r\n this.InitializeScrollbars();\r\n if (!isInteractive) {\r\n this.scrollbarWidth = 0;\r\n }\r\n\r\n this.updateHorizontalPosition();\r\n this.updateVerticalPosition();\r\n\r\n this.updateFooterVisibility();\r\n\r\n this.lastRenderingArgs = {};\r\n }\r\n\r\n private InitializeTouchSupport(): void {\r\n this.touchManager = new TouchUtils.TouchManager();\r\n this.touchInterpreter = new TouchUtils.TouchEventInterpreter(this.touchManager);\r\n this.footerTouchInterpreter = new TouchUtils.TouchEventInterpreter(this.touchManager);\r\n this.columnTouchDelegate = new ColumnTouchDelegate(new TouchUtils.Rectangle());\r\n this.rowTouchDelegate = new RowTouchDelegate(new TouchUtils.Rectangle());\r\n this.bodyTouchDelegate = new BodyTouchDelegate(new TouchUtils.Rectangle());\r\n this.footerTouchDelegate = new ColumnTouchDelegate(new TouchUtils.Rectangle());\r\n\r\n this.columnTouchDelegate.setHandler(this, this.onTouchEvent);\r\n this.rowTouchDelegate.setHandler(this, this.onTouchEvent);\r\n this.bodyTouchDelegate.setHandler(this, this.onTouchEvent);\r\n this.footerTouchDelegate.setHandler(this, this.onTouchEvent);\r\n\r\n this.touchManager.addTouchRegion(this.columnTouchDelegate.dimension, this.columnTouchDelegate, this.columnTouchDelegate);\r\n this.touchManager.addTouchRegion(this.rowTouchDelegate.dimension, this.rowTouchDelegate, this.rowTouchDelegate);\r\n this.touchManager.addTouchRegion(this.bodyTouchDelegate.dimension, this.bodyTouchDelegate, this.bodyTouchDelegate);\r\n this.touchManager.addTouchRegion(this.footerTouchDelegate.dimension, this.footerTouchDelegate, this.footerTouchDelegate);\r\n }\r\n\r\n private InitializeScrollbars(): void {\r\n // Row Dimension\r\n this.rowDim._initializeScrollbar(this.containerElement, null, this.options.layoutKind);\r\n\r\n let rowDimensionScrollbarStyle = this.rowDim.scrollbar.element.style;\r\n rowDimensionScrollbarStyle.position = \"absolute\";\r\n rowDimensionScrollbarStyle.top = \"0\" + TablixControl.UnitOfMeasurement;\r\n rowDimensionScrollbarStyle.right = \"0\" + TablixControl.UnitOfMeasurement;\r\n this.rowDim.scrollbar.width = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\r\n\r\n // Default to true which is the more common case to avoid an extra rendering iteration\r\n // when first rendering the visual\r\n this.rowDim.scrollbar.show(true);\r\n\r\n // Column Dimension\r\n this.columnDim._initializeScrollbar(this.containerElement, null, this.options.layoutKind);\r\n\r\n let columnDimensionScrollbarStyle = this.columnDim.scrollbar.element.style;\r\n columnDimensionScrollbarStyle.position = \"absolute\";\r\n columnDimensionScrollbarStyle.left = \"0\" + TablixControl.UnitOfMeasurement;\r\n columnDimensionScrollbarStyle.bottom = \"0\" + TablixControl.UnitOfMeasurement;\r\n this.columnDim.scrollbar.height = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\r\n\r\n this.columnDim.scrollbar.show(false);\r\n }\r\n\r\n public get container(): HTMLElement {\r\n return this.containerElement;\r\n }\r\n\r\n public get contentHost(): HTMLElement {\r\n return this.mainDiv;\r\n }\r\n\r\n public get footerHost(): HTMLElement {\r\n return this.footerDiv;\r\n }\r\n\r\n public set className(value: string) {\r\n this.containerElement.className = value;\r\n }\r\n\r\n public get hierarchyNavigator(): ITablixHierarchyNavigator {\r\n return this.hierarchyTablixNavigator;\r\n }\r\n\r\n public getBinder(): ITablixBinder {\r\n return this.binder;\r\n }\r\n\r\n public get autoSizeWidth(): boolean {\r\n return this._autoSizeWidth;\r\n }\r\n\r\n public set autoSizeWidth(value: boolean) {\r\n this._autoSizeWidth = value;\r\n\r\n if (!value) {\r\n this.containerElement.style.minWidth = this.containerElement.style.maxWidth = \"none\";\r\n }\r\n }\r\n\r\n public get autoSizeHeight(): boolean {\r\n return this._autoSizeHeight;\r\n }\r\n\r\n public set autoSizeHeight(value: boolean) {\r\n if (!value) {\r\n this.containerElement.style.minHeight = this.containerElement.style.maxHeight = \"none\";\r\n }\r\n }\r\n\r\n public get maxWidth(): number {\r\n return this.maximumWidth;\r\n }\r\n\r\n public set maxWidth(value: number) {\r\n this.maximumWidth = value;\r\n this.containerElement.style.maxWidth = this.maximumWidth + TablixControl.UnitOfMeasurement;\r\n }\r\n\r\n public get viewport(): IViewport {\r\n return this.viewPort;\r\n }\r\n\r\n public set viewport(value: IViewport) {\r\n this.viewPort = value;\r\n this.containerElement.style.width = this.viewPort.width + TablixControl.UnitOfMeasurement;\r\n this.containerElement.style.height = this.viewPort.height + TablixControl.UnitOfMeasurement;\r\n\r\n this.rowDim.scrollbar.invalidateArrange();\r\n this.columnDim.scrollbar.invalidateArrange();\r\n\r\n this.controlLayoutManager.updateViewport(this.viewPort);\r\n }\r\n\r\n public get maxHeight(): number {\r\n return this.maximumHeight;\r\n }\r\n\r\n public set maxHeight(value: number) {\r\n this.maximumHeight = value;\r\n this.containerElement.style.maxHeight = this.maximumHeight + TablixControl.UnitOfMeasurement;\r\n }\r\n\r\n public get minWidth(): number {\r\n return this.minimumWidth;\r\n }\r\n\r\n public set minWidth(value: number) {\r\n this.minimumWidth = value;\r\n this.containerElement.style.minWidth = this.minimumWidth + TablixControl.UnitOfMeasurement;\r\n }\r\n\r\n public get minHeight(): number {\r\n return this.minimumHeight;\r\n }\r\n\r\n public set minHeight(value: number) {\r\n this.minimumHeight = value;\r\n this.containerElement.style.minHeight = this.minimumHeight + TablixControl.UnitOfMeasurement;\r\n }\r\n\r\n public get fontSize(): string {\r\n return this.textFontSize;\r\n }\r\n\r\n public set fontSize(value: string) {\r\n this.textFontSize = !value ? TablixControl.DefaultFontSize : value;\r\n this.containerElement.style.fontSize = this.textFontSize;\r\n }\r\n\r\n public get fontFamily(): string {\r\n return this.textFontFamily;\r\n }\r\n\r\n public set fontFamily(value: string) {\r\n this.textFontFamily = value;\r\n this.containerElement.style.fontFamily = value;\r\n }\r\n\r\n public get fontColor(): string {\r\n return this.textFontColor;\r\n }\r\n\r\n public set fontColor(value: string) {\r\n this.textFontColor = value;\r\n this.containerElement.style.color = value;\r\n }\r\n\r\n public set scrollbarWidth(value: number) {\r\n this.scrollBarElementWidth = value;\r\n this.rowDim.scrollbar.width = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\r\n this.columnDim.scrollbar.height = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\r\n }\r\n\r\n public updateModels(resetScrollOffsets: boolean, rowModel: any, columnModel: any): void {\r\n this.rowDim.model = rowModel;\r\n this.rowDim.modelDepth = this.hierarchyNavigator.getRowHierarchyDepth();\r\n this.columnDim.model = columnModel;\r\n this.columnDim.modelDepth = this.hierarchyNavigator.getColumnHierarchyDepth();\r\n\r\n if (resetScrollOffsets) {\r\n this.rowDim.scrollOffset = 0;\r\n this.columnDim.scrollOffset = 0;\r\n }\r\n\r\n this.layoutManager.updateColumnCount(this.rowDim, this.columnDim);\r\n }\r\n\r\n public updateColumnDimensions(rowHierarchyWidth: number, columnHierarchyWidth: number, count: number) {\r\n let gridDimensions = this.gridDimensions;\r\n\r\n gridDimensions.columnCount = count;\r\n gridDimensions.rowHierarchyWidth = rowHierarchyWidth;\r\n gridDimensions.columnHierarchyWidth = columnHierarchyWidth;\r\n }\r\n\r\n public updateRowDimensions(columnHierarchyHeight: number, rowHierarchyHeight: number, rowHierarchyContentHeight: number, count: number, footerHeight) {\r\n let gridDimensions = this.gridDimensions;\r\n\r\n gridDimensions.rowCount = count;\r\n gridDimensions.rowHierarchyHeight = rowHierarchyHeight;\r\n gridDimensions.rowHierarchyContentHeight = rowHierarchyContentHeight;\r\n gridDimensions.columnHierarchyHeight = columnHierarchyHeight;\r\n gridDimensions.footerHeight = footerHeight;\r\n }\r\n\r\n private updateTouchDimensions(): void {\r\n let gridDimensions = this.gridDimensions;\r\n\r\n this.columnTouchDelegate.resize(gridDimensions.rowHierarchyWidth, 0, gridDimensions.columnHierarchyWidth, gridDimensions.columnHierarchyHeight);\r\n this.columnTouchDelegate.setScrollDensity(gridDimensions.columnCount / gridDimensions.columnHierarchyWidth);\r\n\r\n this.rowTouchDelegate.resize(0, gridDimensions.columnHierarchyHeight, gridDimensions.rowHierarchyWidth, gridDimensions.rowHierarchyHeight);\r\n this.rowTouchDelegate.setScrollDensity(gridDimensions.rowCount / gridDimensions.rowHierarchyHeight);\r\n\r\n this.bodyTouchDelegate.resize(gridDimensions.rowHierarchyWidth, gridDimensions.columnHierarchyHeight,\r\n gridDimensions.columnHierarchyWidth, gridDimensions.rowHierarchyHeight);\r\n this.bodyTouchDelegate.setScrollDensity(gridDimensions.columnCount / gridDimensions.columnHierarchyWidth,\r\n gridDimensions.rowCount / gridDimensions.rowHierarchyHeight);\r\n\r\n this.footerTouchDelegate.resize(gridDimensions.rowHierarchyWidth, gridDimensions.columnHierarchyHeight + gridDimensions.rowHierarchyHeight, gridDimensions.columnHierarchyWidth, gridDimensions.footerHeight);\r\n this.footerTouchDelegate.setScrollDensity(gridDimensions.columnCount / gridDimensions.columnHierarchyWidth);\r\n }\r\n\r\n private onMouseWheel(e: MouseWheelEvent): void {\r\n let dimension = this.determineDimensionToScroll();\r\n if (dimension)\r\n dimension.scrollbar.onMouseWheel(e);\r\n }\r\n\r\n private onFireFoxMouseWheel(e: MouseWheelEvent): void {\r\n let dimension = this.determineDimensionToScroll();\r\n if (dimension)\r\n dimension.scrollbar.onFireFoxMouseWheel(e);\r\n }\r\n\r\n private determineDimensionToScroll(): TablixDimension {\r\n if (this.rowDim.scrollbar.visible)\r\n return this.rowDim;\r\n\r\n // In the absence of the vertical scrollbar, we scroll the\r\n // horizontal scrollbar.\r\n if (this.columnDim.scrollbar.visible)\r\n return this.columnDim;\r\n\r\n return null;\r\n }\r\n\r\n public get layoutManager(): internal.TablixLayoutManager {\r\n return this.controlLayoutManager;\r\n }\r\n\r\n public get columnDimension(): TablixColumnDimension {\r\n return this.columnDim;\r\n }\r\n\r\n public get rowDimension(): TablixRowDimension {\r\n return this.rowDim;\r\n }\r\n\r\n public refresh(clear: boolean): void {\r\n this.render(clear, null);\r\n }\r\n\r\n public _onScrollAsync(dimension: TablixDimension): void { // The intent is to be internal\r\n requestAnimationFrame(() => { this.performPendingScroll(dimension); });\r\n }\r\n\r\n private performPendingScroll(dimension: TablixDimension): void {\r\n this.render(false, dimension);\r\n }\r\n\r\n private updateHorizontalPosition(): void {\r\n if (this.rowDim.scrollbar.visible) {\r\n this.columnDim.scrollbar.element.style.right = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\r\n this.footerDiv.style.right = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\r\n this.mainDiv.style.right = this.scrollBarElementWidth + TablixControl.UnitOfMeasurement;\r\n } else {\r\n this.columnDim.scrollbar.element.style.right = \"0\" + TablixControl.UnitOfMeasurement;\r\n this.mainDiv.style.right = \"0\" + TablixControl.UnitOfMeasurement;\r\n this.footerDiv.style.right = \"0\" + TablixControl.UnitOfMeasurement;\r\n }\r\n }\r\n\r\n public updateFooterVisibility() {\r\n if (this.rowDim.hasFooter() ? (this.footerDiv.style.display !== \"block\") : (this.footerDiv.style.display !== \"none\")) {\r\n if (this.rowDim.hasFooter()) {\r\n this.footerDiv.style.display = \"block\";\r\n } else {\r\n this.footerDiv.style.display = \"none\";\r\n }\r\n }\r\n }\r\n\r\n private updateVerticalPosition(): void {\r\n\r\n let hasVerticalScrollbar = this.rowDim.scrollbar.visible;\r\n // TODO: ideally the tablix control would not know about where it is rendered but the layout manager\r\n // would provider that information; we should refactor the layout manager so that getLayoutKind is not needed anymore.\r\n let isDashboardTile = this.controlLayoutManager.getLayoutKind() === TablixLayoutKind.DashboardTile;\r\n let showFooter = hasVerticalScrollbar || isDashboardTile;\r\n if (showFooter) {\r\n let mainBottom = this.footerDiv.offsetHeight;\r\n let footerBottom = 0;\r\n let verticalScrollbarBottom = 0;\r\n\r\n // If we have a horizontal scrollbar, we need to adjust the bottom\r\n // value by the scrollbar width\r\n let hasHorizontalScrollbar = this.columnDim.scrollbar.visible;\r\n if (hasHorizontalScrollbar) {\r\n mainBottom += this.scrollBarElementWidth;\r\n footerBottom += this.scrollBarElementWidth;\r\n verticalScrollbarBottom = this.scrollBarElementWidth;\r\n }\r\n\r\n this.mainDiv.style.bottom = mainBottom + TablixControl.UnitOfMeasurement;\r\n this.rowDim.scrollbar.element.style.bottom = verticalScrollbarBottom + TablixControl.UnitOfMeasurement;\r\n this.footerDiv.style.bottom = footerBottom + TablixControl.UnitOfMeasurement;\r\n\r\n // With a vertical scrollbar, the footer is always rendered at the bottom\r\n this.footerDiv.style.removeProperty(\"top\");\r\n }\r\n else {\r\n // Without a vertical scrollbar, the footer is rendered below the last row;\r\n // this is controlled by the top value only\r\n this.footerDiv.style.top = this.gridDimensions.rowHierarchyContentHeight + TablixControl.UnitOfMeasurement;\r\n this.footerDiv.style.removeProperty(\"bottom\");\r\n this.mainDiv.style.removeProperty(\"bottom\");\r\n }\r\n }\r\n\r\n private alreadyRendered(scrollingDimension: TablixDimension): boolean {\r\n if (scrollingDimension !== this.lastRenderingArgs.scrollingDimension ||\r\n this.rowDimension.scrollOffset !== this.lastRenderingArgs.rowScrollOffset ||\r\n this.columnDimension.scrollOffset !== this.lastRenderingArgs.columnScrollOffset) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private render(clear: boolean, scrollingDimension: TablixDimension): void {\r\n // at time of rendering always ensure the scroll offset is valid\r\n this.columnDim.makeScrollOffsetValid();\r\n this.rowDim.makeScrollOffsetValid();\r\n\r\n if (clear || scrollingDimension === null) {\r\n this.lastRenderingArgs = {};\r\n } else if (this.alreadyRendered(scrollingDimension)) {\r\n return;\r\n }\r\n\r\n let done = false;\r\n this.renderIterationCount = 0;\r\n\r\n this.controlLayoutManager.onStartRenderingSession(scrollingDimension, this.mainDiv, clear);\r\n let binder: ITablixBinder = this.binder;\r\n binder.onStartRenderingSession();\r\n\r\n let priorFooterHeight: number = this.gridDimensions.footerHeight;\r\n let priorRowHierarchyHeight: number = this.gridDimensions.rowHierarchyHeight;\r\n let priorRowHierarchyContentHeight: number = this.gridDimensions.rowHierarchyContentHeight;\r\n\r\n while (!done && this.renderIterationCount < TablixControl.MaxRenderIterationCount) {\r\n let hScrollbarVisibility = this.columnDim.scrollbar.visible;\r\n let vScrollbarVisibility = this.rowDim.scrollbar.visible;\r\n\r\n this.columnDim._onStartRenderingIteration();\r\n this.rowDim._onStartRenderingIteration();\r\n this.controlLayoutManager.onStartRenderingIteration(clear);\r\n\r\n // These calls add cells to the table.\r\n // Column needs to be rendered before rows as the row call will pair up with columns to produce the body cells.\r\n this.renderCorner();\r\n this.columnDim._render();\r\n this.rowDim._render();\r\n\r\n done = this.controlLayoutManager.onEndRenderingIteration();\r\n this.columnDim._onEndRenderingIteration();\r\n this.rowDim._onEndRenderingIteration();\r\n\r\n if ((hScrollbarVisibility !== this.columnDim.scrollbar.visible)) {\r\n this.updateVerticalPosition();\r\n }\r\n if (vScrollbarVisibility !== this.rowDim.scrollbar.visible) {\r\n this.updateHorizontalPosition();\r\n }\r\n\r\n this.renderIterationCount++;\r\n }\r\n\r\n this.controlLayoutManager.onEndRenderingSession();\r\n binder.onEndRenderingSession();\r\n\r\n if (this.isTouchEnabled)\r\n this.updateTouchDimensions();\r\n\r\n this.lastRenderingArgs.rowScrollOffset = this.rowDimension.scrollOffset;\r\n this.lastRenderingArgs.columnScrollOffset = this.columnDimension.scrollOffset;\r\n\r\n this.updateContainerDimensions();\r\n\r\n let lastRenderingArgs = this.lastRenderingArgs;\r\n lastRenderingArgs.rowScrollOffset = this.rowDimension.scrollOffset;\r\n lastRenderingArgs.columnScrollOffset = this.columnDimension.scrollOffset;\r\n lastRenderingArgs.scrollingDimension = scrollingDimension;\r\n\r\n if (priorFooterHeight !== this.gridDimensions.footerHeight ||\r\n priorRowHierarchyHeight !== this.gridDimensions.rowHierarchyHeight ||\r\n priorRowHierarchyContentHeight !== this.gridDimensions.rowHierarchyContentHeight) {\r\n this.updateVerticalPosition();\r\n }\r\n\r\n // NOTE: it is critical that we refresh the scrollbars only after the vertical\r\n // position was updated above; otherwise the measurements can be incorrect.\r\n if (this.options.interactive) {\r\n this.columnDim.scrollbar.refresh();\r\n this.rowDim.scrollbar.refresh();\r\n }\r\n }\r\n\r\n private updateContainerDimensions(): void {\r\n let gridDimensions = this.gridDimensions;\r\n\r\n if (this._autoSizeWidth) {\r\n let vScrollBarWidth: number = this.rowDim.scrollbar.visible ? this.scrollBarElementWidth : 0;\r\n this.containerElement.style.width =\r\n gridDimensions.rowHierarchyWidth +\r\n gridDimensions.columnHierarchyWidth +\r\n vScrollBarWidth +\r\n TablixControl.UnitOfMeasurement;\r\n }\r\n\r\n if (this._autoSizeHeight) {\r\n let hScrollBarHeight: number = this.columnDim.scrollbar.visible ? this.scrollBarElementWidth : 0;\r\n this.containerElement.style.height =\r\n gridDimensions.columnHierarchyHeight +\r\n gridDimensions.rowHierarchyHeight +\r\n gridDimensions.footerHeight +\r\n hScrollBarHeight +\r\n TablixControl.UnitOfMeasurement;\r\n }\r\n }\r\n\r\n private cornerCellMatch(item: any, cell: ITablixCell): boolean {\r\n let previousItem: any = cell.item;\r\n return cell.type === TablixCellType.CornerCell && previousItem && this.hierarchyTablixNavigator.cornerCellItemEquals(item, previousItem);\r\n }\r\n\r\n private renderCorner(): void {\r\n let columnDepth: number = this.columnDim.getDepth();\r\n let rowDepth: number = this.rowDim.getDepth();\r\n\r\n for (let i = 0; i < columnDepth; i++) {\r\n for (let j = 0; j < rowDepth; j++) {\r\n let item = this.hierarchyTablixNavigator.getCorner(j, i);\r\n let cell: ITablixCell = this.controlLayoutManager.getOrCreateCornerCell(item, j, i);\r\n let match = this.cornerCellMatch(item, cell);\r\n if (!match) {\r\n this._unbindCell(cell);\r\n cell.type = TablixCellType.CornerCell;\r\n cell.item = item;\r\n\r\n this.binder.bindCornerCell(item, cell);\r\n }\r\n this.controlLayoutManager.onCornerCellRealized(item, cell);\r\n }\r\n }\r\n }\r\n\r\n public _unbindCell(cell: ITablixCell): void { // The intent is to be internal\r\n switch (cell.type) {\r\n case TablixCellType.BodyCell:\r\n this.binder.unbindBodyCell(cell.item, cell);\r\n break;\r\n case TablixCellType.ColumnHeader:\r\n this.binder.unbindColumnHeader(cell.item, cell);\r\n break;\r\n case TablixCellType.RowHeader:\r\n this.binder.unbindRowHeader(cell.item, cell);\r\n break;\r\n case TablixCellType.CornerCell:\r\n this.binder.unbindCornerCell(cell.item, cell);\r\n }\r\n\r\n cell.item = null;\r\n cell.type = null;\r\n }\r\n\r\n private onTouchEvent(args: any[]): void {\r\n let colShift: number;\r\n let rowShift: number;\r\n let that: TablixControl;\r\n\r\n if ((args) && (args.length > 0)) {\r\n if ((\"columnDim\" in args[0]) && (\"rowDim\" in args[0])) {\r\n that = <TablixControl>args[0];\r\n colShift = that.columnDim.scrollbar.visible ? <number>args[1] : 0;\r\n rowShift = that.rowDim.scrollbar.visible ? <number>args[2] : 0;\r\n\r\n that.columnDim.scrollbar.viewMin = Math.max(0, that.columnDim.scrollbar.viewMin + colShift);\r\n that.columnDim.scrollOffset = Math.max(0, that.columnDim.scrollOffset + colShift);\r\n that.rowDim.scrollbar.viewMin = Math.max(0, that.rowDim.scrollbar.viewMin + rowShift);\r\n that.rowDim.scrollOffset = Math.max(0, that.rowDim.scrollOffset + rowShift);\r\n\r\n if (colShift === 0) {\r\n that._onScrollAsync(that.rowDim);\r\n } else if (rowShift === 0) {\r\n that._onScrollAsync(that.columnDim);\r\n } else {\r\n that._onScrollAsync(null);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls {\r\n\r\n export class TablixDimension {\r\n public _hierarchyNavigator: ITablixHierarchyNavigator;\r\n public _otherDimension; // internal\r\n\r\n public _owner: TablixControl; // protected\r\n public _binder: ITablixBinder; // protected\r\n public _tablixLayoutManager: internal.TablixLayoutManager; // protected\r\n public _layoutManager: IDimensionLayoutManager; // protected\r\n\r\n public model: any;\r\n public modelDepth: number;\r\n\r\n public scrollOffset: number;\r\n private _scrollStep: number = 0.1;\r\n\r\n private _firstVisibleScrollIndex: number;\r\n private _scrollbar: Scrollbar;\r\n public _scrollItems: any[]; // protected\r\n\r\n constructor(tablixControl: TablixControl) {\r\n this._owner = tablixControl;\r\n this._hierarchyNavigator = tablixControl.hierarchyNavigator;\r\n this._binder = tablixControl.getBinder();\r\n this._tablixLayoutManager = tablixControl.layoutManager;\r\n this.scrollOffset = 0;\r\n }\r\n\r\n public _onStartRenderingIteration(): void { // The intent to be internal\r\n this.updateScrollPosition();\r\n }\r\n\r\n public _onEndRenderingIteration(): void { // The intent to be internal\r\n }\r\n\r\n public getValidScrollOffset(scrollOffset: number): number {\r\n return Math.min(Math.max(scrollOffset, 0), Math.max(this.getItemsCount() - this._scrollStep, 0));\r\n }\r\n\r\n public makeScrollOffsetValid(): void {\r\n this.scrollOffset = this.getValidScrollOffset(this.scrollOffset);\r\n }\r\n\r\n public getIntegerScrollOffset(): number {\r\n return Math.floor(this.scrollOffset);\r\n }\r\n\r\n public getFractionScrollOffset(): number {\r\n return this.scrollOffset - this.getIntegerScrollOffset();\r\n }\r\n\r\n public get scrollbar(): Scrollbar {\r\n return this._scrollbar;\r\n }\r\n\r\n public getFirstVisibleItem(level: number): any {\r\n return this._scrollItems[level];\r\n }\r\n\r\n public getFirstVisibleChild(item: any): any {\r\n return this._hierarchyNavigator.getAt(this._hierarchyNavigator.getChildren(item), this.getFirstVisibleChildIndex(item));\r\n }\r\n\r\n public getFirstVisibleChildIndex(item: any): number {\r\n let startItem: any = this.getFirstVisibleItem(this._hierarchyNavigator.getLevel(item) + 1);\r\n let firstVisibleIndex: number;\r\n\r\n if (startItem === undefined || (startItem !== undefined && this._hierarchyNavigator.getParent(startItem) !== item)) {\r\n firstVisibleIndex = 0;\r\n } else {\r\n firstVisibleIndex = this._hierarchyNavigator.getIndex(startItem);\r\n }\r\n return firstVisibleIndex;\r\n }\r\n\r\n public _initializeScrollbar(parentElement: HTMLElement, touchDiv: HTMLDivElement, layoutKind: TablixLayoutKind) { // The intent to be internal\r\n this._scrollbar = this._createScrollbar(parentElement, layoutKind);\r\n this._scrollbar._onscroll.push((e) => this.onScroll());\r\n\r\n if (touchDiv) {\r\n this.scrollbar.initTouch(touchDiv, true);\r\n touchDiv.style.setProperty(\"-ms-touch-action\", \"pinch-zoom\");\r\n }\r\n }\r\n\r\n public getItemsCount(): number {\r\n return this.model ? this._hierarchyNavigator.getLeafCount(this.model) : 0;\r\n }\r\n\r\n public getDepth(): number {\r\n return this.modelDepth;\r\n }\r\n\r\n private onScroll() {\r\n this.scrollOffset = this._scrollbar.viewMin;\r\n this._owner._onScrollAsync(this);\r\n }\r\n\r\n public get otherDimension(): TablixDimension {\r\n return this._otherDimension;\r\n }\r\n\r\n public get layoutManager(): IDimensionLayoutManager {\r\n return this._layoutManager;\r\n }\r\n\r\n public _createScrollbar(parentElement: HTMLElement, layoutKind: TablixLayoutKind): Scrollbar {\r\n // abstract\r\n debug.assertFail(\"PureVirtualMethod: TablixDimension._createScrollbar\");\r\n return null;\r\n }\r\n\r\n private updateScrollPosition(): void {\r\n this._scrollItems = [];\r\n\r\n if (!this.model) {\r\n return;\r\n }\r\n\r\n let firstVisibleScrollIndex: number = this.getIntegerScrollOffset();\r\n let firstVisible: any = this._hierarchyNavigator.getLeafAt(this.model, firstVisibleScrollIndex);\r\n if (!firstVisible) {\r\n return;\r\n }\r\n\r\n this._firstVisibleScrollIndex = firstVisibleScrollIndex;\r\n\r\n do {\r\n this._scrollItems[this._hierarchyNavigator.getLevel(firstVisible)] = firstVisible;\r\n firstVisible = this._hierarchyNavigator.getParent(firstVisible);\r\n } while (firstVisible !== null);\r\n }\r\n }\r\n\r\n export class TablixRowDimension extends TablixDimension {\r\n private _footer: any;\r\n\r\n constructor(tablixControl: TablixControl) {\r\n super(tablixControl);\r\n this._layoutManager = this._tablixLayoutManager.rowLayoutManager;\r\n this._footer = null;\r\n }\r\n\r\n public setFooter(footerHeader: any): void {\r\n this._footer = footerHeader;\r\n this._owner.updateFooterVisibility();\r\n }\r\n\r\n public hasFooter(): boolean {\r\n return (this._footer !== null);\r\n }\r\n\r\n /**\r\n * This method first populates the footer followed by each row and their correlating body cells from top to bottom.\r\n */\r\n public _render() { // The intent to be internal\r\n let firstVisibleRowItem: any = this.getFirstVisibleItem(0);\r\n\r\n if (this.hasFooter()) {\r\n this.addFooterRowHeader(this._footer);\r\n this.addFooterBodyCells(this._footer);\r\n }\r\n\r\n if (firstVisibleRowItem !== undefined) {\r\n this.addNodes(this.model, 0, this.getDepth(), this._hierarchyNavigator.getIndex(firstVisibleRowItem));\r\n }\r\n }\r\n\r\n public _createScrollbar(parentElement: HTMLElement, layoutKind: TablixLayoutKind): Scrollbar {\r\n return new VerticalScrollbar(parentElement, layoutKind);\r\n }\r\n\r\n /**\r\n * This function is a recursive call (with its recursive behavior in addNode()) that will navigate\r\n * through the row hierarchy in DFS (Depth First Search) order and continue into a single row\r\n * upto its estimated edge.\r\n */\r\n private addNodes(items: any, rowIndex: number, depth: number, firstVisibleIndex: number) {\r\n let count = this._hierarchyNavigator.getCount(items);\r\n\r\n //for loop explores children of current \"items\"\r\n for (let i = firstVisibleIndex; i < count; i++) {\r\n if (!this._layoutManager.needsToRealize) {\r\n return;\r\n }\r\n\r\n let item = this._hierarchyNavigator.getAt(items, i);\r\n let cell = this.addNode(item, items, rowIndex, depth);\r\n rowIndex += cell.rowSpan; //next node is bumped down according cells vertical span\r\n }\r\n }\r\n\r\n public getFirstVisibleChildLeaf(item: any): any {\r\n let leaf = item;\r\n\r\n while (!this._hierarchyNavigator.isLeaf(leaf)) {\r\n leaf = this.getFirstVisibleChild(leaf);\r\n }\r\n\r\n return leaf;\r\n }\r\n\r\n private bindRowHeader(item: any, cell: ITablixCell) {\r\n this._binder.bindRowHeader(item, cell);\r\n }\r\n\r\n /**\r\n * This method can be thought of as the continuation of addNodes() as it continues the DFS (Depth First Search)\r\n * started from addNodes(). This function also handles ending the recursion with \"_needsToRealize\" being set to \r\n * false.\r\n *\r\n * Once the body cells are reached, populating is done linearly with addBodyCells().\r\n */\r\n private addNode(item: any, items: any, rowIndex: number, depth: number): ITablixCell {\r\n let previousCount: number;\r\n let rowHeaderCell: ITablixCell = this._tablixLayoutManager.getOrCreateRowHeader(item, items, rowIndex, this._hierarchyNavigator.getLevel(item));\r\n let match = this.rowHeaderMatch(item, rowHeaderCell);\r\n\r\n if (!match) {\r\n this._owner._unbindCell(rowHeaderCell);\r\n rowHeaderCell.type = TablixCellType.RowHeader;\r\n rowHeaderCell.item = item;\r\n rowHeaderCell.unfixRowHeight();\r\n }\r\n\r\n if (this._hierarchyNavigator.isLeaf(item)) {\r\n rowHeaderCell.colSpan = depth - this._hierarchyNavigator.getLevel(item);\r\n rowHeaderCell.rowSpan = 1;\r\n if (!match)\r\n this.bindRowHeader(item, rowHeaderCell);\r\n\r\n this._tablixLayoutManager.onRowHeaderRealized(item, rowHeaderCell);\r\n this.addBodyCells(item, items, rowIndex);\r\n } else {\r\n previousCount = this._layoutManager.getRealizedItemsCount();\r\n this.addNodes(this._hierarchyNavigator.getChildren(item), rowIndex, depth, this.getFirstVisibleChildIndex(item));\r\n rowHeaderCell.colSpan = 1;\r\n rowHeaderCell.rowSpan = this._layoutManager.getRealizedItemsCount() - previousCount + 1;\r\n if (!match)\r\n this.bindRowHeader(item, rowHeaderCell);\r\n this._tablixLayoutManager.onRowHeaderRealized(item, rowHeaderCell);\r\n } \r\n\r\n return rowHeaderCell;\r\n }\r\n\r\n private rowHeaderMatch(item: any, cell: ITablixCell): boolean {\r\n let previousItem = cell.item;\r\n return cell.type === TablixCellType.RowHeader && previousItem && this._hierarchyNavigator.headerItemEquals(item, previousItem);\r\n }\r\n\r\n private addBodyCells(item: any, items: any, rowIndex: number) {\r\n let firstVisibleColumnIndex: number = this._otherDimension.getIntegerScrollOffset();\r\n let columnCount: number = this._otherDimension._layoutManager.getRealizedItemsCount() - this.getDepth();\r\n let hierarchyNavigator = this._hierarchyNavigator;\r\n let otherModel = this._otherDimension.model;\r\n let layoutManager = this._tablixLayoutManager;\r\n\r\n for (let i = 0; i < columnCount; i++) {\r\n //get column header \"item\" by index to pair up with row header to find corelating body cell\r\n let cellItem: any = hierarchyNavigator.getIntersection(item, hierarchyNavigator.getLeafAt(otherModel, firstVisibleColumnIndex + i));\r\n let cell: ITablixCell = layoutManager.getOrCreateBodyCell(cellItem, item, items, rowIndex, i);\r\n this.bindBodyCell(cellItem, cell);\r\n layoutManager.onBodyCellRealized(cellItem, cell);\r\n }\r\n }\r\n\r\n private bindBodyCell(item: any, cell: ITablixCell): void {\r\n let match = this.bodyCelMatch(item, cell);\r\n if (!match) {\r\n this._owner._unbindCell(cell);\r\n cell.type = TablixCellType.BodyCell;\r\n cell.item = item;\r\n cell.unfixRowHeight();\r\n this._binder.bindBodyCell(item, cell);\r\n }\r\n }\r\n\r\n private addFooterRowHeader(item: any) {\r\n let cell: ITablixCell = this._tablixLayoutManager.getOrCreateFooterRowHeader(item, this.model);\r\n cell.colSpan = this.getDepth();\r\n let match = this.rowHeaderMatch(item, cell);\r\n if (!match) {\r\n this._owner._unbindCell(cell);\r\n cell.type = TablixCellType.RowHeader;\r\n cell.item = item;\r\n cell.unfixRowHeight();\r\n this.bindRowHeader(item, cell);\r\n this._tablixLayoutManager.onRowHeaderFooterRealized(item, cell);\r\n }\r\n }\r\n\r\n private addFooterBodyCells(rowItem: any) {\r\n let firstVisibleColumnIndex: number = this._otherDimension.getIntegerScrollOffset();\r\n let columnCount: number = this._otherDimension.layoutManager.getRealizedItemsCount() - this.getDepth();\r\n let layoutManager = this._tablixLayoutManager;\r\n\r\n for (let i = 0; i < columnCount; i++) {\r\n //get column header \"item\" by index to pair up with row header to find corelating body cell\r\n let columnItem: any = this._hierarchyNavigator.getLeafAt(this._otherDimension.model, firstVisibleColumnIndex + i);\r\n //get corelating body cell and bind it\r\n let item: any = this._hierarchyNavigator.getIntersection(rowItem, columnItem);\r\n let cell: ITablixCell = layoutManager.getOrCreateFooterBodyCell(item, i);\r\n this.bindBodyCell(item, cell);\r\n layoutManager.onBodyCellFooterRealized(item, cell);\r\n }\r\n }\r\n\r\n private bodyCelMatch(item: any, cell: ITablixCell): boolean {\r\n let previousItem: any = cell.item;\r\n return cell.type === TablixCellType.BodyCell && previousItem && this._hierarchyNavigator.bodyCellItemEquals(item, previousItem);\r\n }\r\n }\r\n\r\n export class TablixColumnDimension extends TablixDimension {\r\n constructor(tablixControl: TablixControl) {\r\n super(tablixControl);\r\n this._layoutManager = this._tablixLayoutManager.columnLayoutManager;\r\n }\r\n\r\n public _render(): void { // The intent to be internal\r\n let firstVisibleColumnItem: any = this.getFirstVisibleItem(0);\r\n\r\n if (firstVisibleColumnItem !== undefined) {\r\n this.addNodes(this.model, 0, this.getDepth(), this._hierarchyNavigator.getIndex(firstVisibleColumnItem));\r\n }\r\n }\r\n\r\n public _createScrollbar(parentElement: HTMLElement, layoutKind: TablixLayoutKind): Scrollbar {\r\n let scrollbar: HorizontalScrollbar = new HorizontalScrollbar(parentElement, layoutKind);\r\n\r\n // Set smallest increment of the scrollbar to 0.2 rows\r\n scrollbar.smallIncrement = 0.2;\r\n\r\n return scrollbar;\r\n }\r\n\r\n private addNodes(items: any, columnIndex: number, depth: number, firstVisibleIndex: number): void {\r\n let count = this._hierarchyNavigator.getCount(items);\r\n for (let i = firstVisibleIndex; i < count; i++) {\r\n if (!this._layoutManager.needsToRealize) {\r\n return;\r\n }\r\n let cell: ITablixCell = this.addNode(this._hierarchyNavigator.getAt(items, i), items, columnIndex, depth);\r\n columnIndex += cell.colSpan;\r\n }\r\n }\r\n\r\n private addNode(item: any, items: any, columnIndex: number, depth: number) {\r\n let cell: ITablixCell = this._tablixLayoutManager.getOrCreateColumnHeader(item, items, this._hierarchyNavigator.getLevel(item), columnIndex);\r\n\r\n let match = this.columnHeaderMatch(item, cell);\r\n\r\n if (!match) {\r\n this._owner._unbindCell(cell);\r\n cell.type = TablixCellType.ColumnHeader;\r\n cell.item = item;\r\n cell.unfixRowHeight();\r\n }\r\n\r\n if (this._hierarchyNavigator.isLeaf(item)) {\r\n cell.rowSpan = depth - this._hierarchyNavigator.getLevel(item);\r\n }\r\n else {\r\n let previousCount: number = this._layoutManager.getRealizedItemsCount();\r\n this.addNodes(this._hierarchyNavigator.getChildren(item), columnIndex, depth, this.getFirstVisibleChildIndex(item));\r\n\r\n // In case we have a grand total with multiple measures, the multi-measures will be direct children\r\n // There can be difference in level > 1. In this case, we want the Total cell to have rowspan = the difference\r\n let childrenLevelDifference = this._hierarchyNavigator.getChildrenLevelDifference(item);\r\n if (childrenLevelDifference === Infinity) // No Children\r\n cell.rowSpan = 1;\r\n else\r\n cell.rowSpan = childrenLevelDifference;\r\n cell.colSpan = this._layoutManager.getRealizedItemsCount() - previousCount + 1;\r\n }\r\n\r\n if (!match)\r\n this._binder.bindColumnHeader(item, cell);\r\n \r\n this._tablixLayoutManager.onColumnHeaderRealized(item, cell);\r\n return cell;\r\n }\r\n\r\n public columnHeaderMatch(item: any, cell: ITablixCell): boolean {\r\n let previousItem: any = cell.item;\r\n return cell.type === TablixCellType.ColumnHeader && previousItem && this._hierarchyNavigator.headerItemEquals(item, previousItem);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls {\r\n\r\n /**\r\n * This class represents the touch region of the column headers (this can also apply to footer/total).\r\n * This class is reponsible for interpreting gestures in terms of pixels to changes in column position.\r\n *\r\n * Unlike the table body, this can only scroll in one direction. \r\n */\r\n export class ColumnTouchDelegate implements TouchUtils.ITouchHandler, TouchUtils.IPixelToItem {\r\n\r\n /** \r\n * Used to termine if the touch event is within bounds.\r\n */\r\n private dim: TouchUtils.Rectangle;\r\n /**\r\n * Average pixel width of columns in table.\r\n */\r\n private averageSize: number;\r\n /**\r\n * Used for 'firing' a scroll event following a received gesture.\r\n */\r\n private tablixControl: TablixControl;\r\n /**\r\n * Stores the event handler of TablixControl for scroll events.\r\n */\r\n private handlers: any;\r\n\r\n /**\r\n * @constructor \r\n * @param region Location and area of the touch region in respect to its HTML element.\r\n */\r\n constructor(region: TouchUtils.Rectangle) {\r\n this.dim = region;\r\n this.averageSize = 1; //default\r\n this.handlers = null;\r\n this.tablixControl = null;\r\n }\r\n\r\n get dimension(): TouchUtils.Rectangle {\r\n return this.dim;\r\n }\r\n\r\n /** \r\n * Sets the amount of columns to be shifted per delta in pixels.\r\n *\r\n * @param xRatio Column to pixel ratio (# columns / # pixels).\r\n */\r\n public setScrollDensity(xRatio: number): void {\r\n this.averageSize = xRatio;\r\n }\r\n\r\n /**\r\n * Resize element.\r\n * \r\n * @param x X location from upper left of listened HTML element.\r\n * @param y Y location from upper left of listened HTML element.\r\n * @param width Width of area to listen for events.\r\n * @param height Height of area to listen for events.\r\n */\r\n public resize(x: number, y: number, width: number, height: number) {\r\n this.dim.x = x;\r\n this.dim.y = y;\r\n this.dim.width = width;\r\n this.dim.height = height;\r\n }\r\n\r\n /**\r\n * @see IPixelToItem.\r\n */\r\n public getPixelToItem(x: number, y: number, dx: number, dy: number, down: boolean): TouchUtils.TouchEvent {\r\n return new TouchUtils.TouchEvent(x * this.averageSize, 0, down, -dx * this.averageSize, 0);\r\n }\r\n\r\n /**\r\n * Fires event to Tablix Control to scroll with the event passed from the TouchManager.\r\n *\r\n * @param e Event recieved from touch manager.\r\n */\r\n public touchEvent(e: TouchUtils.TouchEvent): void {\r\n let args: any[] = [];\r\n\r\n args[0] = this.tablixControl;\r\n args[1] = e.dx;\r\n args[2] = e.dy;\r\n\r\n if (this.handlers) {\r\n fire([this.handlers], args);\r\n }\r\n }\r\n\r\n /**\r\n * Asigns handler for scrolling when scroll event is fired.\r\n *\r\n * @param tablixObj TablixControl that's handling the fired event.\r\n * @param handlerCall The call to be made (EXAMPLE: handlerCall = object.method;).\r\n */\r\n public setHandler(tablixObj: TablixControl, handlerCall: (args: any[]) => void): void {\r\n this.handlers = handlerCall;\r\n this.tablixControl = tablixObj;\r\n }\r\n }\r\n\r\n /**\r\n * This class represents the touch region of the row headers (left or right side aligned).\r\n * This class is reponsible for interpreting gestures in terms of pixels to changes in row position.\r\n *\r\n * Unlike the table body, this can only scroll in one direction. \r\n */\r\n export class RowTouchDelegate implements TouchUtils.ITouchHandler, TouchUtils.IPixelToItem {\r\n /**\r\n * Used to termine if the touch event is within bounds.\r\n */\r\n private dim: TouchUtils.Rectangle;\r\n \r\n /**\r\n * Average pixel height of rows in table.\r\n */\r\n private averageSize: number;\r\n \r\n /**\r\n * Used for 'firing' a scroll event following a recieved gesture.\r\n */\r\n private tablixControl: TablixControl;\r\n \r\n /**\r\n * Stores the event handler of TablixControl for scroll events.\r\n */\r\n private handlers: any;\r\n\r\n /**\r\n * @constructor\r\n * @param region Location and area of the touch region in respect to its HTML element.\r\n */\r\n constructor(region: TouchUtils.Rectangle) {\r\n this.dim = region;\r\n this.averageSize = 30; //default\r\n this.handlers = null;\r\n this.tablixControl = null;\r\n }\r\n\r\n get dimension(): TouchUtils.Rectangle {\r\n return this.dim;\r\n }\r\n\r\n /**\r\n * Sets the amount of rows to be shifted per delta in pixels.\r\n *\r\n * @param yRatio Row to pixel ratio (# rows / # pixels).\r\n */\r\n public setScrollDensity(yRatio: number): void {\r\n this.averageSize = yRatio;\r\n }\r\n\r\n /**\r\n * Resize element.\r\n * @param x X location from upper left of listened HTML element.\r\n * @param y Y location from upper left of listened HTML element.\r\n * @param width Width of area to listen for events.\r\n * @param height Height of area to listen for events.\r\n */\r\n public resize(x: number, y: number, width: number, height: number) {\r\n this.dim.x = x;\r\n this.dim.y = y;\r\n this.dim.width = width;\r\n this.dim.height = height;\r\n }\r\n\r\n /**\r\n * @see: IPixelToItem\r\n */\r\n public getPixelToItem(x: number, y: number, dx: number, dy: number, down: boolean): TouchUtils.TouchEvent {\r\n let event: TouchUtils.TouchEvent = new TouchUtils.TouchEvent(0, y * this.averageSize, down,\r\n 0, -dy * this.averageSize);\r\n return event;\r\n }\r\n\r\n /**\r\n * Fires event to Tablix Control to scroll with the event passed from the TouchManager.\r\n *\r\n * @param e Event recieved from touch manager.\r\n */\r\n public touchEvent(e: TouchUtils.TouchEvent): void {\r\n let args: any[] = [];\r\n\r\n args[0] = this.tablixControl;\r\n args[1] = e.dx;\r\n args[2] = e.dy;\r\n\r\n if (this.handlers) {\r\n fire([this.handlers], args);\r\n }\r\n }\r\n\r\n /**\r\n * Asigns handler for scrolling when scroll event is fired.\r\n *\r\n * @param tablixObj TablixControl that's handling the fired event.\r\n * @param handlerCall The call to be made (EXAMPLE: handlerCall = object.method;).\r\n */\r\n public setHandler(tablixObj: TablixControl, handlerCall: (args: any[]) => void): void {\r\n this.handlers = handlerCall;\r\n this.tablixControl = tablixObj;\r\n }\r\n }\r\n\r\n /**\r\n * This class represents the touch region covering the body of the table.\r\n * This class is reponsible for interpreting gestures in terms of pixels to\r\n * changes in row and column position.\r\n */\r\n export class BodyTouchDelegate implements TouchUtils.ITouchHandler, TouchUtils.IPixelToItem {\r\n private static DefaultAverageSizeX = 30;\r\n private static DefaultAverageSizeY = 30;\r\n \r\n /**\r\n * Used to termine if the touch event is within bounds.\r\n */\r\n private dim: TouchUtils.Rectangle;\r\n \r\n /**\r\n * Average pixel width of columns in table.\r\n */\r\n private averageSizeX: number;\r\n \r\n /**\r\n * Average pixel height of rows in table.\r\n */\r\n private averageSizeY: number;\r\n \r\n /**\r\n * Used for 'firing' a scroll event following a recieved gesture.\r\n */\r\n private tablixControl: TablixControl;\r\n \r\n /**\r\n * Stores the event handler of TablixControl for scroll events.\r\n */\r\n private handlers: any;\r\n\r\n /**\r\n * @constructor\r\n * @param region Location and area of the touch region in respect to its HTML element.\r\n */\r\n constructor(region: TouchUtils.Rectangle) {\r\n this.dim = region;\r\n this.averageSizeX = BodyTouchDelegate.DefaultAverageSizeX;\r\n this.averageSizeY = BodyTouchDelegate.DefaultAverageSizeY;\r\n this.handlers = null;\r\n this.tablixControl = null;\r\n }\r\n\r\n /**\r\n * Returns dimension.\r\n * \r\n * @return The dimentions of the region this delegate listens to.\r\n */\r\n get dimension(): TouchUtils.Rectangle {\r\n return this.dim;\r\n }\r\n\r\n /**\r\n * Sets the amount of rows and columns to be shifted per delta in pixels.\r\n *\r\n * @param xRatio Column to pixel ratio (# columns / # pixels)\r\n * @param yRatio Row to pixel ratio (# rows / # pixels)\r\n */\r\n public setScrollDensity(xRatio: number, yRatio: number): void {\r\n this.averageSizeX = xRatio;\r\n this.averageSizeY = yRatio;\r\n }\r\n\r\n /**\r\n * Resize element.\r\n * \r\n * @param x X location from upper left of listened HTML element.\r\n * @param y Y location from upper left of listened HTML element.\r\n * @param width Width of area to listen for events.\r\n * @param height Height of area to listen for events.\r\n */\r\n public resize(x: number, y: number, width: number, height: number) {\r\n let dimension = this.dim;\r\n\r\n dimension.x = x;\r\n dimension.y = y;\r\n dimension.width = width;\r\n dimension.height = height;\r\n }\r\n\r\n /**\r\n * @see: IPixelToItem.\r\n */\r\n public getPixelToItem(x: number, y: number, dx: number, dy: number, down: boolean): TouchUtils.TouchEvent {\r\n return new TouchUtils.TouchEvent(x * this.averageSizeX, y * this.averageSizeY, down, -dx * this.averageSizeX, -dy * this.averageSizeY);\r\n }\r\n\r\n /**\r\n * Fires event to Tablix Control to scroll with the event passed from the TouchManager.\r\n *\r\n * @param e Event recieved from touch manager.\r\n */\r\n public touchEvent(e: TouchUtils.TouchEvent): void {\r\n let args: any[] = [this.tablixControl, e.dx, e.dy];\r\n\r\n if (this.handlers) {\r\n fire([this.handlers], args);\r\n }\r\n }\r\n\r\n /**\r\n * Asigns handler for scrolling when scroll event is fired.\r\n *\r\n * @param tablixObj TablixControl that's handling the fired event.\r\n * @param handlerCall The call to be made (EXAMPLE: handlerCall = object.method;).\r\n */\r\n public setHandler(tablixObj: TablixControl, handlerCall: (args: any[]) => void): void {\r\n this.handlers = handlerCall;\r\n this.tablixControl = tablixObj;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls.TouchUtils {\r\n\r\n export class Point {\r\n public x: number;\r\n public y: number;\r\n\r\n constructor(x?: number, y?: number) {\r\n this.x = x || 0;\r\n this.y = y || 0;\r\n }\r\n\r\n public offset(offsetX: number, offsetY: number) {\r\n this.x += offsetX;\r\n this.y += offsetY;\r\n }\r\n }\r\n\r\n export class Rectangle extends Point {\r\n public width: number;\r\n public height: number;\r\n\r\n constructor(x?: number, y?: number, width?: number, height?: number) {\r\n super(x, y);\r\n this.width = width || 0;\r\n this.height = height || 0;\r\n }\r\n\r\n get point(): Point {\r\n return new Point(this.x, this.y);\r\n }\r\n\r\n public contains(p: Point): boolean {\r\n return Rectangle.contains(this, p);\r\n }\r\n\r\n public static contains(rect: Rectangle, p: Point): boolean {\r\n if (p && !Rectangle.isEmpty(rect)) {\r\n return rect.x <= p.x && p.x < rect.x + rect.width && rect.y <= p.y && p.y < rect.y + rect.height;\r\n }\r\n return false;\r\n }\r\n\r\n public static isEmpty(rect: Rectangle): boolean {\r\n return !(rect !== undefined && rect.width >= 0 && rect.height >= 0);\r\n }\r\n }\r\n\r\n export const enum SwipeDirection {\r\n /**\r\n * Swipe gesture moves along the y-axis at an angle within an established threshold.\r\n */\r\n Vertical,\r\n \r\n /**\r\n * Swipe gesture moves along the x-axis at an angle within an established threshold.\r\n */\r\n Horizontal,\r\n \r\n /**\r\n * Swipe gesture does not stay within the thresholds of either x or y-axis.\r\n */\r\n FreeForm\r\n }\r\n\r\n export enum MouseButton {\r\n NoClick = 0,\r\n LeftClick = 1,\r\n RightClick = 2,\r\n CenterClick = 3\r\n }\r\n\r\n /** \r\n * Interface serves as a way to convert pixel point to any needed unit of\r\n * positioning over two axises such as row/column positioning.\r\n */\r\n export interface IPixelToItem {\r\n\r\n getPixelToItem(x: number, y: number, dx: number, dy: number, down: boolean): TouchEvent;\r\n }\r\n\r\n /**\r\n * Interface for listening to a simple touch event that's abstracted away\r\n * from any platform specific traits.\r\n */\r\n export interface ITouchHandler {\r\n touchEvent(e: TouchEvent): void;\r\n }\r\n\r\n /** \r\n * A simple touch event class that's abstracted away from any platform specific traits.\r\n */\r\n export class TouchEvent {\r\n /* tslint:disable:no-underscore-prefix-for-variables*/\r\n /**\r\n * X-axis (not neccessarily in pixels (see IPixelToItem)).\r\n */\r\n private _x: number;\r\n \r\n /**\r\n * Y-axis (not neccessarily in pixels (see IPixelToItem)).\r\n */\r\n private _y: number;\r\n \r\n /**\r\n * Delta of x-axis (not neccessarily in pixels (see IPixelToItem)).\r\n */\r\n private _dx: number;\r\n \r\n /**\r\n * Delta of y-axis (not neccessarily in pixels (see IPixelToItem)).\r\n */\r\n private _dy: number;\r\n /* tslint:enable:no-underscore-prefix-for-variables*/\r\n /**\r\n * Determines if the mouse button is pressed.\r\n */\r\n private isMouseButtonDown: boolean;\r\n\r\n /**\r\n * @constructor\r\n * @param x X Location of mouse.\r\n * @param y Y Location of mouse.\r\n * @param isMouseDown Indicates if the mouse button is held down or a finger press on screen.\r\n * @param dx (optional) The change in x of the gesture.\r\n * @param dy (optional) The change in y of the gesture.\r\n */\r\n constructor(x: number, y: number, isMouseDown: boolean, dx?: number, dy?: number) {\r\n this._x = x;\r\n this._y = y;\r\n this.isMouseButtonDown = isMouseDown;\r\n this._dx = dx || 0;\r\n this._dy = dy || 0;\r\n }\r\n\r\n public get x(): number {\r\n return this._x;\r\n }\r\n\r\n public get y(): number {\r\n return this._y;\r\n }\r\n\r\n public get dx(): number {\r\n return this._dx;\r\n }\r\n\r\n public get dy(): number {\r\n return this._dy;\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating if the mouse button is held down.\r\n * \r\n * @return: True if the the mouse button is held down,\r\n * otherwise false.\r\n */\r\n public get isMouseDown(): boolean {\r\n return this.isMouseButtonDown;\r\n }\r\n }\r\n\r\n /**\r\n * This interface defines the datamembers stored for each touch region.\r\n */\r\n export interface ITouchHandlerSet {\r\n handler: ITouchHandler;\r\n region: Rectangle;\r\n\r\n lastPoint: TouchEvent;\r\n converter: IPixelToItem;\r\n }\r\n\r\n /** \r\n * This class \"listens\" to the TouchEventInterpreter to recieve touch events and sends it to all \r\n * \"Touch Delegates\" with TouchRegions that contain the mouse event. Prior to sending off the\r\n * event, its position is put in respect to the delegate's TouchRegion and converted to the appropriate\r\n * unit (see IPixelToItem).\r\n */\r\n export class TouchManager {\r\n /**\r\n * List of touch regions and their correlating data memebers.\r\n */\r\n private touchList: ITouchHandlerSet[];\r\n \r\n /**\r\n * Boolean to enable thresholds for fixing to an axis when scrolling.\r\n */\r\n private scrollThreshold: boolean;\r\n \r\n /**\r\n * Boolean to enable locking to an axis when gesture is fixed to an axis.\r\n */\r\n private lockThreshold: boolean;\r\n \r\n /**\r\n * The current direction of the swipe.\r\n */\r\n private swipeDirection: SwipeDirection;\r\n \r\n /**\r\n * The count of consecutive events match the current swipe direction.\r\n */\r\n private matchingDirectionCount: number;\r\n \r\n /**\r\n * The last recieved mouse event.\r\n */\r\n private lastTouchEvent: TouchEvent;\r\n\r\n /**\r\n * Default constructor.\r\n * \r\n * The default behavior is to enable thresholds and lock to axis.\r\n */\r\n constructor() {\r\n this.touchList = [];\r\n this.swipeDirection = SwipeDirection.FreeForm;\r\n this.matchingDirectionCount = 0;\r\n\r\n this.lockThreshold = true;\r\n this.scrollThreshold = true;\r\n this.lastTouchEvent = new TouchEvent(0, 0, false);\r\n }\r\n\r\n public get lastEvent(): TouchEvent {\r\n return this.lastTouchEvent;\r\n }\r\n\r\n /**\r\n * @param region Rectangle indicating the locations of the touch region.\r\n * @param handler Handler for recieved touch events.\r\n * @param converter Converts from pixels to the wanted item of measure (rows, columns, etc).\r\n * \r\n * EXAMPLE: dx -> from # of pixels to the right to # of columns moved to the right.\r\n */\r\n public addTouchRegion(region: Rectangle, handler: ITouchHandler, converter: IPixelToItem): void {\r\n let item: ITouchHandlerSet = <ITouchHandlerSet> {\r\n lastPoint: new TouchEvent(0, 0, false),\r\n handler: handler,\r\n region: region,\r\n converter: converter\r\n };\r\n\r\n this.touchList = this.touchList.concat([item]);\r\n }\r\n\r\n /**\r\n * Sends a mouse up event to all regions with their last event as a mouse down event.\r\n */\r\n public upAllTouches(): void {\r\n let eventPoint: TouchEvent;\r\n let length: number;\r\n\r\n length = this.touchList.length;\r\n for (let i = 0; i < length; i++) {\r\n if (this.touchList[i].lastPoint.isMouseDown) {\r\n eventPoint = this.touchList[i].converter.getPixelToItem(this.touchList[i].lastPoint.x,\r\n this.touchList[i].lastPoint.y,\r\n 0, 0, false);\r\n this.touchList[i].handler.touchEvent(eventPoint);\r\n }\r\n\r\n this.touchList[i].lastPoint = new TouchEvent(this.touchList[i].lastPoint.x,\r\n this.touchList[i].lastPoint.y, false);\r\n }\r\n\r\n this.lastTouchEvent = new TouchEvent(0, 0, false);\r\n }\r\n\r\n public touchEvent(e: TouchEvent): void {\r\n let list: ITouchHandlerSet[];\r\n let length: number;\r\n\r\n let x: number = 0;\r\n let y: number = 0;\r\n let dx: number = 0;\r\n let dy: number = 0;\r\n let angle: number = 0;\r\n\r\n let eventPoint: TouchEvent = null;\r\n\r\n //assume there are already regions in the middle of a drag event and get those regions\r\n list = this._getActive();\r\n\r\n //if this is the start of a mouse drag event, repopulate the list with touched regions\r\n if (!this.lastTouchEvent.isMouseDown && e.isMouseDown) {\r\n list = this._findRegions(e);\r\n }\r\n\r\n //determine the delta values and update last event (delta ignored on first mouse down event)\r\n dx = this.lastTouchEvent.x - e.x;\r\n dy = this.lastTouchEvent.y - e.y;\r\n this.lastTouchEvent = new TouchEvent(e.x, e.y, e.isMouseDown, dx, dy);\r\n\r\n //go through the list\r\n length = list.length;\r\n for (let i = 0; i < length; i++) {\r\n x = e.x - list[i].region.point.x;\r\n y = e.y - list[i].region.point.y;\r\n\r\n //is this in the middle of a drag?\r\n if (list[i].lastPoint.isMouseDown && e.isMouseDown) {\r\n dx = x - list[i].lastPoint.x;\r\n dy = y - list[i].lastPoint.y;\r\n\r\n //calculate the absolute angle from the horizontal axis\r\n angle = Math.abs(180 / Math.PI * Math.atan(dy / dx));\r\n\r\n if (this.scrollThreshold) {\r\n //is the gesture already locked? (6 prior events within the threshold)\r\n if (this.lockThreshold && (this.matchingDirectionCount > 5)) {\r\n if (this.swipeDirection === SwipeDirection.Horizontal) {\r\n dy = 0;\r\n }\r\n else if (this.swipeDirection === SwipeDirection.Vertical) {\r\n dx = 0;\r\n }\r\n }\r\n else {\r\n //is it within the horizontal threshold?\r\n if (angle < 20) {\r\n dy = 0;\r\n if (this.swipeDirection === SwipeDirection.Horizontal) {\r\n this.matchingDirectionCount++;\r\n }\r\n else {\r\n this.matchingDirectionCount = 1;\r\n this.swipeDirection = SwipeDirection.Horizontal;\r\n }\r\n }\r\n else {\r\n //calculate the absolute angle from the vertical axis\r\n angle = Math.abs(180 / Math.PI * Math.atan(dx / dy));\r\n\r\n //is it within the horizontal threshold?\r\n if (angle < 20) {\r\n dx = 0;\r\n\r\n if (this.swipeDirection === SwipeDirection.Vertical) {\r\n this.matchingDirectionCount++;\r\n }\r\n else {\r\n this.matchingDirectionCount = 1;\r\n this.swipeDirection = SwipeDirection.Vertical;\r\n }\r\n }\r\n else {\r\n if (this.swipeDirection === SwipeDirection.FreeForm) {\r\n this.matchingDirectionCount++;\r\n }\r\n else {\r\n this.swipeDirection = SwipeDirection.FreeForm;\r\n this.matchingDirectionCount = 1;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n else {\r\n dx = 0;\r\n dy = 0;\r\n this.swipeDirection = SwipeDirection.FreeForm;\r\n this.matchingDirectionCount = 0;\r\n }\r\n\r\n list[i].lastPoint = new TouchEvent(x, y, e.isMouseDown, dx, dy);\r\n\r\n eventPoint = list[i].converter.getPixelToItem(x, y, dx, dy, e.isMouseDown);\r\n list[i].handler.touchEvent(eventPoint);\r\n }\r\n }\r\n\r\n /**\r\n * @param e Position of event used to find touched regions\r\n * @return Array of regions that contain the event point.\r\n */\r\n private _findRegions(e: TouchEvent): ITouchHandlerSet[] {\r\n let list: ITouchHandlerSet[] = [];\r\n let length: number;\r\n\r\n length = this.touchList.length;\r\n for (let i = 0; i < length; i++) {\r\n if (this.touchList[i].region.contains(new Point(e.x, e.y))) {\r\n list = list.concat([this.touchList[i]]);\r\n }\r\n }\r\n\r\n return list;\r\n }\r\n\r\n /**\r\n * @return Array of regions that contain a mouse down event. (see ITouchHandlerSet.lastPoint).\r\n */\r\n private _getActive(): ITouchHandlerSet[] {\r\n let list: ITouchHandlerSet[] = [];\r\n let length: number;\r\n\r\n length = this.touchList.length;\r\n for (let i = 0; i < length; i++) {\r\n if (this.touchList[i].lastPoint.isMouseDown) {\r\n list = list.concat([this.touchList[i]]);\r\n }\r\n }\r\n\r\n return list;\r\n }\r\n }\r\n\r\n /**\r\n * This interface defines the swipe data.\r\n */\r\n interface ISwipeInfo {\r\n direction: number;\r\n distance: number;\r\n endTime: number;\r\n time: number;\r\n }\r\n\r\n const MinDistanceForSwipe = 80;\r\n const MaxTimeForSwipe = 600;\r\n\r\n /**\r\n * This class is responsible for establishing connections to handle touch events\r\n * and to interpret those events so they're compatible with the touch abstractions.\r\n *\r\n * Touch events with platform specific handles should be done here.\r\n */\r\n export class TouchEventInterpreter {\r\n /**\r\n * HTML element that touch events are drawn from.\r\n */\r\n private touchPanel: HTMLElement;\r\n \r\n /**\r\n * Boolean enabling mouse drag.\r\n */\r\n private allowMouseDrag: boolean;\r\n \r\n /**\r\n * Touch events are interpreted and passed on this manager.\r\n */\r\n private manager: TouchManager;\r\n \r\n /**\r\n * @see TablixLayoutManager. \r\n */\r\n private scale: number;\r\n \r\n /**\r\n * Used for mouse location when a secondary div is used along side the primary with this one being the primary.\r\n */\r\n private touchReferencePoint: HTMLElement;\r\n \r\n /** \r\n * Rectangle containing the targeted Div.\r\n */\r\n private rect: ClientRect;\r\n\r\n private documentMouseMoveWrapper: any;\r\n private documentMouseUpWrapper: any;\r\n\r\n /**\r\n * Those setting related to swipe detection \r\n * touchStartTime - the time that the user touched down the screen.\r\n */\r\n private touchStartTime: number;\r\n /**\r\n * The page y value of the touch event when the user touched down.\r\n */\r\n private touchStartPageY: number;\r\n /**\r\n * The last page y value befoer the user raised up his finger.\r\n */\r\n private touchLastPageY: number;\r\n /**\r\n * The last page x value befoer the user raised up his finger.\r\n */\r\n private touchLastPageX: number;\r\n /**\r\n * An indicator whether we are now running the slide affect.\r\n */\r\n private sliding: boolean;\r\n\r\n constructor(manager: TouchManager) {\r\n this.manager = manager;\r\n this.allowMouseDrag = true;\r\n this.touchPanel = null;\r\n this.scale = 1;\r\n this.documentMouseMoveWrapper = null;\r\n this.documentMouseUpWrapper = null;\r\n this.sliding = false;\r\n }\r\n\r\n public initTouch(panel: HTMLElement, touchReferencePoint?: HTMLElement, allowMouseDrag?: boolean): void {\r\n panel.style.setProperty(\"-ms-touch-action\", \"pinch-zoom\");\r\n\r\n this.touchReferencePoint = touchReferencePoint;\r\n\r\n this.touchPanel = panel;\r\n this.allowMouseDrag = allowMouseDrag === undefined ? true : allowMouseDrag;\r\n if (\"ontouchmove\" in panel) {\r\n panel.addEventListener(\"touchstart\", e => this.onTouchStart(e));\r\n panel.addEventListener(\"touchend\", e => this.onTouchEnd(e));\r\n }\r\n else {\r\n panel.addEventListener(\"mousedown\", e => this.onTouchMouseDown(<MouseEvent>e));\r\n panel.addEventListener(\"mouseup\", e => this.onTouchMouseUp(<MouseEvent>e));\r\n }\r\n }\r\n\r\n private getXYByClient(pageX: number, pageY: number, rect: ClientRect): Point {\r\n let x: number = rect.left;\r\n let y: number = rect.top;\r\n\r\n // Fix for Safari\r\n if (window[\"scrollX\"] !== undefined) {\r\n x += window[\"scrollX\"];\r\n y += window[\"scrollY\"];\r\n }\r\n\r\n let point: Point = new Point(0, 0);\r\n point.offset(pageX - x, pageY - y);\r\n\r\n return point;\r\n }\r\n\r\n public onTouchStart(e: any): void {\r\n if (e.touches.length === 1) {\r\n e.cancelBubble = true;\r\n\r\n let mouchEvent: MouseEvent = e.touches[0];\r\n this.touchStartTime = new Date().getTime();\r\n this.touchStartPageY = mouchEvent.pageY;\r\n\r\n this.onTouchMouseDown(mouchEvent);\r\n }\r\n }\r\n\r\n public onTouchMove(e: any): void {\r\n if (e.touches.length === 1) {\r\n if (e.preventDefault) {\r\n e.preventDefault();\r\n }\r\n\r\n let mouchEvent: MouseEvent = e.touches[0];\r\n this.touchLastPageY = mouchEvent.pageY;\r\n this.touchLastPageX = mouchEvent.pageX;\r\n // while sliding ignore the touch move event \r\n if (!this.sliding) {\r\n this.onTouchMouseMove(mouchEvent);\r\n }\r\n }\r\n }\r\n\r\n public onTouchEnd(e: any): void {\r\n this.clearTouchEvents();\r\n\r\n let swipeInfo = this.getSwipeInfo();\r\n if (this.didUserSwipe(swipeInfo)) {\r\n this.startSlideAffect(swipeInfo);\r\n }\r\n // in case this is not a swipe - we need to reset the rect and the touches \r\n else if (!this.sliding) {\r\n this.upAllTouches();\r\n }\r\n }\r\n\r\n public onTouchMouseDown(e: MouseEvent): void {\r\n this.scale = HTMLElementUtils.getAccumulatedScale(this.touchPanel);\r\n\r\n //any prior touch scrolling that produced a selection outside Tablix will prevent the next touch scroll (1262519)\r\n document.getSelection().removeAllRanges();\r\n\r\n this.rect = (this.touchReferencePoint ? this.touchReferencePoint : this.touchPanel).getBoundingClientRect();\r\n\r\n if (\"ontouchmove\" in this.touchPanel) {\r\n this.documentMouseMoveWrapper = e => this.onTouchMove(e);\r\n document.addEventListener(\"touchmove\", this.documentMouseMoveWrapper);\r\n this.documentMouseUpWrapper = e => this.onTouchEnd(e);\r\n document.addEventListener(\"touchend\", this.documentMouseUpWrapper);\r\n }\r\n else {\r\n this.documentMouseMoveWrapper = e => this.onTouchMouseMove(e);\r\n document.addEventListener(\"mousemove\", this.documentMouseMoveWrapper);\r\n this.documentMouseUpWrapper = e => this.onTouchMouseUp(e);\r\n document.addEventListener(\"mouseup\", this.documentMouseUpWrapper);\r\n }\r\n\r\n if (\"setCapture\" in this.touchPanel) {\r\n this.touchPanel.setCapture();\r\n }\r\n }\r\n\r\n public onTouchMouseMove(e: MouseEvent): void {\r\n let event: TouchEvent;\r\n let point: Point;\r\n\r\n let rect = this.rect;\r\n let validMouseDragEvent: boolean = (rect !== null) && (e.which !== MouseButton.NoClick);\r\n\r\n // Ignore events that are not part of a drag event\r\n if (!validMouseDragEvent || this.sliding)\r\n return;\r\n\r\n point = this.getXYByClient(e.pageX, e.pageY, rect);\r\n event = new TouchEvent(point.x / this.scale, point.y / this.scale, validMouseDragEvent);\r\n\r\n this.manager.touchEvent(event);\r\n\r\n if (e.preventDefault)\r\n e.preventDefault();\r\n else if (\"returnValue\" in e) //some browsers missing preventDefault() may still use this instead\r\n e[\"returnValue\"] = false;\r\n }\r\n\r\n public onTouchMouseUp(e: MouseEvent, bubble?: boolean): void {\r\n this.upAllTouches();\r\n this.clearTouchEvents();\r\n }\r\n\r\n private getSwipeInfo(): ISwipeInfo {\r\n let touchEndTime = new Date().getTime();\r\n let touchTime = touchEndTime - this.touchStartTime;\r\n let touchDist = this.touchLastPageY - this.touchStartPageY;\r\n let touchDirection = touchDist < 0 ? -1 : 1;\r\n\r\n return {\r\n direction: touchDirection,\r\n distance: touchDist,\r\n endTime: touchEndTime,\r\n time: touchTime,\r\n };\r\n }\r\n\r\n private didUserSwipe(swipeInfo: ISwipeInfo): boolean {\r\n return swipeInfo.time < MaxTimeForSwipe && swipeInfo.distance * swipeInfo.direction > MinDistanceForSwipe;\r\n }\r\n\r\n /**\r\n * In case of swipe - auto advance to the swipe direction in 2 steps.\r\n */\r\n private startSlideAffect(swipeInfo: ISwipeInfo): void {\r\n if (this.sliding) {\r\n return;\r\n }\r\n\r\n this.sliding = true;\r\n let point = this.getXYByClient(this.touchLastPageX, this.touchLastPageY, this.rect);\r\n this.slide(point, 300, swipeInfo);\r\n\r\n // second step\r\n requestAnimationFrame(() => {\r\n // in case the user is now scrolling in the opposite direction stop the slide\r\n if (!this.didUserChangeDirection(swipeInfo)) {\r\n this.slide(point, 200, swipeInfo);\r\n }\r\n this.clearSlide();\r\n });\r\n }\r\n\r\n private didUserChangeDirection(swipeInfo: ISwipeInfo): boolean {\r\n if (this.touchStartTime <= swipeInfo.endTime) {\r\n return false;\r\n }\r\n\r\n let updatedDist = this.touchLastPageY - this.touchStartPageY;\r\n let updatedDirection = updatedDist < 0 ? -1 : 1;\r\n return updatedDirection !== swipeInfo.direction;\r\n }\r\n\r\n private slide(point: Point, slideDist: number, swipeInfo: ISwipeInfo): void {\r\n let updatedDist = this.touchStartTime > swipeInfo.endTime ? this.touchLastPageY - this.touchStartPageY : 0;\r\n\r\n point.y += slideDist * swipeInfo.direction + updatedDist;\r\n let event = new TouchEvent(point.x / this.scale, point.y / this.scale, true);\r\n\r\n this.manager.touchEvent(event);\r\n }\r\n\r\n private clearSlide(): void {\r\n this.sliding = false;\r\n this.upAllTouches();\r\n }\r\n\r\n private upAllTouches(): void {\r\n if (this.documentMouseMoveWrapper !== null)\r\n return;\r\n\r\n this.rect = null;\r\n this.manager.upAllTouches();\r\n }\r\n\r\n private clearTouchEvents(): void {\r\n if (\"releaseCapture\" in this.touchPanel) {\r\n this.touchPanel.releaseCapture();\r\n }\r\n\r\n if (this.documentMouseMoveWrapper === null)\r\n return;\r\n\r\n if (\"ontouchmove\" in this.touchPanel) {\r\n document.removeEventListener(\"touchmove\", this.documentMouseMoveWrapper);\r\n document.removeEventListener(\"touchend\", this.documentMouseUpWrapper);\r\n }\r\n else {\r\n document.removeEventListener(\"mousemove\", this.documentMouseMoveWrapper);\r\n document.removeEventListener(\"mouseup\", this.documentMouseUpWrapper);\r\n }\r\n\r\n this.documentMouseMoveWrapper = null;\r\n this.documentMouseUpWrapper = null;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls {\r\n export enum TablixType {\r\n Matrix,\r\n Table\r\n }\r\n\r\n /**\r\n * General section of Formatting Properties for Tablix\r\n */\r\n export interface TablixFormattingPropertiesGeneral {\r\n /** Property that drives whether columns should use automatically calculated (based on content) sizes for width or use persisted sizes.\r\n Default is true i.e. automatically calculate width based on column content */\r\n autoSizeColumnWidth: boolean;\r\n /**\r\n * Font size for the whole tablix\r\n * Default is 8\r\n */\r\n textSize: number;\r\n }\r\n\r\n /**\r\n * General section of Formatting Properties for Table\r\n */\r\n export interface TablixFormattingPropertiesGeneralTable extends TablixFormattingPropertiesGeneral {\r\n /*\r\n * Show/Hide Grand Total\r\n * Default is True\r\n */\r\n totals?: boolean;\r\n }\r\n\r\n /**\r\n * General section of Formatting Properties for Matrix\r\n */\r\n export interface TablixFormattingPropertiesGeneralMatrix extends TablixFormattingPropertiesGeneral {\r\n /**\r\n * Show/Hide Subtotal Rows\r\n */\r\n rowSubtotals?: boolean;\r\n /**\r\n * Show/Hide Subtotal Columns\r\n */\r\n columnSubtotals?: boolean;\r\n }\r\n\r\n /**\r\n * Grid section of Formatting Properties for Tablix\r\n */\r\n export interface TablixFormattingPropertiesGrid {\r\n /**\r\n * Show/Hide vertical gridlines\r\n */\r\n gridVertical?: boolean;\r\n\r\n /**\r\n * vertical gridlines color\r\n */\r\n gridVerticalColor?: string;\r\n\r\n /**\r\n * vertical gridlines Weight\r\n */\r\n gridVerticalWeight?: number;\r\n\r\n /**\r\n * Show/Hide horizontal gridlines\r\n */\r\n gridHorizontal?: boolean;\r\n\r\n /**\r\n * horizontal gridlines color\r\n */\r\n gridHorizontalColor?: string;\r\n\r\n /**\r\n * horizontal gridlines Weight\r\n */\r\n gridHorizontalWeight?: number;\r\n\r\n /**\r\n * Color of the outline. Shared across all regions\r\n */\r\n outlineColor?: string;\r\n\r\n /**\r\n * Weight outline. Shared across all regions\r\n */\r\n outlineWeight?: number;\r\n\r\n /**\r\n * Weight outline. Shared across all regions\r\n */\r\n rowPadding?: number;\r\n\r\n /**\r\n * Maximum height of images in pixels\r\n */\r\n imageHeight?: number;\r\n }\r\n\r\n /**\r\n * Common Formatting Properties for Tablix regions (Column Headers, Row Headers, Total, SubTotals)\r\n */\r\n export interface TablixFormattingPropertiesRegion {\r\n /*\r\n * Font color of all cells within the region\r\n * Default is <Undefined>\r\n */\r\n fontColor?: string;\r\n /*\r\n * Background color of all cells within the region\r\n * Default is <Undefined>\r\n */\r\n backColor?: string;\r\n /*\r\n * Outline style for the whole region. One of the values from powerbi.visuals.outline\r\n * Default is outline.none\r\n */\r\n outline: string;\r\n }\r\n\r\n export interface TablixFormattingPropertiesValues {\r\n /*\r\n * Font color of all cells for Odd Index rows\r\n * Default is <Undefined>\r\n */\r\n fontColorPrimary?: string;\r\n /*\r\n * Background color of all cells for Odd Index rows\r\n * Default is <Undefined>\r\n */\r\n backColorPrimary?: string;\r\n /*\r\n * Font color of all cells for even Index rows\r\n * Default is <Undefined>\r\n */\r\n fontColorSecondary?: string;\r\n /*\r\n * Background color of all cells for even Index rows\r\n * Default is <Undefined>\r\n */\r\n backColorSecondary?: string;\r\n /*\r\n * Outline style for the whole region. One of the values from powerbi.visuals.outline\r\n * Default is outline.none\r\n */\r\n outline: string;\r\n }\r\n\r\n /**\r\n * Formatting Properties for Table Values region\r\n */\r\n export interface TablixFormattingPropertiesValuesTable extends TablixFormattingPropertiesValues {\r\n /*\r\n * Use an icon instead of URL text\r\n * Default is False\r\n */\r\n urlIcon?: boolean;\r\n }\r\n\r\n /**\r\n * Formatting Properties for Table Visual\r\n */\r\n export interface TablixFormattingPropertiesTable {\r\n general?: TablixFormattingPropertiesGeneralTable;\r\n grid?: TablixFormattingPropertiesGrid;\r\n columnHeaders?: TablixFormattingPropertiesRegion;\r\n values?: TablixFormattingPropertiesValuesTable;\r\n total?: TablixFormattingPropertiesRegion;\r\n }\r\n\r\n /**\r\n * Formatting Properties for Matrix Visual\r\n */\r\n export interface TablixFormattingPropertiesMatrix {\r\n general?: TablixFormattingPropertiesGeneralMatrix;\r\n grid?: TablixFormattingPropertiesGrid;\r\n columnHeaders?: TablixFormattingPropertiesRegion;\r\n rowHeaders?: TablixFormattingPropertiesRegion;\r\n values?: TablixFormattingPropertiesValues;\r\n subtotals?: TablixFormattingPropertiesRegion;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.controls {\r\n import PropAutoSizeWidth = internal.TablixObjects.PropGeneralAutoSizeColumns;\r\n import getMetadataObjects = internal.TablixObjects.getMetadadataObjects;\r\n\r\n /**\r\n * Column Width Object identifying a certain column and its width\r\n */\r\n export interface ColumnWidthObject {\r\n /**\r\n * QueryName of the Column\r\n */\r\n queryName: string;\r\n\r\n /**\r\n * Width of the column in px. -1 means it's fixed but unknown.\r\n */\r\n width: number;\r\n }\r\n\r\n /**\r\n * Handler for Column Width Changed event\r\n */\r\n export interface ColumnWidthCallbackType {\r\n (index: number, width: number): void;\r\n }\r\n\r\n /**\r\n * Handler for requesting host to persist Column Width Objects\r\n */\r\n export interface HostPersistCallBack {\r\n (visualObjectInstances: VisualObjectInstancesToPersist): void;\r\n }\r\n\r\n export class TablixColumnWidthManager {\r\n /**\r\n * PropertyID for Column Widths (General > columnWidth)\r\n */\r\n public static columnWidthProp: DataViewObjectPropertyIdentifier = { objectName: 'general', propertyName: 'columnWidth' };\r\n\r\n /**\r\n * Array holding widths for all columns. Index is the index for the column in the visual Table/Matrix\r\n * Width will be a number for fixed size columns, undefined for autosized columns\r\n */\r\n private columnWidthObjects: controls.ColumnWidthObject[];\r\n\r\n /**\r\n * Visual Object Instances to be persisted. Containing autoSizeProperty and any width to remove/merge\r\n */\r\n private visualObjectInstancesToPersist: VisualObjectInstancesToPersist;\r\n\r\n /**\r\n * True if the Tablix is a Matrix\r\n */\r\n private isMatrix: boolean;\r\n /**\r\n * Array of all leaf nodes (Row Groupings + Columns/Values instances)\r\n */\r\n private matrixLeafNodes: MatrixVisualNode[];\r\n /**\r\n * Current DataView\r\n */\r\n private currentDataView: DataView;\r\n /**\r\n * Current value of AutoSizeColumns after last DataView Update\r\n */\r\n private currentAutoColumnSizePropertyValue: boolean;\r\n\r\n /**\r\n * Previous DataView\r\n */\r\n private previousDataView: DataView;\r\n /**\r\n * Previous value of AutoSizeColumns before last DataView Update\r\n */\r\n private previousAutoColumnSizePropertyValue: boolean;\r\n\r\n /**\r\n * Handler for requesting host to persist Column Width Objects\r\n */\r\n private hostPersistCallBack: HostPersistCallBack;\r\n\r\n constructor(dataView: DataView, isMatrix: boolean, hostPersistCallBack: HostPersistCallBack, matrixLeafNodes?: MatrixVisualNode[]) {\r\n this.columnWidthObjects = [];\r\n this.isMatrix = isMatrix;\r\n this.updateDataView(dataView, matrixLeafNodes);\r\n this.hostPersistCallBack = hostPersistCallBack;\r\n }\r\n\r\n /**\r\n * Update the current DataView\r\n * @param {dataView} DataView new DataView\r\n * @param {MatrixVisualNode[]} matrixLeafNodes? (Optional)Matrix Leaf Nodes\r\n */\r\n public updateDataView(dataView: DataView, matrixLeafNodes?: MatrixVisualNode[]): void {\r\n this.previousDataView = this.currentDataView;\r\n if (this.previousDataView)\r\n this.previousAutoColumnSizePropertyValue = PropAutoSizeWidth.getValue<boolean>(getMetadataObjects(this.previousDataView));\r\n else\r\n this.previousAutoColumnSizePropertyValue = undefined;\r\n\r\n this.currentDataView = dataView;\r\n if(this.currentDataView)\r\n this.currentAutoColumnSizePropertyValue = PropAutoSizeWidth.getValue<boolean>(getMetadataObjects(this.currentDataView));\r\n else\r\n this.currentAutoColumnSizePropertyValue = undefined;\r\n\r\n this.matrixLeafNodes = matrixLeafNodes;\r\n \r\n this.updateColumnWidthObjects();\r\n\r\n this.updateTablixColumnWidths();\r\n }\r\n\r\n /**\r\n * Destroy columnWidthObjects and construct it again from the currently displayed Columns\r\n */\r\n private updateColumnWidthObjects(): void {\r\n this.columnWidthObjects.length = 0;\r\n\r\n if (this.isMatrix)\r\n this.updateMatrixColumnWidthObjects();\r\n else\r\n this.updateTableColumnWidthObjects();\r\n }\r\n\r\n private updateTableColumnWidthObjects(): void {\r\n if (this.currentDataView && this.currentDataView.table) {\r\n let columnMetaData = this.currentDataView.table.columns;\r\n for (let i = 0, len = columnMetaData.length; i < len; i++) {\r\n let query = columnMetaData[i].queryName;\r\n this.columnWidthObjects.push({\r\n queryName: query,\r\n width: undefined\r\n });\r\n }\r\n }\r\n }\r\n\r\n private updateMatrixColumnWidthObjects(): void {\r\n // Matrix visual columns are row headers and column hierarchy leaves\r\n\r\n if (this.currentDataView && this.currentDataView.matrix && this.currentDataView.matrix.rows) {\r\n // Get query names of row groups (row headers)\r\n for (let i = 0, len = this.currentDataView.matrix.rows.levels.length; i < len; i++) {\r\n let rowGroup = this.currentDataView.matrix.rows.levels[i]; // TODO: Investigate multi-source groups\r\n if (!_.isEmpty(rowGroup.sources))\r\n this.columnWidthObjects.push({\r\n queryName: rowGroup.sources[0].queryName,\r\n width: undefined\r\n });\r\n }\r\n }\r\n\r\n // Get query names of columns leaves or values\r\n if (this.matrixLeafNodes) {\r\n for (let i = 0, len = this.matrixLeafNodes.length; i < len; i++) {\r\n let query = this.matrixLeafNodes[i].queryName;\r\n this.columnWidthObjects.push({\r\n queryName: query,\r\n width: undefined\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Update the column widths after a dataViewChange\r\n */\r\n public updateTablixColumnWidths(): void {\r\n let columnMetaData = this.currentDataView && this.currentDataView.metadata && this.currentDataView.metadata.columns;\r\n if (columnMetaData) {\r\n // Auto-Size false to true.\r\n // Blow away any saved widths and revert back to default of calculating column sizes\r\n if (this.shouldClearAllColumnWidths()) {\r\n this.autoSizeAllColumns();\r\n }\r\n else {\r\n this.deserializeColumnWidths(columnMetaData);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Read the Column Widths from the Columns metadata\r\n * @param {DataViewMetadataColumn[]} columnMetaData Columns metadata\r\n */\r\n private deserializeColumnWidths(columnMetaData: DataViewMetadataColumn[]): void {\r\n // Clear existing widths\r\n this.columnWidthObjects.forEach(obj => {\r\n obj.width = undefined;\r\n });\r\n\r\n for (let column of columnMetaData) {\r\n let columnWidthPropValue = DataViewObjects.getValue<number>(column.objects, TablixColumnWidthManager.columnWidthProp);\r\n if (!_.isNumber(columnWidthPropValue)) {\r\n continue;\r\n }\r\n\r\n for (let obj of this.columnWidthObjects) {\r\n if (obj.queryName === column.queryName) {\r\n obj.width = columnWidthPropValue;\r\n // Don't break, we need to set all instances of that Group\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns a value indicating that autoSizeColumns was flipped from true to false\r\n */\r\n public shouldPersistAllColumnWidths(): boolean {\r\n // We don't have a previous DataView -> Don't persist\r\n if (!this.previousDataView)\r\n // TODO: 6928446\r\n // Once 6927388 gets fixed, we need to persist the DataView is first loaded with AutoSize off to count for missing set widths\r\n return false;\r\n // We had a DataView before -> return true if Autosize switched from true to false\r\n else\r\n return !this.currentAutoColumnSizePropertyValue && this.previousAutoColumnSizePropertyValue;\r\n }\r\n\r\n /**\r\n * Returns a value indicating that autoSizeColumns was flipped from false to true\r\n */\r\n public shouldClearAllColumnWidths(): boolean {\r\n return this.previousDataView != null && this.previousAutoColumnSizePropertyValue === false\r\n && this.currentDataView != null && this.currentAutoColumnSizePropertyValue === true;\r\n }\r\n\r\n /**\r\n * Returns the current columnWidthObjects\r\n * @returns current columnWidthObjects including undefined widths for autosized columns\r\n */\r\n public getColumnWidthObjects(): controls.ColumnWidthObject[] {\r\n return this.columnWidthObjects;\r\n }\r\n\r\n /**\r\n * Returns the current columnWidthObjects for only the fixed-size columns\r\n * @returns Returns the current columnWidthObjects excluding auto-sized columns\r\n */\r\n public getFixedColumnWidthObjects(): controls.ColumnWidthObject[] {\r\n return this.columnWidthObjects.filter(obj => {\r\n return obj.width != null;\r\n });\r\n }\r\n\r\n /**\r\n * Get the persisted width of a certain column in px, or undefined if the columns is set to autosize or index is out of range\r\n * @param {number} index index of the Column\r\n * @returns Column persisted width in pixel\r\n */\r\n public getPersistedColumnWidth(index: number): number {\r\n let colIndex = this.isMatrix ? index : index - 1;\r\n let item = this.columnWidthObjects[colIndex];\r\n if (item)\r\n return item.width;\r\n else\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Call the host to persist the data\r\n * @param {boolean} generateInstances\r\n */\r\n private callHostToPersist(generateInstances: boolean) {\r\n if (generateInstances)\r\n this.generateVisualObjectInstancesToPersist();\r\n\r\n if (this.hostPersistCallBack) {\r\n this.hostPersistCallBack(this.visualObjectInstancesToPersist);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all persisted columns widths and Update visualObjectInstancesToPersist\r\n */\r\n private autoSizeAllColumns(): void {\r\n this.visualObjectInstancesToPersist = {\r\n merge: [this.getAutoSizeColumnWidthObject()],\r\n remove: [],\r\n };\r\n\r\n for (let columnWidthObject of this.columnWidthObjects) {\r\n this.visualObjectInstancesToPersist.remove.push({\r\n selector: { metadata: columnWidthObject.queryName },\r\n objectName: 'general',\r\n properties: {\r\n columnWidth: undefined\r\n }\r\n });\r\n }\r\n\r\n this.callHostToPersist(false);\r\n }\r\n\r\n /**\r\n * Remove persisted column width for a specific column and Update visualObjectInstancesToPersist\r\n */\r\n private onColumnAutosized(queryName: string): void {\r\n // If AutoSize option is ON, remove the persisted value\r\n // Else, update the persisted value\r\n let width: number = this.currentAutoColumnSizePropertyValue ? undefined : -1;\r\n\r\n for (let obj of this.columnWidthObjects) {\r\n if (obj.queryName === queryName) {\r\n obj.width = width;\r\n // ToDo: make sure aligning size works\r\n }\r\n };\r\n\r\n // If AutoSize option is ON, remove the persisted value\r\n if (this.currentAutoColumnSizePropertyValue) {\r\n this.visualObjectInstancesToPersist = {\r\n remove: [{\r\n selector: { metadata: queryName },\r\n objectName: 'general',\r\n properties: { columnWidth: undefined }\r\n }],\r\n };\r\n\r\n this.callHostToPersist(false);\r\n }\r\n\r\n // Else, do nothing. A Column Resize will be triggered soon\r\n }\r\n\r\n /**\r\n * Handler for a column width change by the user\r\n * @param {number} index zero-based index of the column, including hidden row header for table\r\n * @param {number} width new width\r\n */\r\n public onColumnWidthChanged(index: number, width: number): void {\r\n // Table has a hidden row headers column\r\n let colIndex = this.isMatrix ? index : index - 1;\r\n\r\n if (_.isEmpty(this.columnWidthObjects) || colIndex < 0 || colIndex >= this.columnWidthObjects.length)\r\n return;\r\n\r\n let queryName = this.columnWidthObjects[colIndex].queryName;\r\n\r\n // Column Autosize\r\n if (width === -1)\r\n {\r\n this.onColumnAutosized(queryName);\r\n }\r\n else {\r\n for (let obj of this.columnWidthObjects) {\r\n if (obj.queryName === queryName) {\r\n obj.width = width;\r\n }\r\n };\r\n\r\n this.callHostToPersist(true);\r\n }\r\n }\r\n\r\n /**\r\n * Persist all column widths, called when autoSizeColumns flipped to false\r\n * @param {number[]} widthsToPersist Widths to persist, including an empty row header for table\r\n */\r\n public persistAllColumnWidths(widthsToPersist: number[]): void {\r\n // Table indices are offset with an empty header. \r\n let widths = this.isMatrix ? widthsToPersist : widthsToPersist.slice(1, widthsToPersist.length);\r\n\r\n // ToDo: Handle this properly\r\n // This happens when autosizing turns OFF before knowing all widths (lots of columns outside of ViewPort)\r\n if (this.columnWidthObjects.length !== widths.length) {\r\n return;\r\n }\r\n\r\n // Pick the maximum for each queryName\r\n // This will ensure going from autoSize ON to OFF will not show any ellipsis\r\n let dictionary = new Array<number>();\r\n widths.forEach((w, i) => {\r\n let query = this.columnWidthObjects[i].queryName;\r\n if (dictionary[query] == null)\r\n dictionary[query] = w;\r\n else\r\n dictionary[query] = Math.max(w, dictionary[query]);\r\n });\r\n\r\n for (let obj of this.columnWidthObjects) {\r\n let width = dictionary[obj.queryName];\r\n if (width != null)\r\n obj.width = width;\r\n }\r\n\r\n this.callHostToPersist(true);\r\n }\r\n\r\n /**\r\n * Construct a ColumnAutoSize object\r\n * @returns ColumnAutoSize object\r\n */\r\n private getAutoSizeColumnWidthObject(): VisualObjectInstance {\r\n return {\r\n selector: null,\r\n objectName: 'general',\r\n properties: {\r\n autoSizeColumnWidth: this.currentAutoColumnSizePropertyValue\r\n }\r\n };\r\n }\r\n /**\r\n * Generate visualObjectInstances with autoSizeColumns and Column Widths\r\n */\r\n private generateVisualObjectInstancesToPersist(): void {\r\n // ToDo: Ensure lists need to be reset after call to persist\r\n\r\n // AutoSize Property\r\n this.visualObjectInstancesToPersist = {\r\n merge: [this.getAutoSizeColumnWidthObject()]\r\n };\r\n\r\n // Column Widths\r\n let added = new Array<boolean>();\r\n for (let obj of this.columnWidthObjects) {\r\n // Only persist width if we have a valid queryName to use as selector\r\n // ToDo: Not sure how we can have an item without a queryName\r\n if (obj.queryName && _.isNumber(obj.width) && !added[obj.queryName]) {\r\n this.visualObjectInstancesToPersist.merge.push({\r\n selector: { metadata: obj.queryName },\r\n objectName: 'general',\r\n properties: {\r\n columnWidth: obj.width\r\n }\r\n });\r\n\r\n added[obj.queryName] = true;\r\n }\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface AnimatedTextConfigurationSettings {\r\n align?: string;\r\n maxFontSize?: number;\r\n }\r\n\r\n /**\r\n * Base class for values that are animated when resized.\r\n */\r\n export class AnimatedText {\r\n\r\n /** Note: Public for testability */\r\n public static formatStringProp: DataViewObjectPropertyIdentifier = {\r\n objectName: 'general',\r\n propertyName: 'formatString',\r\n };\r\n\r\n protected animator: IGenericAnimator;\r\n\r\n private name: string;\r\n\r\n /** Note: Public for testability */\r\n public svg: D3.Selection;\r\n public currentViewport: IViewport;\r\n public value: any;\r\n public hostServices: IVisualHostServices;\r\n public style: IVisualStyle;\r\n public visualConfiguration: AnimatedTextConfigurationSettings;\r\n public metaDataColumn: DataViewMetadataColumn;\r\n\r\n private mainText: jsCommon.CssConstants.ClassAndSelector = jsCommon.CssConstants.createClassAndSelector('mainText');\r\n\r\n public constructor(name: string) {\r\n this.name = name;\r\n this.visualConfiguration = { maxFontSize: 60 };\r\n }\r\n\r\n public getMetaDataColumn(dataView: DataView) {\r\n if (dataView && dataView.metadata && dataView.metadata.columns) {\r\n for (let i = 0, ilen = dataView.metadata.columns.length; i < ilen; i++) {\r\n let column = dataView.metadata.columns[i];\r\n if (column.isMeasure) {\r\n this.metaDataColumn = column;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n public getAdjustedFontHeight(\r\n availableWidth: number,\r\n textToMeasure: string,\r\n seedFontHeight: number): number {\r\n \r\n let textProperties: TextProperties= {\r\n fontFamily: null,\r\n fontSize: null,\r\n text: textToMeasure\r\n };\r\n \r\n let fontHeight = this.getAdjustedFontHeightCore(\r\n textProperties,\r\n availableWidth,\r\n seedFontHeight,\r\n 0);\r\n\r\n return fontHeight;\r\n }\r\n\r\n private getAdjustedFontHeightCore(\r\n textProperties: TextProperties,\r\n availableWidth: number,\r\n seedFontHeight: number,\r\n iteration: number): number {\r\n \r\n // Too many attempts - just return what we have so we don't sacrifice perf\r\n if (iteration > 10) {\r\n return seedFontHeight;\r\n }\r\n\r\n textProperties.fontSize = jsCommon.PixelConverter.toString(seedFontHeight);\r\n\r\n let candidateLength = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n if (candidateLength < availableWidth)\r\n return seedFontHeight;\r\n\r\n return this.getAdjustedFontHeightCore(textProperties, availableWidth, seedFontHeight * 0.9, iteration + 1);\r\n }\r\n\r\n public clear() {\r\n this.svg.select(this.mainText.selector).text('');\r\n }\r\n\r\n public doValueTransition(\r\n startValue: any,\r\n endValue: any,\r\n displayUnitSystemType: DisplayUnitSystemType,\r\n animationOptions: AnimationOptions,\r\n duration: number,\r\n forceUpdate: boolean,\r\n formatter?: IValueFormatter): void {\r\n if (!forceUpdate && startValue === endValue && endValue != null)\r\n return;\r\n\r\n if (!startValue)\r\n startValue = 0;\r\n\r\n let svg = this.svg,\r\n viewport = this.currentViewport,\r\n height = viewport.height,\r\n width = viewport.width,\r\n endValueArr = [endValue],\r\n seedFontHeight = this.getSeedFontHeight(width, height),\r\n translateX = this.getTranslateX(width),\r\n translateY = this.getTranslateY(seedFontHeight),\r\n metaDataColumn = this.metaDataColumn;\r\n\r\n // Respect the formatter default value\r\n if (!formatter) {\r\n formatter = valueFormatter.create({\r\n format: this.getFormatString(metaDataColumn),\r\n value: endValue,\r\n displayUnitSystemType: displayUnitSystemType,\r\n formatSingleValues: true,\r\n allowFormatBeautification: true,\r\n columnType: metaDataColumn ? metaDataColumn.type : undefined\r\n });\r\n }\r\n let startText = formatter.format(startValue),\r\n endText = formatter.format(endValue);\r\n\r\n svg.attr('class', this.name);\r\n\r\n let textElement = svg\r\n .selectAll('text')\r\n .data(endValueArr);\r\n\r\n textElement\r\n .enter()\r\n .append('text')\r\n .attr('class', this.mainText.class);\r\n\r\n let fontHeight = this.getAdjustedFontHeight(width, endText, seedFontHeight);\r\n translateY = this.getTranslateY(fontHeight + (height - fontHeight) / 2);\r\n\r\n let textElementUpdate = textElement\r\n .text(startText)\r\n .attr({\r\n 'text-anchor': this.getTextAnchor(),\r\n 'font-size': fontHeight,\r\n 'transform': SVGUtil.translate(translateX, translateY),\r\n })\r\n .style({\r\n 'fill': this.style.titleText.color.value,\r\n })\r\n .call(tooltipUtils.tooltipUpdate, [startText]);\r\n\r\n if (endValue == null) {\r\n textElementUpdate.text(endText).call(tooltipUtils.tooltipUpdate, [endText]);\r\n }\r\n else if (metaDataColumn && AxisHelper.isDateTime(metaDataColumn.type)) {\r\n textElementUpdate.text(endText).call(tooltipUtils.tooltipUpdate, [endText]);\r\n }\r\n else {\r\n let interpolatedValue = startValue;\r\n textElementUpdate\r\n .transition()\r\n .duration(duration)\r\n .tween('text', function (d) {\r\n let i = d3.interpolate(interpolatedValue, d);\r\n return function (t) {\r\n let num = i(t);\r\n this.textContent = formatter.format(num);\r\n };\r\n });\r\n }\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(animationOptions);\r\n }\r\n\r\n public setTextColor(color: string): void {\r\n this.style.titleText.color.value = color;\r\n }\r\n\r\n public getSeedFontHeight(boundingWidth: number, boundingHeight: number) {\r\n // Simply an estimate - it should eventually be modified based on the actual text length\r\n let estimatedSize = Math.floor(Math.min(boundingWidth, boundingHeight) * 0.75);\r\n let maxFontSize = this.visualConfiguration.maxFontSize;\r\n\r\n if (maxFontSize)\r\n return Math.min(maxFontSize, estimatedSize);\r\n\r\n return estimatedSize;\r\n }\r\n\r\n public getTranslateX(width: number): number {\r\n if (this.visualConfiguration) {\r\n switch (this.visualConfiguration.align) {\r\n case 'left':\r\n return 0;\r\n case 'right':\r\n return width;\r\n }\r\n }\r\n return width / 2;\r\n }\r\n\r\n public getTranslateY(height: number): number {\r\n return height;\r\n }\r\n\r\n public getTextAnchor(): string {\r\n if (this.visualConfiguration) {\r\n switch (this.visualConfiguration.align) {\r\n case 'left':\r\n return 'start';\r\n case 'right':\r\n return 'end';\r\n }\r\n }\r\n return 'middle';\r\n }\r\n\r\n protected getFormatString(column: DataViewMetadataColumn): string {\r\n debug.assertAnyValue(column, 'column');\r\n\r\n return valueFormatter.getFormatString(column, AnimatedText.formatStringProp);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n /**\r\n * Renders a number that can be animate change in value.\r\n */\r\n export class AnimatedNumber extends AnimatedText implements IVisual {\r\n private options: VisualInitOptions;\r\n\r\n // TODO: Remove this once all visuals have implemented update.\r\n private dataViews: DataView[];\r\n private formatter: IValueFormatter;\r\n\r\n public constructor(svg?: D3.Selection, animator?: IGenericAnimator) {\r\n super('animatedNumber');\r\n\r\n if (svg)\r\n this.svg = svg;\r\n if (animator)\r\n this.animator = animator;\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n this.options = options;\r\n let element = options.element;\r\n\r\n if (!this.svg)\r\n this.svg = d3.select(element.get(0)).append('svg');\r\n\r\n this.currentViewport = options.viewport;\r\n this.hostServices = options.host;\r\n this.style = options.style;\r\n this.updateViewportDependantProperties();\r\n }\r\n\r\n public updateViewportDependantProperties() {\r\n let viewport = this.currentViewport;\r\n this.svg.attr('width', viewport.width)\r\n .attr('height', viewport.height);\r\n }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n debug.assertValue(options, 'options');\r\n\r\n this.currentViewport = options.viewport;\r\n let dataViews = this.dataViews = options.dataViews;\r\n\r\n if (!dataViews || !dataViews[0]) {\r\n return;\r\n }\r\n\r\n let dataView = dataViews[0];\r\n this.updateViewportDependantProperties();\r\n this.getMetaDataColumn(dataView);\r\n let newValue = dataView && dataView.single ? dataView.single.value : 0;\r\n if (newValue != null) {\r\n this.updateInternal(newValue, options.suppressAnimations, true, this.formatter);\r\n }\r\n }\r\n\r\n public setFormatter(formatter?: IValueFormatter): void {\r\n this.formatter = formatter;\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n this.update({\r\n dataViews: options.dataViews,\r\n suppressAnimations: options.suppressAnimations,\r\n viewport: this.currentViewport\r\n });\r\n }\r\n\r\n public onResizing(viewport: IViewport): void {\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n this.update({\r\n dataViews: this.dataViews,\r\n suppressAnimations: true,\r\n viewport: viewport\r\n });\r\n }\r\n\r\n public canResizeTo(viewport: IViewport): boolean {\r\n // Temporarily disabling resize restriction.\r\n return true;\r\n }\r\n\r\n private updateInternal(target: number, suppressAnimations: boolean, forceUpdate: boolean = false, formatter?: IValueFormatter) {\r\n let start = this.value || 0;\r\n let duration = AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n\r\n this.doValueTransition(\r\n start,\r\n target,\r\n /*displayUnitSystemType*/ null,\r\n this.options.animation,\r\n duration,\r\n forceUpdate,\r\n formatter);\r\n\r\n this.value = target;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface BasicShapeDataViewObjects extends DataViewObjects {\r\n general: BasicShapeDataViewObject;\r\n line: LineObject;\r\n fill: FillObject;\r\n rotation: RotationObject;\r\n }\r\n\r\n export interface LineObject extends DataViewObject {\r\n lineColor: Fill;\r\n roundEdge: number;\r\n weight: number;\r\n transparency: number;\r\n }\r\n\r\n export interface FillObject extends DataViewObject {\r\n transparency: number;\r\n fillColor: Fill;\r\n show: boolean;\r\n }\r\n\r\n export interface RotationObject extends DataViewObject {\r\n angle: number;\r\n }\r\n\r\n export interface BasicShapeDataViewObject extends DataViewObject {\r\n shapeType: string;\r\n shapeSvg: string;\r\n }\r\n\r\n export interface BasicShapeData {\r\n shapeType: string;\r\n lineColor: string;\r\n lineTransparency: number;\r\n lineWeight: number;\r\n showFill: boolean;\r\n fillColor: string;\r\n shapeTransparency: number;\r\n roundEdge: number;\r\n angle: number;\r\n }\r\n\r\n export class BasicShapeVisual implements IVisual {\r\n private currentViewport: IViewport;\r\n private element: JQuery;\r\n private data: BasicShapeData;\r\n private selection: D3.Selection;\r\n\r\n public static DefaultShape: string = basicShapeType.rectangle;\r\n public static DefaultStrokeColor: string = '#00B8AA';\r\n public static DefaultFillColor: string = '#E6E6E6';\r\n public static DefaultFillShowValue: boolean = true; \r\n public static DefaultFillTransValue: number = 0;\r\n public static DefaultWeightValue: number = 3;\r\n public static DefaultLineTransValue: number = 0;\r\n public static DefaultRoundEdgeValue: number = 0;\r\n public static DefaultAngle: number = 0;\r\n\r\n /**property for the shape line color */\r\n get shapeType(): string {\r\n return this.data ? this.data.shapeType : BasicShapeVisual.DefaultShape;\r\n }\r\n set shapeType(shapeType: string) {\r\n this.data.shapeType = shapeType;\r\n }\r\n\r\n /**property for the shape line color */\r\n get lineColor(): string {\r\n return this.data ? this.data.lineColor : BasicShapeVisual.DefaultStrokeColor;\r\n }\r\n set lineColor(color: string) {\r\n this.data.lineColor = color;\r\n }\r\n /**property for the shape line transparency */\r\n get lineTransparency(): number {\r\n return this.data ? this.data.lineTransparency : BasicShapeVisual.DefaultLineTransValue;\r\n }\r\n set lineTransparency(trans: number) {\r\n this.data.lineTransparency = trans;\r\n }\r\n /**property for the shape line weight */\r\n get lineWeight(): number {\r\n return this.data ? this.data.lineWeight : BasicShapeVisual.DefaultWeightValue;\r\n }\r\n set lineWeight(weight: number) {\r\n this.data.lineWeight = weight;\r\n }\r\n /**property for the shape round edge */\r\n get roundEdge(): number {\r\n return this.data ? this.data.roundEdge : BasicShapeVisual.DefaultRoundEdgeValue;\r\n }\r\n set roundEdge(roundEdge: number) {\r\n this.data.roundEdge = roundEdge;\r\n }\r\n /**property for showing the fill properties */\r\n get showFill(): boolean {\r\n return this.data ? this.data.showFill : BasicShapeVisual.DefaultFillShowValue;\r\n }\r\n set showFill(show: boolean) {\r\n this.data.showFill = show;\r\n }\r\n /**property for the shape line color */\r\n get fillColor(): string {\r\n return this.data ? this.data.fillColor : BasicShapeVisual.DefaultFillColor;\r\n }\r\n set fillColor(color: string) {\r\n this.data.fillColor = color;\r\n }\r\n /**property for the shape fill transparency */\r\n get shapeTransparency(): number {\r\n return this.data ? this.data.shapeTransparency : BasicShapeVisual.DefaultFillTransValue;\r\n }\r\n set shapeTransparency(trans: number) {\r\n this.data.shapeTransparency = trans;\r\n }\r\n /**property for the shape angle */\r\n get angle(): number {\r\n return this.data ? this.data.angle : BasicShapeVisual.DefaultAngle;\r\n }\r\n set angle(angle: number) {\r\n this.data.angle = this.scaleTo360Deg(angle);\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n this.element = options.element;\r\n this.selection = d3.select(this.element.context);\r\n this.currentViewport = options.viewport;\r\n }\r\n\r\n public constructor(options?: VisualInitOptions) {\r\n }\r\n\r\n public update(options: VisualUpdateOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n this.currentViewport = options.viewport;\r\n\r\n let dataViews = options.dataViews;\r\n if (!_.isEmpty(dataViews)) {\r\n let dataView = options.dataViews[0];\r\n if (dataView.metadata && dataView.metadata.objects) {\r\n let dataViewObject = <BasicShapeDataViewObjects>options.dataViews[0].metadata.objects;\r\n this.data = this.getDataFromDataView(dataViewObject);\r\n }\r\n }\r\n\r\n this.render();\r\n }\r\n\r\n private getDataFromDataView(dataViewObject: BasicShapeDataViewObjects): BasicShapeData {\r\n if (dataViewObject) {\r\n return {\r\n shapeType: DataViewObjects.getValue(dataViewObject, basicShapeProps.general.shapeType, BasicShapeVisual.DefaultShape),\r\n lineColor: this.getValueFromColor(DataViewObjects.getValue(dataViewObject, basicShapeProps.line.lineColor, BasicShapeVisual.DefaultStrokeColor)),\r\n lineTransparency: DataViewObjects.getValue(dataViewObject, basicShapeProps.line.transparency, BasicShapeVisual.DefaultLineTransValue),\r\n lineWeight: DataViewObjects.getValue(dataViewObject, basicShapeProps.line.weight, BasicShapeVisual.DefaultWeightValue),\r\n roundEdge: DataViewObjects.getValue(dataViewObject, basicShapeProps.line.roundEdge, BasicShapeVisual.DefaultRoundEdgeValue),\r\n shapeTransparency: DataViewObjects.getValue(dataViewObject, basicShapeProps.fill.transparency, BasicShapeVisual.DefaultFillTransValue),\r\n fillColor: this.getValueFromColor(DataViewObjects.getValue(dataViewObject, basicShapeProps.fill.fillColor, BasicShapeVisual.DefaultFillColor)),\r\n showFill: DataViewObjects.getValue(dataViewObject, basicShapeProps.fill.show, BasicShapeVisual.DefaultFillShowValue),\r\n angle: this.scaleTo360Deg(DataViewObjects.getValue(dataViewObject, basicShapeProps.rotation.angle, BasicShapeVisual.DefaultAngle))\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private scaleTo360Deg(angle: number): number {\r\n if (angle !== 0 && (Math.abs(angle) % 360) === 0) return angle;\r\n\r\n angle = angle % 360;\r\n angle = (angle + 360) % 360;\r\n\r\n return angle;\r\n }\r\n\r\n private getValueFromColor(color: any): string {\r\n return color.solid ? color.solid.color : color;\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] {\r\n let objectInstances: VisualObjectInstance[] = [];\r\n\r\n switch (options.objectName) {\r\n case 'line':\r\n let instance: VisualObjectInstance = {\r\n selector: null,\r\n properties: {\r\n lineColor: this.lineColor,\r\n transparency: this.lineTransparency,\r\n weight: this.lineWeight\r\n },\r\n objectName: options.objectName\r\n };\r\n if (this.data.shapeType === basicShapeType.rectangle) {\r\n instance.properties['roundEdge'] = this.roundEdge;\r\n }\r\n\r\n objectInstances.push(instance);\r\n return objectInstances;\r\n case 'fill':\r\n if (this.shapeType !== basicShapeType.line) {\r\n objectInstances.push({\r\n selector: null,\r\n properties: {\r\n show: this.showFill,\r\n fillColor: this.fillColor,\r\n transparency: this.shapeTransparency\r\n },\r\n objectName: options.objectName\r\n });\r\n }\r\n return objectInstances;\r\n case 'rotation':\r\n objectInstances.push({\r\n selector: null,\r\n properties: {\r\n angle: this.angle\r\n },\r\n objectName: options.objectName\r\n });\r\n\r\n return objectInstances;\r\n }\r\n\r\n return null;\r\n\r\n }\r\n\r\n public render(): void {\r\n this.selection.html('');\r\n \r\n switch (this.shapeType) {\r\n case basicShapeType.rectangle:\r\n ShapeFactory.createRectangle(\r\n this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\r\n break;\r\n case basicShapeType.oval:\r\n ShapeFactory.createOval(\r\n this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\r\n break;\r\n case basicShapeType.line:\r\n ShapeFactory.createLine(\r\n this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\r\n break;\r\n case basicShapeType.arrow:\r\n ShapeFactory.createUpArrow(\r\n this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\r\n break;\r\n case basicShapeType.triangle:\r\n ShapeFactory.createTriangle(\r\n this.data, this.currentViewport.height, this.currentViewport.width, this.selection, this.angle);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import EnumExtensions = jsCommon.EnumExtensions;\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n const DEFAULT_AXIS_SCALE_TYPE: string = axisScale.linear;\r\n const COMBOCHART_DOMAIN_OVERLAP_TRESHOLD_PERCENTAGE = 0.1;\r\n // the interactive right margin is set to be the circle selection radius of the hover line\r\n const INTERACTIVITY_RIGHT_MARGIN = 6;\r\n export const DEFAULT_AXIS_COLOR = '#777';\r\n\r\n export const enum CartesianChartType {\r\n Line,\r\n Area,\r\n StackedArea,\r\n ClusteredColumn,\r\n StackedColumn,\r\n ClusteredBar,\r\n StackedBar,\r\n HundredPercentStackedBar,\r\n HundredPercentStackedColumn,\r\n Scatter,\r\n ComboChart,\r\n DataDot,\r\n Waterfall,\r\n LineClusteredColumnCombo,\r\n LineStackedColumnCombo,\r\n DataDotClusteredColumnCombo,\r\n DataDotStackedColumnCombo,\r\n }\r\n\r\n export interface CalculateScaleAndDomainOptions {\r\n viewport: IViewport;\r\n margin: IMargin;\r\n showCategoryAxisLabel: boolean;\r\n showValueAxisLabel: boolean;\r\n forceMerge: boolean;\r\n categoryAxisScaleType: string;\r\n valueAxisScaleType: string;\r\n trimOrdinalDataOnOverflow: boolean;\r\n // optional\r\n playAxisControlLayout?: IRect;\r\n forcedTickCount?: number;\r\n forcedYDomain?: any[];\r\n forcedXDomain?: any[];\r\n ensureXDomain?: NumberRange;\r\n ensureYDomain?: NumberRange;\r\n categoryAxisDisplayUnits?: number;\r\n categoryAxisPrecision?: number;\r\n valueAxisDisplayUnits?: number;\r\n valueAxisPrecision?: number;\r\n }\r\n\r\n export interface MergedValueAxisResult {\r\n domain: number[];\r\n merged: boolean;\r\n tickCount: number;\r\n }\r\n\r\n export interface CartesianSmallViewPortProperties {\r\n hideLegendOnSmallViewPort: boolean;\r\n hideAxesOnSmallViewPort: boolean;\r\n MinHeightLegendVisible: number;\r\n MinHeightAxesVisible: number;\r\n }\r\n\r\n export interface AxisRenderingOptions {\r\n axisLabels: ChartAxesLabels;\r\n viewport: IViewport;\r\n margin: IMargin;\r\n hideXAxisTitle: boolean;\r\n hideYAxisTitle: boolean;\r\n hideY2AxisTitle?: boolean;\r\n xLabelColor?: Fill;\r\n yLabelColor?: Fill;\r\n y2LabelColor?: Fill;\r\n fontSize: number;\r\n }\r\n\r\n export interface CartesianConstructorOptions {\r\n chartType: CartesianChartType;\r\n isScrollable?: boolean;\r\n animator?: IGenericAnimator;\r\n cartesianSmallViewPortProperties?: CartesianSmallViewPortProperties;\r\n behavior?: IInteractiveBehavior;\r\n isLabelInteractivityEnabled?: boolean;\r\n tooltipsEnabled?: boolean;\r\n lineChartLabelDensityEnabled?: boolean;\r\n trimOrdinalDataOnOverflow?: boolean;\r\n }\r\n\r\n export interface ICartesianVisual {\r\n init(options: CartesianVisualInitOptions): void;\r\n setData(dataViews: DataView[]): void;\r\n calculateAxesProperties(options: CalculateScaleAndDomainOptions): IAxisProperties[];\r\n overrideXScale(xProperties: IAxisProperties): void;\r\n render(suppressAnimations: boolean, resizeMode?: ResizeMode): CartesianVisualRenderResult;\r\n calculateLegend(): LegendData;\r\n hasLegend(): boolean;\r\n onClearSelection(): void;\r\n enumerateObjectInstances?(enumeration: ObjectEnumerationBuilder, options: EnumerateVisualObjectInstancesOptions): void;\r\n getVisualCategoryAxisIsScalar?(): boolean;\r\n getSupportedCategoryAxisType?(): string;\r\n getPreferredPlotArea?(isScalar: boolean, categoryCount: number, categoryThickness: number): IViewport;\r\n setFilteredData?(startIndex: number, endIndex: number): CartesianData;\r\n supportsTrendLine?(): boolean;\r\n }\r\n\r\n export interface CartesianVisualConstructorOptions {\r\n isScrollable: boolean;\r\n interactivityService?: IInteractivityService;\r\n animator?: IGenericAnimator;\r\n isLabelInteractivityEnabled?: boolean;\r\n tooltipsEnabled?: boolean;\r\n lineChartLabelDensityEnabled?: boolean;\r\n }\r\n\r\n export interface CartesianVisualRenderResult {\r\n dataPoints: SelectableDataPoint[];\r\n behaviorOptions: any;\r\n labelDataPoints: LabelDataPoint[];\r\n labelsAreNumeric: boolean;\r\n labelDataPointGroups?: LabelDataPointsGroup[];\r\n }\r\n\r\n export interface CartesianDataPoint {\r\n categoryValue: any;\r\n value: number;\r\n categoryIndex: number;\r\n seriesIndex: number;\r\n highlight?: boolean;\r\n }\r\n\r\n export interface CartesianSeries {\r\n data: CartesianDataPoint[];\r\n }\r\n\r\n export interface CartesianData {\r\n series: CartesianSeries[];\r\n categoryMetadata: DataViewMetadataColumn;\r\n categories: any[];\r\n hasHighlights?: boolean;\r\n }\r\n\r\n export interface CartesianVisualInitOptions extends VisualInitOptions {\r\n svg: D3.Selection;\r\n cartesianHost: ICartesianVisualHost;\r\n chartType?: CartesianChartType;\r\n labelsContext?: D3.Selection; //TEMPORARY - for PlayAxis\r\n }\r\n\r\n export interface ICartesianVisualHost {\r\n updateLegend(data: LegendData): void;\r\n getSharedColors(): IDataColorPalette;\r\n triggerRender(suppressAnimations: boolean): void;\r\n }\r\n\r\n export interface ChartAxesLabels {\r\n x: string;\r\n y: string;\r\n y2?: string;\r\n }\r\n\r\n export const enum AxisLinesVisibility {\r\n ShowLinesOnXAxis = 1,\r\n ShowLinesOnYAxis = 2,\r\n ShowLinesOnBothAxis = ShowLinesOnXAxis | ShowLinesOnYAxis,\r\n }\r\n\r\n export interface CategoryLayout {\r\n categoryCount: number;\r\n categoryThickness: number;\r\n outerPaddingRatio: number;\r\n isScalar?: boolean;\r\n }\r\n\r\n export interface CategoryLayoutOptions {\r\n availableWidth: number;\r\n categoryCount: number;\r\n domain: any;\r\n trimOrdinalDataOnOverflow: boolean;\r\n isScalar?: boolean;\r\n isScrollable?: boolean;\r\n }\r\n\r\n export interface CartesianAxisProperties {\r\n x: IAxisProperties;\r\n y1: IAxisProperties;\r\n y2?: IAxisProperties;\r\n }\r\n\r\n export interface ReferenceLineOptions {\r\n graphicContext: D3.Selection;\r\n referenceLineProperties: DataViewObject;\r\n axes: CartesianAxisProperties;\r\n viewport: IViewport;\r\n classAndSelector: ClassAndSelector;\r\n defaultColor: string;\r\n isHorizontal: boolean;\r\n }\r\n\r\n export interface ReferenceLineDataLabelOptions {\r\n referenceLineProperties: DataViewObject;\r\n axes: CartesianAxisProperties;\r\n viewport: IViewport;\r\n defaultColor: string;\r\n isHorizontal: boolean;\r\n key: string;\r\n }\r\n\r\n type RenderPlotAreaDelegate = (\r\n layers: ICartesianVisual[],\r\n axesLayout: CartesianAxesLayout,\r\n suppressAnimations: boolean) => void;\r\n\r\n /** \r\n * Renders a data series as a cartestian visual.\r\n */\r\n export class CartesianChart implements IVisual {\r\n public static MinOrdinalRectThickness = 20;\r\n public static MinScalarRectThickness = 2;\r\n public static OuterPaddingRatio = 0.4;\r\n public static InnerPaddingRatio = 0.2;\r\n public static TickLabelPadding = 2; // between text labels, used by AxisHelper\r\n\r\n private static ClassName = 'cartesianChart';\r\n private static PlayAxisBottomMargin = 80; //do not change unless we add dynamic label measurements for play slider\r\n private static FontSize = 11;\r\n private static FontSizeString = jsCommon.PixelConverter.toString(CartesianChart.FontSize);\r\n\r\n public static AxisTextProperties: TextProperties = {\r\n fontFamily: 'wf_segoe-ui_normal',\r\n fontSize: CartesianChart.FontSizeString,\r\n };\r\n\r\n private element: JQuery;\r\n private chartAreaSvg: D3.Selection;\r\n private clearCatcher: D3.Selection;\r\n private type: CartesianChartType;\r\n private hostServices: IVisualHostServices;\r\n private layers: ICartesianVisual[];\r\n private legend: ILegend;\r\n private legendMargins: IViewport;\r\n private layerLegendData: LegendData;\r\n private hasSetData: boolean;\r\n private visualInitOptions: VisualInitOptions;\r\n private legendObjectProperties: DataViewObject;\r\n private categoryAxisProperties: DataViewObject;\r\n private valueAxisProperties: DataViewObject;\r\n private xAxisReferenceLines: DataViewObjectMap;\r\n private y1AxisReferenceLines: DataViewObjectMap;\r\n private cartesianSmallViewPortProperties: CartesianSmallViewPortProperties;\r\n private interactivityService: IInteractivityService;\r\n private behavior: IInteractiveBehavior;\r\n private sharedColorPalette: SharedColorPalette;\r\n private isLabelInteractivityEnabled: boolean;\r\n private tooltipsEnabled: boolean;\r\n private lineChartLabelDensityEnabled: boolean;\r\n private trimOrdinalDataOnOverflow: boolean;\r\n private isMobileChart: boolean;\r\n\r\n private trendLines: TrendLine[];\r\n\r\n private xRefLine: ClassAndSelector = createClassAndSelector('x-ref-line');\r\n private y1RefLine: ClassAndSelector = createClassAndSelector('y1-ref-line');\r\n\r\n public animator: IGenericAnimator;\r\n\r\n private axes: CartesianAxes;\r\n private scrollableAxes: ScrollableAxes;\r\n private svgAxes: SvgCartesianAxes;\r\n private svgBrush: SvgBrush;\r\n private renderedPlotArea: IViewport; // to help disable animation when property changes result in layout changes (e.g. 'legend off' should not animate)\r\n\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n private dataViews: DataView[];\r\n private currentViewport: IViewport;\r\n private background: VisualBackground;\r\n\r\n private static getAxisVisibility(type: CartesianChartType): AxisLinesVisibility {\r\n switch (type) {\r\n case CartesianChartType.StackedBar:\r\n case CartesianChartType.ClusteredBar:\r\n case CartesianChartType.HundredPercentStackedBar:\r\n return AxisLinesVisibility.ShowLinesOnXAxis;\r\n case CartesianChartType.Scatter:\r\n return AxisLinesVisibility.ShowLinesOnBothAxis;\r\n default:\r\n return AxisLinesVisibility.ShowLinesOnYAxis;\r\n }\r\n }\r\n\r\n constructor(options: CartesianConstructorOptions) {\r\n let isScrollable = false;\r\n this.trimOrdinalDataOnOverflow = true;\r\n if (options) {\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n this.type = options.chartType;\r\n this.isLabelInteractivityEnabled = options.isLabelInteractivityEnabled;\r\n this.lineChartLabelDensityEnabled = options.lineChartLabelDensityEnabled;\r\n if (options.trimOrdinalDataOnOverflow !== undefined)\r\n this.trimOrdinalDataOnOverflow = options.trimOrdinalDataOnOverflow;\r\n if (options.isScrollable)\r\n isScrollable = options.isScrollable;\r\n this.animator = options.animator;\r\n if (options.cartesianSmallViewPortProperties) {\r\n this.cartesianSmallViewPortProperties = options.cartesianSmallViewPortProperties;\r\n }\r\n\r\n if (options.behavior) {\r\n this.behavior = options.behavior;\r\n }\r\n }\r\n\r\n this.axes = new CartesianAxes(isScrollable, ScrollableAxes.ScrollbarWidth, this.trimOrdinalDataOnOverflow);\r\n this.svgAxes = new SvgCartesianAxes(this.axes);\r\n this.svgBrush = new SvgBrush(ScrollableAxes.ScrollbarWidth);\r\n this.scrollableAxes = new ScrollableAxes(this.axes, this.svgBrush);\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n this.visualInitOptions = options;\r\n this.layers = [];\r\n\r\n let element = this.element = options.element;\r\n\r\n this.currentViewport = options.viewport;\r\n this.hostServices = options.host;\r\n\r\n let chartAreaSvg = this.chartAreaSvg = d3.select(element.get(0)).append('svg');\r\n chartAreaSvg.classed(CartesianChart.ClassName, true);\r\n chartAreaSvg.style('position', 'absolute');\r\n\r\n if (this.behavior) {\r\n this.clearCatcher = appendClearCatcher(chartAreaSvg);\r\n this.interactivityService = createInteractivityService(this.hostServices);\r\n }\r\n\r\n if (options.style.maxMarginFactor != null)\r\n this.axes.setMaxMarginFactor(options.style.maxMarginFactor);\r\n\r\n let axisLinesVisibility = CartesianChart.getAxisVisibility(this.type);\r\n this.axes.setAxisLinesVisibility(axisLinesVisibility);\r\n\r\n this.svgAxes.init(chartAreaSvg);\r\n this.svgBrush.init(chartAreaSvg);\r\n\r\n this.sharedColorPalette = new SharedColorPalette(options.style.colorPalette.dataColors);\r\n\r\n this.legend = createLegend(\r\n element,\r\n options.interactivity && options.interactivity.isInteractiveLegend,\r\n this.type !== CartesianChartType.Waterfall ? this.interactivityService : undefined,\r\n this.axes.isScrollable);\r\n\r\n this.isMobileChart = options.interactivity && options.interactivity.isInteractiveLegend;\r\n }\r\n\r\n private isPlayAxis(): boolean {\r\n if (!this.dataViews || !this.dataViews[0])\r\n return false;\r\n\r\n let dataView = this.dataViews[0];\r\n let categoryRoleIsPlay: boolean = dataView.categorical\r\n && dataView.categorical.categories\r\n && dataView.categorical.categories[0]\r\n && dataView.categorical.categories[0].source\r\n && dataView.categorical.categories[0].source.roles\r\n && dataView.categorical.categories[0].source.roles['Play'];\r\n\r\n return this.type === CartesianChartType.Scatter\r\n && (this.animator || this.isMobileChart)\r\n && dataView.matrix != null\r\n && (!dataView.categorical || categoryRoleIsPlay);\r\n }\r\n\r\n public static getIsScalar(objects: DataViewObjects, propertyId: DataViewObjectPropertyIdentifier, type: ValueTypeDescriptor): boolean {\r\n let axisTypeValue = DataViewObjects.getValue(objects, propertyId);\r\n\r\n if (!objects || axisTypeValue === undefined) {\r\n // If we don't have anything set (Auto), show charts as Scalar if the category type is numeric or time. \r\n // If we have the property, it will override the type.\r\n return !AxisHelper.isOrdinal(type);\r\n }\r\n\r\n // also checking type here to be in sync with AxisHelper, which ignores scalar if the type is non-numeric.\r\n return (axisTypeValue === axisType.scalar) && !AxisHelper.isOrdinal(type);\r\n }\r\n\r\n public static getAdditionalTelemetry(dataView: DataView): any {\r\n let telemetry: any = {};\r\n\r\n let categoryColumn = dataView && dataView.categorical && _.first(dataView.categorical.categories);\r\n if (categoryColumn) {\r\n telemetry.axisType = visuals.CartesianChart.getIsScalar(dataView.metadata.objects, visuals.columnChartProps.categoryAxis.axisType, categoryColumn.source.type)\r\n ? 'scalar'\r\n : 'categorical';\r\n }\r\n\r\n return telemetry;\r\n }\r\n\r\n public static detectScalarMapping(dataViewMapping: data.CompiledDataViewMapping): boolean {\r\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\r\n return false;\r\n\r\n let dataViewCategories = <data.CompiledDataViewRoleForMappingWithReduction>dataViewMapping.categorical.categories;\r\n let categoryItems = dataViewCategories.for.in.items;\r\n if (_.isEmpty(categoryItems))\r\n return false;\r\n\r\n let categoryType = categoryItems[0].type;\r\n\r\n if (!dataViewMapping.metadata)\r\n return false;\r\n\r\n let objects = dataViewMapping.metadata.objects;\r\n\r\n return CartesianChart.getIsScalar(objects, columnChartProps.categoryAxis.axisType, categoryType);\r\n }\r\n\r\n private populateObjectProperties(dataViews: DataView[]) {\r\n if (dataViews && dataViews.length > 0) {\r\n let dataViewMetadata = dataViews[0].metadata;\r\n\r\n if (dataViewMetadata) {\r\n this.legendObjectProperties = DataViewObjects.getObject(dataViewMetadata.objects, 'legend', {});\r\n this.xAxisReferenceLines = DataViewObjects.getUserDefinedObjects(dataViewMetadata.objects, 'xAxisReferenceLine');\r\n this.y1AxisReferenceLines = DataViewObjects.getUserDefinedObjects(dataViewMetadata.objects, 'y1AxisReferenceLine');\r\n }\r\n else {\r\n this.legendObjectProperties = {};\r\n }\r\n\r\n this.categoryAxisProperties = CartesianHelper.getCategoryAxisProperties(dataViewMetadata);\r\n this.valueAxisProperties = CartesianHelper.getValueAxisProperties(dataViewMetadata);\r\n }\r\n }\r\n\r\n private updateInternal(options: VisualUpdateOptions, dataChanged: boolean): void {\r\n let dataViews = this.dataViews = options.dataViews;\r\n this.currentViewport = options.viewport;\r\n\r\n if (!dataViews) return;\r\n\r\n if (this.layers.length === 0) {\r\n // Lazily instantiate the chart layers on the first data load.\r\n let objects: DataViewObjects = this.extractMetadataObjects(dataViews);\r\n this.layers = this.createAndInitLayers(objects);\r\n\r\n debug.assert(this.layers.length > 0, 'createAndInitLayers should update the layers.');\r\n }\r\n let layers = this.layers;\r\n\r\n if (dataChanged) {\r\n if (!_.isEmpty(dataViews)) {\r\n this.populateObjectProperties(dataViews);\r\n this.axes.update(dataViews);\r\n this.svgAxes.update(this.categoryAxisProperties, this.valueAxisProperties);\r\n let dataView = dataViews[0];\r\n if (dataView.metadata) {\r\n // flatten background data\r\n this.background = {\r\n image: DataViewObjects.getValue<ImageValue>(dataView.metadata.objects, scatterChartProps.plotArea.image),\r\n transparency: DataViewObjects.getValue(dataView.metadata.objects, scatterChartProps.plotArea.transparency, visualBackgroundHelper.getDefaultTransparency()),\r\n };\r\n }\r\n }\r\n\r\n this.sharedColorPalette.clearPreferredScale();\r\n let layerDataViews = getLayerDataViews(dataViews);\r\n let trendLineDataViews = _.filter(dataViews, (dataView) => TrendLineHelper.isDataViewForRegression(dataView));\r\n this.trendLines = [];\r\n\r\n for (let i = 0, layerCount = layers.length; i < layerCount; i++) {\r\n let layerDataView = layerDataViews[i];\r\n layers[i].setData(layerDataView ? [layerDataView] : []);\r\n\r\n if (this.supportsTrendLines(i)) {\r\n let trendLineDataView = trendLineDataViews[i];\r\n if (trendLineDataView) {\r\n let y2 = (i > 0);\r\n let trendLines = TrendLineHelper.readDataView(trendLineDataView, layerDataView, y2, this.sharedColorPalette);\r\n this.trendLines.push(...trendLines);\r\n }\r\n }\r\n\r\n if (layerCount > 1)\r\n this.sharedColorPalette.rotateScale();\r\n }\r\n }\r\n\r\n this.render(!this.hasSetData || options.suppressAnimations, options.resizeMode);\r\n\r\n this.hasSetData = this.hasSetData || (dataViews && dataViews.length > 0);\r\n\r\n if (dataViews && dataViews.length > 0) {\r\n let warnings = getInvalidValueWarnings(\r\n dataViews,\r\n false /*supportsNaN*/,\r\n false /*supportsNegativeInfinity*/,\r\n false /*supportsPositiveInfinity*/);\r\n\r\n this.axes.addWarnings(warnings);\r\n\r\n if (warnings && warnings.length > 0)\r\n this.hostServices.setWarnings(warnings);\r\n }\r\n }\r\n\r\n // TODO: Remove onDataChanged & onResizing once we have a flag to distinguish between resize and data changed events.\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n this.updateInternal({\r\n dataViews: options.dataViews,\r\n suppressAnimations: options.suppressAnimations,\r\n viewport: this.currentViewport\r\n }, true);\r\n }\r\n\r\n // TODO: Remove onDataChanged & onResizing once we have a flag to distinguish between resize and data changed events.\r\n public onResizing(viewport: IViewport, resizeMode?: ResizeMode): void {\r\n this.updateInternal({\r\n dataViews: this.dataViews,\r\n suppressAnimations: true,\r\n viewport: viewport,\r\n resizeMode: resizeMode,\r\n }, false);\r\n }\r\n\r\n public scrollTo(position: number): void {\r\n this.scrollableAxes.scrollTo(position);\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n let layersLength = this.layers ? this.layers.length : 0;\r\n\r\n if (options.objectName === 'legend') {\r\n if (!this.shouldShowLegendCard())\r\n return;\r\n\r\n let show = DataViewObject.getValue(this.legendObjectProperties, legendProps.show, this.legend.isVisible());\r\n let showTitle = DataViewObject.getValue(this.legendObjectProperties, legendProps.showTitle, true);\r\n let titleText = DataViewObject.getValue(this.legendObjectProperties, legendProps.titleText, this.layerLegendData ? this.layerLegendData.title : '');\r\n let labelColor = DataViewObject.getValue(this.legendObjectProperties, legendProps.labelColor, LegendData.DefaultLegendLabelFillColor);\r\n let fontSize = DataViewObject.getValue(this.legendObjectProperties, legendProps.fontSize, this.layerLegendData && this.layerLegendData.fontSize ? this.layerLegendData.fontSize : SVGLegend.DefaultFontSizeInPt);\r\n\r\n enumeration.pushInstance({\r\n selector: null,\r\n properties: {\r\n show: show,\r\n position: LegendPosition[this.legend.getOrientation()],\r\n showTitle: showTitle,\r\n titleText: titleText,\r\n labelColor: labelColor,\r\n fontSize: fontSize,\r\n },\r\n objectName: options.objectName\r\n });\r\n }\r\n else if (options.objectName === 'categoryAxis' && this.axes.hasCategoryAxis()) {\r\n this.getCategoryAxisValues(enumeration);\r\n }\r\n else if (options.objectName === 'valueAxis') {\r\n this.getValueAxisValues(enumeration);\r\n }\r\n else if (options.objectName === 'y1AxisReferenceLine') {\r\n let refLinedefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\r\n ReferenceLineHelper.enumerateObjectInstances(enumeration, this.y1AxisReferenceLines, refLinedefaultColor, options.objectName);\r\n }\r\n else if (options.objectName === 'xAxisReferenceLine') {\r\n let refLinedefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\r\n ReferenceLineHelper.enumerateObjectInstances(enumeration, this.xAxisReferenceLines, refLinedefaultColor, options.objectName);\r\n }\r\n else if (options.objectName === 'trend') {\r\n if (this.supportsTrendLines()) {\r\n TrendLineHelper.enumerateObjectInstances(enumeration, this.trendLines);\r\n }\r\n }\r\n else if (options.objectName === 'plotArea') {\r\n visualBackgroundHelper.enumeratePlot(enumeration, this.background);\r\n }\r\n\r\n if (options.objectName === 'dataPoint' &&\r\n ComboChart.isComboChart(this.type)) {\r\n ComboChart.enumerateDataPoints(enumeration, options, this.layers);\r\n }\r\n else {\r\n for (let i = 0, len = layersLength; i < len; i++) {\r\n let layer = this.layers[i];\r\n if (layer.enumerateObjectInstances) {\r\n layer.enumerateObjectInstances(enumeration, options);\r\n }\r\n }\r\n }\r\n\r\n return enumeration.complete();\r\n }\r\n\r\n private supportsTrendLines(layerIndex?: number): boolean {\r\n let layerDataViews = getLayerDataViews(this.dataViews);\r\n\r\n if (_.isEmpty(this.layers))\r\n return false;\r\n\r\n // If layerIndex was not given then check all layers.\r\n let layers = layerIndex == null ? this.layers : [this.layers[layerIndex]];\r\n\r\n return _.all(layers, (layer, index) => {\r\n if (!layerDataViews[index])\r\n return true;\r\n return layer.supportsTrendLine && layer.supportsTrendLine();\r\n });\r\n }\r\n\r\n private shouldShowLegendCard(): boolean {\r\n let layers = this.layers;\r\n let dataViews = this.dataViews;\r\n\r\n if (layers && dataViews) {\r\n let layersLength = layers.length;\r\n let layersWithValuesCtr = 0;\r\n\r\n for (let i = 0; i < layersLength; i++) {\r\n if (layers[i].hasLegend()) {\r\n return true;\r\n }\r\n\r\n // if there are at least two layers with values legend card should be shown (even if each of the individual layers don't have legend)\r\n let dataView = dataViews[i];\r\n if (dataView && dataView.categorical && dataView.categorical.values && dataView.categorical.values.length > 0) {\r\n layersWithValuesCtr++;\r\n if (layersWithValuesCtr > 1) {\r\n return true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private getAxisScaleOptions(axisType: AxisLocation): string[] {\r\n let scaleOptions = [DEFAULT_AXIS_SCALE_TYPE];\r\n if (this.axes.isLogScaleAllowed(axisType))\r\n scaleOptions.push(axisScale.log);\r\n return scaleOptions;\r\n }\r\n\r\n private getCategoryAxisValues(enumeration: ObjectEnumerationBuilder): void {\r\n if (!this.categoryAxisProperties) {\r\n return;\r\n }\r\n let supportedType = axisType.both;\r\n let isScalar = false;\r\n let scaleOptions = this.getAxisScaleOptions(AxisLocation.X);\r\n\r\n if (this.layers && this.layers[0].getSupportedCategoryAxisType) {\r\n supportedType = this.layers[0].getSupportedCategoryAxisType();\r\n if (supportedType === axisType.scalar) {\r\n isScalar = true;\r\n }\r\n else {\r\n isScalar = CartesianHelper.isScalar(supportedType === axisType.both, this.categoryAxisProperties);\r\n }\r\n }\r\n\r\n if (!isScalar) {\r\n this.categoryAxisProperties['start'] = null;\r\n this.categoryAxisProperties['end'] = null;\r\n }\r\n\r\n let instance: VisualObjectInstance = {\r\n selector: null,\r\n properties: {},\r\n objectName: 'categoryAxis',\r\n validValues: {\r\n axisScale: scaleOptions,\r\n axisStyle: this.axes.categoryAxisHasUnitType ? [axisStyle.showTitleOnly, axisStyle.showUnitOnly, axisStyle.showBoth] : [axisStyle.showTitleOnly]\r\n }\r\n };\r\n\r\n instance.properties['show'] = this.categoryAxisProperties['show'] != null ? this.categoryAxisProperties['show'] : true;\r\n if (this.axes.isYAxisCategorical())//in case of e.g. barChart\r\n instance.properties['position'] = this.valueAxisProperties && this.valueAxisProperties['position'] != null ? this.valueAxisProperties['position'] : yAxisPosition.left;\r\n if (supportedType === axisType.both) {\r\n instance.properties['axisType'] = isScalar ? axisType.scalar : axisType.categorical;\r\n }\r\n if (isScalar) {\r\n instance.properties['axisScale'] = this.categoryAxisProperties['axisScale'] || DEFAULT_AXIS_SCALE_TYPE;\r\n instance.properties['start'] = this.categoryAxisProperties['start'];\r\n instance.properties['end'] = this.categoryAxisProperties['end'];\r\n }\r\n instance.properties['showAxisTitle'] = this.categoryAxisProperties['showAxisTitle'] != null ? this.categoryAxisProperties['showAxisTitle'] : false;\r\n\r\n instance.properties['axisStyle'] = this.categoryAxisProperties['axisStyle'] ? this.categoryAxisProperties['axisStyle'] : axisStyle.showTitleOnly;\r\n instance.properties['labelColor'] = this.categoryAxisProperties['labelColor'] || DEFAULT_AXIS_COLOR;\r\n\r\n if (isScalar) {\r\n instance.properties['labelDisplayUnits'] = this.categoryAxisProperties['labelDisplayUnits'] ? this.categoryAxisProperties['labelDisplayUnits'] : 0;\r\n let labelPrecision = this.categoryAxisProperties['labelPrecision'];\r\n instance.properties['labelPrecision'] = (labelPrecision === undefined || labelPrecision < 0)\r\n ? dataLabelUtils.defaultLabelPrecision\r\n : labelPrecision;\r\n }\r\n enumeration.pushInstance(instance);\r\n }\r\n\r\n //todo: wrap all these object getters and other related stuff into an interface\r\n private getValueAxisValues(enumeration: ObjectEnumerationBuilder): void {\r\n if (!this.valueAxisProperties) {\r\n return;\r\n }\r\n let scaleOptions = this.getAxisScaleOptions(AxisLocation.Y1);\r\n let secScaleOption = this.getAxisScaleOptions(AxisLocation.Y2);\r\n\r\n let instance: VisualObjectInstance = {\r\n selector: null,\r\n properties: {},\r\n objectName: 'valueAxis',\r\n validValues: {\r\n axisScale: scaleOptions,\r\n secAxisScale: secScaleOption,\r\n axisStyle: this.axes.valueAxisHasUnitType ? [axisStyle.showTitleOnly, axisStyle.showUnitOnly, axisStyle.showBoth] : [axisStyle.showTitleOnly]\r\n }\r\n };\r\n\r\n instance.properties['show'] = this.valueAxisProperties['show'] != null ? this.valueAxisProperties['show'] : true;\r\n\r\n if (!this.axes.isYAxisCategorical()) {\r\n instance.properties['position'] = this.valueAxisProperties['position'] != null ? this.valueAxisProperties['position'] : yAxisPosition.left;\r\n }\r\n instance.properties['axisScale'] = this.valueAxisProperties['axisScale'] || DEFAULT_AXIS_SCALE_TYPE;\r\n instance.properties['start'] = this.valueAxisProperties['start'];\r\n instance.properties['end'] = this.valueAxisProperties['end'];\r\n instance.properties['showAxisTitle'] = this.valueAxisProperties['showAxisTitle'] != null ? this.valueAxisProperties['showAxisTitle'] : false;\r\n instance.properties['axisStyle'] = this.valueAxisProperties['axisStyle'] != null ? this.valueAxisProperties['axisStyle'] : axisStyle.showTitleOnly;\r\n instance.properties['labelColor'] = this.valueAxisProperties['labelColor'] || DEFAULT_AXIS_COLOR;\r\n\r\n if (this.type !== CartesianChartType.HundredPercentStackedBar && this.type !== CartesianChartType.HundredPercentStackedColumn) {\r\n instance.properties['labelDisplayUnits'] = this.valueAxisProperties['labelDisplayUnits'] ? this.valueAxisProperties['labelDisplayUnits'] : 0;\r\n let labelPrecision = this.valueAxisProperties['labelPrecision'];\r\n instance.properties['labelPrecision'] = (labelPrecision === undefined || labelPrecision < 0)\r\n ? dataLabelUtils.defaultLabelPrecision\r\n : labelPrecision;\r\n }\r\n\r\n enumeration.pushInstance(instance);\r\n\r\n if (this.layers.length === 2) {\r\n instance.properties['secShow'] = this.valueAxisProperties['secShow'] != null ? this.valueAxisProperties['secShow'] : this.axes.hasY2Axis();\r\n if (instance.properties['secShow']) {\r\n instance.properties['axisLabel'] = '';\r\n }\r\n }\r\n\r\n if (this.axes.hasY2Axis() && instance.properties['secShow']) {\r\n enumeration.pushContainer({\r\n displayName: data.createDisplayNameGetter('Visual_YAxis_ShowSecondary'),\r\n });\r\n\r\n let secInstance: VisualObjectInstance = {\r\n selector: null,\r\n properties: {},\r\n objectName: 'valueAxis'\r\n };\r\n secInstance.properties['secAxisLabel'] = '';\r\n secInstance.properties['secPosition'] = this.valueAxisProperties['secPosition'] != null ? this.valueAxisProperties['secPosition'] : yAxisPosition.right;\r\n secInstance.properties['secAxisScale'] = this.valueAxisProperties['secAxisScale'] || DEFAULT_AXIS_SCALE_TYPE;\r\n secInstance.properties['secStart'] = this.valueAxisProperties['secStart'];\r\n secInstance.properties['secEnd'] = this.valueAxisProperties['secEnd'];\r\n secInstance.properties['secShowAxisTitle'] = this.valueAxisProperties['secShowAxisTitle'] != null ? this.valueAxisProperties['secShowAxisTitle'] : false;\r\n\r\n enumeration\r\n .pushInstance(secInstance)\r\n .pushInstance({\r\n selector: null,\r\n properties: {\r\n secAxisStyle: this.valueAxisProperties['secAxisStyle'] ? this.valueAxisProperties['secAxisStyle'] : axisStyle.showTitleOnly,\r\n labelColor: this.valueAxisProperties['secLabelColor'],\r\n secLabelDisplayUnits: this.valueAxisProperties['secLabelDisplayUnits'] ? this.valueAxisProperties['secLabelDisplayUnits'] : 0,\r\n secLabelPrecision: this.valueAxisProperties['secLabelPrecision'] < 0 ? 0 : this.valueAxisProperties['secLabelPrecision']\r\n },\r\n objectName: 'valueAxis',\r\n validValues: {\r\n secAxisStyle: this.axes.secondaryValueAxisHasUnitType ? [axisStyle.showTitleOnly, axisStyle.showUnitOnly, axisStyle.showBoth] : [axisStyle.showTitleOnly],\r\n axisScale: scaleOptions\r\n },\r\n });\r\n\r\n enumeration.popContainer();\r\n }\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.hasSetData) {\r\n for (let i = 0, len = this.layers.length; i < len; i++) {\r\n let layer = this.layers[i];\r\n layer.onClearSelection();\r\n layer.render(true /* suppressAnimations */);\r\n }\r\n }\r\n }\r\n\r\n private extractMetadataObjects(dataViews: DataView[]): DataViewObjects {\r\n let objects: DataViewObjects;\r\n if (dataViews && dataViews.length > 0) {\r\n let dataViewMetadata = dataViews[0].metadata;\r\n if (dataViewMetadata)\r\n objects = dataViewMetadata.objects;\r\n }\r\n return objects;\r\n }\r\n\r\n private createAndInitLayers(objects: DataViewObjects): ICartesianVisual[] {\r\n // Create the layers\r\n let layers = CartesianLayerFactory.createLayers(\r\n this.type,\r\n objects,\r\n this.interactivityService,\r\n this.animator,\r\n this.axes.isScrollable,\r\n this.tooltipsEnabled,\r\n this.lineChartLabelDensityEnabled);\r\n\r\n // Initialize the layers\r\n let cartesianOptions = <CartesianVisualInitOptions>Prototype.inherit(this.visualInitOptions);\r\n cartesianOptions.svg = this.svgAxes.getScrollableRegion();\r\n cartesianOptions.labelsContext = this.svgAxes.getLabelsRegion();\r\n cartesianOptions.cartesianHost = {\r\n updateLegend: data => this.legend.drawLegend(data, this.currentViewport),\r\n getSharedColors: () => this.sharedColorPalette,\r\n triggerRender: (suppressAnimations: boolean) => this.render(suppressAnimations),\r\n };\r\n cartesianOptions.chartType = this.type;\r\n\r\n for (let i = 0, len = layers.length; i < len; i++)\r\n layers[i].init(cartesianOptions);\r\n\r\n return layers;\r\n }\r\n\r\n private renderLegend(): void {\r\n let layers = this.layers;\r\n let legendData: LegendData = { title: \"\", dataPoints: [] };\r\n\r\n for (let i = 0, len = layers.length; i < len; i++) {\r\n this.layerLegendData = layers[i].calculateLegend();\r\n if (this.layerLegendData) {\r\n legendData.title = i === 0 ? this.layerLegendData.title || \"\"\r\n : legendData.title;\r\n legendData.labelColor = this.layerLegendData.labelColor;\r\n \r\n // Data points have have duplicate identities (ex. Combo Chart uses a measure in both line and column).\r\n // Add the layer number (if it's set) so the D3 keys are different.\r\n if (!_.isEmpty(this.layerLegendData.dataPoints)) {\r\n this.layerLegendData.dataPoints.forEach((dataPoint) => dataPoint.layerNumber = i);\r\n }\r\n\r\n legendData.dataPoints = legendData.dataPoints.concat(this.layerLegendData.dataPoints || []);\r\n legendData.fontSize = this.layerLegendData.fontSize || SVGLegend.DefaultFontSizeInPt;\r\n if (this.layerLegendData.grouped) {\r\n legendData.grouped = true;\r\n }\r\n }\r\n }\r\n\r\n let legendProperties = this.legendObjectProperties;\r\n\r\n if (legendProperties) {\r\n LegendData.update(legendData, legendProperties);\r\n let position = <string>legendProperties[legendProps.position];\r\n\r\n if (position)\r\n this.legend.changeOrientation(LegendPosition[position]);\r\n }\r\n else {\r\n this.legend.changeOrientation(LegendPosition.Top);\r\n }\r\n\r\n if ((legendData.dataPoints.length === 1 && !legendData.grouped) || this.hideLegends()) {\r\n legendData.dataPoints = [];\r\n }\r\n\r\n this.legend.drawLegend(legendData, this.currentViewport);\r\n }\r\n\r\n private hideLegends(): boolean {\r\n if (this.cartesianSmallViewPortProperties) {\r\n if (this.cartesianSmallViewPortProperties.hideLegendOnSmallViewPort && (this.currentViewport.height < this.cartesianSmallViewPortProperties.MinHeightLegendVisible)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n private render(suppressAnimations: boolean, resizeMode?: ResizeMode): void {\r\n // Note: interactive legend shouldn't be rendered explicitly here\r\n // The interactive legend is being rendered in the render method of ICartesianVisual\r\n if (!(this.visualInitOptions.interactivity && this.visualInitOptions.interactivity.isInteractiveLegend)) {\r\n this.renderLegend();\r\n }\r\n\r\n let legendMargins = this.legendMargins = this.legend.getMargins();\r\n let legendOrientation = this.legend.getOrientation();\r\n let hideAxisLabels = this.hideAxisLabels(legendMargins);\r\n\r\n let plotAreaViewport: IViewport = {\r\n height: this.currentViewport.height - legendMargins.height,\r\n width: this.currentViewport.width - legendMargins.width\r\n };\r\n\r\n let padding = Prototype.inherit(SvgCartesianAxes.AxisPadding);\r\n let playAxisControlLayout: IRect;\r\n if (this.isPlayAxis()) {\r\n plotAreaViewport.height -= CartesianChart.PlayAxisBottomMargin;\r\n playAxisControlLayout = {\r\n left: Legend.isLeft(legendOrientation) ? legendMargins.width : 0,\r\n top: Legend.isTop(legendOrientation) ? legendMargins.height + plotAreaViewport.height : plotAreaViewport.height,\r\n height: CartesianChart.PlayAxisBottomMargin,\r\n width: plotAreaViewport.width\r\n };\r\n }\r\n\r\n this.chartAreaSvg.attr({\r\n 'width': plotAreaViewport.width,\r\n 'height': plotAreaViewport.height,\r\n });\r\n Legend.positionChartArea(this.chartAreaSvg, this.legend);\r\n\r\n let interactivityRightMargin = this.calculateInteractivityRightMargin();\r\n\r\n let [ensureXDomain, ensureYDomain] = this.getMinimumDomainExtents();\r\n\r\n let axesLayout = this.axes.negotiateAxes(\r\n this.layers,\r\n plotAreaViewport,\r\n padding,\r\n playAxisControlLayout,\r\n hideAxisLabels,\r\n CartesianChart.AxisTextProperties,\r\n interactivityRightMargin,\r\n ensureXDomain,\r\n ensureYDomain);\r\n\r\n // Even if the caller thinks animations are ok, now that we've laid out the axes and legend we should disable animations\r\n // if the plot area changed. Animations for property changes like legend on/off are not desired.\r\n let plotAreaHasChanged: boolean =\r\n !this.renderedPlotArea\r\n || (this.renderedPlotArea.height !== axesLayout.plotArea.height ||\r\n this.renderedPlotArea.width !== axesLayout.plotArea.width);\r\n suppressAnimations = suppressAnimations || plotAreaHasChanged;\r\n\r\n this.scrollableAxes.render(\r\n axesLayout,\r\n this.layers,\r\n suppressAnimations,\r\n (layers, axesLayout, suppressAnimations) => this.renderPlotArea(layers, axesLayout, suppressAnimations, legendMargins, resizeMode));\r\n\r\n // attach scroll event\r\n this.chartAreaSvg.on('wheel', () => {\r\n if (!(this.axes.isXScrollBarVisible || this.axes.isYScrollBarVisible)) return;\r\n TooltipManager.ToolTipInstance.hide();\r\n let wheelEvent: any = d3.event;\r\n let dy = wheelEvent.deltaY;\r\n this.scrollableAxes.scrollDelta(dy);\r\n });\r\n\r\n this.renderedPlotArea = axesLayout.plotArea;\r\n }\r\n\r\n /**\r\n * Gets any minimum domain extents.\r\n * Reference lines and trend lines may enforce minimum extents on X and/or Y domains.\r\n */\r\n private getMinimumDomainExtents(): NumberRange[] {\r\n let xs: number[] = [];\r\n let ys: number[] = [];\r\n\r\n if (!_.isEmpty(this.xAxisReferenceLines)) {\r\n let xAxisReferenceLineProperties: DataViewObject = this.xAxisReferenceLines[0].object;\r\n let value = ReferenceLineHelper.extractReferenceLineValue(xAxisReferenceLineProperties);\r\n xs.push(value);\r\n }\r\n\r\n if (!_.isEmpty(this.y1AxisReferenceLines)) {\r\n let y1AxisReferenceLineProperties: DataViewObject = this.y1AxisReferenceLines[0].object;\r\n let value = ReferenceLineHelper.extractReferenceLineValue(y1AxisReferenceLineProperties);\r\n ys.push(value);\r\n }\r\n\r\n let ensureXDomain: NumberRange = {\r\n min: d3.min(xs),\r\n max: d3.max(xs)\r\n };\r\n\r\n let ensureYDomain: NumberRange = {\r\n min: d3.min(ys),\r\n max: d3.max(ys)\r\n };\r\n\r\n return [ensureXDomain, ensureYDomain];\r\n }\r\n\r\n private getPlotAreaRect(axesLayout: CartesianAxesLayout, legendMargins: IViewport): IRect {\r\n let rect: Rect = {\r\n left: axesLayout.margin.left,\r\n top: axesLayout.margin.top,\r\n width: axesLayout.plotArea.width,\r\n height: axesLayout.plotArea.height,\r\n };\r\n\r\n // Adjust the margins to the legend position \r\n if (this.legend) {\r\n let legendPosition = this.legend.getOrientation();\r\n\r\n if (Legend.isTop(legendPosition)) {\r\n rect.top += legendMargins.height;\r\n }\r\n else if (Legend.isLeft(legendPosition)) {\r\n rect.left += legendMargins.width;\r\n }\r\n }\r\n\r\n return rect;\r\n }\r\n\r\n private renderBackgroundImage(layout: IRect): void {\r\n visualBackgroundHelper.renderBackgroundImage(\r\n this.background,\r\n this.element,\r\n layout);\r\n }\r\n\r\n private hideAxisLabels(legendMargins: IViewport): boolean {\r\n if (this.cartesianSmallViewPortProperties) {\r\n if (this.cartesianSmallViewPortProperties.hideAxesOnSmallViewPort && (this.currentViewport.height < this.cartesianSmallViewPortProperties.MinHeightAxesVisible) && !this.visualInitOptions.interactivity.isInteractiveLegend) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n private calculateInteractivityRightMargin(): number {\r\n // add right margin in order not to cut the circle selection of the hover line \r\n if (this.visualInitOptions.interactivity && this.visualInitOptions.interactivity.isInteractiveLegend && !this.trimOrdinalDataOnOverflow) {\r\n return INTERACTIVITY_RIGHT_MARGIN;\r\n } else {\r\n return 0;\r\n }\r\n }\r\n\r\n private renderPlotArea(\r\n layers: ICartesianVisual[],\r\n axesLayout: CartesianAxesLayout,\r\n suppressAnimations: boolean,\r\n legendMargins: IViewport,\r\n resizeMode?: ResizeMode): void {\r\n debug.assertValue(layers, 'layers');\r\n\r\n let axes = axesLayout.axes;\r\n let plotArea = axesLayout.plotArea;\r\n let plotAreaRect = this.getPlotAreaRect(axesLayout, legendMargins);\r\n let duration = AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n let easing = this.animator && this.animator.getEasing();\r\n\r\n this.renderBackgroundImage(plotAreaRect);\r\n\r\n if (!_.isEmpty(easing)) \r\n this.svgAxes.renderAxes(axesLayout, duration, easing);\r\n else\r\n this.svgAxes.renderAxes(axesLayout, duration);\r\n\r\n this.renderReferenceLines(axesLayout);\r\n\r\n this.renderLayers(layers, plotArea, axes, suppressAnimations, resizeMode);\r\n\r\n this.renderTrendLines(axesLayout);\r\n }\r\n\r\n private renderTrendLines(axesLayout: CartesianAxesLayout): void {\r\n let scrollableRegion = this.svgAxes.getScrollableRegion();\r\n TrendLineHelper.render(this.trendLines, scrollableRegion, axesLayout.axes, axesLayout.plotArea);\r\n }\r\n\r\n private renderReferenceLines(axesLayout: CartesianAxesLayout): void {\r\n let axes = axesLayout.axes;\r\n let plotArea = axesLayout.plotArea;\r\n let scrollableRegion = this.svgAxes.getScrollableRegion();\r\n let refLineDefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\r\n\r\n let showY1ReferenceLines = false;\r\n if (this.y1AxisReferenceLines) {\r\n for (let referenceLineProperties of this.y1AxisReferenceLines) {\r\n let object: DataViewObject = referenceLineProperties.object;\r\n if (object[ReferenceLineHelper.referenceLineProps.show]) {\r\n\r\n let isHorizontal = !axes.y1.isCategoryAxis;\r\n let y1RefLineOptions = {\r\n graphicContext: scrollableRegion,\r\n referenceLineProperties: object,\r\n axes: axes,\r\n viewport: plotArea,\r\n classAndSelector: this.y1RefLine,\r\n defaultColor: refLineDefaultColor,\r\n isHorizontal: isHorizontal\r\n };\r\n\r\n ReferenceLineHelper.render(y1RefLineOptions);\r\n showY1ReferenceLines = true;\r\n }\r\n }\r\n }\r\n\r\n if (!showY1ReferenceLines) {\r\n scrollableRegion.selectAll(this.y1RefLine.selector).remove();\r\n }\r\n\r\n let showXReferenceLines = false;\r\n if (this.xAxisReferenceLines) {\r\n for (let referenceLineProperties of this.xAxisReferenceLines) {\r\n let object: DataViewObject = referenceLineProperties.object;\r\n if (object[ReferenceLineHelper.referenceLineProps.show]) {\r\n let isHorizontal = false;\r\n let xRefLineOptions = {\r\n graphicContext: scrollableRegion,\r\n referenceLineProperties: object,\r\n axes: axes,\r\n viewport: plotArea,\r\n classAndSelector: this.xRefLine,\r\n defaultColor: refLineDefaultColor,\r\n isHorizontal: isHorizontal\r\n };\r\n\r\n ReferenceLineHelper.render(xRefLineOptions);\r\n showXReferenceLines = true;\r\n }\r\n }\r\n }\r\n\r\n if (!showXReferenceLines) {\r\n scrollableRegion.selectAll(this.xRefLine.selector).remove();\r\n }\r\n }\r\n\r\n private getReferenceLineLabels(axes: CartesianAxisProperties, plotArea: IViewport): LabelDataPoint[] {\r\n let refLineDefaultColor = this.sharedColorPalette.getColorByIndex(0).value;\r\n let referenceLineLabels: LabelDataPoint[] = [];\r\n if (this.y1AxisReferenceLines) {\r\n for (let referenceLineProperties of this.y1AxisReferenceLines) {\r\n let object: DataViewObject = referenceLineProperties.object;\r\n if (object[ReferenceLineHelper.referenceLineProps.show] && object[ReferenceLineHelper.referenceLineProps.dataLabelShow]) {\r\n let isHorizontal = !axes.y1.isCategoryAxis;\r\n let y1RefLineLabelOptions: ReferenceLineDataLabelOptions = {\r\n referenceLineProperties: object,\r\n axes: axes,\r\n viewport: plotArea,\r\n defaultColor: refLineDefaultColor,\r\n isHorizontal: isHorizontal,\r\n key: JSON.stringify({\r\n type: 'y1AxisReferenceLine',\r\n id: referenceLineProperties.id,\r\n }),\r\n };\r\n\r\n referenceLineLabels.push(ReferenceLineHelper.createLabelDataPoint(y1RefLineLabelOptions));\r\n }\r\n }\r\n }\r\n\r\n if (this.xAxisReferenceLines) {\r\n for (let referenceLineProperties of this.xAxisReferenceLines) {\r\n let object: DataViewObject = referenceLineProperties.object;\r\n if (object[ReferenceLineHelper.referenceLineProps.show] && object[ReferenceLineHelper.referenceLineProps.dataLabelShow]) {\r\n let isHorizontal = false;\r\n let xRefLineLabelOptions: ReferenceLineDataLabelOptions = {\r\n referenceLineProperties: object,\r\n axes: axes,\r\n viewport: plotArea,\r\n defaultColor: refLineDefaultColor,\r\n isHorizontal: isHorizontal,\r\n key: JSON.stringify({\r\n type: 'xAxisReferenceLine',\r\n id: referenceLineProperties.id,\r\n }),\r\n };\r\n\r\n referenceLineLabels.push(ReferenceLineHelper.createLabelDataPoint(xRefLineLabelOptions));\r\n }\r\n }\r\n }\r\n\r\n return referenceLineLabels;\r\n }\r\n\r\n private renderDataLabels(labelDataPointGroups: LabelDataPointsGroup[], labelsAreNumeric: boolean, plotArea: IViewport, suppressAnimations: boolean, isCombo: boolean): void {\r\n let labelBackgroundRegion = this.svgAxes.getLabelBackground();\r\n let labelRegion = this.svgAxes.getLabelsRegion();\r\n\r\n if (this.behavior) {\r\n let labelLayoutOptions = NewDataLabelUtils.getDataLabelLayoutOptions(this.type);\r\n let labelLayout = new LabelLayout(labelLayoutOptions);\r\n let dataLabels = labelLayout.layout(labelDataPointGroups, plotArea);\r\n\r\n if (isCombo) {\r\n NewDataLabelUtils.drawLabelBackground(labelBackgroundRegion, dataLabels, \"#FFFFFF\", 0.7);\r\n }\r\n\r\n let svgLabels: D3.UpdateSelection;\r\n let animator = this.animator;\r\n if (animator && !suppressAnimations) {\r\n let isPlayAxis = this.isPlayAxis();\r\n let duration = isPlayAxis ? PlayChart.FrameAnimationDuration : animator.getDuration();\r\n svgLabels = NewDataLabelUtils.animateDefaultLabels(\r\n labelRegion,\r\n dataLabels,\r\n duration,\r\n labelsAreNumeric,\r\n isPlayAxis ? 'linear' : animator.getEasing());\r\n }\r\n else {\r\n svgLabels = NewDataLabelUtils.drawDefaultLabels(labelRegion, dataLabels, labelsAreNumeric);\r\n }\r\n\r\n if (labelLayoutOptions.allowLeaderLines) {\r\n let filteredLabels = _.filter(dataLabels, (d: Label) => d.leaderLinePoints != null && !_.isEmpty(d.leaderLinePoints) && d.identity != null);\r\n NewDataLabelUtils.drawLabelLeaderLines(labelRegion, filteredLabels, (d: Label) => d.identity.getKey());\r\n }\r\n\r\n if (this.interactivityService && this.isLabelInteractivityEnabled) {\r\n let labelsBehaviorOptions: LabelsBehaviorOptions = {\r\n labelItems: svgLabels,\r\n };\r\n this.interactivityService.bind(dataLabels, new LabelsBehavior(), labelsBehaviorOptions, { isLabels: true });\r\n }\r\n }\r\n else {\r\n let labelLayout = new LabelLayout({\r\n maximumOffset: NewDataLabelUtils.maxLabelOffset,\r\n startingOffset: NewDataLabelUtils.startingLabelOffset,\r\n attemptToMoveLabelsIntoViewport: true,\r\n });\r\n\r\n let dataLabels = labelLayout.layout(labelDataPointGroups, plotArea);\r\n\r\n if (isCombo) {\r\n NewDataLabelUtils.drawLabelBackground(labelBackgroundRegion, dataLabels, \"#FFFFFF\", 0.7);\r\n }\r\n NewDataLabelUtils.drawDefaultLabels(labelRegion, dataLabels, labelsAreNumeric);\r\n }\r\n }\r\n\r\n private renderLayers(layers: ICartesianVisual[], plotArea: IViewport, axes: CartesianAxisProperties, suppressAnimations: boolean, resizeMode?: ResizeMode): void {\r\n let labelDataPointGroups: LabelDataPointsGroup[] = [];\r\n let dataPoints: SelectableDataPoint[] = [];\r\n let layerBehaviorOptions: any[] = [];\r\n let labelsAreNumeric: boolean = true;\r\n for (let i = 0, len = layers.length; i < len; i++) {\r\n let result = layers[i].render(suppressAnimations, resizeMode);\r\n if (result) {\r\n if (this.behavior) {\r\n // NOTE: these are not needed if we don't have interactivity\r\n dataPoints = dataPoints.concat(result.dataPoints);\r\n layerBehaviorOptions.push(result.behaviorOptions);\r\n }\r\n\r\n if (result.labelDataPointGroups) {\r\n let resultLabelDataPointsGroups = result.labelDataPointGroups;\r\n for (let resultLabelDataPointsGroup of resultLabelDataPointsGroups) {\r\n if (!resultLabelDataPointsGroup)\r\n continue;\r\n labelDataPointGroups.push({\r\n labelDataPoints: NewDataLabelUtils.removeDuplicates(resultLabelDataPointsGroup.labelDataPoints || []),\r\n maxNumberOfLabels: resultLabelDataPointsGroup.maxNumberOfLabels,\r\n });\r\n }\r\n }\r\n else {\r\n let resultsLabelDataPoints = result.labelDataPoints || [];\r\n labelDataPointGroups.push({\r\n labelDataPoints: NewDataLabelUtils.removeDuplicates(resultsLabelDataPoints),\r\n maxNumberOfLabels: resultsLabelDataPoints.length,\r\n });\r\n }\r\n\r\n labelsAreNumeric = labelsAreNumeric && result.labelsAreNumeric;\r\n }\r\n }\r\n\r\n let referenceLineLabels = this.getReferenceLineLabels(axes, plotArea);\r\n if (!_.isEmpty(referenceLineLabels)) {\r\n labelDataPointGroups.unshift({\r\n labelDataPoints: referenceLineLabels,\r\n maxNumberOfLabels: referenceLineLabels.length,\r\n });\r\n }\r\n\r\n this.renderDataLabels(\r\n labelDataPointGroups,\r\n labelsAreNumeric,\r\n plotArea,\r\n suppressAnimations,\r\n ComboChart.isComboChart(this.type));\r\n\r\n if (this.interactivityService) {\r\n let behaviorOptions: CartesianBehaviorOptions = {\r\n layerOptions: layerBehaviorOptions,\r\n clearCatcher: this.clearCatcher,\r\n };\r\n\r\n this.interactivityService.bind(dataPoints, this.behavior, behaviorOptions);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the actual viewportWidth if visual is not scrollable.\r\n * @return If visual is scrollable, returns the plot area needed to draw all the datapoints.\r\n */\r\n public static getPreferredPlotArea(\r\n categoryCount: number,\r\n categoryThickness: number,\r\n viewport: IViewport,\r\n isScrollable: boolean,\r\n isScalar: boolean,\r\n margin?: IMargin,\r\n noOuterPadding?: boolean): IViewport {\r\n\r\n if (!margin)\r\n margin = { top: 0, right: 0, bottom: 0, left: 0 };\r\n\r\n let plotArea: IViewport = {\r\n height: viewport.height - margin.top - margin.bottom,\r\n width: viewport.width - margin.left - margin.right\r\n };\r\n if (!isScalar && isScrollable) {\r\n let preferredCategorySpan = CartesianChart.getPreferredCategorySpan(categoryCount, categoryThickness, noOuterPadding);\r\n plotArea.width = Math.max(preferredCategorySpan, plotArea.width);\r\n }\r\n return plotArea;\r\n }\r\n\r\n /**\r\n * Returns preferred Category span if the visual is scrollable.\r\n */\r\n public static getPreferredCategorySpan(categoryCount: number, categoryThickness: number, noOuterPadding?: boolean): number {\r\n let span = (categoryThickness * categoryCount);\r\n if (noOuterPadding)\r\n return span;\r\n return span + (categoryThickness * CartesianChart.OuterPaddingRatio * 2);\r\n }\r\n \r\n /**\r\n * Note: Public for testing access.\r\n */\r\n public static getLayout(data: ColumnChartData, options: CategoryLayoutOptions): CategoryLayout {\r\n let categoryCount = options.categoryCount,\r\n availableWidth = options.availableWidth,\r\n domain = options.domain,\r\n trimOrdinalDataOnOverflow = options.trimOrdinalDataOnOverflow,\r\n isScalar = !!options.isScalar,\r\n isScrollable = !!options.isScrollable;\r\n\r\n let categoryThickness = CartesianChart.getCategoryThickness(data ? data.series : null, categoryCount, availableWidth, domain, isScalar, trimOrdinalDataOnOverflow);\r\n\r\n // Total width of the outer padding, the padding that exist on the far right and far left of the chart.\r\n let totalOuterPadding = categoryThickness * CartesianChart.OuterPaddingRatio * 2;\r\n\r\n // visibleCategoryCount will be used to discard data that overflows on ordinal-axis charts.\r\n // Needed for dashboard visuals \r\n let calculatedBarCount = Double.floorWithPrecision((availableWidth - totalOuterPadding) / categoryThickness);\r\n let visibleCategoryCount = Math.min(calculatedBarCount, categoryCount);\r\n let willScroll = visibleCategoryCount < categoryCount && isScrollable;\r\n\r\n let outerPaddingRatio = CartesianChart.OuterPaddingRatio;\r\n if (!isScalar && !willScroll) {\r\n // use dynamic outer padding to improve spacing when we have few categories\r\n let oneOuterPadding = (availableWidth - (categoryThickness * visibleCategoryCount)) / 2;\r\n outerPaddingRatio = oneOuterPadding / categoryThickness;\r\n }\r\n\r\n // If scrollable, visibleCategoryCount will be total categories\r\n if (!isScalar && isScrollable)\r\n visibleCategoryCount = categoryCount;\r\n\r\n return {\r\n categoryCount: visibleCategoryCount,\r\n categoryThickness: categoryThickness,\r\n outerPaddingRatio: outerPaddingRatio,\r\n isScalar: isScalar\r\n };\r\n }\r\n\r\n /** \r\n * Returns the thickness for each category.\r\n * For clustered charts, you still need to divide by\r\n * the number of series to get column width after calling this method.\r\n * For linear or time scales, category thickness accomodates for\r\n * the minimum interval between consequtive points.\r\n * For all types, return value has accounted for outer padding,\r\n * but not inner padding.\r\n */\r\n public static getCategoryThickness(seriesList: CartesianSeries[], numCategories: number, plotLength: number, domain: number[], isScalar: boolean, trimOrdinalDataOnOverflow: boolean): number {\r\n let thickness;\r\n if (numCategories < 2)\r\n thickness = plotLength * (1 - CartesianChart.OuterPaddingRatio);\r\n else if (isScalar && domain && domain.length > 1) {\r\n // the smallest interval defines the column width.\r\n let minInterval = CartesianChart.getMinInterval(seriesList);\r\n let domainSpan = domain[domain.length - 1] - domain[0];\r\n // account for outside padding\r\n let ratio = minInterval / (domainSpan + (minInterval * CartesianChart.OuterPaddingRatio * 2));\r\n thickness = plotLength * ratio;\r\n thickness = Math.max(thickness, CartesianChart.MinScalarRectThickness);\r\n }\r\n else {\r\n // Divide the available width up including outer padding (in terms of category thickness) on\r\n // both sides of the chart, and categoryCount categories. Reverse math:\r\n // availableWidth = (categoryThickness * categoryCount) + (categoryThickness * (outerPadding * 2)),\r\n // availableWidth = categoryThickness * (categoryCount + (outerPadding * 2)),\r\n // categoryThickness = availableWidth / (categoryCount + (outerpadding * 2))\r\n thickness = plotLength / (numCategories + (CartesianChart.OuterPaddingRatio * 2));\r\n if (trimOrdinalDataOnOverflow) {\r\n thickness = Math.max(thickness, CartesianChart.MinOrdinalRectThickness);\r\n }\r\n }\r\n \r\n // spec calls for using the whole plot area, but the max rectangle thickness is \"as if there were three categories\"\r\n // (outerPaddingRatio has the same units as '# of categories' so they can be added)\r\n let maxRectThickness = plotLength / (3 + (CartesianChart.OuterPaddingRatio * 2));\r\n\r\n thickness = Math.min(thickness, maxRectThickness);\r\n\r\n if (!isScalar && numCategories >= 3 && trimOrdinalDataOnOverflow) {\r\n return Math.max(thickness, CartesianChart.MinOrdinalRectThickness);\r\n }\r\n\r\n return thickness;\r\n }\r\n\r\n private static getMinInterval(seriesList: CartesianSeries[]): number {\r\n let minInterval = Number.MAX_VALUE;\r\n if (seriesList.length > 0) {\r\n let series0data = seriesList[0].data.filter(d => !d.highlight);\r\n for (let i = 0, ilen = series0data.length - 1; i < ilen; i++) {\r\n minInterval = Math.min(minInterval, Math.abs(series0data[i + 1].categoryValue - series0data[i].categoryValue));\r\n }\r\n }\r\n return minInterval;\r\n }\r\n }\r\n\r\n function getLayerDataViews(dataViews: DataView[]): DataView[] {\r\n if (_.isEmpty(dataViews))\r\n return [];\r\n\r\n // TODO: figure out a more general way to correlate between layers and input data views.\r\n return _.filter(dataViews, (dataView) => !TrendLineHelper.isDataViewForRegression(dataView));\r\n }\r\n\r\n function hasMultipleYAxes(layers: ICartesianVisual[]): boolean {\r\n debug.assertValue(layers, 'layers');\r\n\r\n return layers.length > 1;\r\n }\r\n\r\n /**\r\n * Returns a boolean, that indicates if y axis title should be displayed.\r\n * @return True if y axis title should be displayed,\r\n * otherwise false.\r\n */\r\n function shouldShowYAxisLabel(layerNumber: number, valueAxisProperties: DataViewObject, yAxisWillMerge: boolean): boolean {\r\n return ((layerNumber === 0 && !!valueAxisProperties && !!valueAxisProperties['showAxisTitle']) ||\r\n (layerNumber === 1 && !yAxisWillMerge && !!valueAxisProperties && !!valueAxisProperties['secShowAxisTitle']));\r\n }\r\n\r\n function tryMergeYDomains(layers: ICartesianVisual[], visualOptions: CalculateScaleAndDomainOptions): MergedValueAxisResult {\r\n debug.assert(layers.length < 3, 'merging of more than 2 layers is not supported');\r\n\r\n let noMerge: MergedValueAxisResult = {\r\n domain: undefined,\r\n merged: false,\r\n tickCount: undefined\r\n };\r\n\r\n if (layers.length < 2)\r\n return noMerge;\r\n\r\n let min: number;\r\n let max: number;\r\n let minOfMax: number;\r\n let maxOfMin: number;\r\n\r\n // TODO: replace full calculateAxesProperties with just a data domain calc\r\n // we need to be aware of which chart require zero (column/bar) and which don't (line)\r\n let y1props = layers[0].calculateAxesProperties(visualOptions)[1];\r\n let y2props = layers[1].calculateAxesProperties(visualOptions)[1];\r\n let firstYDomain = y1props.scale.domain();\r\n let secondYDomain = y2props.scale.domain();\r\n\r\n if (y1props.values && y1props.values.length > 0 && y2props.values && y2props.values.length > 0) {\r\n noMerge.tickCount = Math.max(y1props.values.length, y2props.values.length);\r\n }\r\n\r\n min = Math.min(firstYDomain[0], secondYDomain[0]);\r\n max = Math.max(firstYDomain[1], secondYDomain[1]);\r\n\r\n if (visualOptions.forceMerge) {\r\n return {\r\n domain: [min, max],\r\n merged: true,\r\n tickCount: noMerge.tickCount\r\n };\r\n }\r\n\r\n // If domains don't intersect don't merge axis.\r\n if (firstYDomain[0] > secondYDomain[1] || firstYDomain[1] < secondYDomain[0])\r\n return noMerge;\r\n\r\n maxOfMin = Math.max(firstYDomain[0], secondYDomain[0]);\r\n minOfMax = Math.min(firstYDomain[1], secondYDomain[1]);\r\n\r\n let range = (max - min);\r\n\r\n if (range === 0) {\r\n return noMerge;\r\n }\r\n\r\n let intersection = Math.abs((minOfMax - maxOfMin) / range);\r\n\r\n // Only merge if intersection of domains greater than 10% of total range.\r\n if (intersection < COMBOCHART_DOMAIN_OVERLAP_TRESHOLD_PERCENTAGE)\r\n return noMerge;\r\n else\r\n return {\r\n domain: [min, max],\r\n merged: true,\r\n tickCount: noMerge.tickCount\r\n };\r\n }\r\n\r\n export const enum AxisLocation {\r\n X,\r\n Y1,\r\n Y2,\r\n }\r\n\r\n export interface CartesianAxesLayout {\r\n axes: CartesianAxisProperties;\r\n margin: IMargin;\r\n marginLimits: IMargin;\r\n axisLabels: ChartAxesLabels;\r\n viewport: IViewport;\r\n plotArea: IViewport;\r\n preferredPlotArea: IViewport;\r\n tickLabelMargins: any;\r\n tickPadding: IMargin;\r\n rotateXTickLabels90?: boolean;\r\n }\r\n\r\n class SvgBrush {\r\n private element: D3.Selection;\r\n private brushGraphicsContext: D3.Selection;\r\n private brush: D3.Svg.Brush;\r\n private brushWidth: number;\r\n private scrollCallback: () => void;\r\n private isHorizontal: boolean;\r\n private brushStartExtent: number[];\r\n\r\n private static Brush = createClassAndSelector('brush');\r\n\r\n constructor(brushWidth: number) {\r\n this.brush = d3.svg.brush();\r\n this.brushWidth = brushWidth;\r\n }\r\n\r\n public init(element: D3.Selection): void {\r\n this.element = element;\r\n }\r\n\r\n public remove(): void {\r\n this.element.selectAll(SvgBrush.Brush.selector).remove();\r\n this.brushGraphicsContext = undefined;\r\n }\r\n\r\n public getExtent(): number[] {\r\n return this.brush.extent();\r\n }\r\n\r\n public setExtent(extent: number[]): void {\r\n this.brush.extent(extent);\r\n }\r\n\r\n public setScale(scale: D3.Scale.OrdinalScale): void {\r\n if (this.isHorizontal)\r\n this.brush.x(scale);\r\n else\r\n this.brush.y(scale);\r\n }\r\n\r\n public setOrientation(isHorizontal: boolean): void {\r\n this.isHorizontal = isHorizontal;\r\n }\r\n\r\n public renderBrush(\r\n extentLength: number,\r\n brushX: number,\r\n brushY: number,\r\n scrollCallback: () => void): void {\r\n\r\n // create graphics context if it doesn't exist\r\n if (!this.brushGraphicsContext) {\r\n this.brushGraphicsContext = this.element.append(\"g\")\r\n .classed(SvgBrush.Brush.class, true);\r\n }\r\n\r\n this.scrollCallback = scrollCallback;\r\n\r\n // events\r\n this.brush\r\n .on(\"brushstart\", () => this.brushStartExtent = this.brush.extent())\r\n .on(\"brush\", () => {\r\n window.requestAnimationFrame(scrollCallback);\r\n })\r\n .on(\"brushend\", () => {\r\n this.resizeExtent(extentLength);\r\n this.updateExtentPosition(extentLength);\r\n this.brushStartExtent = null;\r\n });\r\n\r\n // position the graphics context\r\n let brushContext = this.brushGraphicsContext\r\n .attr({\r\n \"transform\": SVGUtil.translate(brushX, brushY),\r\n \"drag-resize-disabled\": \"true\" /* Disables resizing of the visual when dragging the scrollbar in edit mode */\r\n })\r\n .call(this.brush);\r\n \r\n // Disable the zooming feature by removing the resize elements\r\n brushContext.selectAll(\".resize\")\r\n .remove();\r\n\r\n if (this.isHorizontal)\r\n brushContext.selectAll(\"rect\").attr(\"height\", this.brushWidth);\r\n else\r\n brushContext.selectAll(\"rect\").attr(\"width\", this.brushWidth);\r\n }\r\n\r\n public scroll(scrollBarLength: number): void {\r\n this.updateExtentPosition(scrollBarLength);\r\n this.scrollCallback();\r\n }\r\n\r\n private updateExtentPosition(scrollBarLength: number): void {\r\n let extent = this.brush.extent();\r\n debug.assertNonEmpty(extent, 'updateExtentPosition, extent');\r\n let newStartPos = extent[0];\r\n let halfScrollBarLen = scrollBarLength / 2;\r\n\r\n if (extent[0] === extent[1]) {\r\n // user clicked on the brush background, width will be zero, offset x by half width\r\n newStartPos = newStartPos - halfScrollBarLen;\r\n }\r\n\r\n if (extent[1] - extent[0] > scrollBarLength) {\r\n // user is dragging one edge after mousedown in the background, figure out which side is moving\r\n // also, center up on the new extent center\r\n let halfDragLength = (extent[1] - extent[0]) / 2;\r\n if (extent[0] < this.brushStartExtent[0])\r\n newStartPos = extent[0] + halfDragLength - halfScrollBarLen;\r\n else\r\n newStartPos = extent[1] - halfDragLength - halfScrollBarLen;\r\n }\r\n\r\n if (this.isHorizontal)\r\n this.brushGraphicsContext.select(\".extent\").attr('x', newStartPos);\r\n else\r\n this.brushGraphicsContext.select(\".extent\").attr('y', newStartPos);\r\n }\r\n\r\n private resizeExtent(extentLength: number): void {\r\n if (this.isHorizontal)\r\n this.brushGraphicsContext.select(\".extent\").attr(\"width\", extentLength);\r\n else\r\n this.brushGraphicsContext.select(\".extent\").attr(\"height\", extentLength);\r\n }\r\n }\r\n\r\n class ScrollableAxes {\r\n public static ScrollbarWidth = 10;\r\n\r\n private brush: SvgBrush;\r\n private brushMinExtent: number;\r\n private scrollScale: D3.Scale.OrdinalScale;\r\n private axisScale: D3.Scale.OrdinalScale;\r\n\r\n private axes: CartesianAxes;\r\n\r\n constructor(axes: CartesianAxes, svgBrush: SvgBrush) {\r\n this.axes = axes;\r\n this.brush = svgBrush;\r\n }\r\n\r\n private filterDataToViewport(\r\n mainAxisScale: D3.Scale.OrdinalScale,\r\n layers: ICartesianVisual[],\r\n axes: CartesianAxisProperties,\r\n scrollScale: D3.Scale.OrdinalScale,\r\n extent: number[],\r\n visibleCategoryCount: number): void {\r\n\r\n if (scrollScale) {\r\n let selected: number[];\r\n let data: CartesianData[] = [];\r\n\r\n // NOTE: using start + numVisibleCategories to make sure we don't have issues with exactness related to extent start/end\r\n // (don't use extent[1])\r\n /*\r\n When extent[0] and extent[1] are very close to the boundary of a new index, due to floating point err,\r\n the \"start\" might move to the next index but the \"end\" might not change until you slide one more pixel.\r\n It makes things really jittery during scrolling, sometimes you see N columns and sometimes you briefly see N+1.\r\n */\r\n let startIndex = AxisHelper.lookupOrdinalIndex(scrollScale, extent[0]);\r\n var endIndex = startIndex + visibleCategoryCount; // NOTE: intentionally 1 past end index\r\n\r\n let domain = scrollScale.domain();\r\n selected = domain.slice(startIndex, endIndex); // NOTE: Up to but not including 'end'\r\n if (selected && selected.length > 0) {\r\n for (let i = 0; i < layers.length; i++) {\r\n data[i] = layers[i].setFilteredData(selected[0], selected[selected.length - 1] + 1);\r\n }\r\n mainAxisScale.domain(selected);\r\n\r\n let axisPropsToUpdate: IAxisProperties;\r\n if (this.axes.isXScrollBarVisible) {\r\n axisPropsToUpdate = axes.x;\r\n }\r\n else {\r\n axisPropsToUpdate = axes.y1;\r\n }\r\n\r\n axisPropsToUpdate.axis.scale(mainAxisScale);\r\n axisPropsToUpdate.scale(mainAxisScale);\r\n\r\n // tick values are indices for ordinal axes\r\n axisPropsToUpdate.axis.ticks(selected.length);\r\n axisPropsToUpdate.axis.tickValues(selected); \r\n\r\n // use the original tick format to format the tick values\r\n let tickFormat = axisPropsToUpdate.axis.tickFormat();\r\n axisPropsToUpdate.values = _.map(selected, (d) => tickFormat(d));\r\n }\r\n }\r\n }\r\n\r\n public render(\r\n axesLayout: CartesianAxesLayout,\r\n layers: ICartesianVisual[],\r\n suppressAnimations: boolean,\r\n renderDelegate: RenderPlotAreaDelegate): void {\r\n\r\n let plotArea = axesLayout.plotArea;\r\n\r\n if (plotArea.width < 1 || plotArea.height < 1)\r\n return; //do nothing - too small\r\n\r\n this.axisScale = null;\r\n let brushX: number;\r\n let brushY: number;\r\n let scrollbarLength: number;\r\n let numVisibleCategories: number;\r\n let categoryThickness: number;\r\n let newAxisLength: number;\r\n if (this.axes.isXScrollBarVisible) {\r\n this.axisScale = <D3.Scale.OrdinalScale>axesLayout.axes.x.scale;\r\n brushX = axesLayout.margin.left;\r\n brushY = axesLayout.viewport.height;\r\n categoryThickness = axesLayout.axes.x.categoryThickness;\r\n let outerPadding = axesLayout.axes.x.outerPadding;\r\n numVisibleCategories = Double.floorWithPrecision((plotArea.width - outerPadding * 2) / categoryThickness);\r\n scrollbarLength = (numVisibleCategories + 1) * categoryThickness;\r\n newAxisLength = plotArea.width;\r\n }\r\n else if (this.axes.isYScrollBarVisible) {\r\n this.axisScale = <D3.Scale.OrdinalScale>axesLayout.axes.y1.scale;\r\n brushX = axesLayout.viewport.width;\r\n brushY = axesLayout.margin.top;\r\n categoryThickness = axesLayout.axes.y1.categoryThickness;\r\n let outerPadding = axesLayout.axes.y1.outerPadding;\r\n numVisibleCategories = Double.floorWithPrecision((plotArea.height - outerPadding * 2) / categoryThickness);\r\n scrollbarLength = (numVisibleCategories + 1) * categoryThickness;\r\n newAxisLength = plotArea.height;\r\n }\r\n else {\r\n // No scrollbars, render the chart normally.\r\n this.brush.remove();\r\n renderDelegate(layers, axesLayout, suppressAnimations);\r\n return;\r\n }\r\n\r\n // viewport is REALLY small\r\n if (numVisibleCategories < 1)\r\n return; // don't do anything\r\n\r\n this.scrollScale = this.axisScale.copy();\r\n this.scrollScale.rangeBands([0, scrollbarLength]); //no inner/outer padding, keep the math simple\r\n this.brushMinExtent = this.scrollScale(numVisibleCategories - 1);\r\n\r\n // Options: use newAxisLength to squeeze-pop and keep the chart balanced, \r\n // or use scrollbarLength to keep rects still - but it leaves unbalanced right edge\r\n // 1. newAxisLength ex: As you resize smaller we constantly adjust the inner/outer padding to keep things balanced with the same # of rects, \r\n // when we need to drop a rect we pop out the rectangle and the padding seems to jump (to keep things cenetered and balanced). \r\n // 2. scrollbarLenghth ex: As you resize smaller we can leave all rectangles in the exact same place, no squeezing inner/outer padding,\r\n // when we need to drop a rect we just remove it - but this leaves the right side with lots of empty room (bad for dashboard tiles)\r\n // we are using option 1 to squeeze pop and show balanced layout at all sizes, but this is the less ideal experience during resize.\r\n // we should consider using option 2 during resize, then switch to option 1 when resize ends.\r\n this.axisScale.rangeBands([0, newAxisLength], CartesianChart.InnerPaddingRatio, CartesianChart.OuterPaddingRatio);\r\n\r\n this.brush.setOrientation(this.axes.isXScrollBarVisible);\r\n this.brush.setScale(this.scrollScale);\r\n this.brush.setExtent([0, this.brushMinExtent]);\r\n\r\n // This function will be called whenever we scroll.\r\n let renderOnScroll = (extent: number[], suppressAnimations: boolean) => {\r\n this.filterDataToViewport(this.axisScale, layers, axesLayout.axes, this.scrollScale, extent, numVisibleCategories);\r\n renderDelegate(layers, axesLayout, suppressAnimations);\r\n };\r\n\r\n let scrollCallback = () => this.onBrushed(scrollbarLength, renderOnScroll);\r\n this.brush.renderBrush(this.brushMinExtent, brushX, brushY, scrollCallback);\r\n\r\n renderOnScroll(this.brush.getExtent(), suppressAnimations);\r\n }\r\n\r\n public scrollDelta(delta): void {\r\n if (this.axisScale && !_.isEmpty(this.axisScale.domain())) {\r\n let currentStartIndex = this.axisScale.domain()[0];\r\n let newStartIndex = currentStartIndex + Math.round(delta / CartesianChart.MinOrdinalRectThickness);\r\n this.scrollTo(newStartIndex);\r\n }\r\n }\r\n\r\n // PUBLIC FOR UNIT TESTING ONLY\r\n public scrollTo(startIndex: number): void {\r\n debug.assert(this.axes.isXScrollBarVisible || this.axes.isYScrollBarVisible, 'scrolling is not available');\r\n debug.assertValue(this.scrollScale, 'scrollScale');\r\n\r\n let lastIndex = _.last(this.scrollScale.domain());\r\n startIndex = Math.max(0, Math.min(startIndex, lastIndex));\r\n\r\n let extent = this.brush.getExtent();\r\n let extentLength = extent[1] - extent[0];\r\n let halfCategoryThickness = (this.scrollScale(1) - this.scrollScale(0)) / 2;\r\n extent[0] = this.scrollScale(startIndex) + halfCategoryThickness;\r\n extent[1] = extent[0] + extentLength + halfCategoryThickness;\r\n this.brush.setExtent(extent);\r\n\r\n let scrollbarLength = this.scrollScale.rangeExtent()[1];\r\n ScrollableAxes.clampBrushExtent(this.brush, scrollbarLength, this.brushMinExtent);\r\n this.brush.scroll(scrollbarLength);\r\n }\r\n\r\n private onBrushed(scrollbarLength: number, render: (extent: number[], suppressAnimations: boolean) => void): void {\r\n let brush = this.brush;\r\n\r\n ScrollableAxes.clampBrushExtent(this.brush, scrollbarLength, this.brushMinExtent);\r\n let extent = brush.getExtent();\r\n render(extent, /*suppressAnimations*/ true);\r\n }\r\n\r\n private static clampBrushExtent(brush: SvgBrush, scrollbarLength: number, minExtent: number): void {\r\n let extent = brush.getExtent();\r\n let width = extent[1] - extent[0];\r\n\r\n if (width === minExtent && extent[1] <= scrollbarLength && extent[0] >= 0)\r\n return;\r\n\r\n if (width > minExtent) {\r\n let padding = (width - minExtent) / 2;\r\n extent[0] += padding;\r\n extent[1] -= padding;\r\n }\r\n\r\n else if (width < minExtent) {\r\n let padding = (minExtent - width) / 2;\r\n extent[0] -= padding;\r\n extent[1] += padding;\r\n }\r\n\r\n if (extent[0] < 0) {\r\n extent[0] = 0;\r\n extent[1] = minExtent;\r\n }\r\n\r\n else if (extent[0] > scrollbarLength - minExtent) {\r\n extent[0] = scrollbarLength - minExtent;\r\n extent[1] = scrollbarLength;\r\n }\r\n\r\n brush.setExtent(extent);\r\n }\r\n }\r\n\r\n export class SvgCartesianAxes {\r\n // These match D3's internal axis padding values\r\n public static AxisPadding: IMargin = {\r\n left: 10,\r\n right: 10,\r\n top: 0,\r\n bottom: 13, // don't change this - fixes defect 6658705 when in \"Fit-to-Page\" view and the scale factor is greater than 1.0\r\n };\r\n\r\n private axisGraphicsContext: D3.Selection;\r\n private xAxisGraphicsContext: D3.Selection;\r\n private y1AxisGraphicsContext: D3.Selection;\r\n private y2AxisGraphicsContext: D3.Selection;\r\n private svgScrollable: D3.Selection;\r\n private axisGraphicsContextScrollable: D3.Selection;\r\n private labelRegion: D3.Selection;\r\n private labelBackgroundRegion: D3.Selection;\r\n\r\n private categoryAxisProperties: DataViewObject;\r\n private valueAxisProperties: DataViewObject;\r\n\r\n private static AxisGraphicsContext = createClassAndSelector('axisGraphicsContext');\r\n private static TickPaddingRotatedX = 5;\r\n private static AxisLabelFontSize = 11;\r\n private static Y2TickSize = -6;\r\n\r\n constructor(private axes: CartesianAxes) {\r\n }\r\n\r\n public getScrollableRegion(): D3.Selection {\r\n return this.axisGraphicsContextScrollable;\r\n }\r\n\r\n public getLabelsRegion(): D3.Selection {\r\n return this.labelRegion;\r\n }\r\n\r\n public getLabelBackground(): D3.Selection {\r\n return this.labelBackgroundRegion;\r\n }\r\n\r\n public getXAxis(): D3.Selection {\r\n return this.xAxisGraphicsContext;\r\n }\r\n\r\n public getY1Axis(): D3.Selection {\r\n return this.y1AxisGraphicsContext;\r\n }\r\n\r\n public getY2Axis(): D3.Selection {\r\n return this.y2AxisGraphicsContext;\r\n }\r\n\r\n public update(categoryAxisProperties: DataViewObject, valueAxisProperties: DataViewObject): void {\r\n this.categoryAxisProperties = categoryAxisProperties;\r\n this.valueAxisProperties = valueAxisProperties;\r\n }\r\n\r\n public init(svg: D3.Selection): void {\r\n /*\r\n The layout of the visual will look like:\r\n <svg>\r\n <g>\r\n <nonscrollable axis/>\r\n </g>\r\n <svgScrollable>\r\n <g>\r\n <scrollable axis/>\r\n </g>\r\n </svgScrollable>\r\n <g xbrush/>\r\n </svg>\r\n\r\n */\r\n\r\n let axisGraphicsContext = this.axisGraphicsContext = svg.append('g')\r\n .classed(SvgCartesianAxes.AxisGraphicsContext.class, true);\r\n\r\n this.svgScrollable = svg.append('svg')\r\n .classed('svgScrollable', true)\r\n .style('overflow', 'hidden');\r\n\r\n let axisGraphicsContextScrollable = this.axisGraphicsContextScrollable = this.svgScrollable.append('g')\r\n .classed(SvgCartesianAxes.AxisGraphicsContext.class, true);\r\n\r\n this.labelBackgroundRegion = this.svgScrollable.append('g')\r\n .classed(NewDataLabelUtils.labelBackgroundGraphicsContextClass.class, true);\r\n\r\n this.labelRegion = this.svgScrollable.append('g')\r\n .classed(NewDataLabelUtils.labelGraphicsContextClass.class, true);\r\n\r\n let showLinesOnX = this.axes.showLinesOnX;\r\n let showLinesOnY = this.axes.showLinesOnY;\r\n\r\n // NOTE: We infer the axis which should scroll based on whether or not we draw grid lines for the other axis, and\r\n // only allow one axis to scroll.\r\n let scrollX = showLinesOnY;\r\n let scrollY = !scrollX;\r\n if (scrollY) {\r\n this.y1AxisGraphicsContext = axisGraphicsContextScrollable.append('g').attr('class', 'y axis');\r\n this.y2AxisGraphicsContext = axisGraphicsContextScrollable.append('g').attr('class', 'y axis');\r\n }\r\n else {\r\n this.y1AxisGraphicsContext = axisGraphicsContext.append('g').attr('class', 'y axis');\r\n this.y2AxisGraphicsContext = axisGraphicsContext.append('g').attr('class', 'y axis');\r\n }\r\n\r\n if (scrollX) {\r\n this.xAxisGraphicsContext = axisGraphicsContextScrollable.append('g').attr('class', 'x axis');\r\n }\r\n else {\r\n this.xAxisGraphicsContext = axisGraphicsContext.append('g').attr('class', 'x axis');\r\n }\r\n\r\n this.xAxisGraphicsContext.classed('showLinesOnAxis', showLinesOnX);\r\n this.y1AxisGraphicsContext.classed('showLinesOnAxis', showLinesOnY);\r\n this.y2AxisGraphicsContext.classed('showLinesOnAxis', showLinesOnY);\r\n\r\n this.xAxisGraphicsContext.classed('hideLinesOnAxis', !showLinesOnX);\r\n this.y1AxisGraphicsContext.classed('hideLinesOnAxis', !showLinesOnY);\r\n this.y2AxisGraphicsContext.classed('hideLinesOnAxis', !showLinesOnY);\r\n }\r\n\r\n private static updateAnimatedTickTooltips(axisSelection: D3.Transition.Transition, values: any[]): void {\r\n axisSelection.each('end', function () {\r\n d3.select(this)\r\n .selectAll('text')\r\n .append('title')\r\n .text((d, i) => values[i]);\r\n });\r\n }\r\n\r\n private static updateTickTooltips(axisSelection: D3.Selection, values: any[]): void {\r\n axisSelection.selectAll('text').append('title').text((d, i) => values[i]);\r\n }\r\n\r\n public renderAxes(axesLayout: CartesianAxesLayout, duration: number, easing: string = 'cubic-in-out'): void {\r\n let marginLimits = axesLayout.marginLimits;\r\n let plotArea = axesLayout.plotArea;\r\n let viewport = axesLayout.viewport;\r\n let margin = axesLayout.margin;\r\n let axes = axesLayout.axes;\r\n let tickLabelMargins = axesLayout.tickLabelMargins;\r\n\r\n let bottomMarginLimit = marginLimits.bottom;\r\n let leftRightMarginLimit = marginLimits.left;\r\n\r\n let xLabelColor: Fill;\r\n let yLabelColor: Fill;\r\n let y2LabelColor: Fill;\r\n\r\n if (this.axes.shouldRenderAxis(axes.x)) {\r\n if (axes.x.isCategoryAxis) {\r\n xLabelColor = this.categoryAxisProperties && this.categoryAxisProperties['labelColor'] ? this.categoryAxisProperties['labelColor'] : null;\r\n } else {\r\n xLabelColor = this.valueAxisProperties && this.valueAxisProperties['labelColor'] ? this.valueAxisProperties['labelColor'] : null;\r\n }\r\n axes.x.axis.orient(\"bottom\");\r\n // we only rotate ordinal tick labels\r\n if (!axes.x.willLabelsFit && AxisHelper.isOrdinalScale(axes.x.scale))\r\n axes.x.axis.tickPadding(SvgCartesianAxes.TickPaddingRotatedX);\r\n\r\n let xAxisGraphicsElement = this.xAxisGraphicsContext;\r\n if (duration) {\r\n xAxisGraphicsElement\r\n .transition()\r\n .duration(duration)\r\n .ease(easing)\r\n .call(axes.x.axis)\r\n .call(SvgCartesianAxes.updateAnimatedTickTooltips, axes.x.values);\r\n }\r\n else {\r\n xAxisGraphicsElement\r\n .call(axes.x.axis);\r\n }\r\n\r\n xAxisGraphicsElement\r\n .call(SvgCartesianAxes.darkenZeroLine)\r\n .call(SvgCartesianAxes.setAxisLabelColor, xLabelColor);\r\n\r\n let xAxisTextNodes = xAxisGraphicsElement.selectAll('text');\r\n if (axes.x.willLabelsWordBreak) {\r\n xAxisTextNodes\r\n .call(AxisHelper.LabelLayoutStrategy.wordBreak, axes.x, bottomMarginLimit);\r\n } else {\r\n xAxisTextNodes\r\n .call(AxisHelper.LabelLayoutStrategy.rotate,\r\n bottomMarginLimit,\r\n TextMeasurementService.getTailoredTextOrDefault,\r\n CartesianChart.AxisTextProperties,\r\n !axes.x.willLabelsFit && AxisHelper.isOrdinalScale(axes.x.scale),\r\n bottomMarginLimit === tickLabelMargins.xMax,\r\n axes.x,\r\n margin,\r\n this.axes.isXScrollBarVisible || this.axes.isYScrollBarVisible);\r\n }\r\n\r\n if (!duration) {\r\n SvgCartesianAxes.updateTickTooltips(xAxisGraphicsElement, axes.x.values);\r\n }\r\n }\r\n else {\r\n this.xAxisGraphicsContext.selectAll('*').remove();\r\n }\r\n\r\n if (this.axes.shouldRenderAxis(axes.y1)) {\r\n if (axes.y1.isCategoryAxis) {\r\n yLabelColor = this.categoryAxisProperties && this.categoryAxisProperties['labelColor'] ? this.categoryAxisProperties['labelColor'] : null;\r\n } else {\r\n yLabelColor = this.valueAxisProperties && this.valueAxisProperties['labelColor'] ? this.valueAxisProperties['labelColor'] : null;\r\n }\r\n let showY1OnRight = this.axes.shouldShowY1OnRight();\r\n let y1TickPadding = showY1OnRight ? axesLayout.tickPadding.right : axesLayout.tickPadding.left;\r\n axes.y1.axis\r\n .tickSize(-plotArea.width)\r\n .tickPadding(y1TickPadding)\r\n .orient(this.axes.getYAxisOrientation().toLowerCase());\r\n\r\n let y1AxisGraphicsElement = this.y1AxisGraphicsContext;\r\n if (duration) {\r\n y1AxisGraphicsElement\r\n .transition()\r\n .duration(duration)\r\n .ease(easing)\r\n .call(axes.y1.axis)\r\n .call(SvgCartesianAxes.updateAnimatedTickTooltips, axes.y1.values);\r\n }\r\n else {\r\n y1AxisGraphicsElement\r\n .call(axes.y1.axis);\r\n }\r\n\r\n y1AxisGraphicsElement\r\n .call(SvgCartesianAxes.darkenZeroLine)\r\n .call(SvgCartesianAxes.setAxisLabelColor, yLabelColor);\r\n\r\n if (tickLabelMargins.yLeft >= leftRightMarginLimit) {\r\n y1AxisGraphicsElement.selectAll('text')\r\n .call(AxisHelper.LabelLayoutStrategy.clip,\r\n // Can't use padding space to render text, so subtract that from available space for ellipses calculations\r\n leftRightMarginLimit - y1TickPadding,\r\n TextMeasurementService.svgEllipsis);\r\n }\r\n\r\n if (!duration) {\r\n SvgCartesianAxes.updateTickTooltips(y1AxisGraphicsElement, axes.y1.values);\r\n }\r\n\r\n if (axes.y2 && (!this.valueAxisProperties || this.valueAxisProperties['secShow'] == null || this.valueAxisProperties['secShow'])) {\r\n y2LabelColor = this.valueAxisProperties && this.valueAxisProperties['secLabelColor'] ? this.valueAxisProperties['secLabelColor'] : null;\r\n\r\n let y2TickPadding = showY1OnRight ? axesLayout.tickPadding.left : axesLayout.tickPadding.right;\r\n axes.y2.axis\r\n .tickSize(SvgCartesianAxes.Y2TickSize)\r\n .tickPadding(y2TickPadding)\r\n .orient(showY1OnRight ? yAxisPosition.left.toLowerCase() : yAxisPosition.right.toLowerCase());\r\n\r\n let y2AxisGraphicsElement = this.y2AxisGraphicsContext;\r\n if (duration) {\r\n y2AxisGraphicsElement\r\n .transition()\r\n .duration(duration)\r\n .ease(easing)\r\n .call(axes.y2.axis)\r\n .call(SvgCartesianAxes.updateAnimatedTickTooltips, axes.y2.values);\r\n }\r\n else {\r\n y2AxisGraphicsElement\r\n .call(axes.y2.axis);\r\n }\r\n\r\n y2AxisGraphicsElement\r\n .call(SvgCartesianAxes.darkenZeroLine)\r\n .call(SvgCartesianAxes.setAxisLabelColor, y2LabelColor);\r\n\r\n if (tickLabelMargins.yRight >= leftRightMarginLimit) {\r\n y2AxisGraphicsElement.selectAll('text')\r\n .call(AxisHelper.LabelLayoutStrategy.clip,\r\n // Can't use padding space to render text, so subtract that from available space for ellipses calculations\r\n leftRightMarginLimit - y2TickPadding,\r\n TextMeasurementService.svgEllipsis);\r\n }\r\n\r\n if (!duration) {\r\n SvgCartesianAxes.updateTickTooltips(y2AxisGraphicsElement, axes.y2.values);\r\n }\r\n }\r\n else {\r\n this.y2AxisGraphicsContext.selectAll('*').remove();\r\n }\r\n }\r\n else {\r\n this.y1AxisGraphicsContext.selectAll('*').remove();\r\n this.y2AxisGraphicsContext.selectAll('*').remove();\r\n }\r\n\r\n // Axis labels\r\n //TODO: Add label for second Y axis for combo chart\r\n let axisLabels = axesLayout.axisLabels;\r\n let chartHasAxisLabels = (axisLabels.x != null) || (axisLabels.y != null || axisLabels.y2 != null);\r\n if (chartHasAxisLabels) {\r\n let hideXAxisTitle = !this.axes.shouldRenderAxisTitle(axes.x, /* defaultValue */ true, /* secondary */ false);\r\n let hideYAxisTitle = !this.axes.shouldRenderAxisTitle(axes.y1, /* defaultValue */ true, /* secondary */false);\r\n let hideY2AxisTitle = !this.axes.shouldRenderAxisTitle(axes.y2, /* defaultValue */ false, /* secondary */true);\r\n\r\n let renderAxisOptions: AxisRenderingOptions = {\r\n axisLabels: axisLabels,\r\n viewport: viewport,\r\n margin: margin,\r\n hideXAxisTitle: hideXAxisTitle,\r\n hideYAxisTitle: hideYAxisTitle,\r\n hideY2AxisTitle: hideY2AxisTitle,\r\n xLabelColor: xLabelColor,\r\n yLabelColor: yLabelColor,\r\n y2LabelColor: y2LabelColor,\r\n fontSize: SvgCartesianAxes.AxisLabelFontSize,\r\n };\r\n\r\n this.renderAxesLabels(renderAxisOptions);\r\n }\r\n else {\r\n this.axisGraphicsContext.selectAll('.xAxisLabel').remove();\r\n this.axisGraphicsContext.selectAll('.yAxisLabel').remove();\r\n }\r\n\r\n this.translateAxes(viewport, margin);\r\n }\r\n\r\n private renderAxesLabels(options: AxisRenderingOptions): void {\r\n debug.assertValue(options, 'options');\r\n debug.assertValue(options.viewport, 'options.viewport');\r\n debug.assertValue(options.axisLabels, 'options.axisLabels');\r\n\r\n this.axisGraphicsContext.selectAll('.xAxisLabel').remove();\r\n this.axisGraphicsContext.selectAll('.yAxisLabel').remove();\r\n\r\n let margin = options.margin;\r\n let width = options.viewport.width - (margin.left + margin.right);\r\n let height = options.viewport.height;\r\n let fontSize = options.fontSize;\r\n\r\n let heightOffset = fontSize;\r\n let showOnRight = this.axes.shouldShowY1OnRight();\r\n\r\n if (!options.hideXAxisTitle) {\r\n let xAxisLabel = this.axisGraphicsContext.append(\"text\")\r\n .style(\"text-anchor\", \"middle\")\r\n .text(options.axisLabels.x)\r\n .call((text: D3.Selection) => {\r\n text.each(function () {\r\n let text = d3.select(this);\r\n text.attr({\r\n \"class\": \"xAxisLabel\",\r\n \"transform\": SVGUtil.translate(width / 2, height - heightOffset)\r\n });\r\n });\r\n });\r\n\r\n xAxisLabel.style(\"fill\", options.xLabelColor ? options.xLabelColor.solid.color : null);\r\n\r\n xAxisLabel.call(AxisHelper.LabelLayoutStrategy.clip,\r\n width,\r\n TextMeasurementService.svgEllipsis)\r\n .call(tooltipUtils.tooltipUpdate, [options.axisLabels.x]);\r\n }\r\n\r\n if (!options.hideYAxisTitle) {\r\n let yAxisLabel = this.axisGraphicsContext.append(\"text\")\r\n .style(\"text-anchor\", \"middle\")\r\n .text(options.axisLabels.y)\r\n .call((text: D3.Selection) => {\r\n text.each(function () {\r\n let text = d3.select(this);\r\n text.attr({\r\n \"class\": \"yAxisLabel\",\r\n \"transform\": \"rotate(-90)\",\r\n \"y\": showOnRight ? width + margin.right - fontSize : -margin.left,\r\n \"x\": -((height - margin.top - margin.bottom) / 2),\r\n \"dy\": \"1em\",\r\n });\r\n });\r\n });\r\n\r\n yAxisLabel.style(\"fill\", options.yLabelColor ? options.yLabelColor.solid.color : null);\r\n\r\n yAxisLabel.call(AxisHelper.LabelLayoutStrategy.clip,\r\n height - (margin.bottom + margin.top),\r\n TextMeasurementService.svgEllipsis)\r\n .call(tooltipUtils.tooltipUpdate, [options.axisLabels.y]);\r\n }\r\n\r\n if (!options.hideY2AxisTitle && options.axisLabels.y2) {\r\n let y2AxisLabel = this.axisGraphicsContext.append(\"text\")\r\n .style(\"text-anchor\", \"middle\")\r\n .text(options.axisLabels.y2)\r\n .call((text: D3.Selection) => {\r\n text.each(function () {\r\n let text = d3.select(this);\r\n text.attr({\r\n \"class\": \"yAxisLabel\",\r\n \"transform\": \"rotate(-90)\",\r\n \"y\": showOnRight ? -margin.left : width + margin.right - fontSize,\r\n \"x\": -((height - margin.top - margin.bottom) / 2),\r\n \"dy\": \"1em\",\r\n });\r\n });\r\n });\r\n\r\n y2AxisLabel.style(\"fill\", options.y2LabelColor ? options.y2LabelColor.solid.color : null);\r\n\r\n y2AxisLabel.call(AxisHelper.LabelLayoutStrategy.clip,\r\n height - (margin.bottom + margin.top),\r\n TextMeasurementService.svgEllipsis)\r\n .call(tooltipUtils.tooltipUpdate, [options.axisLabels.y2]);\r\n }\r\n }\r\n\r\n // Margin convention: http://bl.ocks.org/mbostock/3019563\r\n private translateAxes(viewport: IViewport, margin: IMargin): void {\r\n let width = viewport.width - (margin.left + margin.right);\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n\r\n let showY1OnRight = this.axes.shouldShowY1OnRight();\r\n\r\n this.xAxisGraphicsContext\r\n .attr('transform', SVGUtil.translate(0, height));\r\n\r\n this.y1AxisGraphicsContext\r\n .attr('transform', SVGUtil.translate(showY1OnRight ? width : 0, 0));\r\n\r\n this.y2AxisGraphicsContext\r\n .attr('transform', SVGUtil.translate(showY1OnRight ? 0 : width, 0));\r\n\r\n this.svgScrollable.attr({\r\n 'x': 0,\r\n 'width': viewport.width,\r\n 'height': viewport.height\r\n });\r\n\r\n this.axisGraphicsContext.attr('transform', SVGUtil.translate(margin.left, margin.top));\r\n this.axisGraphicsContextScrollable.attr('transform', SVGUtil.translate(margin.left, margin.top));\r\n this.labelRegion.attr('transform', SVGUtil.translate(margin.left, margin.top));\r\n this.labelBackgroundRegion.attr('transform', SVGUtil.translate(margin.left, margin.top));\r\n\r\n if (this.axes.isXScrollBarVisible) {\r\n this.svgScrollable.attr({\r\n 'x': margin.left\r\n });\r\n this.axisGraphicsContextScrollable.attr('transform', SVGUtil.translate(0, margin.top));\r\n this.labelRegion.attr('transform', SVGUtil.translate(0, margin.top));\r\n this.labelBackgroundRegion.attr('transform', SVGUtil.translate(0, margin.top));\r\n this.svgScrollable.attr('width', width);\r\n }\r\n else if (this.axes.isYScrollBarVisible) {\r\n this.svgScrollable.attr('height', height + margin.top);\r\n }\r\n }\r\n\r\n /**\r\n * Within the context of the given selection (g), find the offset of\r\n * the zero tick using the d3 attached datum of g.tick elements.\r\n * 'Classed' is undefined for transition selections\r\n */\r\n private static darkenZeroLine(g: D3.Selection): void {\r\n // remove zero-line class from all first, filtering can cause lines that are no longer zero to still be dark (since the key is index based)\r\n g.selectAll('g.tick line').classed('zero-line', false);\r\n let zeroTick = g.selectAll('g.tick').filter((data) => data === 0).node();\r\n if (zeroTick) {\r\n d3.select(zeroTick).select('line').classed('zero-line', true);\r\n }\r\n }\r\n\r\n private static setAxisLabelColor(g: D3.Selection, fill: Fill): void {\r\n g.selectAll('g.tick text').style('fill', fill ? fill.solid.color : null);\r\n }\r\n }\r\n\r\n export class CartesianAxes {\r\n private static YAxisLabelPadding = 20;\r\n private static XAxisLabelPadding = 18;\r\n private static MaxMarginFactor = 0.25;\r\n private static MinimumMargin: IMargin = {\r\n left: 1,\r\n right: 1,\r\n top: 8, //half of the default font height\r\n bottom: 25,\r\n };\r\n\r\n private categoryAxisProperties: DataViewObject;\r\n private valueAxisProperties: DataViewObject;\r\n\r\n private maxMarginFactor: number;\r\n private yAxisOrientation: string;\r\n private scrollbarWidth: number;\r\n private trimOrdinalDataOnOverflow: boolean;\r\n public showLinesOnX: boolean;\r\n public showLinesOnY: boolean;\r\n public isScrollable: boolean;\r\n public isXScrollBarVisible: boolean;\r\n public isYScrollBarVisible: boolean;\r\n public categoryAxisHasUnitType: boolean;\r\n public valueAxisHasUnitType: boolean;\r\n public secondaryValueAxisHasUnitType: boolean;\r\n\r\n private layout: CartesianAxesLayout;\r\n\r\n constructor(isScrollable: boolean, scrollbarWidth: number, trimOrdinalDataOnOverflow: boolean) {\r\n this.scrollbarWidth = scrollbarWidth;\r\n this.isScrollable = isScrollable;\r\n this.maxMarginFactor = CartesianAxes.MaxMarginFactor;\r\n this.yAxisOrientation = yAxisPosition.left;\r\n this.trimOrdinalDataOnOverflow = trimOrdinalDataOnOverflow;\r\n }\r\n\r\n public shouldShowY1OnRight(): boolean {\r\n return this.yAxisOrientation === yAxisPosition.right;\r\n }\r\n\r\n public isYAxisCategorical(): boolean {\r\n return this.layout && this.layout.axes.y1.isCategoryAxis;\r\n }\r\n\r\n public hasCategoryAxis(): boolean {\r\n let axes = this.layout && this.layout.axes;\r\n if (!axes)\r\n return false;\r\n\r\n return this.isYAxisCategorical()\r\n ? axes.y1 && axes.y1.axis != null\r\n : axes.x && axes.x.axis != null;\r\n }\r\n\r\n public hasY2Axis(): boolean {\r\n return this.layout && this.layout.axes.y2 != null;\r\n }\r\n\r\n public getYAxisOrientation(): string {\r\n return this.yAxisOrientation;\r\n }\r\n\r\n public setAxisLinesVisibility(axisLinesVisibility: AxisLinesVisibility): void {\r\n this.showLinesOnX = EnumExtensions.hasFlag(axisLinesVisibility, AxisLinesVisibility.ShowLinesOnBothAxis) ||\r\n EnumExtensions.hasFlag(axisLinesVisibility, AxisLinesVisibility.ShowLinesOnXAxis);\r\n\r\n this.showLinesOnY = EnumExtensions.hasFlag(axisLinesVisibility, AxisLinesVisibility.ShowLinesOnBothAxis) ||\r\n EnumExtensions.hasFlag(axisLinesVisibility, AxisLinesVisibility.ShowLinesOnYAxis);\r\n }\r\n\r\n public setMaxMarginFactor(factor: number): void {\r\n this.maxMarginFactor = factor;\r\n }\r\n\r\n public update(dataViews: DataView[]) {\r\n if (dataViews && dataViews.length > 0) {\r\n let dataViewMetadata = dataViews[0].metadata;\r\n this.categoryAxisProperties = CartesianHelper.getCategoryAxisProperties(dataViewMetadata);\r\n this.valueAxisProperties = CartesianHelper.getValueAxisProperties(dataViewMetadata);\r\n }\r\n\r\n let axisPosition = this.valueAxisProperties['position'];\r\n this.yAxisOrientation = axisPosition ? axisPosition.toString() : yAxisPosition.left;\r\n }\r\n\r\n public addWarnings(warnings: IVisualWarning[]): void {\r\n let axes = this.layout && this.layout.axes;\r\n if (axes && axes.x && axes.x.hasDisallowedZeroInDomain\r\n || axes.y1 && axes.y1.hasDisallowedZeroInDomain\r\n || axes.y2 && axes.y2.hasDisallowedZeroInDomain) {\r\n warnings.unshift(new ZeroValueWarning());\r\n }\r\n }\r\n\r\n /** \r\n * Computes the Cartesian Chart axes from the set of layers.\r\n */\r\n private calculateAxes(\r\n layers: ICartesianVisual[],\r\n viewport: IViewport,\r\n margin: IMargin,\r\n playAxisControlLayout: IRect,\r\n textProperties: TextProperties,\r\n scrollbarVisible: boolean,\r\n existingAxisProperties: CartesianAxisProperties,\r\n hideAxisTitles: boolean,\r\n ensureXDomain?: NumberRange,\r\n ensureYDomain?: NumberRange): CartesianAxisProperties {\r\n debug.assertValue(layers, 'layers');\r\n\r\n let visualOptions: CalculateScaleAndDomainOptions = {\r\n viewport: viewport,\r\n margin: margin,\r\n forcedXDomain: [this.categoryAxisProperties ? this.categoryAxisProperties['start'] : null, this.categoryAxisProperties ? this.categoryAxisProperties['end'] : null],\r\n forceMerge: this.valueAxisProperties && this.valueAxisProperties['secShow'] === false,\r\n showCategoryAxisLabel: false,\r\n showValueAxisLabel: false,\r\n trimOrdinalDataOnOverflow: this.trimOrdinalDataOnOverflow,\r\n categoryAxisScaleType: this.categoryAxisProperties && this.categoryAxisProperties['axisScale'] != null ? <string>this.categoryAxisProperties['axisScale'] : DEFAULT_AXIS_SCALE_TYPE,\r\n valueAxisScaleType: this.valueAxisProperties && this.valueAxisProperties['axisScale'] != null ? <string>this.valueAxisProperties['axisScale'] : DEFAULT_AXIS_SCALE_TYPE,\r\n categoryAxisDisplayUnits: this.categoryAxisProperties && this.categoryAxisProperties['labelDisplayUnits'] != null ? <number>this.categoryAxisProperties['labelDisplayUnits'] : 0,\r\n valueAxisDisplayUnits: this.valueAxisProperties && this.valueAxisProperties['labelDisplayUnits'] != null ? <number>this.valueAxisProperties['labelDisplayUnits'] : 0,\r\n categoryAxisPrecision: this.categoryAxisProperties ? CartesianHelper.getPrecision(this.categoryAxisProperties['labelPrecision']) : null,\r\n valueAxisPrecision: this.valueAxisProperties ? CartesianHelper.getPrecision(this.valueAxisProperties['labelPrecision']) : null,\r\n playAxisControlLayout: playAxisControlLayout,\r\n ensureXDomain: ensureXDomain,\r\n ensureYDomain: ensureYDomain,\r\n };\r\n\r\n let skipMerge = this.valueAxisProperties && this.valueAxisProperties['secShow'] === true;\r\n\r\n let yAxisWillMerge = false;\r\n let mergeResult: MergedValueAxisResult;\r\n if (hasMultipleYAxes(layers) && !skipMerge) {\r\n mergeResult = tryMergeYDomains(layers, visualOptions);\r\n yAxisWillMerge = mergeResult.merged;\r\n if (yAxisWillMerge) {\r\n visualOptions.forcedYDomain = mergeResult.domain;\r\n }\r\n else {\r\n visualOptions.forcedTickCount = mergeResult.tickCount;\r\n }\r\n }\r\n\r\n if (this.valueAxisProperties) {\r\n visualOptions.forcedYDomain = AxisHelper.applyCustomizedDomain([this.valueAxisProperties['start'], this.valueAxisProperties['end']], visualOptions.forcedYDomain);\r\n }\r\n\r\n let result: CartesianAxisProperties;\r\n for (let layerNumber = 0, len = layers.length; layerNumber < len; layerNumber++) {\r\n let currentlayer = layers[layerNumber];\r\n\r\n if (layerNumber === 1 && !yAxisWillMerge) {\r\n visualOptions.forcedYDomain = this.valueAxisProperties ? [this.valueAxisProperties['secStart'], this.valueAxisProperties['secEnd']] : null;\r\n visualOptions.valueAxisScaleType = this.valueAxisProperties && this.valueAxisProperties['secAxisScale'] != null ? <string>this.valueAxisProperties['secAxisScale'] : DEFAULT_AXIS_SCALE_TYPE;\r\n visualOptions.valueAxisDisplayUnits = this.valueAxisProperties && this.valueAxisProperties['secLabelDisplayUnits'] != null ? <number>this.valueAxisProperties['secLabelDisplayUnits'] : 0;\r\n visualOptions.valueAxisPrecision = this.valueAxisProperties ? CartesianHelper.getPrecision(this.valueAxisProperties['secLabelPrecision']) : null;\r\n }\r\n visualOptions.showCategoryAxisLabel = (!!this.categoryAxisProperties && !!this.categoryAxisProperties['showAxisTitle']);//here\r\n\r\n visualOptions.showValueAxisLabel = shouldShowYAxisLabel(layerNumber, this.valueAxisProperties, yAxisWillMerge);\r\n\r\n let axes = currentlayer.calculateAxesProperties(visualOptions);\r\n\r\n if (layerNumber === 0) {\r\n result = {\r\n x: axes[0],\r\n y1: axes[1]\r\n };\r\n }\r\n else if (axes && !result.y2) {\r\n if (result.x.usingDefaultDomain || _.isEmpty(result.x.dataDomain)) {\r\n visualOptions.showValueAxisLabel = (!!this.valueAxisProperties && !!this.valueAxisProperties['showAxisTitle']);\r\n\r\n let axes = currentlayer.calculateAxesProperties(visualOptions);\r\n // no categories returned for the first layer, use second layer x-axis properties\r\n result.x = axes[0];\r\n // and 2nd value axis to be the primary\r\n result.y1 = axes[1];\r\n }\r\n else {\r\n // make sure all layers use the same x-axis/scale for drawing\r\n currentlayer.overrideXScale(result.x);\r\n if (!yAxisWillMerge && !axes[1].usingDefaultDomain)\r\n result.y2 = axes[1];\r\n }\r\n }\r\n\r\n if (existingAxisProperties && existingAxisProperties.x) {\r\n result.x.willLabelsFit = existingAxisProperties.x.willLabelsFit;\r\n result.x.willLabelsWordBreak = existingAxisProperties.x.willLabelsWordBreak;\r\n } else {\r\n let width = viewport.width - (margin.left + margin.right);\r\n result.x.willLabelsFit = AxisHelper.LabelLayoutStrategy.willLabelsFit(\r\n result.x,\r\n width,\r\n TextMeasurementService.measureSvgTextWidth,\r\n textProperties);\r\n\r\n // If labels do not fit and we are not scrolling, try word breaking\r\n result.x.willLabelsWordBreak = (!result.x.willLabelsFit && !scrollbarVisible) && AxisHelper.LabelLayoutStrategy.willLabelsWordBreak(\r\n result.x,\r\n margin,\r\n width,\r\n TextMeasurementService.measureSvgTextWidth,\r\n TextMeasurementService.estimateSvgTextHeight,\r\n TextMeasurementService.getTailoredTextOrDefault,\r\n textProperties);\r\n }\r\n }\r\n\r\n // Adjust for axis titles\r\n if (hideAxisTitles) {\r\n result.x.axisLabel = null;\r\n result.y1.axisLabel = null;\r\n if (result.y2) {\r\n result.y2.axisLabel = null;\r\n }\r\n }\r\n this.addUnitTypeToAxisLabels(result);\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Negotiate the axes regions, the plot area, and determine if we need a scrollbar for ordinal categories.\r\n * @param layers an array of Cartesian layout layers (column, line, etc.)\r\n * @param parentViewport the full viewport for the visual\r\n * @param padding the D3 axis padding values\r\n * @param playAxisControlLayout if this is a playable Cartesian chart, includes the layout for the play controls (start/stop, time slider)\r\n * @param hideAxisLabels forces axis titles to be hidden\r\n * @param textProperties text properties to be used by text measurement\r\n * @param interactivityRightMargin extra right margin for the interactivity\r\n * @param ensureXDomain if non null, includes values that must be part of the axis domain\r\n * @param ensureYDomain if non null, includes values that must be part of the axis domain\r\n */\r\n public negotiateAxes(\r\n layers: ICartesianVisual[],\r\n parentViewport: IViewport,\r\n padding: IMargin,\r\n playAxisControlLayout: IRect,\r\n hideAxisLabels: boolean,\r\n textProperties: TextProperties,\r\n interactivityRightMargin: number,\r\n ensureXDomain?: NumberRange,\r\n ensureYDomain?: NumberRange): CartesianAxesLayout {\r\n\r\n // 1> MinMargins -> some initial axis properties / text\r\n // 2> Get axis margins for the initial text, no rotateXTickLabels90. margins grown? -> axis properties / text again (possibly more tick labels now)\r\n // ?> do we have more labels? do we need rotate? are we done?\r\n // 3> margins again (rotate? margins grow?) -> text again (less tick labls now?)\r\n // FREEZE PROPERTIES THAT CAN CHANGE\r\n // 4> margins (final), axes (final)\r\n \r\n // 1.a) initialize margins\r\n let margin: IMargin = Prototype.inherit(CartesianAxes.MinimumMargin);\r\n let viewport: IViewport = Prototype.inherit(parentViewport);\r\n let leftRightMarginLimit = viewport.width * this.maxMarginFactor;\r\n let bottomMarginLimit = Math.max(CartesianAxes.MinimumMargin.bottom, Math.ceil(viewport.height * this.maxMarginFactor));\r\n let marginLimits = {\r\n left: leftRightMarginLimit,\r\n right: leftRightMarginLimit,\r\n top: 0,\r\n bottom: bottomMarginLimit,\r\n };\r\n\r\n // 1.b) Calculate axis properties using initial margins\r\n let axes = this.calculateAxes(\r\n layers,\r\n viewport,\r\n margin,\r\n playAxisControlLayout,\r\n textProperties,\r\n /*scrollbarVisible*/ false,\r\n /*previousAxisProperties*/ null,\r\n hideAxisLabels,\r\n ensureXDomain,\r\n ensureYDomain);\r\n\r\n // these are used by getTickLabelMargins\r\n let renderXAxis = this.shouldRenderAxis(axes.x);\r\n let renderY1Axis = this.shouldRenderAxis(axes.y1);\r\n let renderY2Axis = this.shouldRenderAxis(axes.y2, true);\r\n let showY1OnRight = this.shouldShowY1OnRight();\r\n\r\n let plotArea: IViewport = {\r\n width: viewport.width - (margin.left + margin.right),\r\n height: viewport.height - (margin.top + margin.bottom)\r\n };\r\n\r\n let isScalar = false;\r\n if (!_.isEmpty(layers)) {\r\n if (layers[0].getVisualCategoryAxisIsScalar)\r\n isScalar = layers[0].getVisualCategoryAxisIsScalar();\r\n }\r\n\r\n // 2.a) calculate axis tick margins\r\n let tickLabelMargins = undefined;\r\n tickLabelMargins = AxisHelper.getTickLabelMargins(\r\n plotArea,\r\n marginLimits.left,\r\n TextMeasurementService.measureSvgTextWidth,\r\n TextMeasurementService.estimateSvgTextHeight,\r\n axes,\r\n marginLimits.bottom,\r\n textProperties,\r\n /*scrolling*/ false,\r\n showY1OnRight,\r\n renderXAxis,\r\n renderY1Axis,\r\n renderY2Axis);\r\n\r\n margin = this.updateAxisMargins(axes, tickLabelMargins, padding, showY1OnRight, renderY1Axis, renderY2Axis, isScalar ? 0 : interactivityRightMargin);\r\n\r\n // if any of these change, we need to calculate margins again\r\n let previousTickCountY1 = axes.y1 && axes.y1.values.length;\r\n let previousTickCountY2 = axes.y2 && axes.y2.values.length;\r\n let previousWillFitX = axes.x && axes.x.willLabelsFit;\r\n let previousWillBreakX = axes.x && axes.x.willLabelsWordBreak;\r\n\r\n // 2.b) Re-calculate the axes with the new margins.\r\n axes = this.calculateAxes(\r\n layers,\r\n viewport,\r\n margin,\r\n playAxisControlLayout,\r\n textProperties,\r\n /*scrollbarVisible*/ false,\r\n /*previousAxes*/ null,\r\n hideAxisLabels,\r\n ensureXDomain,\r\n ensureYDomain);\r\n\r\n plotArea.width = viewport.width - (margin.left + margin.right);\r\n plotArea.height = viewport.height - (margin.top + margin.bottom);\r\n\r\n // check properties that affect getTickLabelMargin - if these are the same, we don't need to calculate axis margins again\r\n let preferredPlotArea: IViewport = this.getPreferredPlotArea(axes, layers, isScalar);\r\n let rotateXTickLabels90 = !this.willAllCategoriesFitInPlotArea(plotArea, preferredPlotArea);\r\n let allDone = ((!axes.y1 || axes.y1.values.length === previousTickCountY1)\r\n && (!axes.y2 || axes.y2.values.length === previousTickCountY2)\r\n && (!axes.x || axes.x.willLabelsFit === previousWillFitX)\r\n && (!axes.x || axes.x.willLabelsWordBreak === previousWillBreakX)\r\n && !rotateXTickLabels90);\r\n\r\n this.isXScrollBarVisible = false;\r\n this.isYScrollBarVisible = false;\r\n if (!allDone) {\r\n // 3.a) calculate axis tick margins\r\n tickLabelMargins = AxisHelper.getTickLabelMargins(\r\n plotArea,\r\n marginLimits.left,\r\n TextMeasurementService.measureSvgTextWidth,\r\n TextMeasurementService.estimateSvgTextHeight,\r\n axes,\r\n marginLimits.bottom,\r\n textProperties,\r\n rotateXTickLabels90,\r\n showY1OnRight,\r\n renderXAxis,\r\n renderY1Axis,\r\n renderY2Axis);\r\n\r\n margin = this.updateAxisMargins(axes, tickLabelMargins, padding, showY1OnRight, renderY1Axis, renderY2Axis, isScalar ? 0 : interactivityRightMargin);\r\n\r\n // 3.b) Re-calculate the axes with the new final margins\r\n axes = this.calculateAxes(\r\n layers,\r\n viewport,\r\n margin,\r\n playAxisControlLayout,\r\n textProperties,\r\n /*scrollbarVisible*/ rotateXTickLabels90,\r\n axes,\r\n hideAxisLabels,\r\n ensureXDomain,\r\n ensureYDomain);\r\n\r\n // now we can determine if we need actual scrolling\r\n // rotateXTickLabels90 will give more plotArea to categories since the left-overflow of a rotated category label doesn't exist anymore\r\n plotArea.width = viewport.width - (margin.left + margin.right);\r\n plotArea.height = viewport.height - (margin.top + margin.bottom);\r\n preferredPlotArea = this.getPreferredPlotArea(axes, layers, isScalar);\r\n let willScroll = !this.willAllCategoriesFitInPlotArea(plotArea, preferredPlotArea);\r\n if (willScroll) {\r\n if (this.showLinesOnY) {\r\n this.isXScrollBarVisible = true;\r\n plotArea.height -= this.scrollbarWidth;\r\n viewport.height -= this.scrollbarWidth;\r\n }\r\n if (this.showLinesOnX) {\r\n this.isYScrollBarVisible = true;\r\n plotArea.width -= this.scrollbarWidth;\r\n viewport.width -= this.scrollbarWidth;\r\n }\r\n\r\n // 3.c) Re-calculate the axes with the final margins (and the updated viewport - scrollbarWidth)\r\n axes = this.calculateAxes(\r\n layers,\r\n viewport,\r\n margin,\r\n playAxisControlLayout,\r\n textProperties,\r\n /*scrollbarVisible*/ true,\r\n axes,\r\n hideAxisLabels,\r\n ensureXDomain,\r\n ensureYDomain);\r\n }\r\n }\r\n\r\n ///////DONE\r\n let axisLabels = hideAxisLabels ?\r\n { x: null, y: null, y2: null } :\r\n { x: axes.x.axisLabel, y: axes.y1.axisLabel, y2: axes.y2 ? axes.y2.axisLabel : null };\r\n\r\n this.layout = {\r\n axes: axes,\r\n axisLabels: axisLabels,\r\n margin: margin,\r\n marginLimits: marginLimits,\r\n viewport: viewport,\r\n plotArea: plotArea,\r\n preferredPlotArea: preferredPlotArea,\r\n tickLabelMargins: tickLabelMargins,\r\n tickPadding: padding,\r\n rotateXTickLabels90: rotateXTickLabels90,\r\n };\r\n\r\n return this.layout;\r\n }\r\n\r\n private getPreferredPlotArea(axes, layers, isScalar): IViewport {\r\n let preferredPlotArea: IViewport;\r\n if (!isScalar && this.isScrollable && !_.isEmpty(layers) && layers[0].getPreferredPlotArea) {\r\n let categoryThickness = this.showLinesOnY ? axes.x.categoryThickness : axes.y1.categoryThickness;\r\n let categoryCount = this.showLinesOnY ? axes.x.dataDomain.length : axes.y1.dataDomain.length;\r\n preferredPlotArea = layers[0].getPreferredPlotArea(isScalar, categoryCount, categoryThickness);\r\n }\r\n return preferredPlotArea;\r\n }\r\n\r\n private willAllCategoriesFitInPlotArea(plotArea: IViewport, preferredPlotArea: IViewport): boolean {\r\n if (this.showLinesOnY && preferredPlotArea && Double.greaterWithPrecision(preferredPlotArea.width, plotArea.width)) {\r\n return false;\r\n }\r\n if (this.showLinesOnX && preferredPlotArea && Double.greaterWithPrecision(preferredPlotArea.height, plotArea.height)) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n private updateAxisMargins(\r\n axes: CartesianAxisProperties,\r\n tickLabelMargins: TickLabelMargins,\r\n padding: IMargin,\r\n showY1OnRight: boolean,\r\n renderY1Axis: boolean,\r\n renderY2Axis: boolean,\r\n interactivityRightMargin: number): IMargin {\r\n\r\n // We look at the y axes as main and second sides, if the y axis orientation is right then the main side represents the right side.\r\n let maxY1Padding = showY1OnRight ? tickLabelMargins.yRight : tickLabelMargins.yLeft,\r\n maxY2Padding = showY1OnRight ? tickLabelMargins.yLeft : tickLabelMargins.yRight,\r\n maxXAxisBottom = tickLabelMargins.xMax;\r\n\r\n maxY1Padding += padding.left;\r\n if ((renderY2Axis && !showY1OnRight) || (showY1OnRight && renderY1Axis))\r\n maxY2Padding += padding.right;\r\n maxXAxisBottom += padding.bottom;\r\n\r\n let axisLabels = { x: axes.x.axisLabel, y: axes.y1.axisLabel, y2: axes.y2 ? axes.y2.axisLabel : null };\r\n if (axisLabels.x != null)\r\n maxXAxisBottom += CartesianAxes.XAxisLabelPadding;\r\n if (axisLabels.y != null)\r\n maxY1Padding += CartesianAxes.YAxisLabelPadding;\r\n if (axisLabels.y2 != null)\r\n maxY2Padding += CartesianAxes.YAxisLabelPadding;\r\n\r\n let margin: IMargin = Prototype.inherit(CartesianAxes.MinimumMargin);\r\n margin.left = showY1OnRight ? maxY2Padding : maxY1Padding;\r\n margin.right = showY1OnRight ? maxY1Padding : maxY2Padding;\r\n margin.right += interactivityRightMargin; // for mobile interactive legend\r\n margin.bottom = maxXAxisBottom;\r\n\r\n return margin;\r\n }\r\n\r\n public isLogScaleAllowed(axisType: AxisLocation): boolean {\r\n let axes = this.layout && this.layout.axes;\r\n if (!axes)\r\n return false;\r\n\r\n switch (axisType) {\r\n case AxisLocation.X:\r\n return axes.x.isLogScaleAllowed;\r\n case AxisLocation.Y1:\r\n return axes.y1.isLogScaleAllowed;\r\n case AxisLocation.Y2:\r\n return axes.y2 && axes.y2.isLogScaleAllowed;\r\n }\r\n }\r\n\r\n public axesHaveTicks(viewport: IViewport): boolean {\r\n if (!this.layout)\r\n return false;\r\n\r\n let margin = this.layout.margin;\r\n\r\n let width = viewport.width - (margin.left + margin.right);\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n\r\n // TODO: this is never the case, remove.\r\n if (AxisHelper.getRecommendedNumberOfTicksForXAxis(width) === 0\r\n && AxisHelper.getRecommendedNumberOfTicksForYAxis(height) === 0) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n public shouldRenderAxisTitle(axisProperties: IAxisProperties, defaultValue: boolean, secondary: boolean): boolean {\r\n let propertyName = secondary ? 'secShowAxisTitle' : 'showAxisTitle';\r\n\r\n return !!this.getAxisProperty(axisProperties, propertyName, defaultValue);\r\n }\r\n\r\n public shouldRenderAxis(axisProperties: IAxisProperties, secondary: boolean = false): boolean {\r\n if (!axisProperties)\r\n return false;\r\n\r\n let propertyName = secondary ? 'secShow' : 'show';\r\n\r\n return this.getAxisProperty(axisProperties, propertyName, true)\r\n && axisProperties.values\r\n && axisProperties.values.length > 0;\r\n }\r\n\r\n private getAxisProperty(axisProperties: IAxisProperties, propertyName: string, defaultValue: DataViewPropertyValue): DataViewPropertyValue {\r\n if (!axisProperties)\r\n return defaultValue;\r\n\r\n let properties = axisProperties.isCategoryAxis\r\n ? this.categoryAxisProperties\r\n : this.valueAxisProperties;\r\n\r\n if (properties && properties[propertyName] != null)\r\n return properties[propertyName];\r\n else\r\n return defaultValue;\r\n }\r\n\r\n // TODO: clean this up\r\n private addUnitTypeToAxisLabels(axes: CartesianAxisProperties): void {\r\n let unitType = CartesianAxes.getUnitType(axes.x.formatter);\r\n if (axes.x.isCategoryAxis) {\r\n this.categoryAxisHasUnitType = unitType != null;\r\n }\r\n else {\r\n this.valueAxisHasUnitType = unitType != null;\r\n }\r\n\r\n if (axes.x.axisLabel && unitType) {\r\n if (axes.x.isCategoryAxis) {\r\n axes.x.axisLabel = AxisHelper.createAxisLabel(this.categoryAxisProperties, axes.x.axisLabel, unitType);\r\n }\r\n else {\r\n axes.x.axisLabel = AxisHelper.createAxisLabel(this.valueAxisProperties, axes.x.axisLabel, unitType);\r\n }\r\n }\r\n\r\n unitType = CartesianAxes.getUnitType(axes.y1.formatter);\r\n\r\n if (!axes.y1.isCategoryAxis) {\r\n this.valueAxisHasUnitType = unitType != null;\r\n }\r\n else {\r\n this.categoryAxisHasUnitType = unitType != null;\r\n }\r\n\r\n if (axes.y1.axisLabel && unitType) {\r\n if (!axes.y1.isCategoryAxis) {\r\n axes.y1.axisLabel = AxisHelper.createAxisLabel(this.valueAxisProperties, axes.y1.axisLabel, unitType);\r\n }\r\n else {\r\n axes.y1.axisLabel = AxisHelper.createAxisLabel(this.categoryAxisProperties, axes.y1.axisLabel, unitType);\r\n }\r\n }\r\n\r\n if (axes.y2) {\r\n let unitType = CartesianAxes.getUnitType(axes.y2.formatter);\r\n this.secondaryValueAxisHasUnitType = unitType != null;\r\n if (axes.y2.axisLabel && unitType) {\r\n axes.y2.axisLabel = AxisHelper.createAxisLabel(this.valueAxisProperties, axes.y2.axisLabel, unitType, true);\r\n }\r\n }\r\n }\r\n\r\n private static getUnitType(formatter: IValueFormatter) {\r\n if (formatter &&\r\n formatter.displayUnit &&\r\n formatter.displayUnit.value > 1)\r\n return formatter.displayUnit.title;\r\n }\r\n }\r\n\r\n module CartesianLayerFactory {\r\n\r\n export function createLayers(\r\n type: CartesianChartType,\r\n objects: DataViewObjects,\r\n interactivityService: IInteractivityService,\r\n animator?: any,\r\n isScrollable: boolean = false,\r\n tooltipsEnabled?: boolean,\r\n lineChartLabelDensityEnabled?: boolean): ICartesianVisual[] {\r\n\r\n let layers: ICartesianVisual[] = [];\r\n\r\n let cartesianOptions: CartesianVisualConstructorOptions = {\r\n isScrollable: isScrollable,\r\n animator: animator,\r\n interactivityService: interactivityService,\r\n tooltipsEnabled: tooltipsEnabled,\r\n lineChartLabelDensityEnabled: lineChartLabelDensityEnabled,\r\n };\r\n\r\n switch (type) {\r\n case CartesianChartType.Area:\r\n layers.push(createLineChartLayer(LineChartType.area, /* inComboChart */ false, cartesianOptions));\r\n //layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ false, cartesianOptions, true));\r\n break;\r\n case CartesianChartType.Line:\r\n layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ false, cartesianOptions));\r\n //layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ false, cartesianOptions, true));\r\n break;\r\n case CartesianChartType.StackedArea:\r\n layers.push(createLineChartLayer(LineChartType.stackedArea, /* inComboChart */ false, cartesianOptions));\r\n break;\r\n case CartesianChartType.Scatter:\r\n layers.push(createScatterChartLayer(cartesianOptions));\r\n //layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ false, cartesianOptions, true));\r\n break;\r\n case CartesianChartType.Waterfall:\r\n layers.push(createWaterfallChartLayer(cartesianOptions));\r\n break;\r\n case CartesianChartType.DataDot:\r\n layers.push(createDataDotChartLayer(cartesianOptions));\r\n break;\r\n case CartesianChartType.StackedColumn:\r\n layers.push(createColumnChartLayer(ColumnChartType.stackedColumn, cartesianOptions));\r\n break;\r\n case CartesianChartType.ClusteredColumn:\r\n layers.push(createColumnChartLayer(ColumnChartType.clusteredColumn, cartesianOptions));\r\n break;\r\n case CartesianChartType.HundredPercentStackedColumn:\r\n layers.push(createColumnChartLayer(ColumnChartType.hundredPercentStackedColumn, cartesianOptions));\r\n break;\r\n case CartesianChartType.StackedBar:\r\n layers.push(createColumnChartLayer(ColumnChartType.stackedBar, cartesianOptions));\r\n break;\r\n case CartesianChartType.ClusteredBar:\r\n layers.push(createColumnChartLayer(ColumnChartType.clusteredBar, cartesianOptions));\r\n break;\r\n case CartesianChartType.HundredPercentStackedBar:\r\n layers.push(createColumnChartLayer(ColumnChartType.hundredPercentStackedBar, cartesianOptions));\r\n break;\r\n case CartesianChartType.ComboChart:\r\n let columnType = getComboColumnType();\r\n layers.push(createColumnChartLayer(columnType, cartesianOptions));\r\n layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ true, cartesianOptions));\r\n break;\r\n case CartesianChartType.LineClusteredColumnCombo:\r\n layers.push(createColumnChartLayer(ColumnChartType.clusteredColumn, cartesianOptions));\r\n layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ true, cartesianOptions));\r\n break;\r\n case CartesianChartType.LineStackedColumnCombo:\r\n layers.push(createColumnChartLayer(ColumnChartType.stackedColumn, cartesianOptions));\r\n layers.push(createLineChartLayer(LineChartType.default, /* inComboChart */ true, cartesianOptions));\r\n break;\r\n case CartesianChartType.DataDotClusteredColumnCombo:\r\n layers.push(createColumnChartLayer(ColumnChartType.clusteredColumn, cartesianOptions));\r\n layers.push(createDataDotChartLayer(cartesianOptions));\r\n break;\r\n case CartesianChartType.DataDotStackedColumnCombo:\r\n layers.push(createColumnChartLayer(ColumnChartType.stackedColumn, cartesianOptions));\r\n layers.push(createDataDotChartLayer(cartesianOptions));\r\n break;\r\n }\r\n\r\n return layers;\r\n }\r\n\r\n function createLineChartLayer(type: LineChartType, inComboChart: boolean, defaultOptions: CartesianVisualConstructorOptions, isTrendLayer?: boolean): LineChart {\r\n let options: LineChartConstructorOptions = {\r\n animator: defaultOptions.animator,\r\n interactivityService: defaultOptions.interactivityService,\r\n isScrollable: defaultOptions.isScrollable,\r\n tooltipsEnabled: !isTrendLayer && defaultOptions.tooltipsEnabled,\r\n chartType: type,\r\n lineChartLabelDensityEnabled: defaultOptions.lineChartLabelDensityEnabled,\r\n isTrendLayer: isTrendLayer,\r\n };\r\n\r\n if (inComboChart) {\r\n options.chartType = options.chartType | LineChartType.lineShadow;\r\n }\r\n\r\n return new LineChart(options);\r\n }\r\n\r\n function createScatterChartLayer(defaultOptions: CartesianVisualConstructorOptions): ScatterChart {\r\n defaultOptions.isScrollable = false;\r\n return new ScatterChart(defaultOptions);\r\n }\r\n\r\n function createWaterfallChartLayer(defaultOptions: CartesianVisualConstructorOptions): WaterfallChart {\r\n return new WaterfallChart(defaultOptions);\r\n }\r\n\r\n function createDataDotChartLayer(defaultOptions: CartesianVisualConstructorOptions): DataDotChart {\r\n return new DataDotChart(defaultOptions);\r\n }\r\n\r\n function createColumnChartLayer(type: ColumnChartType, defaultOptions: CartesianVisualConstructorOptions): ColumnChart {\r\n let options: ColumnChartConstructorOptions = {\r\n animator: <IColumnChartAnimator>defaultOptions.animator,\r\n interactivityService: defaultOptions.interactivityService,\r\n isScrollable: defaultOptions.isScrollable,\r\n tooltipsEnabled: defaultOptions.tooltipsEnabled,\r\n chartType: type\r\n };\r\n return new ColumnChart(options);\r\n }\r\n\r\n function getComboColumnType(objects?: DataViewObjects): ColumnChartType {\r\n // This supports existing serialized forms of pinned combo-chart visuals\r\n let columnType: ColumnChartType = ColumnChartType.clusteredColumn;\r\n if (objects) {\r\n let comboChartTypes: ComboChartDataViewObject = (<ComboChartDataViewObjects>objects).general;\r\n if (comboChartTypes) {\r\n switch (comboChartTypes.visualType1) {\r\n case 'Column':\r\n columnType = ColumnChartType.clusteredColumn;\r\n break;\r\n case 'ColumnStacked':\r\n columnType = ColumnChartType.stackedColumn;\r\n break;\r\n default:\r\n debug.assertFail('Unsupported cartesian chart type ' + comboChartTypes.visualType1);\r\n }\r\n\r\n // second visual is always LineChart (for now)\r\n if (comboChartTypes.visualType2) {\r\n debug.assert(comboChartTypes.visualType2 === 'Line', 'expecting a LineChart for VisualType2');\r\n }\r\n }\r\n }\r\n\r\n return columnType;\r\n }\r\n }\r\n\r\n export class SharedColorPalette implements IDataColorPalette {\r\n private palette: IDataColorPalette;\r\n private preferredScale: IColorScale;\r\n private rotated: boolean;\r\n\r\n constructor(palette: IDataColorPalette) {\r\n this.palette = palette;\r\n this.clearPreferredScale();\r\n }\r\n\r\n public getColorScaleByKey(scaleKey: string): IColorScale {\r\n this.setPreferredScale(scaleKey);\r\n return this.preferredScale;\r\n }\r\n\r\n public getNewColorScale(): IColorScale {\r\n return this.preferredScale;\r\n }\r\n\r\n public getColorByIndex(index: number): IColorInfo {\r\n return this.palette.getColorByIndex(index);\r\n }\r\n\r\n public getSentimentColors(): IColorInfo[] {\r\n return this.palette.getSentimentColors();\r\n }\r\n\r\n public getBasePickerColors(): IColorInfo[] {\r\n return this.palette.getBasePickerColors();\r\n }\r\n\r\n public clearPreferredScale(): void {\r\n this.preferredScale = this.palette.getNewColorScale();\r\n this.rotated = false;\r\n }\r\n\r\n public rotateScale(): void {\r\n // We create a new rotated the scale such that the first color of the new scale is the first\r\n // free color of the previous scale. Note that the new scale does not have any colors allocated\r\n // to particular keys.\r\n this.preferredScale = this.preferredScale.clone();\r\n this.preferredScale.clearAndRotateScale();\r\n this.rotated = true;\r\n }\r\n\r\n private setPreferredScale(scaleKey: string): void {\r\n if (!this.rotated) {\r\n // The first layer to express a preference sets the preferred scale.\r\n this.preferredScale = this.palette.getColorScaleByKey(scaleKey);\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import EnumExtensions = jsCommon.EnumExtensions;\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface ColumnChartConstructorOptions extends CartesianVisualConstructorOptions {\r\n chartType: ColumnChartType;\r\n animator: IColumnChartAnimator;\r\n }\r\n\r\n export interface ColumnChartData extends CartesianData {\r\n categoryFormatter: IValueFormatter;\r\n series: ColumnChartSeries[];\r\n valuesMetadata: DataViewMetadataColumn[];\r\n legendData: LegendData;\r\n hasHighlights: boolean;\r\n categoryMetadata: DataViewMetadataColumn;\r\n scalarCategoryAxis: boolean;\r\n labelSettings: VisualDataLabelsSettings;\r\n axesLabels: ChartAxesLabels;\r\n hasDynamicSeries: boolean;\r\n isMultiMeasure: boolean;\r\n defaultDataPointColor?: string;\r\n showAllDataPoints?: boolean;\r\n }\r\n\r\n export interface ColumnChartSeries extends CartesianSeries {\r\n displayName: string;\r\n key: string;\r\n index: number;\r\n data: ColumnChartDataPoint[];\r\n identity: SelectionId;\r\n color: string;\r\n labelSettings: VisualDataLabelsSettings;\r\n }\r\n\r\n export interface ColumnChartDataPoint extends CartesianDataPoint, SelectableDataPoint, TooltipEnabledDataPoint, LabelEnabledDataPoint {\r\n categoryValue: number;\r\n /** Adjusted for 100% stacked if applicable */\r\n value: number;\r\n /** The top (column) or right (bar) of the rectangle, used for positioning stacked rectangles */\r\n position: number;\r\n valueAbsolute: number;\r\n /** Not adjusted for 100% stacked */\r\n valueOriginal: number;\r\n seriesIndex: number;\r\n labelSettings: VisualDataLabelsSettings;\r\n categoryIndex: number;\r\n color: string;\r\n /** The original values from the highlighted rect, used in animations */\r\n originalValue: number;\r\n originalPosition: number;\r\n originalValueAbsolute: number;\r\n\r\n /**\r\n * True if this data point is a highlighted portion and overflows (whether due to the highlight\r\n * being greater than original or of a different sign), so it needs to be thinner to accomodate.\r\n */\r\n drawThinner?: boolean;\r\n key: string;\r\n lastSeries?: boolean;\r\n chartType: ColumnChartType;\r\n }\r\n\r\n const flagBar: number = 1 << 1;\r\n const flagColumn: number = 1 << 2;\r\n const flagClustered: number = 1 << 3;\r\n const flagStacked: number = 1 << 4;\r\n const flagStacked100: number = flagStacked | (1 << 5);\r\n\r\n export enum ColumnChartType {\r\n clusteredBar = flagBar | flagClustered,\r\n clusteredColumn = flagColumn | flagClustered,\r\n hundredPercentStackedBar = flagBar | flagStacked100,\r\n hundredPercentStackedColumn = flagColumn | flagStacked100,\r\n stackedBar = flagBar | flagStacked,\r\n stackedColumn = flagColumn | flagStacked,\r\n }\r\n\r\n export interface ColumnAxisOptions {\r\n xScale: D3.Scale.Scale;\r\n yScale: D3.Scale.Scale;\r\n seriesOffsetScale?: D3.Scale.Scale;\r\n columnWidth: number;\r\n /** Used by clustered only since categoryWidth !== columnWidth */\r\n categoryWidth?: number;\r\n isScalar: boolean;\r\n margin: IMargin;\r\n }\r\n\r\n export interface IColumnLayout {\r\n shapeLayout: {\r\n width: (d: ColumnChartDataPoint) => number;\r\n x: (d: ColumnChartDataPoint) => number;\r\n y: (d: ColumnChartDataPoint) => number;\r\n height: (d: ColumnChartDataPoint) => number;\r\n };\r\n shapeLayoutWithoutHighlights: {\r\n width: (d: ColumnChartDataPoint) => number;\r\n x: (d: ColumnChartDataPoint) => number;\r\n y: (d: ColumnChartDataPoint) => number;\r\n height: (d: ColumnChartDataPoint) => number;\r\n };\r\n zeroShapeLayout: {\r\n width: (d: ColumnChartDataPoint) => number;\r\n x: (d: ColumnChartDataPoint) => number;\r\n y: (d: ColumnChartDataPoint) => number;\r\n height: (d: ColumnChartDataPoint) => number;\r\n };\r\n }\r\n\r\n export interface ColumnChartContext {\r\n height: number;\r\n width: number;\r\n duration: number;\r\n hostService: IVisualHostServices;\r\n margin: IMargin;\r\n /** A group for graphics can be placed that won't be clipped to the data area of the chart. */\r\n unclippedGraphicsContext: D3.Selection;\r\n /** A SVG for graphics that should be clipped to the data area, e.g. data bars, columns, lines */\r\n mainGraphicsContext: D3.Selection;\r\n layout: CategoryLayout;\r\n animator: IColumnChartAnimator;\r\n onDragStart?: (datum: ColumnChartDataPoint) => void;\r\n interactivityService: IInteractivityService;\r\n viewportHeight: number;\r\n viewportWidth: number;\r\n is100Pct: boolean;\r\n isComboChart: boolean;\r\n }\r\n\r\n export interface IColumnChartStrategy {\r\n setData(data: ColumnChartData): void;\r\n setupVisualProps(columnChartProps: ColumnChartContext): void;\r\n setXScale(is100Pct: boolean, forcedTickCount?: number, forcedXDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureXDomain?: NumberRange): IAxisProperties;\r\n setYScale(is100Pct: boolean, forcedTickCount?: number, forcedYDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureYDomain?: NumberRange): IAxisProperties;\r\n drawColumns(useAnimation: boolean): ColumnChartDrawInfo;\r\n selectColumn(selectedColumnIndex: number, lastSelectedColumnIndex: number): void;\r\n getClosestColumnIndex(x: number, y: number): number;\r\n }\r\n\r\n export interface IColumnChartConverterStrategy {\r\n getLegend(colors: IDataColorPalette, defaultLegendLabelColor: string, defaultColor?: string): LegendSeriesInfo;\r\n getValueBySeriesAndCategory(series: number, category: number): number;\r\n getMeasureNameByIndex(series: number, category: number): string;\r\n hasHighlightValues(series: number): boolean;\r\n getHighlightBySeriesAndCategory(series: number, category: number): number;\r\n }\r\n\r\n export interface LegendSeriesInfo {\r\n legend: LegendData;\r\n seriesSources: DataViewMetadataColumn[];\r\n seriesObjects: DataViewObjects[][];\r\n }\r\n\r\n export interface ColumnChartDrawInfo {\r\n eventGroup: D3.Selection;\r\n shapesSelection: D3.Selection;\r\n viewport: IViewport;\r\n axisOptions: ColumnAxisOptions;\r\n labelDataPoints: LabelDataPoint[];\r\n }\r\n const RoleNames = {\r\n category: 'Category',\r\n series: 'Series',\r\n y: 'Y',\r\n };\r\n\r\n /**\r\n * Renders a stacked and clustered column chart.\r\n */\r\n export class ColumnChart implements ICartesianVisual {\r\n private static ColumnChartClassName = 'columnChart';\r\n public static clusteredValidLabelPositions: RectLabelPosition[] = [RectLabelPosition.OutsideEnd, RectLabelPosition.InsideEnd, RectLabelPosition.InsideCenter, RectLabelPosition.InsideBase];\r\n public static stackedValidLabelPositions: RectLabelPosition[] = [RectLabelPosition.InsideCenter, RectLabelPosition.InsideEnd, RectLabelPosition.InsideBase];\r\n public static SeriesClasses: jsCommon.CssConstants.ClassAndSelector = jsCommon.CssConstants.createClassAndSelector('series');\r\n\r\n private svg: D3.Selection;\r\n private unclippedGraphicsContext: D3.Selection;\r\n private mainGraphicsContext: D3.Selection;\r\n private xAxisProperties: IAxisProperties;\r\n private yAxisProperties: IAxisProperties;\r\n private currentViewport: IViewport;\r\n private data: ColumnChartData;\r\n private style: IVisualStyle;\r\n private colors: IDataColorPalette;\r\n private chartType: ColumnChartType;\r\n private columnChart: IColumnChartStrategy;\r\n private hostService: IVisualHostServices;\r\n private cartesianVisualHost: ICartesianVisualHost;\r\n private interactivity: InteractivityOptions;\r\n private margin: IMargin;\r\n private options: CartesianVisualInitOptions;\r\n private lastInteractiveSelectedColumnIndex: number;\r\n private interactivityService: IInteractivityService;\r\n private dataView: DataView;\r\n private categoryAxisType: string;\r\n private animator: IColumnChartAnimator;\r\n private isScrollable: boolean;\r\n private tooltipsEnabled: boolean;\r\n private element: JQuery;\r\n private isComboChart: boolean;\r\n\r\n constructor(options: ColumnChartConstructorOptions) {\r\n debug.assertValue(options, 'options');\r\n\r\n let chartType = options.chartType;\r\n debug.assertValue(chartType, 'chartType');\r\n this.chartType = chartType;\r\n this.categoryAxisType = null;\r\n this.animator = options.animator;\r\n this.isScrollable = options.isScrollable;\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n this.interactivityService = options.interactivityService;\r\n }\r\n\r\n public static customizeQuery(options: CustomizeQueryOptions): void {\r\n let dataViewMapping = options.dataViewMappings[0];\r\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\r\n return;\r\n\r\n dataViewMapping.categorical.dataVolume = 4;\r\n\r\n if (CartesianChart.detectScalarMapping(dataViewMapping)) {\r\n let dataViewCategories = <data.CompiledDataViewRoleForMappingWithReduction>dataViewMapping.categorical.categories;\r\n dataViewCategories.dataReductionAlgorithm = { sample: {} };\r\n }\r\n }\r\n\r\n public static getSortableRoles(options: VisualSortableOptions): string[] {\r\n let dataViewMapping = options.dataViewMappings[0];\r\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\r\n return null;\r\n\r\n let dataViewCategories = <data.CompiledDataViewRoleForMappingWithReduction>dataViewMapping.categorical.categories;\r\n let categoryItems = dataViewCategories.for.in.items;\r\n if (!_.isEmpty(categoryItems)) {\r\n let categoryType = categoryItems[0].type;\r\n\r\n let objects: DataViewObjects;\r\n if (dataViewMapping.metadata)\r\n objects = dataViewMapping.metadata.objects;\r\n\r\n //TODO: column chart should be sortable by X if it has scalar axis\r\n // But currenly it doesn't support this. Return 'category' once\r\n // it is supported.\r\n if (!CartesianChart.getIsScalar(objects, columnChartProps.categoryAxis.axisType, categoryType)) {\r\n return ['Category', 'Y'];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n public updateVisualMetadata(x: IAxisProperties, y: IAxisProperties, margin) {\r\n this.xAxisProperties = x;\r\n this.yAxisProperties = y;\r\n this.margin = margin;\r\n }\r\n\r\n public init(options: CartesianVisualInitOptions) {\r\n this.svg = options.svg;\r\n this.svg.classed(ColumnChart.ColumnChartClassName, true);\r\n\r\n this.unclippedGraphicsContext = this.svg.append('g').classed('columnChartUnclippedGraphicsContext', true);\r\n this.mainGraphicsContext = this.unclippedGraphicsContext.append('svg').classed('columnChartMainGraphicsContext', true);\r\n this.style = options.style;\r\n this.currentViewport = options.viewport;\r\n this.hostService = options.host;\r\n this.interactivity = options.interactivity;\r\n this.colors = this.style.colorPalette.dataColors;\r\n this.cartesianVisualHost = options.cartesianHost;\r\n this.options = options;\r\n this.isComboChart = ComboChart.isComboChart(options.chartType);\r\n this.element = options.element;\r\n }\r\n\r\n private getCategoryLayout(numCategoryValues: number, options: CalculateScaleAndDomainOptions): CategoryLayout {\r\n let availableWidth: number;\r\n if (ColumnChart.isBar(this.chartType)) {\r\n availableWidth = this.currentViewport.height - (this.margin.top + this.margin.bottom);\r\n }\r\n else {\r\n availableWidth = this.currentViewport.width - (this.margin.left + this.margin.right);\r\n }\r\n\r\n let metaDataColumn = this.data ? this.data.categoryMetadata : undefined;\r\n let categoryDataType: ValueTypeDescriptor = AxisHelper.getCategoryValueType(metaDataColumn);\r\n let isScalar = this.data ? this.data.scalarCategoryAxis : false;\r\n let domain = AxisHelper.createDomain(this.data.series, categoryDataType, isScalar, options.forcedXDomain, options.ensureXDomain);\r\n return CartesianChart.getLayout(\r\n this.data,\r\n {\r\n availableWidth: availableWidth,\r\n categoryCount: numCategoryValues,\r\n domain: domain,\r\n isScalar: isScalar,\r\n isScrollable: this.isScrollable,\r\n trimOrdinalDataOnOverflow: options.trimOrdinalDataOnOverflow\r\n });\r\n }\r\n\r\n public static converter(\r\n dataView: DataView,\r\n colors: IDataColorPalette,\r\n is100PercentStacked: boolean = false,\r\n isScalar: boolean = false,\r\n dataViewMetadata: DataViewMetadata = null,\r\n chartType?: ColumnChartType,\r\n interactivityService?: IInteractivityService,\r\n tooltipsEnabled: boolean = true): ColumnChartData {\r\n debug.assertValue(dataView, 'dataView');\r\n debug.assertValue(colors, 'colors');\r\n\r\n let xAxisCardProperties = CartesianHelper.getCategoryAxisProperties(dataViewMetadata);\r\n let valueAxisProperties = CartesianHelper.getValueAxisProperties(dataViewMetadata);\r\n isScalar = CartesianHelper.isScalar(isScalar, xAxisCardProperties);\r\n let dataViewCat = ColumnUtil.applyUserMinMax(isScalar, dataView.categorical, xAxisCardProperties);\r\n\r\n let converterStrategy = new ColumnChartConverterHelper(dataView);\r\n\r\n let categoryInfo = converterHelper.getPivotedCategories(dataViewCat, columnChartProps.general.formatString);\r\n let categories = categoryInfo.categories,\r\n categoryFormatter: IValueFormatter = categoryInfo.categoryFormatter,\r\n categoryIdentities: DataViewScopeIdentity[] = categoryInfo.categoryIdentities,\r\n categoryMetadata: DataViewMetadataColumn = dataViewCat && dataViewCat.categories && dataViewCat.categories.length > 0 ? dataViewCat.categories[0].source : undefined;\r\n\r\n let labelSettings: VisualDataLabelsSettings = dataLabelUtils.getDefaultColumnLabelSettings(is100PercentStacked || ColumnChart.isStacked(chartType));\r\n let defaultLegendLabelColor = LegendData.DefaultLegendLabelFillColor;\r\n let defaultDataPointColor = undefined;\r\n let showAllDataPoints = undefined;\r\n if (dataViewMetadata && dataViewMetadata.objects) {\r\n let objects = dataViewMetadata.objects;\r\n\r\n defaultDataPointColor = DataViewObjects.getFillColor(objects, columnChartProps.dataPoint.defaultColor);\r\n showAllDataPoints = DataViewObjects.getValue<boolean>(objects, columnChartProps.dataPoint.showAllDataPoints);\r\n defaultLegendLabelColor = DataViewObjects.getFillColor(objects, columnChartProps.legend.labelColor, LegendData.DefaultLegendLabelFillColor);\r\n\r\n let labelsObj = <DataLabelObject>objects['labels'];\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, labelSettings);\r\n }\r\n\r\n // Allocate colors\r\n let legendAndSeriesInfo = converterStrategy.getLegend(colors, defaultLegendLabelColor, defaultDataPointColor);\r\n let legend: LegendDataPoint[] = legendAndSeriesInfo.legend.dataPoints;\r\n let seriesSources: DataViewMetadataColumn[] = legendAndSeriesInfo.seriesSources;\r\n\r\n // Determine data points\r\n let result = ColumnChart.createDataPoints(\r\n dataView,\r\n categories,\r\n categoryIdentities,\r\n legend,\r\n legendAndSeriesInfo.seriesObjects,\r\n converterStrategy,\r\n labelSettings,\r\n is100PercentStacked,\r\n isScalar,\r\n converterHelper.categoryIsAlsoSeriesRole(dataView, RoleNames.series, RoleNames.category),\r\n categoryInfo.categoryObjects,\r\n defaultDataPointColor,\r\n chartType,\r\n categoryMetadata,\r\n tooltipsEnabled);\r\n let columnSeries: ColumnChartSeries[] = result.series;\r\n\r\n let valuesMetadata: DataViewMetadataColumn[] = [];\r\n for (let j = 0, jlen = legend.length; j < jlen; j++) {\r\n valuesMetadata.push(seriesSources[j]);\r\n }\r\n\r\n let labels = converterHelper.createAxesLabels(xAxisCardProperties, valueAxisProperties, categoryMetadata, valuesMetadata);\r\n\r\n if (!ColumnChart.isColumn(chartType)) {\r\n // Replace between x and y axes\r\n let temp = labels.xAxisLabel;\r\n labels.xAxisLabel = labels.yAxisLabel;\r\n labels.yAxisLabel = temp;\r\n }\r\n\r\n if (interactivityService) {\r\n for (let series of columnSeries) {\r\n interactivityService.applySelectionStateToData(series.data);\r\n }\r\n\r\n interactivityService.applySelectionStateToData(legendAndSeriesInfo.legend.dataPoints);\r\n }\r\n\r\n return {\r\n categories: categories,\r\n categoryFormatter: categoryFormatter,\r\n series: columnSeries,\r\n valuesMetadata: valuesMetadata,\r\n legendData: legendAndSeriesInfo.legend,\r\n hasHighlights: result.hasHighlights,\r\n categoryMetadata: categoryMetadata,\r\n scalarCategoryAxis: isScalar,\r\n labelSettings: labelSettings,\r\n axesLabels: { x: labels.xAxisLabel, y: labels.yAxisLabel },\r\n hasDynamicSeries: result.hasDynamicSeries,\r\n isMultiMeasure: result.isMultiMeasure,\r\n defaultDataPointColor: defaultDataPointColor,\r\n showAllDataPoints: showAllDataPoints,\r\n };\r\n }\r\n\r\n private static canSupportOverflow(chartType: ColumnChartType, seriesCount: number): boolean {\r\n return !ColumnChart.isStacked(chartType) || seriesCount === 1;\r\n }\r\n\r\n private static createDataPoints(\r\n dataView: DataView,\r\n categories: any[],\r\n categoryIdentities: DataViewScopeIdentity[],\r\n legend: LegendDataPoint[],\r\n seriesObjectsList: DataViewObjects[][],\r\n converterStrategy: ColumnChartConverterHelper,\r\n defaultLabelSettings: VisualDataLabelsSettings,\r\n is100PercentStacked: boolean = false,\r\n isScalar: boolean = false,\r\n isCategoryAlsoSeries?: boolean,\r\n categoryObjectsList?: DataViewObjects[],\r\n defaultDataPointColor?: string,\r\n chartType?: ColumnChartType,\r\n categoryMetadata?: DataViewMetadataColumn,\r\n tooltipsEnabled?: boolean): { series: ColumnChartSeries[]; hasHighlights: boolean; hasDynamicSeries: boolean; isMultiMeasure: boolean } {\r\n let dataViewCat = dataView.categorical;\r\n\r\n let grouped = dataViewCat && dataViewCat.values ? dataViewCat.values.grouped() : undefined;\r\n let categoryCount = categories.length;\r\n let seriesCount = legend.length;\r\n let columnSeries: ColumnChartSeries[] = [];\r\n\r\n if (seriesCount < 1 || categoryCount < 1)\r\n return { series: columnSeries, hasHighlights: false, hasDynamicSeries: false, isMultiMeasure: false };\r\n\r\n let dvCategories = dataViewCat.categories;\r\n categoryMetadata = !_.isEmpty(dvCategories) ? dvCategories[0].source : null;\r\n let categoryType = AxisHelper.getCategoryValueType(categoryMetadata);\r\n let isDateTime = AxisHelper.isDateTime(categoryType);\r\n let baseValuesPos = [], baseValuesNeg = [];\r\n\r\n let rawValues: number[][] = [];\r\n let rawHighlightValues: number[][] = [];\r\n\r\n let hasDynamicSeries = !!(dataViewCat.values && dataViewCat.values.source);\r\n let isMultiMeasure = !hasDynamicSeries && seriesCount > 1;\r\n\r\n let highlightsOverflow = false; // Overflow means the highlight larger than value or the signs being different\r\n let hasHighlights = converterStrategy.hasHighlightValues(0);\r\n for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\r\n let seriesValues = [];\r\n let seriesHighlightValues = [];\r\n for (let categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {\r\n let value = converterStrategy.getValueBySeriesAndCategory(seriesIndex, categoryIndex);\r\n seriesValues[categoryIndex] = value;\r\n if (hasHighlights) {\r\n let highlightValue = converterStrategy.getHighlightBySeriesAndCategory(seriesIndex, categoryIndex);\r\n seriesHighlightValues[categoryIndex] = highlightValue;\r\n // There are two cases where we don't use overflow logic; if all are false, use overflow logic appropriate for the chart.\r\n if (!((value >= 0 && highlightValue >= 0 && value >= highlightValue) || // Both positive; value greater than highlight\r\n (value <= 0 && highlightValue <= 0 && value <= highlightValue))) { // Both negative; value less than highlight\r\n highlightsOverflow = true;\r\n }\r\n }\r\n }\r\n rawValues.push(seriesValues);\r\n if (hasHighlights) {\r\n rawHighlightValues.push(seriesHighlightValues);\r\n }\r\n }\r\n\r\n if (highlightsOverflow && !ColumnChart.canSupportOverflow(chartType, seriesCount)) {\r\n highlightsOverflow = false;\r\n hasHighlights = false;\r\n rawValues = rawHighlightValues;\r\n }\r\n\r\n let dataPointObjects: DataViewObjects[] = categoryObjectsList,\r\n formatStringProp = columnChartProps.general.formatString;\r\n for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\r\n let seriesDataPoints: ColumnChartDataPoint[] = [],\r\n legendItem = legend[seriesIndex],\r\n seriesLabelSettings: VisualDataLabelsSettings;\r\n\r\n if (!hasDynamicSeries) {\r\n let labelsSeriesGroup = !_.isEmpty(grouped) && grouped[0].values ? grouped[0].values[seriesIndex] : null;\r\n let labelObjects = (labelsSeriesGroup && labelsSeriesGroup.source && labelsSeriesGroup.source.objects) ? <DataLabelObject>labelsSeriesGroup.source.objects['labels'] : null;\r\n if (labelObjects) {\r\n seriesLabelSettings = Prototype.inherit(defaultLabelSettings);\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(labelObjects, seriesLabelSettings);\r\n }\r\n }\r\n\r\n columnSeries.push({\r\n displayName: legendItem.label,\r\n key: 'series' + seriesIndex,\r\n index: seriesIndex,\r\n data: seriesDataPoints,\r\n identity: legendItem.identity,\r\n color: legendItem.color,\r\n labelSettings: seriesLabelSettings,\r\n });\r\n\r\n if (seriesCount > 1)\r\n dataPointObjects = seriesObjectsList[seriesIndex];\r\n let valueColumnMetadata = dataViewCat.values[seriesIndex].source;\r\n let gradientMeasureIndex: number = GradientUtils.getGradientMeasureIndex(dataViewCat);\r\n let gradientValueColumn: DataViewValueColumn = GradientUtils.getGradientValueColumn(dataViewCat);\r\n let valueMeasureIndex: number = DataRoleHelper.getMeasureIndexOfRole(grouped, \"Y\");\r\n let pctFormatString = valueFormatter.getLocalizedString('Percentage');\r\n\r\n for (let categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {\r\n if (seriesIndex === 0) {\r\n baseValuesPos.push(0);\r\n baseValuesNeg.push(0);\r\n }\r\n\r\n let value = AxisHelper.normalizeNonFiniteNumber(rawValues[seriesIndex][categoryIndex]);\r\n if (value == null) {\r\n // Optimization: Ignore null dataPoints from the fabricated category/series combination in the self cross-join.\r\n // However, we must retain the first series because it is used to compute things like axis scales, and value lookups.\r\n if (seriesIndex > 0)\r\n continue;\r\n }\r\n\r\n let originalValue: number = value;\r\n let categoryValue = categories[categoryIndex];\r\n\r\n // ignore variant measures\r\n if (isDateTime && categoryValue != null && !(categoryValue instanceof Date))\r\n continue;\r\n\r\n if (isDateTime && categoryValue)\r\n categoryValue = categoryValue.getTime();\r\n if (isScalar && (categoryValue == null || isNaN(categoryValue)))\r\n continue;\r\n\r\n let multipliers: ValueMultiplers;\r\n if (is100PercentStacked)\r\n multipliers = StackedUtil.getStackedMultiplier(dataViewCat, categoryIndex, seriesCount, categoryCount, converterStrategy);\r\n\r\n let unadjustedValue = value,\r\n isNegative = value < 0;\r\n\r\n if (multipliers) {\r\n if (isNegative)\r\n value *= multipliers.neg;\r\n else\r\n value *= multipliers.pos;\r\n }\r\n\r\n let valueAbsolute = Math.abs(value);\r\n let position: number;\r\n if (isNegative) {\r\n position = baseValuesNeg[categoryIndex];\r\n\r\n if (!isNaN(valueAbsolute))\r\n baseValuesNeg[categoryIndex] -= valueAbsolute;\r\n }\r\n else {\r\n if (!isNaN(valueAbsolute))\r\n baseValuesPos[categoryIndex] += valueAbsolute;\r\n\r\n position = baseValuesPos[categoryIndex];\r\n }\r\n\r\n let seriesGroup = grouped && grouped.length > seriesIndex && grouped[seriesIndex].values ? grouped[seriesIndex].values[valueMeasureIndex] : null;\r\n let category = !_.isEmpty(dataViewCat.categories) ? dataViewCat.categories[0] : null;\r\n let identity = SelectionIdBuilder.builder()\r\n .withCategory(category, categoryIndex)\r\n .withSeries(dataViewCat.values, seriesGroup)\r\n .withMeasure(converterStrategy.getMeasureNameByIndex(seriesIndex))\r\n .createSelectionId();\r\n\r\n let rawCategoryValue = categories[categoryIndex];\r\n let color = ColumnChart.getDataPointColor(legendItem, categoryIndex, dataPointObjects);\r\n let gradientColumnForTooltip = gradientMeasureIndex === 0 ? null : gradientValueColumn;\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n if (category) {\r\n tooltipInfo.push({\r\n displayName: category.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(rawCategoryValue, category.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (hasDynamicSeries) {\r\n if (!category || category.source !== dataViewCat.values.source) {\r\n // Category/series on the same column -- don't repeat its value in the tooltip.\r\n tooltipInfo.push({\r\n displayName: dataViewCat.values.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(grouped[seriesIndex].name, dataViewCat.values.source, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n if (originalValue != null) {\r\n let valueString: string;\r\n let formattedOriginalValue = converterHelper.formatFromMetadataColumn(originalValue, valueColumnMetadata, formatStringProp);\r\n if (is100PercentStacked) {\r\n let originalPct: string = valueFormatter.format(valueAbsolute, pctFormatString);\r\n valueString = formattedOriginalValue + ' (' + originalPct + ')';\r\n }\r\n else {\r\n valueString = formattedOriginalValue;\r\n }\r\n tooltipInfo.push({\r\n displayName: valueColumnMetadata.displayName,\r\n value: valueString,\r\n });\r\n }\r\n\r\n if (gradientColumnForTooltip && gradientColumnForTooltip.values[categoryIndex] != null) {\r\n tooltipInfo.push({\r\n displayName: gradientColumnForTooltip.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(gradientColumnForTooltip.values[categoryIndex], gradientColumnForTooltip.source, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n let series = columnSeries[seriesIndex];\r\n let dataPointLabelSettings = (series.labelSettings) ? series.labelSettings : defaultLabelSettings;\r\n let labelColor = dataPointLabelSettings.labelColor;\r\n let lastValue = undefined;\r\n //Stacked column/bar label color is white by default (except last series)\r\n if ((ColumnChart.isStacked(chartType))) {\r\n lastValue = this.getStackedLabelColor(isNegative, seriesIndex, seriesCount, categoryIndex, rawValues);\r\n labelColor = (lastValue || (seriesIndex === seriesCount - 1 && !isNegative)) ? labelColor : dataLabelUtils.defaultInsideLabelColor;\r\n }\r\n\r\n let dataPoint: ColumnChartDataPoint = {\r\n categoryValue: categoryValue,\r\n value: value,\r\n position: position,\r\n valueAbsolute: valueAbsolute,\r\n valueOriginal: unadjustedValue,\r\n seriesIndex: seriesIndex,\r\n labelSettings: dataPointLabelSettings,\r\n categoryIndex: categoryIndex,\r\n color: color,\r\n selected: false,\r\n originalValue: value,\r\n originalPosition: position,\r\n originalValueAbsolute: valueAbsolute,\r\n identity: identity,\r\n key: identity.getKey(),\r\n tooltipInfo: tooltipInfo,\r\n labelFill: labelColor,\r\n labelFormatString: valueColumnMetadata.format,\r\n lastSeries: lastValue,\r\n chartType: chartType\r\n };\r\n\r\n seriesDataPoints.push(dataPoint);\r\n\r\n if (hasHighlights) {\r\n let valueHighlight = rawHighlightValues[seriesIndex][categoryIndex];\r\n let unadjustedValueHighlight = valueHighlight;\r\n\r\n let highlightedTooltip: boolean = true;\r\n if (valueHighlight === null) {\r\n valueHighlight = 0;\r\n highlightedTooltip = false;\r\n }\r\n\r\n if (is100PercentStacked) {\r\n valueHighlight *= multipliers.pos;\r\n }\r\n let absoluteValueHighlight = Math.abs(valueHighlight);\r\n let highlightPosition = position;\r\n\r\n if (valueHighlight > 0) {\r\n highlightPosition -= valueAbsolute - absoluteValueHighlight;\r\n }\r\n else if (valueHighlight === 0 && value > 0) {\r\n highlightPosition -= valueAbsolute;\r\n }\r\n\r\n let highlightIdentity = SelectionId.createWithHighlight(identity);\r\n\r\n let highlightedValueAndPct: string;\r\n let highlightedValueFormat: string;\r\n if (highlightedTooltip && unadjustedValueHighlight != null && valueHighlight != null) {\r\n let highlightedPct: string = valueFormatter.format(valueHighlight, pctFormatString);\r\n highlightedValueFormat = converterHelper.formatFromMetadataColumn(unadjustedValueHighlight, valueColumnMetadata, formatStringProp);\r\n highlightedValueAndPct = highlightedValueFormat + ' (' + highlightedPct + ')';\r\n }\r\n\r\n if (tooltipsEnabled) {\r\n let highlightValue: string;\r\n if (is100PercentStacked) {\r\n highlightValue = highlightedValueAndPct;\r\n }\r\n else {\r\n highlightValue = highlightedValueFormat;\r\n }\r\n if (highlightValue != null) {\r\n tooltipInfo.push({\r\n displayName: ToolTipComponent.localizationOptions.highlightedValueDisplayName,\r\n value: highlightValue,\r\n });\r\n }\r\n }\r\n\r\n if (highlightedTooltip) {\r\n // Override non highlighted data point\r\n dataPoint.tooltipInfo = tooltipInfo;\r\n }\r\n\r\n let highlightDataPoint: ColumnChartDataPoint = {\r\n categoryValue: categoryValue,\r\n value: valueHighlight,\r\n position: highlightPosition,\r\n valueAbsolute: absoluteValueHighlight,\r\n valueOriginal: unadjustedValueHighlight,\r\n seriesIndex: seriesIndex,\r\n labelSettings: dataPointLabelSettings,\r\n categoryIndex: categoryIndex,\r\n color: color,\r\n selected: false,\r\n highlight: true,\r\n originalValue: value,\r\n originalPosition: position,\r\n originalValueAbsolute: valueAbsolute,\r\n drawThinner: highlightsOverflow,\r\n identity: highlightIdentity,\r\n key: highlightIdentity.getKey(),\r\n tooltipInfo: tooltipInfo,\r\n labelFormatString: valueColumnMetadata.format,\r\n labelFill: labelColor,\r\n lastSeries: lastValue,\r\n chartType: chartType\r\n };\r\n\r\n seriesDataPoints.push(highlightDataPoint);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n series: columnSeries,\r\n hasHighlights: hasHighlights,\r\n hasDynamicSeries: hasDynamicSeries,\r\n isMultiMeasure: isMultiMeasure,\r\n };\r\n }\r\n\r\n private static getDataPointColor(\r\n legendItem: LegendDataPoint,\r\n categoryIndex: number,\r\n dataPointObjects?: DataViewObjects[]): string {\r\n debug.assertValue(legendItem, 'legendItem');\r\n debug.assertValue(categoryIndex, 'categoryIndex');\r\n debug.assertAnyValue(dataPointObjects, 'dataPointObjects');\r\n\r\n if (dataPointObjects) {\r\n let colorOverride = DataViewObjects.getFillColor(dataPointObjects[categoryIndex], columnChartProps.dataPoint.fill);\r\n if (colorOverride)\r\n return colorOverride;\r\n }\r\n\r\n return legendItem.color;\r\n }\r\n\r\n private static getStackedLabelColor(isNegative: boolean, seriesIndex: number, seriesCount: number, categoryIndex: number, rawValues: number[][]): boolean {\r\n let lastValue = !(isNegative && seriesIndex === seriesCount - 1 && seriesCount !== 1);\r\n //run for the next series and check if current series is last\r\n for (let i = seriesIndex + 1; i < seriesCount; i++) {\r\n let nextValues = AxisHelper.normalizeNonFiniteNumber(rawValues[i][categoryIndex]);\r\n if ((nextValues !== null) && (((!isNegative || (isNegative && seriesIndex === 0)) && nextValues > 0) || (isNegative && seriesIndex !== 0))) {\r\n lastValue = false;\r\n break;\r\n }\r\n }\r\n return lastValue;\r\n }\r\n\r\n public static sliceSeries(series: ColumnChartSeries[], endIndex: number, startIndex: number = 0): ColumnChartSeries[] {\r\n let newSeries: ColumnChartSeries[] = [];\r\n if (series && series.length > 0) {\r\n for (let i = 0, len = series.length; i < len; i++) {\r\n let iNewSeries = newSeries[i] = Prototype.inherit(series[i]);\r\n // TODO: [investigate] possible perf improvement.\r\n // if data[n].categoryIndex > endIndex implies data[n+1].categoryIndex > endIndex\r\n // then we could short circuit the filter loop.\r\n iNewSeries.data = series[i].data.filter(d => d.categoryIndex >= startIndex && d.categoryIndex < endIndex);\r\n }\r\n }\r\n return newSeries;\r\n }\r\n\r\n public static getInteractiveColumnChartDomElement(element: JQuery): HTMLElement {\r\n return element.children(\"svg\").get(0);\r\n }\r\n\r\n public setData(dataViews: DataView[]): void {\r\n debug.assertValue(dataViews, \"dataViews\");\r\n let is100PctStacked = ColumnChart.isStacked100(this.chartType);\r\n this.data = {\r\n categories: [],\r\n categoryFormatter: null,\r\n series: [],\r\n valuesMetadata: [],\r\n legendData: null,\r\n hasHighlights: false,\r\n categoryMetadata: null,\r\n scalarCategoryAxis: false,\r\n labelSettings: dataLabelUtils.getDefaultColumnLabelSettings(is100PctStacked || ColumnChart.isStacked(this.chartType)),\r\n axesLabels: { x: null, y: null },\r\n hasDynamicSeries: false,\r\n defaultDataPointColor: null,\r\n isMultiMeasure: false,\r\n };\r\n\r\n if (dataViews.length > 0) {\r\n let dataView = this.dataView = dataViews[0];\r\n\r\n if (dataView && dataView.categorical) {\r\n let dvCategories = dataView.categorical.categories;\r\n let categoryMetadata = (dvCategories && dvCategories.length > 0)\r\n ? dvCategories[0].source\r\n : null;\r\n let categoryType = AxisHelper.getCategoryValueType(categoryMetadata);\r\n\r\n this.data = ColumnChart.converter(\r\n dataView,\r\n this.cartesianVisualHost.getSharedColors(),\r\n is100PctStacked,\r\n CartesianChart.getIsScalar(dataView.metadata ? dataView.metadata.objects : null, columnChartProps.categoryAxis.axisType, categoryType),\r\n dataView.metadata,\r\n this.chartType,\r\n this.interactivityService,\r\n this.tooltipsEnabled);\r\n }\r\n }\r\n\r\n this.setChartStrategy();\r\n }\r\n\r\n private setChartStrategy(): void {\r\n switch (this.chartType) {\r\n case ColumnChartType.clusteredBar:\r\n this.columnChart = new ClusteredBarChartStrategy();\r\n break;\r\n case ColumnChartType.clusteredColumn:\r\n this.columnChart = new ClusteredColumnChartStrategy();\r\n break;\r\n case ColumnChartType.stackedBar:\r\n case ColumnChartType.hundredPercentStackedBar:\r\n this.columnChart = new StackedBarChartStrategy();\r\n break;\r\n case ColumnChartType.stackedColumn:\r\n case ColumnChartType.hundredPercentStackedColumn:\r\n default:\r\n this.columnChart = new StackedColumnChartStrategy();\r\n break;\r\n }\r\n\r\n // For single series, render stacked as a clustered\r\n if (ColumnChart.isStacked(this.chartType) && this.data.series.length === 1) {\r\n switch (this.chartType) {\r\n case (ColumnChartType.stackedBar):\r\n this.columnChart = new ClusteredBarChartStrategy();\r\n break;\r\n case (ColumnChartType.stackedColumn):\r\n this.columnChart = new ClusteredColumnChartStrategy();\r\n break;\r\n }\r\n }\r\n }\r\n\r\n public calculateLegend(): LegendData {\r\n // if we're in interactive mode, return the interactive legend\r\n if (this.interactivity && this.interactivity.isInteractiveLegend) {\r\n return this.createInteractiveLegendDataPoints(0);\r\n }\r\n let legendData = this.data ? this.data.legendData : null;\r\n let legendDataPoints = legendData ? legendData.dataPoints : [];\r\n\r\n if (_.isEmpty(legendDataPoints))\r\n return null;\r\n\r\n return legendData;\r\n }\r\n\r\n public hasLegend(): boolean {\r\n return this.data && (this.data.hasDynamicSeries || (this.data.series && this.data.series.length > 1));\r\n }\r\n\r\n public enumerateObjectInstances(enumeration: ObjectEnumerationBuilder, options: EnumerateVisualObjectInstancesOptions): void {\r\n switch (options.objectName) {\r\n case 'dataPoint':\r\n if (this.dataView && !GradientUtils.hasGradientRole(this.dataView.categorical))\r\n this.enumerateDataPoints(enumeration);\r\n break;\r\n case 'labels':\r\n this.enumerateDataLabels(enumeration);\r\n break;\r\n }\r\n }\r\n\r\n private enumerateDataLabels(enumeration: ObjectEnumerationBuilder): void {\r\n let data = this.data,\r\n labelSettings = this.data.labelSettings,\r\n seriesCount = data.series.length,\r\n showLabelPerSeries = !data.hasDynamicSeries && (seriesCount > 1 || !data.categoryMetadata);\r\n\r\n //Draw default settings\r\n dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings, null, showLabelPerSeries));\r\n\r\n if (seriesCount === 0)\r\n return;\r\n\r\n //Draw series settings\r\n if (showLabelPerSeries && labelSettings.showLabelPerSeries) {\r\n for (let i = 0; i < seriesCount; i++) {\r\n let series = data.series[i],\r\n labelSettings: VisualDataLabelsSettings = (series.labelSettings) ? series.labelSettings : this.data.labelSettings;\r\n\r\n enumeration.pushContainer({ displayName: series.displayName });\r\n dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings, series));\r\n enumeration.popContainer();\r\n }\r\n }\r\n }\r\n\r\n private getLabelSettingsOptions(enumeration: ObjectEnumerationBuilder, labelSettings: VisualDataLabelsSettings, series?: ColumnChartSeries, showAll?: boolean): VisualDataLabelsSettingsOptions {\r\n return {\r\n enumeration: enumeration,\r\n dataLabelsSettings: labelSettings,\r\n show: true,\r\n displayUnits: !ColumnChart.isStacked100(this.chartType),\r\n precision: true,\r\n selector: series && series.identity ? series.identity.getSelector() : null,\r\n showAll: showAll,\r\n fontSize: true,\r\n };\r\n }\r\n\r\n private enumerateDataPoints(enumeration: ObjectEnumerationBuilder): void {\r\n let data = this.data;\r\n if (!data)\r\n return;\r\n\r\n let seriesCount = data.series.length;\r\n\r\n if (seriesCount === 0)\r\n return;\r\n\r\n if (data.hasDynamicSeries || seriesCount > 1 || !data.categoryMetadata) {\r\n for (let i = 0; i < seriesCount; i++) {\r\n let series = data.series[i];\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: series.displayName,\r\n selector: ColorHelper.normalizeSelector(series.identity.getSelector()),\r\n properties: {\r\n fill: { solid: { color: series.color } }\r\n },\r\n });\r\n }\r\n }\r\n else {\r\n // For single-category, single-measure column charts, the user can color the individual bars.\r\n let singleSeriesData = data.series[0].data;\r\n let categoryFormatter = data.categoryFormatter;\r\n\r\n // Add default color and show all slices\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n selector: null,\r\n properties: {\r\n defaultColor: { solid: { color: data.defaultDataPointColor || this.colors.getColorByIndex(0).value } }\r\n }\r\n }).pushInstance({\r\n objectName: 'dataPoint',\r\n selector: null,\r\n properties: {\r\n showAllDataPoints: !!data.showAllDataPoints\r\n }\r\n });\r\n \r\n if (data.showAllDataPoints) {\r\n for (let i = 0; i < singleSeriesData.length; i++) {\r\n let singleSeriesDataPoints = singleSeriesData[i],\r\n categoryValue: any = data.categories[i];\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: categoryFormatter ? categoryFormatter.format(categoryValue) : categoryValue,\r\n selector: ColorHelper.normalizeSelector(singleSeriesDataPoints.identity.getSelector(), /*isSingleSeries*/true),\r\n properties: {\r\n fill: { solid: { color: singleSeriesDataPoints.color } }\r\n },\r\n });\r\n }\r\n } \r\n }\r\n }\r\n\r\n public calculateAxesProperties(options: CalculateScaleAndDomainOptions): IAxisProperties[] {\r\n let data = this.data;\r\n this.currentViewport = options.viewport;\r\n let margin = this.margin = options.margin;\r\n\r\n let origCatgSize = (data && data.categories) ? data.categories.length : 0;\r\n let chartLayout: CategoryLayout = data ? this.getCategoryLayout(origCatgSize, options) : {\r\n categoryCount: 0,\r\n categoryThickness: CartesianChart.MinOrdinalRectThickness,\r\n outerPaddingRatio: CartesianChart.OuterPaddingRatio,\r\n isScalar: false\r\n };\r\n this.categoryAxisType = chartLayout.isScalar ? axisType.scalar : null;\r\n\r\n if (data && !chartLayout.isScalar && !this.isScrollable && options.trimOrdinalDataOnOverflow) {\r\n // trim data that doesn't fit on dashboard\r\n let catgSize = Math.min(origCatgSize, chartLayout.categoryCount);\r\n if (catgSize !== origCatgSize) {\r\n data = Prototype.inherit(data);\r\n data.series = ColumnChart.sliceSeries(data.series, catgSize);\r\n data.categories = data.categories.slice(0, catgSize);\r\n }\r\n }\r\n this.columnChart.setData(data);\r\n\r\n let preferredPlotArea = this.getPreferredPlotArea(chartLayout.isScalar, chartLayout.categoryCount, chartLayout.categoryThickness);\r\n let is100Pct = ColumnChart.isStacked100(this.chartType);\r\n\r\n let chartContext: ColumnChartContext = {\r\n height: preferredPlotArea.height,\r\n width: preferredPlotArea.width,\r\n duration: 0,\r\n hostService: this.hostService,\r\n unclippedGraphicsContext: this.unclippedGraphicsContext,\r\n mainGraphicsContext: this.mainGraphicsContext,\r\n margin: this.margin,\r\n layout: chartLayout,\r\n animator: this.animator,\r\n interactivityService: this.interactivityService,\r\n viewportHeight: this.currentViewport.height - (margin.top + margin.bottom),\r\n viewportWidth: this.currentViewport.width - (margin.left + margin.right),\r\n is100Pct: is100Pct,\r\n isComboChart: this.isComboChart,\r\n };\r\n this.ApplyInteractivity(chartContext);\r\n this.columnChart.setupVisualProps(chartContext);\r\n\r\n let ensureXDomain: NumberRange;\r\n let ensureYDomain: NumberRange;\r\n\r\n let isBarChart = ColumnChart.isBar(this.chartType);\r\n\r\n if (isBarChart) {\r\n let temp = options.forcedXDomain;\r\n options.forcedXDomain = options.forcedYDomain;\r\n options.forcedYDomain = temp;\r\n\r\n // In the case of clustered and stacked bar charts, the y1 reference line is a vertical line\r\n ensureXDomain = options.ensureYDomain;\r\n }\r\n else {\r\n ensureYDomain = options.ensureYDomain;\r\n }\r\n\r\n this.xAxisProperties = this.columnChart.setXScale(\r\n is100Pct,\r\n options.forcedTickCount,\r\n options.forcedXDomain,\r\n isBarChart ? options.valueAxisScaleType : options.categoryAxisScaleType,\r\n isBarChart ? options.valueAxisDisplayUnits : options.categoryAxisDisplayUnits,\r\n isBarChart ? options.valueAxisPrecision : options.categoryAxisPrecision,\r\n ensureXDomain);\r\n\r\n this.yAxisProperties = this.columnChart.setYScale(\r\n is100Pct,\r\n options.forcedTickCount,\r\n options.forcedYDomain,\r\n isBarChart ? options.categoryAxisScaleType : options.valueAxisScaleType,\r\n isBarChart ? options.categoryAxisDisplayUnits : options.valueAxisDisplayUnits,\r\n isBarChart ? options.categoryAxisPrecision : options.valueAxisPrecision,\r\n ensureYDomain);\r\n\r\n if (options.showCategoryAxisLabel && this.xAxisProperties.isCategoryAxis || options.showValueAxisLabel && !this.xAxisProperties.isCategoryAxis) {\r\n this.xAxisProperties.axisLabel = data.axesLabels.x;\r\n }\r\n else {\r\n this.xAxisProperties.axisLabel = null;\r\n }\r\n if (options.showValueAxisLabel && !this.yAxisProperties.isCategoryAxis || options.showCategoryAxisLabel && this.yAxisProperties.isCategoryAxis) {\r\n this.yAxisProperties.axisLabel = data.axesLabels.y;\r\n }\r\n else {\r\n this.yAxisProperties.axisLabel = null;\r\n }\r\n\r\n return [this.xAxisProperties, this.yAxisProperties];\r\n }\r\n\r\n public getPreferredPlotArea(isScalar: boolean, categoryCount: number, categoryThickness: number): IViewport {\r\n let plotArea: IViewport = {\r\n height: this.currentViewport.height - this.margin.top - this.margin.bottom,\r\n width: this.currentViewport.width - this.margin.left - this.margin.right\r\n };\r\n\r\n if (this.isScrollable && !isScalar) {\r\n let preferredCategorySpan = CartesianChart.getPreferredCategorySpan(categoryCount, categoryThickness);\r\n if (ColumnChart.isBar(this.chartType)) {\r\n plotArea.height = Math.max(preferredCategorySpan, plotArea.height);\r\n }\r\n else\r\n plotArea.width = Math.max(preferredCategorySpan, plotArea.width);\r\n }\r\n return plotArea;\r\n }\r\n\r\n private ApplyInteractivity(chartContext: ColumnChartContext): void {\r\n let interactivity = this.interactivity;\r\n if (interactivity) {\r\n if (interactivity.dragDataPoint) {\r\n chartContext.onDragStart = (datum: ColumnChartDataPoint) => {\r\n if (!datum.identity)\r\n return;\r\n\r\n this.hostService.onDragStart({\r\n event: <any>d3.event,\r\n data: {\r\n data: datum.identity.getSelector()\r\n }\r\n });\r\n };\r\n }\r\n\r\n if (interactivity.isInteractiveLegend) {\r\n let dragMove = () => {\r\n let mousePoint = d3.mouse(this.mainGraphicsContext[0][0]); // get the x and y for the column area itself\r\n let x: number = mousePoint[0];\r\n let y: number = mousePoint[1];\r\n let index: number = this.columnChart.getClosestColumnIndex(x, y);\r\n this.selectColumn(index);\r\n };\r\n\r\n let ColumnChartSvg: EventTarget = ColumnChart.getInteractiveColumnChartDomElement(this.element);\r\n\r\n //set click interaction on the visual\r\n this.svg.on('click', dragMove);\r\n //set click interaction on the background\r\n d3.select(ColumnChartSvg)\r\n .on('click', dragMove)\r\n .style('touch-action', 'none');\r\n let drag = d3.behavior.drag()\r\n .origin(Object)\r\n .on(\"drag\", dragMove);\r\n //set drag interaction on the visual\r\n this.svg.call(drag);\r\n //set drag interaction on the background\r\n d3.select(ColumnChartSvg).call(drag);\r\n }\r\n }\r\n }\r\n\r\n private selectColumn(indexOfColumnSelected: number, force: boolean = false): void {\r\n if (!force && this.lastInteractiveSelectedColumnIndex === indexOfColumnSelected) return; // same column, nothing to do here\r\n\r\n let legendData: LegendData = this.createInteractiveLegendDataPoints(indexOfColumnSelected);\r\n let legendDataPoints: LegendDataPoint[] = legendData.dataPoints;\r\n this.cartesianVisualHost.updateLegend(legendData);\r\n if (legendDataPoints.length > 0) {\r\n this.columnChart.selectColumn(indexOfColumnSelected, this.lastInteractiveSelectedColumnIndex);\r\n }\r\n this.lastInteractiveSelectedColumnIndex = indexOfColumnSelected;\r\n }\r\n\r\n private createInteractiveLegendDataPoints(columnIndex: number): LegendData {\r\n let data = this.data;\r\n if (!data || _.isEmpty(data.series))\r\n return { dataPoints: [] };\r\n\r\n let formatStringProp = columnChartProps.general.formatString;\r\n let legendDataPoints: LegendDataPoint[] = [];\r\n let category = data.categories && data.categories[columnIndex];\r\n let allSeries = data.series;\r\n let dataPoints = data.legendData && data.legendData.dataPoints;\r\n let converterStrategy = new ColumnChartConverterHelper(this.dataView);\r\n\r\n for (let i = 0, len = allSeries.length; i < len; i++) {\r\n let measure = converterStrategy.getValueBySeriesAndCategory(i, columnIndex);\r\n let valueMetadata = data.valuesMetadata[i];\r\n let formattedLabel = converterHelper.getFormattedLegendLabel(valueMetadata, this.dataView.categorical.values, formatStringProp);\r\n let dataPointColor: string;\r\n if (allSeries.length === 1) {\r\n let series = allSeries[0];\r\n dataPointColor = series.data.length > columnIndex && series.data[columnIndex].color;\r\n } else {\r\n dataPointColor = dataPoints.length > i && dataPoints[i].color;\r\n }\r\n\r\n legendDataPoints.push({\r\n color: dataPointColor,\r\n icon: LegendIcon.Box,\r\n label: formattedLabel,\r\n category: data.categoryFormatter ? data.categoryFormatter.format(category) : category,\r\n measure: valueFormatter.format(measure, valueFormatter.getFormatString(valueMetadata, formatStringProp)),\r\n identity: SelectionId.createNull(),\r\n selected: false\r\n });\r\n }\r\n\r\n return { dataPoints: legendDataPoints };\r\n }\r\n\r\n public overrideXScale(xProperties: IAxisProperties): void {\r\n this.xAxisProperties = xProperties;\r\n }\r\n\r\n public render(suppressAnimations: boolean): CartesianVisualRenderResult {\r\n let columnChartDrawInfo = this.columnChart.drawColumns(!suppressAnimations /* useAnimations */);\r\n let data = this.data;\r\n\r\n let margin = this.margin;\r\n let viewport = this.currentViewport;\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n let width = viewport.width - (margin.left + margin.right);\r\n\r\n this.mainGraphicsContext\r\n .attr('height', height)\r\n .attr('width', width);\r\n\r\n if (this.tooltipsEnabled)\r\n TooltipManager.addTooltip(columnChartDrawInfo.eventGroup, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n\r\n let allDataPoints: ColumnChartDataPoint[] = [];\r\n let behaviorOptions: ColumnBehaviorOptions = undefined;\r\n if (this.interactivityService) {\r\n for (let i = 0, ilen = data.series.length; i < ilen; i++) {\r\n allDataPoints = allDataPoints.concat(data.series[i].data);\r\n }\r\n behaviorOptions = {\r\n datapoints: allDataPoints,\r\n eventGroup: columnChartDrawInfo.eventGroup,\r\n bars: columnChartDrawInfo.shapesSelection,\r\n hasHighlights: data.hasHighlights,\r\n mainGraphicsContext: this.mainGraphicsContext,\r\n viewport: columnChartDrawInfo.viewport,\r\n axisOptions: columnChartDrawInfo.axisOptions,\r\n showLabel: data.labelSettings.show\r\n };\r\n }\r\n\r\n if (this.interactivity && this.interactivity.isInteractiveLegend) {\r\n if (this.data.series.length > 0) {\r\n this.selectColumn(CartesianHelper.findMaxCategoryIndex(this.data.series), true); // start with the last column\r\n }\r\n }\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n return { dataPoints: allDataPoints, behaviorOptions: behaviorOptions, labelDataPoints: columnChartDrawInfo.labelDataPoints, labelsAreNumeric: true };\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService) {\r\n this.interactivityService.clearSelection();\r\n }\r\n }\r\n\r\n public getVisualCategoryAxisIsScalar(): boolean {\r\n return this.data ? this.data.scalarCategoryAxis : false;\r\n }\r\n\r\n public getSupportedCategoryAxisType(): string {\r\n let metaDataColumn = this.data ? this.data.categoryMetadata : undefined;\r\n let valueType = AxisHelper.getCategoryValueType(metaDataColumn);\r\n let isOrdinal = AxisHelper.isOrdinal(valueType);\r\n return isOrdinal ? axisType.categorical : axisType.both;\r\n }\r\n\r\n public setFilteredData(startIndex: number, endIndex: number): CartesianData {\r\n let data = Prototype.inherit(this.data);\r\n data.series = ColumnChart.sliceSeries(data.series, endIndex, startIndex);\r\n data.categories = data.categories.slice(startIndex, endIndex);\r\n this.columnChart.setData(data);\r\n return data;\r\n }\r\n\r\n public static getLabelFill(labelColor: string, isInside: boolean, isCombo: boolean): string {\r\n if (labelColor) {\r\n return labelColor;\r\n }\r\n if (isInside && !isCombo) {\r\n return NewDataLabelUtils.defaultInsideLabelColor;\r\n }\r\n return NewDataLabelUtils.defaultLabelColor;\r\n }\r\n\r\n public supportsTrendLine(): boolean {\r\n let isScalar = this.data ? this.data.scalarCategoryAxis : false;\r\n return this.chartType === ColumnChartType.clusteredColumn && isScalar;\r\n }\r\n\r\n public static isBar(chartType: ColumnChartType): boolean {\r\n return EnumExtensions.hasFlag(chartType, flagBar);\r\n }\r\n\r\n public static isColumn(chartType: ColumnChartType): boolean {\r\n return EnumExtensions.hasFlag(chartType, flagColumn);\r\n }\r\n\r\n public static isClustered(chartType: ColumnChartType): boolean {\r\n return EnumExtensions.hasFlag(chartType, flagClustered);\r\n }\r\n\r\n public static isStacked(chartType: ColumnChartType): boolean {\r\n return EnumExtensions.hasFlag(chartType, flagStacked);\r\n }\r\n\r\n public static isStacked100(chartType: ColumnChartType): boolean {\r\n return EnumExtensions.hasFlag(chartType, flagStacked100);\r\n }\r\n }\r\n\r\n class ColumnChartConverterHelper implements IColumnChartConverterStrategy {\r\n private dataView: DataViewCategorical;\r\n private reader: powerbi.data.IDataViewCategoricalReader;\r\n\r\n constructor(dataView: DataView) {\r\n this.dataView = dataView && dataView.categorical;\r\n this.reader = powerbi.data.createIDataViewCategoricalReader(dataView);\r\n }\r\n\r\n public getLegend(colors: IDataColorPalette, defaultLegendLabelColor: string, defaultColor?: string): LegendSeriesInfo {\r\n let legend: LegendDataPoint[] = [];\r\n let seriesSources: DataViewMetadataColumn[] = [];\r\n let seriesObjects: DataViewObjects[][] = [];\r\n let grouped: boolean = false;\r\n\r\n let colorHelper = new ColorHelper(colors, columnChartProps.dataPoint.fill, defaultColor);\r\n let legendTitle = undefined;\r\n if (this.dataView && this.dataView.values) {\r\n let allValues = this.dataView.values;\r\n let valueGroups = allValues.grouped();\r\n\r\n let hasDynamicSeries = !!(allValues && allValues.source);\r\n\r\n let formatStringProp = columnChartProps.general.formatString;\r\n for (let valueGroupsIndex = 0, valueGroupsLen = valueGroups.length; valueGroupsIndex < valueGroupsLen; valueGroupsIndex++) {\r\n let valueGroup = valueGroups[valueGroupsIndex],\r\n valueGroupObjects = valueGroup.objects,\r\n values = valueGroup.values;\r\n\r\n for (let valueIndex = 0, valuesLen = values.length; valueIndex < valuesLen; valueIndex++) {\r\n let series = values[valueIndex];\r\n let source = series.source;\r\n // Gradient measures do not create series.\r\n if (DataRoleHelper.hasRole(source, 'Gradient') && !DataRoleHelper.hasRole(source, 'Y'))\r\n continue;\r\n\r\n seriesSources.push(source);\r\n seriesObjects.push(series.objects);\r\n\r\n let selectionId = series.identity ?\r\n SelectionId.createWithIdAndMeasure(series.identity, source.queryName) :\r\n SelectionId.createWithMeasure(this.getMeasureNameByIndex(valueIndex));\r\n\r\n let label = converterHelper.getFormattedLegendLabel(source, allValues, formatStringProp);\r\n\r\n let color = hasDynamicSeries\r\n ? colorHelper.getColorForSeriesValue(valueGroupObjects, allValues.identityFields, source.groupName)\r\n : colorHelper.getColorForMeasure(source.objects, source.queryName);\r\n\r\n legend.push({\r\n icon: LegendIcon.Box,\r\n color: color,\r\n label: label,\r\n identity: selectionId,\r\n selected: false,\r\n });\r\n\r\n if (series.identity && source.groupName !== undefined) {\r\n grouped = true;\r\n }\r\n }\r\n }\r\n\r\n let dvValues = this.dataView.values;\r\n legendTitle = dvValues && dvValues.source ? dvValues.source.displayName : \"\";\r\n }\r\n\r\n let legendData: LegendData = {\r\n title: legendTitle,\r\n dataPoints: legend,\r\n grouped: grouped,\r\n labelColor: defaultLegendLabelColor,\r\n };\r\n\r\n return {\r\n legend: legendData,\r\n seriesSources: seriesSources,\r\n seriesObjects: seriesObjects,\r\n };\r\n }\r\n\r\n public getValueBySeriesAndCategory(series: number, category: number): number {\r\n if (this.reader.hasDynamicSeries()) {\r\n // Combo chart dynamic series is broken when line and column have the same measure, so for now,\r\n // work around this by using the grouped directly instead of relying on the reader and roles\r\n let grouped = this.dataView.values.grouped();\r\n return grouped[series].values[0].values[category];\r\n }\r\n return this.reader.getValue('Y', category, series);\r\n }\r\n\r\n public getMeasureNameByIndex(index: number): string {\r\n return this.dataView.values[index].source.queryName;\r\n }\r\n\r\n public hasHighlightValues(series: number): boolean {\r\n let column = this.dataView && this.dataView.values ? this.dataView.values[series] : undefined;\r\n return column && !!column.highlights;\r\n }\r\n\r\n public getHighlightBySeriesAndCategory(series: number, category: number): number {\r\n return this.dataView.values[series].highlights[category];\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import PixelConverter = jsCommon.PixelConverter;\r\n\r\n export class ClusteredColumnChartStrategy implements IColumnChartStrategy {\r\n private static classes = {\r\n item: {\r\n class: 'column',\r\n selector: '.column',\r\n },\r\n };\r\n\r\n private data: ColumnChartData;\r\n private graphicsContext: ColumnChartContext;\r\n private seriesOffsetScale: D3.Scale.OrdinalScale;\r\n private width: number;\r\n private height: number;\r\n private margin: IMargin;\r\n private xProps: IAxisProperties;\r\n private yProps: IAxisProperties;\r\n private categoryLayout: CategoryLayout;\r\n private viewportHeight: number;\r\n private viewportWidth: number;\r\n private columnsCenters: number[];\r\n private columnSelectionLineHandle: D3.Selection;\r\n private animator: IColumnChartAnimator;\r\n private interactivityService: IInteractivityService;\r\n private layout: IColumnLayout;\r\n private isComboChart: boolean;\r\n\r\n public setupVisualProps(columnChartProps: ColumnChartContext): void {\r\n this.graphicsContext = columnChartProps;\r\n this.margin = columnChartProps.margin;\r\n this.width = this.graphicsContext.width;\r\n this.height = this.graphicsContext.height;\r\n this.categoryLayout = columnChartProps.layout;\r\n this.animator = columnChartProps.animator;\r\n this.interactivityService = columnChartProps.interactivityService;\r\n this.viewportHeight = columnChartProps.viewportHeight;\r\n this.viewportWidth = columnChartProps.viewportWidth;\r\n this.isComboChart = columnChartProps.isComboChart;\r\n }\r\n\r\n public setData(data: ColumnChartData) {\r\n this.data = data;\r\n }\r\n\r\n public setXScale(is100Pct: boolean, forcedTickCount?: number, forcedXDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureXDomain?: NumberRange): IAxisProperties {\r\n let width = this.width;\r\n\r\n let forcedXMin, forcedXMax;\r\n\r\n if (forcedXDomain && forcedXDomain.length === 2) {\r\n forcedXMin = forcedXDomain[0];\r\n forcedXMax = forcedXDomain[1];\r\n }\r\n\r\n let props = this.xProps = ColumnUtil.getCategoryAxis(\r\n this.data,\r\n width,\r\n this.categoryLayout,\r\n false,\r\n forcedXMin,\r\n forcedXMax,\r\n axisScaleType,\r\n axisDisplayUnits,\r\n axisPrecision,\r\n ensureXDomain);\r\n\r\n // create clustered offset scale\r\n let seriesLength = this.data.series.length;\r\n let columnWidth = (this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio)) / seriesLength;\r\n this.seriesOffsetScale = d3.scale.ordinal()\r\n .domain(this.data.series.map(s => s.index))\r\n .rangeBands([0, seriesLength * columnWidth]);\r\n\r\n return props;\r\n }\r\n\r\n public setYScale(is100Pct: boolean, forcedTickCount?: number, forcedYDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureYDomain?: NumberRange): IAxisProperties {\r\n debug.assert(!is100Pct, 'Cannot have 100% clustered chart.');\r\n\r\n let height = this.viewportHeight;\r\n let valueDomain = AxisHelper.createValueDomain(this.data.series, true) || emptyDomain;\r\n let combinedDomain = AxisHelper.combineDomain(forcedYDomain, valueDomain, ensureYDomain);\r\n let shouldClamp = AxisHelper.scaleShouldClamp(combinedDomain, valueDomain);\r\n\r\n this.yProps = AxisHelper.createAxis({\r\n pixelSpan: height,\r\n dataDomain: combinedDomain,\r\n metaDataColumn: this.data.valuesMetadata[0],\r\n formatString: valueFormatter.getFormatString(this.data.valuesMetadata[0], columnChartProps.general.formatString),\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: true,\r\n forcedTickCount: forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false,\r\n scaleType: axisScaleType,\r\n axisDisplayUnits: axisDisplayUnits,\r\n axisPrecision: axisPrecision,\r\n shouldClamp: shouldClamp,\r\n });\r\n\r\n return this.yProps;\r\n }\r\n\r\n public drawColumns(useAnimation: boolean): ColumnChartDrawInfo {\r\n let data = this.data;\r\n debug.assertValue(data, 'data could not be null or undefined');\r\n\r\n this.columnsCenters = null; // invalidate the columnsCenters so that will be calculated again\r\n\r\n let categoryWidth = (this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio));\r\n let columnWidth = categoryWidth / data.series.length;\r\n let axisOptions: ColumnAxisOptions = {\r\n columnWidth: columnWidth,\r\n categoryWidth: categoryWidth,\r\n xScale: this.xProps.scale,\r\n yScale: this.yProps.scale,\r\n seriesOffsetScale: this.seriesOffsetScale,\r\n isScalar: this.categoryLayout.isScalar,\r\n margin: this.margin,\r\n };\r\n let clusteredColumnLayout = this.layout = ClusteredColumnChartStrategy.getLayout(data, axisOptions);\r\n let dataLabelSettings = data.labelSettings;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n if (dataLabelSettings && dataLabelSettings.show) {\r\n labelDataPoints = this.createLabelDataPoints();\r\n }\r\n\r\n let result: ColumnChartAnimationResult;\r\n let shapes: D3.UpdateSelection;\r\n let series = ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\r\n if (this.animator && useAnimation) {\r\n result = this.animator.animate({\r\n viewModel: data,\r\n series: series,\r\n layout: clusteredColumnLayout,\r\n itemCS: ClusteredColumnChartStrategy.classes.item,\r\n interactivityService: this.interactivityService,\r\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\r\n viewPort: { height: this.height, width: this.width }\r\n });\r\n shapes = result.shapes;\r\n }\r\n if (!this.animator || !useAnimation || result.failed) {\r\n shapes = ColumnUtil.drawDefaultShapes(data, series, clusteredColumnLayout, ClusteredColumnChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\r\n }\r\n\r\n ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\r\n\r\n return {\r\n eventGroup: this.graphicsContext.mainGraphicsContext,\r\n shapesSelection: shapes,\r\n viewport: { height: this.height, width: this.width },\r\n axisOptions: axisOptions,\r\n labelDataPoints: labelDataPoints,\r\n };\r\n }\r\n\r\n public selectColumn(selectedColumnIndex: number, lastSelectedColumnIndex: number): void {\r\n ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, ClusteredColumnChartStrategy.classes.item.selector, selectedColumnIndex, lastSelectedColumnIndex);\r\n this.moveHandle(selectedColumnIndex);\r\n }\r\n\r\n public getClosestColumnIndex(x: number, y: number): number {\r\n return ColumnUtil.getClosestColumnIndex(x, this.getColumnsCenters());\r\n }\r\n\r\n /**\r\n * Get the chart's columns centers (x value).\r\n */\r\n private getColumnsCenters(): number[] {\r\n if (!this.columnsCenters) { // lazy creation\r\n let categoryWidth: number = this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio);\r\n // use the axis scale and first series data to get category centers\r\n if (this.data.series.length > 0) {\r\n let xScaleOffset = 0;\r\n if (!this.categoryLayout.isScalar)\r\n xScaleOffset = categoryWidth / 2;\r\n let firstSeries = this.data.series[0];\r\n this.columnsCenters = firstSeries.data.map(d => this.xProps.scale(this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + xScaleOffset);\r\n }\r\n }\r\n return this.columnsCenters;\r\n }\r\n\r\n private moveHandle(selectedColumnIndex: number) {\r\n let columnCenters = this.getColumnsCenters();\r\n let x = columnCenters[selectedColumnIndex];\r\n\r\n let hoverLine = d3.select('.interactive-hover-line');\r\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\r\n\r\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\r\n }\r\n\r\n if (!this.columnSelectionLineHandle) {\r\n let handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\r\n handle.append('line')\r\n .classed('interactive-hover-line', true)\r\n .attr({\r\n x1: x,\r\n x2: x,\r\n y1: 0,\r\n y2: this.height,\r\n });\r\n\r\n handle.append('circle')\r\n .attr({\r\n cx: x,\r\n cy: this.height,\r\n r: '6px',\r\n })\r\n .classed('drag-handle', true);\r\n }\r\n else {\r\n let handle = this.columnSelectionLineHandle;\r\n handle.select('line').attr({ x1: x, x2: x });\r\n handle.select('circle').attr({ cx: x });\r\n }\r\n }\r\n\r\n public static getLayout(data: ColumnChartData, axisOptions: ColumnAxisOptions): IColumnLayout {\r\n let columnWidth = axisOptions.columnWidth;\r\n let halfColumnWidth = 0.5 * columnWidth;\r\n let quarterColumnWidth = halfColumnWidth / 2;\r\n let isScalar = axisOptions.isScalar;\r\n let xScale = axisOptions.xScale;\r\n let yScale = axisOptions.yScale;\r\n let seriesOffsetScale = axisOptions.seriesOffsetScale;\r\n let scaledY0 = yScale(0);\r\n let xScaleOffset = 0;\r\n\r\n if (isScalar)\r\n xScaleOffset = axisOptions.categoryWidth / 2;\r\n\r\n return {\r\n shapeLayout: {\r\n width: (d: ColumnChartDataPoint) => d.drawThinner ? halfColumnWidth : columnWidth,\r\n x: (d: ColumnChartDataPoint) => xScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - xScaleOffset + (d.drawThinner ? quarterColumnWidth : 0),\r\n y: (d: ColumnChartDataPoint) => scaledY0 + AxisHelper.diffScaled(yScale, Math.max(0, d.value), 0),\r\n height: (d: ColumnChartDataPoint) => Math.abs(AxisHelper.diffScaled(yScale, 0, d.value)),\r\n },\r\n shapeLayoutWithoutHighlights: {\r\n width: (d: ColumnChartDataPoint) => columnWidth,\r\n x: (d: ColumnChartDataPoint) => xScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - xScaleOffset,\r\n y: (d: ColumnChartDataPoint) => scaledY0 + AxisHelper.diffScaled(yScale, Math.max(0, d.originalValue), 0),\r\n height: (d: ColumnChartDataPoint) => Math.abs(AxisHelper.diffScaled(yScale, 0, d.originalValue)),\r\n },\r\n zeroShapeLayout: {\r\n width: (d: ColumnChartDataPoint) => d.drawThinner ? halfColumnWidth : columnWidth,\r\n x: (d: ColumnChartDataPoint) => xScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - xScaleOffset + (d.drawThinner ? quarterColumnWidth : 0),\r\n y: (d: ColumnChartDataPoint) => scaledY0,\r\n height: (d: ColumnChartDataPoint) => 0,\r\n },\r\n };\r\n }\r\n\r\n private createLabelDataPoints(): LabelDataPoint[] {\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n let data = this.data;\r\n let series = data.series;\r\n let formattersCache = NewDataLabelUtils.createColumnFormatterCacheManager();\r\n let shapeLayout = this.layout.shapeLayout;\r\n\r\n for (let currentSeries of series) {\r\n let labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\r\n if (!labelSettings.show)\r\n continue;\r\n\r\n let axisFormatter: number = NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\r\n for (let dataPoint of currentSeries.data) {\r\n if ((data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\r\n continue;\r\n }\r\n\r\n // Calculate parent rectangle\r\n let parentRect: IRect = {\r\n left: shapeLayout.x(dataPoint),\r\n top: shapeLayout.y(dataPoint),\r\n width: shapeLayout.width(dataPoint),\r\n height: shapeLayout.height(dataPoint),\r\n };\r\n\r\n // Calculate label text\r\n let formatString = dataPoint.labelFormatString;\r\n let formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\r\n let text = NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\r\n\r\n // Calculate text size\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\r\n\r\n labelDataPoints.push({\r\n isPreferred: true,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\r\n insideFill: ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\r\n parentType: LabelDataPointParentType.Rectangle,\r\n parentShape: {\r\n rect: parentRect,\r\n orientation: dataPoint.value >= 0 ? NewRectOrientation.VerticalBottomBased : NewRectOrientation.VerticalTopBased,\r\n validPositions: ColumnChart.clusteredValidLabelPositions,\r\n },\r\n identity: dataPoint.identity,\r\n fontSize: labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt,\r\n });\r\n }\r\n }\r\n\r\n return labelDataPoints;\r\n }\r\n }\r\n\r\n export class ClusteredBarChartStrategy implements IColumnChartStrategy {\r\n private static classes = {\r\n item: {\r\n class: 'bar',\r\n selector: '.bar'\r\n },\r\n };\r\n\r\n private data: ColumnChartData;\r\n private graphicsContext: ColumnChartContext;\r\n private seriesOffsetScale: D3.Scale.OrdinalScale;\r\n private width: number;\r\n private height: number;\r\n private margin: IMargin;\r\n private xProps: IAxisProperties;\r\n private yProps: IAxisProperties;\r\n private categoryLayout: CategoryLayout;\r\n private viewportHeight: number;\r\n private viewportWidth: number;\r\n private barsCenters: number[];\r\n private columnSelectionLineHandle: D3.Selection;\r\n private animator: IColumnChartAnimator;\r\n private interactivityService: IInteractivityService;\r\n private layout: IColumnLayout;\r\n private isComboChart: boolean;\r\n\r\n public setupVisualProps(barChartProps: ColumnChartContext): void {\r\n this.graphicsContext = barChartProps;\r\n this.margin = barChartProps.margin;\r\n this.width = this.graphicsContext.width;\r\n this.height = this.graphicsContext.height;\r\n this.categoryLayout = barChartProps.layout;\r\n this.animator = barChartProps.animator;\r\n this.interactivityService = barChartProps.interactivityService;\r\n this.viewportHeight = barChartProps.viewportHeight;\r\n this.viewportWidth = barChartProps.viewportWidth;\r\n this.isComboChart = barChartProps.isComboChart;\r\n }\r\n\r\n public setData(data: ColumnChartData) {\r\n this.data = data;\r\n }\r\n\r\n public setYScale(is100Pct: boolean, forcedTickCount?: number, forcedYDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureYDomain?: NumberRange): IAxisProperties {\r\n let height = this.height;\r\n let forcedYMin, forcedYMax;\r\n\r\n if (forcedYDomain && forcedYDomain.length === 2) {\r\n forcedYMin = forcedYDomain[0];\r\n forcedYMax = forcedYDomain[1];\r\n }\r\n\r\n let props = this.yProps = ColumnUtil.getCategoryAxis(\r\n this.data,\r\n height,\r\n this.categoryLayout,\r\n true,\r\n forcedYMin,\r\n forcedYMax,\r\n axisScaleType,\r\n axisDisplayUnits,\r\n axisPrecision,\r\n ensureYDomain\r\n );\r\n\r\n // create clustered offset scale\r\n let seriesLength = this.data.series.length;\r\n let columnWidth = (this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio)) / seriesLength;\r\n this.seriesOffsetScale = d3.scale.ordinal()\r\n .domain(this.data.series.map(s => s.index))\r\n .rangeBands([0, seriesLength * columnWidth]);\r\n\r\n return props;\r\n }\r\n\r\n public setXScale(is100Pct: boolean, forcedTickCount?: number, forcedXDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureXDomain?: NumberRange): IAxisProperties {\r\n debug.assert(!is100Pct, 'Cannot have 100% clustered chart.');\r\n debug.assert(forcedTickCount === undefined, 'Cannot have clustered bar chart as combo chart.');\r\n\r\n let width = this.width;\r\n let valueDomain = AxisHelper.createValueDomain(this.data.series, true) || emptyDomain;\r\n let combinedDomain = AxisHelper.combineDomain(forcedXDomain, valueDomain, ensureXDomain);\r\n let shouldClamp = AxisHelper.scaleShouldClamp(combinedDomain, valueDomain);\r\n\r\n this.xProps = AxisHelper.createAxis({\r\n pixelSpan: width,\r\n dataDomain: combinedDomain,\r\n metaDataColumn: this.data.valuesMetadata[0],\r\n formatString: valueFormatter.getFormatString(this.data.valuesMetadata[0], columnChartProps.general.formatString),\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: false,\r\n forcedTickCount: forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false,\r\n scaleType: axisScaleType,\r\n axisDisplayUnits: axisDisplayUnits,\r\n axisPrecision: axisPrecision,\r\n shouldClamp: shouldClamp,\r\n });\r\n\r\n this.xProps.axis.tickSize(-this.viewportHeight, 0);\r\n\r\n return this.xProps;\r\n }\r\n\r\n public drawColumns(useAnimation: boolean): ColumnChartDrawInfo {\r\n let data = this.data;\r\n debug.assertValue(data, 'data could not be null or undefined');\r\n\r\n this.barsCenters = null; // invalidate the columnsCenters so that will be calculated again\r\n\r\n let categoryWidth = (this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio));\r\n let columnWidth = categoryWidth / data.series.length;\r\n let axisOptions: ColumnAxisOptions = {\r\n columnWidth: columnWidth,\r\n categoryWidth: categoryWidth,\r\n xScale: this.xProps.scale,\r\n yScale: this.yProps.scale,\r\n seriesOffsetScale: this.seriesOffsetScale,\r\n isScalar: this.categoryLayout.isScalar,\r\n margin: this.margin,\r\n };\r\n let clusteredBarLayout = this.layout = ClusteredBarChartStrategy.getLayout(data, axisOptions);\r\n let dataLabelSettings = data.labelSettings;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n if (dataLabelSettings && dataLabelSettings.show) {\r\n labelDataPoints = this.createLabelDataPoints();\r\n }\r\n\r\n let result: ColumnChartAnimationResult;\r\n let shapes: D3.UpdateSelection;\r\n let series = ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\r\n if (this.animator && useAnimation) {\r\n result = this.animator.animate({\r\n viewModel: data,\r\n series: series,\r\n layout: clusteredBarLayout,\r\n itemCS: ClusteredBarChartStrategy.classes.item,\r\n interactivityService: this.interactivityService,\r\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\r\n viewPort: { height: this.height, width: this.width }\r\n });\r\n shapes = result.shapes;\r\n }\r\n if (!this.animator || !useAnimation || result.failed) {\r\n shapes = ColumnUtil.drawDefaultShapes(data, series, clusteredBarLayout, ClusteredBarChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\r\n }\r\n\r\n ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\r\n\r\n return {\r\n eventGroup: this.graphicsContext.mainGraphicsContext,\r\n shapesSelection: shapes,\r\n viewport: { height: this.height, width: this.width },\r\n axisOptions: axisOptions,\r\n labelDataPoints: labelDataPoints,\r\n };\r\n }\r\n\r\n public selectColumn(selectedColumnIndex: number, lastSelectedColumnIndex: number): void {\r\n ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, ClusteredBarChartStrategy.classes.item.selector, selectedColumnIndex, lastSelectedColumnIndex);\r\n this.moveHandle(selectedColumnIndex);\r\n }\r\n\r\n public getClosestColumnIndex(x: number, y: number): number {\r\n return ColumnUtil.getClosestColumnIndex(y, this.getBarsCenters());\r\n }\r\n\r\n /** \r\n * Get the chart's columns centers (y value).\r\n */\r\n private getBarsCenters(): number[] {\r\n if (!this.barsCenters) { // lazy creation\r\n let barWidth: number = this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio);\r\n // use the axis scale and first series data to get category centers\r\n if (this.data.series.length > 0) {\r\n let yScaleOffset = 0;\r\n if (!this.categoryLayout.isScalar)\r\n yScaleOffset = barWidth / 2;\r\n let firstSeries = this.data.series[0];\r\n this.barsCenters = firstSeries.data.map(d => this.yProps.scale(this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + yScaleOffset);\r\n }\r\n }\r\n return this.barsCenters;\r\n }\r\n\r\n private moveHandle(selectedColumnIndex: number) {\r\n let barCenters = this.getBarsCenters();\r\n let y = barCenters[selectedColumnIndex];\r\n\r\n let hoverLine = d3.select('.interactive-hover-line');\r\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\r\n\r\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\r\n }\r\n\r\n if (!this.columnSelectionLineHandle) {\r\n let handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\r\n handle.append('line')\r\n .classed('interactive-hover-line', true)\r\n .attr({\r\n x1: 0,\r\n x2: this.width,\r\n y1: y,\r\n y2: y,\r\n });\r\n handle.append('circle')\r\n .attr({\r\n cx: 0,\r\n cy: y,\r\n r: '6px',\r\n })\r\n .classed('drag-handle', true);\r\n }\r\n else {\r\n let handle = this.columnSelectionLineHandle;\r\n handle.select('line').attr({ y1: y, y2: y });\r\n handle.select('circle').attr({ cy: y });\r\n }\r\n }\r\n\r\n public static getLayout(data: ColumnChartData, axisOptions: ColumnAxisOptions): IColumnLayout {\r\n let columnWidth = axisOptions.columnWidth;\r\n let halfColumnWidth = 0.5 * columnWidth;\r\n let quarterColumnWidth = halfColumnWidth / 2;\r\n let isScalar = axisOptions.isScalar;\r\n let xScale = axisOptions.xScale;\r\n let yScale = axisOptions.yScale;\r\n let seriesOffsetScale = axisOptions.seriesOffsetScale;\r\n let scaledX0 = xScale(0);\r\n let yScaleOffset = 0;\r\n\r\n if (isScalar)\r\n yScaleOffset = axisOptions.categoryWidth / 2;\r\n\r\n return {\r\n shapeLayout: {\r\n width: (d: ColumnChartDataPoint) => Math.abs(AxisHelper.diffScaled(xScale, 0, d.value)),\r\n x: (d: ColumnChartDataPoint) => scaledX0 + AxisHelper.diffScaled(xScale, Math.min(0, d.value), 0),\r\n y: (d: ColumnChartDataPoint) => yScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - yScaleOffset + (d.drawThinner ? quarterColumnWidth : 0),\r\n height: (d: ColumnChartDataPoint) => d.drawThinner ? halfColumnWidth : columnWidth,\r\n },\r\n shapeLayoutWithoutHighlights: {\r\n width: (d: ColumnChartDataPoint) => Math.abs(AxisHelper.diffScaled(xScale, 0, d.originalValue)),\r\n x: (d: ColumnChartDataPoint) => scaledX0 + AxisHelper.diffScaled(xScale, Math.min(0, d.originalValue), 0),\r\n y: (d: ColumnChartDataPoint) => yScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - yScaleOffset,\r\n height: (d: ColumnChartDataPoint) => columnWidth,\r\n },\r\n zeroShapeLayout: {\r\n width: (d: ColumnChartDataPoint) => 0,\r\n x: (d: ColumnChartDataPoint) => scaledX0 + AxisHelper.diffScaled(xScale, Math.min(0, d.value), 0),\r\n y: (d: ColumnChartDataPoint) => yScale(isScalar ? d.categoryValue : d.categoryIndex) + seriesOffsetScale(d.seriesIndex) - yScaleOffset + (d.drawThinner ? quarterColumnWidth : 0),\r\n height: (d: ColumnChartDataPoint) => d.drawThinner ? halfColumnWidth : columnWidth,\r\n },\r\n };\r\n }\r\n\r\n private createLabelDataPoints(): LabelDataPoint[] {\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n let data = this.data;\r\n let series = data.series;\r\n let formattersCache = NewDataLabelUtils.createColumnFormatterCacheManager();\r\n let shapeLayout = this.layout.shapeLayout;\r\n\r\n for (let currentSeries of series) {\r\n let labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\r\n if (!labelSettings.show)\r\n continue;\r\n\r\n let axisFormatter: number = NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\r\n for (let dataPoint of currentSeries.data) {\r\n if ((this.interactivityService && this.interactivityService.hasSelection() && !dataPoint.selected) || (data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\r\n continue;\r\n }\r\n\r\n // Calculate label text\r\n let formatString = dataPoint.labelFormatString;\r\n let formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\r\n let text = NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\r\n\r\n // Calculate text size\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\r\n\r\n // Calculate parent rectangle\r\n let parentRect: IRect = {\r\n left: shapeLayout.x(dataPoint),\r\n top: shapeLayout.y(dataPoint),\r\n width: shapeLayout.width(dataPoint),\r\n height: shapeLayout.height(dataPoint),\r\n };\r\n\r\n labelDataPoints.push({\r\n isPreferred: true,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\r\n insideFill: ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\r\n parentType: LabelDataPointParentType.Rectangle,\r\n parentShape: {\r\n rect: parentRect,\r\n orientation: dataPoint.value >= 0 ? NewRectOrientation.HorizontalLeftBased : NewRectOrientation.HorizontalRightBased,\r\n validPositions: ColumnChart.clusteredValidLabelPositions,\r\n },\r\n identity: dataPoint.identity,\r\n fontSize: labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt,\r\n });\r\n }\r\n }\r\n\r\n return labelDataPoints;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import PixelConverter = jsCommon.PixelConverter;\r\n\r\n export class StackedColumnChartStrategy implements IColumnChartStrategy {\r\n private static classes = {\r\n item: {\r\n class: 'column',\r\n selector: '.column'\r\n },\r\n highlightItem: {\r\n class: 'highlightColumn',\r\n selector: '.highlightColumn'\r\n },\r\n };\r\n\r\n private data: ColumnChartData;\r\n private graphicsContext: ColumnChartContext;\r\n private width: number;\r\n private height: number;\r\n private margin: IMargin;\r\n private xProps: IAxisProperties;\r\n private yProps: IAxisProperties;\r\n private categoryLayout: CategoryLayout;\r\n private columnsCenters: number[];\r\n private columnSelectionLineHandle: D3.Selection;\r\n private animator: IColumnChartAnimator;\r\n private interactivityService: IInteractivityService;\r\n private viewportHeight: number;\r\n private viewportWidth: number;\r\n private layout: IColumnLayout;\r\n private isComboChart: boolean;\r\n\r\n public setupVisualProps(columnChartProps: ColumnChartContext): void {\r\n this.graphicsContext = columnChartProps;\r\n this.margin = columnChartProps.margin;\r\n this.width = this.graphicsContext.width;\r\n this.height = this.graphicsContext.height;\r\n this.categoryLayout = columnChartProps.layout;\r\n this.animator = columnChartProps.animator;\r\n this.interactivityService = columnChartProps.interactivityService;\r\n this.viewportHeight = columnChartProps.viewportHeight;\r\n this.viewportWidth = columnChartProps.viewportWidth;\r\n this.isComboChart = columnChartProps.isComboChart;\r\n }\r\n\r\n public setData(data: ColumnChartData) {\r\n this.data = data;\r\n }\r\n\r\n public setXScale(is100Pct: boolean, forcedTickCount?: number, forcedXDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, xReferenceLineValue?: number): IAxisProperties {\r\n let width = this.width;\r\n\r\n let forcedXMin, forcedXMax;\r\n\r\n if (forcedXDomain && forcedXDomain.length === 2) {\r\n forcedXMin = forcedXDomain[0];\r\n forcedXMax = forcedXDomain[1];\r\n }\r\n\r\n let props = this.xProps = ColumnUtil.getCategoryAxis(\r\n this.data,\r\n width,\r\n this.categoryLayout,\r\n false,\r\n forcedXMin,\r\n forcedXMax,\r\n axisScaleType,\r\n axisDisplayUnits,\r\n axisPrecision,\r\n xReferenceLineValue);\r\n\r\n return props;\r\n }\r\n\r\n public setYScale(is100Pct: boolean, forcedTickCount?: number, forcedYDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, y1ReferenceLineValue?: number): IAxisProperties {\r\n let height = this.viewportHeight;\r\n let valueDomain = StackedUtil.calcValueDomain(this.data.series, is100Pct);\r\n let valueDomainArr = [valueDomain.min, valueDomain.max];\r\n let combinedDomain = AxisHelper.combineDomain(forcedYDomain, valueDomainArr, y1ReferenceLineValue);\r\n let shouldClamp = AxisHelper.scaleShouldClamp(combinedDomain, valueDomainArr);\r\n let metadataColumn = this.data.valuesMetadata[0];\r\n let formatString = is100Pct ?\r\n this.graphicsContext.hostService.getLocalizedString('Percentage')\r\n : valueFormatter.getFormatString(metadataColumn, columnChartProps.general.formatString);\r\n\r\n this.yProps = AxisHelper.createAxis({\r\n pixelSpan: height,\r\n dataDomain: combinedDomain,\r\n metaDataColumn: metadataColumn,\r\n formatString: formatString,\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: true,\r\n forcedTickCount: forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false,\r\n scaleType: axisScaleType,\r\n axisDisplayUnits: axisDisplayUnits,\r\n axisPrecision: axisPrecision,\r\n is100Pct: is100Pct,\r\n shouldClamp: shouldClamp,\r\n });\r\n\r\n return this.yProps;\r\n }\r\n\r\n public drawColumns(useAnimation: boolean): ColumnChartDrawInfo {\r\n let data = this.data;\r\n debug.assertValue(data, 'data should not be null or undefined');\r\n\r\n this.columnsCenters = null; // invalidate the columnsCenters so that will be calculated again\r\n\r\n let axisOptions: ColumnAxisOptions = {\r\n columnWidth: this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio),\r\n xScale: this.xProps.scale,\r\n yScale: this.yProps.scale,\r\n isScalar: this.categoryLayout.isScalar,\r\n margin: this.margin,\r\n };\r\n let stackedColumnLayout = this.layout = StackedColumnChartStrategy.getLayout(data, axisOptions);\r\n let dataLabelSettings = data.labelSettings;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n if (dataLabelSettings && dataLabelSettings.show) {\r\n labelDataPoints = this.createLabelDataPoints();\r\n }\r\n\r\n let result: ColumnChartAnimationResult;\r\n let shapes: D3.UpdateSelection;\r\n let series = ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\r\n if (this.animator && useAnimation) {\r\n result = this.animator.animate({\r\n viewModel: data,\r\n series: series,\r\n layout: stackedColumnLayout,\r\n itemCS: StackedColumnChartStrategy.classes.item,\r\n interactivityService: this.interactivityService,\r\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\r\n viewPort: { height: this.height, width: this.width },\r\n });\r\n shapes = result.shapes;\r\n }\r\n if (!this.animator || !useAnimation || result.failed) {\r\n shapes = ColumnUtil.drawDefaultShapes(data, series, stackedColumnLayout, StackedColumnChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\r\n }\r\n\r\n ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\r\n\r\n return {\r\n eventGroup: this.graphicsContext.mainGraphicsContext,\r\n shapesSelection: shapes,\r\n viewport: { height: this.height, width: this.width },\r\n axisOptions,\r\n labelDataPoints: labelDataPoints,\r\n };\r\n }\r\n\r\n public selectColumn(selectedColumnIndex: number, lastSelectedColumnIndex: number): void {\r\n ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, StackedColumnChartStrategy.classes.item.selector, selectedColumnIndex, lastSelectedColumnIndex);\r\n this.moveHandle(selectedColumnIndex);\r\n }\r\n\r\n public getClosestColumnIndex(x: number, y: number): number {\r\n return ColumnUtil.getClosestColumnIndex(x, this.getColumnsCenters());\r\n }\r\n\r\n /**\r\n * Get the chart's columns centers (x value).\r\n */\r\n private getColumnsCenters(): number[] {\r\n if (!this.columnsCenters) { // lazy creation\r\n let categoryWidth: number = this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio);\r\n // use the axis scale and first series data to get category centers\r\n if (this.data.series.length > 0) {\r\n let xScaleOffset = 0;\r\n if (!this.categoryLayout.isScalar)\r\n xScaleOffset = categoryWidth / 2;\r\n let firstSeries = this.data.series[0];\r\n this.columnsCenters = firstSeries.data.map(d => this.xProps.scale(this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + xScaleOffset);\r\n }\r\n }\r\n return this.columnsCenters;\r\n }\r\n\r\n private moveHandle(selectedColumnIndex: number) {\r\n let columnCenters = this.getColumnsCenters();\r\n let x = columnCenters[selectedColumnIndex];\r\n\r\n let hoverLine = d3.select('.interactive-hover-line');\r\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\r\n\r\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\r\n }\r\n\r\n if (!this.columnSelectionLineHandle) {\r\n let handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\r\n handle.append('line')\r\n .classed('interactive-hover-line', true)\r\n .attr({\r\n x1: x,\r\n x2: x,\r\n y1: 0,\r\n y2: this.height,\r\n });\r\n\r\n handle.append('circle')\r\n .attr({\r\n cx: x,\r\n cy: this.height,\r\n r: '6px',\r\n })\r\n .classed('drag-handle', true);\r\n }\r\n else {\r\n let handle = this.columnSelectionLineHandle;\r\n handle.select('line').attr({ x1: x, x2: x });\r\n handle.select('circle').attr({ cx: x });\r\n }\r\n }\r\n\r\n public static getLayout(data: ColumnChartData, axisOptions: ColumnAxisOptions): IColumnLayout {\r\n let columnWidth = axisOptions.columnWidth;\r\n let isScalar = axisOptions.isScalar;\r\n let xScale = axisOptions.xScale;\r\n let yScale = axisOptions.yScale;\r\n let xScaleOffset = 0;\r\n if (isScalar)\r\n xScaleOffset = columnWidth / 2;\r\n\r\n // d.position is the top left corner (for drawing) - set in columnChart.converter\r\n // for positive values, this is the previous stack position + the new value,\r\n // for negative values it is just the previous stack position\r\n\r\n return {\r\n shapeLayout: {\r\n width: (d: ColumnChartDataPoint) => columnWidth,\r\n x: (d: ColumnChartDataPoint) => xScale(isScalar ? d.categoryValue : d.categoryIndex) - xScaleOffset,\r\n y: (d: ColumnChartDataPoint) => yScale(d.position),\r\n height: (d: ColumnChartDataPoint) => yScale(d.position - d.valueAbsolute) - yScale(d.position),\r\n },\r\n shapeLayoutWithoutHighlights: {\r\n width: (d: ColumnChartDataPoint) => columnWidth,\r\n x: (d: ColumnChartDataPoint) => xScale(isScalar ? d.categoryValue : d.categoryIndex) - xScaleOffset,\r\n y: (d: ColumnChartDataPoint) => yScale(d.originalPosition),\r\n height: (d: ColumnChartDataPoint) => yScale(d.originalPosition - d.originalValueAbsolute) - yScale(d.originalPosition),\r\n },\r\n zeroShapeLayout: {\r\n width: (d: ColumnChartDataPoint) => columnWidth,\r\n x: (d: ColumnChartDataPoint) => xScale(isScalar ? d.categoryValue : d.categoryIndex) - xScaleOffset,\r\n y: (d: ColumnChartDataPoint) => d.value >= 0 ? yScale(d.position - d.valueAbsolute) : yScale(d.position),\r\n height: (d: ColumnChartDataPoint) => 0\r\n },\r\n };\r\n }\r\n\r\n private createLabelDataPoints(): LabelDataPoint[]{\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n let data = this.data;\r\n let series = data.series;\r\n let formattersCache = NewDataLabelUtils.createColumnFormatterCacheManager();\r\n let shapeLayout = this.layout.shapeLayout;\r\n\r\n for (let currentSeries of series) {\r\n let labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\r\n if (!labelSettings.show)\r\n continue;\r\n\r\n let axisFormatter: number = NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\r\n for (let dataPoint of currentSeries.data) {\r\n if ((data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\r\n continue;\r\n }\r\n\r\n // Calculate parent rectangle\r\n let parentRect: IRect = {\r\n left: shapeLayout.x(dataPoint),\r\n top: shapeLayout.y(dataPoint),\r\n width: shapeLayout.width(dataPoint),\r\n height: shapeLayout.height(dataPoint),\r\n };\r\n\r\n // Calculate label text\r\n let formatString = \"\";\r\n if (this.graphicsContext.is100Pct) {\r\n formatString = NewDataLabelUtils.hundredPercentFormat;\r\n }\r\n else {\r\n formatString = dataPoint.labelFormatString;\r\n }\r\n let formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\r\n let text = NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\r\n\r\n // Calculate text size\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\r\n\r\n labelDataPoints.push({\r\n isPreferred: true,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\r\n insideFill: ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\r\n parentType: LabelDataPointParentType.Rectangle,\r\n parentShape: {\r\n rect: parentRect,\r\n orientation: dataPoint.value >= 0 ? NewRectOrientation.VerticalBottomBased : NewRectOrientation.VerticalTopBased,\r\n validPositions: ColumnChart.stackedValidLabelPositions,\r\n },\r\n identity: dataPoint.identity,\r\n fontSize: labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt,\r\n });\r\n }\r\n }\r\n \r\n return labelDataPoints;\r\n }\r\n }\r\n\r\n export class StackedBarChartStrategy implements IColumnChartStrategy {\r\n private static classes = {\r\n item: {\r\n class: 'bar',\r\n selector: '.bar'\r\n },\r\n highlightItem: {\r\n class: 'highlightBar',\r\n selector: '.highlightBar'\r\n },\r\n };\r\n\r\n private data: ColumnChartData;\r\n private graphicsContext: ColumnChartContext;\r\n private width: number; height: number;\r\n private margin: IMargin;\r\n private xProps: IAxisProperties;\r\n private yProps: IAxisProperties;\r\n private categoryLayout: CategoryLayout;\r\n private barsCenters: number[];\r\n private columnSelectionLineHandle: D3.Selection;\r\n private animator: IColumnChartAnimator;\r\n private interactivityService: IInteractivityService;\r\n private viewportHeight: number;\r\n private viewportWidth: number;\r\n private layout: IColumnLayout;\r\n private isComboChart: boolean;\r\n\r\n public setupVisualProps(barChartProps: ColumnChartContext): void {\r\n this.graphicsContext = barChartProps;\r\n this.margin = barChartProps.margin;\r\n this.width = this.graphicsContext.width;\r\n this.height = this.graphicsContext.height;\r\n this.categoryLayout = barChartProps.layout;\r\n this.animator = barChartProps.animator;\r\n this.interactivityService = barChartProps.interactivityService;\r\n this.viewportHeight = barChartProps.viewportHeight;\r\n this.viewportWidth = barChartProps.viewportWidth;\r\n this.isComboChart = barChartProps.isComboChart;\r\n }\r\n\r\n public setData(data: ColumnChartData) {\r\n this.data = data;\r\n }\r\n\r\n public setYScale(is100Pct: boolean, forcedTickCount?: number, forcedYDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureYDomain?: NumberRange): IAxisProperties {\r\n let height = this.height;\r\n\r\n let forcedYMin, forcedYMax;\r\n\r\n if (forcedYDomain && forcedYDomain.length === 2) {\r\n forcedYMin = forcedYDomain[0];\r\n forcedYMax = forcedYDomain[1];\r\n }\r\n\r\n let props = this.yProps = ColumnUtil.getCategoryAxis(\r\n this.data,\r\n height,\r\n this.categoryLayout,\r\n true,\r\n forcedYMin,\r\n forcedYMax,\r\n axisScaleType,\r\n axisDisplayUnits,\r\n axisPrecision,\r\n ensureYDomain);\r\n\r\n return props;\r\n }\r\n\r\n public setXScale(is100Pct: boolean, forcedTickCount?: number, forcedXDomain?: any[], axisScaleType?: string, axisDisplayUnits?: number, axisPrecision?: number, ensureXDomain?: NumberRange): IAxisProperties {\r\n debug.assert(forcedTickCount === undefined, 'Cannot have stacked bar chart as combo chart.');\r\n\r\n let width = this.width;\r\n let valueDomain = StackedUtil.calcValueDomain(this.data.series, is100Pct);\r\n let valueDomainArr = [valueDomain.min, valueDomain.max];\r\n let combinedDomain = AxisHelper.combineDomain(forcedXDomain, valueDomainArr, ensureXDomain);\r\n let shouldClamp = AxisHelper.scaleShouldClamp(combinedDomain, valueDomainArr);\r\n let metadataColumn = this.data.valuesMetadata[0];\r\n let formatString = is100Pct ?\r\n this.graphicsContext.hostService.getLocalizedString('Percentage')\r\n : valueFormatter.getFormatString(metadataColumn, columnChartProps.general.formatString);\r\n\r\n this.xProps = AxisHelper.createAxis({\r\n pixelSpan: width,\r\n dataDomain: combinedDomain,\r\n metaDataColumn: metadataColumn,\r\n formatString: formatString,\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: false,\r\n forcedTickCount: forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false,\r\n scaleType: axisScaleType,\r\n axisDisplayUnits: axisDisplayUnits,\r\n axisPrecision: axisPrecision,\r\n is100Pct: is100Pct,\r\n shouldClamp: shouldClamp,\r\n });\r\n\r\n this.xProps.axis.tickSize(-this.viewportHeight, 0);\r\n\r\n return this.xProps;\r\n }\r\n\r\n public drawColumns(useAnimation: boolean): ColumnChartDrawInfo {\r\n let data = this.data;\r\n debug.assertValue(data, 'data should not be null or undefined');\r\n\r\n this.barsCenters = null; // invalidate the barsCenters so that will be calculated again\r\n\r\n let axisOptions: ColumnAxisOptions = {\r\n columnWidth: this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio),\r\n xScale: this.xProps.scale,\r\n yScale: this.yProps.scale,\r\n isScalar: this.categoryLayout.isScalar,\r\n margin: this.margin,\r\n };\r\n let stackedBarLayout = this.layout = StackedBarChartStrategy.getLayout(data, axisOptions);\r\n let dataLabelSettings = data.labelSettings;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n if (dataLabelSettings && dataLabelSettings.show) {\r\n labelDataPoints = this.createLabelDataPoints();\r\n }\r\n\r\n let result: ColumnChartAnimationResult;\r\n let shapes: D3.UpdateSelection;\r\n let series = ColumnUtil.drawSeries(data, this.graphicsContext.mainGraphicsContext, axisOptions);\r\n if (this.animator && useAnimation) {\r\n result = this.animator.animate({\r\n viewModel: data,\r\n series: series,\r\n layout: stackedBarLayout,\r\n itemCS: StackedBarChartStrategy.classes.item,\r\n interactivityService: this.interactivityService,\r\n mainGraphicsContext: this.graphicsContext.mainGraphicsContext,\r\n viewPort: { height: this.height, width: this.width },\r\n });\r\n shapes = result.shapes;\r\n }\r\n if (!this.animator || !useAnimation || result.failed) {\r\n shapes = ColumnUtil.drawDefaultShapes(data, series, stackedBarLayout, StackedBarChartStrategy.classes.item, !this.animator, this.interactivityService && this.interactivityService.hasSelection());\r\n }\r\n\r\n ColumnUtil.applyInteractivity(shapes, this.graphicsContext.onDragStart);\r\n\r\n return {\r\n eventGroup: this.graphicsContext.mainGraphicsContext,\r\n shapesSelection: shapes,\r\n viewport: { height: this.height, width: this.width },\r\n axisOptions: axisOptions,\r\n labelDataPoints: labelDataPoints,\r\n };\r\n }\r\n\r\n public selectColumn(selectedColumnIndex: number, lastInteractiveSelectedColumnIndex: number): void {\r\n ColumnUtil.setChosenColumnOpacity(this.graphicsContext.mainGraphicsContext, StackedBarChartStrategy.classes.item.selector, selectedColumnIndex, lastInteractiveSelectedColumnIndex);\r\n this.moveHandle(selectedColumnIndex);\r\n }\r\n\r\n public getClosestColumnIndex(x: number, y: number): number {\r\n return ColumnUtil.getClosestColumnIndex(y, this.getBarsCenters());\r\n }\r\n\r\n /** \r\n * Get the chart's columns centers (y value).\r\n */\r\n private getBarsCenters(): number[] {\r\n if (!this.barsCenters) { // lazy creation\r\n let barWidth: number = this.categoryLayout.categoryThickness * (1 - CartesianChart.InnerPaddingRatio);\r\n // use the axis scale and first series data to get category centers\r\n if (this.data.series.length > 0) {\r\n let yScaleOffset = 0;\r\n if (!this.categoryLayout.isScalar)\r\n yScaleOffset = barWidth / 2;\r\n let firstSeries = this.data.series[0];\r\n this.barsCenters = firstSeries.data.map(d => this.yProps.scale(this.categoryLayout.isScalar ? d.categoryValue : d.categoryIndex) + yScaleOffset);\r\n }\r\n }\r\n return this.barsCenters;\r\n }\r\n\r\n private moveHandle(selectedColumnIndex: number) {\r\n let barCenters = this.getBarsCenters();\r\n let y = barCenters[selectedColumnIndex];\r\n \r\n let hoverLine = d3.select('.interactive-hover-line');\r\n if (!hoverLine.empty() && !this.columnSelectionLineHandle) {\r\n\r\n this.columnSelectionLineHandle = d3.select(hoverLine.node().parentNode);\r\n }\r\n\r\n if (!this.columnSelectionLineHandle) {\r\n let handle = this.columnSelectionLineHandle = this.graphicsContext.unclippedGraphicsContext.append('g');\r\n handle.append('line')\r\n .classed('interactive-hover-line', true)\r\n .attr({\r\n x1: 0,\r\n x2: this.width,\r\n y1: y,\r\n y2: y\r\n });\r\n handle.append('circle')\r\n .classed('drag-handle', true)\r\n .attr({\r\n cx: 0,\r\n cy: y,\r\n r: '6px',\r\n });\r\n\r\n }\r\n else {\r\n let handle = this.columnSelectionLineHandle;\r\n handle.select('line').attr({ y1: y, y2: y });\r\n handle.select('circle').attr({ cy: y });\r\n }\r\n }\r\n\r\n public static getLayout(data: ColumnChartData, axisOptions: ColumnAxisOptions): IColumnLayout {\r\n let columnWidth = axisOptions.columnWidth;\r\n let isScalar = axisOptions.isScalar;\r\n let xScale = axisOptions.xScale;\r\n let yScale = axisOptions.yScale;\r\n let yScaleOffset = 0;\r\n if (isScalar)\r\n yScaleOffset = columnWidth / 2;\r\n\r\n // d.position is the top right corner for bars - set in columnChart.converter\r\n // for positive values, this is the previous stack position + the new value,\r\n // for negative values it is just the previous stack position\r\n\r\n return {\r\n shapeLayout: {\r\n width: (d: ColumnChartDataPoint) => xScale(d.position) - xScale(d.position - d.valueAbsolute),\r\n x: (d: ColumnChartDataPoint) => xScale(d.position - d.valueAbsolute),\r\n y: (d: ColumnChartDataPoint) => yScale(isScalar ? d.categoryValue : d.categoryIndex) - yScaleOffset,\r\n height: (d: ColumnChartDataPoint) => columnWidth,\r\n },\r\n shapeLayoutWithoutHighlights: {\r\n width: (d: ColumnChartDataPoint) => xScale(d.originalPosition) - xScale(d.originalPosition - d.originalValueAbsolute),\r\n x: (d: ColumnChartDataPoint) => xScale(d.originalPosition - d.originalValueAbsolute),\r\n y: (d: ColumnChartDataPoint) => yScale(isScalar ? d.categoryValue : d.categoryIndex) - yScaleOffset,\r\n height: (d: ColumnChartDataPoint) => columnWidth,\r\n },\r\n zeroShapeLayout: {\r\n width: (d: ColumnChartDataPoint) => 0,\r\n x: (d: ColumnChartDataPoint) => d.value >= 0 ? xScale(d.position - d.valueAbsolute) : xScale(d.position),\r\n y: (d: ColumnChartDataPoint) => yScale(isScalar ? d.categoryValue : d.categoryIndex) - yScaleOffset,\r\n height: (d: ColumnChartDataPoint) => columnWidth,\r\n },\r\n };\r\n }\r\n\r\n private createLabelDataPoints(): LabelDataPoint[] {\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n let data = this.data;\r\n let series = data.series;\r\n let formattersCache = NewDataLabelUtils.createColumnFormatterCacheManager();\r\n let shapeLayout = this.layout.shapeLayout;\r\n\r\n for (let currentSeries of series) {\r\n let labelSettings = currentSeries.labelSettings ? currentSeries.labelSettings : data.labelSettings;\r\n if (!labelSettings.show)\r\n continue;\r\n\r\n let axisFormatter: number = NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yProps.formatter, labelSettings);\r\n for (let dataPoint of currentSeries.data) {\r\n if ((this.interactivityService && this.interactivityService.hasSelection() && !dataPoint.selected) || (data.hasHighlights && !dataPoint.highlight) || dataPoint.value == null) {\r\n continue;\r\n }\r\n\r\n // Calculate label text\r\n let formatString = undefined;\r\n if (this.graphicsContext.is100Pct) {\r\n formatString = NewDataLabelUtils.hundredPercentFormat;\r\n }\r\n else {\r\n formatString = dataPoint.labelFormatString;\r\n }\r\n let formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\r\n let text = NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\r\n\r\n // Calculate text size\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\r\n\r\n // Calculate parent rectangle\r\n let parentRect: IRect = {\r\n left: shapeLayout.x(dataPoint),\r\n top: shapeLayout.y(dataPoint),\r\n width: shapeLayout.width(dataPoint),\r\n height: shapeLayout.height(dataPoint),\r\n };\r\n\r\n labelDataPoints.push({\r\n isPreferred: true,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: ColumnChart.getLabelFill(labelSettings.labelColor, false, this.isComboChart),\r\n insideFill: ColumnChart.getLabelFill(labelSettings.labelColor, true, this.isComboChart),\r\n parentType: LabelDataPointParentType.Rectangle,\r\n parentShape: {\r\n rect: parentRect,\r\n orientation: dataPoint.value >= 0 ? NewRectOrientation.HorizontalLeftBased : NewRectOrientation.HorizontalRightBased,\r\n validPositions: ColumnChart.stackedValidLabelPositions,\r\n },\r\n identity: dataPoint.identity,\r\n fontSize: labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt,\r\n });\r\n }\r\n }\r\n\r\n return labelDataPoints;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.samples {\r\n import SelectionManager = utility.SelectionManager;\r\n export interface HelloViewModel {\r\n text: string;\r\n color: string;\r\n size: number;\r\n selector: SelectionId;\r\n toolTipInfo: TooltipDataItem[];\r\n }\r\n\r\n export class HelloIVisual implements IVisual {\r\n public static capabilities: VisualCapabilities = {\r\n dataRoles: [{\r\n displayName: 'Values',\r\n name: 'Values',\r\n kind: VisualDataRoleKind.GroupingOrMeasure\r\n }],\r\n dataViewMappings: [{\r\n table: {\r\n rows: {\r\n for: { in: 'Values' },\r\n dataReductionAlgorithm: { window: { count: 100 } }\r\n },\r\n rowCount: { preferred: { min: 1 } }\r\n },\r\n }],\r\n objects: {\r\n general: {\r\n displayName: data.createDisplayNameGetter('Visual_General'),\r\n properties: {\r\n fill: {\r\n type: { fill: { solid: { color: true } } },\r\n displayName: 'Fill'\r\n },\r\n size: {\r\n type: { numeric: true },\r\n displayName: 'Size'\r\n }\r\n },\r\n }\r\n },\r\n };\r\n\r\n private static DefaultText = 'Invalid DV';\r\n private root: D3.Selection;\r\n private svgText: D3.Selection;\r\n private dataView: DataView;\r\n private selectiionManager: SelectionManager;\r\n\r\n public static converter(dataView: DataView): HelloViewModel {\r\n var viewModel: HelloViewModel = {\r\n size: HelloIVisual.getSize(dataView),\r\n color: HelloIVisual.getFill(dataView).solid.color,\r\n text: HelloIVisual.DefaultText,\r\n toolTipInfo: [{\r\n displayName: 'Test',\r\n value: '1...2....3... can you see me? I am sending random strings to the tooltip',\r\n }],\r\n selector: SelectionId.createNull()\r\n };\r\n var table = dataView.table;\r\n if (!table) return viewModel;\r\n\r\n viewModel.text = table.rows[0][0];\r\n if (dataView.categorical) {\r\n viewModel.selector = dataView.categorical.categories[0].identity\r\n ? SelectionId.createWithId(dataView.categorical.categories[0].identity[0])\r\n : SelectionId.createNull();\r\n }\r\n\r\n return viewModel;\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.root = d3.select(options.element.get(0))\r\n .append('svg')\r\n .classed('hello', true);\r\n\r\n this.svgText = this.root\r\n .append('text')\r\n .style('cursor', 'pointer')\r\n .style('stroke', 'green')\r\n .style('stroke-width', '0px')\r\n .attr('text-anchor', 'middle');\r\n\r\n this.selectiionManager = new SelectionManager({ hostServices: options.host });\r\n }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n if (!options.dataViews && !options.dataViews[0]) return;\r\n var dataView = this.dataView = options.dataViews[0];\r\n var viewport = options.viewport;\r\n var viewModel: HelloViewModel = HelloIVisual.converter(dataView);\r\n\r\n this.root.attr({\r\n 'height': viewport.height,\r\n 'width': viewport.width\r\n });\r\n\r\n var textProperties = {\r\n fontFamily: 'tahoma',\r\n fontSize: viewModel.size + 'px',\r\n text: viewModel.text\r\n };\r\n var textHeight = TextMeasurementService.estimateSvgTextHeight(textProperties);\r\n var selectionManager = this.selectiionManager;\r\n\r\n this.svgText.style({\r\n 'fill': viewModel.color,\r\n 'font-size': textProperties.fontSize,\r\n 'font-family': textProperties.fontFamily,\r\n }).attr({\r\n 'y': viewport.height / 2 + textHeight / 3 + 'px',\r\n 'x': viewport.width / 2,\r\n }).text(viewModel.text)\r\n .on('click', function () {\r\n selectionManager\r\n .select(viewModel.selector)\r\n .then(ids => d3.select(this).style('stroke-width', ids.length > 0 ? '2px' : '0px'));\r\n })\r\n .data([viewModel]);\r\n\r\n TooltipManager.addTooltip(this.svgText, (tooltipEvent: TooltipEvent) => tooltipEvent.data.toolTipInfo);\r\n }\r\n\r\n private static getFill(dataView: DataView): Fill {\r\n if (dataView) {\r\n var objects = dataView.metadata.objects;\r\n if (objects) {\r\n var general = objects['general'];\r\n if (general) {\r\n var fill = <Fill>general['fill'];\r\n if (fill)\r\n return fill;\r\n }\r\n }\r\n }\r\n return { solid: { color: 'red' } };\r\n }\r\n\r\n private static getSize(dataView: DataView): number {\r\n if (dataView) {\r\n var objects = dataView.metadata.objects;\r\n if (objects) {\r\n var general = objects['general'];\r\n if (general) {\r\n var size = <number>general['size'];\r\n if (size)\r\n return size;\r\n }\r\n }\r\n }\r\n return 100;\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] {\r\n var instances: VisualObjectInstance[] = [];\r\n var dataView = this.dataView;\r\n switch (options.objectName) {\r\n case 'general':\r\n var general: VisualObjectInstance = {\r\n objectName: 'general',\r\n displayName: 'General',\r\n selector: null,\r\n properties: {\r\n fill: HelloIVisual.getFill(dataView),\r\n size: HelloIVisual.getSize(dataView)\r\n }\r\n };\r\n instances.push(general);\r\n break;\r\n }\r\n\r\n return instances;\r\n }\r\n\r\n public destroy(): void {\r\n this.root = null;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export interface ComboChartDataViewObjects extends DataViewObjects {\r\n general: ComboChartDataViewObject;\r\n }\r\n\r\n export interface ComboChartDataViewObject extends DataViewObject {\r\n visualType1: string;\r\n visualType2: string;\r\n }\r\n\r\n /**\r\n * This module only supplies the capabilities for comboCharts.\r\n * Implementation is in cartesianChart and the various ICartesianVisual implementations.\r\n */\r\n export module ComboChart {\r\n export const capabilities = comboChartCapabilities;\r\n\r\n /**\r\n * Handles the case of a column layer in a combo chart. In this case, the column layer is enumearated last.\r\n */\r\n export function enumerateDataPoints(enumeration: ObjectEnumerationBuilder, options: EnumerateVisualObjectInstancesOptions, layers: ICartesianVisual[]): void {\r\n if (!layers)\r\n return;\r\n\r\n let columnChartLayerIndex: number;\r\n let layersLength: number = layers.length;\r\n\r\n for (let layerIndex = 0; layerIndex < layersLength; layerIndex++) {\r\n let layer = layers[layerIndex];\r\n\r\n if (layer.enumerateObjectInstances) {\r\n if (layer instanceof ColumnChart) {\r\n columnChartLayerIndex = layerIndex;\r\n continue;\r\n }\r\n\r\n layer.enumerateObjectInstances(enumeration, options);\r\n }\r\n }\r\n\r\n if (columnChartLayerIndex !== undefined)\r\n layers[columnChartLayerIndex].enumerateObjectInstances(enumeration, options);\r\n }\r\n\r\n export function customizeQuery(options: CustomizeQueryOptions): void {\r\n // If there is a dynamic series but no values on the column data view mapping, remove the dynamic series\r\n let columnMapping = !_.isEmpty(options.dataViewMappings) && options.dataViewMappings[0];\r\n if (columnMapping) {\r\n let columnValuesMapping: data.CompiledDataViewGroupedRoleMapping = columnMapping.categorical && <data.CompiledDataViewGroupedRoleMapping>columnMapping.categorical.values;\r\n let seriesSelect = columnValuesMapping.group && !_.isEmpty(columnValuesMapping.group.select) && <data.CompiledDataViewRoleForMapping>columnValuesMapping.group.select[0];\r\n if (_.isEmpty(seriesSelect.for.in.items))\r\n columnValuesMapping.group.by.items = undefined;\r\n }\r\n\r\n if (columnMapping && columnMapping.categorical) {\r\n columnMapping.categorical.dataVolume = 4;\r\n }\r\n\r\n let lineMapping = options.dataViewMappings.length > 1 && options.dataViewMappings[1];\r\n if (lineMapping && lineMapping.categorical) {\r\n lineMapping.categorical.dataVolume = 4;\r\n }\r\n }\r\n\r\n export function getSortableRoles(options: VisualSortableOptions): string[] {\r\n if (options && options.dataViewMappings.length > 0) {\r\n let dataViewMapping = options.dataViewMappings[0];\r\n //TODO: column chart should be sortable by X if it has scalar axis\r\n // But currenly it doesn't support this. Return 'category' once\r\n // it is supported.\r\n if (!CartesianChart.detectScalarMapping(dataViewMapping))\r\n return ['Category', 'Y', 'Y2'];\r\n }\r\n\r\n return null;\r\n }\r\n\r\n export function isComboChart(chartType: CartesianChartType): boolean {\r\n return chartType === CartesianChartType.ComboChart\r\n || chartType === CartesianChartType.LineClusteredColumnCombo\r\n || chartType === CartesianChartType.LineStackedColumnCombo\r\n || chartType === CartesianChartType.DataDotClusteredColumnCombo\r\n || chartType === CartesianChartType.DataDotStackedColumnCombo;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ArrayExtensions = jsCommon.ArrayExtensions;\r\n\r\n export class DataColorPalette implements IDataColorPalette {\r\n private scales: { [index: string]: IColorScale };\r\n private colors: IColorInfo[];\r\n private sentimentColors: IColorInfo[];\r\n\r\n // Hardcoded values for Color Picker.\r\n private basePickerColors: IColorInfo[] = [\r\n { value: '#FFFFFF' },\r\n { value: '#000000' },\r\n { value: '#00B8AA' },\r\n { value: '#374649' },\r\n { value: '#FD625E' },\r\n { value: '#F2C811' },\r\n { value: '#5F6B6D' },\r\n { value: '#8AD4EB' },\r\n { value: '#FE9666' },\r\n { value: '#A66999' }\r\n ];\r\n\r\n /**\r\n * Creates a DataColorPalette using the given theme, or the default theme.\r\n */\r\n constructor(colors?: IColorInfo[], sentimentcolors?: IColorInfo[]) {\r\n // TODO: Default theme is currently hardcoded. Theme should eventually come from PV and be added as a parameter in the ctor. \r\n this.colors = colors || ThemeManager.getDefaultTheme();\r\n this.sentimentColors = sentimentcolors || ThemeManager.defaultSentimentColors;\r\n this.scales = {};\r\n }\r\n\r\n public getColorScaleByKey(key: string): IColorScale {\r\n let scale = this.scales[key];\r\n if (scale === undefined) {\r\n scale = this.createScale();\r\n this.scales[key] = scale;\r\n }\r\n\r\n return scale;\r\n }\r\n\r\n public getNewColorScale(): IColorScale {\r\n return this.createScale();\r\n }\r\n\r\n public getColorByIndex(index: number): IColorInfo {\r\n debug.assert(index >= 0 && index < this.colors.length, 'index is out of bounds');\r\n return this.colors[index];\r\n }\r\n\r\n public getSentimentColors(): IColorInfo[] {\r\n return this.sentimentColors;\r\n }\r\n\r\n public getBasePickerColors(): IColorInfo[] {\r\n return this.basePickerColors;\r\n }\r\n\r\n public getAllColors(): IColorInfo[] {\r\n return this.colors;\r\n }\r\n\r\n private createScale(): IColorScale {\r\n return D3ColorScale.createFromColors(this.colors);\r\n }\r\n }\r\n\r\n export class D3ColorScale implements IColorScale {\r\n private scale: D3.Scale.OrdinalScale;\r\n\r\n constructor(scale: D3.Scale.OrdinalScale) {\r\n this.scale = scale;\r\n }\r\n\r\n public getColor(key: any): IColorInfo {\r\n return this.scale(key);\r\n }\r\n\r\n public clearAndRotateScale(): void {\r\n let offset = this.scale.domain().length;\r\n let rotatedColors = ArrayExtensions.rotate(this.scale.range(), offset);\r\n this.scale = d3.scale.ordinal().range(rotatedColors);\r\n }\r\n\r\n public clone(): IColorScale {\r\n return new D3ColorScale(this.scale.copy());\r\n }\r\n\r\n public getDomain(): any[]{\r\n return this.scale.domain();\r\n }\r\n\r\n public static createFromColors(colors: IColorInfo[]): D3ColorScale {\r\n return new D3ColorScale(d3.scale.ordinal().range(colors));\r\n }\r\n }\r\n\r\n // TODO: When theming support is added, this should be changed into a fully fledged service. For now though we will\r\n class ThemeManager {\r\n private static colorSectorCount = 12;\r\n \r\n // declare the Theme code as a private implementation detail inside the DataColorPalette so that the code stays hidden\r\n // until it's ready for wider use.\r\n private static defaultBaseColors: IColorInfo[] = [\r\n // First loop\r\n { value: '#01B8AA' },\r\n { value: '#374649' },\r\n { value: '#FD625E' },\r\n { value: '#F2C80F' },\r\n { value: '#5F6B6D' },\r\n { value: '#8AD4EB' },\r\n { value: '#FE9666' }, // Bethany's Mango\r\n { value: '#A66999' },\r\n { value: '#3599B8' },\r\n { value: '#DFBFBF' },\r\n\r\n // Second loop\r\n { value: '#4AC5BB' },\r\n { value: '#5F6B6D' },\r\n { value: '#FB8281' },\r\n { value: '#F4D25A' },\r\n { value: '#7F898A' },\r\n { value: '#A4DDEE' },\r\n { value: '#FDAB89' },\r\n { value: '#B687AC' },\r\n { value: '#28738A' },\r\n { value: '#A78F8F' },\r\n\r\n // Third loop\r\n { value: '#168980' },\r\n { value: '#293537' },\r\n { value: '#BB4A4A' },\r\n { value: '#B59525' },\r\n { value: '#475052' },\r\n { value: '#6A9FB0' },\r\n { value: '#BD7150' },\r\n { value: '#7B4F71' },\r\n { value: '#1B4D5C' },\r\n { value: '#706060' },\r\n\r\n // Fourth loop\r\n { value: '#0F5C55' },\r\n { value: '#1C2325' },\r\n { value: '#7D3231' },\r\n { value: '#796419' },\r\n { value: '#303637' },\r\n { value: '#476A75' },\r\n { value: '#7E4B36' },\r\n { value: '#52354C' },\r\n { value: '#0D262E' },\r\n { value: '#544848' },\r\n ];\r\n\r\n private static defaultTheme: IColorInfo[];\r\n \r\n public static defaultSentimentColors: IColorInfo[] = [\r\n { value: '#C0433A' }, // Red\r\n { value: '#E8D62E' }, // Yellow\r\n { value: '#79C75B' }, // Green\r\n ];\r\n\r\n public static getDefaultTheme(): IColorInfo[] {\r\n if (!ThemeManager.defaultTheme) {\r\n // Extend the list of available colors by cycling the base colors\r\n ThemeManager.defaultTheme = [];\r\n let baseColors = ThemeManager.defaultBaseColors;\r\n for (let i = 0; i < ThemeManager.colorSectorCount; ++i) {\r\n for (let j = 0, jlen = baseColors.length; j < jlen; ++j) {\r\n ThemeManager.defaultTheme.push(\r\n {\r\n value: jsCommon.Color.rotate(baseColors[j].value, i / ThemeManager.colorSectorCount)\r\n });\r\n }\r\n }\r\n }\r\n\r\n return ThemeManager.defaultTheme;\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\n/**\r\n * IMPORTANT: This chart is not currently enabled in the PBI system and is under development.\r\n */\r\nmodule powerbi.visuals {\r\n\r\n export interface IDataDotChartConfiguration {\r\n xAxisProperties: IAxisProperties;\r\n yAxisProperties: IAxisProperties;\r\n margin: any;\r\n }\r\n\r\n export interface DataDotChartData {\r\n series: DataDotChartSeries;\r\n hasHighlights: boolean;\r\n hasDynamicSeries: boolean;\r\n }\r\n\r\n export interface DataDotChartSeries extends CartesianSeries {\r\n xCol: DataViewMetadataColumn;\r\n yCol: DataViewMetadataColumn;\r\n data: DataDotChartDataPoint[]; //overridden type of array \r\n }\r\n\r\n export interface DataDotChartDataPoint extends CartesianDataPoint, SelectableDataPoint {\r\n highlight: boolean;\r\n }\r\n\r\n export interface DataDotChartConstructorOptions extends CartesianVisualConstructorOptions {\r\n }\r\n\r\n /**\r\n * The data dot chart shows a set of circles with the data value inside them.\r\n * The circles are regularly spaced similar to column charts.\r\n * The radius of all dots is the same across the chart.\r\n * This is most often combined with a column chart to create the 'chicken pox' chart.\r\n * If any of the data values do not fit within the circles, then the data values are hidden\r\n * and the y axis for the dots is displayed instead.\r\n * This chart only supports a single series of data.\r\n * This chart does not display a legend.\r\n */\r\n export class DataDotChart implements ICartesianVisual {\r\n public static formatStringProp: DataViewObjectPropertyIdentifier = { objectName: 'general', propertyName: 'formatString' };\r\n private static ClassName = 'dataDotChart';\r\n\r\n private static DotClassName = 'dot';\r\n private static DotClassSelector = '.dot';\r\n private static DotColorKey = 'dataDot';\r\n\r\n private static DotLabelClassName = 'label';\r\n private static DotLabelClassSelector = '.label';\r\n private static DotLabelVerticalOffset = '0.4em';\r\n private static DotLabelTextAnchor = 'middle';\r\n\r\n private options: CartesianVisualInitOptions;\r\n\r\n // Chart properties\r\n private svg: D3.Selection;\r\n private element: JQuery;\r\n private mainGraphicsG: D3.Selection;\r\n private mainGraphicsContext: D3.Selection;\r\n private currentViewport: IViewport;\r\n private hostService: IVisualHostServices;\r\n private cartesianVisualHost: ICartesianVisualHost;\r\n private style: IVisualStyle;\r\n private colors: IDataColorPalette;\r\n private isScrollable: boolean;\r\n\r\n // Cartesian chart properties\r\n private xAxisProperties: IAxisProperties;\r\n private yAxisProperties: IAxisProperties;\r\n private margin;\r\n\r\n // Data properties\r\n private data: DataDotChartData;\r\n private dataViewCategorical: DataViewCategorical;\r\n private clippedData: DataDotChartData;\r\n\r\n // Interactivity properties\r\n private interactivityService: IInteractivityService;\r\n private interactivity: InteractivityOptions;\r\n\r\n constructor(options: DataDotChartConstructorOptions) {\r\n this.isScrollable = options.isScrollable;\r\n this.interactivityService = options.interactivityService;\r\n }\r\n\r\n public init(options: CartesianVisualInitOptions): void {\r\n this.options = options;\r\n\r\n // Common properties\r\n this.svg = options.svg;\r\n this.svg.classed(DataDotChart.ClassName, true);\r\n this.mainGraphicsG = this.svg.append('g')\r\n .classed('dataDotChartMainGraphicsContext', true);\r\n this.mainGraphicsContext = this.mainGraphicsG.append('svg');\r\n this.currentViewport = options.viewport;\r\n this.hostService = options.host;\r\n this.cartesianVisualHost = options.cartesianHost;\r\n this.style = options.style;\r\n this.colors = this.style.colorPalette.dataColors;\r\n\r\n // Interactivity properties\r\n this.interactivity = options.interactivity;\r\n\r\n this.element = options.element;\r\n }\r\n\r\n public setData(dataViews: DataView[]): void {\r\n this.data = {\r\n series: <DataDotChartSeries>{\r\n data: <DataDotChartDataPoint[]>[]\r\n },\r\n hasHighlights: false,\r\n hasDynamicSeries: false,\r\n };\r\n\r\n if (dataViews.length > 0) {\r\n\r\n // I only handle a single data view\r\n let dataView = dataViews[0];\r\n if (dataView && dataView.categorical) {\r\n\r\n let dataViewCategorical = this.dataViewCategorical = dataView.categorical;\r\n let dvCategories = dataViewCategorical.categories;\r\n\r\n // I default to text unless there is a category type\r\n let categoryType = ValueType.fromDescriptor({ text: true });\r\n if (dvCategories && dvCategories.length > 0 && dvCategories[0].source && dvCategories[0].source.type)\r\n categoryType = <ValueType>dvCategories[0].source.type;\r\n\r\n this.data = DataDotChart.converter(dataView, valueFormatter.format(null), this.interactivityService);\r\n }\r\n }\r\n }\r\n\r\n public setFilteredData(startIndex: number, endIndex: number): any {\r\n let data = this.clippedData = Prototype.inherit(this.data);\r\n\r\n if (data && data.series && data.series.data)\r\n data.series = { data: data.series.data.slice(startIndex, endIndex), xCol: data.series.xCol, yCol: data.series.yCol };\r\n\r\n return data;\r\n }\r\n\r\n public calculateAxesProperties(options: CalculateScaleAndDomainOptions): IAxisProperties[] {\r\n this.currentViewport = options.viewport;\r\n this.margin = options.margin;\r\n\r\n let data = this.clippedData = this.data;\r\n let viewport = this.currentViewport;\r\n let margin = this.margin;\r\n let series: DataDotChartSeries = data ? data.series : null;\r\n let seriesArray = series && series.data && series.data.length > 0 ? [series] : [];\r\n let categoryCount = series && series.data ? series.data.length : 0;\r\n\r\n // If there are highlights, then the series is 2x in length and highlights are interwoven.\r\n if (data.hasHighlights) {\r\n categoryCount = categoryCount / 2;\r\n }\r\n\r\n let width = viewport.width - (margin.left + margin.right);\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n\r\n let xMetaDataColumn: DataViewMetadataColumn;\r\n let yMetaDataColumn: DataViewMetadataColumn;\r\n\r\n if (DataDotChart.hasDataPoint(series)) {\r\n xMetaDataColumn = series.xCol;\r\n yMetaDataColumn = series.yCol;\r\n }\r\n\r\n let layout = CartesianChart.getLayout(\r\n null,\r\n {\r\n availableWidth: width,\r\n categoryCount: categoryCount,\r\n domain: null,\r\n isScalar: false,\r\n isScrollable: this.isScrollable,\r\n trimOrdinalDataOnOverflow: options.trimOrdinalDataOnOverflow\r\n });\r\n let outerPadding = layout.categoryThickness * CartesianChart.OuterPaddingRatio;\r\n\r\n // clip data that won't fit\r\n if (!this.isScrollable) {\r\n this.clippedData = DataDotChart.createClippedDataIfOverflowed(data, layout.categoryCount);\r\n }\r\n\r\n let yDomain = AxisHelper.createValueDomain(seriesArray, /*includeZero:*/ true) || emptyDomain;\r\n\r\n let combinedDomain = AxisHelper.combineDomain(options.forcedYDomain, yDomain, options.ensureYDomain);\r\n\r\n this.yAxisProperties = AxisHelper.createAxis({\r\n pixelSpan: height,\r\n dataDomain: combinedDomain,\r\n metaDataColumn: yMetaDataColumn,\r\n formatString: valueFormatter.getFormatString(yMetaDataColumn, DataDotChart.formatStringProp),\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: true,\r\n forcedTickCount: options.forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false\r\n });\r\n\r\n let axisType = this.xAxisProperties ? this.xAxisProperties.axisType : ValueType.fromDescriptor({ text: true });\r\n let xDomain = AxisHelper.createDomain(seriesArray, axisType, /*isScalar:*/ false, options.forcedXDomain, options.ensureXDomain);\r\n this.xAxisProperties = AxisHelper.createAxis({\r\n pixelSpan: width,\r\n dataDomain: xDomain,\r\n metaDataColumn: xMetaDataColumn,\r\n formatString: valueFormatter.getFormatString(xMetaDataColumn, DataDotChart.formatStringProp),\r\n outerPadding: outerPadding,\r\n isScalar: false,\r\n isVertical: false,\r\n forcedTickCount: options.forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n categoryThickness: layout.categoryThickness,\r\n getValueFn: (index, type) => this.lookupXValue(index, type),\r\n isCategoryAxis: true\r\n });\r\n\r\n return [this.xAxisProperties, this.yAxisProperties];\r\n }\r\n\r\n private static createClippedDataIfOverflowed(data: DataDotChartData, categoryCount: number): DataDotChartData {\r\n\r\n // If there are highlights, then the series is 2x in length and highlights are interwoven.\r\n let requiredLength = data.hasHighlights ? Math.min(data.series.data.length, categoryCount * 2) : Math.min(data.series.data.length, categoryCount);\r\n\r\n if (requiredLength >= data.series.data.length) {\r\n return data;\r\n }\r\n\r\n let clipped: DataDotChartData = Prototype.inherit(data);\r\n clipped.series = Prototype.inherit(data.series); // This prevents clipped and data from sharing the series object\r\n clipped.series.data = clipped.series.data.slice(0, requiredLength);\r\n return clipped;\r\n }\r\n\r\n private static hasDataPoint(series: DataDotChartSeries): boolean {\r\n return (series && series.data && series.data.length > 0);\r\n }\r\n\r\n private lookupXValue(index: number, type: ValueType): any {\r\n let data = this.data;\r\n\r\n let isDateTime = AxisHelper.isDateTime(type);\r\n if (isDateTime)\r\n return new Date(index);\r\n\r\n if (data && data.series) {\r\n let seriesData = data.series.data;\r\n\r\n if (seriesData) {\r\n let dataAtIndex = seriesData[index];\r\n if (dataAtIndex) {\r\n return dataAtIndex.categoryValue;\r\n }\r\n }\r\n }\r\n\r\n return index;\r\n }\r\n\r\n public overrideXScale(xProperties: IAxisProperties): void {\r\n this.xAxisProperties = xProperties;\r\n }\r\n\r\n public render(suppressAnimations: boolean): CartesianVisualRenderResult {\r\n if (!this.clippedData)\r\n return;\r\n let data = this.clippedData;\r\n let dataPoints = data.series.data;\r\n let hasHighlights = data.hasHighlights;\r\n\r\n let margin = this.margin;\r\n let viewport = this.currentViewport;\r\n let width = viewport.width - (margin.left + margin.right);\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n let xScale = <D3.Scale.OrdinalScale>this.xAxisProperties.scale;\r\n let yScale = this.yAxisProperties.scale;\r\n let dotWidth = this.xAxisProperties.categoryThickness * (1 - CartesianChart.InnerPaddingRatio);\r\n let dotRadius = dotWidth / 2;\r\n let dotColor = this.cartesianVisualHost.getSharedColors().getNewColorScale().getColor(DataDotChart.DotColorKey);\r\n\r\n let hasSelection = this.interactivityService ? this.interactivityService.hasSelection() : false;\r\n\r\n this.mainGraphicsContext.attr('width', width)\r\n .attr('height', height);\r\n\r\n let dots = this.mainGraphicsContext.selectAll(DataDotChart.DotClassSelector).data(dataPoints, d => d.identity.getKey());\r\n\r\n dots.enter()\r\n .append('circle')\r\n .classed(DataDotChart.DotClassName, true);\r\n\r\n dots\r\n .style({ 'fill': dotColor.value })\r\n .style('fill-opacity', (d: DataDotChartDataPoint) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights))\r\n .classed('null-value', (d: DataDotChartDataPoint) => d.value === null)\r\n .attr({\r\n r: (d: DataDotChartDataPoint) => dotRadius,\r\n cx: d => xScale(d.categoryIndex) + dotRadius,\r\n cy: d => yScale(d.value)\r\n });\r\n\r\n dots.exit().remove();\r\n\r\n let dotLabels = this.mainGraphicsContext.selectAll(DataDotChart.DotLabelClassSelector).data(dataPoints, d => d.identity.getKey());\r\n\r\n dotLabels.enter()\r\n .append('text')\r\n .classed(DataDotChart.DotLabelClassName, true)\r\n .attr({\r\n 'text-anchor': DataDotChart.DotLabelTextAnchor,\r\n dy: DataDotChart.DotLabelVerticalOffset\r\n });\r\n\r\n dotLabels\r\n .classed('null-value', (d: DataDotChartDataPoint) => d.value === null)\r\n .classed('overflowed', false)\r\n .attr({\r\n x: d => xScale(d.categoryIndex) + dotRadius,\r\n y: d => yScale(d.value)\r\n })\r\n .text(d => this.yAxisProperties.formatter.format(d.value));\r\n\r\n let overflowed = false;\r\n dotLabels\r\n .each(function () {\r\n // jQuery fails to properly inspect SVG class elements, the $('<div>') notation works around it.\r\n if (!overflowed && !$(\"<div>\").addClass($(this).attr(\"class\")).hasClass(\"null-value\")) {\r\n let width = TextMeasurementService.measureSvgTextElementWidth(this);\r\n if (width > dotWidth) {\r\n dotLabels.classed('overflowed', true);\r\n overflowed = true;\r\n }\r\n }\r\n });\r\n\r\n dotLabels.exit().remove();\r\n let behaviorOptions: DataDotChartBehaviorOptions = undefined;\r\n if (this.interactivityService) {\r\n behaviorOptions = {\r\n dots: dots,\r\n dotLabels: dotLabels,\r\n datapoints: dataPoints\r\n };\r\n } \r\n\r\n // This should always be the last line in the render code.\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n\r\n return { dataPoints: dataPoints, behaviorOptions: behaviorOptions, labelDataPoints: [], labelsAreNumeric: true };\r\n }\r\n\r\n public calculateLegend(): LegendData {\r\n return this.createLegendDataPoints(0); // start with index 0\r\n }\r\n\r\n public hasLegend(): boolean {\r\n return this.data && this.data.hasDynamicSeries;\r\n }\r\n\r\n private createLegendDataPoints(columnIndex: number): LegendData {\r\n let data = this.data;\r\n if (!data)\r\n return null;\r\n\r\n let series = data.series;\r\n let seriesData = series.data;\r\n\r\n let legendDataPoints: LegendDataPoint[] = [];\r\n let category: any;\r\n\r\n let axisType = this.xAxisProperties ? this.xAxisProperties.axisType : ValueType.fromDescriptor({ text: true });\r\n\r\n // Category will be the same for all series. This is an optimization.\r\n if (data.series && data.series.data) {\r\n let firstDataPoint: DataDotChartDataPoint = data.series.data[0];\r\n category = firstDataPoint && this.lookupXValue(firstDataPoint.categoryValue, axisType);\r\n }\r\n\r\n // Create a legend data point for the specified column \r\n if (series.yCol) {\r\n\r\n let formatStringProp = DataDotChart.formatStringProp;\r\n let lineDataPoint = seriesData[columnIndex];\r\n let measure = lineDataPoint && lineDataPoint.value;\r\n\r\n let label = converterHelper.getFormattedLegendLabel(series.yCol, this.dataViewCategorical.values, formatStringProp);\r\n\r\n let dotColor = this.cartesianVisualHost.getSharedColors().getNewColorScale().getColor(DataDotChart.DotColorKey);\r\n let dataViewCategoricalValues = this.dataViewCategorical.values;\r\n let identity = dataViewCategoricalValues && dataViewCategoricalValues.length > columnIndex ?\r\n SelectionId.createWithIdAndMeasure(dataViewCategoricalValues[columnIndex].identity, dataViewCategoricalValues[columnIndex].source.queryName) :\r\n SelectionId.createWithMeasure(dataViewCategoricalValues.source.queryName);\r\n legendDataPoints.push({\r\n color: dotColor.value,\r\n icon: LegendIcon.Line,\r\n label: label,\r\n category: valueFormatter.format(category, valueFormatter.getFormatString(series.xCol, formatStringProp)),\r\n measure: valueFormatter.format(measure, valueFormatter.getFormatString(series.yCol, formatStringProp)),\r\n identity: identity,\r\n selected: false\r\n });\r\n }\r\n\r\n return { dataPoints: legendDataPoints };\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService)\r\n this.interactivityService.clearSelection();\r\n\r\n // cartesianChart handles calling render again.\r\n }\r\n\r\n public static converter(dataView: DataView, blankCategoryValue: string, interactivityService: IInteractivityService): DataDotChartData {\r\n let categorical = dataView.categorical;\r\n\r\n let category: DataViewCategoryColumn = categorical.categories && categorical.categories.length > 0\r\n ? categorical.categories[0]\r\n : {\r\n source: undefined,\r\n values: [blankCategoryValue],\r\n identity: undefined\r\n };\r\n\r\n let categoryType: ValueTypeDescriptor = AxisHelper.getCategoryValueType(category.source);\r\n let isDateTime = AxisHelper.isDateTime(categoryType);\r\n let categoryValues = category.values;\r\n\r\n // I only handle a single series\r\n if (!_.isEmpty(categorical.values)) {\r\n let measure = categorical.values[0];\r\n\r\n let hasHighlights: boolean = !!measure.highlights;\r\n\r\n let dataPoints: DataDotChartDataPoint[] = [];\r\n for (let categoryIndex = 0, len = measure.values.length; categoryIndex < len; categoryIndex++) {\r\n\r\n debug.assert(!category.identity || categoryIndex < category.identity.length, 'Category identities is smaller than category values.');\r\n\r\n // I create the identity from the category. If there is no category, then I use the measure name to create identity\r\n let identity = category.identity ?\r\n SelectionId.createWithIdAndMeasure(category.identity[categoryIndex], measure.source.queryName) :\r\n SelectionId.createWithMeasure(measure.source.queryName);\r\n\r\n let categoryValue = categoryValues[categoryIndex];\r\n\r\n // ignore variant measures\r\n if (isDateTime && categoryValue != null && !(categoryValue instanceof Date))\r\n continue;\r\n\r\n dataPoints.push({\r\n categoryValue: isDateTime && categoryValue ? categoryValue.getTime() : categoryValue,\r\n value: measure.values[categoryIndex],\r\n categoryIndex: categoryIndex,\r\n seriesIndex: 0,\r\n selected: false,\r\n identity: identity,\r\n highlight: false\r\n });\r\n\r\n if (hasHighlights) {\r\n\r\n let highlightIdentity = SelectionId.createWithHighlight(identity);\r\n let highlightValue = measure.highlights[categoryIndex];\r\n\r\n dataPoints.push({\r\n categoryValue: isDateTime && categoryValue ? categoryValue.getTime() : categoryValue,\r\n value: highlightValue,\r\n categoryIndex: categoryIndex,\r\n seriesIndex: 0,\r\n selected: false,\r\n identity: highlightIdentity,\r\n highlight: true\r\n });\r\n }\r\n }\r\n\r\n if (interactivityService)\r\n interactivityService.applySelectionStateToData(dataPoints);\r\n\r\n return {\r\n series: {\r\n xCol: category.source,\r\n yCol: measure.source,\r\n data: dataPoints\r\n },\r\n hasHighlights: hasHighlights,\r\n hasDynamicSeries: true,\r\n };\r\n }\r\n\r\n return {\r\n series: <DataDotChartSeries> {\r\n data: <DataDotChartDataPoint[]>[]\r\n },\r\n hasHighlights: false,\r\n hasDynamicSeries: false,\r\n };\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface FunnelChartConstructorOptions {\r\n animator?: IFunnelAnimator;\r\n funnelSmallViewPortProperties?: FunnelSmallViewPortProperties;\r\n behavior?: FunnelWebBehavior;\r\n tooltipsEnabled?: boolean;\r\n }\r\n\r\n export interface FunnelPercent {\r\n value: number;\r\n percent: number;\r\n isTop: boolean;\r\n }\r\n\r\n /**\r\n * value and highlightValue may be modified in the converter to\r\n * allow rendering non-standard values, such as negatives.\r\n * Store the original values for non-rendering, user-facing elements\r\n * e.g. data labels\r\n */\r\n export interface FunnelSlice extends SelectableDataPoint, TooltipEnabledDataPoint, LabelEnabledDataPoint {\r\n value: number;\r\n originalValue: number;\r\n label: string;\r\n key: string;\r\n categoryOrMeasureIndex: number;\r\n highlight?: boolean;\r\n highlightValue?: number;\r\n originalHighlightValue?: number;\r\n color: string;\r\n }\r\n\r\n export interface FunnelData {\r\n slices: FunnelSlice[];\r\n categoryLabels: string[];\r\n valuesMetadata: DataViewMetadataColumn[];\r\n hasHighlights: boolean;\r\n highlightsOverflow: boolean;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n percentBarLabelSettings: VisualDataLabelsSettings;\r\n canShowDataLabels: boolean;\r\n hasNegativeValues: boolean;\r\n allValuesAreNegative: boolean;\r\n }\r\n\r\n export interface FunnelAxisOptions {\r\n maxScore: number;\r\n valueScale: D3.Scale.LinearScale;\r\n categoryScale: D3.Scale.OrdinalScale;\r\n maxWidth: number;\r\n margin: IMargin;\r\n rangeStart: number;\r\n rangeEnd: number;\r\n barToSpaceRatio: number;\r\n categoryLabels: string[];\r\n }\r\n\r\n export interface IFunnelLayout {\r\n percentBarLayout: {\r\n mainLine: {\r\n x2: (d: FunnelPercent) => number;\r\n transform: (d: FunnelPercent) => string;\r\n },\r\n leftTick: {\r\n y2: (d: FunnelPercent) => number;\r\n transform: (d: FunnelPercent) => string;\r\n },\r\n rightTick: {\r\n y2: (d: FunnelPercent) => number;\r\n transform: (d: FunnelPercent) => string;\r\n },\r\n text: {\r\n x: (d: FunnelPercent) => number;\r\n y: (d: FunnelPercent) => number;\r\n style: () => string;\r\n transform: (d: FunnelPercent) => string;\r\n fill: string;\r\n maxWidth: number,\r\n },\r\n };\r\n shapeLayout: {\r\n width: (d: FunnelSlice) => number;\r\n height: (d: FunnelSlice) => number;\r\n x: (d: FunnelSlice) => number;\r\n y: (d: FunnelSlice) => number;\r\n };\r\n shapeLayoutWithoutHighlights: {\r\n width: (d: FunnelSlice) => number;\r\n height: (d: FunnelSlice) => number;\r\n x: (d: FunnelSlice) => number;\r\n y: (d: FunnelSlice) => number;\r\n };\r\n zeroShapeLayout: {\r\n width: (d: FunnelSlice) => number;\r\n height: (d: FunnelSlice) => number;\r\n x: (d: FunnelSlice) => number;\r\n y: (d: FunnelSlice) => number;\r\n };\r\n interactorLayout: {\r\n width: (d: FunnelSlice) => number;\r\n height: (d: FunnelSlice) => number;\r\n x: (d: FunnelSlice) => number;\r\n y: (d: FunnelSlice) => number;\r\n };\r\n }\r\n\r\n export interface IFunnelChartSelectors {\r\n funnel: {\r\n bars: ClassAndSelector;\r\n highlights: ClassAndSelector;\r\n interactors: ClassAndSelector;\r\n };\r\n percentBar: {\r\n root: ClassAndSelector;\r\n mainLine: ClassAndSelector;\r\n leftTick: ClassAndSelector;\r\n rightTick: ClassAndSelector;\r\n text: ClassAndSelector;\r\n };\r\n }\r\n\r\n export interface FunnelSmallViewPortProperties {\r\n hideFunnelCategoryLabelsOnSmallViewPort: boolean;\r\n minHeightFunnelCategoryLabelsVisible: number;\r\n }\r\n\r\n /**\r\n * Renders a funnel chart.\r\n */\r\n export class FunnelChart implements IVisual {\r\n public static DefaultBarOpacity = 1;\r\n public static DimmedBarOpacity = 0.4;\r\n public static PercentBarToBarRatio = 0.75;\r\n public static TickPadding = 0;\r\n public static InnerTickSize = 0;\r\n public static MinimumInteractorSize = 15;\r\n public static InnerTextClassName = 'labelSeries';\r\n public static Selectors: IFunnelChartSelectors = {\r\n funnel: {\r\n bars: createClassAndSelector('funnelBar'),\r\n highlights: createClassAndSelector('highlight'),\r\n interactors: createClassAndSelector('funnelBarInteractor'),\r\n },\r\n percentBar: {\r\n root: createClassAndSelector('percentBars'),\r\n mainLine: createClassAndSelector('mainLine'),\r\n leftTick: createClassAndSelector('leftTick'),\r\n rightTick: createClassAndSelector('rightTick'),\r\n text: createClassAndSelector('value'),\r\n },\r\n };\r\n public static FunnelBarHighlightClass = [FunnelChart.Selectors.funnel.bars.class, FunnelChart.Selectors.funnel.highlights.class].join(' ');\r\n public static YAxisPadding = 10;\r\n\r\n private static VisualClassName = 'funnelChart';\r\n private static DefaultFontFamily = 'wf_standard-font';\r\n private static BarToSpaceRatio = 0.1;\r\n private static MaxBarHeight = 40;\r\n private static MinBarThickness = 12;\r\n private static LabelFunnelPadding = 6;\r\n private static InnerTextMinimumPadding = 10;\r\n private static OverflowingHighlightWidthRatio = 0.5;\r\n private static MaxMarginFactor = 0.25;\r\n\r\n private svg: D3.Selection;\r\n private funnelGraphicsContext: D3.Selection;\r\n private percentGraphicsContext: D3.Selection;\r\n private clearCatcher: D3.Selection;\r\n private axisGraphicsContext: D3.Selection;\r\n private currentViewport: IViewport;\r\n private colors: IDataColorPalette;\r\n private data: FunnelData;\r\n private hostServices: IVisualHostServices;\r\n private margin: IMargin;\r\n private options: VisualInitOptions;\r\n private interactivityService: IInteractivityService;\r\n private behavior: FunnelWebBehavior;\r\n private defaultDataPointColor: string;\r\n private labelPositionObjects: string[] = [labelPosition.outsideEnd, labelPosition.insideCenter];\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n private dataViews: DataView[];\r\n private funnelSmallViewPortProperties: FunnelSmallViewPortProperties;\r\n private tooltipsEnabled: boolean;\r\n\r\n /**\r\n * Note: Public for testing.\r\n */\r\n public animator: IFunnelAnimator;\r\n\r\n constructor(options?: FunnelChartConstructorOptions) {\r\n if (options) {\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n if (options.funnelSmallViewPortProperties) {\r\n this.funnelSmallViewPortProperties = options.funnelSmallViewPortProperties;\r\n }\r\n if (options.animator) {\r\n this.animator = options.animator;\r\n }\r\n if (options.behavior) {\r\n this.behavior = options.behavior;\r\n }\r\n }\r\n }\r\n\r\n private static isValidValueColumn(valueColumn: DataViewValueColumn): boolean {\r\n debug.assertValue(valueColumn, 'valueColumn');\r\n return DataRoleHelper.hasRole(valueColumn.source, 'Y');\r\n }\r\n\r\n private static getFirstValidValueColumn(values: DataViewValueColumns): DataViewValueColumn {\r\n for (let valueColumn of values) {\r\n if (!FunnelChart.isValidValueColumn(valueColumn))\r\n continue;\r\n return valueColumn;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n public static converter(dataView: DataView, colors: IDataColorPalette, hostServices: IVisualHostServices, defaultDataPointColor?: string, tooltipsEnabled: boolean = true): FunnelData {\r\n let slices: FunnelSlice[] = [];\r\n let formatStringProp = funnelChartProps.general.formatString;\r\n let categorical: DataViewCategorical = dataView.categorical;\r\n let categories = categorical.categories || [];\r\n let values = categorical.values;\r\n let valueMetaData: DataViewMetadataColumn[] = [];\r\n if (values) {\r\n valueMetaData = _.map(values, (v) => { return v.source; });\r\n }\r\n let hasHighlights = values && values.length > 0 && values[0] && !!values[0].highlights;\r\n let highlightsOverflow = false;\r\n let hasNegativeValues = false;\r\n let allValuesAreNegative = false;\r\n let categoryLabels = [];\r\n let dataLabelsSettings: VisualDataLabelsSettings = dataLabelUtils.getDefaultFunnelLabelSettings();\r\n let percentBarLabelSettings: VisualDataLabelsSettings = dataLabelUtils.getDefaultLabelSettings(true);\r\n let colorHelper = new ColorHelper(colors, funnelChartProps.dataPoint.fill, defaultDataPointColor);\r\n let firstValue: number;\r\n let firstHighlight: number;\r\n let previousValue: number;\r\n let previousHighlight: number;\r\n let gradientValueColumn: DataViewValueColumn = GradientUtils.getGradientValueColumn(categorical);\r\n\r\n if (dataView && dataView.metadata && dataView.metadata.objects) {\r\n let labelsObj = <DataLabelObject>dataView.metadata.objects['labels'];\r\n if (labelsObj)\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\r\n\r\n let percentLabelsObj = <DataLabelObject>dataView.metadata.objects['percentBarLabel'];\r\n if (percentLabelsObj)\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(percentLabelsObj, percentBarLabelSettings);\r\n }\r\n\r\n // Always take the first valid value field\r\n let firstValueColumn = !_.isEmpty(values) && FunnelChart.getFirstValidValueColumn(values);\r\n \r\n // If we don't have a valid value column, just return\r\n if (!firstValueColumn)\r\n return {\r\n slices: slices,\r\n categoryLabels: categoryLabels,\r\n valuesMetadata: valueMetaData,\r\n hasHighlights: hasHighlights,\r\n highlightsOverflow: highlightsOverflow,\r\n canShowDataLabels: true,\r\n dataLabelsSettings: dataLabelsSettings,\r\n hasNegativeValues: hasNegativeValues,\r\n allValuesAreNegative: allValuesAreNegative,\r\n percentBarLabelSettings: percentBarLabelSettings,\r\n };\r\n\r\n // Calculate the first value for percent tooltip values\r\n firstValue = firstValueColumn.values[0];\r\n if (hasHighlights) {\r\n firstHighlight = firstValueColumn.highlights[0];\r\n }\r\n let pctFormatString = valueFormatter.getLocalizedString('Percentage');\r\n\r\n if (categories.length === 1) {\r\n // Single Category, Value and (optional) Gradient\r\n let category = categories[0];\r\n let categoryValues = category.values;\r\n\r\n for (let i = 0, ilen = categoryValues.length; i < ilen; i++) {\r\n let measureName = firstValueColumn.source.queryName;\r\n\r\n let identity = SelectionIdBuilder.builder()\r\n .withCategory(category, i)\r\n .withMeasure(measureName)\r\n .createSelectionId();\r\n\r\n let value = firstValueColumn.values[i];\r\n let formattedCategoryValue = converterHelper.formatFromMetadataColumn(categoryValues[i], category.source, formatStringProp);\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n \r\n tooltipInfo.push({\r\n displayName: category.source.displayName,\r\n value: formattedCategoryValue,\r\n });\r\n\r\n if (value != null) {\r\n tooltipInfo.push({\r\n displayName: firstValueColumn.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(value, firstValueColumn.source, formatStringProp),\r\n });\r\n }\r\n\r\n let highlightValue: number;\r\n if (hasHighlights) {\r\n highlightValue = firstValueColumn.highlights[i];\r\n if (highlightValue != null) {\r\n tooltipInfo.push({\r\n displayName: ToolTipComponent.localizationOptions.highlightedValueDisplayName,\r\n value: converterHelper.formatFromMetadataColumn(highlightValue, firstValueColumn.source, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n let gradientColumnMetadata = gradientValueColumn ? gradientValueColumn.source : undefined;\r\n if (gradientColumnMetadata && gradientColumnMetadata !== firstValueColumn.source && gradientValueColumn.values[i] != null) {\r\n tooltipInfo.push({\r\n displayName: gradientColumnMetadata.displayName,\r\n value: converterHelper.formatFromMetadataColumn(gradientValueColumn.values[i], gradientColumnMetadata, formatStringProp),\r\n });\r\n }\r\n\r\n if (hasHighlights) {\r\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstHighlight ? highlightValue / firstHighlight : null, previousHighlight ? highlightValue / previousHighlight : null, true);\r\n }\r\n else {\r\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstValue ? value / firstValue : null, previousValue ? value / previousValue : null);\r\n } \r\n }\r\n \r\n // Same color for all bars\r\n let color = colorHelper.getColorForMeasure(category.objects && category.objects[i], '');\r\n\r\n slices.push({\r\n label: formattedCategoryValue,\r\n value: value,\r\n originalValue: value,\r\n categoryOrMeasureIndex: i,\r\n identity: identity,\r\n selected: false,\r\n key: identity.getKey(),\r\n tooltipInfo: tooltipInfo,\r\n color: color,\r\n labelFill: dataLabelsSettings.labelColor,\r\n });\r\n\r\n if (hasHighlights) {\r\n let highlightIdentity = SelectionId.createWithHighlight(identity);\r\n let highlightValue = firstValueColumn.highlights[i];\r\n slices.push({\r\n label: formattedCategoryValue,\r\n value: value,\r\n originalValue: value,\r\n categoryOrMeasureIndex: i,\r\n identity: highlightIdentity,\r\n selected: false,\r\n key: highlightIdentity.getKey(),\r\n highlight: true,\r\n highlightValue: highlightValue,\r\n originalHighlightValue: highlightValue,\r\n tooltipInfo: tooltipInfo,\r\n color: color,\r\n });\r\n previousHighlight = highlightValue;\r\n }\r\n previousValue = value;\r\n }\r\n }\r\n else if (valueMetaData.length > 0 && values && values.length > 0) {\r\n // Multi-measures\r\n for (let i = 0, len = values.length; i < len; i++) {\r\n let valueColumn = values[i];\r\n\r\n if (!FunnelChart.isValidValueColumn(valueColumn))\r\n continue;\r\n\r\n let value = valueColumn.values[0];\r\n let identity = SelectionId.createWithMeasure(valueColumn.source.queryName);\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n // Same color for all bars\r\n let color = colorHelper.getColorForMeasure(valueColumn.source.objects, '');\r\n\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n\r\n if (value != null) {\r\n tooltipInfo.push({\r\n displayName: valueColumn.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(value, valueColumn.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (hasHighlights) {\r\n let highlightValue = valueColumn.highlights[0];\r\n if (highlightValue != null) {\r\n tooltipInfo.push({\r\n displayName: ToolTipComponent.localizationOptions.highlightedValueDisplayName,\r\n value: converterHelper.formatFromMetadataColumn(highlightValue, valueColumn.source, formatStringProp),\r\n });\r\n }\r\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstHighlight ? highlightValue / firstHighlight : null, previousHighlight ? highlightValue / previousHighlight : null, true);\r\n }\r\n else {\r\n FunnelChart.addFunnelPercentsToTooltip(pctFormatString, tooltipInfo, hostServices, firstValue ? value / firstValue : null, previousValue ? value / previousValue : null);\r\n }\r\n }\r\n\r\n slices.push({\r\n label: valueMetaData[i].displayName,\r\n value: value,\r\n originalValue: value,\r\n categoryOrMeasureIndex: i,\r\n identity: identity,\r\n selected: false,\r\n key: identity.getKey(),\r\n tooltipInfo: tooltipInfo,\r\n color: color,\r\n labelFill: dataLabelsSettings.labelColor,\r\n });\r\n if (hasHighlights) {\r\n let highlightIdentity = SelectionId.createWithHighlight(identity);\r\n let highlight = valueColumn.highlights[0];\r\n slices.push({\r\n label: valueMetaData[i].displayName,\r\n value: value,\r\n originalValue: value,\r\n categoryOrMeasureIndex: i,\r\n identity: highlightIdentity,\r\n key: highlightIdentity.getKey(),\r\n selected: false,\r\n highlight: true,\r\n originalHighlightValue: highlight,\r\n highlightValue: highlight,\r\n tooltipInfo: tooltipInfo,\r\n color: color,\r\n });\r\n previousHighlight = highlight;\r\n }\r\n previousValue = value;\r\n }\r\n }\r\n\r\n for (let i = 0; i < slices.length; i += hasHighlights ? 2 : 1) {\r\n let slice = slices[i];\r\n categoryLabels.push(slice.label);\r\n }\r\n\r\n // Calculate negative value warning flags\r\n allValuesAreNegative = slices.length > 0 && _.every(slices, (slice: FunnelSlice) => (slice.highlight ? slice.highlightValue <= 0 : true) && slice.value < 0);\r\n for (let slice of slices) {\r\n if (allValuesAreNegative) {\r\n slice.value = Math.abs(slice.value);\r\n if (slice.highlight)\r\n slice.highlightValue = Math.abs(slice.highlightValue);\r\n }\r\n else {\r\n let value = slice.value;\r\n let isValueNegative = value < 0;\r\n if (isValueNegative)\r\n slice.value = 0;\r\n\r\n let isHighlightValueNegative = false;\r\n if (slice.highlight) {\r\n let highlightValue = slice.highlightValue;\r\n isHighlightValueNegative = highlightValue < 0;\r\n slice.highlightValue = isHighlightValueNegative ? 0 : highlightValue;\r\n }\r\n\r\n if (!hasNegativeValues)\r\n hasNegativeValues = isValueNegative || isHighlightValueNegative;\r\n }\r\n\r\n if (slice.highlightValue > slice.value) {\r\n highlightsOverflow = true;\r\n }\r\n }\r\n\r\n return {\r\n slices: slices,\r\n categoryLabels: categoryLabels,\r\n valuesMetadata: valueMetaData,\r\n hasHighlights: hasHighlights,\r\n highlightsOverflow: highlightsOverflow,\r\n canShowDataLabels: true,\r\n dataLabelsSettings: dataLabelsSettings,\r\n hasNegativeValues: hasNegativeValues,\r\n allValuesAreNegative: allValuesAreNegative,\r\n percentBarLabelSettings: percentBarLabelSettings,\r\n };\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n\r\n switch (options.objectName) {\r\n case 'dataPoint':\r\n let dataViewCat: DataViewCategorical = this.dataViews && this.dataViews.length > 0 && this.dataViews[0] && this.dataViews[0].categorical;\r\n let hasGradientRole = GradientUtils.hasGradientRole(dataViewCat);\r\n if (!hasGradientRole) {\r\n this.enumerateDataPoints(enumeration);\r\n }\r\n break;\r\n case 'labels':\r\n let labelSettingsOptions = FunnelChart.getLabelSettingsOptions(enumeration, this.data.dataLabelsSettings, true, this.labelPositionObjects);\r\n dataLabelUtils.enumerateDataLabels(labelSettingsOptions);\r\n break;\r\n case 'percentBarLabel':\r\n let percentLabelSettingOptions = FunnelChart.getLabelSettingsOptions(enumeration, this.data.percentBarLabelSettings, false);\r\n dataLabelUtils.enumerateDataLabels(percentLabelSettingOptions);\r\n break;\r\n }\r\n\r\n return enumeration.complete();\r\n }\r\n\r\n private static getLabelSettingsOptions(enumeration: ObjectEnumerationBuilder, labelSettings: VisualDataLabelsSettings, isDataLabels: boolean, positionObject?: any): VisualDataLabelsSettingsOptions {\r\n return {\r\n enumeration: enumeration,\r\n dataLabelsSettings: labelSettings,\r\n show: true,\r\n displayUnits: isDataLabels,\r\n precision: isDataLabels,\r\n position: isDataLabels,\r\n positionObject: positionObject,\r\n fontSize: true,\r\n };\r\n }\r\n\r\n private enumerateDataPoints(enumeration: ObjectEnumerationBuilder): void {\r\n let data = this.data;\r\n if (!data)\r\n return;\r\n\r\n let slices = data.slices;\r\n\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n selector: null,\r\n properties: {\r\n defaultColor: { solid: { color: this.defaultDataPointColor || this.colors.getColorByIndex(0).value } }\r\n },\r\n });\r\n\r\n for (let i = 0; i < slices.length; i++) {\r\n let slice = slices[i];\r\n if (slice.highlight)\r\n continue;\r\n\r\n let color = slice.color;\r\n let selector = slice.identity.getSelector();\r\n let isSingleSeries = !!selector.data;\r\n\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: slice.label,\r\n selector: ColorHelper.normalizeSelector(selector, isSingleSeries),\r\n properties: {\r\n fill: { solid: { color: color } }\r\n },\r\n });\r\n }\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n this.options = options;\r\n let element = options.element;\r\n let svg = this.svg = d3.select(element.get(0))\r\n .append('svg')\r\n .classed(FunnelChart.VisualClassName, true);\r\n\r\n if (this.behavior)\r\n this.clearCatcher = appendClearCatcher(this.svg);\r\n\r\n this.currentViewport = options.viewport;\r\n this.margin = {\r\n left: 5,\r\n right: 5,\r\n top: 0,\r\n bottom: 0\r\n };\r\n let style = options.style;\r\n this.colors = style.colorPalette.dataColors;\r\n this.hostServices = options.host;\r\n if (this.behavior) {\r\n this.interactivityService = createInteractivityService(this.hostServices);\r\n }\r\n this.percentGraphicsContext = svg.append('g').classed(FunnelChart.Selectors.percentBar.root.class, true);\r\n this.funnelGraphicsContext = svg.append('g');\r\n this.axisGraphicsContext = svg.append('g');\r\n\r\n this.updateViewportProperties();\r\n }\r\n\r\n private updateViewportProperties() {\r\n let viewport = this.currentViewport;\r\n this.svg.attr('width', viewport.width)\r\n .attr('height', viewport.height);\r\n }\r\n\r\n public update(options: VisualUpdateOptions): void {\r\n debug.assertValue(options, 'options');\r\n this.data = {\r\n slices: [],\r\n categoryLabels: [],\r\n valuesMetadata: [],\r\n hasHighlights: false,\r\n highlightsOverflow: false,\r\n canShowDataLabels: true,\r\n dataLabelsSettings: dataLabelUtils.getDefaultFunnelLabelSettings(),\r\n hasNegativeValues: false,\r\n allValuesAreNegative: false,\r\n percentBarLabelSettings: dataLabelUtils.getDefaultLabelSettings(true),\r\n };\r\n\r\n let dataViews = this.dataViews = options.dataViews;\r\n this.currentViewport = options.viewport;\r\n\r\n if (dataViews && dataViews.length > 0) {\r\n let dataView = dataViews[0];\r\n\r\n if (dataView.metadata && dataView.metadata.objects) {\r\n let defaultColor = DataViewObjects.getFillColor(dataView.metadata.objects, funnelChartProps.dataPoint.defaultColor);\r\n if (defaultColor)\r\n this.defaultDataPointColor = defaultColor;\r\n }\r\n\r\n if (dataView.categorical) {\r\n this.data = FunnelChart.converter(dataView, this.colors, this.hostServices, this.defaultDataPointColor, this.tooltipsEnabled);\r\n\r\n if (this.interactivityService) {\r\n this.interactivityService.applySelectionStateToData(this.data.slices);\r\n }\r\n }\r\n\r\n let warnings = getInvalidValueWarnings(\r\n dataViews,\r\n false /*supportsNaN*/,\r\n false /*supportsNegativeInfinity*/,\r\n false /*supportsPositiveInfinity*/);\r\n\r\n if (this.data.allValuesAreNegative) {\r\n warnings.unshift(new AllNegativeValuesWarning());\r\n }\r\n else if (this.data.hasNegativeValues) {\r\n warnings.unshift(new NegativeValuesNotSupportedWarning());\r\n }\r\n\r\n this.hostServices.setWarnings(warnings);\r\n }\r\n\r\n this.updateViewportProperties();\r\n this.updateInternal(options.suppressAnimations);\r\n }\r\n\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n this.update({\r\n dataViews: options.dataViews,\r\n suppressAnimations: options.suppressAnimations,\r\n viewport: this.currentViewport\r\n });\r\n }\r\n\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n public onResizing(viewport: IViewport): void {\r\n this.currentViewport = viewport;\r\n this.update({\r\n dataViews: this.dataViews,\r\n suppressAnimations: true,\r\n viewport: this.currentViewport\r\n });\r\n }\r\n\r\n private getMaxLabelLength(labels: string[], properties: TextProperties): number {\r\n let max = 0;\r\n let textMeasurer: ITextAsSVGMeasurer = TextMeasurementService.measureSvgTextWidth;\r\n \r\n for (let i = 0, len = labels.length; i < len; i++) {\r\n properties.text = labels[i];\r\n max = Math.max(max, textMeasurer(properties));\r\n }\r\n \r\n return max + FunnelChart.LabelFunnelPadding;\r\n }\r\n\r\n private updateInternal(suppressAnimations: boolean) {\r\n if (this.data == null)\r\n return;\r\n\r\n let data = this.data;\r\n let slices = data.slices;\r\n let slicesWithoutHighlights = slices.filter((d: FunnelSlice) => !d.highlight);\r\n let isHidingPercentBars = this.isHidingPercentBars();\r\n\r\n let axisOptions = this.setUpAxis();\r\n let margin = axisOptions.margin;\r\n\r\n let funnelContext = this.funnelGraphicsContext.attr('transform',\r\n SVGUtil.translate(margin.left, margin.top));\r\n\r\n this.percentGraphicsContext.attr('transform',\r\n SVGUtil.translate(margin.left, margin.top));\r\n\r\n this.svg.style('font-family', dataLabelUtils.StandardFontFamily);\r\n\r\n let layout = FunnelChart.getLayout(data, axisOptions);\r\n let labelLayout = dataLabelUtils.getFunnelChartLabelLayout(\r\n data,\r\n axisOptions,\r\n FunnelChart.InnerTextMinimumPadding,\r\n data.dataLabelsSettings,\r\n this.currentViewport);\r\n\r\n let result: FunnelAnimationResult;\r\n let shapes: D3.UpdateSelection;\r\n let dataLabels: D3.UpdateSelection;\r\n\r\n if (this.animator && !suppressAnimations) {\r\n let animationOptions: FunnelAnimationOptions = {\r\n viewModel: data,\r\n interactivityService: this.interactivityService,\r\n layout: layout,\r\n axisGraphicsContext: this.axisGraphicsContext,\r\n shapeGraphicsContext: funnelContext,\r\n percentGraphicsContext: this.percentGraphicsContext,\r\n labelGraphicsContext: this.svg,\r\n axisOptions: axisOptions,\r\n slicesWithoutHighlights: slicesWithoutHighlights,\r\n labelLayout: labelLayout,\r\n isHidingPercentBars: isHidingPercentBars,\r\n visualInitOptions: this.options,\r\n };\r\n result = this.animator.animate(animationOptions);\r\n shapes = result.shapes;\r\n dataLabels = result.dataLabels;\r\n }\r\n if (!this.animator || suppressAnimations || result.failed) {\r\n FunnelChart.drawDefaultAxis(this.axisGraphicsContext, axisOptions, isHidingPercentBars);\r\n shapes = FunnelChart.drawDefaultShapes(data, slices, funnelContext, layout, this.interactivityService && this.interactivityService.hasSelection());\r\n FunnelChart.drawPercentBars(data, this.percentGraphicsContext, layout, isHidingPercentBars);\r\n if (data.dataLabelsSettings.show && data.canShowDataLabels) {\r\n dataLabels = dataLabelUtils.drawDefaultLabelsForFunnelChart(data.slices, this.svg, labelLayout);\r\n }\r\n else {\r\n dataLabelUtils.cleanDataLabels(this.svg);\r\n }\r\n }\r\n\r\n if (this.interactivityService) {\r\n let interactors: D3.UpdateSelection = FunnelChart.drawInteractorShapes(slices, funnelContext, layout);\r\n let behaviorOptions: FunnelBehaviorOptions = {\r\n bars: shapes,\r\n interactors: interactors,\r\n clearCatcher: this.clearCatcher,\r\n hasHighlights: data.hasHighlights,\r\n };\r\n\r\n this.interactivityService.bind(slices, this.behavior, behaviorOptions);\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(interactors, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n }\r\n }\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(shapes, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n }\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n }\r\n\r\n private getUsableVerticalSpace(): number {\r\n let categoryLabels = this.data.categoryLabels;\r\n let margin = this.margin;\r\n let verticalSpace = this.currentViewport.height - (margin.top + margin.bottom);\r\n return verticalSpace - (FunnelChart.MinBarThickness * categoryLabels.length);\r\n }\r\n\r\n private isHidingPercentBars(): boolean {\r\n let data = this.data;\r\n\r\n if (data.percentBarLabelSettings.show) {\r\n let percentBarTextHeight = this.getPercentBarTextHeight();\r\n let verticalSpace = this.getUsableVerticalSpace() - (2 * FunnelChart.MinBarThickness * FunnelChart.PercentBarToBarRatio) - (2 * percentBarTextHeight);\r\n return verticalSpace <= 0;\r\n }\r\n return true;\r\n }\r\n\r\n private isSparklines(): boolean {\r\n return this.getUsableVerticalSpace() <= 0;\r\n }\r\n\r\n private setUpAxis(): FunnelAxisOptions {\r\n let data = this.data;\r\n let slices = data.slices;\r\n let categoryLabels = data.categoryLabels;\r\n let viewport = this.currentViewport;\r\n let margin = this.margin;\r\n let isSparklines = this.isSparklines();\r\n let isHidingPercentBars = this.isHidingPercentBars();\r\n let percentBarTextHeight = isHidingPercentBars ? 0 : this.getPercentBarTextHeight();\r\n let verticalRange = viewport.height - (margin.top + margin.bottom) - (2 * percentBarTextHeight);\r\n let maxMarginFactor = FunnelChart.MaxMarginFactor;\r\n\r\n if (categoryLabels.length > 0 && isSparklines) {\r\n categoryLabels = [];\r\n data.canShowDataLabels = false;\r\n } else if (this.showCategoryLabels()) {\r\n let textProperties = FunnelChart.getTextProperties();\r\n // Get the amount of space needed for the labels, then add the minimum level of padding for the axis.\r\n let longestLabelLength = this.getMaxLabelLength(categoryLabels, textProperties);\r\n let maxLabelLength = viewport.width * maxMarginFactor;\r\n let labelLength = Math.min(longestLabelLength, maxLabelLength);\r\n margin.left = labelLength + FunnelChart.YAxisPadding;\r\n } else {\r\n categoryLabels = [];\r\n }\r\n\r\n let horizontalRange = viewport.width - (margin.left + margin.right);\r\n let barToSpaceRatio = FunnelChart.BarToSpaceRatio;\r\n let maxScore = d3.max(slices.map(d => d.value));\r\n\r\n if (data.hasHighlights) {\r\n let maxHighlight = d3.max(slices.map(d => d.highlightValue));\r\n maxScore = d3.max([maxScore, maxHighlight]);\r\n }\r\n\r\n let minScore = 0;\r\n let rangeStart = 0;\r\n let rangeEnd = verticalRange;\r\n\r\n let delta: number;\r\n if (isHidingPercentBars)\r\n delta = verticalRange - (categoryLabels.length * FunnelChart.MaxBarHeight);\r\n else\r\n delta = verticalRange - (categoryLabels.length * FunnelChart.MaxBarHeight) - (2 * FunnelChart.MaxBarHeight * FunnelChart.PercentBarToBarRatio);\r\n\r\n if (categoryLabels.length > 0 && delta > 0) {\r\n rangeStart = Math.ceil(delta / 2);\r\n rangeEnd = Math.ceil(verticalRange - delta / 2);\r\n }\r\n\r\n // Offset funnel axis start and end by percent bar text height\r\n if (!isHidingPercentBars) {\r\n rangeStart += percentBarTextHeight;\r\n rangeEnd += percentBarTextHeight;\r\n }\r\n\r\n let valueScale = d3.scale.linear()\r\n .domain([minScore, maxScore])\r\n .range([horizontalRange, 0]);\r\n let categoryScale = d3.scale.ordinal()\r\n .domain(d3.range(0, data.categoryLabels.length))\r\n .rangeBands([rangeStart, rangeEnd], barToSpaceRatio, isHidingPercentBars ? barToSpaceRatio : FunnelChart.PercentBarToBarRatio);\r\n\r\n return {\r\n margin: margin,\r\n valueScale: valueScale,\r\n categoryScale: categoryScale,\r\n maxScore: maxScore,\r\n maxWidth: horizontalRange,\r\n rangeStart: rangeStart,\r\n rangeEnd: rangeEnd,\r\n barToSpaceRatio: barToSpaceRatio,\r\n categoryLabels: categoryLabels,\r\n };\r\n }\r\n\r\n private getPercentBarTextHeight(): number {\r\n let percentBarTextProperties = FunnelChart.getTextProperties(this.data.percentBarLabelSettings.fontSize);\r\n return TextMeasurementService.estimateSvgTextHeight(percentBarTextProperties);\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService)\r\n this.interactivityService.clearSelection();\r\n }\r\n\r\n public static getLayout(data: FunnelData, axisOptions: FunnelAxisOptions): IFunnelLayout {\r\n let highlightsOverflow = data.highlightsOverflow;\r\n let categoryScale = axisOptions.categoryScale;\r\n let valueScale = axisOptions.valueScale;\r\n let maxScore = axisOptions.maxScore;\r\n let columnHeight = categoryScale.rangeBand();\r\n let percentBarTickHeight = Math.ceil(columnHeight / 2);\r\n let overFlowHighlightColumnWidth = columnHeight * FunnelChart.OverflowingHighlightWidthRatio;\r\n let overFlowHighlightOffset = overFlowHighlightColumnWidth / 2;\r\n let lastCategoryIndex = axisOptions.categoryLabels.length - 1;\r\n let horizontalDistance = Math.abs(valueScale(maxScore) - valueScale(0));\r\n let emptyHorizontalSpace = (value: number): number => (horizontalDistance - Math.abs(valueScale(value) - valueScale(0))) /2;\r\n let getMinimumShapeSize = (value: number): number => Math.max(FunnelChart.MinimumInteractorSize, Math.abs(valueScale(value) - valueScale(0)));\r\n let percentBarFontSize = PixelConverter.fromPoint(data.percentBarLabelSettings.fontSize);\r\n let percentBarTextProperties = FunnelChart.getTextProperties(data.percentBarLabelSettings.fontSize);\r\n let baselineDelta = TextMeasurementService.estimateSvgTextBaselineDelta(percentBarTextProperties);\r\n let percentBarYOffset = TextMeasurementService.estimateSvgTextHeight(percentBarTextProperties) - baselineDelta;\r\n\r\n return {\r\n percentBarLayout: {\r\n mainLine: {\r\n x2: (d: FunnelPercent) => Math.abs(valueScale(d.value) - valueScale(0)),\r\n transform: (d: FunnelPercent) => {\r\n let xOffset = valueScale(d.value) - emptyHorizontalSpace(d.value);\r\n let yOffset = d.isTop\r\n ? categoryScale(0) - percentBarTickHeight\r\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight;\r\n return SVGUtil.translate(xOffset, yOffset);\r\n },\r\n },\r\n leftTick: {\r\n y2: (d: FunnelPercent) => percentBarTickHeight,\r\n transform: (d: FunnelPercent) => {\r\n let xOffset = valueScale(d.value) - emptyHorizontalSpace(d.value);\r\n let yOffset = d.isTop\r\n ? categoryScale(0) - percentBarTickHeight - (percentBarTickHeight / 2)\r\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight - (percentBarTickHeight / 2);\r\n return SVGUtil.translate(xOffset, yOffset);\r\n },\r\n },\r\n rightTick: {\r\n y2: (d: FunnelPercent) => percentBarTickHeight,\r\n transform: (d: FunnelPercent) => {\r\n let columnOffset = valueScale(d.value) - emptyHorizontalSpace(d.value);\r\n let columnWidth = Math.abs(valueScale(d.value) - valueScale(0));\r\n let xOffset = columnOffset + columnWidth;\r\n let yOffset = d.isTop\r\n ? categoryScale(0) - percentBarTickHeight - (percentBarTickHeight / 2)\r\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight - (percentBarTickHeight / 2);\r\n return SVGUtil.translate(xOffset, yOffset);\r\n },\r\n },\r\n text: {\r\n x: (d: FunnelPercent) => Math.ceil((Math.abs(valueScale(maxScore) - valueScale(0)) / 2)),\r\n y: (d: FunnelPercent) => {\r\n return d.isTop\r\n ? -percentBarTickHeight / 2 - baselineDelta\r\n : percentBarYOffset + (percentBarTickHeight / 2);\r\n },\r\n style: () => `font-size: ${percentBarFontSize};`,\r\n transform: (d: FunnelPercent) => {\r\n let xOffset = d.isTop\r\n ? categoryScale(0) - percentBarTickHeight\r\n : categoryScale(lastCategoryIndex) + columnHeight + percentBarTickHeight;\r\n return SVGUtil.translate(0, xOffset);\r\n },\r\n fill: data.percentBarLabelSettings.labelColor,\r\n maxWidth: horizontalDistance,\r\n },\r\n },\r\n shapeLayout: {\r\n height: ((d: FunnelSlice) => d.highlight && highlightsOverflow ? overFlowHighlightColumnWidth : columnHeight),\r\n width: (d: FunnelSlice) => {\r\n return Math.abs(valueScale(FunnelChart.getFunnelSliceValue(d)) - valueScale(0));\r\n },\r\n y: (d: FunnelSlice) => {\r\n return categoryScale(d.categoryOrMeasureIndex) + (d.highlight && highlightsOverflow ? overFlowHighlightOffset : 0);\r\n },\r\n x: (d: FunnelSlice) => {\r\n let value = FunnelChart.getFunnelSliceValue(d);\r\n return valueScale(value) - emptyHorizontalSpace(value);\r\n },\r\n },\r\n shapeLayoutWithoutHighlights: {\r\n height: ((d: FunnelSlice) => columnHeight),\r\n width: (d: FunnelSlice) => {\r\n return Math.abs(valueScale(d.value) - valueScale(0));\r\n },\r\n y: (d: FunnelSlice) => {\r\n return categoryScale(d.categoryOrMeasureIndex) + (0);\r\n },\r\n x: (d: FunnelSlice) => {\r\n return valueScale(d.value) - emptyHorizontalSpace(d.value);\r\n },\r\n },\r\n zeroShapeLayout: {\r\n height: ((d: FunnelSlice) => d.highlight && highlightsOverflow ? overFlowHighlightColumnWidth : columnHeight),\r\n width: (d: FunnelSlice) => 0,\r\n y: (d: FunnelSlice) => {\r\n return categoryScale(d.categoryOrMeasureIndex) + (d.highlight && highlightsOverflow ? overFlowHighlightOffset : 0);\r\n },\r\n x: (d: FunnelSlice) => {\r\n return valueScale((valueScale.domain()[0] + valueScale.domain()[1]) / 2);\r\n },\r\n },\r\n interactorLayout: {\r\n height: ((d: FunnelSlice) => d.highlight && highlightsOverflow ? overFlowHighlightColumnWidth : columnHeight),\r\n width: (d: FunnelSlice) => getMinimumShapeSize(FunnelChart.getFunnelSliceValue(d)),\r\n y: (d: FunnelSlice) => {\r\n return categoryScale(d.categoryOrMeasureIndex) + (d.highlight && highlightsOverflow ? overFlowHighlightOffset : 0);\r\n },\r\n x: (d: FunnelSlice) => {\r\n let size = getMinimumShapeSize(FunnelChart.getFunnelSliceValue(d));\r\n return (horizontalDistance - size) / 2;\r\n },\r\n },\r\n };\r\n }\r\n\r\n public static drawDefaultAxis(graphicsContext: D3.Selection, axisOptions: FunnelAxisOptions, isHidingPercentBars: boolean): void {\r\n //Generate ordinal domain\r\n var indices = d3.range(0, axisOptions.categoryLabels.length);\r\n let xScaleForAxis = d3.scale.ordinal()\r\n .domain(indices)\r\n .rangeBands([axisOptions.rangeStart, axisOptions.rangeEnd], axisOptions.barToSpaceRatio, isHidingPercentBars ? axisOptions.barToSpaceRatio : FunnelChart.PercentBarToBarRatio);\r\n let xAxis = d3.svg.axis()\r\n .scale(xScaleForAxis)\r\n .orient(\"right\")\r\n .tickPadding(FunnelChart.TickPadding)\r\n .innerTickSize(FunnelChart.InnerTickSize)\r\n .ticks(indices.length)\r\n .tickValues(indices)\r\n .tickFormat((i) => { return axisOptions.categoryLabels[i]; }); //To output the category label\r\n graphicsContext.attr('class', 'axis hideLinesOnAxis')\r\n .attr('transform', SVGUtil.translate(0, axisOptions.margin.top))\r\n .call(xAxis);\r\n\r\n graphicsContext.selectAll('.tick')\r\n .call(tooltipUtils.tooltipUpdate, axisOptions.categoryLabels);\r\n \r\n // Subtract the padding from the margin since we can't have text there. Then shorten the labels if necessary.\r\n let leftRightMarginLimit = axisOptions.margin.left - FunnelChart.LabelFunnelPadding;\r\n graphicsContext.selectAll('.tick text')\r\n .call(AxisHelper.LabelLayoutStrategy.clip, leftRightMarginLimit, TextMeasurementService.svgEllipsis);\r\n }\r\n\r\n public static drawDefaultShapes(data: FunnelData, slices: FunnelSlice[], graphicsContext: D3.Selection, layout: IFunnelLayout, hasSelection: boolean): D3.UpdateSelection {\r\n let hasHighlights = data.hasHighlights;\r\n let columns = graphicsContext.selectAll(FunnelChart.Selectors.funnel.bars.selector).data(slices, (d: FunnelSlice) => d.key);\r\n\r\n columns.enter()\r\n .append('rect')\r\n .attr(\"class\", (d: FunnelSlice) => d.highlight ? FunnelChart.FunnelBarHighlightClass : FunnelChart.Selectors.funnel.bars.class);\r\n\r\n columns\r\n .style(\"fill\", d => {\r\n return d.color;\r\n })\r\n .style(\"fill-opacity\", d => (d: FunnelSlice) => ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, hasHighlights))\r\n .attr(layout.shapeLayout);\r\n\r\n columns.exit().remove();\r\n\r\n return columns;\r\n }\r\n\r\n public static getFunnelSliceValue(slice: FunnelSlice, asOriginal: boolean = false) {\r\n if (asOriginal)\r\n return slice.highlight ? slice.originalHighlightValue : slice.originalValue;\r\n else\r\n return slice.highlight ? slice.highlightValue : slice.value;\r\n }\r\n\r\n public static drawInteractorShapes(slices: FunnelSlice[], graphicsContext: D3.Selection, layout: IFunnelLayout): D3.UpdateSelection {\r\n // Draw invsible ineractors for just data points which are below threshold\r\n let interactorsData = slices.filter((d: FunnelSlice) => {\r\n return !d.highlight && layout.interactorLayout.width(d) === FunnelChart.MinimumInteractorSize;\r\n });\r\n \r\n let columns = graphicsContext.selectAll(FunnelChart.Selectors.funnel.interactors.selector).data(interactorsData, (d: FunnelSlice) => d.key);\r\n\r\n columns.enter()\r\n .append('rect')\r\n .attr(\"class\", FunnelChart.Selectors.funnel.interactors.class);\r\n\r\n columns\r\n .style(\"fill-opacity\", 0)\r\n .attr(layout.interactorLayout);\r\n\r\n columns.exit().remove();\r\n\r\n return columns;\r\n }\r\n\r\n private static drawPercentBarComponents(graphicsContext: D3.Selection, data: FunnelPercent[], layout: IFunnelLayout, percentLabelSettings: VisualDataLabelsSettings) {\r\n // Main line\r\n let mainLine: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.mainLine.selector).data(data);\r\n mainLine.exit().remove();\r\n mainLine.enter()\r\n .append('line')\r\n .classed(FunnelChart.Selectors.percentBar.mainLine.class, true);\r\n mainLine\r\n .attr(layout.percentBarLayout.mainLine);\r\n\r\n // Left tick\r\n let leftTick: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.leftTick.selector).data(data);\r\n leftTick.exit().remove();\r\n leftTick.enter()\r\n .append('line')\r\n .classed(FunnelChart.Selectors.percentBar.leftTick.class, true);\r\n leftTick\r\n .attr(layout.percentBarLayout.leftTick);\r\n\r\n // Right tick\r\n let rightTick: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.rightTick.selector).data(data);\r\n rightTick.exit().remove();\r\n rightTick.enter()\r\n .append('line')\r\n .classed(FunnelChart.Selectors.percentBar.rightTick.class, true);\r\n rightTick\r\n .attr(layout.percentBarLayout.rightTick);\r\n\r\n // Text\r\n let text: D3.UpdateSelection = graphicsContext.selectAll(FunnelChart.Selectors.percentBar.text.selector).data(data);\r\n let localizedString: string = valueFormatter.getLocalizedString(\"Percentage1\");\r\n text.exit().remove();\r\n text.enter().append('text').classed(FunnelChart.Selectors.percentBar.text.class, true);\r\n text\r\n .attr(layout.percentBarLayout.text)\r\n .text((fp: FunnelPercent) => {\r\n return dataLabelUtils.getLabelFormattedText({\r\n label: fp.percent,\r\n format: localizedString,\r\n fontSize: percentLabelSettings.fontSize,\r\n maxWidth: layout.percentBarLayout.text.maxWidth,\r\n });\r\n })\r\n .append('title').text((d: FunnelPercent) => formattingService.formatValue(d.percent, localizedString)); \r\n }\r\n\r\n public static drawPercentBars(data: FunnelData, graphicsContext: D3.Selection, layout: IFunnelLayout, isHidingPercentBars: boolean): void {\r\n if (isHidingPercentBars || !data.slices || (data.hasHighlights ? data.slices.length / 2 : data.slices.length) < 2) {\r\n FunnelChart.drawPercentBarComponents(graphicsContext, [], layout, data.percentBarLabelSettings);\r\n return;\r\n }\r\n\r\n let slices = [data.slices[data.hasHighlights ? 1 : 0], data.slices[data.slices.length - 1]];\r\n let baseline = FunnelChart.getFunnelSliceValue(slices[0]);\r\n\r\n if (baseline <= 0) {\r\n FunnelChart.drawPercentBarComponents(graphicsContext, [], layout, data.percentBarLabelSettings);\r\n return;\r\n }\r\n\r\n let percentData: FunnelPercent[] = [\r\n {\r\n value: FunnelChart.getFunnelSliceValue(slices[0]),\r\n percent: 1,\r\n isTop: true,\r\n },\r\n {\r\n value: FunnelChart.getFunnelSliceValue(slices[1]),\r\n percent: FunnelChart.getFunnelSliceValue(slices[1]) / baseline,\r\n isTop: false,\r\n },\r\n ];\r\n\r\n FunnelChart.drawPercentBarComponents(graphicsContext, percentData, layout, data.percentBarLabelSettings);\r\n }\r\n\r\n private showCategoryLabels(): boolean {\r\n if (this.funnelSmallViewPortProperties) {\r\n if ((this.funnelSmallViewPortProperties.hideFunnelCategoryLabelsOnSmallViewPort) && (this.currentViewport.height < this.funnelSmallViewPortProperties.minHeightFunnelCategoryLabelsVisible)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n private static addFunnelPercentsToTooltip(pctFormatString: string, tooltipInfo: TooltipDataItem[], hostServices: IVisualHostServices, percentOfFirst?: number, percentOfPrevious?: number, highlight?: boolean): void {\r\n if (percentOfFirst != null) {\r\n tooltipInfo.push({\r\n displayName: hostServices.getLocalizedString(\"Funnel_PercentOfFirst\" + (highlight ? \"_Highlight\" : \"\")),\r\n value: valueFormatter.format(percentOfFirst, pctFormatString),\r\n });\r\n }\r\n if (percentOfPrevious != null) {\r\n tooltipInfo.push({\r\n displayName: hostServices.getLocalizedString(\"Funnel_PercentOfPrevious\" + (highlight ? \"_Highlight\" : \"\")),\r\n value: valueFormatter.format(percentOfPrevious, pctFormatString),\r\n });\r\n }\r\n }\r\n\r\n private static getTextProperties(fontSize?: number): TextProperties {\r\n return {\r\n fontSize: PixelConverter.fromPoint(fontSize || dataLabelUtils.DefaultFontSizeInPt),\r\n fontFamily: FunnelChart.DefaultFontFamily,\r\n };\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface GaugeData extends TooltipEnabledDataPoint {\r\n percent: number;\r\n adjustedTotal: number;\r\n total: number;\r\n metadataColumn: DataViewMetadataColumn;\r\n targetSettings: GaugeTargetSettings;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n calloutValueLabelsSettings: VisualDataLabelsSettings;\r\n dataPointSettings: GaugeDataPointSettings;\r\n }\r\n\r\n interface KpiArcAttributes {\r\n start: number;\r\n end: number;\r\n fill: string;\r\n }\r\n\r\n export interface GaugeTargetSettings {\r\n min: number;\r\n max: number;\r\n target: number;\r\n }\r\n\r\n export interface GaugeTargetData extends GaugeTargetSettings {\r\n total: number;\r\n tooltipItems: TooltipDataItem[];\r\n }\r\n\r\n export interface GaugeDataPointSettings {\r\n fillColor: string;\r\n targetColor: string;\r\n }\r\n\r\n interface GaugeStyle {\r\n transition: {\r\n ease: string\r\n };\r\n arcColors: {\r\n background: string;\r\n foreground: string;\r\n };\r\n targetLine: {\r\n show: boolean;\r\n color: string;\r\n thickness: number;\r\n };\r\n labels: {\r\n count: number;\r\n padding: number;\r\n fontSize: number;\r\n };\r\n kpiBands: {\r\n show: boolean;\r\n separationRadians: number;\r\n thickness: number;\r\n };\r\n }\r\n\r\n export interface GaugeSmallViewPortProperties {\r\n hideGaugeSideNumbersOnSmallViewPort: boolean;\r\n smallGaugeMarginsOnSmallViewPort: boolean;\r\n MinHeightGaugeSideNumbersVisible: number;\r\n GaugeMarginsOnSmallViewPort: number;\r\n }\r\n\r\n export interface GaugeVisualProperties {\r\n radius: number;\r\n innerRadiusOfArc: number;\r\n innerRadiusFactor: number;\r\n left: number;\r\n top: number;\r\n height: number;\r\n width: number;\r\n margin: IMargin;\r\n transformString: string;\r\n }\r\n\r\n export interface AnimatedNumberProperties {\r\n transformString: string;\r\n viewport: IViewport;\r\n }\r\n\r\n export interface GaugeConstructorOptions {\r\n gaugeSmallViewPortProperties?: GaugeSmallViewPortProperties;\r\n animator?: IGenericAnimator;\r\n tooltipsEnabled?: boolean;\r\n }\r\n\r\n export interface GaugeDataViewObjects extends DataViewObjects {\r\n axis: GaugeDataViewObject;\r\n }\r\n\r\n export interface GaugeDataViewObject extends DataViewObject {\r\n min?: number;\r\n max?: number;\r\n target?: number;\r\n }\r\n\r\n /** \r\n * Renders a number that can be animate change in value.\r\n */\r\n export class Gauge implements IVisual {\r\n private static MIN_VALUE = -Infinity;\r\n private static MAX_VALUE = +Infinity;\r\n private static MinDistanceFromBottom = 10;\r\n private static MinWidthForTargetLabel = 150;\r\n private static DefaultTopBottomMargin = 20;\r\n private static DefaultLeftRightMargin = 45;\r\n private static ReducedLeftRightMargin = 15;\r\n private static DEFAULT_MAX = 1;\r\n private static DEFAULT_MIN = 0;\r\n private static VisualClassName = 'gauge';\r\n private static DefaultStyleProperties: GaugeStyle = {\r\n transition: {\r\n ease: 'bounce'\r\n },\r\n arcColors: {\r\n background: '#e9e9e9',\r\n foreground: '#00B8AA'\r\n },\r\n targetLine: {\r\n show: true,\r\n color: '#666666',\r\n thickness: 2\r\n },\r\n labels: {\r\n count: 2,\r\n padding: 5,\r\n fontSize: NewDataLabelUtils.DefaultLabelFontSizeInPt,\r\n },\r\n kpiBands: {\r\n show: false,\r\n separationRadians: Math.PI / 128,\r\n thickness: 5\r\n },\r\n };\r\n private static DefaultTargetSettings: GaugeTargetSettings = {\r\n min: 0,\r\n max: 1,\r\n target: undefined\r\n };\r\n private static DefaultDataPointSettings: GaugeDataPointSettings = {\r\n fillColor: Gauge.DefaultStyleProperties.arcColors.foreground,\r\n targetColor: Gauge.DefaultStyleProperties.targetLine.color\r\n };\r\n\r\n private static InnerRadiusFactor = 0.7;\r\n private static KpiBandDistanceFromMainArc = 2;\r\n private static MainGaugeGroupClassName = 'mainGroup';\r\n private static LabelText: ClassAndSelector = createClassAndSelector('labelText');\r\n private static TargetConnector: ClassAndSelector = createClassAndSelector('targetConnector');\r\n private static TargetText: ClassAndSelector = createClassAndSelector('targetText');\r\n\r\n /** Note: Public for testability */\r\n public static formatStringProp: DataViewObjectPropertyIdentifier = {\r\n objectName: 'general',\r\n propertyName: 'formatString',\r\n };\r\n\r\n private svg: D3.Selection;\r\n private mainGraphicsContext: D3.Selection;\r\n private currentViewport: IViewport;\r\n private element: JQuery;\r\n private style: IVisualStyle;\r\n private data: GaugeData;\r\n private color: D3.Scale.OrdinalScale;\r\n\r\n private backgroundArc: D3.Svg.Arc;\r\n private foregroundArc: D3.Svg.Arc;\r\n private kpiArcs: D3.Svg.Arc[];\r\n\r\n private kpiArcPaths: D3.Selection[];\r\n private foregroundArcPath: D3.Selection;\r\n private backgroundArcPath: D3.Selection;\r\n private targetLine: D3.Selection;\r\n private targetConnector: D3.Selection;\r\n private targetText: D3.Selection;\r\n private options: VisualInitOptions;\r\n\r\n private lastAngle = -Math.PI / 2;\r\n private margin: IMargin;\r\n private animatedNumberGrapicsContext: D3.Selection;\r\n private animatedNumber: AnimatedNumber;\r\n private settings: GaugeStyle;\r\n private targetSettings: GaugeTargetSettings;\r\n private gaugeVisualProperties: GaugeVisualProperties;\r\n private gaugeSmallViewPortProperties: GaugeSmallViewPortProperties;\r\n private showTargetLabel: boolean;\r\n\r\n private tooltipsEnabled: boolean;\r\n\r\n private hostService: IVisualHostServices;\r\n\r\n // TODO: Remove this once all visuals have implemented update.\r\n private dataViews: DataView[];\r\n\r\n public animator: IGenericAnimator;\r\n\r\n constructor(options?: GaugeConstructorOptions) {\r\n if (options) {\r\n if (options.gaugeSmallViewPortProperties) {\r\n this.gaugeSmallViewPortProperties = options.gaugeSmallViewPortProperties;\r\n }\r\n this.animator = options.animator;\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n }\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n\r\n switch (options.objectName) {\r\n case 'axis':\r\n this.enumerateAxis(enumeration);\r\n break;\r\n case 'labels': {\r\n let labelSettings = this.data ? this.data.dataLabelsSettings : dataLabelUtils.getDefaultGaugeLabelSettings();\r\n dataLabelUtils.enumerateDataLabels(this.getDataLabelSettingsOptions(enumeration, labelSettings));\r\n break;\r\n }\r\n case 'calloutValue': {\r\n let labelSettings = this.data ? this.data.calloutValueLabelsSettings : dataLabelUtils.getDefaultGaugeLabelSettings();\r\n dataLabelUtils.enumerateDataLabels(this.getDataLabelSettingsOptions(enumeration, labelSettings));\r\n break;\r\n }\r\n case 'dataPoint': {\r\n this.enumerateDataPoint(enumeration);\r\n break;\r\n }\r\n }\r\n return enumeration.complete();\r\n }\r\n\r\n private getDataLabelSettingsOptions(enumeration: ObjectEnumerationBuilder, labelSettings: VisualDataLabelsSettings): VisualDataLabelsSettingsOptions {\r\n return {\r\n dataLabelsSettings: labelSettings,\r\n show: true,\r\n precision: true,\r\n displayUnits: true,\r\n fontSize: true,\r\n enumeration: enumeration,\r\n };\r\n }\r\n\r\n private enumerateAxis(enumeration: ObjectEnumerationBuilder): void {\r\n let dataView: DataView = this.dataViews[0];\r\n\r\n if (dataView && dataView.metadata) {\r\n let properties: GaugeTargetSettings = Gauge.getGaugeObjectsProperties(dataView);\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: 'axis',\r\n properties: <any>properties,\r\n });\r\n }\r\n }\r\n\r\n private enumerateDataPoint(enumeration: ObjectEnumerationBuilder): void {\r\n let dataPointSettings = this.data ? this.data.dataPointSettings : Gauge.DefaultDataPointSettings;\r\n let properties: any = {};\r\n\r\n properties.fill = { solid: { color: dataPointSettings.fillColor } };\r\n\r\n if (dataPointSettings.targetColor != null) {\r\n properties.target = { solid: { color: dataPointSettings.targetColor } };\r\n }\r\n\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: gaugeProps.dataPoint.target.objectName,\r\n properties: properties\r\n });\r\n }\r\n\r\n private static getGaugeObjectsProperties(dataView: DataView): GaugeTargetSettings {\r\n let properties: any = {};\r\n let objects: GaugeDataViewObjects = <GaugeDataViewObjects>dataView.metadata.objects;\r\n let hasAxisObject: boolean = !!objects && !!objects.axis;\r\n\r\n if (!DataRoleHelper.hasRoleInDataView(dataView, gaugeRoleNames.minValue))\r\n properties.min = hasAxisObject ? objects.axis.min : undefined;\r\n\r\n if (!DataRoleHelper.hasRoleInDataView(dataView, gaugeRoleNames.maxValue))\r\n properties.max = hasAxisObject ? objects.axis.max : undefined;\r\n\r\n if (!DataRoleHelper.hasRoleInDataView(dataView, gaugeRoleNames.targetValue))\r\n properties.target = hasAxisObject ? objects.axis.target : undefined;\r\n\r\n return properties;\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n this.element = options.element;\r\n this.currentViewport = options.viewport;\r\n this.style = options.style;\r\n this.options = options;\r\n this.settings = Gauge.DefaultStyleProperties;\r\n this.targetSettings = Gauge.DefaultTargetSettings;\r\n\r\n this.setMargins();\r\n\r\n this.color = d3.scale.ordinal().range(\r\n this.style.colorPalette.dataColors.getSentimentColors().map(\r\n color => color.value));\r\n\r\n this.hostService = options.host;\r\n let svg = this.svg = d3.select(this.element.get(0)).append('svg');\r\n svg.classed(Gauge.VisualClassName, true);\r\n let mainGraphicsContext = this.mainGraphicsContext = svg.append('g');\r\n mainGraphicsContext.attr('class', Gauge.MainGaugeGroupClassName);\r\n\r\n this.initKpiBands();\r\n\r\n let backgroundArc = this.backgroundArc = d3.svg.arc()\r\n .innerRadius(0)\r\n .outerRadius(0)\r\n .startAngle(-Math.PI / 2)\r\n .endAngle(Math.PI / 2);\r\n\r\n let foregroundArc = this.foregroundArc = d3.svg.arc()\r\n .innerRadius(0)\r\n .outerRadius(0)\r\n .startAngle(-Math.PI / 2);\r\n\r\n this.backgroundArcPath = mainGraphicsContext.append('path')\r\n .classed('backgroundArc', true)\r\n .attr('d', backgroundArc);\r\n\r\n this.foregroundArcPath = mainGraphicsContext.append('path')\r\n .datum({ endAngle: -Math.PI / 2 })\r\n .classed('foregroundArc', true)\r\n .attr('d', foregroundArc);\r\n\r\n let g = this.animatedNumberGrapicsContext = svg.append('g');\r\n\r\n this.animatedNumber = new AnimatedNumber(g);\r\n this.animatedNumber.init(options);\r\n\r\n let gaugeDrawingOptions = this.gaugeVisualProperties = this.getGaugeVisualProperties();\r\n let animatedNumberProperties = this.getAnimatedNumberProperties(\r\n gaugeDrawingOptions.radius,\r\n gaugeDrawingOptions.innerRadiusFactor,\r\n gaugeDrawingOptions.top,\r\n gaugeDrawingOptions.left);\r\n this.animatedNumberGrapicsContext.attr('transform', animatedNumberProperties.transformString);\r\n this.animatedNumber.onResizing(animatedNumberProperties.viewport);\r\n }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n debug.assertValue(options, 'options');\r\n\r\n this.currentViewport = options.viewport;\r\n let dataViews = this.dataViews = options.dataViews;\r\n\r\n if (!dataViews || !dataViews[0]) {\r\n return;\r\n }\r\n\r\n this.data = Gauge.converter(dataViews[0], this.tooltipsEnabled);\r\n this.targetSettings = this.data.targetSettings;\r\n\r\n if (dataViews[0])\r\n dataViews[0].single = { value: this.data.total };\r\n\r\n // Only show the target label if:\r\n // 1. There is a target\r\n // 2. The viewport width is big enough for a target\r\n // 3. We're showing label text for side numbers\r\n // 4. Data label settings specify to show\r\n this.showTargetLabel = this.targetSettings.target != null\r\n && (this.currentViewport.width > Gauge.MinWidthForTargetLabel || !this.showMinMaxLabelsOnBottom())\r\n && this.showSideNumbersLabelText()\r\n && this.data.dataLabelsSettings.show;\r\n\r\n this.setMargins();\r\n\r\n this.gaugeVisualProperties = this.getGaugeVisualProperties();\r\n this.drawViewPort(this.gaugeVisualProperties);\r\n this.updateInternal(options.suppressAnimations);\r\n this.updateCalloutValue(options.suppressAnimations);\r\n\r\n let warnings = getInvalidValueWarnings(\r\n dataViews,\r\n false /*supportsNaN*/,\r\n false /*supportsNegativeInfinity*/,\r\n false /*supportsPositiveInfinity*/);\r\n\r\n this.hostService.setWarnings(warnings);\r\n }\r\n\r\n private updateCalloutValue(suppressAnimations: boolean): void {\r\n if (this.data.calloutValueLabelsSettings.show) {\r\n let animatedNumberProperties = this.getAnimatedNumberProperties(\r\n this.gaugeVisualProperties.radius,\r\n this.gaugeVisualProperties.innerRadiusFactor,\r\n this.gaugeVisualProperties.top,\r\n this.gaugeVisualProperties.left);\r\n this.animatedNumberGrapicsContext.attr('transform', animatedNumberProperties.transformString);\r\n this.animatedNumber.setTextColor(this.data.calloutValueLabelsSettings.labelColor);\r\n\r\n let calloutValue: number = this.data ? this.data.total : null;\r\n let formatter = this.getFormatter(this.data.calloutValueLabelsSettings, calloutValue);\r\n\r\n this.animatedNumber.setFormatter(formatter);\r\n this.animatedNumber.update({\r\n viewport: animatedNumberProperties.viewport,\r\n dataViews: this.dataViews,\r\n suppressAnimations: suppressAnimations,\r\n });\r\n\r\n this.animatedNumberGrapicsContext.selectAll('title').remove();\r\n this.animatedNumberGrapicsContext.append('title').text([formatter.format(calloutValue)]);\r\n }\r\n else {\r\n this.animatedNumber.clear();\r\n this.animatedNumberGrapicsContext.selectAll('title').remove();\r\n }\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n this.update({\r\n dataViews: options.dataViews,\r\n suppressAnimations: options.suppressAnimations,\r\n viewport: this.currentViewport\r\n });\r\n }\r\n\r\n public onResizing(viewport: IViewport): void {\r\n // TODO: Remove onDataChanged & onResizing once all visuals have implemented update.\r\n this.update({\r\n dataViews: this.dataViews,\r\n suppressAnimations: true,\r\n viewMode: ViewMode.View,\r\n viewport: viewport\r\n });\r\n }\r\n\r\n private static getValidSettings(targetData: GaugeTargetData): GaugeTargetSettings {\r\n let maxVal = (targetData.max === Gauge.MAX_VALUE) ? Gauge.DEFAULT_MAX : targetData.max;\r\n let minVal = (targetData.min === Gauge.MIN_VALUE) ? Gauge.DEFAULT_MIN : targetData.min;\r\n let targetVal = targetData.target;\r\n\r\n return {\r\n min: minVal,\r\n max: maxVal,\r\n target: targetVal\r\n };\r\n }\r\n\r\n private static getGaugeData(dataView: DataView): GaugeTargetData {\r\n let settings: GaugeTargetData = {\r\n max: Gauge.MAX_VALUE,\r\n min: Gauge.MIN_VALUE,\r\n target: undefined,\r\n total: 0,\r\n tooltipItems: []\r\n };\r\n\r\n if (dataView && dataView.categorical && dataView.categorical.values && dataView.metadata && dataView.metadata.columns) {\r\n let values = dataView.categorical.values;\r\n let metadataColumns = dataView.metadata.columns;\r\n\r\n debug.assert(metadataColumns.length >= values.length, 'length');\r\n\r\n for (let i = 0; i < values.length; i++) {\r\n let col = metadataColumns[i],\r\n value = values[i].values[0] || 0;\r\n if (col && col.roles) {\r\n if (col.roles[gaugeRoleNames.y]) {\r\n settings.total = value;\r\n if (value)\r\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: converterHelper.formatFromMetadataColumn(value, values[i].source, Gauge.formatStringProp) });\r\n } else if (col.roles[gaugeRoleNames.minValue]) {\r\n settings.min = value;\r\n } else if (col.roles[gaugeRoleNames.maxValue]) {\r\n settings.max = value;\r\n } else if (col.roles[gaugeRoleNames.targetValue]) {\r\n settings.target = value;\r\n if (value)\r\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: converterHelper.formatFromMetadataColumn(value, values[i].source, Gauge.formatStringProp) });\r\n }\r\n }\r\n }\r\n\r\n // Override settings according to property pane axis values\r\n let gaugeObjectsSettings: GaugeTargetSettings = Gauge.getGaugeObjectsProperties(dataView);\r\n if (gaugeObjectsSettings && !$.isEmptyObject(gaugeObjectsSettings))\r\n Gauge.overrideGaugeSettings(settings, gaugeObjectsSettings);\r\n }\r\n else {\r\n settings.tooltipItems = undefined;\r\n }\r\n\r\n return settings;\r\n }\r\n\r\n private static overrideGaugeSettings(settings: GaugeTargetData, gaugeObjectsSettings: GaugeTargetSettings) {\r\n if ($.isNumeric(gaugeObjectsSettings.min))\r\n settings.min = gaugeObjectsSettings.min;\r\n\r\n if ($.isNumeric(gaugeObjectsSettings.max))\r\n settings.max = gaugeObjectsSettings.max;\r\n\r\n if ($.isNumeric(gaugeObjectsSettings.target))\r\n settings.target = gaugeObjectsSettings.target;\r\n }\r\n \r\n /** Note: Made public for testability */\r\n public static converter(dataView: DataView, tooltipsEnabled: boolean = true): GaugeData {\r\n let gaugeData = Gauge.getGaugeData(dataView),\r\n total = gaugeData.total,\r\n formatString: string = null,\r\n hasPercent = false;\r\n\r\n if (dataView.metadata && !_.isEmpty(dataView.metadata.columns)) {\r\n formatString = valueFormatter.getFormatString(dataView.metadata.columns[0], Gauge.formatStringProp, true);\r\n if (formatString != null)\r\n hasPercent = valueFormatter.getFormatMetadata(formatString).hasPercent;\r\n }\r\n\r\n if (total > 0 && gaugeData.max === Gauge.MAX_VALUE) {\r\n gaugeData.max = hasPercent ? Gauge.DEFAULT_MAX : total * 2;\r\n }\r\n\r\n let settings: GaugeTargetSettings = Gauge.getValidSettings(gaugeData);\r\n\r\n //Checking that the value is plotted inside the gauge boundaries\r\n let adjustedTotal = Math.max(total, settings.min);\r\n adjustedTotal = Math.min(adjustedTotal, settings.max);\r\n\r\n let percent: number = (settings.min !== settings.max)\r\n ? (adjustedTotal - settings.min) / (settings.max - settings.min)\r\n : 0;\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n\r\n if (tooltipsEnabled && dataView && gaugeData.tooltipItems != null) {\r\n tooltipInfo = gaugeData.tooltipItems;\r\n }\r\n\r\n return {\r\n percent: percent,\r\n adjustedTotal: adjustedTotal,\r\n total: total,\r\n metadataColumn: Gauge.getMetaDataColumn(dataView),\r\n targetSettings: settings,\r\n tooltipInfo: tooltipInfo,\r\n dataLabelsSettings: Gauge.convertDataLabelSettings(dataView, \"labels\"),\r\n calloutValueLabelsSettings: Gauge.convertDataLabelSettings(dataView, \"calloutValue\"),\r\n dataPointSettings: Gauge.convertDataPointSettings(dataView, settings)\r\n };\r\n }\r\n\r\n private static convertDataLabelSettings(dataview: DataView, objectName: string): VisualDataLabelsSettings {\r\n let dataViewMetadata = dataview.metadata;\r\n let dataLabelsSettings = dataLabelUtils.getDefaultGaugeLabelSettings();\r\n if (dataViewMetadata) {\r\n let objects: DataViewObjects = dataViewMetadata.objects;\r\n if (objects) {\r\n // Handle label settings\r\n let labelsObj = <DataLabelObject>objects[objectName];\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\r\n }\r\n }\r\n\r\n return dataLabelsSettings;\r\n }\r\n\r\n private static convertDataPointSettings(dataView: DataView, targetSettings: GaugeTargetSettings): GaugeDataPointSettings {\r\n \r\n // Default the fill color the the default fill color. Default the target to undefined as it's only used if there's a target.\r\n let fillColor = Gauge.DefaultDataPointSettings.fillColor;\r\n let targetColor: string;\r\n\r\n if (dataView && dataView.metadata && dataView.metadata.objects) {\r\n // If there is saved metadata, use it for the colors\r\n let objects = dataView.metadata.objects;\r\n\r\n fillColor = DataViewObjects.getFillColor(objects, gaugeProps.dataPoint.fill, Gauge.DefaultDataPointSettings.fillColor);\r\n\r\n if (targetSettings && (targetSettings.target != null)) {\r\n targetColor = DataViewObjects.getFillColor(objects, gaugeProps.dataPoint.target, Gauge.DefaultDataPointSettings.targetColor);\r\n }\r\n }\r\n else if (targetSettings && (targetSettings.target != null)) {\r\n // If there isn't metadata, but a target is set, default to the default target color\r\n targetColor = Gauge.DefaultDataPointSettings.targetColor;\r\n }\r\n\r\n return {\r\n fillColor: fillColor,\r\n targetColor: targetColor\r\n };\r\n }\r\n\r\n public static getMetaDataColumn(dataView: DataView) {\r\n if (dataView && dataView.metadata && dataView.metadata.columns) {\r\n for (let i = 0, ilen = dataView.metadata.columns.length; i < ilen; i++) {\r\n let column = dataView.metadata.columns[i];\r\n if (column.isMeasure) {\r\n return column;\r\n }\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private initKpiBands() {\r\n if (!this.settings.kpiBands.show)\r\n return;\r\n let kpiArcs = this.kpiArcs = [];\r\n let kpiArcPaths = this.kpiArcPaths = [];\r\n let mainGraphicsContext = this.mainGraphicsContext;\r\n\r\n for (let i = 0; i < 3; i++) {\r\n let arc = d3.svg.arc()\r\n .innerRadius(0)\r\n .outerRadius(0)\r\n .startAngle(0)\r\n .endAngle(0);\r\n\r\n kpiArcs.push(arc);\r\n\r\n let arcPath = mainGraphicsContext.append('path')\r\n .attr(\"d\", arc);\r\n\r\n kpiArcPaths.push(arcPath);\r\n }\r\n }\r\n\r\n private updateKpiBands(radius: number, innerRadiusFactor: number, tString: string, kpiAngleAttr: KpiArcAttributes[]) {\r\n if (!this.settings.kpiBands.show)\r\n return;\r\n\r\n for (let i = 0; i < kpiAngleAttr.length; i++) {\r\n this.kpiArcs[i]\r\n .innerRadius(radius * innerRadiusFactor - (Gauge.KpiBandDistanceFromMainArc + this.settings.kpiBands.thickness))\r\n .outerRadius(radius * innerRadiusFactor - Gauge.KpiBandDistanceFromMainArc)\r\n .startAngle(kpiAngleAttr[i].start)\r\n .endAngle(kpiAngleAttr[i].end);\r\n\r\n this.kpiArcPaths[i]\r\n .attr('fill', kpiAngleAttr[i].fill)\r\n .attr('d', this.kpiArcs[i])\r\n .attr('transform', tString);\r\n }\r\n }\r\n\r\n private removeTargetElements() {\r\n if (this.targetLine) {\r\n this.targetLine.remove();\r\n this.targetText.remove();\r\n this.targetConnector.remove();\r\n this.targetLine = this.targetConnector = this.targetText = null;\r\n }\r\n }\r\n\r\n private getTargetRatio(): number {\r\n let targetSettings = this.targetSettings;\r\n let range = targetSettings.max - targetSettings.min;\r\n if (range !== 0)\r\n return (targetSettings.target - targetSettings.min) / range;\r\n\r\n return 0;\r\n }\r\n\r\n private updateTargetLine(radius: number, innerRadius: number, left, top) {\r\n if (!this.targetLine) {\r\n this.targetLine = this.mainGraphicsContext.append('line');\r\n }\r\n\r\n let angle = this.getTargetRatio() * Math.PI;\r\n\r\n let outY = top - radius * Math.sin(angle);\r\n let outX = left - radius * Math.cos(angle);\r\n\r\n let inY = top - innerRadius * Math.sin(angle);\r\n let inX = left - innerRadius * Math.cos(angle);\r\n\r\n this.targetLine.attr({\r\n x1: inX,\r\n y1: inY,\r\n x2: outX,\r\n y2: outY\r\n });\r\n }\r\n\r\n /** Note: public for testability */\r\n public getAnimatedNumberProperties(radius: number,\r\n innerRadiusFactor: number,\r\n top: number, left: number): AnimatedNumberProperties {\r\n let boxAngle = Math.PI / 4;\r\n let scale = 1;\r\n let innerRadiusOfArc = radius * innerRadiusFactor;\r\n let innerRadiusForTextBoundingBox = innerRadiusOfArc - (this.settings.kpiBands.show\r\n ? (Gauge.KpiBandDistanceFromMainArc + this.settings.kpiBands.thickness)\r\n : 0);\r\n let innerRCos = innerRadiusForTextBoundingBox * Math.cos(boxAngle);\r\n let innerRSin = innerRadiusForTextBoundingBox * Math.sin(boxAngle);\r\n let innerY = top - innerRSin;\r\n let innerX = left - innerRCos;\r\n innerY = innerY * scale;\r\n innerX = innerX * scale;\r\n let animatedNumberWidth = innerRCos * 2;\r\n\r\n let properties: AnimatedNumberProperties = {\r\n transformString: SVGUtil.translate(innerX, innerY),\r\n viewport: { height: innerRSin, width: animatedNumberWidth }\r\n };\r\n return properties;\r\n }\r\n\r\n /** Note: public for testability */\r\n public getGaugeVisualProperties(): GaugeVisualProperties {\r\n let viewport = this.currentViewport;\r\n let margin: IMargin = this.margin;\r\n let width = viewport.width - margin.right - margin.left;\r\n let halfWidth = width / 2;\r\n let height = viewport.height - margin.top - margin.bottom;\r\n let radius = Math.min(halfWidth, height);\r\n let innerRadiusFactor = Gauge.InnerRadiusFactor;\r\n let left = margin.left + halfWidth;\r\n let top = radius + (height - radius) / 2 + margin.top;\r\n let tString = SVGUtil.translate(left, top);\r\n let innerRadiusOfArc = radius * innerRadiusFactor;\r\n\r\n let gaugeData: GaugeVisualProperties = {\r\n radius: radius,\r\n innerRadiusOfArc: innerRadiusOfArc,\r\n left: left,\r\n top: top,\r\n height: height,\r\n width: width,\r\n margin: margin,\r\n transformString: tString,\r\n innerRadiusFactor: innerRadiusFactor\r\n };\r\n\r\n return gaugeData;\r\n }\r\n\r\n /** Note: public for testability */\r\n public drawViewPort(drawOptions: GaugeVisualProperties): void {\r\n debug.assertAnyValue(drawOptions, \"Gauge options\");\r\n\r\n let separation = this.settings.kpiBands.separationRadians;\r\n let innerRadiusFactor = Gauge.InnerRadiusFactor;\r\n\r\n let backgroudArc = this.backgroundArc;\r\n let color = this.color;\r\n\r\n let attrs: KpiArcAttributes[] = [{\r\n fill: color(0),\r\n start: -Math.PI / 2,\r\n end: -Math.PI / 2 + Math.PI / 4 - separation\r\n }, {\r\n fill: color(1),\r\n start: -Math.PI / 2 + Math.PI * 1 / 4 + separation,\r\n end: -Math.PI / 2 + Math.PI * 3 / 4 - separation\r\n }, {\r\n fill: color(2),\r\n start: -Math.PI / 2 + Math.PI * 3 / 4 + separation,\r\n end: Math.PI / 2\r\n }];\r\n\r\n let radius = drawOptions.radius;\r\n let transformString = drawOptions.transformString;\r\n this.updateKpiBands(radius, innerRadiusFactor, transformString, attrs);\r\n\r\n backgroudArc\r\n .innerRadius(radius * innerRadiusFactor)\r\n .outerRadius(radius)\r\n .startAngle(-Math.PI / 2)\r\n .endAngle(Math.PI / 2);\r\n\r\n this.backgroundArcPath\r\n .attr(\"d\", backgroudArc)\r\n .attr(\"transform\", transformString);\r\n\r\n let foregroundArc = this.foregroundArc;\r\n\r\n foregroundArc\r\n .innerRadius(radius * innerRadiusFactor)\r\n .outerRadius(radius)\r\n .startAngle(-Math.PI / 2);\r\n\r\n this.foregroundArcPath\r\n .datum({ endAngle: this.lastAngle })\r\n .attr(\"transform\", transformString)\r\n .attr(\"d\", foregroundArc);\r\n\r\n let innerRadiusOfArc = drawOptions.innerRadiusOfArc;\r\n let left = drawOptions.left;\r\n let top = drawOptions.top;\r\n let margin = drawOptions.margin;\r\n let height = drawOptions.height;\r\n let targetSettings = this.targetSettings;\r\n\r\n if (!this.settings.targetLine.show || targetSettings.target == null) {\r\n this.removeTargetElements();\r\n } else {\r\n if (targetSettings.min > targetSettings.target || targetSettings.max < targetSettings.target) {\r\n this.removeTargetElements();\r\n } else {\r\n this.updateTargetLine(radius, innerRadiusOfArc, left, top);\r\n this.appendTargetTextAlongArc(radius, height, drawOptions.width, margin);\r\n }\r\n }\r\n this.svg.attr('height', this.currentViewport.height).attr('width', this.currentViewport.width);\r\n }\r\n\r\n private createTicks(): string[] {\r\n let settings = this.settings;\r\n let targetSettings = this.targetSettings;\r\n let total = targetSettings.max - targetSettings.min;\r\n let numberOfLabels = settings.labels.count;\r\n let step = total / numberOfLabels;\r\n let arr: string[] = [];\r\n let formatter = this.getFormatter(this.data.dataLabelsSettings, targetSettings.max);\r\n\r\n for (let i = 0; i < numberOfLabels + 1; i++) {\r\n arr.push(formatter.format(targetSettings.min + (i * step)));\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n private updateInternal(suppressAnimations: boolean) {\r\n let height = this.gaugeVisualProperties.height;\r\n let width = this.gaugeVisualProperties.width;\r\n let radius = this.gaugeVisualProperties.radius;\r\n let margin: IMargin = this.margin;\r\n let duration = AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n\r\n let data = this.data;\r\n let lastAngle = this.lastAngle = -Math.PI / 2 + Math.PI * data.percent;\r\n\r\n let ticks = this.createTicks();\r\n\r\n this.foregroundArcPath\r\n .transition()\r\n .ease(this.settings.transition.ease)\r\n .duration(duration)\r\n .call(this.arcTween, [lastAngle, this.foregroundArc]);\r\n\r\n this.appendTextAlongArc(ticks, radius, height, width, margin);\r\n this.updateVisualConfigurations();\r\n this.updateVisualStyles();\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(this.foregroundArcPath, (tooltipEvent: TooltipEvent) => data.tooltipInfo);\r\n TooltipManager.addTooltip(this.backgroundArcPath, (tooltipEvent: TooltipEvent) => data.tooltipInfo);\r\n }\r\n }\r\n\r\n private updateVisualStyles() {\r\n let fillColor: string = this.data.dataLabelsSettings.labelColor || this.style.labelText.color.value;\r\n this.mainGraphicsContext.selectAll('text')\r\n .style({\r\n 'fill': fillColor,\r\n });\r\n }\r\n\r\n private updateVisualConfigurations() {\r\n let configOptions = this.settings;\r\n let dataPointSettings = this.data.dataPointSettings;\r\n\r\n this.mainGraphicsContext\r\n .select('line')\r\n .attr({\r\n stroke: dataPointSettings.targetColor,\r\n 'stroke-width': configOptions.targetLine.thickness,\r\n });\r\n\r\n this.backgroundArcPath.style('fill', configOptions.arcColors.background);\r\n this.foregroundArcPath.style('fill', dataPointSettings.fillColor);\r\n }\r\n\r\n private appendTextAlongArc(ticks: string[], radius: number, height: number, width: number, margin: IMargin) {\r\n this.svg.selectAll(Gauge.LabelText.selector).remove();\r\n if (!this.data.dataLabelsSettings.show) return;\r\n\r\n let total = ticks.length;\r\n let divisor = total - 1;\r\n let top = (radius + (height - radius) / 2 + margin.top);\r\n let showMinMaxLabelsOnBottom = this.showMinMaxLabelsOnBottom();\r\n let fontSize = PixelConverter.fromPoint(this.data.dataLabelsSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt);\r\n let padding = this.settings.labels.padding;\r\n\r\n for (let count = 0; count < total; count++) {\r\n let textProperties: TextProperties = {\r\n text: ticks[count],\r\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: dataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: dataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n\r\n if (Math.floor(total / 2) === count)\r\n continue; // Skip Middle label, by design\r\n\r\n if (this.showSideNumbersLabelText()) {\r\n\r\n let x = (margin.left + width / 2) - (radius * Math.cos(Math.PI * count / divisor));\r\n let y = top - (radius * Math.sin(Math.PI * count / divisor));\r\n let anchor: string;\r\n let onRight = count * 2 > total;\r\n let onBottom = false;\r\n\r\n if (showMinMaxLabelsOnBottom && (count === 0 || count === total - 1)) {\r\n // If this is a min or max label and we're showing them on the bottom rather than the sides\r\n // Adjust the label display properties to appear under the arc\r\n onBottom = true;\r\n y += padding / 2;\r\n\r\n // Align the labels with the outer edge of the arc\r\n anchor = onRight ? 'end' : 'start';\r\n textProperties.text = TextMeasurementService.getTailoredTextOrDefault(textProperties, radius);\r\n }\r\n else {\r\n // For all other labels, display around the arc\r\n anchor = onRight ? 'start' : 'end';\r\n x += padding * (onRight ? 1 : -1);\r\n }\r\n\r\n let text = this.mainGraphicsContext\r\n .append('text')\r\n .attr({\r\n 'x': x,\r\n 'y': y,\r\n 'dy': onBottom ? fontSize : 0,\r\n 'class': Gauge.LabelText.class\r\n })\r\n .style({\r\n 'text-anchor': anchor,\r\n 'font-size': fontSize\r\n })\r\n .text(textProperties.text)\r\n .append('title').text(textProperties.text);\r\n\r\n if (!onBottom)\r\n this.truncateTextIfNeeded(text, x, onRight);\r\n }\r\n }\r\n }\r\n\r\n private truncateTextIfNeeded(text: D3.Selection, positionX: number, onRight: boolean) {\r\n let availableSpace = (onRight ? this.currentViewport.width - positionX : positionX);\r\n text.call(AxisHelper.LabelLayoutStrategy.clip,\r\n availableSpace,\r\n TextMeasurementService.svgEllipsis);\r\n }\r\n\r\n private getFormatter(dataLabelSettings: VisualDataLabelsSettings, value2?: number): IValueFormatter {\r\n let realValue2 = dataLabelSettings.displayUnits === 0 ? value2 : null;\r\n let formatString: string = valueFormatter.getFormatString(this.data.metadataColumn, Gauge.formatStringProp);\r\n let precision = dataLabelUtils.getLabelPrecision(dataLabelSettings.precision, formatString);\r\n let valueFormatterOptions: ValueFormatterOptions = dataLabelUtils.getOptionsForLabelFormatter(dataLabelSettings, formatString, realValue2, precision);\r\n valueFormatterOptions.formatSingleValues = dataLabelSettings.displayUnits > 0 ? false : true;\r\n return valueFormatter.create(valueFormatterOptions);\r\n }\r\n\r\n private appendTargetTextAlongArc(radius: number, height: number, width: number, margin: IMargin) {\r\n let targetSettings = this.targetSettings;\r\n\r\n let target = targetSettings.target;\r\n let tRatio = this.getTargetRatio();\r\n let top = (radius + (height - radius) / 2 + margin.top);\r\n let flag = tRatio > 0.5;\r\n let padding = this.settings.labels.padding;\r\n let anchor = flag ? 'start' : 'end';\r\n let formatter = this.getFormatter(this.data.dataLabelsSettings, targetSettings.max);\r\n let maxRatio = Math.asin(Gauge.MinDistanceFromBottom / radius) / Math.PI;\r\n\r\n let finalRatio = tRatio < maxRatio || tRatio > (1 - maxRatio)\r\n ? flag\r\n ? 1 - maxRatio\r\n : maxRatio\r\n : tRatio;\r\n\r\n let targetX = (margin.left + width / 2) - ((radius + padding) * Math.cos(Math.PI * finalRatio));\r\n let targetY = top - ((radius + padding) * Math.sin(Math.PI * finalRatio));\r\n\r\n if (!this.targetText) {\r\n this.targetText = this.mainGraphicsContext\r\n .append('text')\r\n .classed(Gauge.TargetText.class, true);\r\n }\r\n\r\n this.targetText\r\n .attr({\r\n 'x': targetX,\r\n 'y': targetY,\r\n })\r\n .style({\r\n 'text-anchor': anchor,\r\n 'display': this.showTargetLabel ? '' : 'none',\r\n 'font-size': this.style.labelText.fontSize\r\n })\r\n .text(formatter.format(target));\r\n\r\n this.truncateTextIfNeeded(this.targetText, targetX, flag);\r\n this.targetText.call(tooltipUtils.tooltipUpdate, [formatter.format(target)]);\r\n\r\n if (!this.targetConnector) {\r\n this.targetConnector = this.mainGraphicsContext\r\n .append('line')\r\n .classed(Gauge.TargetConnector.class, true);\r\n }\r\n\r\n // Hide the target connector if the text is going to align with the target line in the arc\r\n // It should only be shown if the target text is displaced (ex. when the target is very close to min/max)\r\n if (tRatio === finalRatio) {\r\n this.targetConnector.style('display', 'none');\r\n }\r\n else {\r\n this.targetConnector\r\n .attr({\r\n 'x1': (margin.left + width / 2) - (radius * Math.cos(Math.PI * tRatio)),\r\n 'y1': top - (radius * Math.sin(Math.PI * tRatio)),\r\n 'x2': targetX,\r\n 'y2': targetY\r\n })\r\n .style({\r\n 'stroke-width': this.settings.targetLine.thickness,\r\n 'stroke': this.settings.targetLine.color,\r\n 'display': ''\r\n });\r\n }\r\n }\r\n\r\n private arcTween(transition, arr): void {\r\n transition.attrTween('d', (d) => {\r\n let interpolate = d3.interpolate(d.endAngle, arr[0]);\r\n return (t) => {\r\n d.endAngle = interpolate(t);\r\n return arr[1](d);\r\n };\r\n });\r\n }\r\n\r\n private showMinMaxLabelsOnBottom(): boolean {\r\n // More vertical space, put labels on bottom\r\n if (this.currentViewport.height > this.currentViewport.width)\r\n return true;\r\n\r\n // We want to show the start/end ticks on the bottom when there\r\n // is insufficient space for the left and right label text\r\n if (this.data && this.gaugeVisualProperties) {\r\n let ticks = this.createTicks();\r\n let visualWhitespace = (this.currentViewport.width - (this.gaugeVisualProperties.radius * 2)) / 2;\r\n let maxLabelWidth = visualWhitespace - this.settings.labels.padding;\r\n let textProperties: TextProperties = TextMeasurementService.getMeasurementProperties($(this.svg.node()));\r\n textProperties.fontSize = PixelConverter.fromPoint(this.data.dataLabelsSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt);\r\n\r\n let width: number;\r\n for (let tickValue of [ticks[0], ticks[ticks.length - 1]]) {\r\n textProperties.text = tickValue;\r\n width = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n if (width > maxLabelWidth)\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private setMargins(): void {\r\n if (this.gaugeSmallViewPortProperties) {\r\n if (this.gaugeSmallViewPortProperties.smallGaugeMarginsOnSmallViewPort && (this.currentViewport.height < this.gaugeSmallViewPortProperties.MinHeightGaugeSideNumbersVisible)) {\r\n let margins = this.gaugeSmallViewPortProperties.GaugeMarginsOnSmallViewPort;\r\n this.margin = { top: margins, bottom: margins, left: margins, right: margins };\r\n return;\r\n }\r\n }\r\n\r\n this.margin = {\r\n top: Gauge.DefaultTopBottomMargin,\r\n bottom: Gauge.DefaultTopBottomMargin,\r\n left: Gauge.DefaultLeftRightMargin,\r\n right: Gauge.DefaultLeftRightMargin\r\n };\r\n\r\n // If we're not showing side labels, reduce the margin so that the gauge has more room to display\r\n if (!this.showSideNumbersLabelText() || this.showMinMaxLabelsOnBottom()) {\r\n let targetSettings = this.targetSettings;\r\n\r\n if (this.showTargetLabel) {\r\n // If we're showing the target label, only reduce the margin on the side that doesn't have a target label\r\n let tRatio = (targetSettings.target - targetSettings.min) / (targetSettings.max - targetSettings.min);\r\n\r\n if (tRatio > 0.5)\r\n this.margin.left = Gauge.ReducedLeftRightMargin;\r\n else\r\n this.margin.right = Gauge.ReducedLeftRightMargin;\r\n }\r\n else {\r\n // Otherwise, reduce both margins\r\n this.margin.left = this.margin.right = Gauge.ReducedLeftRightMargin;\r\n }\r\n }\r\n\r\n let fontSize = 0;\r\n if (this.data && this.data.dataLabelsSettings && this.data.dataLabelsSettings.fontSize && this.data.dataLabelsSettings.fontSize >= NewDataLabelUtils.DefaultLabelFontSizeInPt) {\r\n fontSize = PixelConverter.fromPointToPixel(this.data.dataLabelsSettings.fontSize - NewDataLabelUtils.DefaultLabelFontSizeInPt);\r\n }\r\n\r\n if (fontSize !== 0) {\r\n this.margin.bottom += fontSize;\r\n this.margin.left += fontSize;\r\n this.margin.right += fontSize;\r\n }\r\n }\r\n\r\n private showSideNumbersLabelText(): boolean {\r\n if (this.gaugeSmallViewPortProperties) {\r\n if (this.gaugeSmallViewPortProperties.hideGaugeSideNumbersOnSmallViewPort) {\r\n if (this.currentViewport.height < this.gaugeSmallViewPortProperties.MinHeightGaugeSideNumbersVisible) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import Utility = jsCommon.Utility;\r\n\r\n export interface ImageDataViewObjects extends DataViewObjects {\r\n general: ImageDataViewObject;\r\n imageScaling: ImageScalingDataViewObject;\r\n }\r\n\r\n export interface ImageDataViewObject extends DataViewObject {\r\n imageUrl: string;\r\n }\r\n\r\n export interface ImageScalingDataViewObject extends DataViewObject {\r\n imageScalingType: string;\r\n }\r\n\r\n export class ImageVisual implements IVisual {\r\n\r\n private element: JQuery;\r\n private imageBackgroundElement: JQuery;\r\n private scalingType: string = imageScalingType.normal;\r\n\r\n public init(options: VisualInitOptions) {\r\n this.element = options.element;\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] {\r\n switch (options.objectName) {\r\n case 'imageScaling':\r\n return this.enumerateImageScaling();\r\n }\r\n return null;\r\n }\r\n\r\n private enumerateImageScaling(): VisualObjectInstance[] {\r\n return [{\r\n selector: null,\r\n objectName: 'imageScaling',\r\n properties: {\r\n imageScalingType: this.scalingType,\r\n }\r\n }];\r\n }\r\n\r\n public update(options: VisualUpdateOptions): void {\r\n let dataViews = options.dataViews;\r\n if (!dataViews || dataViews.length === 0)\r\n return;\r\n\r\n let objects = <ImageDataViewObjects>dataViews[0].metadata.objects;\r\n if (!objects || !objects.general)\r\n return;\r\n\r\n let div: JQuery = this.imageBackgroundElement;\r\n if (!div) {\r\n div = $(\"<div class='imageBackground' />\");\r\n this.imageBackgroundElement = div;\r\n this.imageBackgroundElement.appendTo(this.element);\r\n }\r\n\r\n let viewport = options.viewport;\r\n div.css('height', viewport.height);\r\n\r\n if (objects.imageScaling)\r\n this.scalingType = objects.imageScaling.imageScalingType.toString();\r\n else\r\n this.scalingType = imageScalingType.normal;\r\n\r\n let imageUrl = objects.general.imageUrl;\r\n if (Utility.isLocalUrl(imageUrl))\r\n div.css(\"backgroundImage\", \"url(\" + imageUrl + \")\");\r\n\r\n if (this.scalingType === imageScalingType.fit)\r\n div.css(\"background-size\", \"100% 100%\");\r\n else if (this.scalingType === imageScalingType.fill)\r\n div.css(\"background-size\", \"cover\");\r\n else\r\n div.css(\"background-size\", \"contain\");\r\n }\r\n }\r\n} ","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface KPIStatusWithHistoryData {\r\n dataPoints: KPIStatusWithHistoryDataPoint[];\r\n directionType: string;\r\n goals: number[];\r\n formattedGoalString: string;\r\n actual: number;\r\n targetExists: boolean;\r\n historyExists: boolean;\r\n indicatorExists: boolean;\r\n trendExists: boolean;\r\n formattedValue: string;\r\n showGoal: boolean;\r\n showDistanceFromGoal: boolean;\r\n showTrendLine: boolean;\r\n }\r\n\r\n export interface KPIStatusWithHistoryDataPoint {\r\n x: number;\r\n y: number;\r\n actual: number;\r\n goals: number[];\r\n }\r\n\r\n export class KPIStatusWithHistory implements IVisual {\r\n\r\n public static directionTypeStringProp: DataViewObjectPropertyIdentifier = { objectName: 'status', propertyName: 'direction' };\r\n public static showKPIGoal: DataViewObjectPropertyIdentifier = { objectName: 'goals', propertyName: 'showGoal' };\r\n public static showKPIDistance: DataViewObjectPropertyIdentifier = { objectName: 'goals', propertyName: 'showDistance' };\r\n public static showKPITrendLine: DataViewObjectPropertyIdentifier = { objectName: 'trendline', propertyName: 'show' };\r\n public static indicatorDisplayUnitsProp: DataViewObjectPropertyIdentifier = { objectName: 'indicator', propertyName: 'indicatorDisplayUnits' };\r\n public static indicatorPrecisionProp: DataViewObjectPropertyIdentifier = { objectName: 'indicator', propertyName: 'indicatorPrecision' };\r\n\r\n public static status = { INCREASE: \"increase\", DROP: \"drop\", IN_BETWEEN: \"in-between\", NOGOAL: \"no-goal\" };\r\n public static statusBandingType = { Below: \"BELOW\", Above: \"ABOVE\" };\r\n public static actualTextConsts = { VERTICAL_OFFSET_FROM_HALF_HEIGHT: 20, FONT_WIDTH_FACTOR: 14, RIGHT_MARGIN: 10 };\r\n\r\n public static kpiRedClass = 'kpi-visual-red';\r\n public static kpiYellowClass = 'kpi-visual-yellow';\r\n public static kpiGreenClass = 'kpi-visual-green';\r\n public static kpiTextGreyClass = 'kpi-visual-text-grey';\r\n public static kpiGraphGreyClass = 'kpi-visual-graph-grey';\r\n\r\n public static allColorClasses = KPIStatusWithHistory.kpiRedClass + ' ' + KPIStatusWithHistory.kpiYellowClass + ' ' + KPIStatusWithHistory.kpiGreenClass + ' ' + KPIStatusWithHistory.kpiTextGreyClass + ' ' + KPIStatusWithHistory.kpiGraphGreyClass;\r\n\r\n public static trendAreaFilePercentage = 1;\r\n\r\n public static estimatedIconHeightInPx = 9;\r\n\r\n public static indicatorTextSizeInPx = 60;\r\n\r\n private svg: D3.Selection;\r\n private dataView: DataView;\r\n private mainGroupElement: D3.Selection;\r\n private kpiActualText: D3.Selection;\r\n private absoluteGoalDistanceText: D3.Selection;\r\n private areaFill: D3.Selection;\r\n private host: IVisualHostServices;\r\n private exclamationMarkIcon: D3.Selection;\r\n private successMarkIcon: D3.Selection;\r\n private betweenIcon: D3.Selection;\r\n private rootElement: D3.Selection;\r\n private indicatorTextContainer: D3.Selection;\r\n private textContainer: D3.Selection;\r\n\r\n private static getLocalizedString: (stringId: string) => string;\r\n\r\n private static defaultCardFormatSetting: CardFormatSetting;\r\n private static defaultLabelSettings;\r\n\r\n public init(options: VisualInitOptions): void {\r\n KPIStatusWithHistory.getLocalizedString = options.host.getLocalizedString;\r\n this.rootElement = d3.select(options.element.get(0)).append('div').attr('text-align', 'center').classed('kpiVisual', true);\r\n this.svg = this.rootElement.append('svg');\r\n let mainGroupElement = this.mainGroupElement = this.svg.append('g');\r\n this.areaFill = mainGroupElement.append(\"path\");\r\n\r\n this.textContainer = this.rootElement.append(\"div\").classed('textContainer', true);\r\n\r\n this.indicatorTextContainer = this.textContainer.append(\"div\").classed('indicatorText', true);\r\n\r\n this.absoluteGoalDistanceText = this.textContainer.append(\"div\").classed('goalText', true);\r\n\r\n this.kpiActualText = this.indicatorTextContainer.append(\"div\").attr('id', 'indicatorText');\r\n\r\n this.initIcons();\r\n\r\n this.host = options.host;\r\n }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n if (!options.dataViews || !options.dataViews[0]) return;\r\n let dataView = this.dataView = options.dataViews[0];\r\n let viewport = options.viewport;\r\n \r\n // We must have at least one measure\r\n if ((!dataView.categorical || !dataView.categorical.values || dataView.categorical.values.length < 1) &&\r\n (!dataView.categorical || !dataView.categorical.categories || dataView.categorical.categories.length < 1)) {\r\n this.svg.attr(\"visibility\", \"hidden\");\r\n this.textContainer.attr(\"style\", \"display:none\");\r\n return;\r\n }\r\n this.svg.attr(\"visibility\", \"visible\");\r\n\r\n let kpiViewModel: KPIStatusWithHistoryData = KPIStatusWithHistory.converter(\r\n dataView,\r\n viewport,\r\n KPIStatusWithHistory.getProp_KPIDirection(dataView));\r\n\r\n this.render(kpiViewModel, viewport);\r\n }\r\n\r\n private initIcons() {\r\n this.successMarkIcon = this.indicatorTextContainer.append(\"div\").classed('powervisuals-glyph checkmark kpi-visual-green', true);\r\n this.betweenIcon = this.indicatorTextContainer.append('div').classed('powervisuals-glyph circle-small kpi-visual-yellow', true);\r\n this.exclamationMarkIcon = this.indicatorTextContainer.append(\"div\").classed('powervisuals-glyph exclamation kpi-visual-red', true);\r\n \r\n this.successMarkIcon.attr('style', 'display:none');\r\n this.betweenIcon.attr('style', 'display:none');\r\n this.exclamationMarkIcon.attr('style', 'display:none');\r\n }\r\n\r\n private render(kpiViewModel: KPIStatusWithHistoryData, viewport: IViewport) {\r\n\r\n this.setShowDataMissingWarning(!(kpiViewModel.indicatorExists && kpiViewModel.trendExists));\r\n\r\n if (kpiViewModel.dataPoints.length === 0 || !kpiViewModel.indicatorExists || !kpiViewModel.trendExists) {\r\n this.areaFill.attr(\"visibility\", \"hidden\");\r\n this.svg.attr(\"visibility\", \"hidden\");\r\n this.textContainer.attr(\"style\", \"display:none\");\r\n return;\r\n }\r\n\r\n this.svg.attr({\r\n 'height': viewport.height,\r\n 'width': viewport.width,\r\n });\r\n\r\n let status = KPIStatusWithHistory.status.NOGOAL;\r\n if (kpiViewModel.targetExists && kpiViewModel.indicatorExists && kpiViewModel.trendExists) {\r\n status = GetStatus(kpiViewModel.actual, kpiViewModel.goals, kpiViewModel.directionType);\r\n }\r\n\r\n let actualText = kpiViewModel.formattedValue;\r\n\r\n let calculatedHeight = KPIStatusWithHistory.indicatorTextSizeInPx;\r\n\r\n this.textContainer\r\n .attr('style', \"width:\" + viewport.width + \"px;\" +\r\n \"top:\" + ((viewport.height - calculatedHeight) / 2) + \"px\");\r\n\r\n this.kpiActualText\r\n .classed(KPIStatusWithHistory.allColorClasses, false)\r\n .classed(GetTextColorClassByStatus(status), true)\r\n .attr(\"text-anchor\", \"middle\")\r\n .text(actualText);\r\n\r\n let icon: D3.Selection = null;\r\n\r\n switch (status) {\r\n case KPIStatusWithHistory.status.INCREASE:\r\n icon = this.successMarkIcon;\r\n this.exclamationMarkIcon.attr(\"style\", \"display:none\");\r\n this.betweenIcon.attr(\"style\", \"display:none\");\r\n break;\r\n case KPIStatusWithHistory.status.IN_BETWEEN:\r\n icon = this.betweenIcon;\r\n this.exclamationMarkIcon.attr(\"style\", \"display:none\");\r\n this.successMarkIcon.attr(\"style\", \"display:none\");\r\n break;\r\n case KPIStatusWithHistory.status.DROP:\r\n icon = this.exclamationMarkIcon;\r\n this.successMarkIcon.attr(\"style\", \"display:none\");\r\n this.betweenIcon.attr(\"style\", \"display:none\");\r\n break;\r\n default:\r\n this.exclamationMarkIcon.attr(\"style\", \"display:none\");\r\n this.successMarkIcon.attr(\"style\", \"display:none\");\r\n this.betweenIcon.attr(\"style\", \"display:none\");\r\n }\r\n\r\n if (icon) {\r\n icon.attr('style', 'font-size:12px');\r\n }\r\n\r\n let shownGoalString = kpiViewModel.showGoal ? kpiViewModel.formattedGoalString + \" \" : \"\";\r\n let shownDistanceFromGoalString = kpiViewModel.showDistanceFromGoal ? getDistanceFromGoalInPercentageString(kpiViewModel.actual, kpiViewModel.goals, kpiViewModel.directionType) : \"\";\r\n\r\n this.absoluteGoalDistanceText\r\n .attr(\"text-anchor\", \"middle\")\r\n .text(shownGoalString + shownDistanceFromGoalString);\r\n\r\n if (kpiViewModel.showTrendLine && kpiViewModel.historyExists) {\r\n let area = d3.svg.area()\r\n .x(function (d) { return d.x; })\r\n .y0(viewport.height)\r\n .y1(function (d) { return d.y; });\r\n\r\n this.areaFill\r\n .classed(KPIStatusWithHistory.allColorClasses, false)\r\n .classed(GetGraphColorClassByStatus(status), true)\r\n .attr(\"d\", area(kpiViewModel.dataPoints))\r\n .attr(\"stroke\", \"none\")\r\n .attr(\"visibility\", \"visible\")\r\n .attr('fill-opacity', 0.2);\r\n } else {\r\n this.areaFill.attr(\"visibility\", \"hidden\");\r\n }\r\n\r\n }\r\n\r\n private setShowDataMissingWarning(show: boolean) {\r\n this.host.setWarnings(show ? [new VisualKPIDataMissingWarning()] : []);\r\n }\r\n\r\n private static getDefaultFormatSettings(): CardFormatSetting {\r\n return {\r\n labelSettings: dataLabelUtils.getDefaultLabelSettings(true, Card.DefaultStyle.value.color),\r\n textSize: 27,\r\n wordWrap: false\r\n };\r\n }\r\n\r\n private static getFormatString(column: DataViewMetadataColumn): string {\r\n debug.assertAnyValue(column, 'column');\r\n return valueFormatter.getFormatString(column, AnimatedText.formatStringProp);\r\n }\r\n\r\n private static getProp_Show_KPIGoal(dataView: DataView) {\r\n if (dataView && dataView.metadata) {\r\n return DataViewObjects.getValue<boolean>(dataView.metadata.objects, KPIStatusWithHistory.showKPIGoal, true);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private static getProp_Show_KPITrendLine(dataView: DataView) {\r\n if (dataView && dataView.metadata) {\r\n return DataViewObjects.getValue<boolean>(dataView.metadata.objects, KPIStatusWithHistory.showKPITrendLine, true);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private static getProp_Show_KPIDistance(dataView: DataView) {\r\n if (dataView && dataView.metadata) {\r\n return DataViewObjects.getValue<boolean>(dataView.metadata.objects, KPIStatusWithHistory.showKPIDistance, true);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private static getProp_KPIDirection(dataView: DataView) {\r\n if (dataView && dataView.metadata) {\r\n return DataViewObjects.getValue<string>(dataView.metadata.objects, KPIStatusWithHistory.directionTypeStringProp, kpiDirection.positive);\r\n }\r\n\r\n return kpiDirection.positive;\r\n }\r\n\r\n private static getProp_Indicator_DisplayUnits(dataView: DataView) {\r\n KPIStatusWithHistory.initDefaultLabelSettings();\r\n if (dataView && dataView.metadata) {\r\n return DataViewObjects.getValue<number>(dataView.metadata.objects, KPIStatusWithHistory.indicatorDisplayUnitsProp, KPIStatusWithHistory.defaultLabelSettings.displayUnits);\r\n }\r\n\r\n return KPIStatusWithHistory.defaultLabelSettings.displayUnits;\r\n }\r\n\r\n private static getProp_Indicator_Precision(dataView: DataView) {\r\n KPIStatusWithHistory.initDefaultLabelSettings();\r\n if (dataView && dataView.metadata) {\r\n return DataViewObjects.getValue<number>(dataView.metadata.objects, KPIStatusWithHistory.indicatorPrecisionProp, KPIStatusWithHistory.defaultLabelSettings.precision);\r\n }\r\n\r\n return KPIStatusWithHistory.defaultLabelSettings.precision;\r\n }\r\n\r\n private static initDefaultLabelSettings() {\r\n if (!KPIStatusWithHistory.defaultCardFormatSetting) {\r\n KPIStatusWithHistory.defaultCardFormatSetting = KPIStatusWithHistory.getDefaultFormatSettings();\r\n KPIStatusWithHistory.defaultLabelSettings = KPIStatusWithHistory.defaultCardFormatSetting.labelSettings;\r\n }\r\n }\r\n\r\n private static getFormattedValue(metaDataColumn: DataViewMetadataColumn, theValue: number, precision: number, displayUnits: number, displayUnitSystemType: DisplayUnitSystemType = DisplayUnitSystemType.WholeUnits): string {\r\n let isDefaultDisplayUnit = displayUnits === 0;\r\n let formatter = valueFormatter.create({\r\n format: KPIStatusWithHistory.getFormatString(metaDataColumn),\r\n value: displayUnits,\r\n precision: precision,\r\n displayUnitSystemType: displayUnitSystemType,\r\n formatSingleValues: isDefaultDisplayUnit ? true : false,\r\n allowFormatBeautification: true,\r\n columnType: metaDataColumn ? metaDataColumn.type : undefined\r\n });\r\n return formatter.format(theValue);\r\n }\r\n\r\n private static getFormattedGoalString(metaDataColumn: DataViewMetadataColumn, goals: any[], precision: number, displayUnits: number): string {\r\n if (!goals || goals.length === 0) {\r\n return \"\";\r\n }\r\n\r\n let goalsString = KPIStatusWithHistory.getLocalizedString('Visual_KPI_Goal_Title') + \": \" + KPIStatusWithHistory.getFormattedValue(metaDataColumn, goals[0], precision, displayUnits);\r\n\r\n if (goals.length === 2) {\r\n goalsString += \", \" + KPIStatusWithHistory.getFormattedValue(metaDataColumn, goals[1], precision, displayUnits);\r\n }\r\n\r\n return goalsString;\r\n }\r\n\r\n public static converter(dataView: DataView, viewPort: powerbi.IViewport, directionType: string): KPIStatusWithHistoryData {\r\n let dataPoints: KPIStatusWithHistoryDataPoint[] = [];\r\n let catDv: DataViewCategorical = dataView.categorical;\r\n let indicatorMetadataColumn: DataViewMetadataColumn = null;\r\n let goalMetadataColumn: DataViewMetadataColumn = null;\r\n let formattedGoalString = \"\";\r\n let formattedValue = \"\";\r\n let targetExists = false;\r\n let indicatorExists = false;\r\n let trendExists = false;\r\n\r\n let historyExists = true;\r\n if (!dataView.categorical.categories) {\r\n historyExists = false;\r\n }\r\n\r\n let values = catDv.values;\r\n\r\n let columns = dataView.metadata.columns;\r\n\r\n for (let column of columns) {\r\n if (DataRoleHelper.hasRole(column, 'Indicator')) {\r\n indicatorExists = true;\r\n indicatorMetadataColumn = column;\r\n }\r\n\r\n if (DataRoleHelper.hasRole(column, 'TrendLine')) {\r\n trendExists = true;\r\n }\r\n\r\n if (DataRoleHelper.hasRole(column, 'Goal')) {\r\n targetExists = true;\r\n goalMetadataColumn = column;\r\n }\r\n\r\n }\r\n\r\n if (!indicatorExists || !trendExists || !values || values.length === 0 || !values[0].values || !dataView.categorical.values) {\r\n return {\r\n dataPoints: dataPoints,\r\n directionType: directionType,\r\n actual: 0,\r\n goals: [],\r\n formattedGoalString,\r\n targetExists: targetExists,\r\n historyExists: historyExists,\r\n indicatorExists,\r\n trendExists,\r\n formattedValue,\r\n showGoal: false,\r\n showDistanceFromGoal: false,\r\n showTrendLine: false\r\n };\r\n }\r\n\r\n var category, categoryValues;\r\n if (historyExists) {\r\n category = catDv.categories[0]; // This only works if we have a category axis\r\n categoryValues = category.values;\r\n }\r\n\r\n let historyActualData = [];\r\n let historyGoalData = [];\r\n\r\n let indicatorColumns: DataViewValueColumn[] = KPIStatusWithHistory.getColumnsByRole(values, \"Indicator\");\r\n\r\n let goalColumns: DataViewValueColumn[] = KPIStatusWithHistory.getColumnsByRole(values, \"Goal\");\r\n\r\n let actualValue;\r\n\r\n for (let i = 0, len = values[0].values.length; i < len; i++) {\r\n\r\n actualValue = indicatorColumns[0].values[i];\r\n\r\n let goals = [];\r\n\r\n for (let goalCnt = 0; goalCnt < goalColumns.length; goalCnt++) {\r\n goals.push(goalColumns[goalCnt].values[i]);\r\n }\r\n\r\n historyGoalData.push(goals);\r\n\r\n historyActualData.push(actualValue);\r\n }\r\n\r\n let maxActualData = Math.max.apply(Math, historyActualData);\r\n let minActualData = Math.min.apply(Math, historyActualData);\r\n let areaMaxHight = viewPort.height * KPIStatusWithHistory.trendAreaFilePercentage;\r\n\r\n let precision = KPIStatusWithHistory.getProp_Indicator_Precision(dataView);\r\n let displayUnits = KPIStatusWithHistory.getProp_Indicator_DisplayUnits(dataView);\r\n\r\n for (let i = 0; i < historyActualData.length; i++) {\r\n let yPos = areaMaxHight * (historyActualData[i] - minActualData) / (maxActualData - minActualData);\r\n\r\n let selectorId = null;\r\n if (historyExists) {\r\n selectorId = SelectionId.createWithId(category.identity[i]).getSelector();\r\n }\r\n\r\n dataPoints.push({\r\n x: i * viewPort.width / (historyActualData.length - 1),\r\n y: viewPort.height - yPos,\r\n actual: historyActualData[i],\r\n goals: historyGoalData[i],\r\n });\r\n }\r\n\r\n var actual, goals;\r\n if (dataPoints.length > 0) {\r\n actual = dataPoints[dataPoints.length - 1].actual;\r\n goals = dataPoints[dataPoints.length - 1].goals;\r\n }\r\n\r\n if (dataPoints.length === 1) {\r\n historyExists = false;\r\n }\r\n\r\n formattedValue = KPIStatusWithHistory.getFormattedValue(indicatorMetadataColumn, actual, precision, displayUnits, DisplayUnitSystemType.DataLabels);\r\n\r\n formattedGoalString = KPIStatusWithHistory.getFormattedGoalString(goalMetadataColumn, goals, precision, displayUnits);\r\n\r\n let showGoal = KPIStatusWithHistory.getProp_Show_KPIGoal(dataView);\r\n\r\n let showDistanceFromGoal = KPIStatusWithHistory.getProp_Show_KPIDistance(dataView);\r\n\r\n let showTrendLine = KPIStatusWithHistory.getProp_Show_KPITrendLine(dataView);\r\n\r\n return {\r\n dataPoints: dataPoints,\r\n directionType: directionType,\r\n actual: actual,\r\n goals: goals,\r\n formattedGoalString,\r\n targetExists: targetExists,\r\n historyExists: historyExists,\r\n indicatorExists,\r\n trendExists,\r\n formattedValue,\r\n showGoal,\r\n showDistanceFromGoal,\r\n showTrendLine\r\n };\r\n }\r\n\r\n public static getColumnsByRole(values: DataViewValueColumns, roleString: string): DataViewValueColumn[] {\r\n let retval: DataViewValueColumn[] = [];\r\n\r\n for (let i = 0; i < values.length; i++) {\r\n if (DataRoleHelper.hasRole(values[i].source, roleString)) {\r\n retval.push(values[i]);\r\n }\r\n }\r\n\r\n return retval;\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] {\r\n let instances: VisualObjectInstance[] = [];\r\n let dataView = this.dataView;\r\n switch (options.objectName) {\r\n case 'indicator':\r\n instances.push({\r\n selector: null,\r\n objectName: 'indicator',\r\n properties: {\r\n indicatorDisplayUnits: KPIStatusWithHistory.getProp_Indicator_DisplayUnits(dataView),\r\n indicatorPrecision: KPIStatusWithHistory.getProp_Indicator_Precision(dataView)\r\n }\r\n });\r\n case 'trendline':\r\n instances.push({\r\n selector: null,\r\n objectName: 'trendline',\r\n properties: {\r\n show: KPIStatusWithHistory.getProp_Show_KPITrendLine(dataView)\r\n }\r\n });\r\n case 'goals':\r\n instances.push({\r\n selector: null,\r\n objectName: 'goals',\r\n properties: {\r\n showGoal: KPIStatusWithHistory.getProp_Show_KPIGoal(dataView),\r\n showDistance: KPIStatusWithHistory.getProp_Show_KPIDistance(dataView)\r\n }\r\n });\r\n case 'status':\r\n instances.push({\r\n selector: null,\r\n objectName: 'status',\r\n properties: {\r\n direction: KPIStatusWithHistory.getProp_KPIDirection(dataView)\r\n }\r\n });\r\n }\r\n return instances;\r\n }\r\n\r\n public destroy(): void {\r\n this.svg = null;\r\n }\r\n }\r\n\r\n function GetStatus(actual, goals: any[], directionType) {\r\n if (!goals || goals.length === 0) {\r\n return KPIStatusWithHistory.status.NOGOAL;\r\n }\r\n\r\n let maxGoal, minGoal;\r\n\r\n if (goals.length === 2) {\r\n maxGoal = Math.max.apply(Math, goals);\r\n minGoal = Math.min.apply(Math, goals);\r\n\r\n if (actual >= minGoal && actual <= maxGoal) {\r\n return KPIStatusWithHistory.status.IN_BETWEEN;\r\n }\r\n }\r\n else {\r\n maxGoal = goals[0];\r\n minGoal = goals[0];\r\n }\r\n\r\n switch (directionType) {\r\n case kpiDirection.positive:\r\n if (actual < minGoal) {\r\n return KPIStatusWithHistory.status.DROP;\r\n }\r\n break;\r\n\r\n case kpiDirection.negative:\r\n if (actual > maxGoal) {\r\n return KPIStatusWithHistory.status.DROP;\r\n }\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n\r\n return KPIStatusWithHistory.status.INCREASE;\r\n }\r\n\r\n function getDistanceFromGoalInPercentageString(actual, goals: any[], directionType) {\r\n if (!goals || goals.length !== 1 || goals[0] === 0) {\r\n return \"\";\r\n }\r\n\r\n let sign = \"+\";\r\n let distance;\r\n\r\n let goal: number = goals[0];\r\n\r\n distance = Math.abs(actual - goal);\r\n\r\n switch (directionType) {\r\n case kpiDirection.positive:\r\n if (actual < goal) {\r\n sign = \"-\";\r\n }\r\n break;\r\n\r\n case kpiDirection.negative:\r\n if (actual > goal) {\r\n sign = \"-\";\r\n }\r\n break;\r\n }\r\n\r\n let percent = Number((100 * distance / goal).toFixed(2));\r\n\r\n return \"(\" + sign + percent + \"%)\";\r\n }\r\n\r\n function GetTextColorClassByStatus(status) {\r\n switch (status) {\r\n case KPIStatusWithHistory.status.NOGOAL:\r\n return KPIStatusWithHistory.kpiTextGreyClass;\r\n\r\n case KPIStatusWithHistory.status.INCREASE:\r\n return KPIStatusWithHistory.kpiGreenClass;\r\n\r\n case KPIStatusWithHistory.status.IN_BETWEEN:\r\n return KPIStatusWithHistory.kpiYellowClass;\r\n\r\n case KPIStatusWithHistory.status.DROP:\r\n return KPIStatusWithHistory.kpiRedClass;\r\n }\r\n }\r\n\r\n function GetGraphColorClassByStatus(status) {\r\n switch (status) {\r\n case KPIStatusWithHistory.status.NOGOAL:\r\n return KPIStatusWithHistory.kpiGraphGreyClass;\r\n\r\n case KPIStatusWithHistory.status.INCREASE:\r\n return KPIStatusWithHistory.kpiGreenClass;\r\n\r\n case KPIStatusWithHistory.status.IN_BETWEEN:\r\n return KPIStatusWithHistory.kpiYellowClass;\r\n\r\n case KPIStatusWithHistory.status.DROP:\r\n return KPIStatusWithHistory.kpiRedClass;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import EnumExtensions = jsCommon.EnumExtensions;\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n\r\n export interface LineChartConstructorOptions extends CartesianVisualConstructorOptions {\r\n chartType?: LineChartType;\r\n lineChartLabelDensityEnabled?: boolean;\r\n }\r\n\r\n export interface LineChartDataLabelsSettings extends PointDataLabelsSettings {\r\n labelDensity: number;\r\n }\r\n\r\n export interface ILineChartConfiguration {\r\n xAxisProperties: IAxisProperties;\r\n yAxisProperties: IAxisProperties;\r\n margin: any;\r\n }\r\n\r\n export interface LineChartCategoriesData extends LineChartDataPoint { }\r\n\r\n export interface LineChartData extends CartesianData {\r\n series: LineChartSeries[];\r\n isScalar?: boolean;\r\n dataLabelsSettings: LineChartDataLabelsSettings;\r\n axesLabels: ChartAxesLabels;\r\n hasDynamicSeries?: boolean;\r\n defaultSeriesColor?: string;\r\n categoryData?: LineChartCategoriesData[];\r\n }\r\n\r\n export interface LineChartSeries extends CartesianSeries, SelectableDataPoint {\r\n displayName: string;\r\n key: string;\r\n lineIndex: number;\r\n color: string;\r\n xCol: DataViewMetadataColumn;\r\n yCol: DataViewMetadataColumn;\r\n data: LineChartDataPoint[];\r\n labelSettings: LineChartDataLabelsSettings;\r\n }\r\n\r\n export interface LineChartDataPoint extends CartesianDataPoint, TooltipEnabledDataPoint, SelectableDataPoint, LabelEnabledDataPoint {\r\n value: number;\r\n categoryIndex: number;\r\n seriesIndex: number;\r\n key: string;\r\n labelSettings: LineChartDataLabelsSettings;\r\n pointColor?: string;\r\n stackedValue?: number;\r\n weight?: number;\r\n }\r\n\r\n export interface HoverLineDataPoint {\r\n color: string;\r\n label: string;\r\n category: string;\r\n measure: any;\r\n value: number;\r\n stackedValue: number;\r\n }\r\n\r\n export const enum LineChartType {\r\n default = 1 << 0,\r\n area = 1 << 1,\r\n smooth = 1 << 2,\r\n lineShadow = 1 << 3,\r\n stackedArea = 1 << 4\r\n }\r\n\r\n const enum LineChartRelativePosition {\r\n none,\r\n equal,\r\n lesser,\r\n greater,\r\n };\r\n\r\n /**\r\n * Renders a data series as a line visual.\r\n */\r\n export class LineChart implements ICartesianVisual {\r\n private static ClassName = 'lineChart';\r\n private static MainGraphicsContextClassName = 'mainGraphicsContext';\r\n private static CategorySelector: ClassAndSelector = createClassAndSelector('cat');\r\n private static CategoryValuePoint: ClassAndSelector = createClassAndSelector('dot');\r\n private static CategoryPointSelector: ClassAndSelector = createClassAndSelector('point');\r\n private static CategoryAreaSelector: ClassAndSelector = createClassAndSelector('catArea');\r\n private static HoverLineCircleDot: ClassAndSelector = createClassAndSelector('circle-item');\r\n private static LineClassSelector: ClassAndSelector = createClassAndSelector('line');\r\n private static PointRadius = 5;\r\n private static CircleRadius = 4;\r\n private static PathElementName = 'path';\r\n private static CircleElementName = 'circle';\r\n private static CircleClassName = 'selection-circle';\r\n private static LineElementName = 'line';\r\n private static RectOverlayName = 'rect';\r\n private static ScalarOuterPadding = 10;\r\n private static interactivityStrokeWidth = 10;\r\n private static pathXAdjustment = 5; // Based on half the stroke width for taking stroke into account in coordinate transforms\r\n public static AreaFillOpacity = 0.4;\r\n public static DimmedAreaFillOpacity = 0.2;\r\n\r\n private isInteractiveChart: boolean;\r\n private isScrollable: boolean;\r\n private tooltipsEnabled: boolean;\r\n private lineClassAndSelector: ClassAndSelector;\r\n\r\n private element: JQuery;\r\n private cartesainSVG: D3.Selection;\r\n private mainGraphicsContext: D3.Selection;\r\n private mainGraphicsSVG: D3.Selection;\r\n private hoverLineContext: D3.Selection;\r\n private options: CartesianVisualInitOptions;\r\n private dataViewCat: DataViewCategorical;\r\n\r\n private colors: IDataColorPalette;\r\n private host: IVisualHostServices;\r\n private data: LineChartData;\r\n private clippedData: LineChartData;\r\n private lineType: LineChartType;\r\n private cartesianVisualHost: ICartesianVisualHost;\r\n\r\n private xAxisProperties: IAxisProperties;\r\n private yAxisProperties: IAxisProperties;\r\n private margin: IMargin;\r\n private currentViewport: IViewport;\r\n\r\n private selectionCircles: D3.Selection[];\r\n private dragHandle: D3.Selection;\r\n private hoverLine: D3.Selection;\r\n private lastInteractiveSelectedColumnIndex: number;\r\n private scaleDetector: SVGScaleDetector;\r\n\r\n private interactivityService: IInteractivityService;\r\n private animator: IGenericAnimator;\r\n private lineChartLabelDensityEnabled: boolean;\r\n\r\n private previousCategoryCount: number;\r\n private shouldAdjustMouseCoordsOnPathsForStroke: boolean;\r\n\r\n private static validLabelPositions = [\r\n NewPointLabelPosition.Above,\r\n NewPointLabelPosition.Below,\r\n NewPointLabelPosition.Right,\r\n NewPointLabelPosition.Left,\r\n NewPointLabelPosition.AboveRight,\r\n NewPointLabelPosition.AboveLeft,\r\n NewPointLabelPosition.BelowRight,\r\n NewPointLabelPosition.BelowLeft\r\n ];\r\n private static validStackedLabelPositions = [RectLabelPosition.InsideCenter, RectLabelPosition.InsideEnd, RectLabelPosition.InsideBase];\r\n\r\n private overlayRect: D3.Selection;\r\n private isComboChart: boolean;\r\n\r\n private lastDragMoveXPosition: number;\r\n private deferDragMoveOperation = jsCommon.DeferUtility.deferUntilNextFrame(() => {\r\n if (this.lastDragMoveXPosition) {\r\n let index: number = this.findIndex(this.lastDragMoveXPosition - this.margin.left);\r\n this.selectColumn(index);\r\n this.lastDragMoveXPosition = undefined;\r\n }\r\n });\r\n\r\n public static customizeQuery(options: CustomizeQueryOptions): void {\r\n let dataViewMapping = options.dataViewMappings[0];\r\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\r\n return;\r\n\r\n dataViewMapping.categorical.dataVolume = 4;\r\n\r\n if (CartesianChart.detectScalarMapping(dataViewMapping)) {\r\n let dataViewCategories = <data.CompiledDataViewRoleForMappingWithReduction>dataViewMapping.categorical.categories;\r\n dataViewCategories.dataReductionAlgorithm = { sample: {} };\r\n }\r\n }\r\n\r\n public static getSortableRoles(options: VisualSortableOptions): string[] {\r\n let dataViewMapping = options.dataViewMappings[0];\r\n if (!dataViewMapping || !dataViewMapping.categorical || !dataViewMapping.categorical.categories)\r\n return null;\r\n\r\n let dataViewCategories = <data.CompiledDataViewRoleForMappingWithReduction>dataViewMapping.categorical.categories;\r\n let categoryItems = dataViewCategories.for.in.items;\r\n\r\n if (!_.isEmpty(categoryItems)) {\r\n let categoryType = categoryItems[0].type;\r\n\r\n let objects: DataViewObjects;\r\n if (dataViewMapping.metadata)\r\n objects = dataViewMapping.metadata.objects;\r\n\r\n //TODO: line chart should be sortable by X if it has scalar axis\r\n // But currently it doesn't support this. Always return 'category'\r\n // once it is supported.\r\n if (!CartesianChart.getIsScalar(objects, lineChartProps.categoryAxis.axisType, categoryType))\r\n return ['Category', 'Y'];\r\n }\r\n\r\n return null;\r\n }\r\n\r\n public static converter(\r\n dataView: DataView,\r\n blankCategoryValue: string,\r\n colors: IDataColorPalette,\r\n isScalar: boolean,\r\n interactivityService?: IInteractivityService,\r\n shouldCalculateStacked?: boolean,\r\n isComboChart?: boolean,\r\n tooltipsEnabled: boolean = true): LineChartData {\r\n let reader = powerbi.data.createIDataViewCategoricalReader(dataView);\r\n let valueRoleName = isComboChart ? \"Y2\" : \"Y\";\r\n let categorical = dataView.categorical;\r\n let category = categorical.categories && categorical.categories.length > 0\r\n ? categorical.categories[0]\r\n : {\r\n source: undefined,\r\n values: [blankCategoryValue],\r\n identity: undefined,\r\n };\r\n\r\n let xAxisCardProperties = CartesianHelper.getCategoryAxisProperties(dataView.metadata);\r\n isScalar = CartesianHelper.isScalar(isScalar, xAxisCardProperties);\r\n categorical = ColumnUtil.applyUserMinMax(isScalar, categorical, xAxisCardProperties);\r\n\r\n let formatStringProp = lineChartProps.general.formatString;\r\n let categoryType: ValueType = AxisHelper.getCategoryValueType(category.source, isScalar);\r\n let isDateTime = AxisHelper.isDateTime(categoryType);\r\n let categoryValues = category.values;\r\n let categoryData = [];\r\n let series: LineChartSeries[] = [];\r\n let seriesLen = categorical.values ? categorical.values.length : 0;\r\n let hasDynamicSeries = !!(categorical.values && categorical.values.source);\r\n let values = categorical.values;\r\n let defaultLabelSettings: LineChartDataLabelsSettings = dataLabelUtils.getDefaultLineChartLabelSettings(isComboChart);\r\n let defaultSeriesColor: string;\r\n\r\n if (dataView.metadata && dataView.metadata.objects) {\r\n let objects = dataView.metadata.objects;\r\n\r\n // If the line layer is in a combo chart, the \"Default Column Color\" slice's value (lineChartProps.dataPoint.defaultColor) will not affect the line series as well\r\n defaultSeriesColor = isComboChart ? undefined : DataViewObjects.getFillColor(objects, lineChartProps.dataPoint.defaultColor);\r\n\r\n let labelsObj = <DataLabelObject>objects['labels'];\r\n dataLabelUtils.updateLineChartLabelSettingsFromLabelsObject(labelsObj, defaultLabelSettings);\r\n }\r\n\r\n let colorHelper = new ColorHelper(colors, lineChartProps.dataPoint.fill, defaultSeriesColor);\r\n\r\n let grouped: DataViewValueColumnGroup[];\r\n if (dataView.categorical.values)\r\n grouped = dataView.categorical.values.grouped();\r\n\r\n let stackedValues;\r\n if (shouldCalculateStacked) {\r\n //initialize array with zeros\r\n stackedValues = categorical.values && categorical.values.length > 0 ? _.times(categorical.values[0].values.length, () => 0) : [];\r\n }\r\n\r\n for (let seriesIndex = 0; seriesIndex < seriesLen; seriesIndex++) {\r\n let column = categorical.values[seriesIndex];\r\n let valuesMetadata = column.source;\r\n let dataPoints: LineChartDataPoint[] = [];\r\n let groupedIdentity = grouped[seriesIndex];\r\n let identity = hasDynamicSeries && groupedIdentity\r\n ? SelectionId.createWithIdAndMeasure(groupedIdentity.identity, column.source.queryName)\r\n : SelectionId.createWithMeasure(column.source.queryName);\r\n let key = identity.getKey();\r\n let color = this.getColor(colorHelper, hasDynamicSeries, values, grouped, seriesIndex, groupedIdentity);\r\n let seriesLabelSettings: LineChartDataLabelsSettings;\r\n\r\n if (!hasDynamicSeries) {\r\n let labelsSeriesGroup = grouped && grouped.length > 0 && grouped[0].values ? grouped[0].values[seriesIndex] : null;\r\n let labelObjects = (labelsSeriesGroup && labelsSeriesGroup.source && labelsSeriesGroup.source.objects) ? <DataLabelObject>labelsSeriesGroup.source.objects['labels'] : null;\r\n if (labelObjects) {\r\n seriesLabelSettings = Prototype.inherit(defaultLabelSettings);\r\n dataLabelUtils.updateLineChartLabelSettingsFromLabelsObject(labelObjects, seriesLabelSettings);\r\n }\r\n }\r\n\r\n let dataPointLabelSettings = (seriesLabelSettings) ? seriesLabelSettings : defaultLabelSettings;\r\n\r\n let useHighlightValues = column.highlights && column.highlights.length > 0;\r\n let categoryCount = reader.hasCategories() ? reader.getCategoryCount() : 1;\r\n // NOTE: line capabilities don't allow highlights, but comboChart does - so only use highlight values if we are in \"combo\" mode\r\n for (let categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {\r\n let categoryValue = categoryValues[categoryIndex];\r\n let value = AxisHelper.normalizeNonFiniteNumber(useHighlightValues ? reader.getHighlight(valueRoleName, categoryIndex, seriesIndex) : reader.getValue(valueRoleName, categoryIndex, seriesIndex));\r\n\r\n // When Scalar, skip null categories and null values so we draw connected lines and never draw isolated dots.\r\n if (isScalar && (categoryValue == null || value == null))\r\n continue;\r\n\r\n // ignore variant measures\r\n if (isDateTime && categoryValue != null && !(categoryValue instanceof Date))\r\n continue;\r\n\r\n let categorical: DataViewCategorical = dataView.categorical;\r\n let tooltipInfo: TooltipDataItem[];\r\n\r\n if (tooltipsEnabled) {\r\n // This tooltip is using in combo chart and mobile tooltip.\r\n tooltipInfo = [];\r\n\r\n if (category.source) {\r\n tooltipInfo.push({\r\n displayName: category.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(categoryValue, category.source, formatStringProp),\r\n });\r\n }\r\n\r\n // This dynamicSeries tooltip is only using in mobile tooltip.\r\n if (hasDynamicSeries) {\r\n if (!category.source || category.source !== categorical.values.source) {\r\n // Category/series on the same column -- don't repeat its value in the tooltip.\r\n tooltipInfo.push({\r\n displayName: categorical.values.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(grouped[seriesIndex].name, categorical.values.source, formatStringProp),\r\n });\r\n }\r\n }\r\n if (value != null) {\r\n tooltipInfo.push({\r\n displayName: valuesMetadata.displayName,\r\n value: converterHelper.formatFromMetadataColumn(value, valuesMetadata, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n let categoryKey = category && !_.isEmpty(category.identity) && category.identity[categoryIndex] ? category.identity[categoryIndex].key : categoryIndex;\r\n\r\n let dataPoint: LineChartDataPoint = {\r\n categoryValue: isDateTime && categoryValue ? categoryValue.getTime() : categoryValue,\r\n value: value,\r\n categoryIndex: categoryIndex,\r\n seriesIndex: seriesIndex,\r\n tooltipInfo: tooltipInfo,\r\n selected: false,\r\n identity: identity,\r\n key: JSON.stringify({ series: key, category: categoryKey }),\r\n labelFill: dataPointLabelSettings.labelColor,\r\n labelFormatString: valuesMetadata.format,\r\n labelSettings: dataPointLabelSettings\r\n };\r\n\r\n if (shouldCalculateStacked) {\r\n stackedValues[categoryIndex] += value;\r\n dataPoint.stackedValue = stackedValues[categoryIndex];\r\n }\r\n\r\n if (category.objects && category.objects[categoryIndex]) {\r\n dataPoint['pointColor'] = DataViewObjects.getFillColor(category.objects[categoryIndex], lineChartProps.dataPoint.fill);\r\n }\r\n\r\n dataPoints.push(dataPoint);\r\n\r\n if (!categoryData[categoryIndex]) {\r\n categoryData[categoryIndex] = dataPoint;\r\n }\r\n }\r\n\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(dataPoints);\r\n }\r\n\r\n if (dataPoints.length > 0) {\r\n series.push({\r\n displayName: valuesMetadata.displayName,\r\n key: key,\r\n lineIndex: seriesIndex,\r\n color: color,\r\n xCol: category.source,\r\n yCol: column.source,\r\n data: dataPoints,\r\n identity: identity,\r\n selected: false,\r\n labelSettings: seriesLabelSettings,\r\n });\r\n }\r\n }\r\n\r\n xAxisCardProperties = CartesianHelper.getCategoryAxisProperties(dataView.metadata);\r\n let valueAxisProperties = CartesianHelper.getValueAxisProperties(dataView.metadata);\r\n\r\n // Convert to DataViewMetadataColumn\r\n let valuesMetadataArray: powerbi.DataViewMetadataColumn[] = [];\r\n if (values) {\r\n for (let i = 0; i < values.length; i++) {\r\n\r\n if (values[i] && values[i].source && values[i].source.displayName) {\r\n valuesMetadataArray.push({ displayName: values[i].source.displayName });\r\n }\r\n }\r\n }\r\n\r\n let axesLabels = converterHelper.createAxesLabels(xAxisCardProperties, valueAxisProperties, category.source, valuesMetadataArray);\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(series);\r\n }\r\n\r\n return {\r\n series: series,\r\n isScalar: isScalar,\r\n dataLabelsSettings: defaultLabelSettings,\r\n axesLabels: { x: axesLabels.xAxisLabel, y: axesLabels.yAxisLabel },\r\n hasDynamicSeries: hasDynamicSeries,\r\n categoryMetadata: category.source,\r\n categories: categoryValues,\r\n categoryData: categoryData,\r\n };\r\n }\r\n\r\n public static getInteractiveLineChartDomElement(element: JQuery): HTMLElement {\r\n return element.children(\"svg\").get(0);\r\n }\r\n\r\n private static getColor(\r\n colorHelper: ColorHelper,\r\n hasDynamicSeries: boolean,\r\n values: DataViewValueColumns,\r\n grouped: DataViewValueColumnGroup[],\r\n seriesIndex: number,\r\n groupedIdentity: DataViewValueColumnGroup): string {\r\n\r\n let objects: DataViewObjects;\r\n if (hasDynamicSeries) {\r\n if (grouped && grouped[seriesIndex])\r\n objects = grouped[seriesIndex].objects;\r\n }\r\n else if (values[seriesIndex]) {\r\n objects = values[seriesIndex].source.objects;\r\n }\r\n\r\n return hasDynamicSeries && groupedIdentity\r\n ? colorHelper.getColorForSeriesValue(objects, values.identityFields, groupedIdentity.name)\r\n : colorHelper.getColorForMeasure(objects, values[seriesIndex].source.queryName);\r\n }\r\n\r\n private static createStackedValueDomain(data: LineChartSeries[]): number[] {\r\n debug.assertValue(data, 'data');\r\n if (data.length === 0)\r\n return null;\r\n\r\n let minY = <number>d3.min(data, (kv) => { return d3.min(kv.data, d => { return d.stackedValue; }); });\r\n let maxY = <number>d3.max(data, (kv) => { return d3.max(kv.data, d => { return d.stackedValue; }); });\r\n\r\n return [minY, maxY];\r\n }\r\n\r\n constructor(options: LineChartConstructorOptions) {\r\n this.isScrollable = options.isScrollable ? options.isScrollable : false;\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n this.lineType = options.chartType ? options.chartType : LineChartType.default;\r\n this.interactivityService = options.interactivityService;\r\n this.animator = options.animator;\r\n this.lineChartLabelDensityEnabled = options.lineChartLabelDensityEnabled;\r\n this.lineClassAndSelector = LineChart.LineClassSelector;\r\n }\r\n\r\n public init(options: CartesianVisualInitOptions) {\r\n this.options = options;\r\n this.element = options.element;\r\n this.cartesainSVG = options.svg;\r\n this.host = options.host;\r\n this.currentViewport = options.viewport;\r\n this.colors = options.style.colorPalette.dataColors;\r\n this.isInteractiveChart = options.interactivity && options.interactivity.isInteractiveLegend;\r\n this.cartesianVisualHost = options.cartesianHost;\r\n this.scaleDetector = new SVGScaleDetector(this.cartesainSVG);\r\n\r\n let chartType = options.chartType;\r\n this.isComboChart = chartType === CartesianChartType.ComboChart || chartType === CartesianChartType.LineClusteredColumnCombo || chartType === CartesianChartType.LineStackedColumnCombo;\r\n\r\n let svg = options.svg;\r\n svg.classed(LineChart.ClassName, true);\r\n\r\n let graphicsContextParent = this.mainGraphicsSVG = svg.append('svg')\r\n .classed('lineChartSVG', true);\r\n\r\n if (!this.isComboChart && !this.isInteractiveChart) {\r\n this.overlayRect = graphicsContextParent\r\n .append(LineChart.RectOverlayName)\r\n .style(\"opacity\", SVGUtil.AlmostZero);\r\n }\r\n this.mainGraphicsContext = graphicsContextParent\r\n .append('g')\r\n .classed(LineChart.MainGraphicsContextClassName, true);\r\n\r\n this.hoverLineContext = svg.append('g')\r\n .classed('hover-line', true);\r\n\r\n this.hoverLineContext.append(LineChart.LineElementName)\r\n .attr(\"x1\", 0).attr(\"x2\", 0)\r\n .attr(\"y1\", 0).attr(\"y2\", 0);\r\n\r\n let hoverLine = this.hoverLine = this.hoverLineContext.select(LineChart.LineElementName);\r\n if (this.isInteractiveChart) {\r\n hoverLine.classed('interactive', true);\r\n }\r\n hoverLine.style('opacity', SVGUtil.AlmostZero);\r\n\r\n // define circles object - which will hold the handle circles.\r\n // this object will be populated on render() function, with number of circles which matches the nubmer of lines.\r\n this.selectionCircles = [];\r\n\r\n this.xAxisProperties = {\r\n axis: null,\r\n scale: null,\r\n isScalar: null,\r\n axisType: null,\r\n formatter: null,\r\n graphicsContext: null,\r\n values: null,\r\n axisLabel: null,\r\n isCategoryAxis: true\r\n };\r\n\r\n if (this.isInteractiveChart) {\r\n let rootSvg: EventTarget = LineChart.getInteractiveLineChartDomElement(this.element);\r\n let dragMove = () => {\r\n this.lastDragMoveXPosition = d3.mouse(rootSvg)[0];\r\n this.deferDragMoveOperation();\r\n };\r\n\r\n // assign drag and onClick events\r\n let drag = d3.behavior.drag()\r\n .origin(Object)\r\n .on(\"drag\", dragMove);\r\n d3.select(rootSvg)\r\n .style('touch-action', 'none')\r\n .call(drag)\r\n .on('click', dragMove);\r\n }\r\n\r\n // Internet Explorer and Edge use the stroke edge, not the path edge for the mouse coordinate's origin.\r\n // We need to adjust mouse events on the interactivity lines to account for this.\r\n this.shouldAdjustMouseCoordsOnPathsForStroke = !jsCommon.BrowserUtils.isChrome();\r\n }\r\n\r\n public setData(dataViews: DataView[]): void {\r\n this.data = {\r\n series: [],\r\n dataLabelsSettings: dataLabelUtils.getDefaultLineChartLabelSettings(this.isComboChart),\r\n axesLabels: { x: null, y: null },\r\n hasDynamicSeries: false,\r\n categories: [],\r\n categoryMetadata: undefined,\r\n categoryData: [],\r\n };\r\n\r\n if (dataViews.length > 0) {\r\n let dataView = dataViews[0];\r\n\r\n if (dataView) {\r\n if (dataView.categorical) {\r\n let dataViewCat = this.dataViewCat = dataView.categorical;\r\n let dvCategories = dataViewCat.categories;\r\n let categoryType = ValueType.fromDescriptor({ text: true });\r\n if (dvCategories && dvCategories.length > 0 && dvCategories[0].source && dvCategories[0].source.type)\r\n categoryType = <ValueType>dvCategories[0].source.type;\r\n\r\n let convertedData = LineChart.converter(\r\n dataView,\r\n valueFormatter.format(null),\r\n this.cartesianVisualHost.getSharedColors(),\r\n CartesianChart.getIsScalar(dataView.metadata ? dataView.metadata.objects : null, lineChartProps.categoryAxis.axisType, categoryType),\r\n this.interactivityService,\r\n EnumExtensions.hasFlag(this.lineType, LineChartType.stackedArea),\r\n this.isComboChart);\r\n this.data = convertedData;\r\n }\r\n }\r\n }\r\n }\r\n\r\n public calculateLegend(): LegendData {\r\n return this.createLegendDataPoints(0); // start with index 0\r\n }\r\n\r\n public hasLegend(): boolean {\r\n return this.data && (this.data.hasDynamicSeries || (this.data.series && this.data.series.length > 1));\r\n }\r\n\r\n public setFilteredData(startIndex: number, endIndex: number): CartesianData {\r\n let catgSize = endIndex - startIndex;\r\n let data = this.clippedData = Prototype.inherit(this.data);\r\n data.series = LineChart.sliceSeries(data.series, catgSize, startIndex);\r\n data.categories = data.categories.slice(startIndex, endIndex);\r\n return data;\r\n }\r\n\r\n public calculateAxesProperties(options: CalculateScaleAndDomainOptions): IAxisProperties[] {\r\n let data = this.data;\r\n let viewport = options.viewport;\r\n let margin = options.margin;\r\n this.currentViewport = viewport;\r\n this.margin = margin;\r\n\r\n let origCatgSize = data.series && data.series.length > 0 ? data.series[0].data.length : 0;\r\n let categoryWidth = CartesianChart.MinOrdinalRectThickness;\r\n let isScalar = this.data.isScalar;\r\n let trimOrdinalDataOnOverflow = options.trimOrdinalDataOnOverflow;\r\n let preferredPlotArea = this.getPreferredPlotArea(isScalar, origCatgSize, categoryWidth);\r\n\r\n this.clippedData = undefined;\r\n if (data && !isScalar && !this.isScrollable && trimOrdinalDataOnOverflow) {\r\n // trim data that doesn't fit on dashboard\r\n let categoryCount = this.getCategoryCount(origCatgSize);\r\n let catgSize = Math.min(origCatgSize, categoryCount);\r\n\r\n if (catgSize !== origCatgSize) {\r\n data = this.clippedData = Prototype.inherit(data);\r\n this.clippedData.series = LineChart.sliceSeries(data.series, catgSize);\r\n }\r\n }\r\n\r\n let xMetaDataColumn: DataViewMetadataColumn;\r\n let yMetaDataColumn: DataViewMetadataColumn;\r\n if (data.series && data.series.length > 0) {\r\n xMetaDataColumn = data.series[0].xCol;\r\n yMetaDataColumn = data.series[0].yCol;\r\n }\r\n\r\n let valueDomain = EnumExtensions.hasFlag(this.lineType, LineChartType.stackedArea) ? LineChart.createStackedValueDomain(data.series) : AxisHelper.createValueDomain(data.series, false);\r\n let hasZeroValueInYDomain = options.valueAxisScaleType === axisScale.log && !AxisHelper.isLogScalePossible(valueDomain);\r\n let combinedDomain = AxisHelper.combineDomain(options.forcedYDomain, valueDomain, options.ensureYDomain);\r\n this.yAxisProperties = AxisHelper.createAxis({\r\n pixelSpan: preferredPlotArea.height,\r\n dataDomain: combinedDomain,\r\n metaDataColumn: yMetaDataColumn,\r\n formatString: valueFormatter.getFormatString(yMetaDataColumn, lineChartProps.general.formatString),\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: true,\r\n forcedTickCount: options.forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false,\r\n scaleType: options.valueAxisScaleType,\r\n axisDisplayUnits: options.valueAxisDisplayUnits,\r\n axisPrecision: options.valueAxisPrecision,\r\n shouldClamp: false, // clamping causes incorrect lines when you have axis extents specified, do not enable this.\r\n });\r\n\r\n let metaDataColumn = this.data ? this.data.categoryMetadata : undefined;\r\n let categoryDataType: ValueTypeDescriptor = AxisHelper.getCategoryValueType(metaDataColumn);\r\n let xDomain = AxisHelper.createDomain(data.series, categoryDataType, this.data.isScalar, options.forcedXDomain, options.ensureXDomain);\r\n let hasZeroValueInXDomain = options.categoryAxisScaleType === axisScale.log && !AxisHelper.isLogScalePossible(xDomain);\r\n this.xAxisProperties = AxisHelper.createAxis({\r\n pixelSpan: preferredPlotArea.width,\r\n dataDomain: xDomain,\r\n metaDataColumn: xMetaDataColumn,\r\n formatString: valueFormatter.getFormatString(xMetaDataColumn, lineChartProps.general.formatString),\r\n outerPadding: this.data.isScalar ? LineChart.ScalarOuterPadding : 0,\r\n isScalar: this.data.isScalar,\r\n isVertical: false,\r\n forcedTickCount: options.forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n getValueFn: (index, type) => CartesianHelper.lookupXValue(this.data, index, type, this.data.isScalar),\r\n categoryThickness: CartesianChart.getCategoryThickness(data.series, origCatgSize, this.getAvailableWidth(), xDomain, isScalar, trimOrdinalDataOnOverflow),\r\n isCategoryAxis: true,\r\n scaleType: options.categoryAxisScaleType,\r\n axisDisplayUnits: options.categoryAxisDisplayUnits,\r\n axisPrecision: options.categoryAxisPrecision\r\n });\r\n\r\n this.xAxisProperties.axisLabel = options.showCategoryAxisLabel ? data.axesLabels.x : null;\r\n this.yAxisProperties.axisLabel = options.showValueAxisLabel ? data.axesLabels.y : null;\r\n\r\n this.xAxisProperties.hasDisallowedZeroInDomain = hasZeroValueInXDomain;\r\n this.yAxisProperties.hasDisallowedZeroInDomain = hasZeroValueInYDomain;\r\n\r\n return [this.xAxisProperties, this.yAxisProperties];\r\n }\r\n\r\n public enumerateObjectInstances(enumeration: ObjectEnumerationBuilder, options: EnumerateVisualObjectInstancesOptions): void {\r\n switch (options.objectName) {\r\n case 'dataPoint':\r\n this.enumerateDataPoints(enumeration);\r\n break;\r\n case 'labels':\r\n this.enumerateDataLabels(enumeration);\r\n break;\r\n }\r\n }\r\n\r\n private enumerateDataPoints(enumeration: ObjectEnumerationBuilder): void {\r\n let data = this.data;\r\n if (!data || !data.series || data.series.length === 0)\r\n return;\r\n\r\n let formatStringProp = lineChartProps.general.formatString;\r\n let singleSeriesData = data.series;\r\n let seriesLength = singleSeriesData.length;\r\n\r\n for (let i = 0; i < seriesLength; i++) {\r\n let selector = ColorHelper.normalizeSelector(singleSeriesData[i].identity.getSelector());\r\n\r\n let label = converterHelper.getFormattedLegendLabel(singleSeriesData[i].yCol, this.dataViewCat.values, formatStringProp);\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: label,\r\n selector: selector,\r\n properties: {\r\n fill: { solid: { color: data.defaultSeriesColor || singleSeriesData[i].color } }\r\n },\r\n });\r\n }\r\n }\r\n\r\n private enumerateDataLabels(enumeration: ObjectEnumerationBuilder): void {\r\n let data = this.data,\r\n labelSettings = this.data.dataLabelsSettings,\r\n seriesCount = data.series.length,\r\n showLabelPerSeries = this.showLabelPerSeries();\r\n\r\n //Draw default settings\r\n dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings, null, showLabelPerSeries));\r\n\r\n if (seriesCount === 0)\r\n return;\r\n\r\n //Draw series settings\r\n if (showLabelPerSeries && labelSettings.showLabelPerSeries) {\r\n for (let i = 0; i < seriesCount; i++) {\r\n let series = data.series[i],\r\n labelSettings: LineChartDataLabelsSettings = (series.labelSettings) ? series.labelSettings : this.data.dataLabelsSettings;\r\n\r\n enumeration.pushContainer({ displayName: series.displayName });\r\n dataLabelUtils.enumerateDataLabels(this.getLabelSettingsOptions(enumeration, labelSettings, series));\r\n enumeration.popContainer();\r\n }\r\n }\r\n }\r\n\r\n public supportsTrendLine(): boolean {\r\n let isScalar = this.data ? this.data.isScalar : false;\r\n return !EnumExtensions.hasFlag(this.lineType, LineChartType.stackedArea) && isScalar;\r\n }\r\n\r\n private getLabelSettingsOptions(enumeration: ObjectEnumerationBuilder, labelSettings: LineChartDataLabelsSettings, series?: LineChartSeries, showAll?: boolean): VisualDataLabelsSettingsOptions {\r\n return {\r\n enumeration: enumeration,\r\n dataLabelsSettings: labelSettings,\r\n show: true,\r\n displayUnits: true,\r\n precision: true,\r\n selector: series && series.identity ? series.identity.getSelector() : null,\r\n showAll: showAll,\r\n fontSize: true,\r\n labelDensity: this.lineChartLabelDensityEnabled,\r\n };\r\n }\r\n\r\n public overrideXScale(xProperties: IAxisProperties): void {\r\n this.xAxisProperties = xProperties;\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService)\r\n this.interactivityService.clearSelection();\r\n }\r\n\r\n public render(suppressAnimations: boolean): CartesianVisualRenderResult {\r\n let duration = AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n if (this.data.categoryData.length !== this.previousCategoryCount) {\r\n duration = 0;\r\n }\r\n this.previousCategoryCount = this.data.categoryData.length;\r\n let result: CartesianVisualRenderResult;\r\n if (!this.isInteractiveChart) // If we're not a mobile interactive chart, use the new render path\r\n result = this.renderNew(duration);\r\n else // If not, use the old path kept around for mobile compatibility until mobile code can be moved and tested within the new render path\r\n result = this.renderOld(duration);\r\n\r\n // This should always be the last line in the render code.\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n\r\n return result;\r\n }\r\n\r\n private renderNew(duration: number): CartesianVisualRenderResult {\r\n let data = this.clippedData ? this.clippedData : this.data;\r\n if (!data)\r\n return;\r\n\r\n let dataPointCount = data.categories.length * data.series.length;\r\n if (dataPointCount > AnimatorCommon.MaxDataPointsToAnimate) {\r\n // Too many data points to animate.\r\n duration = 0;\r\n }\r\n\r\n let isStackedArea = EnumExtensions.hasFlag(this.lineType, LineChartType.stackedArea);\r\n let margin = this.margin;\r\n let viewport = this.currentViewport;\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n let width = viewport.width - (margin.left + margin.right);\r\n let xScale = this.xAxisProperties.scale;\r\n let yScale = this.yAxisProperties.scale;\r\n let horizontalOffset = this.getXOfFirstCategory();\r\n\r\n let hasSelection = this.interactivityService && this.interactivityService.hasSelection();\r\n let renderAreas: boolean = EnumExtensions.hasFlag(this.lineType, LineChartType.area) || EnumExtensions.hasFlag(this.lineType, LineChartType.stackedArea);\r\n let xPosition = (d: LineChartDataPoint) => { return xScale(this.getXValue(d)) + horizontalOffset; };\r\n\r\n let y0Position, yPosition;\r\n if (isStackedArea) {\r\n y0Position = (d: LineChartDataPoint) => { return yScale(d.stackedValue - d.value); };\r\n yPosition = (d: LineChartDataPoint) => { return yScale(d.stackedValue); };\r\n }\r\n else {\r\n y0Position = yScale(0);\r\n yPosition = (d: LineChartDataPoint) => { return yScale(d.value); };\r\n }\r\n\r\n let area;\r\n if (renderAreas) {\r\n area = d3.svg.area()\r\n .x(xPosition)\r\n .y0(y0Position)\r\n .y1(yPosition)\r\n .defined((d: LineChartDataPoint) => { return d.value !== null; });\r\n }\r\n\r\n let line = d3.svg.line()\r\n .x(xPosition)\r\n .y(yPosition)\r\n .defined((d: LineChartDataPoint) => {\r\n return d.value !== null;\r\n });\r\n\r\n if (EnumExtensions.hasFlag(this.lineType, LineChartType.smooth)) {\r\n line.interpolate('basis');\r\n if (area) {\r\n area.interpolate('basis');\r\n }\r\n }\r\n\r\n this.mainGraphicsSVG\r\n .attr('height', height)\r\n .attr('width', width);\r\n let areas = undefined;\r\n // Render Areas\r\n if (renderAreas) {\r\n areas = this.mainGraphicsContext.selectAll(LineChart.CategoryAreaSelector.selector).data(data.series, (d: LineChartSeries) => d.identity.getKey());\r\n areas.enter()\r\n .append(LineChart.PathElementName)\r\n .classed(LineChart.CategoryAreaSelector.class, true);\r\n areas\r\n .style('fill', (d: LineChartSeries) => d.color)\r\n .style('fill-opacity', (d: LineChartSeries) => (hasSelection && !d.selected) ? LineChart.DimmedAreaFillOpacity : LineChart.AreaFillOpacity)\r\n .transition()\r\n .ease('linear')\r\n .duration(duration)\r\n .attr('d', (d: LineChartSeries) => area(d.data));\r\n areas.exit()\r\n .remove();\r\n }\r\n\r\n // Render Lines\r\n let lines = this.mainGraphicsContext.selectAll(this.lineClassAndSelector.selector).data(data.series, (d: LineChartSeries) => d.identity.getKey());\r\n lines.enter()\r\n .append(LineChart.PathElementName)\r\n .classed(this.lineClassAndSelector.class, true);\r\n lines\r\n .style('stroke', (d: LineChartSeries) => d.color)\r\n .style('stroke-opacity', (d: LineChartSeries) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false))\r\n .transition()\r\n .ease('linear')\r\n .duration(duration)\r\n .attr('d', (d: LineChartSeries) => {\r\n return line(d.data);\r\n });\r\n lines.exit()\r\n .remove();\r\n\r\n // Render extra lines that are wider and invisible used for better interactivity\r\n let interactivityLines;\r\n if (this.interactivityService) {\r\n interactivityLines = this.mainGraphicsContext.selectAll(\".interactivity-line\").data(data.series, (d: LineChartSeries) => d.identity.getKey());\r\n interactivityLines.enter()\r\n .append(LineChart.PathElementName)\r\n .classed('interactivity-line', true)\r\n .style('stroke-width', LineChart.interactivityStrokeWidth);\r\n interactivityLines\r\n .attr('d', (d: LineChartSeries) => {\r\n return line(d.data);\r\n });\r\n interactivityLines.exit()\r\n .remove();\r\n }\r\n\r\n // Prepare grouping for dots\r\n let dotGroups = this.mainGraphicsContext.selectAll(LineChart.CategorySelector.selector)\r\n .data(data.series, (d: LineChartSeries) => d.identity.getKey());\r\n\r\n dotGroups.enter()\r\n .append('g')\r\n .classed(LineChart.CategorySelector.class, true);\r\n\r\n dotGroups.exit()\r\n .remove();\r\n\r\n // Render dots\r\n let dots = dotGroups.selectAll(LineChart.CategoryValuePoint.selector)\r\n .data((series: LineChartSeries) => {\r\n return series.data.filter((value: LineChartDataPoint, i: number) => {\r\n return this.shouldDrawCircle(series, i);\r\n });\r\n }, (d: LineChartDataPoint) => d.key);\r\n dots.enter()\r\n .append(LineChart.CircleElementName)\r\n .classed(LineChart.CategoryValuePoint.class, true);\r\n dots\r\n .style('fill', function () {\r\n let lineSeries = d3.select(this.parentNode).datum();\r\n return lineSeries.color;\r\n })\r\n .style('fill-opacity', function () {\r\n let lineSeries = d3.select(this.parentNode).datum();\r\n return ColumnUtil.getFillOpacity(lineSeries.selected, false, hasSelection, false);\r\n })\r\n .transition()\r\n .duration(duration)\r\n .attr({\r\n cx: (d: LineChartDataPoint, i: number) => xScale(this.getXValue(d)) + horizontalOffset,\r\n cy: (d: LineChartDataPoint, i: number) => yScale(isStackedArea ? d.stackedValue : d.value),\r\n r: LineChart.CircleRadius\r\n });\r\n dots.exit()\r\n .remove();\r\n\r\n // Render explicit dots\r\n let explicitDots: D3.UpdateSelection;\r\n if (!this.isComboChart) {\r\n explicitDots = dotGroups.selectAll(LineChart.CategoryPointSelector.selector)\r\n .data((series: LineChartSeries) => {\r\n return _.filter(series.data, (value: LineChartDataPoint) => { return value.pointColor != null; });\r\n }, (d: LineChartDataPoint) => d.key);\r\n explicitDots.enter()\r\n .append(LineChart.CircleElementName)\r\n .classed(LineChart.CategoryPointSelector.class, true);\r\n explicitDots\r\n .style('fill', (d: LineChartDataPoint) => d.pointColor)\r\n .transition()\r\n .duration(duration)\r\n .attr({\r\n cx: (d: LineChartDataPoint) => xScale(this.getXValue(d)),\r\n cy: (d: LineChartDataPoint) => yScale(isStackedArea ? d.stackedValue : d.value),\r\n r: LineChart.PointRadius\r\n });\r\n explicitDots.exit()\r\n .remove();\r\n }\r\n\r\n // Add data labels\r\n let labelDataPointsGroups: LabelDataPointsGroup[];\r\n if (data.dataLabelsSettings.show)\r\n labelDataPointsGroups = this.createLabelDataPoints();\r\n\r\n if (this.tooltipsEnabled) {\r\n if (!this.isComboChart) {\r\n this.overlayRect\r\n .attr({\r\n x: 0,\r\n width: width,\r\n height: height\r\n });\r\n\r\n let seriesTooltipApplier = (tooltipEvent: TooltipEvent) => {\r\n let pointX: number = tooltipEvent.elementCoordinates[0];\r\n let index = this.getCategoryIndexFromTooltipEvent(tooltipEvent, pointX);\r\n let categoryData = this.selectColumnForTooltip(index);\r\n return this.getSeriesTooltipInfo(categoryData);\r\n };\r\n\r\n let clearHoverLine = () => {\r\n this.hoverLine.style('opacity', SVGUtil.AlmostZero);\r\n this.hoverLineContext.selectAll(LineChart.HoverLineCircleDot.selector).remove();\r\n };\r\n TooltipManager.addTooltip(this.mainGraphicsSVG, seriesTooltipApplier, true, clearHoverLine);\r\n } else {\r\n let seriesTooltipApplier = (tooltipEvent: TooltipEvent) => {\r\n let pointX: number = tooltipEvent.elementCoordinates[0];\r\n return this.getTooltipInfoForCombo(tooltipEvent, pointX);\r\n };\r\n\r\n if (interactivityLines)\r\n TooltipManager.addTooltip(interactivityLines, seriesTooltipApplier, true);\r\n\r\n TooltipManager.addTooltip(dots, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo, true);\r\n if (explicitDots)\r\n TooltipManager.addTooltip(explicitDots, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo, true);\r\n }\r\n }\r\n\r\n let dataPointsToBind: SelectableDataPoint[] = undefined;\r\n let behaviorOptions: LineChartBehaviorOptions = undefined;\r\n if (this.interactivityService) {\r\n // Register interactivity\r\n dataPointsToBind = data.series.slice();\r\n\r\n for (let i = 0, ilen = data.series.length; i < ilen; i++) {\r\n dataPointsToBind = dataPointsToBind.concat(data.series[i].data);\r\n }\r\n\r\n behaviorOptions = {\r\n lines: lines,\r\n interactivityLines: interactivityLines,\r\n dots: dots,\r\n areas: areas,\r\n tooltipOverlay: this.overlayRect,\r\n };\r\n }\r\n\r\n return {\r\n dataPoints: dataPointsToBind,\r\n behaviorOptions: behaviorOptions,\r\n labelDataPoints: [],\r\n labelsAreNumeric: true,\r\n labelDataPointGroups: labelDataPointsGroups,\r\n };\r\n }\r\n\r\n private renderOld(duration: number): CartesianVisualRenderResult {\r\n let data = this.clippedData ? this.clippedData : this.data;\r\n if (!data)\r\n return;\r\n\r\n let margin = this.margin;\r\n let viewport = this.currentViewport;\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n let xScale = this.xAxisProperties.scale;\r\n let yScale = this.yAxisProperties.scale;\r\n\r\n let hasSelection = this.interactivityService && this.interactivityService.hasSelection();\r\n\r\n let area;\r\n if (EnumExtensions.hasFlag(this.lineType, LineChartType.area)) {\r\n area = d3.svg.area()\r\n .x((d: LineChartDataPoint) => { return xScale(this.getXValue(d)); })\r\n .y0(height)\r\n .y1((d: LineChartDataPoint) => { return yScale(d.value); })\r\n .defined((d: LineChartDataPoint) => { return d.value !== null; });\r\n }\r\n\r\n let line = d3.svg.line()\r\n .x((d: LineChartDataPoint) => {\r\n return xScale(this.getXValue(d));\r\n })\r\n .y((d: LineChartDataPoint) => {\r\n return yScale(d.value);\r\n })\r\n .defined((d: LineChartDataPoint) => {\r\n return d.value !== null;\r\n });\r\n\r\n if (EnumExtensions.hasFlag(this.lineType, LineChartType.smooth)) {\r\n line.interpolate('basis');\r\n if (area) {\r\n area.interpolate('basis');\r\n }\r\n }\r\n\r\n let firstCategoryOffset = this.getXOfFirstCategory();\r\n\r\n this.mainGraphicsContext.attr('transform', SVGUtil.translate(firstCategoryOffset, 0));\r\n\r\n this.mainGraphicsSVG.attr('height', this.getAvailableHeight())\r\n .attr('width', this.getAvailableWidth());\r\n this.hoverLineContext.attr('transform', SVGUtil.translate(firstCategoryOffset, 0));\r\n\r\n if (EnumExtensions.hasFlag(this.lineType, LineChartType.area)) {\r\n let catAreaSelect = this.mainGraphicsContext.selectAll(LineChart.CategoryAreaSelector.selector)\r\n .data(data.series, (d: LineChartDataPoint) => d.identity.getKey());\r\n\r\n let catAreaEnter =\r\n catAreaSelect\r\n .enter().append('g')\r\n .classed(LineChart.CategoryAreaSelector.class, true);\r\n\r\n catAreaEnter.append(LineChart.PathElementName);\r\n\r\n let catAreaUpdate = this.mainGraphicsContext.selectAll(LineChart.CategoryAreaSelector.selector);\r\n\r\n catAreaUpdate.select(LineChart.PathElementName)\r\n .transition()\r\n .ease('linear')\r\n .duration(duration)\r\n .attr('d', (d: LineChartSeries) => area(d.data))\r\n .style('fill', (d: LineChartSeries) => d.color)\r\n .style('fill-opacity', (d: LineChartSeries) => (hasSelection && !d.selected) ? LineChart.DimmedAreaFillOpacity : LineChart.AreaFillOpacity);\r\n\r\n catAreaSelect.exit().remove();\r\n }\r\n\r\n let catSelect = this.mainGraphicsContext.selectAll(LineChart.CategorySelector.selector)\r\n .data(data.series, (d: LineChartDataPoint) => d.identity.getKey());\r\n\r\n let catEnter = catSelect\r\n .enter()\r\n .append('g')\r\n .classed(LineChart.CategorySelector.class, true);\r\n\r\n catEnter.append(LineChart.PathElementName);\r\n catEnter.selectAll(LineChart.CategoryValuePoint.selector)\r\n .data((d: LineChartSeries) => d.data)\r\n .enter()\r\n .append(LineChart.CircleElementName)\r\n .classed(LineChart.CategoryValuePoint.class, true);\r\n\r\n // moving this up to avoid using the svg path generator with NaN values\r\n // do not move this without validating that no errors are thrown in the browser console\r\n catSelect.exit().remove();\r\n\r\n // add the drag handle, if needed\r\n if (this.isInteractiveChart && !this.dragHandle) {\r\n let handleTop = this.getAvailableHeight();\r\n this.dragHandle = this.hoverLineContext.append('circle')\r\n .attr('cx', 0)\r\n .attr('cy', handleTop)\r\n .attr('r', '6px')\r\n .classed('drag-handle', true);\r\n }\r\n\r\n // Create the selection circles\r\n let linesCount = catSelect.data().length; // number of lines plotted\r\n while (this.selectionCircles.length < linesCount) {\r\n let addedCircle = this.hoverLineContext.append(LineChart.CircleElementName)\r\n .classed(LineChart.CircleClassName, true)\r\n .attr('r', LineChart.CircleRadius).style('opacity', 0);\r\n this.selectionCircles.push(addedCircle);\r\n }\r\n\r\n while (this.selectionCircles.length > linesCount) {\r\n this.selectionCircles.pop().remove();\r\n }\r\n\r\n let catUpdate = this.mainGraphicsContext.selectAll(LineChart.CategorySelector.selector);\r\n\r\n let lineSelection = catUpdate.select(LineChart.PathElementName)\r\n .classed(this.lineClassAndSelector.class, true)\r\n .style('stroke', (d: LineChartSeries) => d.color)\r\n .style('stroke-opacity', (d: LineChartSeries) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false));\r\n lineSelection\r\n .transition()\r\n .ease('linear')\r\n .duration(duration)\r\n .attr('d', (d: LineChartSeries) => {\r\n return line(d.data);\r\n });\r\n\r\n let that = this;\r\n let updateSelection = catUpdate.selectAll(LineChart.CategoryValuePoint.selector);\r\n let transitions = updateSelection\r\n .style('fill', function () {\r\n let lineSeries = d3.select(this.parentNode).datum();\r\n return lineSeries.color;\r\n })\r\n .style('fill-opacity', function () {\r\n let lineSeries = d3.select(this.parentNode).datum();\r\n return ColumnUtil.getFillOpacity(lineSeries.selected, false, hasSelection, false);\r\n })\r\n .transition()\r\n .duration(duration)\r\n .attr({\r\n 'cx': function (d: LineChartDataPoint, i: number) {\r\n let lineSeries = d3.select(this.parentNode).datum();\r\n let circleIndex = that.shouldDrawCircle(lineSeries, i);\r\n return circleIndex ? xScale(that.getXValue(d)) : 0;\r\n },\r\n 'cy': function (d: LineChartDataPoint, i: number) {\r\n let lineSeries = d3.select(this.parentNode).datum();\r\n let circleIndex = that.shouldDrawCircle(lineSeries, i);\r\n return circleIndex ? yScale(d.value) : 0;\r\n },\r\n 'r': function (d: LineChartDataPoint, i: number) {\r\n let lineSeries = d3.select(this.parentNode).datum();\r\n let circleIndex = that.shouldDrawCircle(lineSeries, i);\r\n return circleIndex ? LineChart.CircleRadius : 0;\r\n }\r\n });\r\n if (this.isInteractiveChart && this.hasDataPoint(data.series)) {\r\n let selectionSize = updateSelection.size();\r\n let endedTransitionCount = 0;\r\n transitions.each('end', () => {\r\n // When transitions finish, and it's an interactive chart - select the last column (draw the legend and the handle)\r\n endedTransitionCount++;\r\n if (endedTransitionCount === selectionSize) { // all transitions had finished\r\n this.selectColumn(CartesianHelper.findMaxCategoryIndex(data.series), true);\r\n }\r\n });\r\n }\r\n\r\n let dataPoints: LineChartDataPoint[] = null;\r\n if (data.dataLabelsSettings.show) {\r\n dataPoints = [];\r\n for (let i = 0, ilen = data.series.length; i < ilen; i++) {\r\n Array.prototype.push.apply(dataPoints, data.series[i].data);\r\n }\r\n }\r\n\r\n catSelect.exit().remove();\r\n\r\n // # Code from here is taken from renderNew:\r\n\r\n // Add data labels\r\n let labelDataPointsGroups: LabelDataPointsGroup[];\r\n if (data.dataLabelsSettings.show)\r\n labelDataPointsGroups = this.createLabelDataPoints();\r\n\r\n return dataPoints == null ? null : {\r\n dataPoints: dataPoints,\r\n behaviorOptions: null,\r\n labelDataPoints: null,\r\n labelsAreNumeric: null,\r\n labelDataPointGroups: labelDataPointsGroups\r\n };\r\n }\r\n\r\n /**\r\n * Note: Public for tests.\r\n */\r\n public getSeriesTooltipInfo(pointData: HoverLineDataPoint[]): TooltipDataItem[] {\r\n\r\n let tooltipinfo: TooltipDataItem[] = [];\r\n const maxNumberOfItems = 10; // to limit the number of rows we display\r\n\r\n // count to the maximum number of rows we can display\r\n let count = 0;\r\n for (let point of pointData) {\r\n if (count >= maxNumberOfItems) break;\r\n if (point.value != null) {\r\n tooltipinfo.push({\r\n header: point.category,\r\n color: point.color,\r\n displayName: point.label,\r\n value: point.measure\r\n });\r\n count++;\r\n }\r\n }\r\n\r\n if (tooltipinfo.length === 0)\r\n return null; //don't draw an empty tooltip container\r\n\r\n return tooltipinfo;\r\n }\r\n\r\n /**\r\n * Note: Public for tests.\r\n */\r\n public getTooltipInfoForCombo(tooltipEvent: TooltipEvent, pointX: number): TooltipDataItem[] {\r\n // update pointX, the mouse coordinate, with the left-offset of the SVGRect from the x-scale space so we can use the d3.scale to get the index.\r\n let categoryIndex = this.getCategoryIndexFromTooltipEvent(tooltipEvent, pointX);\r\n let seriesData = <LineChartSeries>tooltipEvent.data;\r\n\r\n let dataPoint: LineChartDataPoint;\r\n if (seriesData && seriesData.data && seriesData.data.length) {\r\n dataPoint = _.find(seriesData.data, (dp: LineChartDataPoint) => dp.categoryIndex === categoryIndex);\r\n }\r\n if (dataPoint)\r\n return dataPoint.tooltipInfo;\r\n // return undefined so we don't show an empty tooltip\r\n }\r\n\r\n /**\r\n * Note: Public for tests.\r\n */\r\n public getCategoryIndexFromTooltipEvent(tooltipEvent: TooltipEvent, pointX: number): number {\r\n if (tooltipEvent.data && tooltipEvent.data.categoryIndex != null) {\r\n // Tooltip originated with a dot; simply return the categoryIndex from the dot's bound data\r\n return tooltipEvent.data.categoryIndex;\r\n }\r\n\r\n let seriesData = <LineChartSeries>tooltipEvent.data;\r\n let offsetX = 0; // Offset based on the firstCategoryOffset (since lines don't start at x = 0) as well as the offset due to lines that may not start at the first category\r\n if (seriesData && !_.isEmpty(seriesData.data) && this.xAxisProperties) {\r\n // Tooltip originated from a path; determine series offset from the first point that is part of a path\r\n pointX = this.adjustPathXCoordinate(pointX);\r\n let firstPathPoint = _.find(seriesData.data, (dataPoint: LineChartDataPoint, index: number, dataPoints: LineChartDataPoint[]) => {\r\n let nextDataPoint = dataPoints[index + 1];\r\n return dataPoint.value != null && nextDataPoint && nextDataPoint.value != null;\r\n });\r\n debug.assertValue(firstPathPoint, \"If there is data on the tooltipEvent but no categoryIndex, there should always be two consecutive non-null values\");\r\n offsetX = this.xAxisProperties.scale(this.getXValue(firstPathPoint)) + this.getXOfFirstCategory();\r\n }\r\n // else: Tooltip originated from the background; no offsetX is needed\r\n return this.findIndex(pointX, offsetX);\r\n }\r\n\r\n public getVisualCategoryAxisIsScalar(): boolean {\r\n return this.data ? this.data.isScalar : false;\r\n }\r\n\r\n public getSupportedCategoryAxisType(): string {\r\n let dvCategories = this.dataViewCat ? this.dataViewCat.categories : undefined;\r\n let categoryType = ValueType.fromDescriptor({ text: true });\r\n if (dvCategories && dvCategories.length > 0 && dvCategories[0].source && dvCategories[0].source.type)\r\n categoryType = <ValueType>dvCategories[0].source.type;\r\n\r\n let isOrdinal = AxisHelper.isOrdinal(categoryType);\r\n return isOrdinal ? axisType.categorical : axisType.both;\r\n }\r\n\r\n public getPreferredPlotArea(isScalar: boolean, categoryCount: number, categoryThickness: number): IViewport {\r\n return CartesianChart.getPreferredPlotArea(\r\n categoryCount,\r\n categoryThickness,\r\n this.currentViewport,\r\n this.isScrollable,\r\n isScalar,\r\n this.margin,\r\n true);\r\n }\r\n\r\n private getCategoryCount(origCatgSize): number {\r\n let availableWidth = this.getAvailableWidth();\r\n let categoryThickness = CartesianChart.MinOrdinalRectThickness;\r\n return Math.min(Math.round((availableWidth - categoryThickness * CartesianChart.OuterPaddingRatio * 2) / categoryThickness), origCatgSize);\r\n }\r\n\r\n private getAvailableWidth(): number {\r\n return this.currentViewport.width - (this.margin.left + this.margin.right);\r\n }\r\n\r\n private getAvailableHeight(): number {\r\n return this.currentViewport.height - (this.margin.top + this.margin.bottom);\r\n }\r\n\r\n private static sliceSeries(series: LineChartSeries[], newLength: number, startIndex: number = 0): LineChartSeries[] {\r\n let newSeries: LineChartSeries[] = [];\r\n if (series && series.length > 0) {\r\n debug.assert(series[0].data.length >= newLength, \"invalid newLength\");\r\n for (let i = 0, len = series.length; i < len; i++) {\r\n newSeries[i] = Prototype.inherit(series[i]);\r\n newSeries[i].data = series[i].data.slice(startIndex, startIndex + newLength);\r\n }\r\n }\r\n return newSeries;\r\n }\r\n\r\n private getXOfFirstCategory(): number {\r\n if (!this.data.isScalar) {\r\n // This will place the line points in the middle of the bands\r\n // So they center with Labels when scale is ordinal.\r\n let xScale = <D3.Scale.OrdinalScale>this.xAxisProperties.scale;\r\n if (xScale.rangeBand) {\r\n return xScale.rangeBand() / 2;\r\n }\r\n }\r\n return 0;\r\n }\r\n\r\n private hasDataPoint(series: LineChartSeries[]): boolean {\r\n if (series.length === 0)\r\n return false;\r\n for (let i = 0, len = series.length; i < len; i++) {\r\n if (series[i].data.length > 0)\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n private getXValue(d: LineChartDataPoint): any {\r\n return this.data.isScalar ? d.categoryValue : d.categoryIndex;\r\n }\r\n\r\n /**\r\n * This checks to see if a data point is isolated, which means\r\n * the previous and next data point are both null.\r\n */\r\n private shouldDrawCircle(d: LineChartSeries, i: number): boolean {\r\n let dataLength = d.data.length;\r\n let isLastPoint = i === (dataLength - 1);\r\n let isFirstPoint = i === 0;\r\n\r\n if (i > dataLength - 1 || d.data[i] === null || d.data[i].value === null)\r\n return false;\r\n\r\n if (isFirstPoint && isLastPoint)\r\n return true;\r\n if (isFirstPoint && dataLength > 1 && d.data[i + 1].value === null)\r\n return true;\r\n if (!isFirstPoint && isLastPoint && d.data[i - 1].value === null)\r\n return true;\r\n if (!isFirstPoint && !isLastPoint && d.data[i - 1].value === null && d.data[i + 1].value === null)\r\n return true;\r\n return false;\r\n }\r\n\r\n public selectColumnForTooltip(columnIndex: number, force: boolean = false): HoverLineDataPoint[] {\r\n let x = this.getChartX(columnIndex) + this.getXOfFirstCategory();\r\n\r\n let dataPoints = this.createTooltipDataPoints(columnIndex);\r\n if (dataPoints.length > 0) {\r\n this.setHoverLineForTooltip(x);\r\n }\r\n this.setDotsForTooltip(x, dataPoints);\r\n\r\n return dataPoints;\r\n }\r\n\r\n private setHoverLineForTooltip(chartX: number) {\r\n chartX = chartX || 0;\r\n this.hoverLine\r\n .attr('x1', chartX)\r\n .attr('x2', chartX)\r\n .attr(\"y1\", 0)\r\n .attr(\"y2\", this.getAvailableHeight())\r\n .style('opacity', 1);\r\n }\r\n\r\n private setDotsForTooltip(chartX: number, dataPoints: HoverLineDataPoint[]) {\r\n let isStackedArea = EnumExtensions.hasFlag(this.lineType, LineChartType.stackedArea);\r\n let dotYPosition = isStackedArea ? d => this.yAxisProperties.scale(d.stackedValue) : d => this.yAxisProperties.scale(d.value);\r\n let tooltipDots = this.hoverLineContext.selectAll(LineChart.HoverLineCircleDot.selector).data(dataPoints);\r\n tooltipDots\r\n .enter()\r\n .append(LineChart.CircleElementName)\r\n .classed(LineChart.HoverLineCircleDot.class, true);\r\n tooltipDots\r\n .filter(d => d.value)\r\n .attr('fill', d => d.color)\r\n .attr(\"r\", 3)\r\n .attr(\"cx\", chartX)\r\n .attr(\"cy\", dotYPosition);\r\n tooltipDots.exit().remove();\r\n }\r\n\r\n /**\r\n * Updates the hover line and the legend with the selected colums (given by columnIndex).\r\n * This is for the Mobile renderer with InteractiveLegend\r\n */\r\n public selectColumn(columnIndex: number, force: boolean = false) {\r\n if (!force && this.lastInteractiveSelectedColumnIndex === columnIndex) return; // same column, nothing to do here\r\n\r\n this.lastInteractiveSelectedColumnIndex = columnIndex;\r\n let x = this.getChartX(columnIndex);\r\n this.setHoverLine(x, columnIndex);\r\n let legendItems = this.createLegendDataPoints(columnIndex);\r\n if (legendItems)\r\n this.options.cartesianHost.updateLegend(legendItems);\r\n }\r\n\r\n private setHoverLine(chartX: number, columnIndex: number) {\r\n this.hoverLine\r\n .attr('x1', chartX)\r\n .attr('x2', chartX)\r\n .attr(\"y1\", 0).attr(\"y2\", this.getAvailableHeight())\r\n .style('opacity', 1);\r\n\r\n let that = this;\r\n this.mainGraphicsContext\r\n .selectAll(LineChart.CategorySelector.selector)\r\n .selectAll(LineChart.PathElementName)\r\n .each(function (series: LineChartSeries) {\r\n // Get the item color for the handle dots\r\n let color = series.color;\r\n let circleToChange = that.selectionCircles[series.lineIndex];\r\n\r\n circleToChange\r\n .attr({\r\n 'cx': chartX,\r\n 'cy': () => {\r\n let pathElement = d3.select(this).node<D3.D3Element>();\r\n let pos = that.getPosition(chartX, pathElement);\r\n return pos.y;\r\n }\r\n })\r\n .style({\r\n 'opacity': () => _.some(series.data, (value) => value.categoryIndex === columnIndex) ? 1 : 0,\r\n 'fill': color\r\n });\r\n\r\n if (that.dragHandle) that.dragHandle.attr('cx', chartX);\r\n });\r\n }\r\n\r\n private getChartX(columnIndex: number): number {\r\n let x: number = 0;\r\n if (this.data.isScalar) {\r\n if (columnIndex >= 0 && columnIndex < this.data.categoryData.length)\r\n x = Math.max(0, this.xAxisProperties.scale(this.data.categoryData[columnIndex].categoryValue));\r\n } else {\r\n x = Math.max(0, this.xAxisProperties.scale(columnIndex));\r\n }\r\n\r\n let rangeEnd = powerbi.visuals.AxisHelper.extent(this.xAxisProperties.scale)[1];\r\n x = Math.min(x, rangeEnd);\r\n if (!isNaN(x))\r\n return x;\r\n return 0;\r\n }\r\n\r\n /**\r\n * Finds the index of the category of the given x coordinate given.\r\n * pointX is in non-scaled screen-space, and offsetX is in render-space.\r\n * offsetX does not need any scaling adjustment.\r\n * @param {number} pointX The mouse coordinate in screen-space, without scaling applied\r\n * @param {number} offsetX Any left offset in d3.scale render-space\r\n * @return {number}\r\n */\r\n private findIndex(pointX: number, offsetX?: number): number {\r\n // we are using mouse coordinates that do not know about any potential CSS transform scale\r\n let xScale = this.scaleDetector.getScale().x;\r\n if (!Double.equalWithPrecision(xScale, 1.0, 0.00001)) {\r\n pointX = pointX / xScale;\r\n }\r\n if (offsetX) {\r\n pointX += offsetX;\r\n }\r\n\r\n let index = powerbi.visuals.AxisHelper.invertScale(this.xAxisProperties.scale, pointX);\r\n if (this.data.isScalar) {\r\n // When we have scalar data the inverted scale produces a category value, so we need to search for the closest index.\r\n index = AxisHelper.findClosestXAxisIndex(index, this.data.categoryData);\r\n }\r\n\r\n return index;\r\n }\r\n\r\n private getPosition(x: number, pathElement: D3.D3Element): SVGPoint {\r\n let pathLength = pathElement.getTotalLength();\r\n let pos: SVGPoint;\r\n let beginning = 0, end = pathLength, target;\r\n\r\n while (true) {\r\n target = Math.floor((beginning + end) / 2);\r\n pos = pathElement.getPointAtLength(target);\r\n SVGUtil.ensureValidSVGPoint(pos);\r\n if ((target === end || target === beginning) && pos.x !== x)\r\n break;\r\n if (pos.x > x) end = target;\r\n else if (pos.x < x) beginning = target;\r\n else\r\n break;\r\n }\r\n return pos;\r\n }\r\n\r\n private createTooltipDataPoints(columnIndex: number): HoverLineDataPoint[] {\r\n let data = this.data;\r\n if (!data || data.series.length === 0 || !data.categoryData)\r\n return [];\r\n\r\n let dataPoints: HoverLineDataPoint[] = [];\r\n let category: any;\r\n\r\n debug.assert(columnIndex < data.categoryData.length, 'category index out of range');\r\n let categoryDataPoint: LineChartDataPoint = data.categoryData[columnIndex];\r\n if (this.data.isScalar) {\r\n if (categoryDataPoint) {\r\n if (AxisHelper.isDateTime(this.xAxisProperties.axisType)) {\r\n category = CartesianHelper.lookupXValue(this.data, categoryDataPoint.categoryValue, this.xAxisProperties.axisType, this.data.isScalar);\r\n }\r\n else {\r\n category = categoryDataPoint.categoryValue;\r\n }\r\n }\r\n }\r\n else {\r\n category = CartesianHelper.lookupXValue(this.data, columnIndex, this.xAxisProperties.axisType, this.data.isScalar);\r\n }\r\n\r\n let formatStringProp = lineChartProps.general.formatString;\r\n\r\n for (let series of data.series) {\r\n let lineData = series.data;\r\n let lineDataPoint: LineChartDataPoint;\r\n if (this.data.isScalar) {\r\n if (categoryDataPoint) {\r\n lineDataPoint = lineData.filter((data) => {\r\n return data.categoryValue === categoryDataPoint.categoryValue;\r\n })[0];\r\n }\r\n }\r\n else {\r\n lineDataPoint = lineData[columnIndex];\r\n }\r\n\r\n let value = lineDataPoint && lineDataPoint.value;\r\n if (value != null) {\r\n let label = converterHelper.getFormattedLegendLabel(series.yCol, this.dataViewCat.values, formatStringProp);\r\n dataPoints.push({\r\n color: series.color,\r\n label: label,\r\n category: valueFormatter.format(category, valueFormatter.getFormatString(series.xCol, formatStringProp)),\r\n measure: valueFormatter.format(value, valueFormatter.getFormatString(series.yCol, formatStringProp)),\r\n value: value,\r\n stackedValue: lineDataPoint.stackedValue\r\n });\r\n }\r\n }\r\n\r\n return dataPoints;\r\n }\r\n\r\n private createLegendDataPoints(columnIndex: number): LegendData {\r\n let data = this.data;\r\n if (!data || !data.series || data.series.length < 1)\r\n return;\r\n\r\n let legendDataPoints: LegendDataPoint[] = [];\r\n let category: any;\r\n\r\n // 'category' and 'measure' are only for Mobile interactive legend, Minerva legend does not need them\r\n let categoryDataPoint: LineChartDataPoint = data.categoryData[columnIndex];\r\n if (this.isInteractiveChart && categoryDataPoint) {\r\n if (this.data.isScalar) {\r\n category = categoryDataPoint.categoryValue;\r\n if (AxisHelper.isDateTime(this.xAxisProperties.axisType))\r\n category = new Date(category);\r\n }\r\n else {\r\n category = CartesianHelper.lookupXValue(this.data, columnIndex, this.xAxisProperties.axisType, this.data.isScalar);\r\n }\r\n }\r\n\r\n let formatStringProp = lineChartProps.general.formatString;\r\n let seriesYCol: DataViewMetadataColumn = null;\r\n // iterating over the line data (i is for a line)\r\n for (let i = 0, len = data.series.length; i < len; i++) {\r\n let series = data.series[i];\r\n let lineData = series.data;\r\n\r\n // 'category' and 'measure' are only for Mobile interactive legend, Minerva legend does not need them\r\n let measure: any;\r\n if (this.isInteractiveChart) {\r\n let lineDataPoint;\r\n if (this.data.isScalar) {\r\n // Scalar series skip null values, and therefore do not share the same category index\r\n // Search this series for the categoryValue - it may not exist\r\n if (categoryDataPoint) {\r\n let targetCategoryValue = categoryDataPoint.categoryValue;\r\n for (let i = 0; i < lineData.length; i++) {\r\n if (lineData[i].categoryValue === targetCategoryValue) {\r\n lineDataPoint = lineData[i];\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n else {\r\n // ordinal series all share the same x-indicies\r\n lineDataPoint = lineData[columnIndex];\r\n }\r\n measure = lineDataPoint && lineDataPoint.value;\r\n }\r\n\r\n let label = converterHelper.getFormattedLegendLabel(series.yCol, this.dataViewCat.values, formatStringProp);\r\n seriesYCol = series.yCol;\r\n legendDataPoints.push({\r\n color: series.color,\r\n icon: LegendIcon.Line,\r\n label: label,\r\n // TODO: category: CartesianChartInteractiveLegend only needs one category value for part of the Title, we don't need to put it on each point.\r\n category: valueFormatter.format(category, valueFormatter.getFormatString(series.xCol, formatStringProp)),\r\n measure: valueFormatter.format(measure, valueFormatter.getFormatString(series.yCol, formatStringProp)),\r\n identity: series.identity,\r\n selected: series.selected,\r\n });\r\n }\r\n\r\n let dvValues = this.dataViewCat ? this.dataViewCat.values : null;\r\n let title = dvValues && dvValues.source ? dvValues.source.displayName : \"\";\r\n return {\r\n title: title,\r\n dataPoints: legendDataPoints\r\n };\r\n }\r\n\r\n private createLabelDataPoints(): LabelDataPointsGroup[] {\r\n let xScale = this.xAxisProperties.scale;\r\n let yScale = this.yAxisProperties.scale;\r\n let lineshift = this.getXOfFirstCategory();\r\n let data = this.data;\r\n let series = data.series;\r\n let formattersCache = NewDataLabelUtils.createColumnFormatterCacheManager();\r\n let dataLabelsSettings = data.dataLabelsSettings;\r\n let isStackedArea = EnumExtensions.hasFlag(this.lineType, LineChartType.stackedArea);\r\n let labelDataPointsGroups: LabelDataPointsGroup[] = [];\r\n let labelSettings: LineChartDataLabelsSettings;\r\n let axisFormatter: number;\r\n let seriesLabelDataPoints: LabelDataPoint[];\r\n let seriesDataPointsCandidates: LineChartDataPoint[];\r\n let seriesIndex;\r\n let seriesCount;\r\n\r\n for (seriesIndex = 0, seriesCount = series.length; seriesIndex < seriesCount; seriesIndex++) {\r\n let currentSeries = series[seriesIndex];\r\n labelSettings = (currentSeries.labelSettings) ? currentSeries.labelSettings : dataLabelsSettings;\r\n if (!labelSettings.show)\r\n continue;\r\n\r\n axisFormatter = NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yAxisProperties.formatter, labelSettings);\r\n let dataPoints = currentSeries.data;\r\n seriesLabelDataPoints = [];\r\n seriesDataPointsCandidates = [];\r\n\r\n let createLabelDataPoint: (dataPoint: LineChartDataPoint, seriesIndex) => LabelDataPoint = (dataPoint: LineChartDataPoint) => {\r\n if (dataPoint.value == null)\r\n return null;\r\n\r\n let formatString = \"\";\r\n formatString = dataPoint.labelFormatString;\r\n let formatter = formattersCache.getOrCreate(formatString, labelSettings, axisFormatter);\r\n let text = NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\r\n\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties) + NewDataLabelUtils.LabelDensityPadding;\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\r\n let parentShape: LabelParentRect | LabelParentPoint;\r\n let isParentRect: boolean = false;\r\n\r\n if (isStackedArea) {\r\n let bottomPos = Math.max(dataPoint.stackedValue - dataPoint.value, yScale.domain()[0]); //this is to make sure the bottom position doesn't go below the domain\r\n let areaWidth = this.currentViewport.width; // Conceptually, we allow line labels to fill the full plot area, so the width is equal to the plot area\r\n\r\n parentShape = {\r\n rect: {\r\n left: xScale(this.getXValue(dataPoint)) - areaWidth / 2,\r\n top: yScale(Math.max(dataPoint.stackedValue, dataPoint.stackedValue - dataPoint.value)),\r\n width: areaWidth,\r\n height: Math.abs(yScale(dataPoint.stackedValue) - yScale(bottomPos))\r\n },\r\n orientation: dataPoint.value >= 0 ? NewRectOrientation.VerticalBottomBased : NewRectOrientation.VerticalTopBased,\r\n validPositions: LineChart.validStackedLabelPositions,\r\n };\r\n\r\n isParentRect = true;\r\n }\r\n else {\r\n parentShape = {\r\n point: {\r\n x: xScale(this.getXValue(dataPoint)) + lineshift,\r\n y: yScale(dataPoint.value),\r\n },\r\n radius: 0,\r\n validPositions: this.lineChartLabelDensityEnabled ? LineChart.validLabelPositions : [NewPointLabelPosition.Above],\r\n };\r\n }\r\n\r\n let labelDataPoint: LabelDataPoint = {\r\n isPreferred: false,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : NewDataLabelUtils.defaultLabelColor,\r\n insideFill: labelSettings.labelColor && isStackedArea ? labelSettings.labelColor : NewDataLabelUtils.defaultInsideLabelColor,\r\n parentType: isParentRect ? LabelDataPointParentType.Rectangle : LabelDataPointParentType.Point,\r\n parentShape: parentShape,\r\n fontSize: labelSettings.fontSize,\r\n identity: dataPoint.identity,\r\n key: dataPoint.key,\r\n };\r\n return labelDataPoint;\r\n };\r\n\r\n if (!_.isEmpty(dataPoints)) {\r\n let categoryCount = dataPoints.length;\r\n let lastDataPoint = dataPoints[categoryCount - 1];\r\n let lastLabelDataPoint = createLabelDataPoint(lastDataPoint, seriesIndex);\r\n if (lastLabelDataPoint)\r\n seriesLabelDataPoints.push(lastLabelDataPoint);\r\n for (let categoryIndex = 0; categoryIndex < categoryCount - 1; categoryIndex++) {\r\n let labelDataPoint = createLabelDataPoint(dataPoints[categoryIndex], seriesIndex);\r\n if (labelDataPoint)\r\n seriesLabelDataPoints.push(labelDataPoint);\r\n }\r\n }\r\n\r\n let maxLabelsToRender = dataPoints.length;\r\n labelDataPointsGroups[seriesIndex] = {\r\n labelDataPoints: seriesLabelDataPoints,\r\n maxNumberOfLabels: maxLabelsToRender,\r\n };\r\n }\r\n\r\n return labelDataPointsGroups;\r\n }\r\n\r\n /**\r\n * Adjust a mouse coordinate originating from a path; used to fix\r\n * an inconsistency between Internet Explorer and other browsers.\r\n *\r\n * Internet explorer places the origin for the coordinate system of\r\n * mouse events based on the stroke, so that the very edge of the stroke\r\n * is zero. Chrome places the 0 on the edge of the path so that the\r\n * edge of the stroke is -(strokeWidth / 2). We adjust coordinates\r\n * to match Chrome.\r\n *\r\n * TODO: Firefox is similar to IE, but does a very poor job at it, so\r\n * the edge is inacurate.\r\n *\r\n * @param value The x coordinate to be adjusted\r\n */\r\n private adjustPathXCoordinate(x: number): number {\r\n if (this.shouldAdjustMouseCoordsOnPathsForStroke) {\r\n let xScale = this.scaleDetector.getScale().x;\r\n if (!Double.equalWithPrecision(xScale, 1.0, 0.00001)) {\r\n x -= LineChart.pathXAdjustment * xScale;\r\n }\r\n else {\r\n x -= LineChart.pathXAdjustment;\r\n }\r\n }\r\n return x;\r\n }\r\n\r\n //private isMinMax(index: number, dataPoints: LineChartDataPoint[]): boolean {\r\n // // Check if the point is the start/end point\r\n // if (!dataPoints[index - 1] || !dataPoints[index + 1])\r\n // return true;\r\n\r\n // let currentValue = dataPoints[index].value;\r\n // let prevValue = dataPoints[index - 1].value;\r\n // let nextValue = dataPoints[index + 1].value;\r\n // return (prevValue > currentValue && currentValue < nextValue) // Min point\r\n // || (prevValue < currentValue && currentValue > nextValue); // Max point\r\n //}\r\n\r\n //private calculatePointsWeight(labelDataPoints: LabelDataPoint[], dataPointsCandidates: LineChartDataPoint[], minIndex: number, maxIndex: number) {\r\n // let previousMinMaxIndex = 0;\r\n // labelDataPoints[0].weight = dataPointsCandidates[0].weight = 0;\r\n // let previousMinMax: LineChartDataPoint = dataPointsCandidates[0];\r\n // let dataPointCount = labelDataPoints.length;\r\n // let yScale = this.yAxisProperties.scale;\r\n // let totalValueDelta = yScale(dataPointsCandidates[maxIndex].value) - yScale(dataPointsCandidates[minIndex].value);\r\n\r\n // for (let i = 1; i < dataPointCount; i++) {\r\n // let dataPoint = dataPointsCandidates[i];\r\n // let weight = (Math.abs(yScale(previousMinMax.value) - yScale(dataPoint.value))) / totalValueDelta + (i - previousMinMaxIndex) / dataPointCount;\r\n // labelDataPoints[i].weight = weight;\r\n // if (this.isMinMax(i, dataPointsCandidates)) {\r\n // previousMinMax.weight += weight;\r\n // previousMinMax = dataPoint;\r\n // previousMinMaxIndex = i;\r\n // }\r\n // }\r\n //}\r\n\r\n //private sortByWeightAndPreferrance(a: LabelDataPoint, b: LabelDataPoint): number {\r\n // // Compare by prederrance first\r\n // if (!a.isPreferred && b.isPreferred) return 1;\r\n // if (a.isPreferred && !b.isPreferred) return -1;\r\n // // Compare by weight\r\n // if ((!a.weight && b.weight) || (a.weight < b.weight)) return 1;\r\n // if ((a.weight && !b.weight) || (a.weight > b.weight)) return -1;\r\n // return 0;\r\n //}\r\n\r\n private showLabelPerSeries(): boolean {\r\n let data = this.data;\r\n return !data.hasDynamicSeries && (data.series.length > 1 || !data.categoryMetadata);\r\n }\r\n\r\n /**\r\n * Obtains the pointLabelPosition for the category index within the given series\r\n *\r\n * Rules for line chart data labels:\r\n * 1. Top and bottom > left and right\r\n * 2. Top > bottom unless we're at a local minimum\r\n * 3. Right > left unless:\r\n * a. There is no data point to the left and there is one to the right\r\n * b. There is an equal data point to the right, but not to the left\r\n */\r\n //private getValidLabelPositions(series: LineChartSeries, categoryIndex: number): NewPointLabelPosition[]{\r\n // let data = series.data;\r\n // let dataLength = data.length;\r\n // let isLastPoint = categoryIndex === (dataLength - 1);\r\n // let isFirstPoint = categoryIndex === 0;\r\n\r\n // let currentValue = data[categoryIndex].value;\r\n // let previousValue = !isFirstPoint ? data[categoryIndex - 1].value : undefined;\r\n // let nextValue = !isLastPoint ? data[categoryIndex + 1].value : undefined;\r\n // let previousRelativePosition = LineChartRelativePosition.equal;\r\n // let nextRelativePosition = LineChartRelativePosition.equal;\r\n // if (previousValue === null || previousValue === undefined) {\r\n // previousRelativePosition = LineChartRelativePosition.none;\r\n // }\r\n // else if (previousValue > currentValue) {\r\n // previousRelativePosition = LineChartRelativePosition.greater;\r\n // }\r\n // else if (previousValue < currentValue) {\r\n // previousRelativePosition = LineChartRelativePosition.lesser;\r\n // }\r\n // if (nextValue === null || nextValue === undefined) {\r\n // nextRelativePosition = LineChartRelativePosition.none;\r\n // }\r\n // else if (nextValue > currentValue) {\r\n // nextRelativePosition = LineChartRelativePosition.greater;\r\n // }\r\n // else if (nextValue < currentValue) {\r\n // nextRelativePosition = LineChartRelativePosition.lesser;\r\n // }\r\n\r\n // switch (previousRelativePosition) {\r\n // case LineChartRelativePosition.none:\r\n // switch (nextRelativePosition) {\r\n // case LineChartRelativePosition.none:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.equal:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Left, NewPointLabelPosition.Right];\r\n // case LineChartRelativePosition.greater:\r\n // return [NewPointLabelPosition.Below, NewPointLabelPosition.Above, NewPointLabelPosition.Left, NewPointLabelPosition.Right];\r\n // case LineChartRelativePosition.lesser:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Left, NewPointLabelPosition.Right];\r\n // }\r\n // case LineChartRelativePosition.equal:\r\n // switch (nextRelativePosition) {\r\n // case LineChartRelativePosition.none:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.equal:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.greater:\r\n // return [NewPointLabelPosition.Below, NewPointLabelPosition.Above, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.lesser:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // }\r\n // case LineChartRelativePosition.greater:\r\n // switch (nextRelativePosition) {\r\n // case LineChartRelativePosition.none:\r\n // return [NewPointLabelPosition.Below, NewPointLabelPosition.Above, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.equal:\r\n // return [NewPointLabelPosition.Below, NewPointLabelPosition.Above, NewPointLabelPosition.Left, NewPointLabelPosition.Right];\r\n // case LineChartRelativePosition.greater:\r\n // return [NewPointLabelPosition.Below, NewPointLabelPosition.Above, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.lesser:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // }\r\n // case LineChartRelativePosition.lesser:\r\n // switch (nextRelativePosition) {\r\n // case LineChartRelativePosition.none:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.equal:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Left, NewPointLabelPosition.Right];\r\n // case LineChartRelativePosition.greater:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // case LineChartRelativePosition.lesser:\r\n // return [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Right, NewPointLabelPosition.Left];\r\n // }\r\n // }\r\n //}\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import Color = jsCommon.Color;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import Polygon = shapes.Polygon;\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n\r\n export interface MapConstructionOptions {\r\n filledMap?: boolean;\r\n geocoder?: IGeocoder;\r\n mapControlFactory?: IMapControlFactory;\r\n behavior?: MapBehavior;\r\n tooltipsEnabled?: boolean;\r\n filledMapDataLabelsEnabled?: boolean;\r\n disableZooming?: boolean;\r\n disablePanning?: boolean;\r\n isLegendScrollable?: boolean;\r\n viewChangeThrottleInterval?: number; // Minimum interval between viewChange events (in milliseconds)\r\n enableCurrentLocation?: boolean;\r\n }\r\n\r\n export interface IMapControlFactory {\r\n createMapControl(element: HTMLElement, options?: Microsoft.Maps.MapOptions): Microsoft.Maps.Map;\r\n ensureMap(locale: string, action: () => void): void;\r\n }\r\n\r\n export interface MapData {\r\n dataPoints: MapDataPoint[];\r\n geocodingCategory: string;\r\n hasDynamicSeries: boolean;\r\n hasSize: boolean;\r\n }\r\n\r\n /**\r\n * The main map data point, which exists for each category\r\n */\r\n export interface MapDataPoint {\r\n geocodingQuery: string;\r\n value: number;\r\n categoryValue: string;\r\n subDataPoints: MapSubDataPoint[];\r\n location?: IGeocodeCoordinate;\r\n paths?: IGeocodeBoundaryPolygon[];\r\n radius?: number;\r\n }\r\n\r\n /**\r\n * SubDataPoint that carries series-based data. For category only maps\r\n * there will only be one of these on each MapDataPoint; for dynamic series,\r\n * there will be one per series for each MapDataPoint.\r\n */\r\n export interface MapSubDataPoint {\r\n value: number;\r\n fill: string;\r\n stroke: string;\r\n identity: SelectionId;\r\n tooltipInfo: TooltipDataItem[];\r\n }\r\n\r\n export interface MapRendererData {\r\n bubbleData?: MapBubble[];\r\n sliceData?: MapSlice[][];\r\n shapeData?: MapShape[];\r\n }\r\n\r\n export interface MapVisualDataPoint extends TooltipEnabledDataPoint, SelectableDataPoint {\r\n x: number;\r\n y: number;\r\n radius: number;\r\n fill: string;\r\n stroke: string;\r\n strokeWidth: number;\r\n labeltext: string;\r\n labelFill: string;\r\n }\r\n\r\n export interface MapBubble extends MapVisualDataPoint {\r\n }\r\n\r\n export interface MapSlice extends MapVisualDataPoint {\r\n value: number;\r\n startAngle?: number;\r\n endAngle?: number;\r\n }\r\n\r\n export interface MapShape extends TooltipEnabledDataPoint, SelectableDataPoint {\r\n absolutePointArray: Float64Array;\r\n path: string;\r\n fill: string;\r\n stroke: string;\r\n strokeWidth: number;\r\n key: string;\r\n labeltext: string;\r\n displayLabel: boolean;\r\n catagoryLabeltext?: string;\r\n labelFormatString: string;\r\n }\r\n\r\n /**\r\n * Used because data points used in D3 pie layouts are placed within a container with pie information.\r\n */\r\n export interface MapSliceContainer {\r\n data: MapSlice;\r\n }\r\n\r\n /** Note: public for UnitTest */\r\n export interface IMapDataPointRenderer {\r\n init(mapControl: Microsoft.Maps.Map, mapDiv: JQuery, addClearCatcher: boolean): void;\r\n setData(data: MapData): void;\r\n getDataPointCount(): number;\r\n converter(viewPort: IViewport, dataView: DataView, labelSettings: PointDataLabelsSettings, interactivityService: IInteractivityService, tooltipsEnabled: boolean): MapRendererData;\r\n updateInternal(data: MapRendererData, viewport: IViewport, dataChanged: boolean, interactivityService: IInteractivityService, redrawDataLabels: boolean): MapBehaviorOptions;\r\n updateInternalDataLabels(viewport: IViewport, redrawDataLabels: boolean): void;\r\n getDataPointPadding(): number;\r\n clearDataPoints(): void;\r\n }\r\n\r\n export interface DataViewMetadataAutoGeneratedColumn extends DataViewMetadataColumn {\r\n /**\r\n * Indicates that the column was added manually.\r\n */\r\n isAutoGeneratedColumn?: boolean;\r\n }\r\n\r\n export const MaxLevelOfDetail = 23;\r\n export const MinLevelOfDetail = 1;\r\n export const DefaultFillOpacity = 0.5;\r\n export const DefaultBackgroundColor = \"#000000\";\r\n export const LeaderLineColor = \"#000000\";\r\n\r\n export class MapBubbleDataPointRenderer implements IMapDataPointRenderer {\r\n private mapControl: Microsoft.Maps.Map;\r\n private mapData: MapData;\r\n private maxDataPointRadius: number;\r\n private svg: D3.Selection;\r\n private clearSvg: D3.Selection;\r\n private clearCatcher: D3.Selection;\r\n private bubbleGraphicsContext: D3.Selection;\r\n private sliceGraphicsContext: D3.Selection;\r\n private labelGraphicsContext: D3.Selection;\r\n private labelBackgroundGraphicsContext: D3.Selection;\r\n private sliceLayout: D3.Layout.PieLayout;\r\n private arc: D3.Svg.Arc;\r\n private dataLabelsSettings: PointDataLabelsSettings;\r\n private tooltipsEnabled: boolean;\r\n private static validLabelPositions: NewPointLabelPosition[] = [NewPointLabelPosition.Above, NewPointLabelPosition.Below, NewPointLabelPosition.Left, NewPointLabelPosition.Right];\r\n private mapRendererData: MapRendererData;\r\n private root: JQuery;\r\n\r\n public constructor(tooltipsEnabled: boolean) {\r\n this.tooltipsEnabled = tooltipsEnabled;\r\n }\r\n\r\n public init(mapControl: Microsoft.Maps.Map, mapDiv: JQuery, addClearCatcher: boolean): void {\r\n /*\r\n The layout of the visual would look like :\r\n <div class=\"visual mapControl\">\r\n <div class=\"MicrosoftMap\">\r\n <!-- Bing maps stuff -->\r\n <svg>\r\n <rect class=\"clearCatcher\"></rect>\r\n </svg>\r\n </div>\r\n <svg>\r\n <g class=\"mapBubbles>\r\n <!-- our geometry -->\r\n </g>\r\n <g class=\"mapSlices>\r\n <!-- our geometry -->\r\n </g>\r\n </svg>\r\n </div>\r\n\r\n */\r\n\r\n this.mapControl = mapControl;\r\n this.root = mapDiv;\r\n let root = d3.select(mapDiv[0]);\r\n root.attr(\"drag-resize-disabled\", \"true\"); // Enable panning within the maps in IE\r\n let svg = this.svg = root\r\n .append('svg')\r\n .style(\"position\", \"absolute\") // Absolute position so that the svg will overlap with the canvas.\r\n .style(\"pointer-events\", \"none\");\r\n if (addClearCatcher) {\r\n let clearSvg = this.clearSvg = d3.select(<HTMLElement>this.mapControl.getRootElement())\r\n .append('svg')\r\n .style('position', 'absolute'); // Absolute position so that the svg will overlap with the canvas.\r\n this.clearCatcher = appendClearCatcher(clearSvg);\r\n }\r\n this.bubbleGraphicsContext = svg\r\n .append(\"g\")\r\n .classed(\"mapBubbles\", true);\r\n this.sliceGraphicsContext = svg\r\n .append(\"g\")\r\n .classed(\"mapSlices\", true);\r\n this.labelBackgroundGraphicsContext = svg\r\n .append(\"g\")\r\n .classed(NewDataLabelUtils.labelBackgroundGraphicsContextClass.class, true);\r\n this.labelGraphicsContext = svg\r\n .append(\"g\")\r\n .classed(NewDataLabelUtils.labelGraphicsContextClass.class, true);\r\n this.sliceLayout = d3.layout.pie()\r\n .sort(null)\r\n .value((d: MapSlice) => {\r\n return d.value;\r\n });\r\n this.arc = d3.svg.arc();\r\n this.clearMaxDataPointRadius();\r\n this.dataLabelsSettings = dataLabelUtils.getDefaultMapLabelSettings();\r\n }\r\n\r\n public setData(data: MapData): void {\r\n this.mapData = data;\r\n }\r\n\r\n public clearDataPoints(): void {\r\n this.mapData = {\r\n dataPoints: [],\r\n geocodingCategory: null,\r\n hasDynamicSeries: false,\r\n hasSize: false,\r\n };\r\n }\r\n\r\n public getDataPointCount(): number {\r\n if (!this.mapData)\r\n return 0;\r\n // Filter out any data points without a location since those aren't actually being drawn\r\n return _.filter(this.mapData.dataPoints, (value: MapDataPoint) => !!value.location).length;\r\n }\r\n\r\n public getDataPointPadding(): number {\r\n return this.maxDataPointRadius * 2;\r\n }\r\n\r\n private clearMaxDataPointRadius(): void {\r\n this.maxDataPointRadius = 0;\r\n }\r\n\r\n private setMaxDataPointRadius(dataPointRadius: number): void {\r\n this.maxDataPointRadius = Math.max(dataPointRadius, this.maxDataPointRadius);\r\n }\r\n\r\n public getDefaultMap(geocodingCategory: string, dataPointCount: number): void {\r\n this.clearDataPoints();\r\n }\r\n\r\n public converter(viewport: IViewport, dataView: DataView, labelSettings: PointDataLabelsSettings, interactivityService: IInteractivityService, tooltipsEnabled: boolean = true): MapRendererData {\r\n let mapControl = this.mapControl;\r\n let widthOverTwo = viewport.width / 2;\r\n let heightOverTwo = viewport.height / 2;\r\n\r\n let strokeWidth = 1;\r\n\r\n //update data label settings\r\n this.dataLabelsSettings = labelSettings;\r\n\r\n // See MapSeriesPresenter::GetDataPointRadius for the PV behavior\r\n let radiusScale = Math.min(viewport.width, viewport.height) / 384;\r\n this.clearMaxDataPointRadius();\r\n\r\n let bubbleData: MapBubble[] = [];\r\n let sliceData: MapSlice[][] = [];\r\n let categorical: DataViewCategorical = dataView ? dataView.categorical : null;\r\n\r\n let grouped: DataViewValueColumnGroup[];\r\n let sizeIndex = -1;\r\n let dataValuesSource: DataViewMetadataColumn;\r\n if (categorical && categorical.values) {\r\n grouped = categorical.values.grouped();\r\n sizeIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, \"Size\");\r\n dataValuesSource = categorical.values.source;\r\n }\r\n\r\n let dataPoints = this.mapData ? this.mapData.dataPoints : [];\r\n let hasSize = this.mapData.hasSize;\r\n for (let categoryIndex = 0, categoryCount = dataPoints.length; categoryIndex < categoryCount; categoryIndex++) {\r\n let dataPoint = dataPoints[categoryIndex];\r\n let categoryValue = dataPoint.categoryValue;\r\n let location = dataPoint.location;\r\n\r\n if (location) {\r\n let xy = mapControl.tryLocationToPixel(new Microsoft.Maps.Location(location.latitude, location.longitude));\r\n let x = xy.x + widthOverTwo;\r\n let y = xy.y + heightOverTwo;\r\n\r\n let radius = dataPoint.radius * radiusScale;\r\n this.setMaxDataPointRadius(radius);\r\n let subDataPoints = dataPoint.subDataPoints;\r\n\r\n let seriesCount = subDataPoints.length;\r\n if (seriesCount === 1) {\r\n let subDataPoint: MapSubDataPoint = subDataPoints[0];\r\n\r\n bubbleData.push({\r\n x: x,\r\n y: y,\r\n labeltext: categoryValue,\r\n radius: radius,\r\n fill: subDataPoint.fill,\r\n stroke: subDataPoint.stroke,\r\n strokeWidth: strokeWidth,\r\n tooltipInfo: subDataPoint.tooltipInfo,\r\n identity: subDataPoint.identity,\r\n selected: false,\r\n labelFill: labelSettings.labelColor,\r\n });\r\n }\r\n else {\r\n let slices = [];\r\n\r\n for (var seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\r\n let subDataPoint: MapSubDataPoint = subDataPoints[seriesIndex];\r\n let value = hasSize ? subDataPoint.value : 1; // Normalize values if there is no size in the data\r\n\r\n slices.push({\r\n x: x,\r\n y: y,\r\n labeltext: categoryValue,\r\n radius: radius,\r\n fill: subDataPoint.fill,\r\n stroke: subDataPoint.stroke,\r\n strokeWidth: strokeWidth,\r\n value: value,\r\n tooltipInfo: subDataPoint.tooltipInfo,\r\n identity: subDataPoint.identity,\r\n selected: false,\r\n labelFill: labelSettings.labelColor,\r\n });\r\n }\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(slices);\r\n }\r\n sliceData.push(slices);\r\n }\r\n }\r\n }\r\n\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(bubbleData);\r\n }\r\n\r\n return { bubbleData: bubbleData, sliceData: sliceData };\r\n }\r\n\r\n public updateInternal(data: MapRendererData, viewport: IViewport, dataChanged: boolean, interactivityService: IInteractivityService, redrawDataLabels: boolean): MapBehaviorOptions {\r\n debug.assertValue(viewport, \"viewport\");\r\n Map.removeTransform3d(this.root);\r\n\r\n this.mapRendererData = data;\r\n if (this.svg) {\r\n this.svg\r\n .style(\"width\", viewport.width.toString() + \"px\")\r\n .style(\"height\", viewport.height.toString() + \"px\");\r\n }\r\n if (this.clearSvg) {\r\n this.clearSvg\r\n .style(\"width\", viewport.width.toString() + \"px\")\r\n .style(\"height\", viewport.height.toString() + \"px\");\r\n }\r\n\r\n let arc = this.arc;\r\n\r\n let hasSelection = interactivityService && interactivityService.hasSelection();\r\n\r\n let bubbles = this.bubbleGraphicsContext.selectAll(\".bubble\").data(data.bubbleData, (d: MapBubble) => d.identity.getKey());\r\n\r\n bubbles.enter()\r\n .append(\"circle\")\r\n .classed(\"bubble\", true);\r\n bubbles\r\n .attr(\"cx\", (d: MapBubble) => d.x)\r\n .attr(\"cy\", (d: MapBubble) => d.y)\r\n .attr(\"r\", (d: MapBubble) => d.radius)\r\n .style(\"fill\", (d: MapBubble) => d.fill)\r\n .style(\"stroke\", (d: MapBubble) => d.stroke)\r\n .style(\"fill-opacity\", (d: MapBubble) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false))\r\n .style(\"strokeWidth\", (d: MapBubble) => d.strokeWidth)\r\n .style(\"stroke-opacity\", (d: MapBubble) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false))\r\n .style(\"cursor\", \"default\");\r\n bubbles.exit().remove();\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(this.bubbleGraphicsContext, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n bubbles.style(\"pointer-events\", \"all\");\r\n }\r\n\r\n let sliceData = data.sliceData;\r\n\r\n let sliceContainers = this.sliceGraphicsContext.selectAll(\".sliceContainer\").data(sliceData);\r\n sliceContainers.enter()\r\n .append(\"g\")\r\n .classed(\"sliceContainer\", true);\r\n\r\n sliceContainers.exit().remove();\r\n\r\n let sliceLayout = this.sliceLayout;\r\n let slices = sliceContainers.selectAll(\".slice\")\r\n .data(function (d) {\r\n return sliceLayout(d);\r\n }, (d: MapSliceContainer) => d.data.identity.getKey());\r\n\r\n slices.enter()\r\n .append(\"path\")\r\n .classed(\"slice\", true);\r\n\r\n slices\r\n .style(\"fill\", (t: MapSliceContainer) => t.data.fill)\r\n .style(\"fill-opacity\", (d) => ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false))\r\n .style(\"stroke\", (t: MapSliceContainer) => t.data.stroke)\r\n .style(\"strokeWidth\", (t: MapSliceContainer) => t.data.strokeWidth)\r\n .style(\"stroke-opacity\", (d) => ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, false))\r\n .style(\"cursor\", \"default\")\r\n .attr(\"transform\", (t: MapSliceContainer) => SVGUtil.translate(t.data.x, t.data.y))\r\n .attr('d', (t: MapSliceContainer) => {\r\n return arc.innerRadius(0).outerRadius((t: MapSliceContainer) => t.data.radius)(t);\r\n });\r\n\r\n slices.exit().remove();\r\n\r\n this.updateInternalDataLabels(viewport, redrawDataLabels);\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(this.sliceGraphicsContext, (tooltipEvent: TooltipEvent) => tooltipEvent.data.data.tooltipInfo);\r\n slices.style(\"pointer-events\", \"all\");\r\n }\r\n\r\n let allData: SelectableDataPoint[] = data.bubbleData.slice();\r\n for (let i = 0, ilen = sliceData.length; i < ilen; i++) {\r\n allData.push.apply(allData, sliceData[i]);\r\n }\r\n\r\n let behaviorOptions: MapBehaviorOptions = {\r\n bubbleEventGroup: this.bubbleGraphicsContext,\r\n sliceEventGroup: this.sliceGraphicsContext,\r\n bubbles: bubbles,\r\n slices: slices,\r\n clearCatcher: this.clearCatcher,\r\n dataPoints: allData,\r\n };\r\n return behaviorOptions;\r\n }\r\n\r\n public updateInternalDataLabels(viewport: IViewport, redrawDataLabels: boolean): void {\r\n let labelSettings = this.dataLabelsSettings;\r\n let dataLabels: Label[] = [];\r\n if (labelSettings && (labelSettings.show || labelSettings.showCategory)) {\r\n let labelDataPoints = this.createLabelDataPoints();\r\n let labelLayout = new LabelLayout({\r\n maximumOffset: NewDataLabelUtils.maxLabelOffset,\r\n startingOffset: NewDataLabelUtils.startingLabelOffset\r\n });\r\n let labelDataPointsGroup: LabelDataPointsGroup = {\r\n labelDataPoints: labelDataPoints,\r\n maxNumberOfLabels: labelDataPoints.length\r\n };\r\n dataLabels = labelLayout.layout([labelDataPointsGroup], { width: viewport.width, height: viewport.height });\r\n }\r\n\r\n NewDataLabelUtils.drawLabelBackground(this.labelGraphicsContext, dataLabels, powerbi.visuals.DefaultBackgroundColor, powerbi.visuals.DefaultFillOpacity);\r\n NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, dataLabels, false); // Once we properly split up and handle show and showCategory, the false here should change to !labelSettings.showCategory\r\n }\r\n\r\n private createLabelDataPoints(): LabelDataPoint[] {\r\n let data = this.mapRendererData;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n let dataPoints = data.bubbleData;\r\n dataPoints = dataPoints.concat(_.map(data.sliceData, (value: MapSlice[]) => value[0]));\r\n let labelSettings = this.dataLabelsSettings;\r\n\r\n for (let dataPoint of dataPoints) {\r\n debug.assertValue(dataPoint, 'dataPoint should never be null/undefined');\r\n let text = dataPoint.labeltext;\r\n\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties);\r\n\r\n labelDataPoints.push({\r\n isPreferred: true,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : NewDataLabelUtils.defaultInsideLabelColor, // Use inside for outside colors because we draw backgrounds for map labels\r\n insideFill: NewDataLabelUtils.defaultInsideLabelColor,\r\n parentType: LabelDataPointParentType.Point,\r\n parentShape: {\r\n point: {\r\n x: dataPoint.x,\r\n y: dataPoint.y,\r\n },\r\n radius: dataPoint.radius,\r\n validPositions: MapBubbleDataPointRenderer.validLabelPositions,\r\n },\r\n fontSize: labelSettings.fontSize,\r\n identity: undefined,\r\n hasBackground: true,\r\n });\r\n }\r\n\r\n return labelDataPoints;\r\n }\r\n }\r\n\r\n export interface FilledMapParams {\r\n level: number;\r\n maxPolygons: number;\r\n strokeWidth: number;\r\n }\r\n\r\n export class MapShapeDataPointRenderer implements IMapDataPointRenderer {\r\n private mapControl: Microsoft.Maps.Map;\r\n private svg: D3.Selection;\r\n private clearSvg: D3.Selection;\r\n private clearCatcher: D3.Selection;\r\n private polygonInfo: MapPolygonInfo;\r\n private mapData: MapData;\r\n private shapeGraphicsContext: D3.Selection;\r\n private labelGraphicsContext: D3.Selection;\r\n private labelBackgroundGraphicsContext: D3.Selection;\r\n private maxShapeDimension: number;\r\n private mapRendererData: MapRendererData;\r\n private dataLabelsSettings: PointDataLabelsSettings;\r\n private filledMapDataLabelsEnabled: boolean;\r\n private tooltipsEnabled: boolean;\r\n private labelLayout: FilledMapLabelLayout;\r\n private static validLabelPolygonPositions: NewPointLabelPosition[] = [NewPointLabelPosition.Center, NewPointLabelPosition.Below, NewPointLabelPosition.Above, NewPointLabelPosition.Right, NewPointLabelPosition.Left, NewPointLabelPosition.BelowRight, NewPointLabelPosition.BelowLeft, NewPointLabelPosition.AboveRight, NewPointLabelPosition.AboveLeft];\r\n private root: JQuery;\r\n\r\n public static getFilledMapParams(category: string, dataCount: number): FilledMapParams {\r\n switch (category) {\r\n case MapUtil.CategoryTypes.Continent:\r\n case MapUtil.CategoryTypes.CountryRegion:\r\n if (dataCount < 10) {\r\n return { level: 1, maxPolygons: 50, strokeWidth: 0 };\r\n }\r\n else if (dataCount < 30) {\r\n return { level: 1, maxPolygons: 20, strokeWidth: 0 };\r\n }\r\n return { level: 1, maxPolygons: 5, strokeWidth: 0 };\r\n default:\r\n if (dataCount < 100) {\r\n return { level: 1, maxPolygons: 5, strokeWidth: 6 };\r\n }\r\n if (dataCount < 200) {\r\n return { level: 0, maxPolygons: 5, strokeWidth: 6 };\r\n }\r\n return { level: 0, maxPolygons: 5, strokeWidth: 0 };\r\n }\r\n }\r\n\r\n public static buildPaths(locations: IGeocodeBoundaryPolygon[]): IGeocodeBoundaryPolygon[] {\r\n let paths = [];\r\n for (let i = 0; i < locations.length; i++) {\r\n let location = locations[i];\r\n let polygon = location.geographic;\r\n\r\n if (polygon.length > 2) {\r\n paths.push(location);\r\n }\r\n }\r\n\r\n return paths;\r\n }\r\n\r\n public constructor(fillMapDataLabelsEnabled: boolean, tooltipsEnabled: boolean) {\r\n this.filledMapDataLabelsEnabled = fillMapDataLabelsEnabled;\r\n this.tooltipsEnabled = tooltipsEnabled;\r\n }\r\n\r\n public init(mapControl: Microsoft.Maps.Map, mapDiv: JQuery, addClearCatcher: boolean): void {\r\n /*\r\n The layout of the visual would look like :\r\n <div class=\"visual mapControl\">\r\n <div class=\"MicrosoftMap\">\r\n <!-- Bing maps stuff -->\r\n <svg>\r\n <rect class=\"clearCatcher\"></rect>\r\n </svg>\r\n </div>\r\n <svg>\r\n <g class=\"mapShapes>\r\n <!-- our geometry -->\r\n </g>\r\n </svg>\r\n </div>\r\n\r\n */\r\n\r\n this.mapControl = mapControl;\r\n this.polygonInfo = new MapPolygonInfo();\r\n\r\n this.root = mapDiv;\r\n let root = d3.select(mapDiv[0]);\r\n root.attr('drag-resize-disabled', 'true'); // Enable panning within the maps in IE\r\n let svg = this.svg = root\r\n .append('svg')\r\n .style('position', 'absolute') // Absolute position so that the svg will overlap with the canvas.\r\n .style(\"pointer-events\", \"none\");\r\n if (addClearCatcher) {\r\n let clearSvg = this.clearSvg = d3.select(<HTMLElement>this.mapControl.getRootElement())\r\n .append('svg')\r\n .style('position', 'absolute'); // Absolute position so that the svg will overlap with the canvas.\r\n this.clearCatcher = appendClearCatcher(clearSvg);\r\n }\r\n this.shapeGraphicsContext = svg\r\n .append('g')\r\n .classed('mapShapes', true);\r\n this.labelBackgroundGraphicsContext = svg\r\n .append(\"g\")\r\n .classed(NewDataLabelUtils.labelBackgroundGraphicsContextClass.class, true);\r\n this.labelGraphicsContext = svg\r\n .append(\"g\")\r\n .classed(NewDataLabelUtils.labelGraphicsContextClass.class, true);\r\n\r\n this.clearMaxShapeDimension();\r\n this.dataLabelsSettings = dataLabelUtils.getDefaultMapLabelSettings();\r\n }\r\n\r\n public setData(data: MapData): void {\r\n this.mapData = data;\r\n }\r\n\r\n public clearDataPoints(): void {\r\n this.mapData = {\r\n dataPoints: [],\r\n geocodingCategory: null,\r\n hasDynamicSeries: false,\r\n hasSize: false,\r\n };\r\n }\r\n\r\n public getDataPointCount(): number {\r\n if (!this.mapData)\r\n return 0;\r\n // Filter out any data points without a location since those aren't actually being drawn\r\n return _.filter(this.mapData.dataPoints, (value: MapDataPoint) => !!value.paths).length;\r\n }\r\n\r\n public converter(viewport: IViewport, dataView: DataView, labelSettings: PointDataLabelsSettings, interactivityService?: IInteractivityService): MapRendererData {\r\n this.clearMaxShapeDimension();\r\n this.dataLabelsSettings = labelSettings;\r\n let strokeWidth = 1;\r\n\r\n let shapeData: MapShape[] = [];\r\n\r\n let dataPoints = this.mapData ? this.mapData.dataPoints : [];\r\n for (let categoryIndex = 0, categoryCount = dataPoints.length; categoryIndex < categoryCount; categoryIndex++) {\r\n let categorical: DataViewCategorical = dataView ? dataView.categorical : null;\r\n let dataPoint: MapDataPoint = dataPoints[categoryIndex];\r\n let subDataPoint = dataPoint.subDataPoints[0];\r\n let paths = dataPoint.paths;\r\n\r\n let grouped: DataViewValueColumnGroup[];\r\n let sizeIndex = -1;\r\n let dataValuesSource: DataViewMetadataColumn;\r\n\r\n if (categorical && categorical.values) {\r\n grouped = categorical.values.grouped();\r\n sizeIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, \"Size\");\r\n dataValuesSource = categorical.values.source;\r\n }\r\n\r\n if (paths) {\r\n let value = dataPoint.value;\r\n let categoryValue = dataPoint.categoryValue;\r\n\r\n let identity = subDataPoint.identity;\r\n let idKey = identity.getKey();\r\n let formattersCache = NewDataLabelUtils.createColumnFormatterCacheManager();\r\n\r\n //Determine Largest Shape\r\n let mainShapeIndex = MapShapeDataPointRenderer.getIndexOfLargestShape(paths);\r\n\r\n for (let pathIndex = 0, pathCount = paths.length; pathIndex < pathCount; pathIndex++) {\r\n let path = paths[pathIndex];\r\n let labelFormatString = (dataView && dataView.categorical && !_.isEmpty(dataView.categorical.values)) ? valueFormatter.getFormatString(dataView.categorical.values[0].source, filledMapProps.general.formatString) : undefined;\r\n this.setMaxShapeDimension(path.absoluteBounds.width, path.absoluteBounds.height);\r\n let formatter = formattersCache.getOrCreate(labelFormatString, labelSettings);\r\n\r\n shapeData.push({\r\n absolutePointArray: path.absolute,\r\n path: path.absoluteString,\r\n fill: subDataPoint.fill,\r\n stroke: subDataPoint.stroke,\r\n strokeWidth: strokeWidth,\r\n tooltipInfo: subDataPoint.tooltipInfo,\r\n identity: identity,\r\n selected: false,\r\n key: JSON.stringify({ id: idKey, pIdx: pathIndex }),\r\n displayLabel: pathIndex === mainShapeIndex,\r\n labeltext: categoryValue,\r\n catagoryLabeltext: (value != null) ? NewDataLabelUtils.getLabelFormattedText(formatter.format(value)) : undefined,\r\n labelFormatString: labelFormatString,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (interactivityService)\r\n interactivityService.applySelectionStateToData(shapeData);\r\n\r\n return { shapeData: shapeData };\r\n }\r\n\r\n public updateInternal(data: MapRendererData, viewport: IViewport, dataChanged: boolean, interactivityService: IInteractivityService, redrawDataLabels: boolean): MapBehaviorOptions {\r\n debug.assertValue(viewport, \"viewport\");\r\n Map.removeTransform3d(this.root);\r\n\r\n this.mapRendererData = data;\r\n if (this.svg) {\r\n this.svg\r\n .style(\"width\", viewport.width.toString() + \"px\")\r\n .style(\"height\", viewport.height.toString() + \"px\");\r\n }\r\n if (this.clearSvg) {\r\n this.clearSvg\r\n .style(\"width\", viewport.width.toString() + \"px\")\r\n .style(\"height\", viewport.height.toString() + \"px\");\r\n }\r\n\r\n this.polygonInfo.reCalc(this.mapControl, viewport.width, viewport.height);\r\n this.shapeGraphicsContext.attr(\"transform\", this.polygonInfo.transformToString(this.polygonInfo.transform));\r\n\r\n let hasSelection = interactivityService && interactivityService.hasSelection();\r\n\r\n let shapes = this.shapeGraphicsContext.selectAll(\"polygon\").data(data.shapeData, (d: MapShape) => d.key);\r\n\r\n shapes.enter()\r\n .append(\"polygon\")\r\n .classed(\"shape\", true)\r\n .attr(\"points\", (d: MapShape) => { // Always add paths to any new data points\r\n return d.path;\r\n });\r\n\r\n shapes\r\n .style(\"fill\", (d: MapShape) => d.fill)\r\n .style(\"fill-opacity\", (d: MapShape) => ColumnUtil.getFillOpacity(d.selected, false, hasSelection, false))\r\n .style(\"cursor\", \"default\");\r\n\r\n if (dataChanged) {\r\n // We only update the paths of existing shapes if we have a change in the data. Updating the lengthy path\r\n // strings every update during resize or zooming/panning is extremely bad for performance.\r\n shapes\r\n .attr(\"points\", (d: MapShape) => {\r\n return d.path;\r\n });\r\n }\r\n\r\n shapes.exit()\r\n .remove();\r\n\r\n this.updateInternalDataLabels(viewport, redrawDataLabels);\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(this.shapeGraphicsContext, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n shapes.style(\"pointer-events\", \"all\");\r\n }\r\n\r\n let behaviorOptions: MapBehaviorOptions = {\r\n shapeEventGroup: this.shapeGraphicsContext,\r\n shapes: shapes,\r\n clearCatcher: this.clearCatcher,\r\n dataPoints: data.shapeData,\r\n };\r\n\r\n return behaviorOptions;\r\n }\r\n\r\n public getDataPointPadding() {\r\n return 12;\r\n }\r\n\r\n public static getIndexOfLargestShape(paths: IGeocodeBoundaryPolygon[]): number {\r\n let largestShapeIndex = 0;\r\n let largestShapeArea = 0;\r\n\r\n for (let pathIndex = 0, pathCount = paths.length; pathIndex < pathCount; pathIndex++) {\r\n let path = paths[pathIndex];\r\n\r\n // Using the area of the polygon (and taking the largest)\r\n let polygon = new Polygon(path.absolute);\r\n let currentShapeArea = Math.abs(Polygon.calculateAbsolutePolygonArea(polygon.polygonPoints));\r\n\r\n if (currentShapeArea > largestShapeArea) {\r\n largestShapeIndex = pathIndex;\r\n largestShapeArea = currentShapeArea;\r\n }\r\n }\r\n\r\n return largestShapeIndex;\r\n }\r\n\r\n public updateInternalDataLabels(viewport: IViewport, redrawDataLabels: boolean): void {\r\n let labelSettings = this.dataLabelsSettings;\r\n let labels: Label[];\r\n\r\n if (labelSettings && (labelSettings.show || labelSettings.showCategory)) {\r\n let labelDataPoints = this.createLabelDataPoints();\r\n\r\n if (this.labelLayout === undefined) {\r\n this.labelLayout = new FilledMapLabelLayout();\r\n }\r\n labels = this.labelLayout.layout(labelDataPoints, { width: viewport.width, height: viewport.height }, this.polygonInfo.transform, redrawDataLabels);\r\n }\r\n\r\n this.drawLabelStems(this.labelGraphicsContext, labels, labelSettings.show, labelSettings.showCategory);\r\n NewDataLabelUtils.drawLabelBackground(this.labelGraphicsContext, labels, powerbi.visuals.DefaultBackgroundColor, powerbi.visuals.DefaultFillOpacity);\r\n NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, labels, false, labelSettings.show && labelSettings.showCategory);\r\n }\r\n\r\n private clearMaxShapeDimension(): void {\r\n this.maxShapeDimension = 0;\r\n }\r\n\r\n private setMaxShapeDimension(width: number, height: number): void {\r\n this.maxShapeDimension = Math.max(width, this.maxShapeDimension);\r\n this.maxShapeDimension = Math.max(height, this.maxShapeDimension);\r\n }\r\n\r\n private createLabelDataPoints(): LabelDataPoint[] {\r\n let data = this.mapRendererData;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n if (this.filledMapDataLabelsEnabled) {\r\n let dataShapes = data.shapeData;\r\n let labelSettings = this.dataLabelsSettings;\r\n\r\n for (let dataShape of dataShapes) {\r\n\r\n if (!dataShape.displayLabel) {\r\n continue;\r\n }\r\n let text, secondRowText: string;\r\n let secondRowTextWidth: number = 0;\r\n let hasSecondRow: boolean = false;\r\n\r\n if (this.dataLabelsSettings.show && !this.dataLabelsSettings.showCategory) {\r\n text = dataShape.catagoryLabeltext;\r\n if (text === undefined)\r\n continue;\r\n } else if (this.dataLabelsSettings.showCategory && !this.dataLabelsSettings.show) {\r\n text = dataShape.labeltext;\r\n if (text === undefined)\r\n continue;\r\n } else if (this.dataLabelsSettings.showCategory && this.dataLabelsSettings.show) {\r\n text = dataShape.catagoryLabeltext;\r\n secondRowText = dataShape.labeltext;\r\n if (text === undefined && secondRowText === undefined)\r\n continue;\r\n hasSecondRow = true;\r\n }\r\n\r\n if (hasSecondRow) {\r\n let secondRowProperties: TextProperties = {\r\n text: secondRowText,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: NewDataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n secondRowTextWidth = TextMeasurementService.measureSvgTextWidth(secondRowProperties);\r\n }\r\n\r\n let firstRowProperties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: NewDataLabelUtils.LabelTextProperties.fontSize,\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(firstRowProperties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(firstRowProperties);\r\n\r\n if (secondRowText && dataShape.labeltext !== undefined && dataShape.catagoryLabeltext !== undefined) {\r\n textHeight = textHeight * 2;\r\n }\r\n\r\n let labelDataPoint: LabelDataPoint = {\r\n parentType: LabelDataPointParentType.Polygon,\r\n parentShape:\r\n {\r\n polygon: new Polygon(dataShape.absolutePointArray),\r\n validPositions: MapShapeDataPointRenderer.validLabelPolygonPositions,\r\n },\r\n text: text,\r\n secondRowText: secondRowText,\r\n textSize: {\r\n width: Math.max(textWidth, secondRowTextWidth),\r\n height: textHeight,\r\n },\r\n insideFill: labelSettings.labelColor,\r\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : NewDataLabelUtils.defaultInsideLabelColor, // Use inside for outside colors because we draw backgrounds for map labels\r\n isPreferred: false,\r\n identity: undefined,\r\n hasBackground: true,\r\n };\r\n labelDataPoints.push(labelDataPoint);\r\n }\r\n }\r\n return labelDataPoints;\r\n }\r\n\r\n private drawLabelStems(labelsContext: D3.Selection, dataLabels: Label[], showText: boolean, showCategory: boolean) {\r\n let filteredLabels = _.filter(dataLabels, (d: Label) => d.isVisible);\r\n let key = (d: Label, index: number) => { return d.identity ? d.identity.getKeyWithoutHighlight() : index; };\r\n NewDataLabelUtils.drawLabelLeaderLines(labelsContext, filteredLabels, key, LeaderLineColor);\r\n }\r\n }\r\n\r\n /** Note: public for UnitTest */\r\n export interface SimpleRange {\r\n min: number;\r\n max: number;\r\n }\r\n\r\n /**\r\n * Interface used to track geocoding requests, a new context being created on each data change.\r\n * For now, it's empty and is used just used to track whether the context has changed so that\r\n * we don't add data points for old geocode requests. If we add additional tracking information\r\n * for geocoding, this is where it can live.\r\n */\r\n interface GeocodingContext {\r\n }\r\n\r\n const DefaultLocationZoomLevel = 11;\r\n\r\n export class Map implements IVisual {\r\n public currentViewport: IViewport;\r\n\r\n private pendingGeocodingRender: boolean;\r\n private mapControl: Microsoft.Maps.Map;\r\n private minLongitude: number;\r\n private maxLongitude: number;\r\n private minLatitude: number;\r\n private maxLatitude: number;\r\n private style: IVisualStyle;\r\n private colors: IDataColorPalette;\r\n private dataPointRenderer: IMapDataPointRenderer;\r\n private geocodingCategory: string;\r\n private legend: ILegend;\r\n private legendHeight;\r\n private legendData: LegendData;\r\n private element: JQuery;\r\n private dataView: DataView;\r\n private dataLabelsSettings: PointDataLabelsSettings;\r\n private static MapContainer = {\r\n cssClass: 'mapControl',\r\n selector: '.mapControl'\r\n };\r\n public static StrokeDarkenColorValue = 255 * 0.25;\r\n private interactivityService: IInteractivityService;\r\n private behavior: MapBehavior;\r\n private defaultDataPointColor: string;\r\n private showAllDataPoints: boolean;\r\n private dataPointsToEnumerate: LegendDataPoint[];\r\n private hasDynamicSeries: boolean;\r\n private geoTaggingAnalyzerService: powerbi.IGeoTaggingAnalyzerService;\r\n private isFilledMap: boolean;\r\n private host: IVisualHostServices;\r\n private geocoder: IGeocoder;\r\n private mapControlFactory: IMapControlFactory;\r\n private tooltipsEnabled: boolean;\r\n private filledMapDataLabelsEnabled: boolean;\r\n private disableZooming: boolean;\r\n private disablePanning: boolean;\r\n private locale: string;\r\n private isLegendScrollable: boolean;\r\n private viewChangeThrottleInterval: number;\r\n private root: JQuery;\r\n private enableCurrentLocation: boolean;\r\n private isCurrentLocation: boolean;\r\n private boundsHaveBeenUpdated: boolean;\r\n private geocodingContext: GeocodingContext;\r\n\r\n constructor(options: MapConstructionOptions) {\r\n if (options.filledMap) {\r\n this.dataPointRenderer = new MapShapeDataPointRenderer(options.filledMapDataLabelsEnabled, options.tooltipsEnabled);\r\n this.filledMapDataLabelsEnabled = options.filledMapDataLabelsEnabled;\r\n this.isFilledMap = true;\r\n }\r\n else {\r\n this.dataPointRenderer = new MapBubbleDataPointRenderer(options.tooltipsEnabled);\r\n this.isFilledMap = false;\r\n }\r\n this.mapControlFactory = options.mapControlFactory ? options.mapControlFactory : this.getDefaultMapControlFactory();\r\n this.behavior = options.behavior;\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n this.disableZooming = options.disableZooming;\r\n this.disablePanning = options.disablePanning;\r\n this.isLegendScrollable = !!options.behavior;\r\n this.viewChangeThrottleInterval = options.viewChangeThrottleInterval;\r\n this.enableCurrentLocation = options.enableCurrentLocation;\r\n this.boundsHaveBeenUpdated = false;\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n debug.assertValue(options, 'options');\r\n let element = this.element = $(\"<div>\");\r\n element.appendTo(options.element);\r\n this.pendingGeocodingRender = false;\r\n this.currentViewport = options.viewport;\r\n this.style = options.style;\r\n this.colors = this.style.colorPalette.dataColors;\r\n if (this.behavior)\r\n this.interactivityService = createInteractivityService(options.host);\r\n this.dataLabelsSettings = dataLabelUtils.getDefaultMapLabelSettings();\r\n this.legend = powerbi.visuals.createLegend(element, options.interactivity && options.interactivity.isInteractiveLegend, this.interactivityService, this.isLegendScrollable);\r\n this.legendHeight = 0;\r\n this.legendData = { dataPoints: [] };\r\n this.geoTaggingAnalyzerService = powerbi.createGeoTaggingAnalyzerService(options.host.getLocalizedString);\r\n this.host = options.host;\r\n if (options.host.locale)\r\n this.locale = options.host.locale();\r\n this.geocoder = options.host.geocoder();\r\n\r\n this.resetBounds();\r\n\r\n this.mapControlFactory.ensureMap(this.locale, () => {\r\n Map.removeHillShading();\r\n Microsoft.Maps.loadModule('Microsoft.Maps.Overlays.Style', {\r\n callback: () => {\r\n this.initialize(element[0]);\r\n if (this.enableCurrentLocation) {\r\n this.createCurrentLocation(element);\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n private createCurrentLocation(element: JQuery): void {\r\n let myLocBtn = InJs.DomFactory.div().addClass(\"mapCurrentLocation\").appendTo(element);\r\n let pushpin: Microsoft.Maps.Pushpin;\r\n\r\n myLocBtn.on('click',() => {\r\n\r\n if (this.isCurrentLocation) {\r\n // Restore previous map view and remove pushpin\r\n if (pushpin) {\r\n this.mapControl.entities.remove(pushpin);\r\n }\r\n this.updateInternal(false, false);\r\n this.isCurrentLocation = false;\r\n } else {\r\n this.host.geolocation().getCurrentPosition((position: Position) => {\r\n let location = new Microsoft.Maps.Location(position.coords.latitude, position.coords.longitude);\r\n if (pushpin) {\r\n this.mapControl.entities.remove(pushpin);\r\n }\r\n pushpin = MapUtil.CurrentLocation.createPushpin(location);\r\n this.mapControl.entities.push(pushpin);\r\n this.updateMapView(location, DefaultLocationZoomLevel);\r\n this.isCurrentLocation = true;\r\n });\r\n }\r\n\r\n });\r\n }\r\n\r\n private addDataPoint(dataPoint: MapDataPoint): void {\r\n let location = dataPoint.location;\r\n this.updateBounds(location.latitude, location.longitude);\r\n\r\n this.scheduleRedraw();\r\n }\r\n\r\n private scheduleRedraw(): void {\r\n if (!this.pendingGeocodingRender && this.mapControl) {\r\n this.pendingGeocodingRender = true;\r\n // Maintain a 3 second delay between redraws from geocoded geometry\r\n setTimeout(() => {\r\n this.updateInternal(true, true);\r\n this.pendingGeocodingRender = false;\r\n }, 3000);\r\n }\r\n }\r\n\r\n private enqueueGeoCode(dataPoint: MapDataPoint): void {\r\n let location = this.geocoder.tryGeocodeImmediate(dataPoint.geocodingQuery, this.geocodingCategory);\r\n if (location)\r\n this.completeGeoCode(dataPoint, location);\r\n else {\r\n let geocodingContext = this.geocodingContext;\r\n this.geocoder.geocode(dataPoint.geocodingQuery, this.geocodingCategory).then((location) => {\r\n if (location && geocodingContext === this.geocodingContext) {\r\n this.completeGeoCode(dataPoint, location);\r\n }\r\n });\r\n }\r\n }\r\n\r\n private completeGeoCode(dataPoint: MapDataPoint, location: IGeocodeCoordinate): void {\r\n dataPoint.location = location;\r\n this.addDataPoint(dataPoint);\r\n }\r\n\r\n private enqueueGeoCodeAndGeoShape(dataPoint: MapDataPoint, params: FilledMapParams): void {\r\n let location = this.geocoder.tryGeocodeImmediate(dataPoint.geocodingQuery, this.geocodingCategory);\r\n if (location)\r\n this.completeGeoCodeAndGeoShape(dataPoint, params, location);\r\n else {\r\n let geocodingContext = this.geocodingContext;\r\n this.geocoder.geocode(dataPoint.geocodingQuery, this.geocodingCategory).then((location) => {\r\n if (location && geocodingContext === this.geocodingContext) {\r\n this.completeGeoCodeAndGeoShape(dataPoint, params, location);\r\n }\r\n });\r\n }\r\n }\r\n\r\n private completeGeoCodeAndGeoShape(dataPoint: MapDataPoint, params: FilledMapParams, location: IGeocodeCoordinate): void {\r\n dataPoint.location = location;\r\n this.enqueueGeoShape(dataPoint, params);\r\n }\r\n\r\n private enqueueGeoShape(dataPoint: MapDataPoint, params: FilledMapParams): void {\r\n debug.assertValue(dataPoint.location, \"cachedLocation\");\r\n let result = this.geocoder.tryGeocodeBoundaryImmediate(dataPoint.location.latitude, dataPoint.location.longitude, this.geocodingCategory, params.level, params.maxPolygons);\r\n if (result)\r\n this.completeGeoShape(dataPoint, params, result);\r\n else {\r\n let geocodingContext = this.geocodingContext;\r\n this.geocoder.geocodeBoundary(dataPoint.location.latitude, dataPoint.location.longitude, this.geocodingCategory, params.level, params.maxPolygons)\r\n .then((result: IGeocodeBoundaryCoordinate) => {\r\n if (geocodingContext === this.geocodingContext)\r\n this.completeGeoShape(dataPoint, params, result);\r\n });\r\n }\r\n }\r\n\r\n private completeGeoShape(dataPoint: MapDataPoint, params: FilledMapParams, result: IGeocodeBoundaryCoordinate): void {\r\n let paths;\r\n if (result.locations.length === 0 || result.locations[0].geographic) {\r\n paths = MapShapeDataPointRenderer.buildPaths(result.locations);\r\n }\r\n else {\r\n MapUtil.calcGeoData(result);\r\n paths = MapShapeDataPointRenderer.buildPaths(result.locations);\r\n }\r\n dataPoint.paths = paths;\r\n this.addDataPoint(dataPoint);\r\n }\r\n\r\n private getOptimumLevelOfDetail(width: number, height: number): number {\r\n let dataPointCount = this.dataPointRenderer.getDataPointCount();\r\n if (dataPointCount === 0)\r\n return MapUtil.MinLevelOfDetail;\r\n\r\n let threshold: number = this.dataPointRenderer.getDataPointPadding();\r\n\r\n for (let levelOfDetail = MapUtil.MaxLevelOfDetail; levelOfDetail >= MapUtil.MinLevelOfDetail; levelOfDetail--) {\r\n let minXmaxY = MapUtil.latLongToPixelXY(this.minLatitude, this.minLongitude, levelOfDetail);\r\n let maxXminY = MapUtil.latLongToPixelXY(this.maxLatitude, this.maxLongitude, levelOfDetail);\r\n\r\n if (maxXminY.x - minXmaxY.x + threshold <= width && minXmaxY.y - maxXminY.y + threshold <= height) {\r\n // if we have less than 2 data points we should not zoom in \"too much\"\r\n if (dataPointCount < 2)\r\n levelOfDetail = Math.min(MapUtil.MaxAutoZoomLevel, levelOfDetail);\r\n\r\n return levelOfDetail;\r\n }\r\n }\r\n\r\n return MapUtil.MinLevelOfDetail;\r\n }\r\n private getViewCenter(levelOfDetail: number): Microsoft.Maps.Location {\r\n let minXmaxY = MapUtil.latLongToPixelXY(this.minLatitude, this.minLongitude, levelOfDetail);\r\n let maxXminY = MapUtil.latLongToPixelXY(this.maxLatitude, this.maxLongitude, levelOfDetail);\r\n return MapUtil.pixelXYToLocation((minXmaxY.x + maxXminY.x) / 2.0, (maxXminY.y + minXmaxY.y) / 2.0, levelOfDetail);\r\n }\r\n\r\n private resetBounds(): void {\r\n this.boundsHaveBeenUpdated = false;\r\n this.minLongitude = MapUtil.MaxAllowedLongitude;\r\n this.maxLongitude = MapUtil.MinAllowedLongitude;\r\n this.minLatitude = MapUtil.MaxAllowedLatitude;\r\n this.maxLatitude = MapUtil.MinAllowedLatitude;\r\n }\r\n\r\n private updateBounds(latitude: number, longitude: number): void {\r\n this.boundsHaveBeenUpdated = true;\r\n if (longitude < this.minLongitude) {\r\n this.minLongitude = longitude;\r\n }\r\n\r\n if (longitude > this.maxLongitude) {\r\n this.maxLongitude = longitude;\r\n }\r\n\r\n if (latitude < this.minLatitude) {\r\n this.minLatitude = latitude;\r\n }\r\n\r\n if (latitude > this.maxLatitude) {\r\n this.maxLatitude = latitude;\r\n }\r\n }\r\n\r\n public static legendObject(dataView: DataView): DataViewObject {\r\n return dataView &&\r\n dataView.metadata &&\r\n dataView.metadata.objects &&\r\n <DataViewObject>dataView.metadata.objects['legend'];\r\n }\r\n\r\n public static isLegendHidden(dataView: DataView): boolean {\r\n let legendObject = Map.legendObject(dataView);\r\n return legendObject != null && legendObject[legendProps.show] === false;\r\n }\r\n\r\n public static legendPosition(dataView: DataView): LegendPosition {\r\n let legendObject = Map.legendObject(dataView);\r\n return legendObject && LegendPosition[<string>legendObject[legendProps.position]];\r\n }\r\n\r\n public static getLegendFontSize(dataView: DataView): number {\r\n let legendObject = Map.legendObject(dataView);\r\n return (legendObject && <number>legendObject[legendProps.fontSize]) || SVGLegend.DefaultFontSizeInPt;\r\n }\r\n\r\n public static isShowLegendTitle(dataView: DataView): boolean {\r\n let legendObject = Map.legendObject(dataView);\r\n return legendObject && <boolean>legendObject[legendProps.showTitle];\r\n }\r\n\r\n private legendTitle(): string {\r\n let legendObject = Map.legendObject(this.dataView);\r\n return (legendObject && <string>legendObject[legendProps.titleText]) || this.legendData.title;\r\n }\r\n\r\n private renderLegend(legendData: LegendData): void {\r\n let hideLegend = Map.isLegendHidden(this.dataView);\r\n let showTitle = Map.isShowLegendTitle(this.dataView);\r\n let title = this.legendTitle();\r\n // Update the legendData based on the hide flag. Cartesian passes in no-datapoints. OnResize reuses the legendData, so this can't mutate.\r\n let clonedLegendData: LegendData = {\r\n dataPoints: hideLegend ? [] : legendData.dataPoints,\r\n grouped: legendData.grouped,\r\n title: showTitle ? title : \"\",\r\n fontSize: Map.getLegendFontSize(this.dataView)\r\n };\r\n\r\n // Update the orientation to match what's in the dataView\r\n let targetOrientation = Map.legendPosition(this.dataView);\r\n if (targetOrientation !== undefined) {\r\n this.legend.changeOrientation(targetOrientation);\r\n } else {\r\n this.legend.changeOrientation(LegendPosition.Top);\r\n }\r\n\r\n this.legend.drawLegend(clonedLegendData, this.currentViewport);\r\n }\r\n\r\n /** Note: public for UnitTest */\r\n public static calculateGroupSizes(categorical: DataViewCategorical, grouped: DataViewValueColumnGroup[], groupSizeTotals: number[], sizeMeasureIndex: number, currentValueScale: SimpleRange): SimpleRange {\r\n let categoryCount = categorical.values[0].values.length;\r\n let seriesCount = grouped.length;\r\n\r\n for (let i = 0, len = categoryCount; i < len; ++i) {\r\n let groupTotal = null;\r\n if (sizeMeasureIndex >= 0) {\r\n for (let j = 0; j < seriesCount; ++j) {\r\n let value = grouped[j].values[sizeMeasureIndex].values[i];\r\n if (value) {\r\n if (groupTotal === null) {\r\n groupTotal = value;\r\n } else {\r\n groupTotal += value;\r\n }\r\n }\r\n }\r\n }\r\n\r\n groupSizeTotals.push(groupTotal);\r\n\r\n if (groupTotal) {\r\n if (!currentValueScale) {\r\n currentValueScale = {\r\n min: groupTotal,\r\n max: groupTotal\r\n };\r\n } else {\r\n currentValueScale.min = Math.min(currentValueScale.min, groupTotal);\r\n currentValueScale.max = Math.max(currentValueScale.max, groupTotal);\r\n }\r\n }\r\n }\r\n\r\n return currentValueScale;\r\n }\r\n\r\n /** Note: public for UnitTest */\r\n public static calculateRadius(range: SimpleRange, value?: number): number {\r\n let rangeDiff = range ? range.max - range.min : 0;\r\n let radius = 6;\r\n if (range != null && value != null && rangeDiff !== 0) {\r\n radius = (14 * ((value - range.min) / rangeDiff)) + 6;\r\n }\r\n\r\n return radius;\r\n }\r\n\r\n /** Note: public for UnitTest */\r\n public static getGeocodingCategory(categorical: DataViewCategorical, geoTaggingAnalyzerService: IGeoTaggingAnalyzerService): string {\r\n if (categorical && categorical.categories && categorical.categories.length > 0 && categorical.categories[0].source) {\r\n // Check categoryString for manually specified information in the model\r\n let type = <ValueType>categorical.categories[0].source.type;\r\n if (type && type.categoryString) {\r\n return geoTaggingAnalyzerService.getFieldType(type.categoryString);\r\n }\r\n\r\n // Check the category name\r\n let categoryName = categorical.categories[0].source.displayName;\r\n let geotaggedResult = geoTaggingAnalyzerService.getFieldType(categoryName);\r\n if (geotaggedResult)\r\n return geotaggedResult;\r\n\r\n // Checking roles for VRM backwards compatibility\r\n let roles = categorical.categories[0].source.roles;\r\n if (roles) {\r\n let roleNames = Object.keys(roles);\r\n for (let i = 0, len = roleNames.length; i < len; ++i) {\r\n let typeFromRoleName = geoTaggingAnalyzerService.getFieldType(roleNames[i]);\r\n if (typeFromRoleName)\r\n return typeFromRoleName;\r\n }\r\n }\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n /** Note: public for UnitTest */\r\n public static hasSizeField(values: DataViewValueColumns, defaultIndexIfNoRole?: number): boolean {\r\n if (_.isEmpty(values))\r\n return false;\r\n\r\n for (let i = 0, ilen = values.length; i < ilen; i++) {\r\n let roles = values[i].source.roles;\r\n\r\n // case for Power Q&A since Power Q&A does not assign role to measures.\r\n if (!roles && i === defaultIndexIfNoRole && values[i].source.type.numeric)\r\n return true;\r\n\r\n if (roles) {\r\n let roleNames = Object.keys(roles);\r\n for (let j = 0, jlen = roleNames.length; j < jlen; j++) {\r\n let role = roleNames[j];\r\n if (role === \"Size\")\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n public static shouldEnumerateDataPoints(dataView: DataView, usesSizeForGradient: boolean): boolean {\r\n let hasSeries = DataRoleHelper.hasRoleInDataView(dataView, 'Series');\r\n let gradientRole = usesSizeForGradient ? 'Size' : 'Gradient';\r\n let hasGradientRole = DataRoleHelper.hasRoleInDataView(dataView, gradientRole);\r\n return hasSeries || !hasGradientRole;\r\n }\r\n\r\n public static shouldEnumerateCategoryLabels(isFilledMap: boolean, filledMapDataLabelsEnabled: boolean): boolean {\r\n return (!isFilledMap || filledMapDataLabelsEnabled);\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n switch (options.objectName) {\r\n case 'dataPoint':\r\n if (Map.shouldEnumerateDataPoints(this.dataView, this.isFilledMap)) {\r\n let bubbleData: MapBubble[] = [];\r\n //TODO: better way of getting this data\r\n let hasDynamicSeries = this.hasDynamicSeries;\r\n if (!hasDynamicSeries) {\r\n let mapData = this.dataPointRenderer.converter(this.getMapViewPort(), this.dataView, this.dataLabelsSettings, this.interactivityService, this.tooltipsEnabled);\r\n bubbleData = mapData.bubbleData;\r\n }\r\n Map.enumerateDataPoints(enumeration, this.dataPointsToEnumerate, this.colors, hasDynamicSeries, this.defaultDataPointColor, this.showAllDataPoints, bubbleData);\r\n }\r\n break;\r\n case 'categoryLabels':\r\n if (Map.shouldEnumerateCategoryLabels(this.isFilledMap, this.filledMapDataLabelsEnabled)) {\r\n dataLabelUtils.enumerateCategoryLabels(enumeration, this.dataLabelsSettings, true, true);\r\n }\r\n break;\r\n case 'legend':\r\n if (this.hasDynamicSeries) {\r\n Map.enumerateLegend(enumeration, this.dataView, this.legend, this.legendTitle());\r\n }\r\n break;\r\n case 'labels':\r\n if (this.filledMapDataLabelsEnabled) {\r\n this.dataLabelsSettings = this.dataLabelsSettings ? this.dataLabelsSettings : dataLabelUtils.getDefaultMapLabelSettings();\r\n let labelSettingOptions: VisualDataLabelsSettingsOptions = {\r\n enumeration: enumeration,\r\n dataLabelsSettings: this.dataLabelsSettings,\r\n show: true,\r\n displayUnits: true,\r\n precision: true,\r\n };\r\n dataLabelUtils.enumerateDataLabels(labelSettingOptions);\r\n }\r\n break;\r\n }\r\n return enumeration.complete();\r\n }\r\n\r\n public static enumerateDataPoints(enumeration: ObjectEnumerationBuilder, dataPoints: LegendDataPoint[], colors: IDataColorPalette, hasDynamicSeries: boolean, defaultDataPointColor: string, showAllDataPoints: boolean, bubbleData: MapBubble[]): void {\r\n let seriesLength = dataPoints && dataPoints.length;\r\n\r\n if (hasDynamicSeries) {\r\n for (let i = 0; i < seriesLength; i++) {\r\n\r\n let dataPoint = dataPoints[i];\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: dataPoint.label,\r\n selector: ColorHelper.normalizeSelector(dataPoint.identity.getSelector()),\r\n properties: {\r\n fill: { solid: { color: dataPoint.color } }\r\n },\r\n });\r\n }\r\n }\r\n else {\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n selector: null,\r\n properties: {\r\n defaultColor: { solid: { color: defaultDataPointColor || colors.getColorByIndex(0).value } }\r\n },\r\n }).pushInstance({\r\n objectName: 'dataPoint',\r\n selector: null,\r\n properties: {\r\n showAllDataPoints: !!showAllDataPoints\r\n },\r\n });\r\n\r\n if (bubbleData) {\r\n for (let i = 0; i < bubbleData.length; i++) {\r\n let bubbleDataPoint = bubbleData[i];\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: bubbleDataPoint.labeltext,\r\n selector: ColorHelper.normalizeSelector(bubbleDataPoint.identity.getSelector()),\r\n properties: {\r\n fill: { solid: { color: Color.normalizeToHexString(bubbleDataPoint.fill) } }\r\n },\r\n });\r\n }\r\n }\r\n\r\n }\r\n }\r\n\r\n public static enumerateLegend(enumeration: ObjectEnumerationBuilder, dataView: DataView, legend: ILegend, legendTitle: string): void {\r\n enumeration.pushInstance({\r\n selector: null,\r\n properties: {\r\n show: !Map.isLegendHidden(dataView),\r\n position: LegendPosition[legend.getOrientation()],\r\n showTitle: Map.isShowLegendTitle(dataView),\r\n titleText: legendTitle,\r\n fontSize: Map.getLegendFontSize(dataView)\r\n },\r\n objectName: 'legend'\r\n });\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n this.resetBounds();\r\n this.geocodingContext = {};\r\n\r\n if (this.behavior)\r\n this.behavior.resetZoomPan();\r\n\r\n this.dataLabelsSettings = dataLabelUtils.getDefaultMapLabelSettings();\r\n this.defaultDataPointColor = null;\r\n this.showAllDataPoints = null;\r\n let dataView = this.dataView = options.dataViews[0];\r\n let isFilledMap = this.isFilledMap;\r\n let warnings = [];\r\n let data: MapData = {\r\n dataPoints: [],\r\n geocodingCategory: null,\r\n hasDynamicSeries: false,\r\n hasSize: false,\r\n };\r\n\r\n if (dataView) {\r\n // Handle object-based settings\r\n if (dataView.metadata && dataView.metadata.objects) {\r\n let objects = dataView.metadata.objects;\r\n\r\n this.defaultDataPointColor = DataViewObjects.getFillColor(objects, mapProps.dataPoint.defaultColor);\r\n this.showAllDataPoints = DataViewObjects.getValue<boolean>(objects, mapProps.dataPoint.showAllDataPoints);\r\n\r\n this.dataLabelsSettings.showCategory = DataViewObjects.getValue<boolean>(objects, filledMapProps.categoryLabels.show, this.dataLabelsSettings.showCategory);\r\n\r\n if (isFilledMap) {\r\n this.dataLabelsSettings.precision = DataViewObjects.getValue(objects, filledMapProps.labels.labelPrecision, this.dataLabelsSettings.precision);\r\n this.dataLabelsSettings.precision = (this.dataLabelsSettings.precision !== dataLabelUtils.defaultLabelPrecision && this.dataLabelsSettings.precision < 0) ? 0 : this.dataLabelsSettings.precision;\r\n this.dataLabelsSettings.displayUnits = DataViewObjects.getValue<number>(objects, filledMapProps.labels.labelDisplayUnits, this.dataLabelsSettings.displayUnits);\r\n let datalabelsObj = objects['labels'];\r\n if (datalabelsObj) {\r\n this.dataLabelsSettings.show = (datalabelsObj['show'] !== undefined) ? <boolean>datalabelsObj['show'] : this.dataLabelsSettings.show;\r\n if (datalabelsObj['color'] !== undefined) {\r\n this.dataLabelsSettings.labelColor = (<Fill>datalabelsObj['color']).solid.color;\r\n }\r\n }\r\n }\r\n else {\r\n let categoryLabelsObj = <DataLabelObject>objects['categoryLabels'];\r\n if (categoryLabelsObj)\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(categoryLabelsObj, this.dataLabelsSettings);\r\n }\r\n }\r\n\r\n // Convert data\r\n let colorHelper = new ColorHelper(this.colors, mapProps.dataPoint.fill, this.defaultDataPointColor);\r\n data = Map.converter(dataView, colorHelper, this.geoTaggingAnalyzerService, isFilledMap);\r\n this.hasDynamicSeries = data.hasDynamicSeries;\r\n\r\n // Create legend\r\n this.legendData = Map.createLegendData(dataView, colorHelper);\r\n this.dataPointsToEnumerate = this.legendData.dataPoints;\r\n this.renderLegend(this.legendData);\r\n\r\n // Start geocoding or geoshaping\r\n if (data != null) {\r\n this.geocodingCategory = data.geocodingCategory;\r\n this.mapControlFactory.ensureMap(this.locale, () => {\r\n Map.removeHillShading();\r\n let params;\r\n if (isFilledMap) {\r\n params = MapShapeDataPointRenderer.getFilledMapParams(this.geocodingCategory, data.dataPoints.length);\r\n }\r\n for (let dataPoint of data.dataPoints) {\r\n if (!dataPoint.location) {\r\n if (!_.isEmpty(dataPoint.categoryValue)) { // If we don't have a location, but the category string is empty, skip geocoding so we don't geocode null/empty string\r\n if (isFilledMap)\r\n this.enqueueGeoCodeAndGeoShape(dataPoint, params);\r\n else\r\n this.enqueueGeoCode(dataPoint);\r\n }\r\n }\r\n else if (isFilledMap && !dataPoint.paths) {\r\n this.enqueueGeoShape(dataPoint, params);\r\n }\r\n else {\r\n this.addDataPoint(dataPoint);\r\n }\r\n }\r\n });\r\n }\r\n else {\r\n // No data from conversion, so clear data points\r\n this.clearDataPoints();\r\n }\r\n\r\n if (isFilledMap) {\r\n if (!this.geocodingCategory || !this.geoTaggingAnalyzerService.isGeoshapable(this.geocodingCategory)) {\r\n warnings.push(new FilledMapWithoutValidGeotagCategoryWarning());\r\n }\r\n }\r\n }\r\n else {\r\n this.clearDataPoints();\r\n this.renderLegend({\r\n dataPoints: [],\r\n title: undefined,\r\n });\r\n this.dataPointsToEnumerate = [];\r\n }\r\n\r\n if (!_.isEmpty(warnings))\r\n this.host.setWarnings(warnings);\r\n\r\n this.dataPointRenderer.setData(data);\r\n\r\n this.updateInternal(true /* dataChanged */, true /* redrawDataLabels */);\r\n }\r\n\r\n public static converter(dataView: DataView, colorHelper: ColorHelper, geoTaggingAnalyzerService: IGeoTaggingAnalyzerService, isFilledMap: boolean): MapData {\r\n let reader = powerbi.data.createIDataViewCategoricalReader(dataView);\r\n let dataPoints: MapDataPoint[] = [];\r\n let hasDynamicSeries = reader.hasDynamicSeries();\r\n let seriesColumnIdentifier = reader.getSeriesColumnIdentityFields();\r\n let sizeQueryName = reader.getMeasureQueryName('Size');\r\n if (sizeQueryName == null)\r\n sizeQueryName = '';\r\n let hasSize = reader.hasValues('Size');\r\n let geocodingCategory = null;\r\n let formatStringProp = mapProps.general.formatString;\r\n\r\n if (reader.hasCategories()) {\r\n // Calculate category totals and range for radius calculation\r\n let categoryTotals: number[] = [];\r\n let categoryTotalRange: SimpleRange;\r\n if (hasSize) {\r\n let categoryMin: number = undefined;\r\n let categoryMax: number = undefined;\r\n for (let categoryIndex = 0, categoryCount = reader.getCategoryCount(); categoryIndex < categoryCount; categoryIndex++) {\r\n let categoryTotal: number;\r\n for (let seriesIndex = 0, seriesCount = reader.getSeriesCount(); seriesIndex < seriesCount; seriesIndex++) {\r\n let currentValue = reader.getValue('Size', categoryIndex, seriesIndex);\r\n // Dont initialze categoryTotal to zero until you find a null value so that it remains undefined for categories that have no non-null values (0 is rendered by filled map while null is not)\r\n if (categoryTotal == null && currentValue != null)\r\n categoryTotal = 0;\r\n if (categoryTotal != null)\r\n categoryTotal += currentValue;\r\n }\r\n categoryTotals.push(categoryTotal);\r\n if (categoryTotal != null) {\r\n if (categoryMin === undefined || categoryTotal < categoryMin)\r\n categoryMin = categoryTotal;\r\n if (categoryMax === undefined || categoryTotal > categoryMax)\r\n categoryMax = categoryTotal;\r\n }\r\n }\r\n categoryTotalRange = (categoryMin !== undefined && categoryMax !== undefined) ? {\r\n max: categoryMax,\r\n min: categoryMin,\r\n } : undefined;\r\n }\r\n\r\n let hasLatLongGroup = reader.hasCompositeCategories() && reader.hasCategoryWithRole('X') && reader.hasCategoryWithRole('Y');\r\n let hasCategoryGroup = reader.hasCategoryWithRole('Category');\r\n\r\n geocodingCategory = Map.getGeocodingCategory(dataView.categorical, geoTaggingAnalyzerService);\r\n\r\n if (hasLatLongGroup || hasCategoryGroup) {\r\n // Create data points\r\n for (let categoryIndex = 0, categoryCount = reader.getCategoryCount(); categoryIndex < categoryCount; categoryIndex++) {\r\n // Get category information\r\n let categoryValue = undefined;\r\n // The category objects should come from whichever category exists; in the case of a composite category, the objects should be the same for\r\n // both categories, so we only need to obtain them from one role.\r\n let categoryObjects = hasCategoryGroup ? reader.getCategoryObjects('Category', categoryIndex) : reader.getCategoryObjects('Y', categoryIndex);\r\n let location: IGeocodeCoordinate;\r\n let categoryTooltipItem: TooltipDataItem;\r\n let latitudeTooltipItem: TooltipDataItem;\r\n let longitudeTooltipItem: TooltipDataItem;\r\n let seriesTooltipItem: TooltipDataItem;\r\n let sizeTooltipItem: TooltipDataItem;\r\n let gradientTooltipItem: TooltipDataItem;\r\n if (hasCategoryGroup) {\r\n // Set category value\r\n categoryValue = reader.getCategoryValue('Category', categoryIndex);\r\n categoryTooltipItem = {\r\n displayName: reader.getCategoryDisplayName('Category'),\r\n value: converterHelper.formatFromMetadataColumn(categoryValue, reader.getCategoryMetadataColumn('Category'), formatStringProp),\r\n };\r\n\r\n // Create location from latitude and longitude if they exist as values\r\n if (reader.hasValues('Y') && reader.hasValues('X')) {\r\n let latitude = reader.getFirstNonNullValueForCategory('Y', categoryIndex);\r\n let longitude = reader.getFirstNonNullValueForCategory('X', categoryIndex);\r\n if (latitude != null && longitude != null) {\r\n location = { latitude: latitude, longitude: longitude };\r\n }\r\n latitudeTooltipItem = {\r\n displayName: reader.getValueDisplayName('Y'),\r\n value: converterHelper.formatFromMetadataColumn(latitude, reader.getValueMetadataColumn('Y'), formatStringProp),\r\n };\r\n longitudeTooltipItem = {\r\n displayName: reader.getValueDisplayName('X'),\r\n value: converterHelper.formatFromMetadataColumn(longitude, reader.getValueMetadataColumn('X'), formatStringProp),\r\n };\r\n }\r\n }\r\n else {\r\n let latitude = reader.getCategoryValue('Y', categoryIndex);\r\n let longitude = reader.getCategoryValue('X', categoryIndex);\r\n\r\n if (latitude != null && longitude != null) {\r\n // Combine latitude and longitude to create the category value\r\n categoryValue = latitude + ', ' + longitude;\r\n // Create location from latitude and longitude\r\n location = { latitude: latitude, longitude: longitude };\r\n latitudeTooltipItem = {\r\n displayName: reader.getCategoryDisplayName('Y'),\r\n value: converterHelper.formatFromMetadataColumn(latitude, reader.getCategoryMetadataColumn('Y'), formatStringProp),\r\n };\r\n longitudeTooltipItem = {\r\n displayName: reader.getCategoryDisplayName('X'),\r\n value: converterHelper.formatFromMetadataColumn(longitude, reader.getCategoryMetadataColumn('X'), formatStringProp),\r\n };\r\n }\r\n }\r\n let value: number = hasSize ? categoryTotals[categoryIndex] : undefined;\r\n\r\n // Calculate sub data points by series\r\n let subDataPoints: MapSubDataPoint[] = [];\r\n let seriesCount = reader.getSeriesCount();\r\n if (!hasSize && !hasDynamicSeries) {\r\n seriesCount = 1;\r\n }\r\n for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\r\n let color: string;\r\n\r\n if (hasDynamicSeries) {\r\n color = colorHelper.getColorForSeriesValue(reader.getSeriesObjects(seriesIndex), seriesColumnIdentifier, <string>(reader.getSeriesName(seriesIndex)));\r\n }\r\n else if (reader.hasCategoryWithRole('Series')) {\r\n color = colorHelper.getColorForSeriesValue(reader.getCategoryObjects('Series', categoryIndex), reader.getCategoryColumnIdentityFields('Series'), categoryValue);\r\n }\r\n else {\r\n color = colorHelper.getColorForMeasure(categoryObjects, sizeQueryName);\r\n }\r\n\r\n let colorRgb = Color.parseColorString(color);\r\n let stroke = Color.hexString(Color.darken(colorRgb, Map.StrokeDarkenColorValue));\r\n colorRgb.A = 0.6;\r\n let fill = Color.rgbString(colorRgb);\r\n\r\n let identityBuilder = new SelectionIdBuilder()\r\n .withCategory(reader.getCategoryColumn(hasCategoryGroup ? 'Category' : 'Y'), categoryIndex)\r\n .withMeasure(sizeQueryName);\r\n if (hasDynamicSeries) {\r\n identityBuilder = identityBuilder.withSeries(reader.getSeriesValueColumns(), reader.getSeriesValueColumnGroup(seriesIndex));\r\n }\r\n\r\n if (hasDynamicSeries) {\r\n seriesTooltipItem = {\r\n displayName: reader.getSeriesDisplayName(),\r\n value: converterHelper.formatFromMetadataColumn(reader.getSeriesName(seriesIndex), reader.getSeriesMetadataColumn(), formatStringProp),\r\n };\r\n }\r\n\r\n let subsliceValue: number;\r\n if (hasSize) {\r\n subsliceValue = reader.getValue('Size', categoryIndex, seriesIndex);\r\n sizeTooltipItem = {\r\n displayName: reader.getValueDisplayName('Size'),\r\n value: converterHelper.formatFromMetadataColumn(subsliceValue, reader.getValueMetadataColumn('Size', seriesIndex), formatStringProp),\r\n };\r\n }\r\n if (reader.hasValues('Gradient')) {\r\n gradientTooltipItem = {\r\n displayName: reader.getValueDisplayName('Gradient'),\r\n value: converterHelper.formatFromMetadataColumn(reader.getValue('Gradient', categoryIndex, seriesIndex), reader.getValueMetadataColumn('Gradient', seriesIndex), formatStringProp),\r\n };\r\n }\r\n\r\n // Combine any existing tooltip items\r\n let tooltipInfo: TooltipDataItem[] = [];\r\n if (categoryTooltipItem)\r\n tooltipInfo.push(categoryTooltipItem);\r\n if (seriesTooltipItem)\r\n tooltipInfo.push(seriesTooltipItem);\r\n if (latitudeTooltipItem)\r\n tooltipInfo.push(latitudeTooltipItem);\r\n if (longitudeTooltipItem)\r\n tooltipInfo.push(longitudeTooltipItem);\r\n if (sizeTooltipItem)\r\n tooltipInfo.push(sizeTooltipItem);\r\n if (gradientTooltipItem)\r\n tooltipInfo.push(gradientTooltipItem);\r\n\r\n // Do not create subslices for data points with null or zero if not filled map\r\n if (subsliceValue || !hasSize || (subsliceValue === 0 && isFilledMap)) {\r\n subDataPoints.push({\r\n value: subsliceValue,\r\n fill: fill,\r\n stroke: stroke,\r\n identity: identityBuilder.createSelectionId(),\r\n tooltipInfo: tooltipInfo,\r\n });\r\n }\r\n }\r\n\r\n // Skip data points that have a null or zero if not filled map\r\n if (value || !hasSize || (value === 0 && isFilledMap)) {\r\n dataPoints.push({\r\n geocodingQuery: categoryValue,\r\n value: value,\r\n categoryValue: categoryValue,\r\n subDataPoints: subDataPoints,\r\n radius: Map.calculateRadius(categoryTotalRange, value),\r\n location: location,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n let mapData: MapData = {\r\n dataPoints: dataPoints,\r\n geocodingCategory: geocodingCategory,\r\n hasDynamicSeries: hasDynamicSeries,\r\n hasSize: hasSize,\r\n };\r\n\r\n return mapData;\r\n }\r\n\r\n public static createLegendData(dataView: DataView, colorHelper: ColorHelper): LegendData {\r\n let reader = powerbi.data.createIDataViewCategoricalReader(dataView);\r\n let legendDataPoints: LegendDataPoint[] = [];\r\n let legendTitle: string;\r\n if (reader.hasDynamicSeries()) {\r\n legendTitle = reader.getSeriesDisplayName();\r\n let seriesColumnIdentifier = reader.getSeriesColumnIdentityFields();\r\n for (let seriesIndex = 0, seriesCount = reader.getSeriesCount(); seriesIndex < seriesCount; seriesIndex++) {\r\n let color = colorHelper.getColorForSeriesValue(reader.getSeriesObjects(seriesIndex), seriesColumnIdentifier, <string>reader.getSeriesName(seriesIndex));\r\n let identity = new SelectionIdBuilder().withSeries(reader.getSeriesValueColumns(), reader.getSeriesValueColumnGroup(seriesIndex)).createSelectionId();\r\n legendDataPoints.push({\r\n color: color,\r\n label: valueFormatter.format(reader.getSeriesName(seriesIndex)),\r\n icon: LegendIcon.Circle,\r\n identity: identity,\r\n selected: false,\r\n });\r\n }\r\n }\r\n let legendData: LegendData = {\r\n dataPoints: legendDataPoints,\r\n title: legendTitle,\r\n };\r\n return legendData;\r\n }\r\n\r\n private swapLogoContainerChildElement() {\r\n // This is a workaround that allow maps to be printed from the IE and Edge browsers.\r\n // For some unknown reason, the presence of an <a> child element in the .LogoContainer\r\n // prevents dashboard map visuals from showing up when printed.\r\n // The trick is to swap out the <a> element with a <div> container.\r\n // There are no user impacts or visual changes.\r\n let logoContainer = this.element.find('.LogoContainer');\r\n\r\n if (logoContainer) {\r\n let aNode = logoContainer.find('a');\r\n if (aNode == null)\r\n return;\r\n\r\n let divNode = $('<div>');\r\n aNode.children().clone().appendTo(divNode);\r\n aNode.remove();\r\n divNode.appendTo(logoContainer);\r\n }\r\n }\r\n\r\n public onResizing(viewport: IViewport): void {\r\n if (this.currentViewport.width !== viewport.width || this.currentViewport.height !== viewport.height) {\r\n this.currentViewport = viewport;\r\n this.renderLegend(this.legendData);\r\n this.updateInternal(false /* dataChanged */, false);\r\n }\r\n }\r\n\r\n private initialize(container: HTMLElement): void {\r\n let mapOptions = {\r\n credentials: MapUtil.Settings.BingKey,\r\n showMapTypeSelector: false,\r\n enableClickableLogo: false,\r\n enableSearchLogo: false,\r\n mapTypeId: Microsoft.Maps.MapTypeId.road,\r\n customizeOverlays: true,\r\n showDashboard: false,\r\n showScalebar: false,\r\n disableKeyboardInput: true, // Workaround for the BingMaps control moving focus from QnA\r\n disableZooming: this.disableZooming,\r\n disablePanning: this.disablePanning,\r\n };\r\n let divQuery = this.root = InJs.DomFactory.div().addClass(Map.MapContainer.cssClass).appendTo(container);\r\n this.mapControl = this.mapControlFactory.createMapControl(divQuery[0], mapOptions);\r\n\r\n if (this.viewChangeThrottleInterval !== undefined) {\r\n Microsoft.Maps.Events.addThrottledHandler(this.mapControl, 'viewchange', () => { this.onViewChanged(); },\r\n this.viewChangeThrottleInterval);\r\n } else {\r\n Microsoft.Maps.Events.addHandler(this.mapControl, 'viewchange', () => { this.onViewChanged(); });\r\n }\r\n\r\n Microsoft.Maps.Events.addHandler(this.mapControl, \"viewchangeend\", () => { this.onViewChangeEnded(); });\r\n this.dataPointRenderer.init(this.mapControl, divQuery, !!this.behavior);\r\n\r\n if (!this.pendingGeocodingRender) {\r\n this.updateInternal(true /* dataChanged */, true);\r\n }\r\n }\r\n\r\n private onViewChanged() {\r\n this.updateOffsets(false, false /* dataChanged */);\r\n if (this.behavior)\r\n this.behavior.viewChanged();\r\n\r\n this.swapLogoContainerChildElement();\r\n }\r\n\r\n private onViewChangeEnded() {\r\n\r\n this.dataPointRenderer.updateInternalDataLabels(this.currentViewport, true);\r\n }\r\n\r\n private getMapViewPort(): IViewport {\r\n let currentViewport = this.currentViewport;\r\n let legendMargins = this.legend.getMargins();\r\n\r\n let mapViewport = {\r\n width: currentViewport.width - legendMargins.width,\r\n height: currentViewport.height - legendMargins.height,\r\n };\r\n\r\n return mapViewport;\r\n }\r\n\r\n public static removeTransform3d(mapRoot: JQuery): void {\r\n // don't remove transform3d from bing maps images in safari (using applewebkit engine)\r\n let userAgent = window.navigator.userAgent.toLowerCase();\r\n if (mapRoot && userAgent.indexOf('applewebkit') === -1) {\r\n let imageTiles = mapRoot.find('img');\r\n imageTiles.css('transform', '');\r\n }\r\n }\r\n\r\n private updateInternal(dataChanged: boolean, redrawDataLabels: boolean) {\r\n if (this.mapControl) {\r\n let isLegendVisible = this.legend.isVisible();\r\n\r\n if (!isLegendVisible)\r\n this.legendData = { dataPoints: [] };\r\n\r\n let mapDiv = this.element.children(Map.MapContainer.selector);\r\n let mapViewport = this.getMapViewPort();\r\n mapDiv.height(mapViewport.height);\r\n mapDiv.width(mapViewport.width);\r\n\r\n // With the risk of double drawing, if the position updates to nearly the same, the map control won't call viewchange, so explicitly update the points\r\n this.updateOffsets(dataChanged, redrawDataLabels);\r\n\r\n // Set zoom level after we rendered that map as we need the max size of the bubbles/ pie slices to calculate it\r\n if (this.boundsHaveBeenUpdated && !(this.behavior && this.behavior.hasReceivedZoomOrPanEvent())) {\r\n let levelOfDetail = this.getOptimumLevelOfDetail(mapViewport.width, mapViewport.height);\r\n let center = this.getViewCenter(levelOfDetail);\r\n\r\n this.updateMapView(center, levelOfDetail);\r\n }\r\n }\r\n }\r\n\r\n private updateMapView(center: Microsoft.Maps.Location, levelOfDetail: number): void {\r\n this.mapControl.setView({ center: center, zoom: levelOfDetail, animate: true });\r\n }\r\n\r\n private updateOffsets(dataChanged: boolean, redrawDataLabels: boolean) {\r\n let dataView = this.dataView;\r\n let data: MapRendererData;\r\n let viewport = this.getMapViewPort();\r\n if (dataView && dataView.categorical) {\r\n // currentViewport may not exist in UnitTests\r\n data = this.dataPointRenderer.converter(viewport, this.dataView, this.dataLabelsSettings, this.interactivityService, this.tooltipsEnabled);\r\n }\r\n else {\r\n data = {\r\n bubbleData: [],\r\n shapeData: [],\r\n sliceData: [],\r\n };\r\n }\r\n\r\n let behaviorOptions = this.dataPointRenderer.updateInternal(data, viewport, dataChanged, this.interactivityService, redrawDataLabels);\r\n Legend.positionChartArea(d3.select(this.root[0]), this.legend);\r\n\r\n if (this.interactivityService && behaviorOptions) {\r\n this.interactivityService.bind(behaviorOptions.dataPoints, this.behavior, behaviorOptions);\r\n }\r\n }\r\n\r\n public onClearSelection(): void {\r\n this.interactivityService.clearSelection();\r\n this.updateOffsets(false, false /* dataChanged */);\r\n }\r\n\r\n private clearDataPoints(): void {\r\n this.dataPointRenderer.clearDataPoints();\r\n this.legend.drawLegend({ dataPoints: [] }, this.currentViewport);\r\n }\r\n\r\n private getDefaultMapControlFactory(): IMapControlFactory {\r\n return {\r\n createMapControl: (element: HTMLElement, options: Microsoft.Maps.MapOptions) => new Microsoft.Maps.Map(element, options),\r\n ensureMap: jsCommon.ensureMap,\r\n };\r\n }\r\n\r\n private static removeHillShading() {\r\n Microsoft.Maps.Globals.roadUriFormat = Microsoft.Maps.Globals.roadUriFormat.replace('&shading=hill', '');\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import getKpiImageMetadata = powerbi.visuals.KpiUtil.getKpiImageMetadata;\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import UrlUtils = jsCommon.UrlUtils;\r\n import Surround = powerbi.visuals.controls.internal.TablixUtils.Surround;\r\n import EdgeSettings = powerbi.visuals.controls.internal.TablixUtils.EdgeSettings;\r\n\r\n const TitleFontFamily = 'wf_segoe-ui_semibold';\r\n const DefaultFontFamily = 'wf_segoe-ui_normal';\r\n const DefaultCaptionFontSizeInPt = 10;\r\n const DefaultTitleFontSizeInPt = 13;\r\n const DefaultDetailFontSizeInPt = 9;\r\n \r\n const DefaultTitleColor = '#767676';\r\n const DefaultTextColor = '#333333';\r\n const DefaultCategoryColor = '#ACACAC';\r\n const DefaultOutline = outline.none;\r\n const DefaultOutlineColor = '#E8E8E8';\r\n const DefaultOutlineWeight = 1;\r\n const DefaultBarShow = true;\r\n const DefaultBarColor = '#A6A6A6';\r\n const DefaultBarOutline = outline.leftOnly;\r\n const DefaultBarWeight = 3;\r\n\r\n export interface CardItemData {\r\n caption: string;\r\n details: string;\r\n showURL: boolean;\r\n showImage: boolean;\r\n showKPI: boolean;\r\n columnIndex: number;\r\n }\r\n \r\n export interface CardSettings {\r\n outlineSettings: OutlineSettings;\r\n barSettings: OutlineSettings;\r\n cardPadding: number;\r\n cardBackground: string;\r\n }\r\n \r\n export interface OutlineSettings{\r\n outline: string;\r\n color: string;\r\n weight: number;\r\n }\r\n \r\n export interface MultiRowCardData {\r\n dataModel: CardData[];\r\n dataColumnCount: number;\r\n cardTitleSettings: VisualDataLabelsSettings;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n categoryLabelsSettings: VisualDataLabelsSettings;\r\n cardSettings: CardSettings;\r\n }\r\n\r\n export interface CardData {\r\n title?: string;\r\n showTitleAsURL?: boolean;\r\n showTitleAsImage?: boolean;\r\n showTitleAsKPI?: boolean;\r\n cardItemsData: CardItemData[];\r\n }\r\n\r\n interface ImageStyle {\r\n maxWidth?: number;\r\n maxHeight?: number;\r\n }\r\n\r\n interface MediaQuery {\r\n maxWidth?: number;\r\n style?: MultiRowCardStyle;\r\n }\r\n\r\n interface MultiRowCardStyle {\r\n row?: {\r\n border?: Surround<EdgeSettings>;\r\n marginBottom?: number;\r\n background?: string\r\n };\r\n card?: {\r\n border?: Surround<EdgeSettings>;\r\n maxRows?: number;\r\n };\r\n cardItemContainer?: {\r\n paddingRight?: number;\r\n minWidth?: number;\r\n };\r\n details?: {\r\n fontSize?: number;\r\n color?: string,\r\n isVisible?: boolean;\r\n };\r\n caption?: {\r\n fontSize?: number;\r\n color?: string,\r\n };\r\n title?: {\r\n fontSize?: number;\r\n color?: string,\r\n };\r\n imageCaption?: ImageStyle;\r\n imageTitle?: ImageStyle;\r\n }\r\n\r\n export class MultiRowCard implements IVisual {\r\n private currentViewport: IViewport;\r\n private options: VisualInitOptions;\r\n private dataView: DataView;\r\n private style: IVisualStyle;\r\n private element: JQuery;\r\n private listView: IListView;\r\n /**\r\n * This includes card height with margin that will be passed to list view.\r\n */\r\n private interactivity: InteractivityOptions;\r\n private isInteractivityOverflowHidden: boolean = false;\r\n private waitingForData: boolean;\r\n private cardHasTitle: boolean;\r\n private isSingleRowCard: boolean;\r\n private maxColPerRow: number;\r\n private data: MultiRowCardData;\r\n\r\n /**\r\n * Note: Public for testability.\r\n */\r\n public static formatStringProp: DataViewObjectPropertyIdentifier = {\r\n objectName: 'general',\r\n propertyName: 'formatString',\r\n };\r\n\r\n private static MultiRowCardRoot = createClassAndSelector('multiRowCard');\r\n private static Card: ClassAndSelector = createClassAndSelector('card');\r\n private static Title: ClassAndSelector = createClassAndSelector('title');\r\n private static CardItemContainer: ClassAndSelector = createClassAndSelector('cardItemContainer');\r\n private static Caption: ClassAndSelector = createClassAndSelector('caption');\r\n private static Details: ClassAndSelector = createClassAndSelector('details');\r\n private static TitleUrlSelector: string = MultiRowCard.Title.selector + ' a';\r\n private static CaptionUrlSelector: string = MultiRowCard.Caption.selector + ' a';\r\n private static TitleImageSelector: string = MultiRowCard.Title.selector + ' img';\r\n private static CaptionImageSelector: string = MultiRowCard.Caption.selector + ' img';\r\n private static KPITitle: ClassAndSelector = createClassAndSelector('kpiTitle');\r\n private static ValuesRole: string = 'Values';\r\n\r\n /**\r\n * Cards have specific styling so defined inline styles and also to support theming and improve performance.\r\n */\r\n private static DefaultStyle: MultiRowCardStyle = {\r\n row: {\r\n border: null,\r\n marginBottom: 20,\r\n background: undefined \r\n },\r\n card: {\r\n border: null\r\n },\r\n cardItemContainer: {\r\n paddingRight: 20,\r\n minWidth: 120,\r\n },\r\n imageCaption: {\r\n maxHeight: 75,\r\n maxWidth: 100,\r\n },\r\n imageTitle: {\r\n maxHeight: 75,\r\n maxWidth: 100,\r\n }\r\n };\r\n\r\n // queries should be ordered by maxWidth in ascending order\r\n private static tileMediaQueries: MediaQuery[] = [\r\n {\r\n maxWidth: 250,\r\n style: {\r\n card: {\r\n maxRows: 2,\r\n },\r\n cardItemContainer: {\r\n minWidth: 110,\r\n },\r\n imageCaption: {\r\n maxHeight: 45,\r\n }\r\n }\r\n },\r\n {\r\n maxWidth: 490,\r\n style: {\r\n card: {\r\n maxRows: 2,\r\n },\r\n cardItemContainer: {\r\n minWidth: 130,\r\n },\r\n imageCaption: {\r\n maxHeight: 52,\r\n }\r\n }\r\n },\r\n {\r\n maxWidth: 750,\r\n style: {\r\n card: {\r\n maxRows: 1,\r\n },\r\n cardItemContainer: {\r\n minWidth: 120,\r\n },\r\n imageCaption: {\r\n maxHeight: 53,\r\n }\r\n }\r\n }\r\n ];\r\n\r\n public init(options: VisualInitOptions) {\r\n debug.assertValue(options, 'options');\r\n this.options = options;\r\n this.style = options.style;\r\n let viewport = this.currentViewport = options.viewport;\r\n let interactivity = this.interactivity = options.interactivity;\r\n\r\n if (interactivity && interactivity.overflow === 'hidden')\r\n this.isInteractivityOverflowHidden = true;\r\n\r\n let multiRowCardDiv = this.element = $('<div/>')\r\n .addClass(MultiRowCard.MultiRowCardRoot.class)\r\n .css({\r\n 'height': getPixelString(viewport.height),\r\n });\r\n options.element.append(multiRowCardDiv);\r\n this.initializeCardRowSelection();\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataViews = options.dataViews;\r\n if (dataViews && dataViews.length > 0) {\r\n let dataView = this.dataView = dataViews[0];\r\n let columnMetadata: DataViewMetadataColumn[] = dataView.table.columns;\r\n let tableRows: any[][] = dataView.table.rows;\r\n let resetScrollbarPosition = options.operationKind !== VisualDataChangeOperationKind.Append;\r\n let data = this.data = MultiRowCard.converter(dataView, columnMetadata.length, tableRows.length, this.isInteractivityOverflowHidden);\r\n this.setCardDimensions();\r\n this.listView.data(data.dataModel, (d: CardData) => data.dataModel.indexOf(d), resetScrollbarPosition);\r\n }\r\n else {\r\n this.data = {\r\n dataModel: [],\r\n dataColumnCount: 0,\r\n cardTitleSettings: dataLabelUtils.getDefaultLabelSettings(true, DefaultTitleColor, DefaultTitleFontSizeInPt),\r\n categoryLabelsSettings: dataLabelUtils.getDefaultLabelSettings(true, DefaultCategoryColor, DefaultDetailFontSizeInPt),\r\n dataLabelsSettings: dataLabelUtils.getDefaultLabelSettings(true, DefaultTextColor, DefaultCaptionFontSizeInPt),\r\n cardSettings: MultiRowCard.getCardSettings(null)\r\n };\r\n }\r\n\r\n this.waitingForData = false;\r\n }\r\n \r\n private static getCardSettings(dataView: DataView): CardSettings {\r\n\r\n let objects = dataView && dataView.metadata && dataView.metadata.objects ? dataView.metadata.objects : null;\r\n\r\n let outlineSettings: OutlineSettings = {\r\n outline: DataViewObjects.getValue(objects, multiRowCardProps.card.outline, DefaultOutline),\r\n color: DataViewObjects.getFillColor(objects, multiRowCardProps.card.outlineColor, DefaultOutlineColor),\r\n weight: DataViewObjects.getValue(objects, multiRowCardProps.card.outlineWeight, DefaultOutlineWeight),\r\n };\r\n\r\n let barShow = DataViewObjects.getValue(objects, multiRowCardProps.card.barShow, DefaultBarShow);\r\n\r\n let barSettings: OutlineSettings = {\r\n // If the bar is hidden, set the outline to none\r\n outline: barShow ? DefaultBarOutline : outline.none,\r\n color: DataViewObjects.getFillColor(objects, multiRowCardProps.card.barColor, DefaultBarColor),\r\n weight: DataViewObjects.getValue(objects, multiRowCardProps.card.barWeight, DefaultBarWeight),\r\n };\r\n\r\n let cardPadding = DataViewObjects.getValue(objects, multiRowCardProps.card.cardPadding, MultiRowCard.DefaultStyle.row.marginBottom);\r\n let cardBackground = DataViewObjects.getFillColor(objects, multiRowCardProps.card.cardBackground, MultiRowCard.DefaultStyle.row.background);\r\n\r\n return {\r\n outlineSettings: outlineSettings,\r\n barSettings: barSettings,\r\n cardPadding: cardPadding,\r\n cardBackground: cardBackground\r\n };\r\n }\r\n\r\n public onResizing(viewport: IViewport): void {\r\n let heightNotChanged = (this.currentViewport.height === viewport.height);\r\n this.currentViewport = viewport;\r\n this.element.css('height', getPixelString(viewport.height));\r\n if (!this.dataView)\r\n return;\r\n\r\n let previousMaxColPerRow = this.maxColPerRow;\r\n this.maxColPerRow = this.getMaxColPerRow();\r\n let widthNotChanged = (previousMaxColPerRow === this.maxColPerRow);\r\n if (heightNotChanged && widthNotChanged)\r\n return;\r\n\r\n this.listView.viewport(viewport);\r\n }\r\n \r\n public static converter(dataView: DataView, columnCount: number, maxCards: number, isDashboardVisual: boolean = false): MultiRowCardData {\r\n let details: CardData[] = [];\r\n let tableDataRows = dataView.table.rows;\r\n let columnMetadata: DataViewMetadataColumn[] = dataView.table.columns;\r\n let cardTitleSettings: VisualDataLabelsSettings ,\r\n dataLabelsSettings: VisualDataLabelsSettings,\r\n categoryLabelsSettings: VisualDataLabelsSettings;\r\n\r\n cardTitleSettings = dataLabelUtils.getDefaultLabelSettings(true, DefaultTitleColor, DefaultTitleFontSizeInPt);\r\n dataLabelsSettings = dataLabelUtils.getDefaultLabelSettings(true, DefaultTextColor, DefaultCaptionFontSizeInPt);\r\n categoryLabelsSettings = dataLabelUtils.getDefaultLabelSettings(true, DefaultCategoryColor, DefaultDetailFontSizeInPt);\r\n\r\n if (dataView.metadata && dataView.metadata.objects) {\r\n let cardTitleLabelObjects = <DataLabelObject>DataViewObjects.getObject(dataView.metadata.objects, 'cardTitle');\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(cardTitleLabelObjects, cardTitleSettings);\r\n\r\n let dataLabelObject = <DataLabelObject>DataViewObjects.getObject(dataView.metadata.objects, 'dataLabels');\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(dataLabelObject, dataLabelsSettings);\r\n\r\n let categoryLabelObject = <DataLabelObject>DataViewObjects.getObject(dataView.metadata.objects, 'categoryLabels');\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(categoryLabelObject, categoryLabelsSettings);\r\n }\r\n\r\n for (let i = 0, len = maxCards; i < len; i++) {\r\n let row = tableDataRows[i];\r\n let isValuePromoted: boolean = undefined;\r\n var title: string = undefined;\r\n let showTitleAsURL: boolean = false;\r\n let showTitleAsImage: boolean = false;\r\n let showTitleAsKPI: boolean = false;\r\n let cardData: CardItemData[] = [];\r\n for (let j = 0; j < columnCount; j++) {\r\n let column = columnMetadata[j];\r\n\r\n let statusGraphicInfo = getKpiImageMetadata(column, row[j]);\r\n let columnCaption: string;\r\n let statusGraphic: string;\r\n\r\n if (statusGraphicInfo) {\r\n columnCaption = statusGraphicInfo.class;\r\n statusGraphic = statusGraphicInfo.statusGraphic;\r\n }\r\n\r\n //TODO: seems we are duplicating this logic in many places. Consider putting it in KPIUtil\r\n if (!columnCaption)\r\n columnCaption = valueFormatter.format(row[j], valueFormatter.getFormatString(column, MultiRowCard.formatStringProp));\r\n\r\n let showKPI = statusGraphicInfo !== undefined && statusGraphicInfo.caption !== undefined;\r\n\r\n // The columnDetail represents column name. In card the column name is shown as details\r\n let columnDetail: string = columnMetadata[j].displayName;\r\n\r\n //Title is shown only on Canvas and only if there is one Category field.\r\n if (!isDashboardVisual && !column.type.numeric) {\r\n if (isValuePromoted === undefined) {\r\n isValuePromoted = true;\r\n title = columnCaption;\r\n showTitleAsURL = converterHelper.isWebUrlColumn(column) && UrlUtils.isValidUrl(title);\r\n showTitleAsImage = converterHelper.isImageUrlColumn(column) && UrlUtils.isValidImageUrl(columnCaption);\r\n showTitleAsKPI = showKPI;\r\n }\r\n else if (isValuePromoted) {\r\n isValuePromoted = false;\r\n }\r\n }\r\n cardData.push({\r\n caption: columnCaption,\r\n details: columnDetail,\r\n showURL: converterHelper.isWebUrlColumn(column) && UrlUtils.isValidUrl(columnCaption),\r\n showImage: converterHelper.isImageUrlColumn(column) && UrlUtils.isValidImageUrl(columnCaption),\r\n showKPI: showKPI,\r\n columnIndex: j\r\n });\r\n }\r\n details.push({\r\n title: isValuePromoted ? title : undefined,\r\n showTitleAsURL: showTitleAsURL,\r\n showTitleAsImage: showTitleAsImage,\r\n showTitleAsKPI: showTitleAsKPI,\r\n cardItemsData: isValuePromoted ? cardData.filter((d: CardItemData) => d.caption !== title) : cardData\r\n });\r\n }\r\n return {\r\n dataModel: details,\r\n dataColumnCount: details[0] ? details[0].cardItemsData.length : 0,\r\n cardTitleSettings: cardTitleSettings,\r\n categoryLabelsSettings: categoryLabelsSettings,\r\n dataLabelsSettings: dataLabelsSettings,\r\n cardSettings: MultiRowCard.getCardSettings(dataView)\r\n };\r\n }\r\n \r\n public static getSortableRoles(options: VisualSortableOptions): string[] {\r\n \r\n if (!options || !options.dataViewMappings || _.isEmpty(options.dataViewMappings)) {\r\n return;\r\n }\r\n\r\n for (let dataViewMapping of options.dataViewMappings) {\r\n if (dataViewMapping.table) {\r\n\r\n let rows = <powerbi.data.CompiledDataViewRoleForMappingWithReduction>dataViewMapping.table.rows;\r\n\r\n if (rows && rows.for && rows.for.in && rows.for.in.items) {\r\n return [MultiRowCard.ValuesRole];\r\n }\r\n }\r\n }\r\n\r\n return;\r\n }\r\n\r\n private initializeCardRowSelection() {\r\n let isDashboardVisual = this.isInteractivityOverflowHidden;\r\n\r\n let rowEnter = (rowSelection: D3.Selection) => {\r\n let cardRow = rowSelection\r\n .append(\"div\")\r\n .classed(MultiRowCard.Card.class, true);\r\n\r\n // The card top padding is not needed when card items are wrapped as top padding is added to each carditemcontainer when wrapped\r\n if (isDashboardVisual) {\r\n cardRow.classed('mrtile', true);\r\n }\r\n else {\r\n if (this.cardHasTitle) {\r\n cardRow.append(\"div\").classed(MultiRowCard.Title.class, true)\r\n .each(function (d: CardData) {\r\n if (d.showTitleAsImage)\r\n appendImage(d3.select(this));\r\n else if (d.showTitleAsURL)\r\n d3.select(this).append('a');\r\n else if (d.showTitleAsKPI)\r\n d3.select(this).append('div')\r\n .classed(MultiRowCard.KPITitle.class, true)\r\n .classed(d.title, true)\r\n .style({\r\n display: 'inline-block',\r\n verticalAlign: 'sub'\r\n });\r\n });\r\n }\r\n }\r\n\r\n let cardItem = cardRow\r\n .selectAll(MultiRowCard.CardItemContainer.selector)\r\n .data((d: CardData) => d.cardItemsData)\r\n .enter()\r\n .append('div')\r\n .classed(MultiRowCard.CardItemContainer.class, true);\r\n\r\n cardItem\r\n .append('div')\r\n .classed(MultiRowCard.Caption.class, true)\r\n .each(function (d: CardItemData) {\r\n if (d.showURL) {\r\n d3.select(this).append('a');\r\n }\r\n else if (d.showImage) {\r\n appendImage(d3.select(this));\r\n }\r\n else if (d.showKPI) {\r\n d3.select(this).append('div')\r\n .classed(d.caption, true)\r\n .style({\r\n display: 'inline-block',\r\n verticalAlign: 'sub'\r\n });\r\n }\r\n });\r\n\r\n cardItem\r\n .append('div')\r\n .classed(MultiRowCard.Details.class, true);\r\n };\r\n\r\n /**\r\n * Row update should:\r\n * 1. bind Data\r\n * 2. Manipulate DOM (likely just updating CSS properties) affected by data\r\n */\r\n let rowUpdate = (rowSelection: D3.Selection) => {\r\n let style = this.getStyle();\r\n let dataLabelHeight = TextMeasurementService.estimateSvgTextHeight(MultiRowCard.getTextProperties(false, style.caption.fontSize));\r\n let categoryLabelHeight = TextMeasurementService.estimateSvgTextHeight(MultiRowCard.getTextProperties(false, style.details.fontSize));\r\n let titleLabelHeight = TextMeasurementService.estimateSvgTextHeight(MultiRowCard.getTextProperties(true, style.title.fontSize));\r\n let rowBorderStyle = this.getBorderStyles(style.row.border);\r\n \r\n rowSelection\r\n .style(rowBorderStyle)\r\n .style({\r\n 'margin-bottom': isDashboardVisual ? '0px' : (this.isSingleRowCard ? '0px' : getPixelString(style.row.marginBottom)),\r\n 'background': style.row.background\r\n });\r\n\r\n if (!isDashboardVisual && this.cardHasTitle) {\r\n rowSelection.selectAll(MultiRowCard.Title.selector)\r\n .filter((d: CardData) => !d.showTitleAsImage && !d.showTitleAsKPI)\r\n .style({\r\n 'font-size': PixelConverter.fromPoint(style.title.fontSize),\r\n 'line-height': PixelConverter.toString(titleLabelHeight),\r\n 'color': style.title.color,\r\n });\r\n\r\n rowSelection.selectAll(MultiRowCard.Title.selector)\r\n .filter((d: CardData) => !d.showTitleAsURL && !d.showTitleAsImage && !d.showTitleAsKPI)\r\n .text((d: CardData) => d.title)\r\n .attr('title', (d: CardData) => d.title);\r\n\r\n rowSelection\r\n .selectAll(MultiRowCard.TitleUrlSelector)\r\n .text((d: CardData) => d.title)\r\n .attr({\r\n 'href': (d: CardData) => d.title,\r\n 'target': '_blank',\r\n });\r\n\r\n rowSelection\r\n .selectAll(MultiRowCard.TitleImageSelector)\r\n .attr('src', (d: CardData) => d.title);\r\n setImageStyle(rowSelection.selectAll(MultiRowCard.Title.selector), style.imageTitle);\r\n\r\n rowSelection\r\n .selectAll(MultiRowCard.KPITitle.selector)\r\n .each(function (d: CardData) {\r\n let element = d3.select(this);\r\n element.classed(d.title);\r\n });\r\n }\r\n \r\n let cardSelection = rowSelection.selectAll(MultiRowCard.Card.selector);\r\n \r\n let cardBorderStyle = this.getBorderStyles(style.card.border);\r\n cardSelection.style(cardBorderStyle);\r\n\r\n cardSelection\r\n .selectAll(MultiRowCard.Caption.selector)\r\n .filter((d: CardItemData) => !d.showImage)\r\n .style({\r\n 'line-height': PixelConverter.toString(dataLabelHeight),\r\n 'font-size': PixelConverter.fromPoint(style.caption.fontSize),\r\n })\r\n .filter((d: CardItemData) => !d.showKPI)\r\n .style({\r\n 'color': style.caption.color,\r\n })\r\n .filter((d: CardItemData) => !d.showURL)\r\n .text((d: CardItemData) => d.caption)\r\n .attr('title', (d: CardItemData) => d.caption);\r\n\r\n cardSelection\r\n .selectAll(MultiRowCard.CaptionImageSelector)\r\n .attr('src', (d: CardItemData) => d.caption)\r\n .style(style.imageCaption);\r\n\r\n cardSelection\r\n .selectAll(MultiRowCard.CardItemContainer.selector)\r\n .style({\r\n 'padding-right': (d: CardItemData) => {\r\n return this.isLastRowItem(d.columnIndex, this.dataView.metadata.columns.length) ? '0px' : getPixelString(style.cardItemContainer.paddingRight);\r\n },\r\n 'width': (d: CardItemData) => {\r\n return this.getColumnWidth(d.columnIndex, this.data.dataColumnCount);\r\n },\r\n 'display': (d: CardItemData) => {\r\n return (this.hideColumn(d.columnIndex) ? 'none' : 'inline-block');\r\n },\r\n });\r\n\r\n setImageStyle(cardSelection.selectAll(MultiRowCard.Caption.selector), style.imageCaption);\r\n\r\n cardSelection\r\n .selectAll(MultiRowCard.CaptionUrlSelector)\r\n .attr({\r\n 'href': (d: CardItemData) => d.caption,\r\n 'target': '_blank',\r\n })\r\n .text((d: CardItemData) => d.caption);\r\n\r\n if (style.details.isVisible) {\r\n cardSelection\r\n .selectAll(MultiRowCard.Details.selector)\r\n .text((d: CardItemData) => d.details)\r\n .style({\r\n 'font-size': PixelConverter.fromPoint(style.details.fontSize),\r\n 'line-height': PixelConverter.toString(categoryLabelHeight),\r\n 'color': style.details.color\r\n })\r\n .attr('title', (d: CardItemData) => d.details);\r\n }\r\n };\r\n\r\n let rowExit = (rowSelection: D3.Selection) => {\r\n rowSelection.remove();\r\n };\r\n\r\n let listViewOptions: ListViewOptions = {\r\n rowHeight: undefined,\r\n enter: rowEnter,\r\n exit: rowExit,\r\n update: rowUpdate,\r\n loadMoreData: () => this.onLoadMoreData(),\r\n viewport: this.currentViewport,\r\n baseContainer: d3.select(this.element.get(0)),\r\n scrollEnabled: !this.isInteractivityOverflowHidden,\r\n isReadMode: () => {\r\n return (this.options.host.getViewMode() !== ViewMode.Edit);\r\n }\r\n };\r\n\r\n this.listView = ListViewFactory.createListView(listViewOptions);\r\n }\r\n \r\n private getBorderStyles(border: Surround<EdgeSettings>): { [property: string]: string } {\r\n \r\n return {\r\n 'border-top': border && border.top ? border.top.getCSS() : '',\r\n 'border-right': border && border.right ? border.right.getCSS() : '',\r\n 'border-bottom': border && border.bottom ? border.bottom.getCSS() : '',\r\n 'border-left': border && border.left ? border.left.getCSS() : ''\r\n };\r\n } \r\n\r\n private getMaxColPerRow(): number {\r\n let rowWidth = this.currentViewport.width;\r\n let minColumnWidth = this.getStyle().cardItemContainer.minWidth;\r\n let columnCount = this.data.dataColumnCount;\r\n //atleast one column fits in a row\r\n let maxColumnPerRow = Math.floor(rowWidth / minColumnWidth) || 1;\r\n return Math.min(columnCount, maxColumnPerRow);\r\n }\r\n\r\n private getRowIndex(fieldIndex: number): number {\r\n return Math.floor((fieldIndex * 1.0) / this.getMaxColPerRow());\r\n }\r\n\r\n private getStyle(): MultiRowCardStyle {\r\n let defaultStyles = MultiRowCard.DefaultStyle;\r\n let customStyles = this.getCustomStyles();\r\n \r\n if (!this.isInteractivityOverflowHidden)\r\n return $.extend(true, {}, defaultStyles, customStyles);\r\n\r\n let viewportWidth = this.currentViewport.width;\r\n let overrideStyle: MultiRowCardStyle = {};\r\n for (let currentQuery of MultiRowCard.tileMediaQueries)\r\n if (viewportWidth <= currentQuery.maxWidth) {\r\n overrideStyle = currentQuery.style;\r\n break;\r\n }\r\n \r\n return $.extend(true, {}, defaultStyles, customStyles, overrideStyle);\r\n }\r\n \r\n private getSurroundSettings(outlineSettings: OutlineSettings): Surround<EdgeSettings>{\r\n \r\n let edge = new EdgeSettings(outlineSettings.weight, outlineSettings.color);\r\n let outlineProp = outlineSettings.outline;\r\n \r\n return {\r\n top: outline.showTop(outlineProp) ? edge : null,\r\n right: outline.showRight(outlineProp) ? edge : null,\r\n bottom: outline.showBottom(outlineProp) ? edge : null,\r\n left: outline.showLeft(outlineProp) ? edge : null,\r\n };\r\n }\r\n\r\n private getCustomStyles(): MultiRowCardStyle {\r\n let dataLabelsSettings = this.data.dataLabelsSettings;\r\n let categoryLabelSettings = this.data.categoryLabelsSettings;\r\n let titleLabelSettings = this.data.cardTitleSettings;\r\n let cardSettings = this.data.cardSettings;\r\n \r\n let customStyle: MultiRowCardStyle = {\r\n row: {\r\n border: this.getSurroundSettings(cardSettings.outlineSettings),\r\n marginBottom: cardSettings.cardPadding,\r\n background: cardSettings.cardBackground\r\n },\r\n card: {\r\n border: this.getSurroundSettings(cardSettings.barSettings)\r\n },\r\n details: {\r\n fontSize: categoryLabelSettings.fontSize,\r\n color: categoryLabelSettings.labelColor,\r\n isVisible: categoryLabelSettings.show,\r\n },\r\n caption: {\r\n fontSize: dataLabelsSettings.fontSize,\r\n color: dataLabelsSettings.labelColor,\r\n },\r\n title: {\r\n fontSize: titleLabelSettings.fontSize,\r\n color: titleLabelSettings.labelColor,\r\n }\r\n };\r\n\r\n return customStyle;\r\n }\r\n\r\n private static getTextProperties(isTitle: boolean, fontSizeInPt: number): TextProperties {\r\n return {\r\n fontFamily: isTitle ? TitleFontFamily : DefaultFontFamily,\r\n fontSize: PixelConverter.fromPoint(fontSizeInPt),\r\n };\r\n }\r\n\r\n private hideColumn(fieldIndex: number): boolean {\r\n //calculate the number of items apearing in the same row as the columnIndex\r\n let rowIndex = this.getRowIndex(fieldIndex);\r\n\r\n // when interactivity is disabled (pinned tile), don't wrap the row\r\n let maxRows = this.getStyle().card.maxRows;\r\n return (maxRows && rowIndex >= maxRows);\r\n }\r\n\r\n private getColumnWidth(fieldIndex: number, columnCount: number): string {\r\n //atleast one column fits in a row\r\n let maxColumnPerRow = this.getMaxColPerRow();\r\n if (maxColumnPerRow >= columnCount)\r\n //all columns fit in the same row, divide the space equaly\r\n return (100.0 / columnCount) + '%';\r\n\r\n //calculate the number of items apearing in the same row as the columnIndex\r\n let rowIndex = this.getRowIndex(fieldIndex);\r\n\r\n let totalRows = Math.ceil((columnCount * 1.0) / maxColumnPerRow);\r\n let lastRowCount = columnCount % maxColumnPerRow;\r\n if (rowIndex < totalRows || lastRowCount === 0)\r\n // items is not on the last row or last row contains max columns allowed per row\r\n return (100.0 / maxColumnPerRow) + '%';\r\n\r\n // items is on the last row\r\n return (100.0 / lastRowCount) + '%';\r\n }\r\n\r\n private isLastRowItem(fieldIndex: number, columnCount: number) {\r\n if (fieldIndex + 1 === columnCount)\r\n return true;\r\n let maxColumnPerRow = this.getMaxColPerRow();\r\n if (maxColumnPerRow - (fieldIndex % maxColumnPerRow) === 1)\r\n return true;\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * This contains the card column wrapping logic.\r\n * Determines how many columns can be shown per each row inside a Card.\r\n * To place the fields evenly along the card,\r\n * the width of each card item is calculated based on the available viewport width.\r\n */\r\n private setCardDimensions(): void {\r\n this.cardHasTitle = false;\r\n\r\n let dataModel = this.data.dataModel;\r\n\r\n if (!this.isInteractivityOverflowHidden && dataModel && dataModel.length > 0) {\r\n this.cardHasTitle = dataModel[0].title !== undefined;\r\n this.isSingleRowCard = dataModel.length === 1 ? true : false;\r\n }\r\n }\r\n\r\n private onLoadMoreData(): void {\r\n if (!this.waitingForData && this.dataView.metadata && this.dataView.metadata.segment) {\r\n this.options.host.loadMoreData();\r\n this.waitingForData = true;\r\n }\r\n }\r\n\r\n private static getDataLabelSettingsOptions(enumeration: ObjectEnumerationBuilder, labelSettings: VisualDataLabelsSettings, show: boolean = false): VisualDataLabelsSettingsOptions {\r\n return {\r\n enumeration: enumeration,\r\n dataLabelsSettings: labelSettings,\r\n show: show,\r\n fontSize: true,\r\n };\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n\r\n let cardTitleSettings = this.data.cardTitleSettings;\r\n let dataLabelsSettings = this.data.dataLabelsSettings;\r\n let categoryLabelsSettings = this.data.categoryLabelsSettings;\r\n\r\n switch (options.objectName) {\r\n case 'cardTitle':\r\n //display title options only if title visible\r\n if (!this.isInteractivityOverflowHidden && this.cardHasTitle)\r\n dataLabelUtils.enumerateDataLabels(MultiRowCard.getDataLabelSettingsOptions(enumeration, cardTitleSettings));\r\n break;\r\n case 'dataLabels':\r\n dataLabelUtils.enumerateDataLabels(MultiRowCard.getDataLabelSettingsOptions(enumeration, dataLabelsSettings));\r\n break;\r\n case 'categoryLabels':\r\n dataLabelUtils.enumerateDataLabels(MultiRowCard.getDataLabelSettingsOptions(enumeration, categoryLabelsSettings, true));\r\n break;\r\n case multiRowCardProps.card.outline.objectName:\r\n this.enumerateCard(enumeration);\r\n break;\r\n }\r\n\r\n return enumeration.complete();\r\n }\r\n \r\n private enumerateCard(enumeration: ObjectEnumerationBuilder): void {\r\n\r\n let cardSettings = this.data.cardSettings;\r\n let propNames = multiRowCardProps.card;\r\n\r\n let properties: any = {};\r\n\r\n let outlineSettings = cardSettings.outlineSettings;\r\n properties[propNames.outline.propertyName] = outlineSettings.outline;\r\n\r\n if (outlineSettings.outline !== outline.none) {\r\n properties[propNames.outlineColor.propertyName] = outlineSettings.color;\r\n properties[propNames.outlineWeight.propertyName] = outlineSettings.weight;\r\n }\r\n\r\n let barSettings = cardSettings.barSettings;\r\n\r\n // The bar is shown if the outline value is not none\r\n let barShow = barSettings.outline !== outline.none;\r\n properties[propNames.barShow.propertyName] = barShow;\r\n\r\n if (barShow) {\r\n properties[propNames.barColor.propertyName] = barSettings.color;\r\n properties[propNames.barWeight.propertyName] = barSettings.weight;\r\n }\r\n\r\n properties[propNames.cardPadding.propertyName] = cardSettings.cardPadding;\r\n properties[propNames.cardBackground.propertyName] = cardSettings.cardBackground;\r\n\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: propNames.outline.objectName,\r\n properties: properties\r\n });\r\n }\r\n }\r\n\r\n function appendImage(selection: D3.Selection): void {\r\n selection\r\n .append('div')\r\n .classed('imgCon', true)\r\n .append('img');\r\n }\r\n\r\n function setImageStyle(selection: D3.Selection, imageStyle: ImageStyle): void {\r\n selection\r\n .selectAll('.imgCon')\r\n .style({\r\n 'height': getPixelString(imageStyle.maxHeight),\r\n })\r\n .selectAll('img')\r\n .style({\r\n 'max-height': getPixelString(imageStyle.maxHeight),\r\n 'max-width': getPixelString(imageStyle.maxWidth),\r\n });\r\n }\r\n\r\n function getPixelString(value: number): string {\r\n return value + \"px\";\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import KeyUtils = jsCommon.KeyUtils;\r\n import StringExtensions = jsCommon.StringExtensions;\r\n import UrlUtils = jsCommon.UrlUtils;\r\n\r\n export interface TextboxDataViewObjects extends DataViewObjects {\r\n general: TextboxDataViewObject;\r\n }\r\n\r\n export interface TextboxDataViewObject extends DataViewObject {\r\n paragraphs: Paragraphs;\r\n }\r\n \r\n /** Represents a rich text box that supports view & edit mode. */\r\n export class Textbox implements IVisual {\r\n private static ClassName = 'textbox';\r\n private editor: RichText.QuillWrapper;\r\n private element: JQuery;\r\n private host: IVisualHostServices;\r\n private viewport: IViewport;\r\n private readOnly: boolean;\r\n private paragraphs: Paragraphs;\r\n\r\n public init(options: VisualInitOptions) {\r\n this.element = options.element;\r\n this.host = options.host;\r\n this.viewport = options.viewport;\r\n\r\n this.readOnly = (this.host.getViewMode() === ViewMode.View);\r\n this.paragraphs = [];\r\n this.refreshView();\r\n }\r\n\r\n public onResizing(viewport: IViewport): void {\r\n this.viewport = viewport;\r\n this.updateSize();\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n let dataViews = options.dataViews;\r\n\r\n this.paragraphs = [];\r\n if (dataViews && dataViews.length > 0) {\r\n let objects = <TextboxDataViewObjects>dataViews[0].metadata.objects;\r\n\r\n if (objects && objects.general)\r\n this.paragraphs = objects.general.paragraphs;\r\n }\r\n\r\n this.refreshView();\r\n }\r\n\r\n public destroy(): void {\r\n }\r\n\r\n public focus(): boolean {\r\n if (!this.editor)\r\n return;\r\n\r\n this.editor.focus();\r\n return true;\r\n }\r\n\r\n public onViewModeChanged(viewMode: ViewMode): void {\r\n this.readOnly = (viewMode === ViewMode.View);\r\n this.refreshView();\r\n }\r\n\r\n public setSelection(start: number, end: number): void {\r\n debug.assertValue(this.editor, 'editor');\r\n\r\n if (this.editor)\r\n this.editor.setSelection(start, end);\r\n }\r\n\r\n private refreshView() {\r\n if (this.readOnly) {\r\n // Showing just HTML, no editor.\r\n // If we are in view-mode and we have an editor, we can remove it (after saving).\r\n if (this.editor) {\r\n this.saveContents();\r\n this.editor.destroy();\r\n this.editor = null;\r\n }\r\n\r\n this.element.empty();\r\n let htmlContent = RichTextConversion.convertParagraphsToHtml(this.paragraphs);\r\n htmlContent.addClass(Textbox.ClassName);\r\n htmlContent.css({\r\n 'font-family': RichText.defaultFont,\r\n 'font-size': RichText.defaultFontSize,\r\n });\r\n this.element.append(htmlContent);\r\n }\r\n else {\r\n // Showing the Quill editor.\r\n // If we are in edit-mode and we don't have an editor we need to create it.\r\n if (!this.editor) {\r\n this.editor = new RichText.QuillWrapper(this.readOnly, this.host);\r\n this.editor.textChanged = (delta, source) => this.saveContents();\r\n\r\n this.element.empty();\r\n let editorElement = this.editor.getElement();\r\n editorElement.addClass(Textbox.ClassName);\r\n editorElement.css({\r\n 'font-family': RichText.defaultFont,\r\n 'font-size': RichText.defaultFontSize,\r\n });\r\n this.element.append(editorElement);\r\n }\r\n\r\n this.editor.setContents(RichTextConversion.convertParagraphsToOps(this.paragraphs));\r\n }\r\n\r\n this.updateSize();\r\n }\r\n\r\n private saveContents(): void {\r\n // It's possible to get here via a throttled text-changed event after a view-mode change has occured and\r\n // we are now in view mode. Since we save changes on view-mode change it is safe to ignore this call.\r\n if (!this.editor)\r\n return;\r\n\r\n let contents: quill.Delta = this.editor.getContents();\r\n this.paragraphs = RichTextConversion.convertDeltaToParagraphs(contents);\r\n\r\n let changes: VisualObjectInstance[] = [{\r\n objectName: 'general',\r\n properties: {\r\n paragraphs: this.paragraphs\r\n },\r\n selector: null, // TODO: need something here?\r\n }];\r\n\r\n this.host.persistProperties(changes);\r\n }\r\n\r\n private updateSize(): void {\r\n if (this.editor)\r\n this.editor.resize(this.viewport);\r\n }\r\n }\r\n\r\n module RichTextConversion {\r\n export function convertDeltaToParagraphs(contents: quill.Delta): Paragraphs {\r\n let paragraphs: Paragraphs = [];\r\n let paragraph: Paragraph = { textRuns: [] };\r\n\r\n for (let i = 0, len = contents.ops.length; i < len; i++) {\r\n let insertOp = <quill.InsertOp>contents.ops[i];\r\n debug.assertValue(insertOp, \"operation should be an insert\");\r\n\r\n if (typeof insertOp.insert === \"string\") {\r\n // string insert values represent text.\r\n let text = <string>insertOp.insert;\r\n let attributes: quill.FormatAttributes = insertOp.attributes;\r\n\r\n if (attributes && attributes.align) {\r\n // Sometimes horizontal alignment is set after the first \"insert\" of the paragraph, which is likely a bug\r\n // in Quill. In any case we should never see different horizontal alignments in a single paragraph.\r\n debug.assert(\r\n paragraph.horizontalTextAlignment === undefined || paragraph.horizontalTextAlignment === attributes.align,\r\n 'paragraph should not have more than one horizontal alignment');\r\n paragraph.horizontalTextAlignment = attributes.align;\r\n }\r\n\r\n // Quill gives us back text runs that may have \\n's in them. We want to create a new paragraph for each \\n we see.\r\n let start = 0;\r\n let end = 0;\r\n let newParagraph: boolean;\r\n do {\r\n end = text.indexOf('\\n', start);\r\n if (end < 0) {\r\n newParagraph = false;\r\n end = text.length;\r\n }\r\n else {\r\n newParagraph = true;\r\n }\r\n\r\n if (end - start > 0) {\r\n let span = text.substring(start, end);\r\n let textRun: TextRun = { value: span };\r\n if (attributes) {\r\n if (attributes.link !== undefined && UrlUtils.isValidUrl(attributes.link))\r\n textRun.url = attributes.link;\r\n\r\n let textStyle = convertFormatAttributesToTextStyle(attributes);\r\n if (textStyle)\r\n textRun.textStyle = textStyle;\r\n }\r\n\r\n paragraph.textRuns.push(textRun);\r\n }\r\n\r\n // If we actually saw a '\\n' then create a new paragraph\r\n if (newParagraph) {\r\n if (paragraph.textRuns.length === 0)\r\n paragraph.textRuns.push({ value: '' });\r\n\r\n paragraphs.push(paragraph);\r\n paragraph = { textRuns: [] };\r\n }\r\n\r\n start = end + 1;\r\n } while (start < text.length);\r\n }\r\n else {\r\n // numeric insert values represent embeds.\r\n debug.assertFail(\"embeds not supported\");\r\n }\r\n }\r\n\r\n if (paragraph.textRuns.length > 0) {\r\n // Quill appears to always insert an extra '\\n' at the end of the text, skip it\r\n if (paragraph.textRuns[0].value.length > 0)\r\n paragraphs.push(paragraph);\r\n }\r\n\r\n return paragraphs;\r\n }\r\n\r\n export function convertParagraphsToHtml(paragraphs: Paragraphs): JQuery {\r\n let $paragraphs: JQuery = $();\r\n\r\n for (let paragraphIndex = 0, len = paragraphs.length; paragraphIndex < len; ++paragraphIndex) {\r\n let paragraphDef = paragraphs[paragraphIndex];\r\n let isParagraphEmpty = true;\r\n\r\n let $paragraph = $('<div>');\r\n\r\n if (paragraphDef.horizontalTextAlignment)\r\n $paragraph.css('text-align', paragraphDef.horizontalTextAlignment);\r\n\r\n for (let textRunIndex = 0, jlen = paragraphDef.textRuns.length; textRunIndex < jlen; ++textRunIndex) {\r\n let textRunDef = paragraphDef.textRuns[textRunIndex];\r\n\r\n let $textRun = $('<span>');\r\n\r\n let styleDef = textRunDef.textStyle;\r\n if (styleDef) {\r\n let css = {};\r\n if (styleDef.fontFamily) {\r\n css['font-family'] = RichText.getCssFontFamily(removeQuotes(styleDef.fontFamily));\r\n }\r\n\r\n if (styleDef.fontSize) {\r\n css['font-size'] = styleDef.fontSize;\r\n }\r\n\r\n if (styleDef.fontStyle) {\r\n css['font-style'] = styleDef.fontStyle;\r\n }\r\n\r\n if (styleDef.fontWeight) {\r\n css['font-weight'] = styleDef.fontWeight;\r\n }\r\n\r\n if (styleDef.textDecoration) {\r\n css['text-decoration'] = styleDef.textDecoration;\r\n }\r\n\r\n $textRun.css(css);\r\n }\r\n\r\n let text = textRunDef.value;\r\n if (!_.isEmpty(text))\r\n isParagraphEmpty = false;\r\n\r\n if (textRunDef.url !== undefined) {\r\n let $link: JQuery;\r\n if (UrlUtils.isValidUrl(textRunDef.url)) {\r\n $link = $('<a>')\r\n .attr('href', textRunDef.url)\r\n .attr('target', '_blank')\r\n .text(text);\r\n }\r\n else {\r\n $link = $('<span>').text(text);\r\n }\r\n\r\n $textRun.append($link);\r\n }\r\n else {\r\n $textRun.text(text);\r\n }\r\n\r\n $paragraph.append($textRun);\r\n }\r\n\r\n // If the entire paragraph is empty we need to make sure we enforce a line-break.\r\n if (isParagraphEmpty)\r\n $paragraph.append($('<br>'));\r\n\r\n $paragraphs = $paragraphs.add($paragraph);\r\n }\r\n\r\n return $paragraphs;\r\n }\r\n\r\n export function convertParagraphsToOps(paragraphs: Paragraphs): quill.Op[] {\r\n let ops: quill.InsertOp[] = [];\r\n\r\n for (let paragraphIndex = 0, len = paragraphs.length; paragraphIndex < len; ++paragraphIndex) {\r\n let paragraphDef = paragraphs[paragraphIndex];\r\n\r\n for (let textRunIndex = 0, jlen = paragraphDef.textRuns.length; textRunIndex < jlen; ++textRunIndex) {\r\n let textRunDef = paragraphDef.textRuns[textRunIndex];\r\n let formats: quill.FormatAttributes = {};\r\n\r\n if (paragraphDef.horizontalTextAlignment)\r\n formats.align = paragraphDef.horizontalTextAlignment;\r\n\r\n let styleDef = textRunDef.textStyle;\r\n if (styleDef) {\r\n if (styleDef.fontFamily) {\r\n formats.font = RichText.getCssFontFamily(removeQuotes(styleDef.fontFamily));\r\n }\r\n\r\n if (styleDef.fontSize) {\r\n formats.size = styleDef.fontSize;\r\n }\r\n\r\n formats.italic = (styleDef.fontStyle === 'italic');\r\n formats.bold = (styleDef.fontWeight === 'bold');\r\n formats.underline = (styleDef.textDecoration === 'underline');\r\n }\r\n\r\n let text = textRunDef.value;\r\n\r\n if (textRunDef.url && UrlUtils.isValidUrl(textRunDef.url))\r\n formats.link = textRunDef.url;\r\n\r\n let op: quill.InsertOp = {\r\n insert: text,\r\n attributes: formats,\r\n };\r\n\r\n ops.push(op);\r\n\r\n // The last text run of the paragraph needs to end with '\\n' to get Quill to handle the text alignment correctly.\r\n if (textRunIndex === (jlen - 1) && !StringExtensions.endsWith(text, '\\n')) {\r\n ops.push({\r\n insert: '\\n',\r\n attributes: formats,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return ops;\r\n }\r\n\r\n function convertFormatAttributesToTextStyle(attributes: quill.FormatAttributes): TextRunStyle {\r\n let style: TextRunStyle = {};\r\n\r\n // NOTE: Align is taken care of when converting to paragraphs.\r\n if (attributes.bold) {\r\n style.fontWeight = 'bold';\r\n }\r\n if (attributes.font) {\r\n // We should always save font names without any quotes.\r\n let font = removeQuotes(attributes.font);\r\n\r\n // Convert built-in font families back into their proper font families (e.g. wf_segoe-ui_normal -> Segoe UI)\r\n font = RichText.getFontFamilyForBuiltInFont(font);\r\n\r\n style.fontFamily = font;\r\n }\r\n if (attributes.italic) {\r\n style.fontStyle = 'italic';\r\n }\r\n if (attributes.size) {\r\n style.fontSize = attributes.size;\r\n }\r\n if (attributes.underline) {\r\n style.textDecoration = 'underline';\r\n }\r\n /*\r\n TODO:\r\n if (attributes.background) {\r\n }\r\n if (attributes.color) {\r\n }\r\n */\r\n\r\n return style;\r\n }\r\n\r\n function removeQuotes(text: string): string {\r\n if (!StringExtensions.startsWith(text, \"'\"))\r\n return text;\r\n\r\n debug.assert(StringExtensions.endsWith(text, \"'\"), \"mismatched quotes\");\r\n\r\n return text.slice(1, text.length - 1);\r\n }\r\n }\r\n\r\n export module RichText {\r\n interface ListValueOption {\r\n label: string;\r\n value: string;\r\n }\r\n \r\n /**\r\n * These fonts are embedded using CSS, or are aliases to other fonts.\r\n */\r\n const fontMap = {\r\n 'Segoe (Bold)': 'wf_segoe-ui_bold',\r\n 'Segoe UI': 'wf_segoe-ui_normal',\r\n 'Segoe UI Light': 'wf_segoe-ui_light',\r\n 'Heading': 'wf_segoe-ui_light',\r\n 'Body': 'wf_segoe-ui_normal',\r\n };\r\n\r\n const fonts: ListValueOption[] = [\r\n 'Arial',\r\n 'Arial Black',\r\n 'Arial Unicode MS',\r\n 'Calibri',\r\n 'Cambria',\r\n 'Cambria Math',\r\n 'Candara',\r\n 'Comic Sans MS',\r\n 'Consolas',\r\n 'Constantia',\r\n 'Corbel',\r\n 'Courier New',\r\n 'Georgia',\r\n 'Lucida Sans Unicode',\r\n 'Segoe (Bold)',\r\n 'Segoe UI',\r\n 'Segoe UI Light',\r\n 'Symbol',\r\n 'Tahoma',\r\n 'Times New Roman',\r\n 'Trebuchet MS',\r\n 'Verdana',\r\n 'Wingdings',\r\n\r\n // Fonts with numbers in the name do not work properly on Chrome. We'd need to quote the font names which causes problems with QuillJS.\r\n // TFS6832899\r\n //'Wingdings 2',\r\n //'Wingdings 3',\r\n\r\n ].map((font) => <ListValueOption>{ label: font, value: getCssFontFamily(font) });\r\n export let defaultFont = getCssFontFamily('Segoe UI Light');\r\n\r\n const fontSizes: ListValueOption[] = [\r\n '8', '9', '10', '10.5', '11', '12', '14', '16', '18', '20', '24', '28', '32', '36', '40', '42', '44', '54', '60', '66', '72', '80', '88', '96'\r\n ].map((size) => <ListValueOption> { label: size, value: size + 'px' });\r\n export const defaultFontSize = '14px';\r\n\r\n const textAlignments: ListValueOption[] = [\r\n 'Left',\r\n 'Center',\r\n 'Right',\r\n ].map((alignment) => <ListValueOption>{ label: alignment, value: alignment.toLowerCase() });\r\n\r\n /**\r\n * Given a font family returns the value we should use for the font-family css property.\r\n */\r\n export function getCssFontFamily(font: string): string {\r\n let family: string = fontMap[font];\r\n if (family == null)\r\n family = font;\r\n\r\n return family;\r\n }\r\n\r\n /**\r\n * Convert built-in font families back into their proper font families (e.g. wf_segoe-ui_normal -> Segoe UI)\r\n */\r\n export function getFontFamilyForBuiltInFont(font: string): string {\r\n let fontFamily = _.findKey(fontMap, (value) => value === font);\r\n return fontFamily || font;\r\n }\r\n\r\n export class QuillWrapper {\r\n private editor: quill.Quill;\r\n private $editorDiv: JQuery;\r\n private $toolbarDiv: JQuery;\r\n private $container: JQuery;\r\n private dependenciesLoaded: JQueryDeferred<void>;\r\n private localizationProvider: jsCommon.IStringResourceProvider;\r\n private host: IVisualHostServices;\r\n private static textChangeThrottle = 200; // ms\r\n\r\n public static preventDefaultKeys: number[] = [\r\n jsCommon.DOMConstants.aKeyCode, // A\r\n jsCommon.DOMConstants.cKeyCode, // C\r\n jsCommon.DOMConstants.xKeyCode, // X\r\n jsCommon.DOMConstants.vKeyCode, // V\r\n ];\r\n\r\n public static loadQuillResources: boolean = true;\r\n\r\n // TODO: How to choose between minified/unminified?\r\n // TODO: Consider loading this from the CDN.\r\n private static quillJsFiles = [powerbi.build + '/externals/quill.min.js'];\r\n private static quillCssFiles = [powerbi.build + '/externals/quill.base.css'];\r\n private QuillPackage: jsCommon.IDependency = {\r\n javaScriptFiles: QuillWrapper.quillJsFiles,\r\n cssFiles: QuillWrapper.quillCssFiles,\r\n };\r\n\r\n public initialized: boolean;\r\n public readOnly: boolean;\r\n public textChanged: (delta, source) => void = (d, s) => { };\r\n \r\n /**\r\n * JavaScript and CSS resources are typically resolved asynchronously.\r\n * This means we potentially defer certain events which typically occur\r\n * synchronously until resources are loaded.\r\n * Setting the global loadQuillResources flag to true will override\r\n * this behavior and cause the wrapper to assume these resources are already loaded\r\n * and not try to load them asynchronously (e.g. for use in unit tests).\r\n */ \r\n constructor(readOnly: boolean, host: IVisualHostServices) {\r\n this.host = host;\r\n this.$container = $('<div>');\r\n\r\n this.readOnly = readOnly;\r\n\r\n this.localizationProvider = {\r\n get: (stringId: string) => this.host.getLocalizedString(stringId),\r\n getOptional: (stringId: string) => this.host.getLocalizedString(stringId)\r\n };\r\n\r\n this.dependenciesLoaded = $.Deferred<void>();\r\n if (QuillWrapper.loadQuillResources) {\r\n // Defer creation of the editor until after resources are loaded.\r\n this.initialized = false;\r\n\r\n // Note that these are called in the order registered so this will always be called before other callbacks.\r\n this.dependenciesLoaded.done(() => {\r\n this.rebuildQuillEditor();\r\n this.initialized = true;\r\n });\r\n\r\n jsCommon.requires(this.QuillPackage, () => this.dependenciesLoaded.resolve());\r\n }\r\n else {\r\n this.rebuildQuillEditor();\r\n this.initialized = true;\r\n this.dependenciesLoaded.resolve();\r\n }\r\n }\r\n\r\n public addModule(name: any, options: any): any {\r\n if (this.editor)\r\n return this.editor.addModule(name, options);\r\n }\r\n\r\n public getElement(): JQuery {\r\n return this.$container;\r\n }\r\n\r\n public getContents(): quill.Delta {\r\n if (this.initialized)\r\n return this.editor.getContents();\r\n }\r\n\r\n public setContents(contents: quill.Delta | quill.Op[]): void {\r\n // If we haven't loaded the editor yet, defer this call until we do\r\n // TODO: prevent these from stacking up?\r\n if (!this.initialized) {\r\n this.dependenciesLoaded.done(() => this.setContents(contents));\r\n return;\r\n }\r\n\r\n this.editor.setHTML('', 'api'); // Clear contents\r\n if (contents)\r\n this.editor.setContents(contents, 'api');\r\n }\r\n\r\n public resize(viewport: IViewport): void {\r\n this.$container.width(viewport.width);\r\n this.$container.height(viewport.height);\r\n }\r\n\r\n public setReadOnly(readOnly: boolean): void {\r\n let readOnlyChanged = readOnly !== this.readOnly;\r\n this.readOnly = readOnly;\r\n\r\n if (this.initialized && readOnlyChanged) {\r\n this.rebuildQuillEditor();\r\n }\r\n }\r\n\r\n public setSelection(start: number, end: number): void {\r\n if (this.editor)\r\n this.editor.setSelection(start, end, 'api');\r\n }\r\n\r\n public getSelection(): quill.Range {\r\n if (this.editor)\r\n return this.editor.getSelection();\r\n }\r\n\r\n public focus(): void {\r\n if (!this.editor)\r\n return;\r\n\r\n if ($(document.activeElement).closest(this.$container).length === 0)\r\n this.editor.focus();\r\n }\r\n\r\n public destroy(): void {\r\n this.host.setToolbar(null);\r\n this.$container.remove();\r\n this.$container = null;\r\n this.$toolbarDiv = null;\r\n this.$editorDiv = null;\r\n this.editor = null;\r\n }\r\n\r\n public getSelectionAtCursor(): quill.Range {\r\n let text = this.getTextWithoutTrailingBreak();\r\n\r\n // Ensure editor has focus before selection interactions\r\n this.editor.focus();\r\n \r\n let selection = this.getSelection();\r\n if (selection && selection.start === selection.end) {\r\n return jsCommon.WordBreaker.find(selection.start, text);\r\n }\r\n\r\n return selection;\r\n }\r\n\r\n public getWord() {\r\n let selection = this.getSelectionAtCursor();\r\n return this.getTextWithoutTrailingBreak().slice(selection.start, selection.end);\r\n }\r\n\r\n public insertLinkAtCursor(link: string, index: number): number {\r\n let endIndex = index + link.length;\r\n \r\n this.editor.insertText(index, link, 'api');\r\n this.editor.formatText(index, endIndex, 'link', link, 'api');\r\n this.setSelection(index, endIndex);\r\n\r\n this.onTextChanged(null, null);\r\n\r\n return endIndex;\r\n }\r\n\r\n public getEditorContainer(): JQuery {\r\n if (this.editor)\r\n return $(this.editor.container);\r\n };\r\n\r\n private getTextWithoutTrailingBreak(): string {\r\n return this.editor.getText().slice(0, -1);\r\n }\r\n\r\n private rebuildQuillEditor(): void {\r\n // Preserve contents if we already have an editor.\r\n let contents: quill.Delta = null;\r\n if (this.editor) {\r\n this.editor.removeAllListeners();\r\n contents = this.editor.getContents();\r\n }\r\n\r\n this.$container.empty();\r\n\r\n // Prevent parent elements from handling keyboard shortcuts (e.g. ctrl+a) that have special meaning for textboxes.\r\n // Quill will also capture and prevent bubbling of some keyboard shortcuts, such as ctrl+c, ctrl+b, etc.\r\n this.$container.keydown((e) => {\r\n if (e.ctrlKey && _.contains(QuillWrapper.preventDefaultKeys, e.which))\r\n e.stopPropagation();\r\n\r\n if (KeyUtils.isArrowKey(e.which))\r\n e.stopPropagation();\r\n });\r\n\r\n let $editorDiv = this.$editorDiv = $('<div>');\r\n\r\n // HACK: Quill does not apply the correct default styling if you clear all the content and add new content.\r\n $editorDiv.css('font-family', defaultFont);\r\n $editorDiv.css('font-size', defaultFontSize);\r\n\r\n let configs = {\r\n readOnly: this.readOnly,\r\n formats: ['bold', 'italic', 'underline', 'font', 'size', 'link', 'align', /* TODO: 'color', 'background' */],\r\n styles: false,\r\n };\r\n this.editor = new Quill($editorDiv.get(0), configs);\r\n\r\n // If not readonly we add a toolbar and disable drag/resize\r\n if (!this.readOnly) {\r\n let $toolbarDiv = this.$toolbarDiv;\r\n if (!$toolbarDiv) {\r\n this.$toolbarDiv = $toolbarDiv = Toolbar.buildToolbar(this, this.localizationProvider);\r\n }\r\n\r\n $toolbarDiv.addClass('unselectable');\r\n this.host.setToolbar($toolbarDiv);\r\n this.editor.addModule('toolbar', { container: $toolbarDiv.get(0) });\r\n\r\n // Disable this so we can select text in the editor.\r\n $editorDiv.attr('drag-resize-disabled', 'true');\r\n }\r\n\r\n this.$container.append($editorDiv);\r\n\r\n if (contents)\r\n this.setContents(contents);\r\n\r\n // Throttle text-changed events to not more frequent than once per 200ms\r\n let textChangeThrottler = new jsCommon.ThrottleUtility(QuillWrapper.textChangeThrottle);\r\n this.editor.on('text-change', (delta, source) => {\r\n if (source !== 'api')\r\n textChangeThrottler.run(() => this.onTextChanged(delta, source));\r\n });\r\n\r\n /*\r\n Webkit browsers have a bug with regard to focus on div elements\r\n with the contenteditable attribute:\r\n\r\n https://bugs.webkit.org/show_bug.cgi?id=38696\r\n\r\n When we blur our rich text box editor the focus remains with the selection\r\n instead of the focused element. This allows the user to continue typing as\r\n if focus remains within the RichTextbox.\r\n\r\n To fix this issue we add an event listener to the contenteditable div\r\n which listens for the 'blur' event and will properly blur our quill\r\n editor as well.\r\n\r\n http://quilljs.com/docs/api/#quillprototypesetselection\r\n\r\n Verified in Chrome 43.0.2357.130 m\r\n\r\n In IE10+ the setSelection method explicitly sets focus to the body which\r\n causes a bug where the user must click twice when attempting to interact\r\n with a <select> element. To prevent this issue we explicitly do not call\r\n setSelection to blur if the user is changing focus to a <select> element.\r\n This issue is also present for link tooltips from the Quill module which\r\n will cause a blur onto the tooltip.\r\n */\r\n this.editor.root.addEventListener('blur', (event) => {\r\n let target: HTMLElement = <HTMLElement>(event.relatedTarget || document.activeElement);\r\n\r\n // The browser will handle moving the cursor and setting focus properly for these types of elements.\r\n if (target &&\r\n target.tagName === 'SELECT' || target.tagName === 'INPUT' || target.getAttribute('contentEditable')) {\r\n return;\r\n }\r\n\r\n this.setSelection(null, null);\r\n }, false);\r\n }\r\n\r\n private onTextChanged(delta, source): void {\r\n this.textChanged(delta, source);\r\n }\r\n }\r\n\r\n module Toolbar {\r\n const DefaultLinkInputValue = 'http://';\r\n\r\n export const selectors = {\r\n linkTooltip: createClassAndSelector('ql-link-tooltip'),\r\n toolbarUrlInput: createClassAndSelector('toolbar-url-input'),\r\n };\r\n\r\n export function buildToolbar(quillWrapper: QuillWrapper, localizationProvider: jsCommon.IStringResourceProvider) {\r\n // Module for adding custom hyperlinks\r\n let linkTooltipTemplate = buildToolbarLinkInputTemplate(localizationProvider);\r\n quillWrapper.addModule('link-tooltip', { template: linkTooltipTemplate });\r\n\r\n let toolbarLinkInput: JQuery = buildToolbarLinkInput(quillWrapper, getTooltip('Link', localizationProvider), localizationProvider.get('RichTextbox_Link_DefaultText'));\r\n\r\n let fontPicker = picker(getTooltip('Font', localizationProvider), fonts, 'font', defaultFont,\r\n // Show the fonts in their own font face.\r\n ($option, option) => { $option.css('font-family', option.value); return $option; }\r\n );\r\n\r\n let $container = div()\r\n .addClass('toolbar ql-toolbar')\r\n .append(\r\n formatGroup()\r\n .append(label(localizationProvider.get('RichTextbox_Font_Label')))\r\n .append(fontPicker)\r\n .append(picker(getTooltip('Size', localizationProvider), fontSizes, 'size', defaultFontSize))\r\n )\r\n .append(\r\n formatGroup()\r\n .append(formatButton(getTooltip('Bold', localizationProvider), 'bold'))\r\n .append(formatButton(getTooltip('Italic', localizationProvider), 'italic'))\r\n .append(formatButton(getTooltip('Underline', localizationProvider), 'underline'))\r\n )\r\n .append(\r\n formatGroup()\r\n .append(toggleGroup('Text Alignment', textAlignments, 'align', 'Left', localizationProvider))\r\n )\r\n .append(toolbarLinkInput);\r\n\r\n // Prevent mousedown from triggering subsequent blur on editor\r\n $container.on('mousedown', (event) => {\r\n let target = <HTMLElement>(event.target || document.activeElement);\r\n if (target.tagName !== 'INPUT' && target.tagName !== 'SELECT')\r\n event.preventDefault();\r\n });\r\n\r\n return $container;\r\n }\r\n\r\n export function setSelectValue($select: JQuery, value: any): void {\r\n $select.val(value);\r\n // NOTE: The 'change' event is not raised when the value of the SELECT element is changed programatically,\r\n // and Quill uses it's own, non-JQuery, method to hook up to the 'change' event, therefore, we need to dispatch\r\n // this event manually on the SELECT element.\r\n let evt = document.createEvent('UIEvent');\r\n evt.initUIEvent('change', false, false, null, 0);\r\n $select.get(0).dispatchEvent(evt);\r\n }\r\n\r\n function linkTooltipTemplateGenerator(removeText: string, doneText: string): JQuery {\r\n return $(`\r\n <a href=\"#\" class=\"url\" target=\"_blank\"></a>\r\n <input class=\"input\" type=\"text\">\r\n <span class=\"bar\">&nbsp;|&nbsp;</span>\r\n <a class=\"change\"></a>\r\n <a class=\"remove\">${removeText}</a>\r\n <a class=\"done\">${doneText}</a>\r\n `);\r\n };\r\n\r\n function buildToolbarLinkInputTemplate(localizationProvider: jsCommon.IStringResourceProvider): string {\r\n let template: JQuery = div();\r\n let doneText = localizationProvider.get('RichTextbox_Link_Done');\r\n let removeText = localizationProvider.get('RichTextbox_Link_Remove');\r\n\r\n template.append(linkTooltipTemplateGenerator(removeText, doneText));\r\n\r\n return template.html();\r\n }\r\n\r\n function formatGroup(): JQuery {\r\n return span()\r\n .addClass('ql-format-group')\r\n .attr('drag-resize-disabled', 'true');\r\n }\r\n\r\n function label(text: string): JQuery {\r\n return $('<label>').text(text);\r\n }\r\n\r\n function div(): JQuery {\r\n return $('<div>');\r\n }\r\n\r\n function span(): JQuery {\r\n return $('<span>');\r\n }\r\n\r\n function toggleGroup(title: string, list: ListValueOption[], format: string, defaultValue: string, localizationProvider: jsCommon.IStringResourceProvider): JQuery {\r\n let tooltip = getTooltip(title, localizationProvider);\r\n let $group = span()\r\n .attr('title', tooltip)\r\n .addClass('ql-toggle-group');\r\n\r\n // Hidden selector that Quill will use to hook up change listeners.\r\n let $select = selector(tooltip, list, defaultValue)\r\n .addClass('ql-picker ql-' + format)\r\n .css('display', 'none');\r\n\r\n let $buttons = list.map((option) => {\r\n let $button = formatButton(getTooltip(option.label, localizationProvider), 'align' + option.value)\r\n .attr('data-value', option.value)\r\n .click((e) => setSelectValue($select, option.value));\r\n return $button;\r\n });\r\n\r\n // Quill will change the value of the selector when the text selection changes, so we need to set the state of the buttons to match.\r\n $select.change((e) => {\r\n let newValue = $select.val();\r\n for (let i = 0; i < $buttons.length; i++) {\r\n $buttons[i].toggleClass('ql-active', $buttons[i].attr('data-value') === newValue);\r\n }\r\n });\r\n\r\n $group.append($select);\r\n $group.append($buttons);\r\n\r\n return $group;\r\n }\r\n\r\n function picker(tooltip: string, list: ListValueOption[], format: string, defaultValue: string, optionModifier?: (JQuery, ListValueOption) => JQuery): JQuery {\r\n let $selector = selector(tooltip, list, defaultValue, optionModifier)\r\n .addClass('ql-picker ql-' + format);\r\n\r\n return $selector;\r\n }\r\n\r\n function selector(tooltip: string, list: ListValueOption[], defaultValue?: string, optionModifier?: (JQuery, ListValueOption) => JQuery): JQuery {\r\n let $selector = $('<select>')\r\n .attr('title', tooltip);\r\n\r\n for (let i = 0; i < list.length; i++) {\r\n let option = list[i];\r\n let $option = $('<option>')\r\n .attr('value', option.value)\r\n .text(option.label);\r\n\r\n if (option.value === defaultValue)\r\n $option.attr('selected', 'selected');\r\n\r\n if (optionModifier !== undefined)\r\n $option = optionModifier($option, option);\r\n\r\n $selector.append($option);\r\n }\r\n\r\n return $selector;\r\n }\r\n\r\n function formatButton(tooltip?: string, format?: string) {\r\n let $button = span()\r\n .addClass('ql-format-button');\r\n\r\n if (tooltip != null)\r\n $button.attr('title', tooltip);\r\n\r\n if (format != null) {\r\n $button.addClass('ql-' + format);\r\n $button.addClass('powervisuals-glyph ' + format);\r\n }\r\n\r\n return $button;\r\n }\r\n\r\n function getTooltip(name: string, localizationProvider: jsCommon.IStringResourceProvider): string {\r\n return localizationProvider.get('RichTextbox_' + name + '_ToolTip');\r\n }\r\n\r\n function clearLinkInput(linkTooltip: JQuery): void {\r\n linkTooltip.removeClass('editing');\r\n linkTooltip.removeClass('blank-editing');\r\n linkTooltip.find('.input').val(DefaultLinkInputValue);\r\n }\r\n\r\n function buildToolbarLinkInput(quillWrapper: QuillWrapper, buttonTooltip: string, defaultLinkText: string): JQuery {\r\n // Pull out link tooltip\r\n let linkTooltip = quillWrapper.getEditorContainer().find(Toolbar.selectors.linkTooltip.selector);\r\n\r\n // Append link tooltip to a new toolbar format group\r\n let toolbarLinkInput: JQuery = formatGroup()\r\n .addClass(Toolbar.selectors.toolbarUrlInput.class)\r\n .append(formatButton(buttonTooltip, 'link').append('<div>'))\r\n .append(linkTooltip);\r\n\r\n // Special case for blank selection (no text near cursor) when enter key or done button clicked\r\n toolbarLinkInput.on('keydown mousedown', (event: JQueryEventObject) => {\r\n if (event.keyCode === jsCommon.DOMConstants.enterKeyCode || (<HTMLElement>event.target).classList.contains('done')) {\r\n if (!linkTooltip.hasClass('blank-editing'))\r\n return true;\r\n\r\n // Only perform these steps if tooltip was not in editing mode (special case for blank)\r\n let link = toolbarLinkInput.find('.input').val();\r\n let selection = quillWrapper.getSelectionAtCursor();\r\n let word = quillWrapper.getWord();\r\n if (!word) {\r\n // Insert the input text as a link\r\n let endCursor = quillWrapper.insertLinkAtCursor(link, selection.start);\r\n clearLinkInput(linkTooltip);\r\n quillWrapper.setSelection(endCursor, endCursor);\r\n return false;\r\n }\r\n }\r\n });\r\n\r\n toolbarLinkInput.find('.input').blur((event: JQueryEventObject) => {\r\n let blurTarget = event.relatedTarget;\r\n // Remove editing class from insert link tooltip (to hide via CSS)\r\n // only when we are not blurring to the 'done' button (tab from input field)\r\n if (blurTarget === null || blurTarget && !blurTarget.classList.contains('done'))\r\n clearLinkInput(linkTooltip);\r\n });\r\n\r\n toolbarLinkInput.find('.ql-link div')\r\n .click((event: JQueryEventObject) => {\r\n // Handle click on button before Quill removes link (default behavior)\r\n let target = (<HTMLElement>event.target).parentElement;\r\n if (target && target.classList.contains('ql-active')) {\r\n toolbarLinkInput.find('.change')[0].click();\r\n return false;\r\n }\r\n\r\n // If blank selection (no text near cursor), special case for link button\r\n let word = quillWrapper.getWord();\r\n if (!word) {\r\n linkTooltip.addClass('editing blank-editing');\r\n let inputElem = (<HTMLInputElement>toolbarLinkInput.find('.input').get(0));\r\n inputElem.value = DefaultLinkInputValue;\r\n inputElem.selectionStart = inputElem.selectionEnd = DefaultLinkInputValue.length;\r\n inputElem.focus();\r\n return false;\r\n }\r\n })\r\n .mousedown((event: JQueryEventObject) => {\r\n // Properly set selection before we handle the click\r\n let linkButton = (<HTMLElement>event.target).parentElement;\r\n if (linkButton && !linkButton.classList.contains('ql-active')) {\r\n let selection = quillWrapper.getSelectionAtCursor();\r\n quillWrapper.setSelection(selection.start, selection.end);\r\n }\r\n });\r\n\r\n return toolbarLinkInput;\r\n }\r\n }\r\n }\r\n}","/*\r\n* Power BI Visualizations\r\n*\r\n* Copyright (c) Microsoft Corporation\r\n* All rights reserved. \r\n* MIT License\r\n*\r\n* Permission is hereby granted, free of charge, to any person obtaining a copy\r\n* of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n* in the Software without restriction, including without limitation the rights\r\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n* copies of the Software, and to permit persons to whom the Software is\r\n* furnished to do so, subject to the following conditions:\r\n* \r\n* The above copyright notice and this permission notice shall be included in \r\n* all copies or substantial portions of the Software.\r\n* \r\n* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n* THE SOFTWARE.\r\n*/\r\n \r\n\r\nmodule powerbi.visuals {\r\nimport SelectionManager = utility.SelectionManager;\r\n\r\nexport const cheerMeterProps = {\r\n dataPoint: {\r\n defaultColor: <DataViewObjectPropertyIdentifier>{\r\n objectName: 'dataPoint',\r\n propertyName: 'defaultColor'\r\n },\r\n fill: <DataViewObjectPropertyIdentifier>{\r\n objectName: 'dataPoint',\r\n propertyName: 'fill'\r\n },\r\n },\r\n };\r\n\r\n export interface TeamData {\r\n name: string;\r\n value: number;\r\n color: string;\r\n identity: SelectionId;\r\n }\r\n\r\n export interface CheerData {\r\n teamA: TeamData;\r\n teamB: TeamData;\r\n background: string;\r\n }\r\n\r\n interface CheerLayout {\r\n x1: number;\r\n x2: number;\r\n y1: number;\r\n y2: number;\r\n fontSize: string;\r\n }\r\n\r\n export class CheerMeter implements IVisual {\r\n public static capabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n displayName: 'Category',\r\n name: 'Category',\r\n kind: powerbi.VisualDataRoleKind.Grouping,\r\n },\r\n {\r\n displayName: 'Noise Measure',\r\n name: 'Y',\r\n kind: powerbi.VisualDataRoleKind.Measure,\r\n },\r\n ],\r\n dataViewMappings: [{\r\n categorical: {\r\n categories: {\r\n for: { in: 'Category' },\r\n },\r\n values: {\r\n select: [{ bind: { to: 'Y' } }]\r\n },\r\n },\r\n }],\r\n objects: {\r\n dataPoint: {\r\n displayName: data.createDisplayNameGetter('Visual_DataPoint'),\r\n description: data.createDisplayNameGetter('Visual_DataPointDescription'),\r\n properties: {\r\n fill: {\r\n displayName: data.createDisplayNameGetter('Visual_Fill'),\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n width: {\r\n displayName: '',\r\n type: { numeric: true }\r\n }\r\n }\r\n },\r\n general: {\r\n displayName: 'General',\r\n properties: {\r\n fill: {\r\n displayName: 'Background color',\r\n type: { fill: { solid: { color: true } } }\r\n },\r\n\r\n }\r\n }\r\n }\r\n };\r\n\r\n private static DefaultFontFamily = 'cursive';\r\n private static DefaultFontColor = 'rgb(165, 172, 175)';\r\n private static DefaultBackgroundColor = '#243C18';\r\n private static PaddingBetweenText = 15;\r\n\r\n private textOne: D3.Selection;\r\n private textTwo: D3.Selection;\r\n private svg: D3.Selection;\r\n private isFirstTime: boolean = true;\r\n private data: CheerData;\r\n private selectionManager: SelectionManager;\r\n\r\n public static converter(dataView: DataView): CheerData {\r\n if (!dataView.categorical || !dataView.categorical.categories) return null;\r\n let cat = dataView.categorical.categories[0];\r\n if (!cat) return null;\r\n let catValues = cat.values;\r\n if (!catValues || _.isEmpty(dataView.categorical.values)) return null;\r\n let values = dataView.categorical.values[0].values;\r\n let objects = dataView.categorical.categories[0].objects;\r\n let object1 = objects && objects.length > 0 ? objects[0] : undefined;\r\n let object2 = objects && objects.length > 1 ? objects[1] : undefined;\r\n let metadataObjects = dataView.metadata.objects;\r\n let backgroundColor = CheerMeter.DefaultBackgroundColor;\r\n if (metadataObjects) {\r\n let general = metadataObjects['general'];\r\n if (general) {\r\n let fill = <Fill>general['fill'];\r\n if (fill) {\r\n backgroundColor = fill.solid.color;\r\n }\r\n }\r\n }\r\n\r\n let color1 = DataViewObjects.getFillColor(\r\n object1,\r\n cheerMeterProps.dataPoint.fill,\r\n CheerMeter.DefaultFontColor);\r\n\r\n let color2 = DataViewObjects.getFillColor(\r\n object2,\r\n cheerMeterProps.dataPoint.fill,\r\n CheerMeter.DefaultFontColor);\r\n\r\n let idn1 = SelectionIdBuilder.builder()\r\n .withCategory(cat, 0)\r\n .createSelectionId();\r\n let idn2 = SelectionIdBuilder.builder()\r\n .withCategory(cat, 1)\r\n .createSelectionId();\r\n\r\n let data = {\r\n teamA: {\r\n name: catValues[0],\r\n value: values[0],\r\n color: color1,\r\n identity: idn1\r\n },\r\n teamB: {\r\n name: catValues[1],\r\n value: values[1],\r\n color: color2,\r\n identity: idn2\r\n },\r\n background: backgroundColor\r\n };\r\n\r\n return data;\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.selectionManager = new SelectionManager({ hostServices: options.host });\r\n let svg = this.svg = d3.select(options.element.get(0)).append('svg');\r\n\r\n this.textOne = svg.append('text')\r\n .style('font-family', CheerMeter.DefaultFontFamily);\r\n\r\n this.textTwo = svg.append('text')\r\n .style('font-family', CheerMeter.DefaultFontFamily);\r\n }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n if (!options.dataViews[0]) { return; }\r\n let data = this.data = CheerMeter.converter(options.dataViews[0]);\r\n if (!data) return;\r\n let duration = options.suppressAnimations ? 0 : AnimatorCommon.MinervaAnimationDuration;\r\n this.draw(data, duration, options.viewport);\r\n }\r\n\r\n private getRecomendedFontProperties(text1: string, text2: string, parentViewport: IViewport): TextProperties {\r\n let textProperties: TextProperties = {\r\n fontSize: '',\r\n fontFamily: CheerMeter.DefaultFontFamily,\r\n text: text1 + text2\r\n };\r\n\r\n let min = 1;\r\n let max = 1000;\r\n let i;\r\n let maxWidth = parentViewport.width;\r\n let width = 0;\r\n\r\n while (min <= max) {\r\n i = (min + max) / 2 | 0;\r\n\r\n textProperties.fontSize = i + 'px';\r\n width = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n\r\n if (maxWidth > width)\r\n min = i + 1;\r\n else if (maxWidth < width)\r\n max = i - 1;\r\n else\r\n break;\r\n }\r\n\r\n textProperties.fontSize = i + 'px';\r\n width = TextMeasurementService.measureSvgTextWidth(textProperties);\r\n if (width > maxWidth) {\r\n i--;\r\n textProperties.fontSize = i + 'px';\r\n }\r\n\r\n return textProperties;\r\n }\r\n\r\n private calculateLayout(data: CheerData, viewport: IViewport): CheerLayout {\r\n let text1 = data.teamA.name;\r\n let text2 = data.teamB.name;\r\n\r\n let avaliableViewport: IViewport = {\r\n height: viewport.height,\r\n width: viewport.width - CheerMeter.PaddingBetweenText\r\n };\r\n let recomendedFontProperties = this.getRecomendedFontProperties(text1, text2, avaliableViewport);\r\n\r\n recomendedFontProperties.text = text1;\r\n let width1 = TextMeasurementService.measureSvgTextWidth(recomendedFontProperties) | 0;\r\n\r\n recomendedFontProperties.text = text2;\r\n let width2 = TextMeasurementService.measureSvgTextWidth(recomendedFontProperties) | 0;\r\n\r\n let padding = ((viewport.width - width1 - width2 - CheerMeter.PaddingBetweenText) / 2) | 0;\r\n\r\n recomendedFontProperties.text = text1 + text2;\r\n let offsetHeight = (TextMeasurementService.measureSvgTextHeight(recomendedFontProperties)) | 0;\r\n\r\n let max = data.teamA.value + data.teamB.value;\r\n let availableHeight = viewport.height - offsetHeight;\r\n let y1 = (((max - data.teamA.value) / max) * availableHeight + offsetHeight / 2) | 0;\r\n let y2 = (((max - data.teamB.value) / max) * availableHeight + offsetHeight / 2) | 0;\r\n\r\n return {\r\n x1: padding,\r\n x2: padding + width1 + CheerMeter.PaddingBetweenText,\r\n y1: y1,\r\n y2: y2,\r\n fontSize: recomendedFontProperties.fontSize\r\n };\r\n }\r\n\r\n private ensureStartState(layout: CheerLayout, viewport: IViewport) {\r\n if (this.isFirstTime) {\r\n this.isFirstTime = false;\r\n let startY = viewport.height / 2;\r\n this.textOne.attr(\r\n {\r\n 'x': layout.x1,\r\n 'y': startY\r\n });\r\n\r\n this.textTwo.attr(\r\n {\r\n 'x': layout.x2,\r\n 'y': startY\r\n });\r\n }\r\n }\r\n\r\n private clearSelection() {\r\n this.selectionManager.clear().then(() => {\r\n this.clearSelectionUI();\r\n });\r\n }\r\n\r\n private clearSelectionUI() {\r\n this.textOne.style('stroke', '#FFF').style('stroke-width', 0);\r\n this.textTwo.style('stroke', '#FFF').style('stroke-width', 0);\r\n }\r\n\r\n private updateSelectionUI(ids: SelectionId[]) {\r\n this.textOne.style('stroke', '#FFF').style('stroke-width', SelectionManager.containsSelection(ids, this.data.teamA.identity) ? '2px' : '0px');\r\n this.textTwo.style('stroke', '#FFF').style('stroke-width', SelectionManager.containsSelection(ids, this.data.teamB.identity) ? '2px' : '0px');\r\n }\r\n\r\n private draw(data: CheerData, duration: number, viewport: IViewport) {\r\n let easeName = 'back';\r\n let textOne = this.textOne;\r\n let textTwo = this.textTwo;\r\n\r\n this.svg\r\n .attr({\r\n 'height': viewport.height,\r\n 'width': viewport.width\r\n })\r\n .on('click', () => {\r\n this.clearSelection();\r\n })\r\n .style('background-color', data.background);\r\n\r\n let layout = this.calculateLayout(data, viewport);\r\n\r\n this.ensureStartState(layout, viewport);\r\n\r\n textOne\r\n .style('font-size', layout.fontSize)\r\n .style('fill', data.teamA.color)\r\n .on('click', () => {\r\n this.selectionManager.select(data.teamA.identity, d3.event.ctrlKey).then((ids) => {\r\n this.updateSelectionUI(ids);\r\n });\r\n d3.event.stopPropagation();\r\n })\r\n .text(data.teamA.name);\r\n\r\n textTwo\r\n .style('font-size', layout.fontSize)\r\n .style('fill', data.teamB.color)\r\n .on('click', () => {\r\n this.selectionManager.select(data.teamB.identity, d3.event.ctrlKey).then((ids) => {\r\n this.updateSelectionUI(ids);\r\n });\r\n d3.event.stopPropagation();\r\n })\r\n .text(data.teamB.name);\r\n\r\n textOne.transition()\r\n .duration(duration)\r\n .ease(easeName)\r\n .attr({\r\n y: layout.y1,\r\n x: layout.x1\r\n });\r\n\r\n textTwo.transition()\r\n .duration(duration)\r\n .ease(easeName)\r\n .attr({\r\n y: layout.y2,\r\n x: layout.x2\r\n });\r\n }\r\n\r\n public destroy(): void {\r\n this.svg = null;\r\n this.textOne = this.textTwo = null;\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] {\r\n let instances: VisualObjectInstance[] = [];\r\n let data = this.data;\r\n switch (options.objectName) {\r\n case 'dataPoint':\r\n if (data) {\r\n let teams = [data.teamA, data.teamB];\r\n\r\n for (let i = 0; i < teams.length; i++) {\r\n let slice = teams[i];\r\n\r\n let color = slice.color;\r\n let selector = slice.identity;\r\n\r\n let dataPointInstance: VisualObjectInstance = {\r\n objectName: 'dataPoint',\r\n displayName: slice.name,\r\n selector: selector,\r\n properties: {\r\n fill: { solid: { color: color } }\r\n },\r\n };\r\n\r\n instances.push(dataPointInstance);\r\n };\r\n }\r\n break;\r\n case 'general':\r\n let general: VisualObjectInstance = {\r\n objectName: 'general',\r\n displayName: 'General',\r\n selector: null,\r\n properties: {\r\n fill: { solid: { color: data ? data.background : CheerMeter.DefaultBackgroundColor } }\r\n }\r\n };\r\n instances.push(general);\r\n break;\r\n }\r\n\r\n return instances;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import Color = jsCommon.Color;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import DataRoleHelper = powerbi.data.DataRoleHelper;\r\n import IDataViewCategoricalReader = powerbi.data.IDataViewCategoricalReader;\r\n\r\n export interface ScatterChartConstructorOptions extends CartesianVisualConstructorOptions {\r\n }\r\n\r\n export interface ScatterChartDataPoint extends SelectableDataPoint, TooltipEnabledDataPoint, LabelEnabledDataPoint {\r\n x: any;\r\n y: any;\r\n size: any;\r\n radius: RadiusData;\r\n fill: string;\r\n formattedCategory: jsCommon.Lazy<string>;\r\n fontSize?: number;\r\n }\r\n\r\n export interface ScatterChartDataPointSeries {\r\n identityKey: string;\r\n dataPoints?: ScatterChartDataPoint[];\r\n hasSize?: boolean;\r\n fill?: string;\r\n }\r\n\r\n export interface RadiusData {\r\n sizeMeasure: DataViewValueColumn;\r\n index: number;\r\n }\r\n\r\n export interface DataRange {\r\n minRange: number;\r\n maxRange: number;\r\n delta: number;\r\n }\r\n\r\n export interface ScatterChartData extends PlayableChartData, ScatterBehaviorChartData {\r\n xCol: DataViewMetadataColumn;\r\n yCol: DataViewMetadataColumn;\r\n dataPoints: ScatterChartDataPoint[];\r\n dataPointSeries: ScatterChartDataPointSeries[];\r\n legendData: LegendData;\r\n axesLabels: ChartAxesLabels;\r\n size?: DataViewMetadataColumn;\r\n sizeRange: NumberRange;\r\n dataLabelsSettings: PointDataLabelsSettings;\r\n defaultDataPointColor?: string;\r\n showAllDataPoints?: boolean;\r\n hasDynamicSeries?: boolean;\r\n fillPoint?: boolean;\r\n colorBorder?: boolean;\r\n colorByCategory?: boolean;\r\n }\r\n\r\n export interface ScatterChartViewModel {\r\n xAxisProperties: IAxisProperties;\r\n yAxisProperties: IAxisProperties;\r\n viewport: IViewport;\r\n data: ScatterChartData;\r\n drawBubbles: boolean;\r\n isPlay: boolean;\r\n fillMarkers: boolean;\r\n hasSelection: boolean;\r\n animationDuration: number;\r\n animationOptions: AnimationOptions;\r\n easeType: string;\r\n suppressDataPointRendering: boolean;\r\n }\r\n\r\n interface ScatterChartMeasureMetadata {\r\n idx: {\r\n x?: number;\r\n y?: number;\r\n size?: number;\r\n };\r\n cols: {\r\n x?: DataViewMetadataColumn;\r\n y?: DataViewMetadataColumn;\r\n size?: DataViewMetadataColumn;\r\n };\r\n axesLabels: ChartAxesLabels;\r\n }\r\n\r\n interface MouseCoordinates {\r\n x: number;\r\n y: number;\r\n }\r\n\r\n export interface ScatterConverterOptions {\r\n viewport: IViewport;\r\n colors: any;\r\n interactivityService?: any;\r\n categoryAxisProperties?: any;\r\n valueAxisProperties?: any;\r\n }\r\n\r\n interface ScatterObjectProperties {\r\n fillPoint?: boolean;\r\n colorBorder?: boolean;\r\n showAllDataPoints?: boolean;\r\n defaultDataPointColor?: string;\r\n colorByCategory?: boolean;\r\n }\r\n\r\n /** Styles to apply to scatter chart data point marker */\r\n export interface ScatterMarkerStyle {\r\n 'stroke-opacity': number;\r\n stroke: string;\r\n fill: string;\r\n 'fill-opacity': number;\r\n }\r\n\r\n export interface CartesianExtents {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n }\r\n\r\n export class ScatterChart implements ICartesianVisual {\r\n private static BubbleRadius = 3 * 2;\r\n public static DefaultBubbleOpacity = 0.85;\r\n public static DimmedBubbleOpacity = 0.4;\r\n public static StrokeDarkenColorValue = 255 * 0.25;\r\n //label layout settings\r\n public static dataLabelLayoutStartingOffset: number = 2;\r\n public static dataLabelLayoutOffsetIterationDelta: number = 6;\r\n public static dataLabelLayoutMaximumOffset: number = ScatterChart.dataLabelLayoutStartingOffset + (2 * ScatterChart.dataLabelLayoutOffsetIterationDelta);\r\n // Chart Area and size range values as defined by PV charts\r\n private static AreaOf300By300Chart = 90000;\r\n private static MinSizeRange = 200;\r\n private static MaxSizeRange = 3000;\r\n private static ClassName = 'scatterChart';\r\n // Animated rendering threshold - if more than this number of data points, rendering is grouped by series and not animated\r\n public static NoAnimationThreshold = 1000;\r\n // No render resize threshold - if more than this number of data points, rendering is suppressed during resize\r\n public static NoRenderResizeThreshold = 1000;\r\n\r\n private svg: D3.Selection;\r\n private element: JQuery;\r\n private currentViewport: IViewport;\r\n private style: IVisualStyle;\r\n private data: ScatterChartData;\r\n private dataView: DataView;\r\n private host: IVisualHostServices;\r\n private margin: IMargin;\r\n\r\n private colors: IDataColorPalette;\r\n private options: CartesianVisualInitOptions;\r\n private interactivity: InteractivityOptions;\r\n private cartesianVisualHost: ICartesianVisualHost;\r\n private isMobileChart: boolean;\r\n private interactivityService: IInteractivityService;\r\n private categoryAxisProperties: DataViewObject;\r\n private valueAxisProperties: DataViewObject;\r\n private animator: IGenericAnimator;\r\n private tooltipsEnabled: boolean;\r\n\r\n private xAxisProperties: IAxisProperties;\r\n private yAxisProperties: IAxisProperties;\r\n\r\n private renderer: SvgRenderer;\r\n private playAxis: PlayAxis<ScatterChartData>;\r\n\r\n constructor(options: ScatterChartConstructorOptions) {\r\n if (options) {\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n this.interactivityService = options.interactivityService;\r\n this.animator = options.animator;\r\n }\r\n\r\n this.renderer = new SvgRenderer();\r\n }\r\n\r\n public init(options: CartesianVisualInitOptions) {\r\n this.options = options;\r\n this.element = options.element;\r\n this.currentViewport = options.viewport;\r\n this.style = options.style;\r\n this.host = options.host;\r\n this.colors = this.style.colorPalette.dataColors;\r\n this.interactivity = options.interactivity;\r\n this.cartesianVisualHost = options.cartesianHost;\r\n this.isMobileChart = options.interactivity && options.interactivity.isInteractiveLegend;\r\n\r\n let svg = this.svg = options.svg;\r\n\r\n // TODO: should we always be adding the playchart class name?\r\n svg.classed(ScatterChart.ClassName + ' ' + PlayChart.ClassName, true);\r\n\r\n this.renderer.init(svg, options.labelsContext, this.isMobileChart, this.tooltipsEnabled);\r\n }\r\n\r\n public static getAdditionalTelemetry(dataView: DataView): any {\r\n let telemetry = {\r\n hasSize: DataRoleHelper.hasRoleInDataView(dataView, 'Size'),\r\n hasPlayAxis: DataRoleHelper.hasRoleInDataView(dataView, 'Play'),\r\n };\r\n\r\n return telemetry;\r\n }\r\n\r\n private static getObjectProperties(dataView: DataView, dataLabelsSettings?: PointDataLabelsSettings): ScatterObjectProperties {\r\n let objects: DataViewObjects;\r\n if (dataView && dataView.metadata && dataView.metadata.objects)\r\n objects = dataView.metadata.objects;\r\n else\r\n objects = {};\r\n\r\n let objectProperties: ScatterObjectProperties = {};\r\n\r\n objectProperties.defaultDataPointColor = DataViewObjects.getFillColor(objects, columnChartProps.dataPoint.defaultColor);\r\n objectProperties.showAllDataPoints = DataViewObjects.getValue<boolean>(objects, columnChartProps.dataPoint.showAllDataPoints, false);\r\n\r\n let labelsObj = <DataLabelObject>objects['categoryLabels'];\r\n if (labelsObj && dataLabelsSettings)\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\r\n\r\n // NOTE: \"fill point\" defaults to on when we have a gradient role.\r\n let hasGradient = dataView && GradientUtils.hasGradientRole(dataView.categorical);\r\n objectProperties.fillPoint = DataViewObjects.getValue(objects, scatterChartProps.fillPoint.show, hasGradient);\r\n\r\n objectProperties.colorBorder = DataViewObjects.getValue(objects, scatterChartProps.colorBorder.show, false);\r\n objectProperties.colorByCategory = DataViewObjects.getValue(objects, scatterChartProps.colorByCategory.show, false);\r\n\r\n return objectProperties;\r\n }\r\n\r\n public static converter(dataView: DataView, options: ScatterConverterOptions, playFrameInfo?: PlayFrameInfo, tooltipsEnabled: boolean = true): ScatterChartData {\r\n let reader = powerbi.data.createIDataViewCategoricalReader(dataView);\r\n let categoryValues: any[],\r\n categoryFormatter: IValueFormatter,\r\n categoryObjects: DataViewObjects[],\r\n categoryIdentities: DataViewScopeIdentity[],\r\n categoryQueryName: string;\r\n\r\n let currentViewport = options.viewport;\r\n let colorPalette = options.colors;\r\n let interactivityService = options.interactivityService;\r\n let categoryAxisProperties = options.categoryAxisProperties;\r\n let valueAxisProperties = options.valueAxisProperties;\r\n\r\n let dataViewCategorical: DataViewCategorical = dataView.categorical;\r\n let gradientValueColumn: DataViewValueColumn = GradientUtils.getGradientValueColumn(dataViewCategorical);\r\n\r\n if (dataViewCategorical.categories && dataViewCategorical.categories.length > 0) {\r\n categoryValues = dataViewCategorical.categories[0].values;\r\n categoryFormatter = valueFormatter.create({ format: valueFormatter.getFormatString(dataViewCategorical.categories[0].source, scatterChartProps.general.formatString), value: categoryValues[0], value2: categoryValues[categoryValues.length - 1] });\r\n categoryIdentities = dataViewCategorical.categories[0].identity;\r\n categoryObjects = dataViewCategorical.categories[0].objects;\r\n categoryQueryName = dataViewCategorical.categories[0].source.queryName;\r\n }\r\n else {\r\n categoryValues = [null];\r\n // creating default formatter for null value (to get the right string of empty value from the locale)\r\n categoryFormatter = valueFormatter.createDefaultFormatter(null);\r\n }\r\n\r\n let categories = dataViewCategorical.categories;\r\n let dataValues = dataViewCategorical.values;\r\n let hasDynamicSeries = !!dataValues.source;\r\n let grouped = dataValues.grouped();\r\n let dvSource = dataValues.source;\r\n let scatterMetadata = ScatterChart.getMetadata(grouped, dvSource);\r\n let dataLabelsSettings = dataLabelUtils.getDefaultPointLabelSettings();\r\n let sizeRange = ScatterChart.getSizeRangeForGroups(grouped, scatterMetadata.idx.size);\r\n\r\n let objProps = ScatterChart.getObjectProperties(dataView, dataLabelsSettings);\r\n\r\n let dataPointSeries = ScatterChart.createDataPointSeries(\r\n reader,\r\n dataValues,\r\n scatterMetadata,\r\n categories,\r\n categoryValues,\r\n categoryFormatter,\r\n categoryIdentities,\r\n categoryObjects,\r\n colorPalette,\r\n currentViewport,\r\n hasDynamicSeries,\r\n dataLabelsSettings,\r\n gradientValueColumn,\r\n objProps.defaultDataPointColor,\r\n categoryQueryName,\r\n objProps.colorByCategory,\r\n playFrameInfo,\r\n tooltipsEnabled);\r\n let dataPoints = _.reduce(dataPointSeries, (a, s) => a.concat(s.dataPoints), []);\r\n\r\n let legendItems = hasDynamicSeries\r\n ? ScatterChart.createSeriesLegend(dataValues, colorPalette, dataValues, valueFormatter.getFormatString(dvSource, scatterChartProps.general.formatString), objProps.defaultDataPointColor)\r\n : [];\r\n\r\n let legendTitle = dataValues && dvSource ? dvSource.displayName : \"\";\r\n if (!legendTitle) {\r\n legendTitle = categories && categories.length > 0 && categories[0].source.displayName ? categories[0].source.displayName : \"\";\r\n }\r\n\r\n if (categoryAxisProperties && categoryAxisProperties[\"showAxisTitle\"] !== null && categoryAxisProperties[\"showAxisTitle\"] === false) {\r\n scatterMetadata.axesLabels.x = null;\r\n }\r\n if (valueAxisProperties && valueAxisProperties[\"showAxisTitle\"] !== null && valueAxisProperties[\"showAxisTitle\"] === false) {\r\n scatterMetadata.axesLabels.y = null;\r\n }\r\n\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(dataPoints);\r\n interactivityService.applySelectionStateToData(legendItems);\r\n }\r\n\r\n return {\r\n xCol: scatterMetadata.cols.x,\r\n yCol: scatterMetadata.cols.y,\r\n dataPoints: dataPoints,\r\n dataPointSeries: dataPointSeries,\r\n legendData: { title: legendTitle, dataPoints: legendItems },\r\n axesLabels: scatterMetadata.axesLabels,\r\n size: scatterMetadata.cols.size,\r\n sizeRange: sizeRange,\r\n dataLabelsSettings: dataLabelsSettings,\r\n defaultDataPointColor: objProps.defaultDataPointColor,\r\n hasDynamicSeries: hasDynamicSeries,\r\n showAllDataPoints: objProps.showAllDataPoints,\r\n fillPoint: objProps.fillPoint,\r\n colorBorder: objProps.colorBorder,\r\n colorByCategory: objProps.colorByCategory,\r\n };\r\n }\r\n\r\n private static getSizeRangeForGroups(\r\n dataViewValueGroups: DataViewValueColumnGroup[],\r\n sizeColumnIndex: number): NumberRange {\r\n\r\n let result: NumberRange = {};\r\n if (dataViewValueGroups) {\r\n dataViewValueGroups.forEach((group) => {\r\n let sizeColumn = ScatterChart.getMeasureValue(sizeColumnIndex, group.values);\r\n let currentRange: NumberRange = AxisHelper.getRangeForColumn(sizeColumn);\r\n if (result.min == null || result.min > currentRange.min) {\r\n result.min = currentRange.min;\r\n }\r\n if (result.max == null || result.max < currentRange.max) {\r\n result.max = currentRange.max;\r\n }\r\n });\r\n }\r\n return result;\r\n }\r\n\r\n private static createDataPointSeries(\r\n reader: IDataViewCategoricalReader,\r\n dataValues: DataViewValueColumns,\r\n metadata: ScatterChartMeasureMetadata,\r\n categories: DataViewCategoryColumn[],\r\n categoryValues: any[],\r\n categoryFormatter: IValueFormatter,\r\n categoryIdentities: DataViewScopeIdentity[],\r\n categoryObjects: DataViewObjects[],\r\n colorPalette: IDataColorPalette,\r\n viewport: IViewport,\r\n hasDynamicSeries: boolean,\r\n labelSettings: PointDataLabelsSettings,\r\n gradientValueColumn: DataViewValueColumn,\r\n defaultDataPointColor: string,\r\n categoryQueryName: string,\r\n colorByCategory: boolean,\r\n playFrameInfo: PlayFrameInfo,\r\n tooltipsEnabled: boolean): ScatterChartDataPointSeries[] {\r\n\r\n let hasX = reader.hasValues(\"X\");\r\n let hasY = reader.hasValues(\"Y\");\r\n\r\n if (!hasX && !hasY) {\r\n return [];\r\n }\r\n\r\n let dataPointSeries: ScatterChartDataPointSeries[] = [],\r\n indicies = metadata.idx,\r\n formatStringProp = scatterChartProps.general.formatString,\r\n dataValueSource = dataValues.source,\r\n grouped = dataValues.grouped();\r\n\r\n let colorHelper = new ColorHelper(colorPalette, scatterChartProps.dataPoint.fill, defaultDataPointColor);\r\n\r\n for (let seriesIndex = 0, len = grouped.length; seriesIndex < len; seriesIndex++) {\r\n let grouping = grouped[seriesIndex];\r\n let seriesValues = grouping.values;\r\n let measureX = ScatterChart.getMeasureValue(indicies.x, seriesValues);\r\n let measureY = ScatterChart.getMeasureValue(indicies.y, seriesValues);\r\n let measureSize = ScatterChart.getMeasureValue(indicies.size, seriesValues);\r\n\r\n let seriesColor: string;\r\n if (hasDynamicSeries) {\r\n seriesColor = colorHelper.getColorForSeriesValue(grouping.objects, dataValues.identityFields, grouping.name);\r\n }\r\n else if (!colorByCategory && !categoryObjects) {\r\n // If we have no Size measure then use a blank query name\r\n let measureSource = (measureSize != null)\r\n ? measureSize.source.queryName\r\n : '';\r\n\r\n seriesColor = colorHelper.getColorForMeasure(null, measureSource);\r\n }\r\n\r\n let series: ScatterChartDataPointSeries = {\r\n identityKey: (grouping && grouping.identity && grouping.identity.key) || \"\",\r\n dataPoints: [],\r\n hasSize: !!(measureSize && measureSize.values),\r\n fill: seriesColor,\r\n };\r\n\r\n dataPointSeries.push(series);\r\n\r\n for (let categoryIndex = 0, ilen = categoryValues.length; categoryIndex < ilen; categoryIndex++) {\r\n let categoryValue = categoryValues[categoryIndex];\r\n\r\n // Zero out X and Y if the role doesn't exist, so you still get a set of vertical/horizontal dots\r\n let xVal = hasX ? AxisHelper.normalizeNonFiniteNumber(reader.getValue(\"X\", categoryIndex, seriesIndex)) : 0;\r\n let yVal = hasY ? AxisHelper.normalizeNonFiniteNumber(reader.getValue(\"Y\", categoryIndex, seriesIndex)) : 0;\r\n // Undefined size is handled later if we don't have a size role, so this is fine to just be undefined\r\n let size = AxisHelper.normalizeNonFiniteNumber(reader.getValue(\"Size\", categoryIndex, seriesIndex));\r\n\r\n // Do not render a dot if X or Y are null\r\n if (xVal == null || yVal == null)\r\n continue;\r\n\r\n let color: string;\r\n if (hasDynamicSeries) {\r\n color = colorHelper.getColorForSeriesValue(grouping.objects, dataValues.identityFields, grouping.name);\r\n }\r\n else if (colorByCategory) {\r\n color = colorHelper.getColorForSeriesValue(categoryObjects && categoryObjects[categoryIndex], dataValues.identityFields, categoryValue);\r\n }\r\n else {\r\n // If we have no Size measure then use a blank query name\r\n let measureSource = (measureSize != null)\r\n ? measureSize.source.queryName\r\n : '';\r\n\r\n color = colorHelper.getColorForMeasure(categoryObjects && categoryObjects[categoryIndex], measureSource);\r\n }\r\n\r\n let category = !_.isEmpty(categories) ? categories[0] : null;\r\n let identity = SelectionIdBuilder.builder()\r\n .withCategory(category, categoryIndex)\r\n .withSeries(dataValues, grouping)\r\n .createSelectionId();\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n\r\n if (category) {\r\n tooltipInfo.push({\r\n displayName: category.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(categoryValue, category.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (hasDynamicSeries) {\r\n // Dynamic series\r\n if ( !category || category.source !== dataValueSource) {\r\n tooltipInfo.push({\r\n displayName: dataValueSource.displayName,\r\n value: converterHelper.formatFromMetadataColumn(grouping.name, dataValueSource, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n if (measureX && xVal != null) {\r\n tooltipInfo.push({\r\n displayName: measureX.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(xVal, measureX.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (measureY && yVal != null) {\r\n tooltipInfo.push({\r\n displayName: measureY.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(yVal, measureY.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (measureSize && measureSize.values[categoryIndex] != null) {\r\n tooltipInfo.push({\r\n displayName: measureSize.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(measureSize.values[categoryIndex], measureSize.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (gradientValueColumn && gradientValueColumn.values[categoryIndex] != null) {\r\n tooltipInfo.push({\r\n displayName: gradientValueColumn.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(gradientValueColumn.values[categoryIndex], gradientValueColumn.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (playFrameInfo) {\r\n tooltipInfo.push({\r\n displayName: playFrameInfo.column.displayName,\r\n value: converterHelper.formatFromMetadataColumn(playFrameInfo.label, playFrameInfo.column, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n let dataPoint: ScatterChartDataPoint = {\r\n x: xVal,\r\n y: yVal,\r\n size: size,\r\n radius: { sizeMeasure: measureSize, index: categoryIndex },\r\n fill: color,\r\n formattedCategory: ScatterChart.createLazyFormattedCategory(categoryFormatter, categories != null ? categoryValue : grouping.name),\r\n selected: false,\r\n identity: identity,\r\n tooltipInfo: tooltipInfo,\r\n labelFill: labelSettings.labelColor,\r\n };\r\n\r\n series.dataPoints.push(dataPoint);\r\n }\r\n }\r\n return dataPointSeries;\r\n }\r\n\r\n public static createLazyFormattedCategory(formatter: IValueFormatter, value: string): jsCommon.Lazy<string> {\r\n return new jsCommon.Lazy(() => formatter.format(value));\r\n }\r\n\r\n private static createSeriesLegend(\r\n dataValues: DataViewValueColumns,\r\n colorPalette: IDataColorPalette,\r\n categorical: DataViewValueColumns,\r\n formatString: string,\r\n defaultDataPointColor: string): LegendDataPoint[] {\r\n\r\n let grouped = dataValues.grouped();\r\n let colorHelper = new ColorHelper(colorPalette, scatterChartProps.dataPoint.fill, defaultDataPointColor);\r\n\r\n let legendItems: LegendDataPoint[] = [];\r\n for (let i = 0, len = grouped.length; i < len; i++) {\r\n let grouping = grouped[i];\r\n let color = colorHelper.getColorForSeriesValue(grouping.objects, dataValues.identityFields, grouping.name);\r\n legendItems.push({\r\n color: color,\r\n icon: LegendIcon.Circle,\r\n label: valueFormatter.format(grouping.name, formatString),\r\n identity: grouping.identity ? SelectionId.createWithId(grouping.identity) : SelectionId.createNull(),\r\n selected: false\r\n });\r\n }\r\n\r\n return legendItems;\r\n }\r\n\r\n public static getBubbleRadius(radiusData: RadiusData, sizeRange: NumberRange, viewport: IViewport): number {\r\n let actualSizeDataRange = null;\r\n let bubblePixelAreaSizeRange = null;\r\n let measureSize = radiusData.sizeMeasure;\r\n\r\n if (!measureSize)\r\n return ScatterChart.BubbleRadius;\r\n\r\n let minSize = sizeRange.min ? sizeRange.min : 0;\r\n let maxSize = sizeRange.max ? sizeRange.max : 0;\r\n\r\n let min = Math.min(minSize, 0);\r\n let max = Math.max(maxSize, 0);\r\n actualSizeDataRange = {\r\n minRange: min,\r\n maxRange: max,\r\n delta: max - min\r\n };\r\n\r\n bubblePixelAreaSizeRange = ScatterChart.getBubblePixelAreaSizeRange(viewport, ScatterChart.MinSizeRange, ScatterChart.MaxSizeRange);\r\n\r\n if (measureSize.values) {\r\n let sizeValue = measureSize.values[radiusData.index];\r\n if (sizeValue != null) {\r\n return ScatterChart.projectSizeToPixels(sizeValue, actualSizeDataRange, bubblePixelAreaSizeRange) / 2;\r\n }\r\n }\r\n\r\n return ScatterChart.BubbleRadius;\r\n }\r\n\r\n public static getMeasureValue(measureIndex: number, seriesValues: DataViewValueColumn[]): DataViewValueColumn {\r\n if (measureIndex >= 0)\r\n return seriesValues[measureIndex];\r\n\r\n return null;\r\n }\r\n\r\n private static getMetadata(grouped: DataViewValueColumnGroup[], source: DataViewMetadataColumn): ScatterChartMeasureMetadata {\r\n let xIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, 'X');\r\n let yIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, 'Y');\r\n let sizeIndex = DataRoleHelper.getMeasureIndexOfRole(grouped, 'Size');\r\n let xCol: DataViewMetadataColumn;\r\n let yCol: DataViewMetadataColumn;\r\n let sizeCol: DataViewMetadataColumn;\r\n let xAxisLabel = \"\";\r\n let yAxisLabel = \"\";\r\n\r\n if (grouped && grouped.length) {\r\n let firstGroup = grouped[0];\r\n if (xIndex >= 0) {\r\n xCol = firstGroup.values[xIndex].source;\r\n xAxisLabel = firstGroup.values[xIndex].source.displayName;\r\n }\r\n if (yIndex >= 0) {\r\n yCol = firstGroup.values[yIndex].source;\r\n yAxisLabel = firstGroup.values[yIndex].source.displayName;\r\n }\r\n if (sizeIndex >= 0) {\r\n sizeCol = firstGroup.values[sizeIndex].source;\r\n }\r\n }\r\n\r\n return {\r\n idx: {\r\n x: xIndex,\r\n y: yIndex,\r\n size: sizeIndex,\r\n },\r\n cols: {\r\n x: xCol,\r\n y: yCol,\r\n size: sizeCol,\r\n },\r\n axesLabels: {\r\n x: xAxisLabel,\r\n y: yAxisLabel\r\n }\r\n };\r\n }\r\n\r\n /** Create a new viewmodel with default data. */\r\n public static getDefaultData(): ScatterChartData {\r\n return {\r\n xCol: undefined,\r\n yCol: undefined,\r\n dataPoints: [],\r\n dataPointSeries: [],\r\n legendData: { dataPoints: [] },\r\n axesLabels: { x: '', y: '' },\r\n sizeRange: [],\r\n dataLabelsSettings: dataLabelUtils.getDefaultPointLabelSettings(),\r\n defaultDataPointColor: null,\r\n hasDynamicSeries: false,\r\n };\r\n }\r\n\r\n private renderAtFrame(data: ScatterChartData): void {\r\n this.data = data;\r\n this.cartesianVisualHost.triggerRender(false);\r\n }\r\n\r\n public setData(dataViews: DataView[]): void {\r\n this.data = ScatterChart.getDefaultData();\r\n\r\n if (dataViews.length > 0) {\r\n let dataView = dataViews[0] || dataViews[1];\r\n\r\n if (dataView) {\r\n this.categoryAxisProperties = CartesianHelper.getCategoryAxisProperties(dataView.metadata, true);\r\n this.valueAxisProperties = CartesianHelper.getValueAxisProperties(dataView.metadata, true);\r\n this.dataView = dataView;\r\n\r\n let converterOptions: ScatterConverterOptions = {\r\n viewport: this.currentViewport,\r\n colors: this.colors,\r\n interactivityService: this.interactivityService,\r\n categoryAxisProperties: this.categoryAxisProperties,\r\n valueAxisProperties: this.valueAxisProperties,\r\n };\r\n\r\n if (PlayChart.isDataViewPlayable(dataView)) {\r\n if (!this.playAxis) {\r\n this.playAxis = new PlayAxis<ScatterChartData>({\r\n animator: this.animator,\r\n interactivityService: this.interactivityService,\r\n isScrollable: false,\r\n });\r\n this.playAxis.init(this.options);\r\n }\r\n\r\n let playData = this.playAxis.setData(\r\n dataView,\r\n (dataView: DataView, playFrameInfo?: PlayFrameInfo) =>\r\n ScatterChart.converter(dataView, converterOptions, playFrameInfo, this.tooltipsEnabled));\r\n this.mergeSizeRanges(playData);\r\n this.data = playData.currentViewModel;\r\n\r\n this.playAxis.setRenderFunction((data) => this.renderAtFrame(data));\r\n }\r\n else {\r\n if (this.playAxis) {\r\n this.playAxis.remove();\r\n this.playAxis = null;\r\n }\r\n\r\n if (dataView.categorical && dataView.categorical.values) {\r\n this.data = ScatterChart.converter(dataView, converterOptions, undefined, this.tooltipsEnabled);\r\n }\r\n }\r\n }\r\n }\r\n else if (this.playAxis) {\r\n this.playAxis.remove();\r\n this.playAxis = null;\r\n }\r\n }\r\n\r\n private mergeSizeRanges(playData: PlayChartData<ScatterChartData>): void {\r\n if (playData && playData.currentViewModel) {\r\n let mergedSizeRange: NumberRange = playData.currentViewModel.sizeRange;\r\n for (let data of playData.allViewModels) {\r\n let sizeRange = data.sizeRange;\r\n if (sizeRange.min != null)\r\n mergedSizeRange.min = Math.min(mergedSizeRange.min, sizeRange.min);\r\n if (sizeRange.max != null)\r\n mergedSizeRange.max = Math.max(mergedSizeRange.max, sizeRange.max);\r\n }\r\n for (let data of playData.allViewModels) {\r\n data.sizeRange = mergedSizeRange;\r\n }\r\n }\r\n }\r\n\r\n public calculateLegend(): LegendData {\r\n return this.data && this.data.legendData;\r\n }\r\n\r\n public hasLegend(): boolean {\r\n return this.data && this.data.hasDynamicSeries;\r\n }\r\n\r\n public enumerateObjectInstances(enumeration: ObjectEnumerationBuilder, options: EnumerateVisualObjectInstancesOptions): void {\r\n switch (options.objectName) {\r\n case 'colorByCategory':\r\n if (this.data) {\r\n // Color by Legend takes precedent during render. Hide the slice but keep the colorByCategory value unchanged in case they remove the Legend field.\r\n if (!this.data.hasDynamicSeries) {\r\n enumeration.pushInstance({\r\n objectName: 'colorByCategory',\r\n selector: null,\r\n properties: {\r\n show: this.data.colorByCategory,\r\n },\r\n });\r\n }\r\n }\r\n break;\r\n case 'dataPoint':\r\n // TODO: DataViewMatix (for PlayAxis) doesn't support category- or series-specific properties yet.\r\n if (!this.playAxis) {\r\n let categoricalDataView: DataViewCategorical = this.dataView && this.dataView.categorical ? this.dataView.categorical : null;\r\n if (!GradientUtils.hasGradientRole(categoricalDataView))\r\n return this.enumerateDataPoints(enumeration);\r\n }\r\n break;\r\n case 'categoryAxis':\r\n enumeration.pushInstance({\r\n selector: null,\r\n properties: {\r\n showAxisTitle: !this.categoryAxisProperties || this.categoryAxisProperties[\"showAxisTitle\"] == null ? true : this.categoryAxisProperties[\"showAxisTitle\"]\r\n },\r\n objectName: 'categoryAxis'\r\n });\r\n break;\r\n case 'valueAxis':\r\n enumeration.pushInstance({\r\n selector: null,\r\n properties: {\r\n showAxisTitle: !this.valueAxisProperties || this.valueAxisProperties[\"showAxisTitle\"] == null ? true : this.valueAxisProperties[\"showAxisTitle\"]\r\n },\r\n objectName: 'valueAxis'\r\n });\r\n break;\r\n case 'categoryLabels':\r\n if (this.data)\r\n dataLabelUtils.enumerateCategoryLabels(enumeration, this.data.dataLabelsSettings, true);\r\n else\r\n dataLabelUtils.enumerateCategoryLabels(enumeration, null, true);\r\n break;\r\n case 'fillPoint':\r\n // Check if the card should be shown or not based on the existence of size measure\r\n if (this.hasSizeMeasure())\r\n return;\r\n\r\n enumeration.pushInstance({\r\n objectName: 'fillPoint',\r\n selector: null,\r\n properties: {\r\n show: this.data.fillPoint,\r\n },\r\n });\r\n break;\r\n case 'colorBorder':\r\n // Check if the card should be shown or not based on the existence of size measure\r\n if (this.hasSizeMeasure())\r\n enumeration.pushInstance({\r\n objectName: 'colorBorder',\r\n selector: null,\r\n properties: {\r\n show: this.data.colorBorder,\r\n },\r\n });\r\n break;\r\n }\r\n }\r\n\r\n private hasSizeMeasure(): boolean {\r\n let sizeRange = this.data.sizeRange;\r\n return sizeRange && sizeRange.min !== undefined;\r\n }\r\n\r\n private enumerateDataPoints(enumeration: ObjectEnumerationBuilder): void {\r\n let data = this.data;\r\n if (!data)\r\n return;\r\n\r\n let seriesCount = data.dataPoints.length;\r\n\r\n if (!data.hasDynamicSeries) {\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n selector: null,\r\n properties: {\r\n defaultColor: { solid: { color: data.defaultDataPointColor || this.colors.getColorByIndex(0).value } }\r\n }\r\n }).pushInstance({\r\n objectName: 'dataPoint',\r\n selector: null,\r\n properties: {\r\n showAllDataPoints: !!data.showAllDataPoints\r\n }\r\n });\r\n\r\n for (let i = 0; i < seriesCount; i++) {\r\n let seriesDataPoints = data.dataPoints[i];\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: seriesDataPoints.formattedCategory.getValue(),\r\n selector: ColorHelper.normalizeSelector(seriesDataPoints.identity.getSelector(), /*isSingleSeries*/ true),\r\n properties: {\r\n fill: { solid: { color: seriesDataPoints.fill } }\r\n },\r\n });\r\n }\r\n }\r\n else {\r\n let legendDataPointLength = data.legendData.dataPoints.length;\r\n for (let i = 0; i < legendDataPointLength; i++) {\r\n let series = data.legendData.dataPoints[i];\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: series.label,\r\n selector: ColorHelper.normalizeSelector(series.identity.getSelector()),\r\n properties: {\r\n fill: { solid: { color: series.color } }\r\n },\r\n });\r\n }\r\n }\r\n }\r\n\r\n public supportsTrendLine(): boolean {\r\n let data = this.data;\r\n if (!data)\r\n return false;\r\n\r\n return !this.hasSizeMeasure() && data.dataPointSeries.length > 0;\r\n }\r\n\r\n private static getExtents(data: ScatterChartData): CartesianExtents {\r\n let dps = data.dataPoints;\r\n if (_.isEmpty(dps)) {\r\n return {\r\n minY: 0,\r\n maxY: 0,\r\n minX: 0,\r\n maxX: 0,\r\n };\r\n }\r\n\r\n return {\r\n minY: d3.min<ScatterChartDataPoint, number>(dps, d => d.y),\r\n maxY: d3.max<ScatterChartDataPoint, number>(dps, d => d.y),\r\n minX: d3.min<ScatterChartDataPoint, number>(dps, d => d.x),\r\n maxX: d3.max<ScatterChartDataPoint, number>(dps, d => d.x),\r\n };\r\n }\r\n\r\n public calculateAxesProperties(options: CalculateScaleAndDomainOptions): IAxisProperties[] {\r\n let data = this.data;\r\n let viewport = this.currentViewport = options.viewport;\r\n let margin = options.margin;\r\n\r\n this.currentViewport = viewport;\r\n this.margin = margin;\r\n\r\n let width = viewport.width - (margin.left + margin.right);\r\n let height = viewport.height - (margin.top + margin.bottom);\r\n\r\n let extents: CartesianExtents = {\r\n minY: 0,\r\n maxY: 10,\r\n minX: 0,\r\n maxX: 10\r\n };\r\n\r\n if (this.playAxis) {\r\n extents = this.playAxis.getCartesianExtents(extents, ScatterChart.getExtents);\r\n this.playAxis.setPlayControlPosition(options.playAxisControlLayout);\r\n }\r\n else if (!_.isEmpty(data.dataPoints)) {\r\n extents = ScatterChart.getExtents(data);\r\n }\r\n\r\n let xDomain = [extents.minX, extents.maxX];\r\n let combinedXDomain = AxisHelper.combineDomain(options.forcedXDomain, xDomain, options.ensureXDomain);\r\n\r\n this.xAxisProperties = AxisHelper.createAxis({\r\n pixelSpan: width,\r\n dataDomain: combinedXDomain,\r\n metaDataColumn: data.xCol,\r\n formatString: valueFormatter.getFormatString(data.xCol, scatterChartProps.general.formatString),\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: false,\r\n forcedTickCount: options.forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: true, //scatter doesn't have a categorical axis, but this is needed for the pane to react correctly to the x-axis toggle one/off\r\n scaleType: options.categoryAxisScaleType,\r\n axisDisplayUnits: options.categoryAxisDisplayUnits,\r\n axisPrecision: options.categoryAxisPrecision\r\n });\r\n this.xAxisProperties.axis.tickSize(-height, 0);\r\n this.xAxisProperties.axisLabel = this.data.axesLabels.x;\r\n\r\n let combinedDomain = AxisHelper.combineDomain(options.forcedYDomain, [extents.minY, extents.maxY], options.ensureYDomain);\r\n\r\n this.yAxisProperties = AxisHelper.createAxis({\r\n pixelSpan: height,\r\n dataDomain: combinedDomain,\r\n metaDataColumn: data.yCol,\r\n formatString: valueFormatter.getFormatString(data.yCol, scatterChartProps.general.formatString),\r\n outerPadding: 0,\r\n isScalar: true,\r\n isVertical: true,\r\n forcedTickCount: options.forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false,\r\n scaleType: options.valueAxisScaleType,\r\n axisDisplayUnits: options.valueAxisDisplayUnits,\r\n axisPrecision: options.valueAxisPrecision\r\n });\r\n this.yAxisProperties.axisLabel = this.data.axesLabels.y;\r\n\r\n // TODO: these should be passed into the render method.\r\n return [this.xAxisProperties, this.yAxisProperties];\r\n }\r\n\r\n public overrideXScale(xProperties: IAxisProperties): void {\r\n this.xAxisProperties = xProperties;\r\n }\r\n\r\n public render(suppressAnimations: boolean, resizeMode?: ResizeMode): CartesianVisualRenderResult {\r\n if (!this.data)\r\n return;\r\n\r\n let data = this.data;\r\n\r\n let margin = this.margin;\r\n let viewport = this.currentViewport;\r\n\r\n let hasSelection = this.interactivityService && this.interactivityService.hasSelection();\r\n\r\n let plotArea: IViewport = {\r\n width: viewport.width - (margin.left + margin.right),\r\n height: viewport.height - (margin.top + margin.bottom)\r\n };\r\n\r\n let duration = AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n if (this.playAxis && this.playAxis.isCurrentlyPlaying() && (this.isMobileChart || duration > 0)) {\r\n duration = PlayChart.FrameAnimationDuration;\r\n }\r\n\r\n let easeType = this.playAxis ? 'linear' : 'cubic-in-out'; // cubic-in-out is the d3.ease default\r\n let fillMarkers = (!data.sizeRange || !data.sizeRange.min) && data.fillPoint;\r\n let drawBubbles = this.hasSizeMeasure();\r\n let suppressDataPointRendering = resizeMode === ResizeMode.Resizing && data.dataPoints && data.dataPoints.length > ScatterChart.NoRenderResizeThreshold;\r\n\r\n let viewModel: ScatterChartViewModel = {\r\n data: data,\r\n drawBubbles: drawBubbles,\r\n isPlay: !!this.playAxis,\r\n xAxisProperties: this.xAxisProperties,\r\n yAxisProperties: this.yAxisProperties,\r\n viewport: plotArea,\r\n hasSelection: hasSelection,\r\n animationDuration: duration,\r\n animationOptions: this.options.animation,\r\n fillMarkers: fillMarkers,\r\n easeType: easeType,\r\n suppressDataPointRendering: suppressDataPointRendering,\r\n };\r\n\r\n if (drawBubbles) {\r\n // Bubbles must be drawn from largest to smallest.\r\n let sortedData = data.dataPoints.sort(ScatterChart.sortBubbles);\r\n viewModel.data = Prototype.inherit(viewModel.data);\r\n viewModel.data.dataPoints = sortedData;\r\n }\r\n\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n if (data.dataLabelsSettings && data.dataLabelsSettings.show || data.dataLabelsSettings.showCategory) {\r\n labelDataPoints = ScatterChartDataLabels.createLabelDataPoints(viewModel);\r\n }\r\n\r\n let behaviorOptions = this.renderer.render(viewModel, this.interactivityService);\r\n\r\n if (this.isMobileChart) {\r\n behaviorOptions = <ScatterMobileBehaviorOptions> {\r\n data: behaviorOptions.data,\r\n dataPointsSelection: behaviorOptions.dataPointsSelection,\r\n eventGroup: behaviorOptions.eventGroup,\r\n plotContext: behaviorOptions.plotContext,\r\n host: this.cartesianVisualHost,\r\n root: this.svg,\r\n visualInitOptions: this.options,\r\n xAxisProperties: this.xAxisProperties,\r\n yAxisProperties: this.yAxisProperties,\r\n background: d3.select(this.element.get(0)),\r\n };\r\n }\r\n\r\n let playRenderResult: PlayChartRenderResult<ScatterChartData, ScatterChartViewModel>;\r\n if (this.playAxis) {\r\n playRenderResult = this.playAxis.render(suppressAnimations, viewModel, viewport, margin);\r\n\r\n if (this.interactivityService) {\r\n let playBehaviorOptions: PlayBehaviorOptions = {\r\n traceLineRenderer: this.renderer.createTraceLineRenderer(playRenderResult.viewModel),\r\n };\r\n\r\n if (hasSelection) {\r\n PlayChart.renderTraceLines(playRenderResult.allDataPoints, playBehaviorOptions.traceLineRenderer, !suppressAnimations);\r\n }\r\n\r\n behaviorOptions.playOptions = playBehaviorOptions;\r\n }\r\n }\r\n\r\n return {\r\n dataPoints: playRenderResult ? playRenderResult.allDataPoints : data.dataPoints,\r\n behaviorOptions: behaviorOptions,\r\n labelDataPoints: labelDataPoints,\r\n labelsAreNumeric: false,\r\n };\r\n }\r\n\r\n public static getStrokeFill(d: ScatterChartDataPoint, colorBorder: boolean): string {\r\n if (d.size != null && colorBorder) {\r\n let colorRgb = Color.parseColorString(d.fill);\r\n return Color.hexString(Color.darken(colorRgb, ScatterChart.StrokeDarkenColorValue));\r\n }\r\n return d.fill;\r\n }\r\n\r\n public static getBubblePixelAreaSizeRange(viewPort: IViewport, minSizeRange: number, maxSizeRange: number): DataRange {\r\n let ratio = 1.0;\r\n if (viewPort.height > 0 && viewPort.width > 0) {\r\n let minSize = Math.min(viewPort.height, viewPort.width);\r\n ratio = (minSize * minSize) / ScatterChart.AreaOf300By300Chart;\r\n }\r\n\r\n let minRange = Math.round(minSizeRange * ratio);\r\n let maxRange = Math.round(maxSizeRange * ratio);\r\n return {\r\n minRange: minRange,\r\n maxRange: maxRange,\r\n delta: maxRange - minRange\r\n };\r\n }\r\n\r\n public static project(value: number, actualSizeDataRange: DataRange, bubblePixelAreaSizeRange: DataRange): number {\r\n if (actualSizeDataRange.delta === 0 || bubblePixelAreaSizeRange.delta === 0) {\r\n return (ScatterChart.rangeContains(actualSizeDataRange, value)) ? bubblePixelAreaSizeRange.minRange : null;\r\n }\r\n\r\n let relativeX = (value - actualSizeDataRange.minRange) / actualSizeDataRange.delta;\r\n return bubblePixelAreaSizeRange.minRange + relativeX * bubblePixelAreaSizeRange.delta;\r\n }\r\n\r\n public static projectSizeToPixels(size: number, actualSizeDataRange: DataRange, bubblePixelAreaSizeRange: DataRange): number {\r\n let projectedSize = 0;\r\n if (actualSizeDataRange) {\r\n // Project value on the required range of bubble area sizes\r\n projectedSize = bubblePixelAreaSizeRange.maxRange;\r\n if (actualSizeDataRange.delta !== 0) {\r\n let value = Math.min(Math.max(size, actualSizeDataRange.minRange), actualSizeDataRange.maxRange);\r\n projectedSize = ScatterChart.project(value, actualSizeDataRange, bubblePixelAreaSizeRange);\r\n }\r\n\r\n projectedSize = Math.sqrt(projectedSize / Math.PI) * 2;\r\n }\r\n\r\n return Math.round(projectedSize);\r\n }\r\n\r\n public static rangeContains(range: DataRange, value: number): boolean {\r\n return range.minRange <= value && value <= range.maxRange;\r\n }\r\n\r\n public static getMarkerFillOpacity(hasSize: boolean, shouldEnableFill: boolean, hasSelection: boolean, isSelected: boolean): number {\r\n if (hasSize || shouldEnableFill) {\r\n if (hasSelection && !isSelected) {\r\n return ScatterChart.DimmedBubbleOpacity;\r\n }\r\n return ScatterChart.DefaultBubbleOpacity;\r\n } else {\r\n return 0;\r\n }\r\n }\r\n\r\n public static getMarkerStrokeOpacity(hasSize: boolean, colorBorder: boolean, hasSelection: boolean, isSelected: boolean): number {\r\n if (hasSize && colorBorder) {\r\n return 1;\r\n } else {\r\n if (hasSelection && !isSelected) {\r\n return ScatterChart.DimmedBubbleOpacity;\r\n }\r\n return ScatterChart.DefaultBubbleOpacity;\r\n }\r\n }\r\n\r\n public static getMarkerStrokeFill(hasSize: boolean, colorBorder: boolean, fill: string): string {\r\n if (hasSize && colorBorder) {\r\n let colorRgb = Color.parseColorString(fill);\r\n return Color.hexString(Color.darken(colorRgb, ScatterChart.StrokeDarkenColorValue));\r\n }\r\n return fill;\r\n }\r\n\r\n public static getMarkerStyle(d: ScatterChartDataPoint, colorBorder: boolean, hasSelection: boolean, fillMarkers: boolean): ScatterMarkerStyle {\r\n return {\r\n 'stroke-opacity': ScatterChart.getMarkerStrokeOpacity(d.size != null, colorBorder, hasSelection, d.selected),\r\n stroke: ScatterChart.getMarkerStrokeFill(d.size != null, colorBorder, d.fill),\r\n fill: d.fill,\r\n 'fill-opacity': ScatterChart.getMarkerFillOpacity(d.size != null, fillMarkers, hasSelection, d.selected),\r\n };\r\n }\r\n\r\n public static getSeriesStyle(hasSize: boolean, colorBorder: boolean, hasSelection: boolean, fillMarkers: boolean, fill: string): ScatterMarkerStyle {\r\n return {\r\n 'stroke-opacity': ScatterChart.getMarkerStrokeOpacity(hasSize, colorBorder, hasSelection, false),\r\n stroke: ScatterChart.getMarkerStrokeFill(hasSize, colorBorder, fill),\r\n fill: fill,\r\n 'fill-opacity': ScatterChart.getMarkerFillOpacity(hasSize, fillMarkers, hasSelection, false),\r\n };\r\n }\r\n\r\n public static getBubbleOpacity(d: ScatterChartDataPoint, hasSelection: boolean): number {\r\n if (hasSelection && !d.selected) {\r\n return ScatterChart.DimmedBubbleOpacity;\r\n }\r\n return ScatterChart.DefaultBubbleOpacity;\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService)\r\n this.interactivityService.clearSelection();\r\n }\r\n\r\n public getSupportedCategoryAxisType(): string {\r\n return axisType.scalar;\r\n }\r\n\r\n public static sortBubbles(a: ScatterChartDataPoint, b: ScatterChartDataPoint): number {\r\n let diff = (b.radius.sizeMeasure.values[b.radius.index] - a.radius.sizeMeasure.values[a.radius.index]);\r\n if (diff !== 0)\r\n return diff;\r\n\r\n // Tie-break equal size bubbles using identity.\r\n return b.identity.getKey().localeCompare(a.identity.getKey());\r\n }\r\n }\r\n\r\n class SvgRenderer {\r\n private static DotClass: ClassAndSelector = createClassAndSelector('dot');\r\n private static MainGraphicsContext = createClassAndSelector('mainGraphicsContext');\r\n private static ScatterMarkerSeriesGroup = createClassAndSelector('scatterMarkerSeriesGroup');\r\n\r\n private mainGraphicsContext: D3.Selection;\r\n private mainGraphicsG: D3.Selection;\r\n private mainGraphicsBackgroundRect: D3.Selection;\r\n private labelGraphicsContext: D3.Selection;\r\n private isMobileChart: boolean;\r\n private tooltipsEnabled: boolean;\r\n\r\n public init(element: D3.Selection, labelsContext: D3.Selection, isMobileChart: boolean, tooltipsEnabled: boolean): void {\r\n this.mainGraphicsG = element.append('g')\r\n .classed(SvgRenderer.MainGraphicsContext.class, true);\r\n\r\n this.isMobileChart = isMobileChart;\r\n if (isMobileChart) {\r\n // The backgroundRect catch user interactions when clicking/dragging on the background of the chart.\r\n this.mainGraphicsBackgroundRect = this.mainGraphicsG\r\n .append(\"rect\")\r\n .classed(\"backgroundRect\", true)\r\n .attr({ width: \"100%\", height: \"100%\" });\r\n }\r\n\r\n this.mainGraphicsContext = this.mainGraphicsG.append('svg');\r\n this.labelGraphicsContext = labelsContext;\r\n this.tooltipsEnabled = tooltipsEnabled;\r\n\r\n // common rendering attributes\r\n this.mainGraphicsContext.attr('stroke-width', \"1\");\r\n }\r\n\r\n public render(viewModel: ScatterChartViewModel, interactivityService: IInteractivityService): ScatterBehaviorOptions {\r\n let viewport = viewModel.viewport;\r\n\r\n this.mainGraphicsContext\r\n .attr({\r\n 'width': viewport.width,\r\n 'height': viewport.height\r\n });\r\n\r\n let scatterMarkers: D3.Selection;\r\n if (viewModel.suppressDataPointRendering) {\r\n scatterMarkers = this.removeScatterMarkers();\r\n }\r\n else if (viewModel.animationDuration > 0 && viewModel.data.dataPoints.length <= ScatterChart.NoAnimationThreshold) {\r\n scatterMarkers = this.drawScatterMarkers(viewModel);\r\n }\r\n else {\r\n scatterMarkers = this.drawScatterMarkersNoAnimation(viewModel, viewModel.drawBubbles);\r\n }\r\n\r\n if (viewModel.drawBubbles)\r\n scatterMarkers.order();\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(this.mainGraphicsContext, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n }\r\n SVGUtil.flushAllD3TransitionsIfNeeded(viewModel.animationOptions);\r\n\r\n return <ScatterBehaviorOptions> {\r\n dataPointsSelection: scatterMarkers,\r\n eventGroup: this.mainGraphicsG,\r\n data: viewModel.data,\r\n plotContext: this.mainGraphicsContext,\r\n };\r\n }\r\n\r\n public createTraceLineRenderer(viewModel: PlayChartViewModel<ScatterChartData, ScatterChartViewModel>): ScatterTraceLineRenderer {\r\n return new ScatterTraceLineRenderer(viewModel, this.mainGraphicsContext, this.tooltipsEnabled);\r\n }\r\n\r\n private removeScatterMarkers(): D3.Selection {\r\n this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector)\r\n .remove();\r\n\r\n return this.mainGraphicsContext.selectAll(SvgRenderer.DotClass.selector);\r\n }\r\n\r\n private drawScatterMarkers(viewModel: ScatterChartViewModel): D3.UpdateSelection {\r\n let data = viewModel.data;\r\n let xScale = viewModel.xAxisProperties.scale;\r\n let yScale = viewModel.yAxisProperties.scale;\r\n\r\n // put all the markers in a single fake group. keeps the dom structure consistent between\r\n // drawScatterMarkers and drawScatterMarkersGrouped.\r\n let fakeDataPointSeries: ScatterChartDataPointSeries[] = [\r\n {\r\n identityKey: \"\",\r\n dataPoints: data.dataPoints,\r\n },\r\n ];\r\n\r\n let fakeSeriesGroups = this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector)\r\n .data(fakeDataPointSeries, (s: ScatterChartDataPointSeries) => s.identityKey);\r\n\r\n fakeSeriesGroups.enter()\r\n .append('g')\r\n .classed(SvgRenderer.ScatterMarkerSeriesGroup.class, true);\r\n\r\n // groups for real series may have been inserted by drawScatterMarkersGrouped, remove them\r\n fakeSeriesGroups.exit()\r\n .remove();\r\n\r\n let markers = fakeSeriesGroups.selectAll(SvgRenderer.DotClass.selector)\r\n .data((s: ScatterChartDataPointSeries) => s.dataPoints, (d: ScatterChartDataPoint) => d.identity.getKey());\r\n\r\n markers.enter().append('circle')\r\n .classed(SvgRenderer.DotClass.class, true)\r\n .style('opacity', 0) // Fade new bubbles into visibility\r\n .attr('r', 0);\r\n\r\n markers\r\n .style({\r\n 'stroke-opacity': (d: ScatterChartDataPoint) => ScatterChart.getMarkerStrokeOpacity(d.size != null, data.colorBorder, viewModel.hasSelection, d.selected),\r\n 'stroke': (d: ScatterChartDataPoint) => ScatterChart.getStrokeFill(d, data.colorBorder),\r\n 'fill': (d: ScatterChartDataPoint) => d.fill,\r\n 'fill-opacity': (d: ScatterChartDataPoint) => ScatterChart.getMarkerFillOpacity(d.size != null, viewModel.fillMarkers, viewModel.hasSelection, d.selected),\r\n })\r\n .transition()\r\n .ease(viewModel.easeType)\r\n .duration(viewModel.animationDuration)\r\n .style('opacity', 1) // Fill-opacity is used for selected / highlight changes, opacity is for enter/exit fadein/fadeout\r\n .attr({\r\n r: (d: ScatterChartDataPoint) => ScatterChart.getBubbleRadius(d.radius, data.sizeRange, viewModel.viewport),\r\n cx: d => xScale(d.x),\r\n cy: d => yScale(d.y),\r\n });\r\n\r\n markers\r\n .exit()\r\n .transition()\r\n .ease(viewModel.easeType)\r\n .duration(viewModel.animationDuration)\r\n .style('opacity', 0) // Fade out bubbles that are removed\r\n .attr('r', 0)\r\n .remove();\r\n\r\n return markers;\r\n }\r\n\r\n private drawScatterMarkersNoAnimation(viewModel: ScatterChartViewModel, isBubble: boolean): D3.Selection {\r\n let data = viewModel.data;\r\n let xScale = viewModel.xAxisProperties.scale;\r\n let yScale = viewModel.yAxisProperties.scale;\r\n\r\n let seriesGroups: D3.UpdateSelection;\r\n if (isBubble) {\r\n let fakeDataPointSeries: ScatterChartDataPointSeries[] = [\r\n {\r\n identityKey: \"\",\r\n dataPoints: data.dataPoints,\r\n },\r\n ];\r\n\r\n seriesGroups = this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector)\r\n .data(fakeDataPointSeries, (s: ScatterChartDataPointSeries) => s.identityKey);\r\n }\r\n else {\r\n seriesGroups = this.mainGraphicsContext.selectAll(SvgRenderer.ScatterMarkerSeriesGroup.selector).data(data.dataPointSeries, (s: ScatterChartDataPointSeries) => s.identityKey);\r\n }\r\n\r\n // a group for each series\r\n seriesGroups.enter()\r\n .append('g')\r\n .classed(SvgRenderer.ScatterMarkerSeriesGroup.class, true);\r\n\r\n // this will also remove the fake group that might have been created by drawScatterMarkers\r\n seriesGroups.exit()\r\n .remove();\r\n\r\n seriesGroups\r\n .each(function (s: ScatterChartDataPointSeries): void {\r\n let seriesStyle: ScatterMarkerStyle = ScatterChart.getSeriesStyle(s.hasSize, data.colorBorder, viewModel.hasSelection, viewModel.fillMarkers, s.fill);\r\n\r\n let g = d3.select(<EventTarget>this);\r\n SvgRenderer.applyStyle(this, seriesStyle);\r\n\r\n let markers = g.selectAll(SvgRenderer.DotClass.selector).data(s.dataPoints, (m: ScatterChartDataPoint) => m.identity.getKey());\r\n\r\n markers.enter()\r\n .append('circle')\r\n .classed(SvgRenderer.DotClass.class, true);\r\n\r\n markers.exit()\r\n .remove();\r\n\r\n markers.each(function (d: ScatterChartDataPoint) {\r\n let style = ScatterChart.getMarkerStyle(d, data.colorBorder, viewModel.hasSelection, viewModel.fillMarkers);\r\n SvgRenderer.styleException(style, seriesStyle);\r\n SvgRenderer.applyStyle(this, style);\r\n });\r\n\r\n markers.attr({\r\n r: (d: ScatterChartDataPoint) => ScatterChart.getBubbleRadius(d.radius, data.sizeRange, viewModel.viewport),\r\n cx: d => xScale(d.x),\r\n cy: d => yScale(d.y),\r\n });\r\n });\r\n\r\n return this.mainGraphicsContext.selectAll(SvgRenderer.DotClass.selector);\r\n }\r\n\r\n private static styleException(elementStyle: ScatterMarkerStyle, seriesStyle: ScatterMarkerStyle): void {\r\n if (seriesStyle) {\r\n for (let name in elementStyle) {\r\n if (elementStyle[name] === seriesStyle[name]) {\r\n elementStyle[name] = null;\r\n }\r\n }\r\n }\r\n }\r\n\r\n private static applyStyle(element: SVGStylable, style: ScatterMarkerStyle): void {\r\n for (let name in style) {\r\n let elementValue = element.style[name];\r\n let styleValue = style[name];\r\n if (styleValue == null) {\r\n if (elementValue === \"\")\r\n continue;\r\n } else {\r\n styleValue = styleValue.toString();\r\n if (styleValue === elementValue)\r\n continue;\r\n }\r\n\r\n element.style[name] = styleValue;\r\n }\r\n }\r\n }\r\n\r\n module ScatterChartDataLabels {\r\n let validLabelPositions = [\r\n NewPointLabelPosition.Below,\r\n NewPointLabelPosition.Above,\r\n NewPointLabelPosition.Right,\r\n NewPointLabelPosition.Left,\r\n NewPointLabelPosition.BelowRight,\r\n NewPointLabelPosition.BelowLeft,\r\n NewPointLabelPosition.AboveRight,\r\n NewPointLabelPosition.AboveLeft\r\n ];\r\n\r\n /*\r\n * Represents standard Cartesian quadrant numbering:\r\n * 2 1\r\n * 3 4\r\n */\r\n export const enum QuadrantNumber {\r\n First,\r\n Second,\r\n Third,\r\n Fourth\r\n }\r\n\r\n export function createLabelDataPoints(viewModel: ScatterChartViewModel): LabelDataPoint[] {\r\n let xScale = viewModel.xAxisProperties.scale;\r\n let yScale = viewModel.yAxisProperties.scale;\r\n let sizeRange = viewModel.data.sizeRange;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n let dataPoints = viewModel.data.dataPoints;\r\n let labelSettings = viewModel.data.dataLabelsSettings;\r\n let preferredLabelsKeys = getPreferredLabelsKeys(viewModel);\r\n\r\n for (let dataPoint of dataPoints) {\r\n let text = dataPoint.formattedCategory.getValue();\r\n\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties);\r\n\r\n labelDataPoints.push({\r\n isPreferred: preferredLabelsKeys ? isLabelPreferred(dataPoint.identity.getKey(), preferredLabelsKeys) : false,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : NewDataLabelUtils.defaultLabelColor,\r\n insideFill: NewDataLabelUtils.defaultInsideLabelColor,\r\n parentType: LabelDataPointParentType.Point,\r\n parentShape: {\r\n point: {\r\n x: xScale(dataPoint.x),\r\n y: yScale(dataPoint.y),\r\n },\r\n radius: ScatterChart.getBubbleRadius(dataPoint.radius, sizeRange, viewModel.viewport),\r\n validPositions: validLabelPositions,\r\n },\r\n identity: dataPoint.identity,\r\n fontSize: labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt,\r\n });\r\n }\r\n\r\n return labelDataPoints;\r\n }\r\n\r\n function getPreferredLabelsKeys(viewModel: ScatterChartViewModel): string[] {\r\n let width = viewModel.viewport.width;\r\n let height = viewModel.viewport.height;\r\n\r\n let visualCenter = new Point(width / 2, height / 2);\r\n let quadrantsCenters: Point[] = getQuadrantsCenters(width, height);\r\n\r\n return getCandidateLabels(visualCenter, quadrantsCenters, viewModel);\r\n }\r\n\r\n function getQuadrantsCenters(visualWidth: number, visualHeight: number): Point[] {\r\n let quadrantsCenters: Point[] = [];\r\n let quarterWidth = visualWidth / 4;\r\n let quarterHeight = visualHeight / 4;\r\n\r\n quadrantsCenters.push(new Point(quarterWidth, quarterHeight));\r\n quadrantsCenters.push(new Point(quarterWidth * 3, quarterHeight));\r\n quadrantsCenters.push(new Point(quarterWidth, quarterHeight * 3));\r\n quadrantsCenters.push(new Point(quarterWidth * 3, quarterHeight * 3));\r\n\r\n return quadrantsCenters;\r\n }\r\n\r\n function getCandidateLabels(\r\n visualCenter: Point,\r\n quadrantsCenters: Point[],\r\n viewModel: ScatterChartViewModel): string[] {\r\n let minDistances: number[] = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE];\r\n let ids: SelectionId[] = [];\r\n\r\n let xScale = viewModel.xAxisProperties.scale;\r\n let yScale = viewModel.yAxisProperties.scale;\r\n\r\n let distance: number;\r\n\r\n for (let dp of viewModel.data.dataPoints) {\r\n let x = xScale(dp.x);\r\n let y = yScale(dp.y);\r\n let quadrantNumber = getPointQuadrantNumber(x, y, visualCenter);\r\n if (viewModel.drawBubbles) {\r\n // Since the array is sorted by size the preferred label will be the first label in the quadrant\r\n if (!ids[quadrantNumber])\r\n ids[quadrantNumber] = dp.identity;\r\n }\r\n else {\r\n distance = getDistanceBetweenPoints(quadrantsCenters[quadrantNumber].x, quadrantsCenters[quadrantNumber].y, x, y);\r\n if (distance < minDistances[quadrantNumber]) {\r\n ids[quadrantNumber] = dp.identity;\r\n minDistances[quadrantNumber] = distance;\r\n }\r\n }\r\n\r\n }\r\n\r\n let preferredLabelsKeys: string[] = [];\r\n for (let id of ids) {\r\n if (id)\r\n preferredLabelsKeys.push(id.getKey());\r\n }\r\n\r\n return preferredLabelsKeys;\r\n }\r\n\r\n function getPointQuadrantNumber(x: number, y: number, centerPoint: Point): number {\r\n if (x > centerPoint.x && y <= centerPoint.y)\r\n return QuadrantNumber.First;\r\n if (x <= centerPoint.x && y <= centerPoint.y)\r\n return QuadrantNumber.Second;\r\n if (x <= centerPoint.x && y > centerPoint.y)\r\n return QuadrantNumber.Third;\r\n else\r\n return QuadrantNumber.Fourth;\r\n }\r\n\r\n function getDistanceBetweenPoints(x1: number, y1: number, x2: number, y2: number): number {\r\n return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));\r\n }\r\n\r\n function isLabelPreferred(key: string, preferredLabelsKeys: string[]) {\r\n for (let preferredLabel of preferredLabelsKeys) {\r\n if (key.localeCompare(preferredLabel) === 0)\r\n return true;\r\n }\r\n return false;\r\n }\r\n }\r\n\r\n class ScatterTraceLineRenderer implements ITraceLineRenderer {\r\n private static TraceLine: ClassAndSelector = createClassAndSelector('traceLine');\r\n private static TraceBubble: ClassAndSelector = createClassAndSelector('traceBubble');\r\n\r\n private viewModel: PlayChartViewModel<ScatterChartData, ScatterChartViewModel>;\r\n private element: D3.Selection;\r\n private tooltipsEnabled: boolean;\r\n\r\n constructor(viewModel: PlayChartViewModel<ScatterChartData, ScatterChartViewModel>, element: D3.Selection, tooltipsEnabled: boolean) {\r\n this.viewModel = viewModel;\r\n this.element = element;\r\n this.tooltipsEnabled = tooltipsEnabled;\r\n }\r\n\r\n public remove() {\r\n this.element.selectAll(ScatterTraceLineRenderer.TraceLine.selector).remove();\r\n this.element.selectAll(ScatterTraceLineRenderer.TraceBubble.selector).remove();\r\n }\r\n\r\n public render(selectedPoints: SelectableDataPoint[], shouldAnimate: boolean): void {\r\n let viewModel = this.viewModel;\r\n let scatterViewModel = viewModel.viewModel;\r\n let seriesPoints: ScatterChartDataPoint[][] = [];\r\n\r\n if (!_.isEmpty(selectedPoints) && !scatterViewModel.suppressDataPointRendering) {\r\n let currentFrameIndex = viewModel.data.currentFrameIndex;\r\n\r\n // filter to the selected identity, only up to and including the current frame. Add frames during play.\r\n let hasBubbleAtCurrentFrame: boolean[] = [];\r\n for (var selectedIndex = 0, selectedLen = selectedPoints.length; selectedIndex < selectedLen; selectedIndex++) {\r\n seriesPoints[selectedIndex] = [];\r\n hasBubbleAtCurrentFrame[selectedIndex] = false;\r\n for (let frameIndex = 0, frameLen = viewModel.data.allViewModels.length; frameIndex < frameLen && frameIndex <= currentFrameIndex; frameIndex++) {\r\n let value = _.find(viewModel.data.allViewModels[frameIndex].dataPoints, (value, index) => {\r\n return value.identity.getKey() === selectedPoints[selectedIndex].identity.getKey();\r\n });\r\n\r\n if (value != null) {\r\n // TODO: Revisit this, we should be able to keep track without modifying Scatter's data points.\r\n (<PlayChartDataPoint>value).frameIndex = frameIndex;\r\n seriesPoints[selectedIndex].push(value);\r\n if (frameIndex === currentFrameIndex)\r\n hasBubbleAtCurrentFrame[selectedIndex] = true;\r\n }\r\n }\r\n }\r\n\r\n let xScale = scatterViewModel.xAxisProperties.scale;\r\n let yScale = scatterViewModel.yAxisProperties.scale;\r\n\r\n let line = d3.svg.line()\r\n .x((d: ScatterChartDataPoint) => xScale(d.x))\r\n .y((d: ScatterChartDataPoint) => yScale(d.y))\r\n .defined((d: ScatterChartDataPoint) => d.x !== null && d.y !== null);\r\n\r\n // Render Lines\r\n let traceLines = this.element.selectAll(ScatterTraceLineRenderer.TraceLine.selector)\r\n .data(selectedPoints, (sp: ScatterChartDataPoint) => sp.identity.getKey());\r\n\r\n traceLines.enter()\r\n .append('path')\r\n .classed(ScatterTraceLineRenderer.TraceLine.class, true);\r\n\r\n // prepare array of new/previous lengths\r\n // NOTE: can't use lambda because we need the \"this\" context to be the DOM Element associated with the .each()\r\n let previousLengths: number[] = [], newLengths: number[] = [];\r\n let reverse = false;\r\n traceLines.each(function (d, i) {\r\n let existingPath = (<SVGPathElement>this);\r\n let previousLength = existingPath.hasAttribute('d') ? existingPath.getTotalLength() : 0;\r\n previousLengths.push(previousLength);\r\n // create offline SVG for new path measurement\r\n let tempSvgPath = $('<svg><path></path></svg>');\r\n let tempPath = $('path', tempSvgPath);\r\n tempPath.attr('d', line(seriesPoints[i]));\r\n let newLength = seriesPoints[i].length > 0 ? (<SVGPathElement>tempPath.get()[0]).getTotalLength() : 0;\r\n newLengths.push(newLength);\r\n\r\n reverse = reverse || (newLength < previousLength);\r\n });\r\n\r\n // animate using stroke-dash* trick\r\n if (!reverse) {\r\n // growing line\r\n traceLines\r\n .style('stroke', (d: ScatterChartDataPoint) => ScatterChart.getStrokeFill(d, true))\r\n .attr({\r\n 'd': (d, i: number) => {\r\n return line(seriesPoints[i]);\r\n },\r\n 'stroke-dasharray': (d, i) => newLengths[i] + \" \" + newLengths[i],\r\n 'stroke-dashoffset': (d, i) => newLengths[i] - previousLengths[i],\r\n });\r\n if (shouldAnimate) {\r\n traceLines\r\n .transition()\r\n .ease('linear')\r\n .duration(PlayChart.FrameAnimationDuration)\r\n .attr('stroke-dashoffset', 0);\r\n }\r\n else {\r\n traceLines.attr('stroke-dashoffset', 0);\r\n }\r\n }\r\n else {\r\n // shrinking line\r\n if (shouldAnimate) {\r\n traceLines\r\n .transition()\r\n .ease('linear')\r\n .duration(PlayChart.FrameAnimationDuration)\r\n .attr('stroke-dashoffset', (d, i) => previousLengths[i] - newLengths[i])\r\n .transition()\r\n .ease('linear')\r\n .duration(1) // animate the shrink first, then update with new line properties\r\n .delay(PlayChart.FrameAnimationDuration)\r\n .style('stroke', (d: ScatterChartDataPoint) => ScatterChart.getStrokeFill(d, true))\r\n .attr({\r\n 'd': (d, i) => {\r\n return line(seriesPoints[i]);\r\n },\r\n 'stroke-dasharray': (d, i) => newLengths[i] + \" \" + newLengths[i],\r\n 'stroke-dashoffset': 0,\r\n });\r\n }\r\n else {\r\n traceLines\r\n .style('stroke', (d: ScatterChartDataPoint) => ScatterChart.getStrokeFill(d, true))\r\n .attr({\r\n 'd': (d, i) => {\r\n return line(seriesPoints[i]);\r\n },\r\n 'stroke-dasharray': (d, i) => newLengths[i] + \" \" + newLengths[i],\r\n 'stroke-dashoffset': 0,\r\n });\r\n }\r\n }\r\n\r\n traceLines.exit()\r\n .remove();\r\n\r\n // Render circles\r\n let circlePoints: ScatterChartDataPoint[] = [];\r\n for (let selectedIndex = 0; selectedIndex < seriesPoints.length; selectedIndex++) {\r\n let points = seriesPoints[selectedIndex];\r\n\r\n // slice to length-1 because we draw lines to the current bubble but we don't need to draw the current frame's bubble\r\n let newPoints = hasBubbleAtCurrentFrame[selectedIndex] ? points.slice(0, points.length - 1) : points;\r\n\r\n circlePoints = circlePoints.concat(newPoints);\r\n }\r\n\r\n let circles = this.element.selectAll(ScatterTraceLineRenderer.TraceBubble.selector)\r\n .data(circlePoints, (d: ScatterChartDataPoint) => d.identity.getKey() + d.x + d.y + d.size);\r\n\r\n circles.enter()\r\n .append('circle')\r\n .style('opacity', 0) //fade new bubbles into visibility\r\n .classed(ScatterTraceLineRenderer.TraceBubble.class, true);\r\n\r\n circles\r\n .attr('cx', (d: ScatterChartDataPoint) => xScale(d.x))\r\n .attr('cy', (d: ScatterChartDataPoint) => yScale(d.y))\r\n .attr('r', (d: ScatterChartDataPoint) => ScatterChart.getBubbleRadius(d.radius, (<ScatterChartData>viewModel.data.currentViewModel).sizeRange, viewModel.viewport))\r\n .style({\r\n 'stroke-opacity': (d: ScatterChartDataPoint) => ScatterChart.getBubbleOpacity(d, true),\r\n 'stroke': (d: ScatterChartDataPoint) => ScatterChart.getStrokeFill(d, viewModel.data.currentViewModel.colorBorder),\r\n 'fill': (d: ScatterChartDataPoint) => d.fill,\r\n // vary the opacity along the traceline from 0.20 to 0.80, with 0.85 left for the circle already drawn by scatterChart\r\n 'fill-opacity': (d: ScatterChartDataPoint) => d.size != null ? 0.20 + ((<PlayChartDataPoint>d).frameIndex / currentFrameIndex) * 0.60 : 0,\r\n })\r\n .transition()\r\n .ease('linear')\r\n .duration(PlayChart.FrameAnimationDuration)\r\n .style('opacity', 1);\r\n\r\n circles.exit()\r\n .transition()\r\n .ease('linear')\r\n .duration(PlayChart.FrameAnimationDuration)\r\n .style('opacity', 0) // fade exiting bubbles out\r\n .remove();\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(circles, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n }\r\n\r\n // sort the z-order, smallest size on top\r\n circles.sort((d1: ScatterChartDataPoint, d2: ScatterChartDataPoint) => { return d2.size - d1.size; });\r\n }\r\n else {\r\n this.remove();\r\n }\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import createDataViewScopeIdentity = powerbi.data.createDataViewScopeIdentity;\r\n import DataViewConcatenateCategoricalColumns = powerbi.data.DataViewConcatenateCategoricalColumns;\r\n import DataViewMatrixUtils = powerbi.data.utils.DataViewMatrixUtils;\r\n import SQExpr = powerbi.data.SQExpr;\r\n import SQExprBuilder = powerbi.data.SQExprBuilder;\r\n\r\n export interface PlayConstructorOptions extends CartesianVisualConstructorOptions {\r\n }\r\n\r\n export interface PlayInitOptions extends CartesianVisualInitOptions {\r\n }\r\n \r\n export interface PlayChartDataPoint {\r\n frameIndex?: number;\r\n };\r\n\r\n export interface PlayChartData<T extends PlayableChartData> {\r\n frameData: PlayChartFrameData[];\r\n allViewModels: T[];\r\n currentViewModel: T;\r\n currentFrameIndex: number;\r\n labelData: PlayAxisTickLabelData;\r\n }\r\n \r\n export interface PlayChartFrameData {\r\n escapedText: string;\r\n text: string;\r\n } \r\n\r\n export interface PlayChartViewModel<TData extends PlayableChartData, TViewModel> {\r\n data: PlayChartData<TData>;\r\n viewModel: TViewModel;\r\n viewport: IViewport;\r\n }\r\n\r\n // TODO: consider a template for the datapoint type <T> instead of any[]\r\n // I tried this an it is quite hard to express correctly with TypeScript.\r\n export interface PlayableChartData {\r\n dataPoints: any[];\r\n }\r\n\r\n interface PlayObjectProperties {\r\n currentFrameIndex?: number;\r\n }\r\n\r\n export interface PlayAxisTickLabelInfo {\r\n label: string;\r\n labelWidth: number;\r\n }\r\n\r\n export interface PlayAxisTickLabelData {\r\n labelInfo: PlayAxisTickLabelInfo[];\r\n anyWordBreaks: boolean;\r\n labelFieldName?: string;\r\n }\r\n\r\n export interface PlayChartRenderResult<TData extends PlayableChartData, TViewModel> {\r\n allDataPoints: SelectableDataPoint[];\r\n viewModel: PlayChartViewModel<TData, TViewModel>;\r\n }\r\n\r\n export interface PlayChartRenderFrameDelegate<T> {\r\n (data: T): void;\r\n }\r\n\r\n export interface PlayFrameInfo {\r\n label: string;\r\n column: DataViewMetadataColumn;\r\n }\r\n\r\n export interface VisualDataConverterDelegate<T> {\r\n (dataView: DataView, playFrameInfo?: PlayFrameInfo): T;\r\n }\r\n\r\n export interface ITraceLineRenderer {\r\n render(selectedPoints: SelectableDataPoint[], shouldAnimate: boolean): void;\r\n remove(): void;\r\n }\r\n \r\n interface SliderSize {\r\n width: number;\r\n marginLeft: number; \r\n };\r\n \r\n interface SliderPipFilter {\r\n skipStep: number;\r\n filter: (index: any, type: any) => number;\r\n }\r\n\r\n export class PlayAxis<T extends PlayableChartData> {\r\n private element: JQuery;\r\n private svg: D3.Selection;\r\n\r\n private playData: PlayChartData<T>;\r\n private renderDelegate: PlayChartRenderFrameDelegate<T>;\r\n private isPlaying: boolean;\r\n private lastViewport: IViewport;\r\n\r\n // do not call converter() when we call persistProperties and a new update() happens\r\n // NOTE: calling persistProperties will still cause a render() call to come from cartesianChart\r\n // TODO: make persist properties only optionally trigger a new onDataChagned, as most charts don't want this (only slicer needs it)\r\n private ridiculousFlagForPersistProperties: boolean;\r\n\r\n private playControl: PlayControl;\r\n\r\n private host: IVisualHostServices;\r\n private interactivityService: IInteractivityService;\r\n private isMobileChart: boolean;\r\n\r\n private static PlayCallout = createClassAndSelector('play-callout');\r\n private static calloutOffsetMultiplier = 0.3;\r\n\r\n constructor(options: PlayConstructorOptions) {\r\n if (options) {\r\n this.interactivityService = options.interactivityService;\r\n }\r\n }\r\n\r\n public init(options: PlayInitOptions) {\r\n debug.assertValue(options, 'options');\r\n\r\n this.element = options.element;\r\n this.svg = options.svg;\r\n this.host = options.host;\r\n\r\n this.isMobileChart = options.interactivity && options.interactivity.isInteractiveLegend;\r\n\r\n if (this.interactivityService) {\r\n this.playControl = new PlayControl(this.element, (frameIndex: number) => this.moveToFrameAndRender(frameIndex), this.isMobileChart);\r\n this.playControl.onPlay(() => this.play());\r\n }\r\n }\r\n\r\n public setData(dataView: DataView, visualConverter: VisualDataConverterDelegate<T>): PlayChartData<T> {\r\n if (dataView) {\r\n if (this.ridiculousFlagForPersistProperties && dataView.metadata) {\r\n // BUG FIX: customer feedback has been strong that we should always default to show the last frame.\r\n // This is essential for dashboard tiles to refresh properly.\r\n\r\n // Only copy frameIndex since it is the only property using persistProperties\r\n //let objectProps = getObjectProperties(dataView.metadata);\r\n //playData.currentFrameIndex = objectProps.currentFrameIndex;\r\n \r\n // Turn off the flag that was set by our persistProperties call\r\n this.ridiculousFlagForPersistProperties = false;\r\n return this.playData;\r\n }\r\n else if (dataView.matrix || dataView.categorical) {\r\n this.playData = PlayChart.converter<T>(dataView, visualConverter);\r\n }\r\n else {\r\n this.playData = PlayChart.getDefaultPlayData<T>();\r\n }\r\n }\r\n else {\r\n this.playData = PlayChart.getDefaultPlayData<T>();\r\n }\r\n\r\n // Next render should be a full one.\r\n this.lastViewport = undefined;\r\n\r\n return this.playData;\r\n }\r\n\r\n public render<TViewModel>(suppressAnimations: boolean, viewModel: TViewModel, viewport: IViewport, margin: IMargin): PlayChartRenderResult<T, TViewModel> {\r\n let playData = this.playData;\r\n\r\n let resized = !this.lastViewport || (this.lastViewport.height !== viewport.height || this.lastViewport.width !== viewport.width);\r\n this.lastViewport = viewport;\r\n\r\n if (resized)\r\n this.stop();\r\n\r\n if (!playData)\r\n return;\r\n\r\n let playViewModel: PlayChartViewModel<T, TViewModel> = {\r\n data: this.playData,\r\n viewModel: viewModel,\r\n viewport: viewport,\r\n };\r\n\r\n let hasSelection = false;\r\n if (this.interactivityService) {\r\n let data = <PlayableChartData>playData.currentViewModel;\r\n this.interactivityService.applySelectionStateToData(data.dataPoints);\r\n hasSelection = this.interactivityService.hasSelection();\r\n }\r\n\r\n this.updateCallout(viewport, margin);\r\n\r\n if (this.playControl && resized) {\r\n this.playControl.rebuild(playData, viewport);\r\n }\r\n\r\n let allDataPoints = playData.allViewModels.map((vm) => vm.dataPoints);\r\n let flatAllDataPoints = _.flatten<SelectableDataPoint>(allDataPoints);\r\n \r\n // NOTE: Return data points to keep track of current selected bubble even if it drops out for a few frames\r\n return {\r\n allDataPoints: flatAllDataPoints,\r\n viewModel: playViewModel,\r\n };\r\n }\r\n\r\n private updateCallout(viewport: IViewport, margin: IMargin): void {\r\n let playData = this.playData;\r\n let frameData = playData.frameData;\r\n let currentFrameIndex = playData.currentFrameIndex;\r\n let height = viewport.height;\r\n let plotAreaHeight = height - margin.top - margin.bottom;\r\n let width = viewport.width;\r\n let plotAreaWidth = width - margin.left - margin.right;\r\n\r\n let calloutDimension = Math.min(height, width * 1.3); //1.3 to compensate for tall, narrow-width viewport\r\n let fontSize = Math.max(12, Math.round(calloutDimension / 7));\r\n fontSize = Math.min(fontSize, 70);\r\n let textProperties = {\r\n fontSize: jsCommon.PixelConverter.toString(fontSize),\r\n text: frameData[currentFrameIndex].text || \"\",\r\n fontFamily: \"wf_segoe-ui_normal\",\r\n };\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(textProperties) - TextMeasurementService.estimateSvgTextBaselineDelta(textProperties);\r\n\r\n let calloutData: string[] = [];\r\n if (currentFrameIndex < frameData.length && currentFrameIndex >= 0 && textHeight < plotAreaHeight) {\r\n let maxTextWidth = plotAreaWidth - (2 * PlayAxis.calloutOffsetMultiplier * textHeight);\r\n let calloutText = TextMeasurementService.getTailoredTextOrDefault(textProperties, maxTextWidth);\r\n calloutData = [calloutText];\r\n }\r\n\r\n let callout = this.svg.selectAll(PlayAxis.PlayCallout.selector).data(calloutData);\r\n\r\n callout.enter()\r\n .append('text')\r\n .classed(PlayAxis.PlayCallout.class, true);\r\n\r\n callout\r\n .text((d: string) => d)\r\n .attr({\r\n x: plotAreaWidth - PlayAxis.calloutOffsetMultiplier * textHeight,\r\n y: () => textHeight,\r\n })\r\n .style({\r\n 'font-size': fontSize + 'px',\r\n 'text-anchor': 'end',\r\n });\r\n\r\n callout.exit().remove();\r\n }\r\n\r\n public play(): void {\r\n let playData = this.playData;\r\n\r\n if (this.isPlaying) {\r\n this.stop();\r\n }\r\n else if (this.playControl) {\r\n this.isPlaying = true;\r\n this.playControl.play();\r\n\r\n let indexToShow = Math.round(this.playControl.getCurrentIndex());\r\n if (indexToShow >= playData.allViewModels.length - 1) {\r\n playData.currentFrameIndex = -1;\r\n } else {\r\n playData.currentFrameIndex = indexToShow - 1;\r\n }\r\n\r\n this.playNextFrame(playData);\r\n }\r\n }\r\n\r\n private playNextFrame(playData: PlayChartData<T>, startFrame?: number, endFrame?: number): void {\r\n if (!this.isPlaying) {\r\n this.stop();\r\n return;\r\n }\r\n\r\n let nextFrame = playData.currentFrameIndex + 1;\r\n if (startFrame != null && endFrame != null) {\r\n nextFrame = Math.abs(endFrame - startFrame + 1);\r\n startFrame = nextFrame;\r\n }\r\n\r\n if (nextFrame < playData.allViewModels.length && nextFrame > -1) {\r\n playData.currentFrameIndex = nextFrame;\r\n playData.currentViewModel = playData.allViewModels[nextFrame];\r\n\r\n this.renderDelegate(playData.currentViewModel);\r\n this.playControl.setFrame(nextFrame);\r\n\r\n if (nextFrame < playData.allViewModels.length) {\r\n window.setTimeout(() => {\r\n this.playNextFrame(playData, startFrame, endFrame);\r\n }, PlayChart.FrameStepDuration);\r\n }\r\n } else {\r\n this.stop();\r\n }\r\n }\r\n\r\n public stop(): void {\r\n if (this.playControl)\r\n this.playControl.pause();\r\n this.isPlaying = false;\r\n }\r\n\r\n public remove(): void {\r\n if (this.playControl)\r\n this.playControl.remove();\r\n d3.selectAll(PlayAxis.PlayCallout.selector).remove();\r\n\r\n // TODO: remove any tracelines\r\n }\r\n\r\n public setRenderFunction(fn: PlayChartRenderFrameDelegate<T>): void {\r\n this.renderDelegate = fn;\r\n }\r\n\r\n public getCartesianExtents(existingExtents: CartesianExtents, getExtents: (T) => CartesianExtents): CartesianExtents {\r\n if (this.playData && this.playData.allViewModels && this.playData.allViewModels.length > 0) {\r\n return PlayChart.getMinMaxForAllFrames(this.playData, getExtents);\r\n }\r\n\r\n return existingExtents;\r\n }\r\n\r\n public setPlayControlPosition(playControlLayout: IRect): void {\r\n if (this.playControl) {\r\n let container = this.playControl.getContainer();\r\n container.css('left', playControlLayout.left ? playControlLayout.left + 'px' : '');\r\n container.css('top', playControlLayout.top ? playControlLayout.top + 'px' : '');\r\n // width is set elsewhere (calculateSliderWidth), where we check for playaxis tick label overflow.\r\n // height is constant\r\n }\r\n }\r\n\r\n private moveToFrameAndRender(frameIndex: number): void {\r\n let playData = this.playData;\r\n\r\n this.isPlaying = false;\r\n\r\n if (playData && frameIndex >= 0 && frameIndex < playData.allViewModels.length && frameIndex !== playData.currentFrameIndex) {\r\n playData.currentFrameIndex = frameIndex;\r\n let data = playData.allViewModels[frameIndex];\r\n playData.currentViewModel = data;\r\n this.renderDelegate(data);\r\n }\r\n }\r\n\r\n public isCurrentlyPlaying(): boolean {\r\n return this.isPlaying;\r\n }\r\n }\r\n\r\n class PlayControl {\r\n private playAxisContainer: JQuery;\r\n private playButton: JQuery;\r\n private playButtonCircle: JQuery;\r\n private slider: JQuery;\r\n private noUiSlider: noUiSlider.noUiSlider;\r\n private renderDelegate: (index: number) => void;\r\n private isMobileChart: boolean;\r\n\r\n private static SliderMarginLeft = 24 + 10 * 2; // playButton width + playButton margin * 2\r\n private static SliderMarginRight = 20;\r\n private static SliderMaxMargin = 100;\r\n private static PlayControlHeight = 80; //tuned for two rows of label text to be perfectly clipped before the third row. Dependent on current font sizes in noui-pips.css\r\n \r\n constructor(element: JQuery, renderDelegate: (index: number) => void, isMobileChart: boolean) {\r\n this.isMobileChart = isMobileChart;\r\n this.createSliderDOM(element);\r\n this.renderDelegate = renderDelegate;\r\n }\r\n\r\n public getContainer(): JQuery {\r\n return this.playAxisContainer;\r\n }\r\n\r\n public remove(): void {\r\n if (this.playAxisContainer)\r\n this.playAxisContainer.remove();\r\n }\r\n\r\n public pause(): void {\r\n this.playButton.removeClass('pause').addClass('play');\r\n }\r\n\r\n public play(): void {\r\n this.playButton.removeClass('play').addClass('pause');\r\n }\r\n\r\n public getCurrentIndex(): number {\r\n // TODO: round() necessary?\r\n return Math.round(<number>this.noUiSlider.get());\r\n }\r\n\r\n public onPlay(handler: (eventObject: JQueryEventObject) => void): void {\r\n this.playButtonCircle.off('click');\r\n this.playButtonCircle.on('click', handler);\r\n }\r\n\r\n public setFrame(frameIndex: number): void {\r\n this.noUiSlider.set([frameIndex]);\r\n };\r\n\r\n public rebuild<T extends PlayableChartData>(playData: PlayChartData<T>, viewport: IViewport): void {\r\n let slider = this.slider;\r\n\r\n // re-create the slider\r\n if (this.noUiSlider)\r\n this.noUiSlider.destroy();\r\n\r\n let labelData = playData.labelData;\r\n let sliderSize: SliderSize = PlayControl.calucalateSliderSize(labelData, viewport.width);\r\n var container = this.getContainer();\r\n if(sliderSize.marginLeft > PlayControl.SliderMarginLeft) {\r\n container.css(\"padding-left\", sliderSize.marginLeft - PlayControl.SliderMarginLeft + \"px\");\r\n container.css(\"box-sizing\", \"border-box\"); \r\n }\r\n let skipStep: number = this.updateSliderControl(playData, sliderSize.width);\r\n let width: number = PlayControl.adjustWidthRegardingLastItem(labelData, skipStep, sliderSize.width);\r\n this.slider.css('width', width + 'px');\r\n\r\n this.noUiSlider.on('slide', () => {\r\n let indexToShow = this.getCurrentIndex();\r\n this.renderDelegate(indexToShow);\r\n });\r\n \r\n let nextLabelIndex = 0;\r\n // update the width and margin-left to center up each label\r\n $('.noUi-value', slider).each((idx, elem) => {\r\n let actualWidth = labelData.labelInfo[nextLabelIndex].labelWidth;\r\n $(elem).width(actualWidth);\r\n $(elem).css('margin-left', -actualWidth / 2 + 'px');\r\n nextLabelIndex += skipStep;\r\n });\r\n }\r\n\r\n /**\r\n * Updates slider control regarding new data.\r\n * @param playData {PlayChartData<T>} Data for the slider.\r\n * @param sliderWidth {number} Slider width. \r\n * @returns {number} skip mode for the slider.\r\n */\r\n private updateSliderControl<T extends PlayableChartData>(playData: PlayChartData<T>, sliderWidth: number): number {\r\n let labelData = playData.labelData;\r\n let sliderElement: HTMLElement = this.slider.get(0);\r\n let numFrames = playData.frameData.length;\r\n let options: noUiSlider.Options = {\r\n start: numFrames === 0 ? 0 : playData.currentFrameIndex,\r\n step: 1,\r\n range: {\r\n min: 0,\r\n max: numFrames === 0 ? 0 : numFrames - 1\r\n }\r\n };\r\n let pipOptions: noUiSlider.PipsOptions = null;\r\n let skipMode: number = 0;\r\n \r\n if (numFrames > 0) {\r\n let filterPipLabels = PlayControl.createPipsFilterFn(playData, sliderWidth, labelData);\r\n skipMode = filterPipLabels.skipStep;\r\n pipOptions = {\r\n mode: 'steps',\r\n density: Math.ceil(100 / numFrames), //only draw ticks where we have labels\r\n format: {\r\n to: (index) => playData.frameData[index].escapedText,\r\n from: (value) => playData.frameData.indexOf(value),\r\n },\r\n filter: filterPipLabels.filter,\r\n };\r\n }\r\n options.pips = pipOptions;\r\n noUiSlider.create(sliderElement, options);\r\n this.noUiSlider = (<noUiSlider.Instance>sliderElement).noUiSlider;\r\n\r\n return skipMode;\r\n }\r\n \r\n private static createPipsFilterFn<T extends PlayableChartData>(playData: PlayChartData<T>, sliderWidth: number, labelData: PlayAxisTickLabelData): SliderPipFilter {\r\n let maxLabelWidth = _.max(_.map(labelData.labelInfo, (l) => l.labelWidth));\r\n\r\n let pipSize = 1; //0=hide, 1=large, 2=small\r\n let skipMode = 1;\r\n let maxAllowedLabelWidth = playData.frameData.length > 1 ? sliderWidth / (playData.frameData.length - 1) : sliderWidth;\r\n let widthRatio = maxLabelWidth / maxAllowedLabelWidth;\r\n\r\n if (widthRatio > 1.25) {\r\n skipMode = Math.ceil(widthRatio);\r\n pipSize = 2;\r\n }\r\n else if (widthRatio > 1.0 || labelData.anyWordBreaks) {\r\n // wordbreak line wrapping is automatic, and we don't reserve enough space to show two lines of text with the larger font\r\n pipSize = 2;\r\n }\r\n\r\n let filterPipLabels = (index: any, type: any) => {\r\n // noUiSlider will word break / wrap to new lines, so max width is the max word length\r\n if (index % skipMode === 0) {\r\n return pipSize;\r\n }\r\n return 0; //hide\r\n };\r\n \r\n\r\n return { filter: filterPipLabels, skipStep: skipMode };\r\n }\r\n\r\n /**\r\n * Adjusts width regarding the last visible label size.\r\n * @param labelData label data for chart.\r\n * @param skipMode skip factor.\r\n * @param sliderWidth current width of slider.\r\n */\r\n private static adjustWidthRegardingLastItem(labelData: PlayAxisTickLabelData, skipMode: number, sliderWidth): number {\r\n let labelLenth: number = labelData.labelInfo.length;\r\n let lastVisibleItemIndex: number = Math.floor((labelLenth - 1) / skipMode) * skipMode;\r\n let distanceToEnd = sliderWidth + PlayControl.SliderMarginRight - (sliderWidth / labelLenth * (lastVisibleItemIndex + 1));\r\n let lastItemWidth = labelData.labelInfo[lastVisibleItemIndex].labelWidth;\r\n let requiredWidth = lastItemWidth / 2 - distanceToEnd;\r\n if (requiredWidth > 0) {\r\n let maxMargin = PlayControl.SliderMaxMargin - PlayControl.SliderMarginRight;\r\n requiredWidth = requiredWidth > maxMargin ? maxMargin : requiredWidth;\r\n return sliderWidth - requiredWidth;\r\n }\r\n\r\n return sliderWidth;\r\n }\r\n\r\n private createSliderDOM(element: JQuery): void {\r\n this.playAxisContainer = $('<div class=\"play-axis-container\"></div>')\r\n .appendTo(element)\r\n .css('height', PlayControl.PlayControlHeight + 'px');\r\n\r\n this.playButtonCircle = $('<div class=\"button-container\"></div>')\r\n .appendTo(this.playAxisContainer);\r\n\r\n if (this.isMobileChart) {\r\n this.playButtonCircle.addClass('mobile-button-container');\r\n }\r\n\r\n this.playButton = $('<div class=\"play\"></div>')\r\n .appendTo(this.playButtonCircle);\r\n\r\n this.slider = $('<div class=\"sliders\"></div>')\r\n .appendTo(this.playAxisContainer);\r\n }\r\n\r\n private static calucalateSliderSize(labelData: PlayAxisTickLabelData, viewportWidth: number): SliderSize {\r\n let leftMargin = 0;\r\n if (!_.isEmpty(labelData.labelInfo)) {\r\n leftMargin = _.first(labelData.labelInfo).labelWidth / 2;\r\n }\r\n\r\n let sliderLeftMargin = Math.max(leftMargin, PlayControl.SliderMarginLeft);\r\n sliderLeftMargin = Math.min(PlayControl.SliderMaxMargin, sliderLeftMargin);\r\n let sliderWidth = Math.max((viewportWidth - sliderLeftMargin - PlayControl.SliderMarginRight), 1);\r\n\r\n return { width: sliderWidth, marginLeft: sliderLeftMargin };\r\n }\r\n }\r\n\r\n export module PlayChart {\r\n // TODO: add speed control to property pane\r\n // NOTE: current noUiSlider speed is a CSS property of the class .noUi-state-tap, and also is hard-coded in noUiSlider.js. We'll need to add a new create param for transition time.\r\n // 800ms matches Silverlight frame speed\r\n export const FrameStepDuration = 800;\r\n export const FrameAnimationDuration = 750; //leave 50ms for the traceline animation - to avoid being cancelled. TODO: add a proper wait impl.\r\n\r\n export const ClassName = 'playChart';\r\n\r\n export function convertMatrixToCategorical(sourceDataView: DataView, frame: number): DataView {\r\n debug.assert(sourceDataView && sourceDataView.metadata && !!sourceDataView.matrix, 'sourceDataView && sourceDataView.metadata && !!sourceDataView.matrix');\r\n\r\n let matrix: DataViewMatrix = sourceDataView.matrix;\r\n\r\n let categorical: DataViewCategorical = {\r\n categories: [],\r\n values: powerbi.data.DataViewTransform.createValueColumns()\r\n };\r\n\r\n // If we don't have enough fields, just return early. We need at least:\r\n // 2 rows and 1 column: (play->category, measures)\r\n // or:\r\n // 1 row and 2 columns: (play, series->measures)\r\n if ((_.isEmpty(matrix.columns.levels)) || (matrix.rows.levels.length < 2 && matrix.columns.levels.length < 2)) {\r\n return { metadata: sourceDataView.metadata, categorical: categorical };\r\n }\r\n\r\n const CategoryRowLevelsStartingIndex = 1;\r\n\r\n let categories: DataViewCategoryColumn[] = [];\r\n // Ignore the play field (first row level); the Category field(s) starts from the second row group (play->category) or we don't use this variable (categories)\r\n // Note related to VSTS 6986788 and 6885783: there are multiple levels for category during drilldown and expand.\r\n for (let i = CategoryRowLevelsStartingIndex, ilen = matrix.rows.levels.length; i < ilen; i++) {\r\n // Consider: Change the following debug.assert() to retail.assert() when the infrastructure is ready.\r\n debug.assert(matrix.rows.levels[i].sources.length > 0, 'The sources is always expected to contain at least one metadata column.');\r\n\r\n let sourceColumn: DataViewMetadataColumn = matrix.rows.levels[i].sources[0];\r\n categories.push({\r\n source: sourceColumn,\r\n values: [],\r\n identity: [],\r\n objects: undefined,\r\n });\r\n }\r\n\r\n // Matrix shape for Play:\r\n //\r\n // Series1 | Series2 | ...\r\n // --------- -------- \r\n // Play1 | Category1 | values | values\r\n // | Category2 | values | values\r\n // | ...\r\n // Play2 | Category1 | values | values\r\n // | Category2 | values | values\r\n // ...\r\n // Or, with drilldown / expand on Category (e.g. expand Country -> Region):\r\n // Series1 | Series2 | ...\r\n // --------- -------- \r\n // Play1 | Country1 | Region1 | values | values\r\n // | | Region2 | values | values\r\n // | Country2 | Region3 | values | values\r\n // | | Region4 | values | values\r\n // | ...\r\n // Play2 | Country1 | Region1 | values | values\r\n // | | Region2 | values | values\r\n // | Country2 | Region3 | values | values\r\n // | | Region4 | values | values\r\n\r\n // we are guaranteed at least one row (it will be the Play field)\r\n let hasRowChildren = !_.isEmpty(matrix.rows.root.children);\r\n let hasColChildren = !_.isEmpty(matrix.columns.root.children);\r\n let hasSeries = matrix.columns.levels.length > 1 && hasColChildren;\r\n let hasPlayAndCategory = matrix.rows.levels.length > 1 && hasRowChildren;\r\n\r\n if (hasSeries && !hasPlayAndCategory) {\r\n // set categories to undefined\r\n categorical.categories = undefined;\r\n\r\n let node = matrix.columns.root;\r\n categorical.values.source = matrix.columns.levels[0].sources[0];\r\n let columnLength = matrix.valueSources.length;\r\n for (let i = 0, len = node.children.length; i < len; i++) {\r\n // add all the value sources for each series\r\n let columnNode = node.children[i];\r\n for (let j = 0; j < columnLength; j++) {\r\n // DEFECT 6547170: groupName must be null to turn into (Blank), undefined will use the field name\r\n let source = <any>_.create(matrix.valueSources[j], { groupName: columnNode.value === undefined ? null : columnNode.value });\r\n let dataViewColumn: DataViewValueColumn = {\r\n identity: columnNode.identity,\r\n values: [],\r\n source: source\r\n };\r\n categorical.values.push(dataViewColumn);\r\n }\r\n }\r\n\r\n // Copying the values from matrix intersection to the categorical values columns...\r\n // Given that this is the case without category levels, the matrix intersection values are stored in playFrameNode.values\r\n let playFrameNode = matrix.rows.root.children[frame];\r\n let matrixIntersectionValues = playFrameNode.values;\r\n for (var i = 0, len = node.children.length; i < len; i++) {\r\n for (let j = 0; j < columnLength; j++) {\r\n categorical.values[i * columnLength + j].values.push(matrixIntersectionValues[i * columnLength + j].value);\r\n }\r\n }\r\n }\r\n else if (hasSeries && hasRowChildren) {\r\n // series and categories\r\n let playFrameNode = matrix.rows.root.children[frame];\r\n \r\n // create the categories first\r\n DataViewMatrixUtils.forEachLeafNode(playFrameNode.children, (categoryGroupLeafNode, index, categoryHierarchicalGroupNodes) => {\r\n addMatrixHierarchicalGroupToCategories(categoryHierarchicalGroupNodes, categories);\r\n });\r\n categorical.categories = categories;\r\n\r\n // now add the series info\r\n categorical.values.source = matrix.columns.levels[0].sources[0];\r\n let nodeQueue = [];\r\n let columnNode = matrix.columns.root;\r\n let seriesIndex = -1;\r\n while (columnNode) {\r\n if (columnNode.children && columnNode.children[0].children) {\r\n for (let j = 0, jlen = columnNode.children.length; j < jlen; j++) {\r\n // each of these is a \"series\"\r\n nodeQueue.push(columnNode.children[j]);\r\n }\r\n } else if (columnNode.children && playFrameNode.children) {\r\n // Processing a single series under here, push all the value sources for every series.\r\n var columnLength = columnNode.children.length;\r\n for (let j = 0; j < columnLength; j++) {\r\n let source = <any>_.create(matrix.valueSources[j], { groupName: columnNode.value });\r\n let dataViewColumn: DataViewValueColumn = {\r\n identity: columnNode.identity,\r\n values: [],\r\n source: source,\r\n };\r\n categorical.values.push(dataViewColumn);\r\n }\r\n\r\n // Copying the values from matrix intersection to the categorical values columns...\r\n DataViewMatrixUtils.forEachLeafNode(playFrameNode.children, leafNode => {\r\n for (let j = 0; j < columnLength; j++) {\r\n categorical.values[seriesIndex * columnLength + j].values.push(leafNode.values[seriesIndex * columnLength + j].value);\r\n }\r\n });\r\n }\r\n\r\n if (nodeQueue.length > 0) {\r\n columnNode = nodeQueue[0];\r\n nodeQueue = nodeQueue.splice(1);\r\n seriesIndex++;\r\n } else\r\n columnNode = undefined;\r\n }\r\n }\r\n else if (hasPlayAndCategory) {\r\n // no series, just play and category\r\n let playFrameNode = matrix.rows.root.children[frame];\r\n let measureLength = matrix.valueSources.length;\r\n for (let j = 0; j < measureLength; j++) {\r\n let dataViewColumn: DataViewValueColumn = {\r\n identity: undefined,\r\n values: [],\r\n source: matrix.valueSources[j]\r\n };\r\n categorical.values.push(dataViewColumn);\r\n }\r\n\r\n DataViewMatrixUtils.forEachLeafNode(playFrameNode.children, (categoryGroupLeafNode, index, categoryHierarchicalGroupNodes) => {\r\n addMatrixHierarchicalGroupToCategories(categoryHierarchicalGroupNodes, categories);\r\n\r\n // Copying the values from matrix intersection to the categorical values columns...\r\n for (let j = 0; j < measureLength; j++) {\r\n categorical.values[j].values.push(categoryGroupLeafNode.values[j].value);\r\n }\r\n });\r\n\r\n categorical.categories = categories;\r\n }\r\n\r\n // the visual code today expects only 1 category column, hence apply DataViewConcatenateCategoricalColumns\r\n return DataViewConcatenateCategoricalColumns.applyToPlayChartCategorical(sourceDataView.metadata, scatterChartCapabilities.objects, 'Category', categorical);\r\n }\r\n\r\n function addMatrixHierarchicalGroupToCategories(sourceCategoryHierarchicalGroupNodes: DataViewMatrixNode[], destinationCategories: DataViewCategoryColumn[]): void {\r\n debug.assertNonEmpty(sourceCategoryHierarchicalGroupNodes, 'sourceCategoryHierarchicalGroupNodes');\r\n debug.assertNonEmpty(destinationCategories, 'destinationCategories');\r\n debug.assert(sourceCategoryHierarchicalGroupNodes.length === destinationCategories.length, 'pre-condition: there should be one category column per matrix row level for Category.');\r\n\r\n // Note: Before the Categorical concatenation logic got added to this playChart logic, the code did NOT populate\r\n // the ***DataViewCategoryColumn.identityFields*** property, and the playChart visual code does not seem to need it.\r\n // If we do want to populate that property, we might want to do reuse data.ISQExpr[] across nodes as much as possible \r\n // because all the child nodes under a given parent will have the exact same identityFields value, and a lot of \r\n // DataViewCategory objects can get created for a given playChart.\r\n\r\n let identity: DataViewScopeIdentity = sourceCategoryHierarchicalGroupNodes[0].identity;\r\n\r\n if (sourceCategoryHierarchicalGroupNodes.length > 1) {\r\n // if the hierarchical group has more than 1 level, create a composite identity from the nodes\r\n let identityExpr = <SQExpr>identity.expr;\r\n for (let i = 1, ilen = sourceCategoryHierarchicalGroupNodes.length; i < ilen; i++) {\r\n let identityExprToAdd = <SQExpr>sourceCategoryHierarchicalGroupNodes[i].identity.expr;\r\n identityExpr = SQExprBuilder.and(identityExpr, identityExprToAdd);\r\n }\r\n identity = createDataViewScopeIdentity(identityExpr);\r\n }\r\n\r\n // add the Category value of each matrix node into its respective category column\r\n for (let j = 0, jlen = destinationCategories.length; j < jlen; j++) {\r\n destinationCategories[j].identity.push(identity);\r\n\r\n let node = sourceCategoryHierarchicalGroupNodes[j];\r\n destinationCategories[j].values.push(node.value);\r\n }\r\n }\r\n\r\n function getObjectProperties(dataViewMetadata: DataViewMetadata, dataLabelsSettings?: PointDataLabelsSettings): PlayObjectProperties {\r\n let objectProperties: PlayObjectProperties = {};\r\n\r\n if (dataViewMetadata && dataViewMetadata.objects) {\r\n let objects = dataViewMetadata.objects;\r\n // TODO: remove?\r\n objectProperties.currentFrameIndex = DataViewObjects.getValue(objects, scatterChartProps.currentFrameIndex.index, null);\r\n }\r\n return objectProperties;\r\n }\r\n\r\n export function converter<T extends PlayableChartData>(dataView: DataView, visualConverter: VisualDataConverterDelegate<T>): PlayChartData<T> {\r\n let dataViewMetadata: DataViewMetadata = dataView.metadata;\r\n let dataLabelsSettings = dataLabelUtils.getDefaultPointLabelSettings();\r\n let objectProperties = getObjectProperties(dataViewMetadata, dataLabelsSettings);\r\n\r\n let allViewModels: T[] = [];\r\n let frameKeys: PlayChartFrameData[] = [];\r\n let convertedData: T = undefined;\r\n let matrixRows = dataView.matrix.rows;\r\n let rowChildrenLength = matrixRows.root.children ? matrixRows.root.children.length : 0;\r\n let keySourceColumn: DataViewMetadataColumn;\r\n if (dataView.matrix && rowChildrenLength > 0 && !_.isEmpty(matrixRows.levels) && !_.isEmpty(matrixRows.levels[0].sources) ) {\r\n keySourceColumn = matrixRows.levels[0].sources[0];\r\n\r\n // TODO: this should probably defer to the visual which knows how to format the categories.\r\n let formatString = valueFormatter.getFormatString(keySourceColumn, scatterChartProps.general.formatString);\r\n let keyFormatter: IValueFormatter;\r\n if (keySourceColumn.type.numeric) {\r\n // use value range, not actual values\r\n let valueRange = Math.abs(matrixRows.root.children[rowChildrenLength - 1].value - matrixRows.root.children[0].value);\r\n keyFormatter = valueFormatter.create({\r\n format: formatString,\r\n value: valueRange,\r\n value2: 0,\r\n });\r\n } else {\r\n keyFormatter = valueFormatter.createDefaultFormatter(formatString, true);\r\n }\r\n\r\n for (let i = 0, len = rowChildrenLength; i < len; i++) {\r\n let key = matrixRows.root.children[i];\r\n let frameLabelText = keyFormatter.format(key.value);\r\n // escaped html\r\n let frameLabelHtml = $(\"<div/>\").text(frameLabelText).html();\r\n frameKeys.push({ escapedText: frameLabelHtml, text: frameLabelText });\r\n \r\n let dataViewCategorical = convertMatrixToCategorical(dataView, i);\r\n let frameInfo = { label: frameLabelHtml, column: keySourceColumn };\r\n convertedData = visualConverter(dataViewCategorical, frameInfo);\r\n allViewModels.push(convertedData);\r\n }\r\n }\r\n else {\r\n let dataViewCategorical = convertMatrixToCategorical(dataView, 0);\r\n convertedData = visualConverter(dataViewCategorical);\r\n allViewModels.push(convertedData);\r\n }\r\n \r\n // NOTE: currentViewModel is already set to the last frame\r\n objectProperties.currentFrameIndex = frameKeys.length - 1;\r\n\r\n return {\r\n allViewModels: allViewModels,\r\n currentViewModel: convertedData,\r\n frameData: frameKeys,\r\n currentFrameIndex: objectProperties.currentFrameIndex,\r\n labelData: getLabelData(frameKeys, keySourceColumn),\r\n };\r\n }\r\n\r\n export function getDefaultPlayData<T extends PlayableChartData>(): PlayChartData<T> {\r\n let defaultData: PlayChartData<T> = {\r\n frameData: [],\r\n allViewModels: [],\r\n currentFrameIndex: 0,\r\n currentViewModel: undefined,\r\n labelData: {\r\n anyWordBreaks: false,\r\n labelInfo: [],\r\n },\r\n };\r\n return defaultData;\r\n }\r\n\r\n export function getMinMaxForAllFrames<T extends PlayableChartData>(playData: PlayChartData<T>, getExtents: (T) => CartesianExtents): CartesianExtents {\r\n let extents: CartesianExtents = {\r\n minY: 0,\r\n maxY: 10,\r\n minX: 0,\r\n maxX: 10,\r\n };\r\n\r\n if (playData.allViewModels && playData.allViewModels.length > 0) {\r\n extents.minY = extents.minX = Number.MAX_VALUE;\r\n extents.maxY = extents.maxX = Number.MIN_VALUE;\r\n for (let i = 0, len = playData.allViewModels.length; i < len; i++) {\r\n let data = playData.allViewModels[i];\r\n let e = getExtents(data);\r\n\r\n // NOTE: D3.min/max handle undefined and NaN nicely, as opposed to Math.min/max\r\n extents = {\r\n minY: d3.min([e.minY, extents.minY]),\r\n maxY: d3.max([e.maxY, extents.maxY]),\r\n minX: d3.min([e.minX, extents.minX]),\r\n maxX: d3.max([e.maxX, extents.maxX]),\r\n };\r\n }\r\n }\r\n\r\n return extents;\r\n }\r\n\r\n function getLabelData(keys: PlayChartFrameData[], keyColumn?: DataViewMetadataColumn): PlayAxisTickLabelData {\r\n let textProperties: TextProperties = {\r\n fontFamily: 'wf_segoe-ui_normal',\r\n fontSize: jsCommon.PixelConverter.toString(14),\r\n };\r\n\r\n let labelInfo: PlayAxisTickLabelInfo[] = [];\r\n let anyWordBreaks = false;\r\n for (let key of keys) {\r\n let labelWidth = jsCommon.WordBreaker.getMaxWordWidth(key.escapedText, TextMeasurementService.measureSvgTextWidth, textProperties);\r\n // TODO: Why isn't this last part included in hasBreakers()?\r\n anyWordBreaks = anyWordBreaks || jsCommon.WordBreaker.hasBreakers(key.escapedText) || (key.escapedText).indexOf('-') > -1; \r\n labelInfo.push({ label: key.escapedText, labelWidth });\r\n }\r\n\r\n return {\r\n labelInfo: labelInfo,\r\n anyWordBreaks: anyWordBreaks,\r\n labelFieldName: keyColumn && keyColumn.displayName,\r\n };\r\n }\r\n\r\n export function isDataViewPlayable(dataView: DataView, playRole: string = 'Play'): boolean {\r\n debug.assertValue(dataView, 'dataView');\r\n\r\n let firstRowSourceRoles = dataView.matrix &&\r\n dataView.matrix.rows &&\r\n dataView.matrix.rows.levels &&\r\n dataView.matrix.rows.levels[0] &&\r\n dataView.matrix.rows.levels[0].sources &&\r\n dataView.matrix.rows.levels[0].sources[0] &&\r\n dataView.matrix.rows.levels[0].sources[0].roles;\r\n\r\n return firstRowSourceRoles && firstRowSourceRoles[playRole];\r\n }\r\n\r\n /** Render trace-lines for selected data points. */\r\n export function renderTraceLines(allDataPoints: SelectableDataPoint[], traceLineRenderer: ITraceLineRenderer, shouldAnimate: boolean): void {\r\n let selectedDataPoints = _.filter(allDataPoints, (d: SelectableDataPoint) => d.selected);\r\n selectedDataPoints = _.uniq(selectedDataPoints, (d: SelectableDataPoint) => d.identity.getKey());\r\n traceLineRenderer.render(selectedDataPoints, shouldAnimate);\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import SlicerOrientation = slicerOrientation.Orientation;\r\n\r\n export interface CheckboxStyle {\r\n transform: string;\r\n 'transform-origin': string;\r\n 'font-size': string;\r\n }\r\n\r\n export class VerticalSlicerRenderer implements ISlicerRenderer, SlicerDefaultValueHandler {\r\n private element: JQuery;\r\n private currentViewport: IViewport;\r\n private dataView: DataView;\r\n private header: D3.Selection;\r\n private body: D3.Selection;\r\n private container: D3.Selection;\r\n private listView: IListView;\r\n private data: SlicerData;\r\n private settings: SlicerSettings;\r\n private behavior: IInteractiveBehavior;\r\n private hostServices: IVisualHostServices;\r\n private textProperties: TextProperties = {\r\n 'fontFamily': 'wf_segoe-ui_normal, helvetica, arial, sans-serif',\r\n 'fontSize': '14px',\r\n };\r\n private domHelper: SlicerUtil.DOMHelper;\r\n\r\n constructor(options?: SlicerConstructorOptions) {\r\n if (options) {\r\n this.behavior = options.behavior;\r\n }\r\n this.domHelper = options.domHelper;\r\n }\r\n\r\n // SlicerDefaultValueHandler\r\n public getDefaultValue(): data.SQConstantExpr {\r\n if (this.data && this.data.defaultValue)\r\n return <data.SQConstantExpr>this.data.defaultValue.value;\r\n }\r\n\r\n public getIdentityFields(): data.SQExpr[] {\r\n return SlicerUtil.DefaultValueHandler.getIdentityFields(this.dataView);\r\n }\r\n\r\n public init(slicerInitOptions: SlicerInitOptions): IInteractivityService {\r\n this.element = slicerInitOptions.visualInitOptions.element;\r\n this.currentViewport = slicerInitOptions.visualInitOptions.viewport;\r\n let hostServices = this.hostServices = slicerInitOptions.visualInitOptions.host;\r\n\r\n let settings = this.settings = Slicer.DefaultStyleProperties();\r\n let domHelper = this.domHelper;\r\n let bodyViewport = domHelper.getSlicerBodyViewport(this.currentViewport, settings, this.textProperties);\r\n let interactivityService: IInteractivityService;\r\n\r\n if (this.behavior)\r\n interactivityService = createInteractivityService(hostServices);\r\n\r\n let containerDiv = document.createElement('div');\r\n containerDiv.className = Selectors.Container.class;\r\n let container = this.container = d3.select(containerDiv);\r\n\r\n let header = domHelper.createSlicerHeader(hostServices);\r\n containerDiv.appendChild(header);\r\n this.header = d3.select(header);\r\n\r\n this.body = container.append('div').classed(SlicerUtil.Selectors.Body.class, true)\r\n .style({\r\n 'height': PixelConverter.toString(bodyViewport.height),\r\n 'width': PixelConverter.toString(bodyViewport.width),\r\n });\r\n\r\n let rowEnter = (rowSelection: D3.Selection) => {\r\n this.onEnterSelection(rowSelection);\r\n };\r\n\r\n let rowUpdate = (rowSelection: D3.Selection) => {\r\n this.onUpdateSelection(rowSelection, interactivityService);\r\n };\r\n\r\n let rowExit = (rowSelection: D3.Selection) => {\r\n rowSelection.remove();\r\n };\r\n\r\n let listViewOptions: ListViewOptions = {\r\n rowHeight: domHelper.getRowHeight(settings, this.textProperties),\r\n enter: rowEnter,\r\n exit: rowExit,\r\n update: rowUpdate,\r\n loadMoreData: () => slicerInitOptions.loadMoreData(),\r\n scrollEnabled: true,\r\n viewport: domHelper.getSlicerBodyViewport(this.currentViewport, settings, this.textProperties),\r\n baseContainer: this.body,\r\n isReadMode: () => {\r\n return (this.hostServices.getViewMode() !== ViewMode.Edit);\r\n }\r\n };\r\n\r\n this.listView = ListViewFactory.createListView(listViewOptions);\r\n\r\n // Append container to DOM\r\n this.element.get(0).appendChild(containerDiv);\r\n\r\n return interactivityService;\r\n }\r\n\r\n public render(options: SlicerRenderOptions): void {\r\n let data = this.data = options.data;\r\n this.currentViewport = options.viewport;\r\n let dataView = options.dataView;\r\n\r\n if (!dataView || !data) {\r\n this.listView.empty();\r\n return;\r\n }\r\n\r\n this.dataView = dataView;\r\n let settings = this.settings = data.slicerSettings;\r\n let domHelper = this.domHelper;\r\n\r\n domHelper.updateSlicerBodyDimensions(this.currentViewport, this.body, settings);\r\n this.updateSelectionStyle();\r\n this.listView\r\n .viewport(domHelper.getSlicerBodyViewport(this.currentViewport, settings, this.textProperties))\r\n .rowHeight(domHelper.getRowHeight(settings, this.textProperties))\r\n .data(\r\n data.slicerDataPoints,\r\n (d: SlicerDataPoint) => $.inArray(d, data.slicerDataPoints),\r\n options.resetScrollbarPosition\r\n );\r\n }\r\n\r\n private updateSelectionStyle(): void {\r\n let settings = this.settings;\r\n this.container.classed('isMultiSelectEnabled', settings && settings.selection && !settings.selection.singleSelect);\r\n }\r\n\r\n private onEnterSelection(rowSelection: D3.Selection): void {\r\n let settings = this.settings;\r\n let listItemElement = rowSelection.append('li')\r\n .classed(Selectors.ItemContainer.class, true);\r\n\r\n let labelElement = listItemElement.append('div')\r\n .classed(Selectors.Input.class, true);\r\n\r\n labelElement.append('input')\r\n .attr('type', 'checkbox');\r\n\r\n labelElement.append('span')\r\n .classed(Selectors.Checkbox.class, true);\r\n\r\n listItemElement.each(function (d: SlicerDataPoint, i: number) {\r\n let item = d3.select(this);\r\n if (d.isImage) {\r\n item.append('img')\r\n .classed(SlicerUtil.Selectors.LabelImage.class, true);\r\n }\r\n else {\r\n item.append('span')\r\n .classed(SlicerUtil.Selectors.LabelText.class, true);\r\n }\r\n\r\n if (d.count != null) {\r\n item.append('span')\r\n .classed(SlicerUtil.Selectors.CountText.class, true)\r\n .style('font-size', PixelConverter.fromPoint(settings.slicerText.textSize));\r\n }\r\n });\r\n }\r\n\r\n private onUpdateSelection(rowSelection: D3.Selection, interactivityService: IInteractivityService): void {\r\n let settings = this.settings;\r\n let data = this.data;\r\n if (data && settings) {\r\n // Style Slicer Header\r\n let domHelper = this.domHelper;\r\n domHelper.styleSlicerHeader(this.header, settings, data.categorySourceName);\r\n this.header.attr('title', data.categorySourceName);\r\n \r\n let labelText = rowSelection.selectAll(SlicerUtil.Selectors.LabelText.selector);\r\n labelText.text((d: SlicerDataPoint) => {\r\n return d.value;\r\n }).attr('title', (d: SlicerDataPoint) => {\r\n return d.tooltip;\r\n });\r\n domHelper.setSlicerTextStyle(labelText, settings);\r\n\r\n let labelImage = rowSelection.selectAll(SlicerUtil.Selectors.LabelImage.selector);\r\n if (!labelImage.empty()) {\r\n labelImage.attr('src', (d: SlicerDataPoint) => {\r\n return d.value;\r\n });\r\n }\r\n\r\n let countText = rowSelection.selectAll(SlicerUtil.Selectors.CountText.selector);\r\n if (!countText.empty()) {\r\n countText.text((d: SlicerDataPoint) => d.count);\r\n domHelper.setSlicerTextStyle(countText, settings);\r\n }\r\n\r\n if (interactivityService && this.body) {\r\n let body = this.body.attr('width', this.currentViewport.width);\r\n let slicerItemContainers = body.selectAll(Selectors.ItemContainer.selector);\r\n let slicerItemLabels = body.selectAll(SlicerUtil.Selectors.LabelText.selector);\r\n let slicerItemInputs = body.selectAll(Selectors.Input.selector);\r\n let slicerClear = this.header.select(SlicerUtil.Selectors.Clear.selector);\r\n\r\n let behaviorOptions: VerticalSlicerBehaviorOptions = {\r\n dataPoints: data.slicerDataPoints,\r\n slicerContainer: this.container,\r\n itemContainers: slicerItemContainers,\r\n itemLabels: slicerItemLabels,\r\n itemInputs: slicerItemInputs,\r\n clear: slicerClear,\r\n interactivityService: interactivityService,\r\n settings: data.slicerSettings,\r\n };\r\n\r\n let orientationBehaviorOptions: SlicerOrientationBehaviorOptions = {\r\n behaviorOptions: behaviorOptions,\r\n orientation: SlicerOrientation.Vertical,\r\n };\r\n\r\n interactivityService.bind(\r\n data.slicerDataPoints,\r\n this.behavior,\r\n orientationBehaviorOptions,\r\n { overrideSelectionFromData: true, hasSelectionOverride: data.hasSelectionOverride, slicerDefaultValueHandler: this });\r\n SlicerWebBehavior.styleSlicerItems(rowSelection.select(Selectors.Input.selector), data.hasSelectionOverride, interactivityService.isSelectionModeInverted());\r\n }\r\n else {\r\n SlicerWebBehavior.styleSlicerItems(rowSelection.select(Selectors.Input.selector), false, false);\r\n }\r\n }\r\n }\r\n }\r\n\r\n module Selectors {\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n export const Container = createClassAndSelector('slicerContainer');\r\n export const ItemContainer = createClassAndSelector('slicerItemContainer');\r\n export const Input = createClassAndSelector('slicerCheckbox');\r\n export const Checkbox = createClassAndSelector('checkbox');\r\n }\r\n\r\n module CheckboxSprite {\r\n export const MinimumSize = 8;\r\n export const Size = 13;\r\n export const SizeRange = Size - MinimumSize;\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import SlicerOrientation = slicerOrientation.Orientation;\r\n\r\n const ItemWidthSampleSize = 50;\r\n const MinTextWidth = 80;\r\n const LoadMoreDataThreshold = 0.8; // The value indicates the percentage of data already shown that triggers a loadMoreData call.\r\n const DefaultStyleProperties = {\r\n labelText: {\r\n marginRight: 2,\r\n paddingLeft: 8,\r\n paddingRight: 8,\r\n },\r\n };\r\n\r\n export class HorizontalSlicerRenderer implements ISlicerRenderer, SlicerDefaultValueHandler {\r\n private element: JQuery;\r\n private currentViewport: IViewport;\r\n private data: SlicerData;\r\n private interactivityService: IInteractivityService;\r\n private behavior: IInteractiveBehavior;\r\n private hostServices: IVisualHostServices;\r\n private dataView: DataView;\r\n private container: D3.Selection;\r\n private header: D3.Selection;\r\n private body: D3.Selection;\r\n private bodyViewport: IViewport;\r\n private itemsContainer: D3.Selection;\r\n private rightNavigationArrow: D3.Selection;\r\n private leftNavigationArrow: D3.Selection;\r\n private dataStartIndex: number;\r\n private itemsToDisplay: number;\r\n private textProperties: TextProperties = {\r\n fontFamily: 'wf_segoe-ui_normal',\r\n fontSize: '14px'\r\n };\r\n private maxItemWidth: number;\r\n private totalItemWidth: number;\r\n private loadMoreData: () => void;\r\n private domHelper: SlicerUtil.DOMHelper;\r\n\r\n constructor(options?: SlicerConstructorOptions) {\r\n if (options) {\r\n this.behavior = options.behavior;\r\n }\r\n this.domHelper = options.domHelper;\r\n this.dataStartIndex = 0;\r\n }\r\n\r\n // SlicerDefaultValueHandler\r\n public getDefaultValue(): data.SQConstantExpr {\r\n if (this.data && this.data.defaultValue)\r\n return <data.SQConstantExpr>this.data.defaultValue.value;\r\n }\r\n\r\n public getIdentityFields(): data.SQExpr[] {\r\n return SlicerUtil.DefaultValueHandler.getIdentityFields(this.dataView);\r\n }\r\n\r\n public init(slicerInitOptions: SlicerInitOptions): IInteractivityService {\r\n this.element = slicerInitOptions.visualInitOptions.element;\r\n this.currentViewport = slicerInitOptions.visualInitOptions.viewport;\r\n let hostServices = this.hostServices = slicerInitOptions.visualInitOptions.host;\r\n\r\n if (this.behavior) {\r\n this.interactivityService = createInteractivityService(hostServices);\r\n }\r\n this.loadMoreData = () => slicerInitOptions.loadMoreData();\r\n\r\n let containerDiv = document.createElement('div');\r\n containerDiv.className = Selectors.container.class;\r\n let container: D3.Selection = this.container = d3.select(containerDiv);\r\n\r\n let header = this.domHelper.createSlicerHeader(this.hostServices);\r\n containerDiv.appendChild(header);\r\n this.header = d3.select(header);\r\n\r\n let body = this.body = container.append('div').classed(SlicerUtil.Selectors.Body.class + \" \" + Selectors.FlexDisplay.class, true);\r\n\r\n this.leftNavigationArrow = body.append(\"button\")\r\n .classed(Selectors.NavigationArrow.class + \" \" + Selectors.LeftNavigationArrow.class, true);\r\n\r\n this.itemsContainer = body.append(\"div\")\r\n .classed(Selectors.ItemsContainer.class + \" \" + Selectors.FlexDisplay.class, true);\r\n\r\n this.rightNavigationArrow = body.append(\"button\")\r\n .classed(Selectors.NavigationArrow.class + \" \" + Selectors.RightNavigationArrow.class, true);\r\n\r\n // Append container to DOM\r\n this.element.get(0).appendChild(containerDiv);\r\n\r\n this.bindNavigationEvents();\r\n\r\n return this.interactivityService;\r\n }\r\n\r\n public render(options: SlicerRenderOptions): void {\r\n let data = options.data;\r\n let dataView = options.dataView;\r\n\r\n if (!dataView || !data) {\r\n this.itemsContainer.selectAll(\"*\").remove();\r\n return;\r\n }\r\n\r\n this.data = data;\r\n this.dataView = dataView;\r\n let resized = this.currentViewport && options.viewport\r\n && (this.currentViewport.height !== options.viewport.height || this.currentViewport.width !== options.viewport.width);\r\n if (!(this.isMaxWidthCalculated() && resized)) {\r\n // Max width calculation is not required during resize, but required on data changes like changes to formatting properties fontSize, outline, outline weight, etc...\r\n // So calculating only on data updates\r\n this.calculateAndSetMaxItemWidth();\r\n this.calculateAndSetTotalItemWidth();\r\n }\r\n\r\n this.currentViewport = options.viewport;\r\n this.updateStyle();\r\n let availableWidthForItemsContainer = this.element.find(Selectors.ItemsContainer.selector).width();\r\n this.itemsToDisplay = this.getNumberOfItemsToDisplay(availableWidthForItemsContainer);\r\n if (this.itemsToDisplay === 0)\r\n return;\r\n\r\n this.renderCore();\r\n }\r\n\r\n private renderCore(): void {\r\n let data = this.data;\r\n if (!data || !data.slicerDataPoints)\r\n return;\r\n\r\n this.normalizePosition(data.slicerDataPoints);\r\n\r\n let itemsToDisplay = this.itemsToDisplay;\r\n let dataStartIndex = this.dataStartIndex;\r\n // Update Navigation Arrows\r\n this.container.classed(Selectors.CanScrollRight.class, dataStartIndex + this.itemsToDisplay <= data.slicerDataPoints.length - 1);\r\n this.container.classed(Selectors.CanScrollLeft.class, dataStartIndex > 0);\r\n\r\n // Manipulate DOM\r\n this.renderItems(data.slicerSettings);\r\n\r\n // Bind Interactivity Service\r\n this.bindInteractivityService();\r\n\r\n // Load More Data\r\n if (dataStartIndex + itemsToDisplay >= data.slicerDataPoints.length * LoadMoreDataThreshold) {\r\n this.loadMoreData();\r\n }\r\n }\r\n\r\n private updateStyle(): void {\r\n let viewport = this.currentViewport;\r\n let data = this.data;\r\n let defaultSettings: SlicerSettings = data.slicerSettings;\r\n let domHelper = this.domHelper;\r\n\r\n this.container\r\n .classed(Selectors.MultiSelectEnabled.class, !defaultSettings.selection.singleSelect)\r\n .style({\r\n \"width\": PixelConverter.toString(viewport.width),\r\n \"height\": PixelConverter.toString(viewport.height),\r\n });\r\n\r\n // Style Slicer Header\r\n domHelper.styleSlicerHeader(this.header, defaultSettings, data.categorySourceName);\r\n let headerTextProperties = domHelper.getHeaderTextProperties(defaultSettings);\r\n this.header.attr('title', data.categorySourceName);\r\n \r\n // Update body width and height\r\n let bodyViewport = this.bodyViewport = domHelper.getSlicerBodyViewport(viewport, defaultSettings, headerTextProperties);\r\n this.body.style({\r\n \"height\": PixelConverter.toString(bodyViewport.height),\r\n \"width\": PixelConverter.toString(bodyViewport.width),\r\n });\r\n }\r\n\r\n private renderItems(defaultSettings: SlicerSettings): void {\r\n let itemsToDisplay = this.itemsToDisplay;\r\n debug.assert(itemsToDisplay > 0, 'items to display should be greater than zero');\r\n let dataStartIndex = this.dataStartIndex;\r\n let materializedDataPoints = this.data.slicerDataPoints.slice(dataStartIndex, dataStartIndex + itemsToDisplay);\r\n let items = this.itemsContainer\r\n .selectAll(SlicerUtil.Selectors.LabelText.selector)\r\n .data(materializedDataPoints, (d: SlicerDataPoint) => _.indexOf(this.data.slicerDataPoints, d));\r\n\r\n items\r\n .enter()\r\n .append(\"div\")\r\n .classed(SlicerUtil.Selectors.LabelText.class + \" \" + Selectors.FlexDisplay.class, true);\r\n\r\n items.order();\r\n\r\n items\r\n .style({\r\n \"font-family\": this.textProperties.fontFamily,\r\n \"padding-left\": PixelConverter.toString(DefaultStyleProperties.labelText.paddingLeft),\r\n \"padding-right\": PixelConverter.toString(DefaultStyleProperties.labelText.paddingRight),\r\n \"margin-right\": (d: SlicerDataPoint, i) => this.isLastRowItem(i, itemsToDisplay) ? \"0px\" : PixelConverter.toString(DefaultStyleProperties.labelText.marginRight),\r\n });\r\n\r\n // Default style settings from formatting pane settings\r\n this.domHelper.setSlicerTextStyle(items, defaultSettings);\r\n\r\n items.exit().remove();\r\n\r\n window.setTimeout(() => {\r\n items\r\n .attr(\"title\", (d: SlicerDataPoint) => d.tooltip)\r\n .text((d: SlicerDataPoint) => d.value);\r\n // Wrap long text into multiple columns based on height availbale\r\n let labels = this.element.find(SlicerUtil.Selectors.LabelText.selector);\r\n let item = labels.first();\r\n let itemWidth = item.width();\r\n let itemHeight = item.height();\r\n labels.each((i, element) => {\r\n TextMeasurementService.wordBreakOverflowingText(element, itemWidth, itemHeight);\r\n });\r\n });\r\n }\r\n\r\n private bindInteractivityService(): void {\r\n if (this.interactivityService && this.body) {\r\n let body = this.body;\r\n let itemsContainer = body.selectAll(Selectors.ItemsContainer.selector);\r\n let itemLabels = body.selectAll(SlicerUtil.Selectors.LabelText.selector);\r\n let clear = this.header.select(SlicerUtil.Selectors.Clear.selector);\r\n let data = this.data;\r\n\r\n let behaviorOptions: HorizontalSlicerBehaviorOptions = {\r\n dataPoints: data.slicerDataPoints,\r\n slicerContainer: this.container,\r\n itemsContainer: itemsContainer,\r\n itemLabels: itemLabels,\r\n clear: clear,\r\n interactivityService: this.interactivityService,\r\n settings: data.slicerSettings,\r\n };\r\n\r\n let orientationBehaviorOptions: SlicerOrientationBehaviorOptions = {\r\n behaviorOptions: behaviorOptions,\r\n orientation: SlicerOrientation.Horizontal,\r\n };\r\n\r\n this.interactivityService.bind(data.slicerDataPoints, this.behavior, orientationBehaviorOptions, { overrideSelectionFromData: true, hasSelectionOverride: data.hasSelectionOverride });\r\n SlicerWebBehavior.styleSlicerItems(this.itemsContainer.selectAll(SlicerUtil.Selectors.LabelText.selector), this.interactivityService.hasSelection(), this.interactivityService.isSelectionModeInverted());\r\n }\r\n else {\r\n SlicerWebBehavior.styleSlicerItems(this.itemsContainer.selectAll(SlicerUtil.Selectors.LabelText.selector), false, false);\r\n }\r\n }\r\n\r\n private normalizePosition(points: SlicerDataPoint[]): void {\r\n let dataStartIndex = this.dataStartIndex;\r\n // if dataStartIndex >= points.length\r\n dataStartIndex = Math.min(dataStartIndex, points.length - 1);\r\n\r\n // if dataStartIndex < 0 \r\n this.dataStartIndex = Math.max(dataStartIndex, 0);\r\n }\r\n\r\n private bindNavigationEvents(): void {\r\n this.registerMouseWheelScrollEvents();\r\n this.registerMouseClickEvents();\r\n }\r\n\r\n private registerMouseClickEvents(): void {\r\n let rightNavigationArrow = this.container.selectAll(Selectors.RightNavigationArrow.selector);\r\n let leftNavigationArrow = this.container.selectAll(Selectors.LeftNavigationArrow.selector);\r\n\r\n rightNavigationArrow\r\n .on(\"click\", () => {\r\n this.scrollRight();\r\n });\r\n\r\n leftNavigationArrow\r\n .on(\"click\", () => {\r\n this.scrollLeft();\r\n });\r\n }\r\n\r\n // Register for mouse wheel scroll events\r\n private registerMouseWheelScrollEvents(): void {\r\n let scrollableElement = this.body.node();\r\n\r\n scrollableElement.addEventListener(\"mousewheel\", (e) => {\r\n this.onMouseWheel((<MouseWheelEvent>e).wheelDelta);\r\n });\r\n\r\n scrollableElement.addEventListener(\"DOMMouseScroll\", (e) => {\r\n this.onMouseWheel((<MouseWheelEvent>e).detail);\r\n });\r\n }\r\n\r\n private onMouseWheel(wheelDelta: number): void {\r\n if (wheelDelta < 0) {\r\n this.scrollRight();\r\n }\r\n else if (wheelDelta > 0) {\r\n this.scrollLeft();\r\n }\r\n }\r\n\r\n /* If there is only one item being displayed, we show the next item when navigation arrows are clicked \r\n * But when there are more than 1 item, n-1 items are shown say we have 10 items in total , in initial page if we show 1 to 5 items when right button is clicked we will show items from 5 to 10\r\n */\r\n private scrollRight(): void {\r\n let itemsToDisplay = this.itemsToDisplay;\r\n let startIndex = this.dataStartIndex;\r\n let dataPointsLength = this.data.slicerDataPoints.length;\r\n let lastItemIndex = dataPointsLength - 1;\r\n\r\n // If it is the last page stay on the same page and don't navigate\r\n if (itemsToDisplay + startIndex > lastItemIndex) {\r\n return;\r\n }\r\n\r\n if (itemsToDisplay === 1) {\r\n startIndex += itemsToDisplay;\r\n }\r\n else {\r\n startIndex += itemsToDisplay - 1;\r\n }\r\n\r\n // Adjust the startIndex to show last n items if startIndex + itemsToDisplay is greater than total datapoints\r\n if (itemsToDisplay + startIndex > lastItemIndex) {\r\n startIndex = lastItemIndex - itemsToDisplay + 1;\r\n }\r\n\r\n this.dataStartIndex = startIndex;\r\n this.renderCore();\r\n }\r\n\r\n /* If there is only one item being displayed, we show the next item when navigation arrows are clicked \r\n * But when there are more than 1 item, n-1 items are shown\r\n */\r\n private scrollLeft(): void {\r\n let itemsToDisplay = this.itemsToDisplay;\r\n let startIndex = this.dataStartIndex;\r\n let firstItemIndex = 0; \r\n // If it is the first page stay on the same page and don't navigate\r\n if (startIndex === 0) {\r\n return;\r\n } \r\n\r\n // If there is only item shown when left navigation button is clicked we want to navigate back to show previous item\r\n if (itemsToDisplay === 1) {\r\n startIndex -= itemsToDisplay;\r\n }\r\n\r\n if (startIndex - itemsToDisplay < firstItemIndex) {\r\n startIndex = firstItemIndex;\r\n }\r\n else {\r\n startIndex = startIndex - itemsToDisplay + 1;\r\n }\r\n this.dataStartIndex = startIndex;\r\n this.renderCore();\r\n }\r\n\r\n private isLastRowItem(fieldIndex: number, columnsToDisplay: number): boolean {\r\n return fieldIndex === columnsToDisplay - 1;\r\n }\r\n\r\n private getScaledTextWidth(textSize: number): number {\r\n return (textSize / jsCommon.TextSizeDefaults.TextSizeMin) * MinTextWidth;\r\n }\r\n\r\n private isMaxWidthCalculated(): boolean {\r\n return this.maxItemWidth !== undefined;\r\n }\r\n\r\n // Sampling a subset of total datapoints to calculate max item width\r\n private calculateAndSetMaxItemWidth(): void { \r\n let dataPointsLength: number = this.getDataPointsCount();\r\n let maxItemWidth = 0;\r\n if (dataPointsLength === 0) {\r\n this.maxItemWidth = maxItemWidth;\r\n return;\r\n }\r\n let data = this.data;\r\n let dataPoints = data.slicerDataPoints;\r\n let sampleSize = Math.min(dataPointsLength, ItemWidthSampleSize);\r\n let properties = jQuery.extend(true, {}, this.textProperties);\r\n let textSize = data.slicerSettings.slicerText.textSize; \r\n // Update text properties from formatting pane values\r\n properties.fontSize = PixelConverter.fromPoint(textSize);\r\n let getMaxWordWidth = jsCommon.WordBreaker.getMaxWordWidth;\r\n\r\n for (let i = 0; i < sampleSize; i++) {\r\n let itemText = dataPoints[i].value;\r\n properties.text = itemText;\r\n maxItemWidth = Math.max(maxItemWidth, getMaxWordWidth(itemText, TextMeasurementService.measureSvgTextWidth, properties));\r\n }\r\n\r\n this.maxItemWidth = Math.min(maxItemWidth, this.getScaledTextWidth(textSize));\r\n }\r\n\r\n private calculateAndSetTotalItemWidth(): void {\r\n let data = this.data;\r\n let itemPadding = DefaultStyleProperties.labelText.paddingLeft + DefaultStyleProperties.labelText.paddingRight + DefaultStyleProperties.labelText.marginRight;\r\n let borderWidth = this.domHelper.getRowsOutlineWidth(data.slicerSettings.slicerText.outline, data.slicerSettings.general.outlineWeight);\r\n this.totalItemWidth = this.maxItemWidth + itemPadding + borderWidth;\r\n }\r\n\r\n private getNumberOfItemsToDisplay(widthAvailable: number): number {\r\n let totalItemWidth = this.totalItemWidth;\r\n if (totalItemWidth === 0)\r\n return 0;\r\n\r\n let dataPointsLength = this.getDataPointsCount();\r\n let numberOfItems = Math.min(dataPointsLength, Math.round(widthAvailable / totalItemWidth));\r\n\r\n // Show atleast 1 item by default \r\n return Math.max(numberOfItems, 1);\r\n\r\n }\r\n\r\n private getDataPointsCount(): number {\r\n return _.size(this.data.slicerDataPoints);\r\n }\r\n }\r\n\r\n module Selectors {\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n export const container = createClassAndSelector('horizontalSlicerContainer');\r\n export const ItemsContainer = createClassAndSelector('slicerItemsContainer');\r\n export const NavigationArrow = createClassAndSelector('navigationArrow');\r\n export const LeftNavigationArrow = createClassAndSelector('left');\r\n export const RightNavigationArrow = createClassAndSelector('right');\r\n export const MultiSelectEnabled = createClassAndSelector('isMultiSelectEnabled');\r\n export const FlexDisplay = createClassAndSelector('flexDisplay');\r\n export const CanScrollRight = createClassAndSelector('canScrollRight');\r\n export const CanScrollLeft = createClassAndSelector('canScrollLeft');\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import DisplayNameKeys = SlicerUtil.DisplayNameKeys;\r\n import DOMHelper = SlicerUtil.DOMHelper;\r\n import SettingsHelper = SlicerUtil.SettingsHelper;\r\n import SlicerOrientation = slicerOrientation.Orientation;\r\n\r\n export interface SlicerDefaultValueHandler {\r\n getDefaultValue(): data.SQConstantExpr;\r\n getIdentityFields(): data.SQExpr[];\r\n }\r\n\r\n export interface SlicerConstructorOptions {\r\n domHelper?: DOMHelper;\r\n behavior?: IInteractiveBehavior;\r\n }\r\n\r\n export interface ISlicerRenderer {\r\n init(options: SlicerInitOptions): IInteractivityService;\r\n render(options: SlicerRenderOptions): void;\r\n }\r\n\r\n export interface SlicerRenderOptions {\r\n dataView: DataView;\r\n data: SlicerData;\r\n viewport: IViewport;\r\n resetScrollbarPosition?: boolean;\r\n }\r\n\r\n export interface SlicerData {\r\n categorySourceName: string;\r\n slicerDataPoints: SlicerDataPoint[];\r\n slicerSettings: SlicerSettings;\r\n hasSelectionOverride?: boolean;\r\n defaultValue?: DefaultValueDefinition;\r\n }\r\n\r\n export interface SlicerDataPoint extends SelectableDataPoint {\r\n value: string;\r\n tooltip: string;\r\n isSelectAllDataPoint?: boolean;\r\n count: number;\r\n isImage?: boolean;\r\n }\r\n\r\n export interface SlicerSettings {\r\n general: {\r\n outlineColor: string;\r\n outlineWeight: number;\r\n orientation: SlicerOrientation;\r\n };\r\n header: {\r\n borderBottomWidth: number;\r\n show: boolean;\r\n outline: string;\r\n fontColor: string;\r\n background?: string;\r\n textSize: number;\r\n };\r\n slicerText: {\r\n color: string;\r\n outline: string;\r\n background?: string;\r\n textSize: number;\r\n };\r\n selection: {\r\n selectAllCheckboxEnabled: boolean;\r\n singleSelect: boolean;\r\n };\r\n }\r\n\r\n export interface SlicerInitOptions {\r\n visualInitOptions: VisualInitOptions;\r\n loadMoreData: () => void;\r\n }\r\n\r\n export class Slicer implements IVisual {\r\n private element: JQuery;\r\n private currentViewport: IViewport;\r\n private dataView: DataView;\r\n private slicerData: SlicerData;\r\n private settings: SlicerSettings;\r\n private interactivityService: IInteractivityService;\r\n private behavior: IInteractiveBehavior;\r\n private hostServices: IVisualHostServices;\r\n private slicerRenderer: ISlicerRenderer;\r\n private slicerOrientation: SlicerOrientation;\r\n private waitingForData: boolean;\r\n private domHelper: DOMHelper;\r\n private initOptions: VisualInitOptions;\r\n public static DefaultStyleProperties(): SlicerSettings {\r\n return {\r\n general: {\r\n outlineColor: '#808080',\r\n outlineWeight: 1,\r\n orientation: SlicerOrientation.Vertical,\r\n },\r\n header: {\r\n borderBottomWidth: 1,\r\n show: true,\r\n outline: visuals.outline.bottomOnly,\r\n fontColor: '#000000',\r\n textSize: 10,\r\n },\r\n slicerText: {\r\n color: '#666666',\r\n outline: visuals.outline.none,\r\n textSize: 10,\r\n },\r\n selection: {\r\n selectAllCheckboxEnabled: false,\r\n singleSelect: true,\r\n },\r\n };\r\n }\r\n\r\n constructor(options?: SlicerConstructorOptions) {\r\n if (options) {\r\n this.behavior = options.behavior;\r\n }\r\n this.domHelper = new DOMHelper();\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.initOptions = options;\r\n this.element = options.element;\r\n this.currentViewport = options.viewport;\r\n this.hostServices = options.host;\r\n let settings = this.settings = Slicer.DefaultStyleProperties();\r\n this.slicerOrientation = settings.general.orientation;\r\n this.waitingForData = false;\r\n\r\n this.initializeSlicerRenderer(this.slicerOrientation);\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataViews = options.dataViews;\r\n debug.assertValue(dataViews, 'dataViews');\r\n\r\n if (_.isEmpty(dataViews)) {\r\n return;\r\n }\r\n\r\n let existingDataView = this.dataView;\r\n this.dataView = dataViews[0];\r\n // Reset scrollbar by default, unless it's an Append operation or Selecting an item\r\n let resetScrollbarPosition = options.operationKind !== VisualDataChangeOperationKind.Append\r\n && !DataViewAnalysis.hasSameCategoryIdentity(existingDataView, this.dataView);\r\n\r\n this.render(resetScrollbarPosition, true);\r\n }\r\n\r\n public onResizing(finalViewport: IViewport): void {\r\n this.currentViewport = finalViewport;\r\n this.render(false /* resetScrollbarPosition */);\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] {\r\n return ObjectEnumerator.enumerateObjectInstances(options, this.slicerData, this.settings, this.dataView);\r\n }\r\n\r\n // public for testability\r\n public loadMoreData(): void {\r\n let dataView = this.dataView;\r\n if (!dataView)\r\n return;\r\n\r\n let dataViewMetadata = dataView.metadata;\r\n // Making sure that hostservices.loadMoreData is not invoked when waiting for server to load the next segment of data\r\n if (!this.waitingForData && dataViewMetadata && dataViewMetadata.segment) {\r\n this.hostServices.loadMoreData();\r\n this.waitingForData = true;\r\n }\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService) {\r\n this.interactivityService.clearSelection();\r\n // calls render so that default behavior can be applied after clear selection.\r\n this.render(false /* resetScrollbarPosition */);\r\n }\r\n }\r\n\r\n private render(resetScrollbarPosition: boolean, stopWaitingForData?: boolean): void {\r\n let localizedSelectAllText = this.hostServices.getLocalizedString(DisplayNameKeys.SelectAll);\r\n this.slicerData = DataConversion.convert(this.dataView, localizedSelectAllText, this.interactivityService, this.hostServices);\r\n if (this.slicerData) {\r\n this.slicerData.slicerSettings.general.outlineWeight = Math.max(this.slicerData.slicerSettings.general.outlineWeight, 0);\r\n this.settings = this.slicerData.slicerSettings;\r\n // TODO: Do we need to check SettingsHelper.areSettingsDefined(), etc. here? Can we just do value validation and coercion in the same place that we create the slicerSettings?\r\n let slicerOrientation = SettingsHelper.areSettingsDefined(this.slicerData) && this.slicerData.slicerSettings.general && this.slicerData.slicerSettings.general.orientation ?\r\n this.slicerData.slicerSettings.general.orientation : Slicer.DefaultStyleProperties().general.orientation;\r\n\r\n let orientationHasChanged = this.orientationHasChanged(slicerOrientation);\r\n if (orientationHasChanged) {\r\n this.slicerOrientation = slicerOrientation;\r\n // Clear the previous slicer type when rendering the new slicer type\r\n this.element.empty();\r\n this.initializeSlicerRenderer(slicerOrientation);\r\n }\r\n }\r\n this.slicerRenderer.render({ dataView: this.dataView, data: this.slicerData, viewport: this.currentViewport, resetScrollbarPosition: resetScrollbarPosition });\r\n\r\n if (stopWaitingForData)\r\n this.waitingForData = false;\r\n }\r\n\r\n private orientationHasChanged(slicerOrientation: SlicerOrientation): boolean {\r\n return this.slicerOrientation !== slicerOrientation;\r\n }\r\n\r\n private initializeSlicerRenderer(slicerOrientation: SlicerOrientation): void {\r\n switch (slicerOrientation) {\r\n case SlicerOrientation.Horizontal:\r\n this.initializeHorizontalSlicer();\r\n break;\r\n\r\n case SlicerOrientation.Vertical:\r\n this.initializeVerticalSlicer();\r\n break;\r\n }\r\n }\r\n\r\n private initializeVerticalSlicer(): void {\r\n let verticalSlicerRenderer = this.slicerRenderer = new VerticalSlicerRenderer({ domHelper: this.domHelper, behavior: this.behavior });\r\n let options = this.createInitOptions();\r\n this.interactivityService = verticalSlicerRenderer.init(options);\r\n }\r\n\r\n private initializeHorizontalSlicer(): void {\r\n let horizontalSlicerRenderer = this.slicerRenderer = new HorizontalSlicerRenderer({ domHelper: this.domHelper, behavior: this.behavior });\r\n let options = this.createInitOptions();\r\n this.interactivityService = horizontalSlicerRenderer.init(options);\r\n }\r\n\r\n private createInitOptions(): SlicerInitOptions {\r\n return {\r\n visualInitOptions: this.initOptions,\r\n loadMoreData: () => this.loadMoreData()\r\n };\r\n }\r\n }\r\n\r\n /** Helper class for calculating the current slicer settings. */\r\n module ObjectEnumerator {\r\n export function enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions, data: SlicerData, settings: SlicerSettings, dataView: DataView): VisualObjectInstance[] {\r\n if (!data)\r\n return;\r\n\r\n switch (options.objectName) {\r\n case 'items':\r\n return enumerateItems(data, settings);\r\n case 'header':\r\n return enumerateHeader(data, settings);\r\n case 'general':\r\n return enumerateGeneral(data, settings);\r\n case 'selection':\r\n if (shouldShowSelectionOption(dataView))\r\n return enumerateSelection(data, settings);\r\n }\r\n }\r\n\r\n function shouldShowSelectionOption(dataView: DataView): boolean {\r\n return !(dataView &&\r\n dataView.metadata &&\r\n dataView.metadata.columns &&\r\n _.some(dataView.metadata.columns, (column) => column.discourageAggregationAcrossGroups));\r\n }\r\n\r\n function enumerateSelection(data: SlicerData, settings: SlicerSettings): VisualObjectInstance[] {\r\n let slicerSettings = settings;\r\n let areSelectionSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.selection;\r\n let selectAllCheckboxEnabled = areSelectionSettingsDefined && data.slicerSettings.selection.selectAllCheckboxEnabled ?\r\n data.slicerSettings.selection.selectAllCheckboxEnabled : slicerSettings.selection.selectAllCheckboxEnabled;\r\n let singleSelect = data && data.slicerSettings && data.slicerSettings.selection && data.slicerSettings.selection.singleSelect !== undefined ?\r\n data.slicerSettings.selection.singleSelect : slicerSettings.selection.singleSelect;\r\n\r\n return [{\r\n selector: null,\r\n objectName: 'selection',\r\n properties: {\r\n selectAllCheckboxEnabled: selectAllCheckboxEnabled,\r\n singleSelect: singleSelect,\r\n }\r\n }];\r\n }\r\n\r\n function enumerateHeader(data: SlicerData, settings: SlicerSettings): VisualObjectInstance[] {\r\n let slicerSettings = settings;\r\n let areHeaderSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.header;\r\n let fontColor = areHeaderSettingsDefined && data.slicerSettings.header.fontColor ?\r\n data.slicerSettings.header.fontColor : slicerSettings.header.fontColor;\r\n let background = areHeaderSettingsDefined && data.slicerSettings.header.background ?\r\n data.slicerSettings.header.background : slicerSettings.header.background;\r\n return [{\r\n selector: null,\r\n objectName: 'header',\r\n properties: {\r\n show: slicerSettings.header.show,\r\n fontColor: fontColor,\r\n background: background,\r\n outline: slicerSettings.header.outline,\r\n textSize: slicerSettings.header.textSize,\r\n }\r\n }];\r\n }\r\n\r\n function enumerateItems(data: SlicerData, settings: SlicerSettings): VisualObjectInstance[] {\r\n let slicerSettings = settings;\r\n let areTextSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.slicerText;\r\n let fontColor = areTextSettingsDefined && data.slicerSettings.slicerText.color ?\r\n data.slicerSettings.slicerText.color : slicerSettings.slicerText.color;\r\n let background = areTextSettingsDefined && data.slicerSettings.slicerText.background ?\r\n data.slicerSettings.slicerText.background : slicerSettings.slicerText.background;\r\n return [{\r\n selector: null,\r\n objectName: 'items',\r\n properties: {\r\n fontColor: fontColor,\r\n background: background,\r\n outline: slicerSettings.slicerText.outline,\r\n textSize: slicerSettings.slicerText.textSize,\r\n }\r\n }];\r\n }\r\n\r\n function enumerateGeneral(data: SlicerData, settings: SlicerSettings): VisualObjectInstance[] {\r\n let slicerSettings = settings;\r\n let areGeneralSettingsDefined = SettingsHelper.areSettingsDefined(data) && data.slicerSettings.general != null;\r\n let outlineColor = areGeneralSettingsDefined && data.slicerSettings.general.outlineColor ?\r\n data.slicerSettings.general.outlineColor : slicerSettings.general.outlineColor;\r\n let outlineWeight = areGeneralSettingsDefined && data.slicerSettings.general.outlineWeight ?\r\n data.slicerSettings.general.outlineWeight : slicerSettings.general.outlineWeight;\r\n let orientation = areGeneralSettingsDefined && data.slicerSettings.general.orientation != null ?\r\n data.slicerSettings.general.orientation : slicerSettings.general.orientation;\r\n\r\n return [{\r\n selector: null,\r\n objectName: 'general',\r\n properties: {\r\n outlineColor: outlineColor,\r\n outlineWeight: outlineWeight,\r\n orientation: orientation,\r\n }\r\n }];\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import TablixFormattingProperties = powerbi.visuals.controls.TablixFormattingPropertiesTable;\r\n import TablixUtils = controls.internal.TablixUtils;\r\n import TablixObjects = controls.internal.TablixObjects;\r\n\r\n export interface DataViewVisualTable extends DataViewTable {\r\n visualRows?: DataViewVisualTableRow[];\r\n formattingProperties?: TablixFormattingProperties;\r\n }\r\n\r\n export interface DataViewVisualTableRow {\r\n index: number;\r\n values: DataViewTableRow;\r\n }\r\n\r\n export interface TableDataAdapter {\r\n update(table: DataViewTable): void;\r\n }\r\n\r\n export interface TableTotal {\r\n totalCells: any[];\r\n }\r\n\r\n export class TableHierarchyNavigator implements controls.ITablixHierarchyNavigator, TableDataAdapter {\r\n private tableDataView: DataViewVisualTable;\r\n private formatter: ICustomValueColumnFormatter;\r\n\r\n constructor(tableDataView: DataViewVisualTable, formatter: ICustomValueColumnFormatter) {\r\n debug.assertValue(tableDataView, 'tableDataView');\r\n debug.assertValue(formatter, 'formatter');\r\n\r\n this.tableDataView = tableDataView;\r\n this.formatter = formatter;\r\n }\r\n\r\n /**\r\n * Returns the depth of the Columnm hierarchy.\r\n */\r\n public getColumnHierarchyDepth(): number {\r\n return 1;\r\n }\r\n\r\n /**\r\n * Returns the depth of the Row hierarchy.\r\n */\r\n public getRowHierarchyDepth(): number {\r\n return 1;\r\n }\r\n\r\n /**\r\n * Returns the leaf count of a hierarchy.\r\n */\r\n public getLeafCount(hierarchy: any): number {\r\n return hierarchy.length;\r\n }\r\n\r\n /**\r\n * Returns the leaf member of a hierarchy at a specified index.\r\n */\r\n public getLeafAt(hierarchy: any, index: number): any {\r\n return hierarchy[index];\r\n }\r\n\r\n /**\r\n * Returns the specified hierarchy member parent.\r\n */\r\n public getParent(item: any): any {\r\n return null;\r\n }\r\n\r\n /**\r\n * Returns the index of the hierarchy member relative to its parent.\r\n */\r\n public getIndex(item: any): number {\r\n if (!item)\r\n return -1;\r\n\r\n if (this.isRow(item))\r\n return (<DataViewVisualTableRow>item).index;\r\n\r\n return this.getColumnIndex(item);\r\n }\r\n\r\n private isRow(item: any): boolean {\r\n if (!item)\r\n return false;\r\n\r\n let row = <DataViewVisualTableRow>item;\r\n return row.index !== undefined && row.values !== undefined;\r\n }\r\n\r\n private getColumnIndex(item: any): number {\r\n return TableHierarchyNavigator.getIndex(this.tableDataView.columns, item);\r\n }\r\n\r\n /**\r\n * Checks whether a hierarchy member is a leaf.\r\n */\r\n public isLeaf(item: any): boolean {\r\n return true;\r\n }\r\n\r\n public isRowHierarchyLeaf(cornerItem: any): boolean {\r\n return false;\r\n }\r\n\r\n public isColumnHierarchyLeaf(cornerItem: any): boolean {\r\n return true;\r\n }\r\n\r\n public isFirstItem(item: MatrixVisualNode, items: MatrixVisualNode[]): boolean {\r\n // checking for item.index is unreliable because reordering the columns would cause a mismatch between index and items order\r\n return item === items[0];\r\n }\r\n\r\n public areAllParentsFirst(item: any, items: any): boolean {\r\n return this.isFirstItem(item, items);\r\n }\r\n\r\n /**\r\n * Checks whether a hierarchy member is the last item within its parent.\r\n */\r\n public isLastItem(item: any, items: any[]): boolean {\r\n debug.assertValue(item, 'item');\r\n\r\n return items[items.length - 1] === item;\r\n }\r\n\r\n public areAllParentsLast(item: any, items: any[]): boolean {\r\n return this.isLastItem(item, items);\r\n }\r\n\r\n /**\r\n * Gets the children members of a hierarchy member.\r\n */\r\n public getChildren(item: any): any {\r\n return null;\r\n }\r\n\r\n public getChildrenLevelDifference(item: any) {\r\n return Infinity;\r\n }\r\n\r\n /**\r\n * Gets the members count in a specified collection.\r\n */\r\n public getCount(items: any): number {\r\n return items.length;\r\n }\r\n\r\n /**\r\n * Gets the member at the specified index.\r\n */\r\n public getAt(items: any, index: number): any {\r\n return items[index];\r\n }\r\n\r\n /**\r\n * Gets the hierarchy member level.\r\n */\r\n public getLevel(item: any): number {\r\n return 0;\r\n }\r\n\r\n /**\r\n * Returns the intersection between a row and a column item.\r\n */\r\n public getIntersection(rowItem: any, columnItem: DataViewMetadataColumn): TablixUtils.TablixVisualCell {\r\n let value: any;\r\n let isTotal: boolean = false;\r\n let position = new TablixUtils.CellPosition();\r\n\r\n let columnIndex: number = TableHierarchyNavigator.getIndex(this.tableDataView.columns, columnItem);;\r\n position.column.index = columnIndex;\r\n position.column.isFirst = columnIndex === 0 ? true : false;\r\n position.column.isLast = columnIndex === this.tableDataView.columns.length - 1;\r\n\r\n let totalRow = <TableTotal>rowItem;\r\n if (totalRow.totalCells != null) {\r\n isTotal = true;\r\n value = totalRow.totalCells[columnIndex];\r\n }\r\n else {\r\n let row = <DataViewVisualTableRow>rowItem;\r\n let rowIndex = row.index;\r\n position.row.index = rowIndex;\r\n position.row.isFirst = rowIndex === 0;\r\n position.row.isLast = rowIndex === this.tableDataView.rows.length - 1;\r\n value = row.values[columnIndex];\r\n }\r\n\r\n let cellItem = new TablixUtils.TablixVisualCell(value, isTotal, columnItem, this.formatter);\r\n cellItem.position = position;\r\n\r\n let tableRow = <DataViewVisualTableRow>rowItem;\r\n if (tableRow && tableRow.values) {\r\n let rowObjects = tableRow.values.objects;\r\n if (rowObjects) {\r\n let cellObject = rowObjects[columnIndex];\r\n if (cellObject) {\r\n cellItem.backColor = TablixObjects.PropValuesBackColor.getValue<string>(cellObject);\r\n }\r\n }\r\n }\r\n return cellItem;\r\n }\r\n\r\n /**\r\n * Returns the corner cell between a row and a column level.\r\n */\r\n public getCorner(rowLevel: number, columnLevel: number): TablixUtils.TablixVisualCell {\r\n return null;\r\n }\r\n\r\n public headerItemEquals(item1: any, item2: any): boolean {\r\n if (item1 === item2)\r\n return true;\r\n\r\n // Typechecking does not work with interfaces nor at runtime. We need to explicitly check for\r\n // properties of DataViewMetadataColumn to determine if we can use the column equivalency check.\r\n // We expect this method to handle either VisualTableRows or DataViewMetadataColumns so checking\r\n // for displayName should be sufficient.\r\n if (item1.displayName && item2.displayName) {\r\n let column1 = <powerbi.DataViewMetadataColumn>item1;\r\n let column2 = <powerbi.DataViewMetadataColumn>item2;\r\n return powerbi.DataViewAnalysis.areMetadataColumnsEquivalent(column1, column2);\r\n }\r\n\r\n if (this.isRow(item1) && this.isRow(item2))\r\n return item1.index === item2.index;\r\n\r\n return false;\r\n }\r\n\r\n public bodyCellItemEquals(item1: TablixUtils.TablixVisualCell, item2: TablixUtils.TablixVisualCell): boolean {\r\n //return (item1.dataPoint === item2.dataPoint);\r\n return (item1.isMatch(item2));\r\n }\r\n\r\n public cornerCellItemEquals(item1: any, item2: any): boolean {\r\n // Should not be called as we don't return any corner items for table\r\n return true;\r\n }\r\n\r\n public update(table: DataViewVisualTable): void {\r\n this.tableDataView = table;\r\n }\r\n\r\n public static getIndex(items: any[], item: any): number {\r\n for (let index = 0, len = items.length; index < len; index++) {\r\n\r\n // For cases when the item was re-created during the DataTransformation phase,\r\n // we check for the item's index to verify equality.\r\n let arrayItem = items[index];\r\n if (arrayItem.index != null && item.index != null && arrayItem.index === item.index) {\r\n return index;\r\n }\r\n else {\r\n if (item === items[index])\r\n return index;\r\n }\r\n }\r\n\r\n return -1;\r\n }\r\n }\r\n\r\n export interface TableBinderOptions {\r\n onBindRowHeader?(item: any): void;\r\n onColumnHeaderClick?(queryName: string, sortDirection: SortDirection): void;\r\n layoutKind?: controls.TablixLayoutKind;\r\n }\r\n\r\n /**\r\n * Note: Public for testability.\r\n */\r\n export class TableBinder implements controls.ITablixBinder {\r\n private options: TableBinderOptions;\r\n private formattingProperties: TablixFormattingProperties;\r\n private tableDataView: DataViewVisualTable;\r\n\r\n private textHeightHeader: number;\r\n private textHeightValue: number;\r\n private textHeightTotal: number;\r\n\r\n constructor(options: TableBinderOptions) {\r\n this.options = options;\r\n }\r\n\r\n public onDataViewChanged(dataView: DataViewVisualTable): void {\r\n this.tableDataView = dataView;\r\n this.formattingProperties = dataView.formattingProperties;\r\n\r\n this.updateTextHeights();\r\n }\r\n\r\n private updateTextHeights(): void {\r\n let textProps: TextProperties = {\r\n fontFamily: '',\r\n fontSize: TablixObjects.getTextSizeInPx(this.formattingProperties.general.textSize),\r\n text: 'a',\r\n };\r\n\r\n textProps.fontFamily = TablixUtils.FontFamilyHeader;\r\n this.textHeightHeader = Math.ceil(TextMeasurementService.measureSvgTextHeight(textProps));\r\n\r\n textProps.fontFamily = TablixUtils.FontFamilyCell;\r\n this.textHeightValue = Math.ceil(TextMeasurementService.measureSvgTextHeight(textProps));\r\n\r\n textProps.fontFamily = TablixUtils.FontFamilyTotal;\r\n this.textHeightTotal = Math.ceil(TextMeasurementService.measureSvgTextHeight(textProps));\r\n }\r\n\r\n public onStartRenderingSession(): void {\r\n }\r\n\r\n public onEndRenderingSession(): void {\r\n }\r\n\r\n /**\r\n * Row Header.\r\n */\r\n public bindRowHeader(item: any, cell: controls.ITablixCell): void {\r\n cell.contentHeight = this.textHeightValue;\r\n\r\n // To clear the CSS classes that adds paddings\r\n TablixUtils.clearCellStyle(cell);\r\n\r\n if (this.options.onBindRowHeader)\r\n this.options.onBindRowHeader(item);\r\n }\r\n\r\n public unbindRowHeader(item: any, cell: controls.ITablixCell): void {\r\n\r\n }\r\n\r\n /**\r\n * Column Header.\r\n */\r\n\r\n public bindColumnHeader(item: DataViewMetadataColumn, cell: controls.ITablixCell): void {\r\n cell.extension.disableDragResize();\r\n TablixUtils.resetCellCssClass(cell);\r\n\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixHeader);\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixColumnHeaderLeaf);\r\n\r\n let cellStyle = new TablixUtils.CellStyle();\r\n // Set default style\r\n cellStyle.fontFamily = TablixUtils.FontFamilyHeader;\r\n cellStyle.fontColor = TablixUtils.FontColorHeaders;\r\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\r\n\r\n cell.contentHeight = this.textHeightHeader;\r\n\r\n if (this.sortIconsEnabled())\r\n TablixUtils.createColumnHeaderWithSortIcon(item, cell);\r\n else\r\n TablixUtils.setCellTextAndTooltip(cell, item.displayName);\r\n\r\n if (this.options.onColumnHeaderClick) {\r\n let handler = (e: MouseEvent) => {\r\n if (TablixUtils.isValidSortClick(e)) {\r\n let sortDirection: SortDirection = TablixUtils.reverseSort(item.sort);\r\n this.options.onColumnHeaderClick(item.queryName ? item.queryName : item.displayName, sortDirection);\r\n }\r\n };\r\n cell.extension.registerClickHandler(handler);\r\n }\r\n this.setColumnHeaderStyle(cell, cellStyle);\r\n\r\n cell.applyStyle(cellStyle);\r\n }\r\n\r\n private setColumnHeaderStyle(cell: controls.ITablixCell, style: TablixUtils.CellStyle): void {\r\n let propsGrid = this.formattingProperties.grid;\r\n let props = this.formattingProperties.columnHeaders;\r\n let propsTotal = this.formattingProperties.total;\r\n let propsValues = this.formattingProperties.values;\r\n\r\n style.borders.top = new TablixUtils.EdgeSettings();\r\n style.borders.top.applyParams(outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n style.borders.bottom = new TablixUtils.EdgeSettings();\r\n style.borders.bottom.applyParams(outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n style.borders.left = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isFirst) {\r\n style.borders.left.applyParams(outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have left border, but Footer or Body has, we need to apply extra padding\r\n if (!outline.showLeft(props.outline) && (outline.showLeft(propsTotal.outline) || outline.showLeft(propsValues.outline)))\r\n style.paddings.left += propsGrid.outlineWeight;\r\n } // else: do nothing\r\n\r\n style.borders.right = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isLast) {\r\n style.borders.right.applyParams(outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have right border, but Footer or Body has, we need to apply extra padding\r\n if (!outline.showRight(props.outline) && (outline.showRight(propsTotal.outline) || outline.showRight(propsValues.outline)))\r\n style.paddings.right += propsGrid.outlineWeight;\r\n }\r\n else {\r\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\r\n }\r\n\r\n style.fontColor = props.fontColor;\r\n style.backColor = props.backColor;\r\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\r\n }\r\n\r\n public unbindColumnHeader(item: any, cell: controls.ITablixCell): void {\r\n TablixUtils.clearCellStyle(cell);\r\n TablixUtils.clearCellTextAndTooltip(cell);\r\n\r\n if (this.sortIconsEnabled())\r\n TablixUtils.removeSortIcons(cell);\r\n\r\n if (this.options.onColumnHeaderClick) {\r\n cell.extension.unregisterClickHandler();\r\n }\r\n }\r\n\r\n /**\r\n * Body Cell.\r\n */\r\n public bindBodyCell(item: TablixUtils.TablixVisualCell, cell: controls.ITablixCell): void {\r\n TablixUtils.resetCellCssClass(cell);\r\n let imgHeight: number;\r\n imgHeight = this.formattingProperties.grid.imageHeight;\r\n\r\n let cellStyle = new TablixUtils.CellStyle();\r\n\r\n if (item.isImage) {\r\n cell.contentHeight = imgHeight;\r\n }\r\n else {\r\n cell.contentHeight = this.textHeightValue;\r\n }\r\n\r\n if (item.isUrl && item.isValidUrl) {\r\n TablixUtils.appendATagToBodyCell(item.textContent, cell, this.formattingProperties.values.urlIcon);\r\n }\r\n else if (item.isImage && item.isValidUrl) {\r\n TablixUtils.appendImgTagToBodyCell(item.textContent, cell, imgHeight);\r\n cellStyle.hasImage = true;\r\n }\r\n else if (item.domContent) {\r\n $(cell.extension.contentHost).append(item.domContent);\r\n }\r\n else if (item.textContent) {\r\n TablixUtils.setCellTextAndTooltip(cell, item.textContent);\r\n }\r\n else {\r\n TablixUtils.setCellTextAndTooltip(cell, \" \");\r\n }\r\n\r\n if (item.isTotal) {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueTotal);\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTableFooter);\r\n\r\n cellStyle.fontFamily = TablixUtils.FontFamilyTotal;\r\n cellStyle.borders.top = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\r\n\r\n cell.contentHeight = this.textHeightTotal;\r\n }\r\n else if (item.position.row.isLast) {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTableBodyCellBottom);\r\n }\r\n else {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTableBodyCell);\r\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridHorizontalWeight.defaultValue, TablixObjects.PropGridHorizontalColor.defaultValue);\r\n }\r\n\r\n if (item.isNumeric)\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueNumeric);\r\n\r\n if (item.isTotal)\r\n this.setFooterStyle(cell, cellStyle);\r\n else\r\n this.setBodyStyle(item, cell, cellStyle);\r\n\r\n cell.applyStyle(cellStyle);\r\n }\r\n\r\n private setBodyStyle(item: TablixUtils.TablixVisualCell, cell: controls.ITablixCell, style: TablixUtils.CellStyle): void {\r\n let propsGrid = this.formattingProperties.grid;\r\n let props = this.formattingProperties.values;\r\n let propsTotal = this.formattingProperties.total;\r\n let propsColumns = this.formattingProperties.columnHeaders;\r\n\r\n style.borders.top = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isFirst) { // First Row\r\n style.borders.top.applyParams(outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n } // else: do nothing\r\n\r\n style.borders.bottom = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isLast) { // Last Row\r\n style.borders.bottom.applyParams(outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n }\r\n else {\r\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\r\n }\r\n\r\n style.borders.left = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isFirst) { // First Column\r\n style.borders.left.applyParams(outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have left border, but Footer or Header has, we need to apply extra padding\r\n if (!outline.showLeft(props.outline) && (outline.showLeft(propsTotal.outline) || outline.showLeft(propsColumns.outline)))\r\n style.paddings.left += propsGrid.outlineWeight;\r\n } // else: do nothing\r\n\r\n style.borders.right = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isLast) { // Last Column\r\n style.borders.right.applyParams(outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have right border, but Footer has, we need to apply extra padding\r\n if (!outline.showRight(props.outline) && (outline.showRight(propsTotal.outline) || outline.showRight(propsColumns.outline)))\r\n style.paddings.right += propsGrid.outlineWeight;\r\n }\r\n else {\r\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\r\n }\r\n\r\n style.fontColor = cell.position.row.index % 2 === 0 ? props.fontColorPrimary : props.fontColorSecondary;\r\n\r\n // Conditional formatting on the cell overrides primary/secondary background colors.\r\n if (item.backColor)\r\n style.backColor = item.backColor;\r\n else\r\n style.backColor = cell.position.row.index % 2 === 0 ? props.backColorPrimary : props.backColorSecondary;\r\n\r\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\r\n }\r\n\r\n private setFooterStyle(cell: controls.ITablixCell, style: TablixUtils.CellStyle): void {\r\n let props = this.formattingProperties.total;\r\n let propsGrid = this.formattingProperties.grid;\r\n let propsValues = this.formattingProperties.values;\r\n let propsColumns = this.formattingProperties.columnHeaders;\r\n\r\n style.borders.top = new TablixUtils.EdgeSettings();\r\n style.borders.top.applyParams(outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n style.borders.bottom = new TablixUtils.EdgeSettings();\r\n style.borders.bottom.applyParams(outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n style.borders.left = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isFirst) { // First Column\r\n style.borders.left.applyParams(outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have left border, but values or column headers have, we need to apply padding\r\n if (!outline.showLeft(props.outline) && (outline.showLeft(propsValues.outline) || outline.showLeft(propsColumns.outline)))\r\n style.paddings.left += propsGrid.outlineWeight;\r\n\r\n } // else: do nothing\r\n\r\n style.borders.right = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isLast) { // Last Column\r\n style.borders.right.applyParams(outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have left border, but values or column headers have, we need to apply padding\r\n if (!outline.showRight(props.outline) && (outline.showRight(propsValues.outline) || outline.showRight(propsColumns.outline)))\r\n style.paddings.right += propsGrid.outlineWeight;\r\n }\r\n else {\r\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\r\n }\r\n\r\n style.fontColor = props.fontColor;\r\n style.backColor = props.backColor;\r\n\r\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\r\n }\r\n\r\n public unbindBodyCell(item: TablixUtils.TablixVisualCell, cell: controls.ITablixCell): void {\r\n TablixUtils.clearCellStyle(cell);\r\n TablixUtils.clearCellTextAndTooltip(cell);\r\n }\r\n\r\n /**\r\n * Corner Cell.\r\n */\r\n public bindCornerCell(item: any, cell: controls.ITablixCell): void {\r\n }\r\n\r\n public unbindCornerCell(item: any, cell: controls.ITablixCell): void {\r\n }\r\n\r\n public bindEmptySpaceHeaderCell(cell: controls.ITablixCell): void {\r\n // Not needed for Table\r\n }\r\n\r\n public unbindEmptySpaceHeaderCell(cell: controls.ITablixCell): void {\r\n // Not needed for Table\r\n }\r\n\r\n public bindEmptySpaceFooterCell(cell: controls.ITablixCell): void {\r\n // Not needed for Table\r\n }\r\n\r\n public unbindEmptySpaceFooterCell(cell: controls.ITablixCell): void {\r\n // Not needed for Table\r\n }\r\n\r\n /**\r\n * Measurement Helper.\r\n */\r\n public getHeaderLabel(item: DataViewMetadataColumn): string {\r\n return item.displayName;\r\n }\r\n\r\n public getCellContent(item: any): string {\r\n return item;\r\n }\r\n\r\n public hasRowGroups(): boolean {\r\n return false;\r\n }\r\n\r\n private sortIconsEnabled(): boolean {\r\n return this.options.layoutKind === controls.TablixLayoutKind.Canvas;\r\n }\r\n }\r\n\r\n export interface TableConstructorOptions {\r\n isConditionalFormattingEnabled?: boolean;\r\n isTouchEnabled?: boolean;\r\n }\r\n\r\n export class Table implements IVisual {\r\n private static preferredLoadMoreThreshold: number = 0.8;\r\n\r\n private element: JQuery;\r\n private currentViewport: IViewport;\r\n private style: IVisualStyle;\r\n private formatter: ICustomValueColumnFormatter;\r\n private isInteractive: boolean;\r\n private isTouchEnabled: boolean;\r\n private getLocalizedString: (stringId: string) => string;\r\n private hostServices: IVisualHostServices;\r\n\r\n private tablixControl: controls.TablixControl;\r\n private hierarchyNavigator: TableHierarchyNavigator;\r\n private waitingForData: boolean;\r\n private lastAllowHeaderResize: boolean;\r\n private waitingForSort: boolean;\r\n private columnWidthManager: controls.TablixColumnWidthManager;\r\n private dataView: DataView;\r\n private isConditionalFormattingEnabled: boolean;\r\n\r\n /**\r\n * Flag indicating that we are persisting objects, so that next onDataChanged can be safely ignored.\r\n */\r\n public persistingObjects: boolean;\r\n\r\n constructor(options?: TableConstructorOptions) {\r\n if (options) {\r\n this.isConditionalFormattingEnabled = options.isConditionalFormattingEnabled;\r\n this.isTouchEnabled = options.isTouchEnabled;\r\n }\r\n }\r\n\r\n public static customizeQuery(options: CustomizeQueryOptions): void {\r\n let dataViewMapping = options.dataViewMappings[0];\r\n if (!dataViewMapping || !dataViewMapping.table || !dataViewMapping.metadata)\r\n return;\r\n\r\n let dataViewTableRows: data.CompiledDataViewRoleForMapping = <data.CompiledDataViewRoleForMapping>dataViewMapping.table.rows;\r\n let objects = dataViewMapping.metadata.objects;\r\n dataViewTableRows.for.in.subtotalType = TablixObjects.shouldShowTableTotals(objects) ? data.CompiledSubtotalType.Before : data.CompiledSubtotalType.None;\r\n }\r\n\r\n public static getSortableRoles(): string[] {\r\n return ['Values'];\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.element = options.element;\r\n this.style = options.style;\r\n this.updateViewport(options.viewport);\r\n this.formatter = valueFormatter.formatValueColumn;\r\n this.isInteractive = options.interactivity && options.interactivity.selection != null;\r\n this.getLocalizedString = options.host.getLocalizedString;\r\n this.hostServices = options.host;\r\n this.persistingObjects = false;\r\n\r\n this.waitingForData = false;\r\n this.lastAllowHeaderResize = true;\r\n this.waitingForSort = false;\r\n }\r\n\r\n /**\r\n * Note: Public for testability.\r\n */\r\n public static converter(dataView: DataView): DataViewVisualTable {\r\n let table = dataView.table;\r\n debug.assertValue(table, 'table');\r\n debug.assertValue(table.rows, 'table.rows');\r\n\r\n let visualTable = Prototype.inherit<DataViewVisualTable>(table);\r\n visualTable.visualRows = [];\r\n\r\n for (let i: number = 0; i < table.rows.length; i++) {\r\n let visualRow: DataViewVisualTableRow = {\r\n index: i,\r\n values: table.rows[i]\r\n };\r\n visualTable.visualRows.push(visualRow);\r\n }\r\n visualTable.formattingProperties = TablixObjects.getTableObjects(dataView);\r\n\r\n return visualTable;\r\n }\r\n\r\n public onResizing(finalViewport: IViewport): void {\r\n this.updateViewport(finalViewport);\r\n }\r\n\r\n // Public for testability\r\n public getColumnWidthManager(): controls.TablixColumnWidthManager {\r\n return this.columnWidthManager;\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataViews = options.dataViews;\r\n\r\n if (dataViews && dataViews.length > 0) {\r\n let previousDataView = this.dataView;\r\n this.dataView = dataViews[0];\r\n\r\n /* To avoid OnDataChanged being called every time we persist Objects. If:\r\n * AutoSizeColumns options was flipped\r\n * A Column was resized manually\r\n * A Column was auto-sized\r\n */\r\n if (this.persistingObjects) {\r\n this.persistingObjects = false;\r\n return;\r\n }\r\n\r\n let visualTable = Table.converter(this.dataView);\r\n let textSize = visualTable.formattingProperties.general.textSize;\r\n\r\n if (options.operationKind === VisualDataChangeOperationKind.Append) {\r\n this.hierarchyNavigator.update(visualTable);\r\n this.tablixControl.updateModels(/*resetScrollOffsets*/false, visualTable.visualRows, visualTable.columns);\r\n this.refreshControl(/*clear*/false);\r\n } else {\r\n this.createOrUpdateHierarchyNavigator(visualTable);\r\n this.createColumnWidthManager();\r\n this.createTablixControl(textSize);\r\n let binder = <TableBinder>this.tablixControl.getBinder();\r\n binder.onDataViewChanged(visualTable);\r\n this.updateInternal(textSize, previousDataView, visualTable);\r\n }\r\n }\r\n\r\n this.waitingForData = false;\r\n this.waitingForSort = false;\r\n }\r\n\r\n private createColumnWidthManager(): void {\r\n if (!this.columnWidthManager) {\r\n this.columnWidthManager = new controls.TablixColumnWidthManager(this.dataView,\r\n false /* isMatrix */,\r\n (objectInstances: VisualObjectInstancesToPersist) => this.persistColumnWidths(objectInstances));\r\n }\r\n else {\r\n this.columnWidthManager.updateDataView(this.dataView);\r\n }\r\n }\r\n\r\n private persistColumnWidths(objectInstances: VisualObjectInstancesToPersist): void {\r\n this.persistingObjects = true;\r\n this.hostServices.persistProperties(objectInstances);\r\n }\r\n\r\n private updateViewport(newViewport: IViewport): void {\r\n this.currentViewport = newViewport;\r\n\r\n if (this.tablixControl) {\r\n this.tablixControl.viewport = this.currentViewport;\r\n this.verifyHeaderResize();\r\n this.refreshControl(false);\r\n }\r\n }\r\n\r\n private refreshControl(clear: boolean): void {\r\n if (visibilityHelper.partiallyVisible(this.element) || this.getLayoutKind() === controls.TablixLayoutKind.DashboardTile) {\r\n this.tablixControl.refresh(clear);\r\n }\r\n }\r\n\r\n private getLayoutKind(): controls.TablixLayoutKind {\r\n return this.isInteractive ? controls.TablixLayoutKind.Canvas : controls.TablixLayoutKind.DashboardTile;\r\n }\r\n\r\n private createOrUpdateHierarchyNavigator(visualTable: DataViewVisualTable): void {\r\n if (!this.tablixControl) {\r\n let dataNavigator = new TableHierarchyNavigator(visualTable, this.formatter);\r\n this.hierarchyNavigator = dataNavigator;\r\n }\r\n else {\r\n this.hierarchyNavigator.update(visualTable);\r\n }\r\n }\r\n\r\n private createTablixControl(textSize: number): void {\r\n if (!this.tablixControl) {\r\n // Create the control\r\n this.tablixControl = this.createControl(this.hierarchyNavigator, textSize);\r\n }\r\n }\r\n\r\n private createControl(dataNavigator: TableHierarchyNavigator, textSize: number): controls.TablixControl {\r\n let layoutKind = this.getLayoutKind();\r\n\r\n let tableBinderOptions: TableBinderOptions = {\r\n onBindRowHeader: (item: any) => this.onBindRowHeader(item),\r\n onColumnHeaderClick: (queryName: string, sortDirection: SortDirection) => this.onColumnHeaderClick(queryName, sortDirection),\r\n layoutKind: layoutKind\r\n };\r\n\r\n let tableBinder = new TableBinder(tableBinderOptions);\r\n let layoutManager: controls.internal.TablixLayoutManager = layoutKind === controls.TablixLayoutKind.DashboardTile\r\n ? controls.internal.DashboardTablixLayoutManager.createLayoutManager(tableBinder)\r\n : controls.internal.CanvasTablixLayoutManager.createLayoutManager(tableBinder, this.columnWidthManager);\r\n\r\n // Create Host element\r\n let tablixContainer = document.createElement('div');\r\n this.element.append(tablixContainer);\r\n\r\n let tablixOptions: controls.TablixOptions = {\r\n interactive: this.isInteractive,\r\n enableTouchSupport: this.isTouchEnabled,\r\n layoutKind: layoutKind,\r\n fontSize: TablixObjects.getTextSizeInPx(textSize),\r\n };\r\n\r\n return new controls.TablixControl(dataNavigator, layoutManager, tableBinder, tablixContainer, tablixOptions);\r\n }\r\n\r\n private updateInternal(textSize: number, previousDataView: DataView, visualTable: DataViewVisualTable) {\r\n if (this.getLayoutKind() === controls.TablixLayoutKind.DashboardTile) {\r\n this.tablixControl.layoutManager.adjustContentSize(converterHelper.hasImageUrlColumn(this.dataView));\r\n }\r\n\r\n this.tablixControl.fontSize = TablixObjects.getTextSizeInPx(textSize);\r\n this.verifyHeaderResize();\r\n\r\n // Update models before the viewport to make sure column widths are computed correctly\r\n this.tablixControl.updateModels(/*resetScrollOffsets*/true, visualTable.visualRows, visualTable.columns);\r\n\r\n let totals = this.createTotalsRow(this.dataView);\r\n this.tablixControl.rowDimension.setFooter(totals);\r\n\r\n this.tablixControl.viewport = this.currentViewport;\r\n let shouldClearControl = this.shouldClearControl(previousDataView, this.dataView);\r\n\r\n // Render\r\n // We need the layout for the DIV to be done so that the control can measure items correctly.\r\n setTimeout(() => {\r\n // Render\r\n this.refreshControl(shouldClearControl);\r\n\r\n //Persist actual widths if autoSize flipped to true\r\n if (this.columnWidthManager.shouldPersistAllColumnWidths()) {\r\n this.columnWidthManager.persistAllColumnWidths(this.tablixControl.layoutManager.columnWidthsToPersist);\r\n }\r\n }, 0);\r\n }\r\n\r\n private shouldClearControl(previousDataView: DataView, newDataView: DataView) {\r\n if (!this.waitingForSort || !previousDataView || !newDataView)\r\n return true;\r\n\r\n return !DataViewAnalysis.isMetadataEquivalent(previousDataView.metadata, newDataView.metadata);\r\n }\r\n\r\n private createTotalsRow(dataView: DataView): TableTotal {\r\n if (!TablixObjects.shouldShowTableTotals(dataView.metadata.objects))\r\n return null;\r\n\r\n let totals = dataView.table.totals;\r\n if (!totals || totals.length === 0)\r\n return null;\r\n\r\n let totalRow: any[] = [];\r\n let columns = dataView.table.columns;\r\n\r\n // Add totals for measure columns, blank for non-measure columns unless it's the first column\r\n for (let i = 0, len = columns.length; i < len; ++i) {\r\n let column = columns[i];\r\n\r\n let totalValue = totals[column.index];\r\n if (totalValue != null) {\r\n totalRow.push(totalValue);\r\n }\r\n else {\r\n // If the first column is a non-measure column, we put 'Total' as the text similar to PV.\r\n // Note that if the first column is a measure column we don't render any Total text at\r\n // all, once again similar to PV.\r\n totalRow.push((i === 0) ? this.getLocalizedString('TableTotalLabel') : '');\r\n }\r\n }\r\n\r\n return <TableTotal>{ totalCells: totalRow };\r\n }\r\n\r\n private onBindRowHeader(item: any): void {\r\n if (this.needsMoreData(item)) {\r\n this.hostServices.loadMoreData();\r\n this.waitingForData = true;\r\n }\r\n }\r\n\r\n private onColumnHeaderClick(queryName: string, sortDirection: SortDirection): void {\r\n this.waitingForSort = true;\r\n this.hostServices.onCustomSort(TablixUtils.getCustomSortEventArgs(queryName, sortDirection));\r\n }\r\n\r\n /**\r\n * Note: Public for testability.\r\n */\r\n public needsMoreData(item: any): boolean {\r\n if (this.waitingForData || !this.dataView.metadata || !this.dataView.metadata.segment)\r\n return false;\r\n\r\n let leafCount = this.tablixControl.rowDimension.getItemsCount();\r\n let loadMoreThreshold = leafCount * Table.preferredLoadMoreThreshold;\r\n\r\n return this.hierarchyNavigator.getIndex(item) >= loadMoreThreshold;\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n\r\n // Visuals are initialized with an empty data view before queries are run, therefore we need to make sure that\r\n // we are resilient here when we do not have data view.\r\n if (this.dataView) {\r\n TablixObjects.enumerateObjectInstances(options, enumeration, this.dataView, controls.TablixType.Table);\r\n }\r\n\r\n return enumeration.complete();\r\n }\r\n\r\n public enumerateObjectRepetition(): VisualObjectRepetition[] {\r\n let enumeration: VisualObjectRepetition[] = [];\r\n\r\n // Visuals are initialized with an empty data view before queries are run, therefore we need to make sure that\r\n // we are resilient here when we do not have data view.\r\n if (this.isConditionalFormattingEnabled && this.dataView) {\r\n TablixObjects.enumerateObjectRepetition(enumeration, this.dataView, controls.TablixType.Table);\r\n }\r\n\r\n return enumeration;\r\n }\r\n\r\n private shouldAllowHeaderResize(): boolean {\r\n return this.hostServices.getViewMode() === ViewMode.Edit;\r\n }\r\n\r\n public onViewModeChanged(viewMode: ViewMode): void {\r\n /* Refreshes the column headers to enable/disable Column resizing */\r\n this.updateViewport(this.currentViewport);\r\n }\r\n\r\n private verifyHeaderResize() {\r\n let currentAllowHeaderResize = this.shouldAllowHeaderResize();\r\n if (currentAllowHeaderResize !== this.lastAllowHeaderResize) {\r\n this.lastAllowHeaderResize = currentAllowHeaderResize;\r\n this.tablixControl.layoutManager.setAllowHeaderResize(currentAllowHeaderResize);\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n import TablixFormattingPropertiesMatrix = powerbi.visuals.controls.TablixFormattingPropertiesMatrix;\r\n import TablixUtils = controls.internal.TablixUtils;\r\n import TablixObjects = controls.internal.TablixObjects;\r\n import UrlUtils = jsCommon.UrlUtils;\r\n\r\n /**\r\n * Extension of the Matrix node for Matrix visual.\r\n */\r\n\r\n export interface MatrixVisualNode extends DataViewMatrixNode {\r\n /**\r\n * Index of the node in its parent's children collection.\r\n * \r\n * Note: For size optimization, we could also look this item up in the parent's \r\n * children collection, but we may need to pay the perf penalty.\r\n */\r\n index?: number;\r\n\r\n /**\r\n * Global index of the node as a leaf node.\r\n * If the node is not a leaf, the value is undefined.\r\n */\r\n leafIndex?: number;\r\n\r\n /**\r\n * Parent of the node.\r\n * Undefined for outermost nodes (children of the one root node).\r\n */\r\n parent?: MatrixVisualNode;\r\n\r\n /**\r\n * Children of the same parent\r\n */\r\n siblings?: MatrixVisualNode[];\r\n\r\n /**\r\n * queryName of the node.\r\n * If the node is not a leaf, the value is undefined.\r\n */\r\n queryName?: string;\r\n }\r\n\r\n export interface MatrixCornerItem {\r\n metadata: DataViewMetadataColumn;\r\n isColumnHeaderLeaf: boolean;\r\n isRowHeaderLeaf: boolean;\r\n }\r\n\r\n export class MatrixVisualBodyItem extends TablixUtils.TablixVisualCell {\r\n public get isMeasure(): boolean {\r\n return true;\r\n };\r\n\r\n public get isValidUrl(): boolean {\r\n return false;\r\n };\r\n\r\n public get isValidImage(): boolean {\r\n return false;\r\n };\r\n }\r\n \r\n /**\r\n * Interface for refreshing Matrix Data View.\r\n */\r\n export interface MatrixDataAdapter {\r\n update(dataViewMatrix?: DataViewMatrix, updateColumns?: boolean): void;\r\n }\r\n\r\n export interface IMatrixHierarchyNavigator extends controls.ITablixHierarchyNavigator, MatrixDataAdapter {\r\n getDataViewMatrix(): DataViewMatrix;\r\n getLeafCount(hierarchy: MatrixVisualNode[]): number;\r\n getLeafAt(hierarchy: MatrixVisualNode[], index: number): any;\r\n getLeafIndex(item: MatrixVisualNode): number;\r\n getParent(item: MatrixVisualNode): MatrixVisualNode;\r\n getIndex(item: MatrixVisualNode): number;\r\n isLeaf(item: MatrixVisualNode): boolean;\r\n isRowHierarchyLeaf(item: any): boolean;\r\n isColumnHierarchyLeaf(item: any): boolean;\r\n isLastItem(item: MatrixVisualNode, items: MatrixVisualNode[]): boolean;\r\n getChildren(item: MatrixVisualNode): MatrixVisualNode[];\r\n getCount(items: MatrixVisualNode[]): number;\r\n getAt(items: MatrixVisualNode[], index: number): MatrixVisualNode;\r\n getLevel(item: MatrixVisualNode): number;\r\n getIntersection(rowItem: MatrixVisualNode, columnItem: MatrixVisualNode): MatrixVisualBodyItem;\r\n getCorner(rowLevel: number, columnLevel: number): MatrixCornerItem;\r\n headerItemEquals(item1: MatrixVisualNode, item2: MatrixVisualNode): boolean;\r\n }\r\n\r\n interface MatrixHierarchy extends DataViewHierarchy {\r\n leafNodes?: MatrixVisualNode[];\r\n }\r\n \r\n /**\r\n * Factory method used by unit tests.\r\n */\r\n export function createMatrixHierarchyNavigator(matrix: DataViewMatrix, formatter: ICustomValueColumnFormatter): IMatrixHierarchyNavigator {\r\n return new MatrixHierarchyNavigator(matrix, formatter);\r\n }\r\n\r\n class MatrixHierarchyNavigator implements IMatrixHierarchyNavigator {\r\n private matrix: DataViewMatrix;\r\n private rowHierarchy: MatrixHierarchy;\r\n private columnHierarchy: MatrixHierarchy;\r\n private formatter: ICustomValueColumnFormatter;\r\n\r\n constructor(matrix: DataViewMatrix, formatter: ICustomValueColumnFormatter) {\r\n this.matrix = matrix;\r\n this.rowHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(matrix.rows);\r\n this.columnHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(matrix.columns);\r\n this.formatter = formatter;\r\n\r\n this.update();\r\n }\r\n \r\n /**\r\n * Returns the data view matrix.\r\n */\r\n public getDataViewMatrix(): DataViewMatrix {\r\n return this.matrix;\r\n }\r\n /**\r\n * Returns the depth of the column hierarchy.\r\n */\r\n public getColumnHierarchyDepth(): number {\r\n return Math.max(this.columnHierarchy.levels.length, 1);\r\n }\r\n\r\n /**\r\n * Returns the depth of the Row hierarchy.\r\n */\r\n public getRowHierarchyDepth(): number {\r\n return Math.max(this.rowHierarchy.levels.length, 1);\r\n }\r\n \r\n /**\r\n * Returns the leaf count of a hierarchy.\r\n */\r\n public getLeafCount(hierarchy: MatrixVisualNode[]): number {\r\n let matrixHierarchy = this.getMatrixHierarchy(hierarchy);\r\n if (matrixHierarchy)\r\n return matrixHierarchy.leafNodes.length;\r\n\r\n return 0;\r\n }\r\n \r\n /**\r\n * Returns the leaf member of a hierarchy at a specified index.\r\n */\r\n public getLeafAt(hierarchy: MatrixVisualNode[], index: number): MatrixVisualNode {\r\n let matrixHierarchy = this.getMatrixHierarchy(hierarchy);\r\n if (matrixHierarchy)\r\n return matrixHierarchy.leafNodes[index];\r\n\r\n return null;\r\n }\r\n \r\n /**\r\n * Returns the leaf index of the visual node.\r\n */\r\n public getLeafIndex(item: MatrixVisualNode): number {\r\n debug.assertValue(item, 'item');\r\n\r\n return item.leafIndex;\r\n }\r\n \r\n /**\r\n * Returns the specified hierarchy member parent.\r\n */\r\n public getParent(item: MatrixVisualNode): MatrixVisualNode {\r\n debug.assertValue(item, 'item');\r\n\r\n // Return null for outermost nodes\r\n if (item.level === 0)\r\n return null;\r\n\r\n return item.parent;\r\n }\r\n \r\n /**\r\n * Returns the index of the hierarchy member relative to its parent.\r\n */\r\n public getIndex(item: MatrixVisualNode): number {\r\n debug.assertValue(item, 'item');\r\n\r\n return item.index;\r\n }\r\n \r\n /**\r\n * Checks whether a hierarchy member is a leaf.\r\n */\r\n public isLeaf(item: MatrixVisualNode): boolean {\r\n debug.assertValue(item, 'item');\r\n\r\n return !item.children || item.children.length === 0;\r\n }\r\n\r\n public isRowHierarchyLeaf(item: MatrixCornerItem): boolean {\r\n return true;\r\n }\r\n\r\n public isColumnHierarchyLeaf(item: MatrixCornerItem): boolean {\r\n return false;\r\n }\r\n\r\n public isFirstItem(item: MatrixVisualNode, items: MatrixVisualNode[]): boolean {\r\n return item === _.first(items);\r\n }\r\n\r\n public areAllParentsFirst(item: MatrixVisualNode, items: MatrixVisualNode[]): boolean {\r\n if (!item)\r\n return false;\r\n\r\n let parent = this.getParent(item);\r\n if (!parent) {\r\n return this.isFirstItem(item, item.siblings);\r\n }\r\n else {\r\n return this.isFirstItem(item, item.siblings) && this.areAllParentsFirst(parent, parent.siblings);\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether a hierarchy member is the last item within its parent. \r\n */\r\n public isLastItem(item: MatrixVisualNode, items: MatrixVisualNode[]): boolean {\r\n debug.assertValue(item, 'item');\r\n\r\n return item === _.last(items);\r\n }\r\n\r\n public areAllParentsLast(item: MatrixVisualNode, items: MatrixVisualNode[]): boolean {\r\n if (!item)\r\n return false;\r\n\r\n let parent = this.getParent(item);\r\n if (!parent) {\r\n return this.isLastItem(item, item.siblings);\r\n }\r\n else {\r\n return this.isLastItem(item, item.siblings) && this.areAllParentsLast(parent, parent.siblings);\r\n }\r\n }\r\n \r\n /**\r\n * Gets the children members of a hierarchy member.\r\n */\r\n public getChildren(item: MatrixVisualNode): MatrixVisualNode[] {\r\n debug.assertValue(item, 'item');\r\n\r\n return item.children;\r\n }\r\n \r\n /**\r\n * Gets the difference between current level and highest child's level. Can be > 1 if there are multiple values\r\n * @param {MatrixVisualNode} item\r\n * @returns\r\n */\r\n public getChildrenLevelDifference(item: MatrixVisualNode): number {\r\n let diff = Infinity;\r\n let children = this.getChildren(item);\r\n for (let i = 0, ilen = children.length; i < ilen; i++) {\r\n diff = Math.min(diff, children[i].level - item.level);\r\n }\r\n\r\n return diff;\r\n }\r\n \r\n /**\r\n * Gets the members count in a specified collection.\r\n */\r\n public getCount(items: MatrixVisualNode[]): number {\r\n debug.assertValue(items, 'items');\r\n\r\n return items.length;\r\n }\r\n \r\n /**\r\n * Gets the member at the specified index.\r\n */\r\n public getAt(items: MatrixVisualNode[], index: number): MatrixVisualNode {\r\n debug.assertValue(items, 'items');\r\n\r\n return items[index];\r\n }\r\n \r\n /**\r\n * Gets the hierarchy member level.\r\n */\r\n public getLevel(item: MatrixVisualNode): number {\r\n debug.assertValue(item, 'item');\r\n\r\n return item.level;\r\n }\r\n \r\n /**\r\n * Returns the intersection between a row and a column item.\r\n */\r\n public getIntersection(rowItem: MatrixVisualNode, columnItem: MatrixVisualNode): MatrixVisualBodyItem {\r\n debug.assertValue(rowItem, 'rowItem');\r\n debug.assertValue(columnItem, 'columnItem');\r\n let isSubtotalItem = rowItem.isSubtotal === true || columnItem.isSubtotal === true;\r\n\r\n let node: DataViewMatrixNodeValue;\r\n let valueSource: DataViewMetadataColumn;\r\n let rowIndex: number = rowItem.leafIndex;\r\n let colIndex: number = columnItem.leafIndex;\r\n let bodyCell: MatrixVisualBodyItem;\r\n\r\n if (!rowItem.values) {\r\n node = undefined;\r\n }\r\n else {\r\n node = <DataViewMatrixNodeValue>(rowItem.values[columnItem.leafIndex]);\r\n }\r\n\r\n if (node) {\r\n valueSource = this.matrix.valueSources[node.valueSourceIndex || 0];\r\n bodyCell = new MatrixVisualBodyItem(node.value, isSubtotalItem, valueSource, this.formatter);\r\n }\r\n else {\r\n bodyCell = new MatrixVisualBodyItem(undefined, isSubtotalItem, undefined, this.formatter);\r\n }\r\n\r\n bodyCell.position.row.index = rowIndex;\r\n bodyCell.position.row.indexInSiblings = rowItem.siblings.indexOf(rowItem);\r\n bodyCell.position.row.isFirst = rowIndex === 0;\r\n bodyCell.position.row.isLast = rowIndex === this.rowHierarchy.leafNodes.length - 1;\r\n bodyCell.position.column.index = colIndex;\r\n bodyCell.position.column.indexInSiblings = columnItem.siblings.indexOf(columnItem);\r\n bodyCell.position.column.isFirst = colIndex === 0;\r\n bodyCell.position.column.isLast = colIndex === this.columnHierarchy.leafNodes.length - 1;\r\n\r\n return bodyCell;\r\n }\r\n \r\n /**\r\n * Returns the corner cell between a row and a column level.\r\n */\r\n public getCorner(rowLevel: number, columnLevel: number): MatrixCornerItem {\r\n debug.assert(rowLevel >= 0, 'rowLevel');\r\n debug.assert(columnLevel >= 0, 'columnLevel');\r\n\r\n let columnLevels = this.columnHierarchy.levels;\r\n let rowLevels = this.rowHierarchy.levels;\r\n\r\n if (columnLevel === columnLevels.length - 1 || columnLevels.length === 0) {\r\n let levelSource = rowLevels[rowLevel];\r\n if (levelSource)\r\n return {\r\n metadata: levelSource.sources[0],\r\n isColumnHeaderLeaf: true,\r\n isRowHeaderLeaf: rowLevel === rowLevels.length - 1,\r\n };\r\n }\r\n\r\n if (rowLevel === rowLevels.length - 1) {\r\n let levelSource = columnLevels[columnLevel];\r\n if (levelSource)\r\n return {\r\n metadata: levelSource.sources[0],\r\n isColumnHeaderLeaf: false,\r\n isRowHeaderLeaf: true,\r\n };\r\n }\r\n\r\n return {\r\n metadata: null,\r\n isColumnHeaderLeaf: false,\r\n isRowHeaderLeaf: false,\r\n };\r\n }\r\n\r\n public headerItemEquals(item1: MatrixVisualNode, item2: MatrixVisualNode): boolean {\r\n if (item1 && item2)\r\n return (item1 === item2);\r\n else\r\n return false;\r\n }\r\n\r\n public bodyCellItemEquals(item1: MatrixVisualBodyItem, item2: MatrixVisualBodyItem): boolean {\r\n return (item1.position.isMatch(item2.position));\r\n }\r\n\r\n public cornerCellItemEquals(item1: any, item2: any): boolean {\r\n return item1 === item2;\r\n }\r\n\r\n public getMatrixColumnHierarchy(): MatrixHierarchy {\r\n return this.columnHierarchy;\r\n }\r\n\r\n public getMatrixRowHierarchy(): MatrixHierarchy {\r\n return this.rowHierarchy;\r\n }\r\n \r\n /**\r\n * Implementation for MatrixDataAdapter interface.\r\n */\r\n public update(dataViewMatrix?: DataViewMatrix, updateColumns: boolean = true): void {\r\n if (dataViewMatrix) {\r\n this.matrix = dataViewMatrix;\r\n this.rowHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(dataViewMatrix.rows);\r\n if (updateColumns)\r\n this.columnHierarchy = MatrixHierarchyNavigator.wrapMatrixHierarchy(dataViewMatrix.columns);\r\n }\r\n this.updateHierarchy(this.rowHierarchy);\r\n if (updateColumns) {\r\n this.updateHierarchy(this.columnHierarchy);\r\n MatrixHierarchyNavigator.updateStaticColumnHeaders(this.columnHierarchy);\r\n }\r\n }\r\n\r\n private static wrapMatrixHierarchy(hierarchy: DataViewHierarchy): MatrixHierarchy {\r\n let matrixHierarchy = Prototype.inherit<MatrixHierarchy>(hierarchy);\r\n matrixHierarchy.leafNodes = [];\r\n\r\n return matrixHierarchy;\r\n }\r\n\r\n private updateHierarchy(hierarchy: MatrixHierarchy): void {\r\n if (hierarchy.leafNodes.length > 0)\r\n hierarchy.leafNodes.length = 0;\r\n\r\n if (hierarchy.root.children)\r\n this.updateRecursive(hierarchy, hierarchy.root.children, null, hierarchy.leafNodes);\r\n }\r\n\r\n private updateRecursive(hierarchy: MatrixHierarchy, nodes: MatrixVisualNode[], parent: MatrixVisualNode, cache: MatrixVisualNode[]): void {\r\n let level: DataViewHierarchyLevel;\r\n for (let i = 0, ilen = nodes.length; i < ilen; i++) {\r\n let node = nodes[i];\r\n node.siblings = nodes;\r\n\r\n if (parent)\r\n node.parent = parent;\r\n\r\n if (!level)\r\n level = hierarchy.levels[node.level];\r\n\r\n if (level) {\r\n let source = level.sources[node.levelSourceIndex ? node.levelSourceIndex : 0];\r\n let formatString = valueFormatter.getFormatString(source, TablixObjects.PropColumnFormatString.getPropertyID());\r\n if (formatString)\r\n node.name = this.formatter(node.value, source, TablixObjects.PropColumnFormatString.getPropertyID());\r\n node.queryName = source.queryName;\r\n }\r\n\r\n node.index = i;\r\n if (node.children && node.children.length > 0) {\r\n this.updateRecursive(hierarchy, node.children, node, cache);\r\n }\r\n else {\r\n node.leafIndex = cache.length;\r\n cache.push(node);\r\n }\r\n }\r\n }\r\n\r\n private static updateStaticColumnHeaders(columnHierarchy: MatrixHierarchy): void {\r\n let columnLeafNodes = columnHierarchy.leafNodes;\r\n if (columnLeafNodes && columnLeafNodes.length > 0) {\r\n let columnLeafSources = columnHierarchy.levels[columnLeafNodes[0].level].sources;\r\n\r\n for (let i = 0, ilen = columnLeafNodes.length; i < ilen; i++) {\r\n let columnLeafNode = columnLeafNodes[i];\r\n\r\n // Static leaf may need to get label from it's definition\r\n if (!columnLeafNode.identity && columnLeafNode.value === undefined) {\r\n // We make distincion between null and undefined. Null can be considered as legit value, undefined means we need to fall back to metadata\r\n let source = columnLeafSources[columnLeafNode.levelSourceIndex ? columnLeafNode.levelSourceIndex : 0];\r\n if (source)\r\n columnLeafNode.name = source.displayName;\r\n }\r\n }\r\n }\r\n }\r\n\r\n private getMatrixHierarchy(rootNodes: MatrixVisualNode[]): MatrixHierarchy {\r\n let rowHierarchyRootNodes = this.rowHierarchy.root.children;\r\n if (rowHierarchyRootNodes && rootNodes === rowHierarchyRootNodes)\r\n return this.rowHierarchy;\r\n\r\n let columnHierarchyRootNodes = this.columnHierarchy.root.children;\r\n if (columnHierarchyRootNodes && rootNodes === columnHierarchyRootNodes)\r\n return this.columnHierarchy;\r\n\r\n return null;\r\n }\r\n }\r\n\r\n export interface MatrixBinderOptions {\r\n onBindRowHeader?(item: MatrixVisualNode): void;\r\n totalLabel?: string;\r\n onColumnHeaderClick?(queryName: string, sortDirection: SortDirection): void;\r\n showSortIcons?: boolean;\r\n }\r\n\r\n export class MatrixBinder implements controls.ITablixBinder {\r\n private formattingProperties: TablixFormattingPropertiesMatrix;\r\n private hierarchyNavigator: IMatrixHierarchyNavigator;\r\n private options: MatrixBinderOptions;\r\n\r\n private textHeightHeader: number;\r\n private textHeightValue: number;\r\n private textHeightTotal: number;\r\n\r\n constructor(hierarchyNavigator: IMatrixHierarchyNavigator, options: MatrixBinderOptions) {\r\n\r\n // We pass the hierarchy navigator in here because it is the object that will\r\n // survive data changes and gets updated with the latest data view.\r\n this.hierarchyNavigator = hierarchyNavigator;\r\n this.options = options;\r\n }\r\n\r\n public onDataViewChanged(formattingProperties: TablixFormattingPropertiesMatrix): void {\r\n this.formattingProperties = formattingProperties;\r\n this.updateTextHeights();\r\n }\r\n\r\n private updateTextHeights(): void {\r\n let textProps: TextProperties = {\r\n fontFamily: '',\r\n fontSize: TablixObjects.getTextSizeInPx(this.formattingProperties.general.textSize),\r\n text: 'a',\r\n };\r\n\r\n textProps.fontFamily = TablixUtils.FontFamilyHeader;\r\n this.textHeightHeader = Math.ceil(TextMeasurementService.measureSvgTextHeight(textProps));\r\n\r\n textProps.fontFamily = TablixUtils.FontFamilyCell;\r\n this.textHeightValue = Math.ceil(TextMeasurementService.measureSvgTextHeight(textProps));\r\n\r\n textProps.fontFamily = TablixUtils.FontFamilyTotal;\r\n this.textHeightTotal = Math.ceil(TextMeasurementService.measureSvgTextHeight(textProps));\r\n }\r\n\r\n public onStartRenderingSession(): void {\r\n }\r\n\r\n public onEndRenderingSession(): void {\r\n }\r\n \r\n /**\r\n * Row Header.\r\n */\r\n public bindRowHeader(item: MatrixVisualNode, cell: controls.ITablixCell): void {\r\n TablixUtils.resetCellCssClass(cell);\r\n\r\n let cellStyle = new TablixUtils.CellStyle();\r\n\r\n let isLeaf = this.hierarchyNavigator && this.hierarchyNavigator.isLeaf(item);\r\n if (isLeaf) {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassMatrixRowHeaderLeaf);\r\n cellStyle.borders.right = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\r\n }\r\n\r\n if (item.isSubtotal) {\r\n cellStyle.paddings.left = TablixUtils.CellPaddingLeftMatrixTotal;\r\n }\r\n\r\n this.bindHeader(item, cell, this.getRowHeaderMetadata(item), cellStyle);\r\n\r\n if (this.options.onBindRowHeader)\r\n this.options.onBindRowHeader(item);\r\n\r\n this.setRowHeaderStyle(cell, cellStyle);\r\n\r\n cell.applyStyle(cellStyle);\r\n }\r\n\r\n private setRowHeaderStyle(cell: controls.ITablixCell, style: TablixUtils.CellStyle): void {\r\n let propsGrid = this.formattingProperties.grid;\r\n let props = this.formattingProperties.rowHeaders;\r\n let propsValues = this.formattingProperties.values;\r\n let propsCols = this.formattingProperties.columnHeaders;\r\n\r\n style.borders.top = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isFirst) {\r\n style.borders.top.applyParams(outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have top border, but Values have, we need to apply extra padding\r\n if (!outline.showTop(props.outline) && outline.showTop(propsValues.outline))\r\n style.paddings.top += propsGrid.outlineWeight;\r\n } // else: do nothing\r\n\r\n style.borders.bottom = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isLast) {\r\n style.borders.bottom.applyParams(outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have bottom border, but Values have, we need to apply extra padding\r\n if (!outline.showBottom(props.outline) && outline.showBottom(propsValues.outline))\r\n style.paddings.bottom += propsGrid.outlineWeight;\r\n }\r\n else {\r\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\r\n }\r\n\r\n style.borders.left = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isFirst) {\r\n style.borders.left.applyParams(outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have left border, but Column Headers have, we need to apply extra padding\r\n if (!outline.showLeft(props.outline) && outline.showLeft(propsCols.outline))\r\n style.paddings.left += propsGrid.outlineWeight;\r\n } // else: do nothing\r\n\r\n style.borders.right = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isLast) {\r\n style.borders.right.applyParams(outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n }\r\n else {\r\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\r\n }\r\n\r\n style.fontColor = props.fontColor;\r\n style.backColor = props.backColor;\r\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\r\n }\r\n\r\n public unbindRowHeader(item: any, cell: controls.ITablixCell): void {\r\n TablixUtils.clearCellStyle(cell);\r\n TablixUtils.clearCellTextAndTooltip(cell);\r\n }\r\n \r\n /**\r\n * Column Header.\r\n */\r\n public bindColumnHeader(item: MatrixVisualNode, cell: controls.ITablixCell): void {\r\n TablixUtils.resetCellCssClass(cell);\r\n\r\n // Set default style\r\n let cellStyle = new TablixUtils.CellStyle();\r\n\r\n let overwriteTotalLabel = false;\r\n\r\n let isLeaf = this.hierarchyNavigator && this.hierarchyNavigator.isLeaf(item);\r\n if (isLeaf) {\r\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\r\n\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixColumnHeaderLeaf);\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueNumeric);\r\n\r\n let sortableHeaderColumnMetadata = this.getSortableHeaderColumnMetadata(item);\r\n if (sortableHeaderColumnMetadata && this.options.showSortIcons) {\r\n this.registerColumnHeaderClickHandler(sortableHeaderColumnMetadata, cell);\r\n TablixUtils.createColumnHeaderWithSortIcon(sortableHeaderColumnMetadata, cell);\r\n }\r\n\r\n // Overwrite only if the there are subtotal siblings (like in the multimeasure case), which means ALL siblings are subtotals.\r\n if (item.isSubtotal && item.parent && item.parent.children.length > 1 && (<MatrixVisualNode>item.parent.children[0]).isSubtotal)\r\n overwriteTotalLabel = true;\r\n }\r\n\r\n cell.extension.disableDragResize();\r\n this.bindHeader(item, cell, this.getColumnHeaderMetadata(item), cellStyle, overwriteTotalLabel);\r\n\r\n this.setColumnHeaderStyle(cell, cellStyle);\r\n\r\n cell.applyStyle(cellStyle);\r\n }\r\n\r\n private setColumnHeaderStyle(cell: controls.ITablixCell, style: TablixUtils.CellStyle): void {\r\n let propsGrid = this.formattingProperties.grid;\r\n let props = this.formattingProperties.columnHeaders;\r\n let propsValues = this.formattingProperties.values;\r\n\r\n style.fontColor = props.fontColor;\r\n style.backColor = props.backColor;\r\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\r\n\r\n style.borders.top = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isFirst) {\r\n style.borders.top.applyParams(outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n } // else: do nothing\r\n\r\n style.borders.bottom = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isLast) {\r\n style.borders.bottom.applyParams(outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n }\r\n else {\r\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\r\n }\r\n\r\n style.borders.left = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isFirst) {\r\n // If we dont have left border, but Values have, we need to apply extra padding\r\n if (!outline.showLeft(props.outline) && outline.showLeft(propsValues.outline))\r\n style.paddings.left += propsGrid.outlineWeight;\r\n }\r\n\r\n style.borders.right = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isLast) {\r\n style.borders.right.applyParams(outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have right border, but Values have, we need to apply extra padding\r\n if (!outline.showRight(props.outline) && outline.showRight(propsValues.outline))\r\n style.paddings.right += propsGrid.outlineWeight;\r\n }\r\n else {\r\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\r\n }\r\n }\r\n\r\n public unbindColumnHeader(item: MatrixVisualNode, cell: controls.ITablixCell): void {\r\n TablixUtils.clearCellStyle(cell);\r\n TablixUtils.clearCellTextAndTooltip(cell);\r\n\r\n let sortableHeaderColumnMetadata = this.getSortableHeaderColumnMetadata(item);\r\n if (sortableHeaderColumnMetadata) {\r\n this.unregisterColumnHeaderClickHandler(cell);\r\n }\r\n\r\n if (this.options.showSortIcons)\r\n TablixUtils.removeSortIcons(cell);\r\n }\r\n\r\n private bindHeader(item: MatrixVisualNode, cell: controls.ITablixCell, metadata: DataViewMetadataColumn, style: TablixUtils.CellStyle, overwriteSubtotalLabel?: boolean): void {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixHeader);\r\n\r\n style.fontFamily = TablixUtils.FontFamilyHeader;\r\n style.fontColor = TablixUtils.FontColorHeaders;\r\n\r\n let imgHeight = this.formattingProperties.grid.imageHeight;\r\n\r\n if (converterHelper.isImageUrlColumn(metadata))\r\n cell.contentHeight = imgHeight;\r\n else if (item.isSubtotal)\r\n cell.contentHeight = this.textHeightTotal;\r\n else\r\n cell.contentHeight = this.textHeightValue;\r\n\r\n if (item.isSubtotal) {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueTotal);\r\n style.fontFamily = TablixUtils.FontFamilyTotal;\r\n\r\n if (!overwriteSubtotalLabel) {\r\n TablixUtils.setCellTextAndTooltip(cell, this.options.totalLabel);\r\n return;\r\n }\r\n }\r\n\r\n let value = MatrixBinder.getNodeLabel(item);\r\n if (!value) {\r\n // just to maintain the height of the row in case all realized cells are nulls\r\n cell.extension.contentHost.innerHTML = TablixUtils.StringNonBreakingSpace;\r\n }\r\n else if (converterHelper.isWebUrlColumn(metadata) && UrlUtils.isValidUrl(value)) {\r\n TablixUtils.appendATagToBodyCell(item.value, cell);\r\n }\r\n else if (converterHelper.isImageUrlColumn(metadata)) {\r\n style.hasImage = true;\r\n\r\n if (UrlUtils.isValidImageUrl(value)) {\r\n TablixUtils.appendImgTagToBodyCell(item.value, cell, imgHeight);\r\n }\r\n else {\r\n TablixUtils.setCellTextAndTooltip(cell, value);\r\n }\r\n }\r\n else {\r\n TablixUtils.setCellTextAndTooltip(cell, value);\r\n }\r\n }\r\n\r\n private registerColumnHeaderClickHandler(columnMetadata: DataViewMetadataColumn, cell: controls.ITablixCell): void {\r\n if (this.options.onColumnHeaderClick) {\r\n let handler = (e: MouseEvent) => {\r\n if (TablixUtils.isValidSortClick(e)) {\r\n let sortDirection: SortDirection = TablixUtils.reverseSort(columnMetadata.sort);\r\n this.options.onColumnHeaderClick(columnMetadata.queryName ? columnMetadata.queryName : columnMetadata.displayName, sortDirection);\r\n }\r\n };\r\n cell.extension.registerClickHandler(handler);\r\n }\r\n }\r\n\r\n private unregisterColumnHeaderClickHandler(cell: controls.ITablixCell) {\r\n if (this.options.onColumnHeaderClick) {\r\n cell.extension.unregisterClickHandler();\r\n }\r\n }\r\n\r\n /**\r\n * Body Cell.\r\n */\r\n public bindBodyCell(item: MatrixVisualBodyItem, cell: controls.ITablixCell): void {\r\n TablixUtils.resetCellCssClass(cell);\r\n\r\n let cellStyle = new TablixUtils.CellStyle();\r\n\r\n cell.contentHeight = this.textHeightValue;\r\n\r\n if (item.domContent) {\r\n $(cell.extension.contentHost).append(item.domContent);\r\n }\r\n else\r\n {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueNumeric);\r\n if (item.isTotal) {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixValueTotal);\r\n cellStyle.fontFamily = TablixUtils.FontFamilyTotal;\r\n cell.contentHeight = this.textHeightTotal;\r\n }\r\n\r\n if (item.textContent) {\r\n TablixUtils.setCellTextAndTooltip(cell, item.textContent);\r\n }\r\n }\r\n\r\n this.setBodyCellStyle(cell, item, cellStyle);\r\n cell.applyStyle(cellStyle);\r\n }\r\n\r\n private setBodyCellStyle(cell: controls.ITablixCell, item: MatrixVisualBodyItem, style: TablixUtils.CellStyle): void {\r\n let propsGrid = this.formattingProperties.grid;\r\n let props = this.formattingProperties.values;\r\n let propsTotal = this.formattingProperties.subtotals;\r\n let propsRows = this.formattingProperties.rowHeaders;\r\n let propsColumns = this.formattingProperties.columnHeaders;\r\n\r\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\r\n\r\n style.borders.top = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isFirst) { // First Row\r\n style.borders.top.applyParams(outline.showTop(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have top border, but Row Headers have, we need to apply extra padding\r\n if (!outline.showTop(props.outline) && outline.showTop(propsRows.outline))\r\n style.paddings.top += propsGrid.outlineWeight;\r\n\r\n } // else: do nothing\r\n\r\n style.borders.bottom = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isLast) { // Last Row\r\n style.borders.bottom.applyParams(outline.showBottom(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have bottom border, but Row Headers have, we need to apply extra padding\r\n if (!outline.showBottom(props.outline) && outline.showBottom(propsRows.outline))\r\n style.paddings.bottom += propsGrid.outlineWeight;\r\n }\r\n else {\r\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\r\n }\r\n\r\n style.borders.left = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isFirst) { // First Column \r\n style.borders.left.applyParams(outline.showLeft(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n } // else: do nothing\r\n\r\n style.borders.right = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isLast) { // Last Column\r\n style.borders.right.applyParams(outline.showRight(props.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have right border, but Column Headers have, we need to apply extra padding\r\n if (!outline.showRight(props.outline) && outline.showRight(propsColumns.outline))\r\n style.paddings.right += propsGrid.outlineWeight;\r\n }\r\n else {\r\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\r\n }\r\n\r\n let rowBandingIndex: number;\r\n if (this.formattingProperties.general.rowSubtotals && propsTotal.backColor) // Totals breaking banding sequence\r\n rowBandingIndex = item.position.row.indexInSiblings;\r\n else\r\n rowBandingIndex = item.position.row.index;\r\n\r\n if (item.isTotal && propsTotal.fontColor) {\r\n style.fontColor = propsTotal.fontColor;\r\n }\r\n else {\r\n style.fontColor = rowBandingIndex % 2 === 0 ? props.fontColorPrimary : props.fontColorSecondary;\r\n }\r\n\r\n if (item.isTotal && propsTotal.backColor) {\r\n style.backColor = propsTotal.backColor;\r\n }\r\n else {\r\n style.backColor = rowBandingIndex % 2 === 0 ? props.backColorPrimary : props.backColorSecondary;\r\n }\r\n }\r\n\r\n public unbindBodyCell(item: MatrixVisualBodyItem, cell: controls.ITablixCell): void {\r\n TablixUtils.clearCellStyle(cell);\r\n TablixUtils.clearCellTextAndTooltip(cell);\r\n }\r\n \r\n /**\r\n * Corner Cell.\r\n */\r\n public bindCornerCell(item: MatrixCornerItem, cell: controls.ITablixCell): void {\r\n TablixUtils.resetCellCssClass(cell);\r\n\r\n let cellStyle = new TablixUtils.CellStyle();\r\n\r\n cellStyle.fontFamily = TablixUtils.FontFamilyHeader;\r\n cellStyle.fontColor = TablixUtils.FontColorHeaders;\r\n\r\n cell.contentHeight = this.textHeightHeader;\r\n\r\n if (item.isColumnHeaderLeaf) {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixColumnHeaderLeaf);\r\n\r\n cellStyle.borders.bottom = new TablixUtils.EdgeSettings(TablixObjects.PropGridOutlineWeight.defaultValue, TablixObjects.PropGridOutlineColor.defaultValue);\r\n\r\n let cornerHeaderMetadata = this.getSortableCornerColumnMetadata(item);\r\n if (cornerHeaderMetadata)\r\n this.registerColumnHeaderClickHandler(cornerHeaderMetadata, cell);\r\n\r\n if (this.options.showSortIcons)\r\n TablixUtils.createColumnHeaderWithSortIcon(cornerHeaderMetadata, cell);\r\n else\r\n TablixUtils.setCellTextAndTooltip(cell, cornerHeaderMetadata.displayName);\r\n }\r\n else {\r\n let itemText = item.metadata ? item.metadata.displayName : '';\r\n TablixUtils.setCellTextAndTooltip(cell, itemText);\r\n }\r\n\r\n if (item.isRowHeaderLeaf) {\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassMatrixRowHeaderLeaf);\r\n }\r\n\r\n TablixUtils.addCellCssClass(cell, TablixUtils.CssClassTablixHeader);\r\n\r\n this.setCornerCellsStyle(cell, cellStyle);\r\n\r\n cell.applyStyle(cellStyle);\r\n cell.extension.disableDragResize();\r\n }\r\n\r\n private setCornerCellsStyle(cell: controls.ITablixCell, style: TablixUtils.CellStyle): void {\r\n let propsGrid = this.formattingProperties.grid;\r\n let propsCol = this.formattingProperties.columnHeaders;\r\n let propsRow = this.formattingProperties.rowHeaders;\r\n\r\n style.fontColor = propsCol.fontColor || propsRow.fontColor;\r\n style.backColor = propsCol.backColor || propsRow.backColor;\r\n\r\n style.paddings.top = style.paddings.bottom = propsGrid.rowPadding;\r\n\r\n style.borders.top = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isFirst) {\r\n style.borders.top.applyParams(outline.showTop(propsCol.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n } // else: do nothing\r\n\r\n style.borders.bottom = new TablixUtils.EdgeSettings();\r\n if (cell.position.row.isLast) {\r\n style.borders.bottom.applyParams(outline.showBottom(propsCol.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n }\r\n else {\r\n style.borders.bottom.applyParams(propsGrid.gridHorizontal, propsGrid.gridHorizontalWeight, propsGrid.gridHorizontalColor);\r\n }\r\n\r\n style.borders.left = new TablixUtils.EdgeSettings();\r\n if (cell.position.column.isFirst) {\r\n style.borders.left.applyParams(outline.showLeft(propsCol.outline), propsGrid.outlineWeight, propsGrid.outlineColor);\r\n\r\n // If we dont have left border, but Row Headers have, we need to apply extra padding\r\n if (!outline.showLeft(propsCol.outline) && outline.showLeft(propsRow.outline))\r\n style.paddings.left += propsGrid.outlineWeight;\r\n } // else: do nothing\r\n\r\n style.borders.right = new TablixUtils.EdgeSettings();\r\n style.borders.right.applyParams(propsGrid.gridVertical, propsGrid.gridVerticalWeight, propsGrid.gridVerticalColor);\r\n }\r\n\r\n public unbindCornerCell(item: MatrixCornerItem, cell: controls.ITablixCell): void {\r\n TablixUtils.clearCellStyle(cell);\r\n TablixUtils.clearCellTextAndTooltip(cell);\r\n\r\n if (this.options.showSortIcons)\r\n TablixUtils.removeSortIcons(cell);\r\n\r\n if (item.isColumnHeaderLeaf) {\r\n this.unregisterColumnHeaderClickHandler(cell);\r\n }\r\n }\r\n\r\n public bindEmptySpaceHeaderCell(cell: controls.ITablixCell): void {\r\n }\r\n\r\n public unbindEmptySpaceHeaderCell(cell: controls.ITablixCell): void {\r\n }\r\n\r\n public bindEmptySpaceFooterCell(cell: controls.ITablixCell): void {\r\n }\r\n\r\n public unbindEmptySpaceFooterCell(cell: controls.ITablixCell): void {\r\n }\r\n \r\n /**\r\n * Measurement Helper.\r\n */\r\n public getHeaderLabel(item: MatrixVisualNode): string {\r\n return MatrixBinder.getNodeLabel(item);\r\n }\r\n\r\n public getCellContent(item: MatrixVisualBodyItem): string {\r\n return item.textContent || '';\r\n }\r\n\r\n public hasRowGroups(): boolean {\r\n // Figure out whether we have a static row header, i.e., not row groups\r\n let dataView = this.hierarchyNavigator.getDataViewMatrix();\r\n\r\n if (!dataView || !dataView.rows || !dataView.rows.levels || dataView.rows.levels.length === 0)\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n private static getNodeLabel(node: MatrixVisualNode): string {\r\n // Return formatted value\r\n if (node.name)\r\n return node.name;\r\n\r\n // Return unformatted value (fallback case)\r\n if (node.value != null)\r\n return node.value.toString();\r\n\r\n return '';\r\n }\r\n \r\n /**\r\n * Returns the column metadata of the column that needs to be sorted for the specified matrix corner node.\r\n * \r\n * @return Column metadata or null if the specified corner node does not represent a sortable header.\r\n */\r\n private getSortableCornerColumnMetadata(item: MatrixCornerItem): DataViewMetadataColumn {\r\n if (item.isColumnHeaderLeaf)\r\n return item.metadata;\r\n }\r\n\r\n private getRowHeaderMetadata(item: MatrixVisualNode): DataViewMetadataColumn {\r\n if (!this.hierarchyNavigator || !item)\r\n return;\r\n\r\n let dataView = this.hierarchyNavigator.getDataViewMatrix();\r\n\r\n if (!dataView || !dataView.rows)\r\n return;\r\n\r\n return this.getHierarchyMetadata(dataView.rows, item.level);\r\n }\r\n\r\n private getColumnHeaderMetadata(item: MatrixVisualNode): DataViewMetadataColumn {\r\n if (!this.hierarchyNavigator || !item)\r\n return;\r\n\r\n let dataView = this.hierarchyNavigator.getDataViewMatrix();\r\n if (!dataView || !dataView.columns)\r\n return;\r\n\r\n return this.getHierarchyMetadata(dataView.columns, item.level);\r\n }\r\n\r\n private getHierarchyMetadata(hierarchy: DataViewHierarchy, level: number): DataViewMetadataColumn {\r\n if (!hierarchy || !hierarchy.levels || hierarchy.levels.length < level)\r\n return;\r\n\r\n let levelInfo = hierarchy.levels[level];\r\n if (!levelInfo || !levelInfo.sources || levelInfo.sources.length === 0)\r\n return;\r\n\r\n // This assumes the source will always be the first item in the array of sources.\r\n return levelInfo.sources[0];\r\n }\r\n \r\n /**\r\n * Returns the column metadata of the column that needs to be sorted for the specified header node.\r\n * \r\n * @return Column metadata or null if the specified header node does not represent a sortable header.\r\n */\r\n private getSortableHeaderColumnMetadata(item: MatrixVisualNode): DataViewMetadataColumn {\r\n let dataView = this.hierarchyNavigator.getDataViewMatrix();\r\n\r\n // If there are no row groups, sorting is not supported (as it does not make sense).\r\n if (!dataView.rows || !dataView.rows.levels || dataView.rows.levels.length === 0)\r\n return null;\r\n\r\n let isMultiMeasure: boolean = dataView.valueSources && dataView.valueSources.length > 1;\r\n\r\n let columnGroupCount = dataView.columns ? dataView.columns.levels.length : 0;\r\n\r\n // If we have multiple values, they establish an extra level, so need to subtract 1\r\n if (isMultiMeasure) {\r\n columnGroupCount--;\r\n }\r\n // Check if it has only 1 measure with no column groups\r\n else if (columnGroupCount === 1 &&\r\n dataView.columns.levels[0] &&\r\n dataView.columns.levels[0].sources && dataView.columns.levels[0].sources[0] &&\r\n dataView.columns.levels[0].sources[0].roles && dataView.columns.levels[0].sources[0].roles[\"Values\"]) {\r\n columnGroupCount = 0;\r\n }\r\n\r\n let valueIndex: number = -1;\r\n if (columnGroupCount === 0) {\r\n // Matrices without column groups, support sorting on all columns (which are then measure columns).\r\n valueIndex = item.levelSourceIndex;\r\n }\r\n else if (item.isSubtotal) {\r\n // Matrices with column groups support sorting only on the column grand total.\r\n if (isMultiMeasure) {\r\n // In the multi-measure case we need to check if the parent's level is 0 in order\r\n // to determine whether this is the column grand total. The cells are layed out such\r\n // that the clickable cells are at the innermost level, but the parent for the column\r\n // grand total will have level 0.\r\n if (item.parent && item.parent.level === 0)\r\n valueIndex = item.levelSourceIndex;\r\n }\r\n else {\r\n // In the single-measure case we can directly check the level of the subtotal to\r\n // detect the column grand total (at level 0).\r\n if (item.level === 0)\r\n valueIndex = item.levelSourceIndex;\r\n }\r\n }\r\n\r\n if (valueIndex !== -1) {\r\n // NOTE: if the valueIndex is undefined it implicitly means that it is 0 based on the \r\n // visual node contract\r\n valueIndex = valueIndex ? valueIndex : 0;\r\n return dataView.valueSources[valueIndex];\r\n }\r\n\r\n return null;\r\n }\r\n }\r\n\r\n export interface MatrixConstructorOptions {\r\n isTouchEnabled?: boolean;\r\n }\r\n\r\n export class Matrix implements IVisual {\r\n private static preferredLoadMoreThreshold: number = 0.8;\r\n \r\n /**\r\n * Note: Public only for testing.\r\n */\r\n public static TotalLabel = 'TableTotalLabel';\r\n\r\n private element: JQuery;\r\n private currentViewport: IViewport;\r\n private style: IVisualStyle;\r\n private dataView: DataView;\r\n private formatter: ICustomValueColumnFormatter;\r\n private isInteractive: boolean;\r\n private isTouchEnabled: boolean;\r\n private hostServices: IVisualHostServices;\r\n private hierarchyNavigator: IMatrixHierarchyNavigator;\r\n private waitingForData: boolean;\r\n private tablixControl: controls.TablixControl;\r\n private lastAllowHeaderResize: boolean;\r\n private waitingForSort: boolean;\r\n private columnWidthManager: controls.TablixColumnWidthManager;\r\n\r\n /**\r\n * Flag indicating that we are persisting objects, so that next onDataChanged can be safely ignored.\r\n */\r\n public persistingObjects: boolean;\r\n\r\n constructor(options?: MatrixConstructorOptions) {\r\n if (options) {\r\n this.isTouchEnabled = options.isTouchEnabled;\r\n }\r\n }\r\n\r\n public static customizeQuery(options: CustomizeQueryOptions): void {\r\n let dataViewMapping = options.dataViewMappings[0];\r\n if (!dataViewMapping || !dataViewMapping.matrix || !dataViewMapping.metadata)\r\n return;\r\n\r\n let dataViewMatrix: data.CompiledDataViewMatrixMapping = <data.CompiledDataViewMatrixMapping>dataViewMapping.matrix;\r\n\r\n // If Columns Hierarchy is not empty, set Window DataReduction Count to 100\r\n if (!_.isEmpty(dataViewMatrix.columns.for.in.items)) {\r\n dataViewMatrix.rows.dataReductionAlgorithm.window.count = 100;\r\n }\r\n let objects: DataViewObjects = dataViewMapping.metadata.objects;\r\n (<data.CompiledDataViewRoleForMappingWithReduction>dataViewMatrix.rows).for.in.subtotalType = TablixObjects.shouldShowRowSubtotals(objects) ? data.CompiledSubtotalType.After : data.CompiledSubtotalType.None;\r\n dataViewMatrix.columns.for.in.subtotalType = TablixObjects.shouldShowColumnSubtotals(objects) ? data.CompiledSubtotalType.After : data.CompiledSubtotalType.None;\r\n }\r\n\r\n public static getSortableRoles(): string[] {\r\n return ['Rows', 'Values'];\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.element = options.element;\r\n this.style = options.style;\r\n this.updateViewport(options.viewport);\r\n this.formatter = valueFormatter.formatValueColumn;\r\n this.isInteractive = options.interactivity && options.interactivity.selection != null;\r\n this.hostServices = options.host;\r\n this.persistingObjects = false;\r\n\r\n this.waitingForData = false;\r\n this.lastAllowHeaderResize = true;\r\n this.waitingForSort = false;\r\n }\r\n\r\n public static converter(dataView: DataView): TablixFormattingPropertiesMatrix {\r\n debug.assertValue(dataView, 'dataView');\r\n\r\n return TablixObjects.getMatrixObjects(dataView);\r\n }\r\n\r\n public onResizing(finalViewport: IViewport): void {\r\n this.updateViewport(finalViewport);\r\n }\r\n\r\n /*\r\n Public for testing\r\n */\r\n public getColumnWidthManager(): controls.TablixColumnWidthManager {\r\n return this.columnWidthManager;\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataViews = options.dataViews;\r\n\r\n if (dataViews && dataViews.length > 0) {\r\n let previousDataView = this.dataView;\r\n this.dataView = dataViews[0];\r\n\r\n // We don't check for persisting flag\r\n // Any change to the Column Widths need to go through to update all column group instances\r\n // ToDo: Consider not resetting scrollbar everytime\r\n\r\n let formattingProperties = Matrix.converter(this.dataView);\r\n let textSize = formattingProperties.general.textSize;\r\n\r\n if (options.operationKind === VisualDataChangeOperationKind.Append) {\r\n let rootChanged = previousDataView.matrix.rows.root !== this.dataView.matrix.rows.root;\r\n\r\n this.hierarchyNavigator.update(this.dataView.matrix, rootChanged);\r\n // If Root for Rows or Columns has changed by the DataViewTransform (e.g. when having reorders in values)\r\n if (rootChanged)\r\n this.tablixControl.updateModels(/*resetScrollOffsets*/false, this.dataView.matrix.rows.root.children, this.dataView.matrix.columns.root.children);\r\n\r\n this.refreshControl(/*clear*/false);\r\n } else {\r\n this.createOrUpdateHierarchyNavigator();\r\n this.createColumnWidthManager();\r\n this.createTablixControl(textSize);\r\n let binder = <MatrixBinder>this.tablixControl.getBinder();\r\n binder.onDataViewChanged(formattingProperties);\r\n\r\n this.updateInternal(textSize, previousDataView);\r\n }\r\n }\r\n\r\n this.waitingForData = false;\r\n this.waitingForSort = false;\r\n }\r\n\r\n private createColumnWidthManager(): void {\r\n let columnHierarchy: MatrixHierarchy = (<MatrixHierarchyNavigator>this.hierarchyNavigator).getMatrixColumnHierarchy();\r\n if (!this.columnWidthManager) {\r\n this.columnWidthManager = new controls.TablixColumnWidthManager(this.dataView, true /* isMatrix */, (objectInstances: VisualObjectInstancesToPersist) => this.persistColumnWidths(objectInstances), columnHierarchy.leafNodes);\r\n }\r\n // Dont update if dataView is coming from persisting\r\n else if (!this.persistingObjects) {\r\n this.columnWidthManager.updateDataView(this.dataView, columnHierarchy.leafNodes);\r\n }\r\n }\r\n\r\n private persistColumnWidths(objectInstances: VisualObjectInstancesToPersist): void {\r\n this.persistingObjects = true;\r\n this.hostServices.persistProperties(objectInstances);\r\n }\r\n\r\n private updateViewport(newViewport: IViewport) {\r\n this.currentViewport = newViewport;\r\n\r\n if (this.tablixControl) {\r\n this.tablixControl.viewport = this.currentViewport;\r\n this.verifyHeaderResize();\r\n\r\n this.refreshControl(/*clear*/false);\r\n }\r\n }\r\n\r\n private refreshControl(clear: boolean) {\r\n if (visibilityHelper.partiallyVisible(this.element) || this.getLayoutKind() === controls.TablixLayoutKind.DashboardTile) {\r\n this.tablixControl.refresh(clear);\r\n }\r\n }\r\n\r\n private getLayoutKind() {\r\n return this.isInteractive ? controls.TablixLayoutKind.Canvas : controls.TablixLayoutKind.DashboardTile;\r\n }\r\n\r\n private createOrUpdateHierarchyNavigator(): void {\r\n if (!this.tablixControl) {\r\n let matrixNavigator = createMatrixHierarchyNavigator(this.dataView.matrix, this.formatter);\r\n this.hierarchyNavigator = matrixNavigator;\r\n }\r\n else {\r\n this.hierarchyNavigator.update(this.dataView.matrix);\r\n }\r\n }\r\n\r\n private createTablixControl(textSize: number): void {\r\n if (!this.tablixControl) {\r\n // Create the control\r\n this.tablixControl = this.createControl(this.hierarchyNavigator, textSize);\r\n }\r\n }\r\n\r\n private createControl(matrixNavigator: IMatrixHierarchyNavigator, textSize: number): controls.TablixControl {\r\n let layoutKind = this.getLayoutKind();\r\n\r\n let matrixBinderOptions: MatrixBinderOptions = {\r\n onBindRowHeader: (item: MatrixVisualNode) => { this.onBindRowHeader(item); },\r\n totalLabel: this.hostServices.getLocalizedString(Matrix.TotalLabel),\r\n onColumnHeaderClick: (queryName: string, sortDirection: SortDirection) => this.onColumnHeaderClick(queryName, sortDirection),\r\n showSortIcons: layoutKind === controls.TablixLayoutKind.Canvas,\r\n };\r\n let matrixBinder = new MatrixBinder(this.hierarchyNavigator, matrixBinderOptions);\r\n\r\n let layoutManager: controls.internal.TablixLayoutManager = layoutKind === controls.TablixLayoutKind.DashboardTile\r\n ? controls.internal.DashboardTablixLayoutManager.createLayoutManager(matrixBinder)\r\n : controls.internal.CanvasTablixLayoutManager.createLayoutManager(matrixBinder, this.columnWidthManager);\r\n\r\n let tablixContainer = document.createElement('div');\r\n this.element.append(tablixContainer);\r\n\r\n let tablixOptions: controls.TablixOptions = {\r\n interactive: this.isInteractive,\r\n enableTouchSupport: this.isTouchEnabled,\r\n layoutKind: layoutKind,\r\n fontSize: TablixObjects.getTextSizeInPx(textSize),\r\n };\r\n\r\n return new controls.TablixControl(matrixNavigator, layoutManager, matrixBinder, tablixContainer, tablixOptions);\r\n }\r\n\r\n private updateInternal(textSize: number, previousDataView: DataView) {\r\n if (this.getLayoutKind() === controls.TablixLayoutKind.DashboardTile) {\r\n this.tablixControl.layoutManager.adjustContentSize(converterHelper.hasImageUrlColumn(this.dataView));\r\n }\r\n\r\n this.tablixControl.fontSize = TablixObjects.getTextSizeInPx(textSize);\r\n this.verifyHeaderResize();\r\n\r\n /* To avoid resetting scrollbar every time we persist Objects. If:\r\n * AutoSizeColumns options was flipped\r\n * A Column was resized manually\r\n * A Column was auto-sized\r\n */\r\n\r\n // Update models before the viewport to make sure column widths are computed correctly\r\n // if a persisting operation is going, don't reset the scrollbar (column resize)\r\n this.tablixControl.updateModels(/*resetScrollOffsets*/!this.persistingObjects, this.dataView.matrix.rows.root.children, this.dataView.matrix.columns.root.children);\r\n this.tablixControl.viewport = this.currentViewport;\r\n let shouldClearControl = this.shouldClearControl(previousDataView, this.dataView);\r\n\r\n // We need the layout for the DIV to be done so that the control can measure items correctly.\r\n setTimeout(() => {\r\n // Render\r\n this.refreshControl(shouldClearControl);\r\n\r\n // At this point, all columns are rendered with proper width, reset the flag if it was raised\r\n if (this.persistingObjects) {\r\n this.persistingObjects = false;\r\n return;\r\n }\r\n\r\n // if AutoSize option was set to OFF, persist all columns width\r\n if (this.columnWidthManager.shouldPersistAllColumnWidths()) {\r\n this.columnWidthManager.persistAllColumnWidths(this.tablixControl.layoutManager.columnWidthsToPersist);\r\n }\r\n }, 0);\r\n }\r\n\r\n private shouldClearControl(previousDataView: DataView, newDataView: DataView) {\r\n if (!this.waitingForSort || !previousDataView || !newDataView)\r\n return true;\r\n\r\n // ToDo: Get better criteria\r\n return !DataViewAnalysis.isMetadataEquivalent(previousDataView.metadata, newDataView.metadata);\r\n }\r\n\r\n private onBindRowHeader(item: MatrixVisualNode): void {\r\n if (this.needsMoreData(item)) {\r\n this.hostServices.loadMoreData();\r\n this.waitingForData = true;\r\n }\r\n }\r\n\r\n private onColumnHeaderClick(queryName: string, sortDirection: SortDirection): void {\r\n this.waitingForSort = true;\r\n this.hostServices.onCustomSort(TablixUtils.getCustomSortEventArgs(queryName, sortDirection));\r\n }\r\n \r\n /**\r\n * Note: Public for testability.\r\n */\r\n public needsMoreData(item: MatrixVisualNode): boolean {\r\n if (this.waitingForData || !this.hierarchyNavigator.isLeaf(item) || !this.dataView.metadata || !this.dataView.metadata.segment)\r\n return false;\r\n\r\n let leafCount = this.tablixControl.rowDimension.getItemsCount();\r\n let loadMoreThreshold = leafCount * Matrix.preferredLoadMoreThreshold;\r\n\r\n return this.hierarchyNavigator.getLeafIndex(item) >= loadMoreThreshold;\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n\r\n // Visuals are initialized with an empty data view before queries are run, therefore we need to make sure that\r\n // we are resilient here when we do not have data view.\r\n if (this.dataView) {\r\n TablixObjects.enumerateObjectInstances(options, enumeration, this.dataView, controls.TablixType.Matrix);\r\n }\r\n\r\n return enumeration.complete();\r\n }\r\n\r\n private shouldAllowHeaderResize(): boolean {\r\n return this.hostServices.getViewMode() === ViewMode.Edit;\r\n }\r\n\r\n public onViewModeChanged(viewMode: ViewMode): void {\r\n /* Refreshes the column headers to enable/disable Column resizing */\r\n this.updateViewport(this.currentViewport);\r\n }\r\n\r\n private verifyHeaderResize() {\r\n let currentAllowHeaderResize = this.shouldAllowHeaderResize();\r\n if (currentAllowHeaderResize !== this.lastAllowHeaderResize) {\r\n this.lastAllowHeaderResize = currentAllowHeaderResize;\r\n this.tablixControl.layoutManager.setAllowHeaderResize(currentAllowHeaderResize);\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import CssConstants = jsCommon.CssConstants;\r\n\r\n export interface TreemapConstructorOptions {\r\n animator?: ITreemapAnimator;\r\n isScrollable: boolean;\r\n behavior?: TreemapWebBehavior;\r\n tooltipsEnabled?: boolean;\r\n }\r\n\r\n export interface TreemapData {\r\n root: TreemapNode;\r\n hasHighlights: boolean;\r\n legendData: LegendData;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n legendObjectProperties?: DataViewObject;\r\n dataWasCulled: boolean;\r\n }\r\n\r\n /**\r\n * Treemap node (we extend D3 node (GraphNode) because treemap layout methods rely on the type).\r\n */\r\n export interface TreemapNode extends D3.Layout.GraphNode, SelectableDataPoint, TooltipEnabledDataPoint, LabelEnabledDataPoint {\r\n key: any;\r\n highlightMultiplier?: number;\r\n highlightValue?: number;\r\n color: string;\r\n highlightedTooltipInfo?: TooltipDataItem[];\r\n }\r\n\r\n interface TreemapRawData {\r\n values: number[][];\r\n highlights?: number[][];\r\n highlightsOverflow?: boolean;\r\n totalValue: number;\r\n }\r\n\r\n export interface ITreemapLayout {\r\n shapeClass: (d: TreemapNode) => string;\r\n shapeLayout: {\r\n x: (d: TreemapNode) => number;\r\n y: (d: TreemapNode) => number;\r\n width: (d: TreemapNode) => number;\r\n height: (d: TreemapNode) => number;\r\n };\r\n highlightShapeClass: (d: TreemapNode) => string;\r\n highlightShapeLayout: {\r\n x: (d: TreemapNode) => number;\r\n y: (d: TreemapNode) => number;\r\n width: (d: TreemapNode) => number;\r\n height: (d: TreemapNode) => number;\r\n };\r\n zeroShapeLayout: {\r\n x: (d: TreemapNode) => number;\r\n y: (d: TreemapNode) => number;\r\n width: (d: TreemapNode) => number;\r\n height: (d: TreemapNode) => number;\r\n };\r\n majorLabelClass: (d: TreemapNode) => string;\r\n majorLabelLayout: {\r\n x: (d: TreemapNode) => number;\r\n y: (d: TreemapNode) => number;\r\n };\r\n majorLabelText: (d: TreemapNode) => string;\r\n minorLabelClass: (d: TreemapNode) => string;\r\n minorLabelLayout: {\r\n x: (d: TreemapNode) => number;\r\n y: (d: TreemapNode) => number;\r\n };\r\n minorLabelText: (d: TreemapNode) => string;\r\n areMajorLabelsEnabled: () => boolean;\r\n areMinorLabelsEnabled: () => boolean;\r\n }\r\n\r\n // Todo: move to shared location\r\n interface DataPointObject extends DataViewObject {\r\n fill: Fill;\r\n }\r\n\r\n /**\r\n * Renders an interactive treemap visual from categorical data.\r\n */\r\n export class Treemap implements IVisual {\r\n public static DimmedShapeOpacity = 0.4;\r\n\r\n private static ClassName = 'treemap';\r\n public static LabelsGroupClassName = \"labels\";\r\n public static MajorLabelClassName = 'majorLabel';\r\n public static MinorLabelClassName = 'minorLabel';\r\n public static ShapesClassName = \"shapes\";\r\n public static TreemapNodeClassName = \"treemapNode\";\r\n public static RootNodeClassName = 'rootNode';\r\n public static ParentGroupClassName = 'parentGroup';\r\n public static NodeGroupClassName = 'nodeGroup';\r\n public static HighlightNodeClassName = 'treemapNodeHighlight';\r\n private static TextMargin = 5;\r\n private static MinorLabelTextSize = 10;\r\n private static MinTextWidthForMinorLabel = 18;\r\n private static MajorLabelTextSize = 12;\r\n private static MinTextWidthForMajorLabel = 22;\r\n private static MajorLabelTextProperties: TextProperties = {\r\n fontFamily: 'wf_segoe-ui_normal',\r\n fontSize: Treemap.MajorLabelTextSize + 'px'\r\n };\r\n private static ValuesRoleName = 'Values'; \r\n\r\n /**\r\n * A rect with an area of 9 is a treemap rectangle of only\r\n * a single pixel in the middle with a 1 pixel stroke on each edge.\r\n */\r\n private static CullableArea = 9;\r\n\r\n private svg: D3.Selection;\r\n private treemap: D3.Layout.TreeMapLayout;\r\n private shapeGraphicsContext: D3.Selection;\r\n private labelGraphicsContext: D3.Selection;\r\n // TODO: Remove this once all visuals have implemented update.\r\n private currentViewport: IViewport;\r\n private legend: ILegend;\r\n\r\n private data: TreemapData;\r\n private style: IVisualStyle;\r\n private colors: IDataColorPalette;\r\n private element: JQuery;\r\n private options: VisualInitOptions;\r\n private isScrollable: boolean;\r\n private hostService: IVisualHostServices;\r\n private tooltipsEnabled: boolean;\r\n\r\n /**\r\n * Note: Public for testing.\r\n */\r\n public animator: ITreemapAnimator;\r\n private interactivityService: IInteractivityService;\r\n private behavior: TreemapWebBehavior;\r\n\r\n // TODO: Remove this once all visuals have implemented update.\r\n private dataViews: DataView[];\r\n\r\n public static getLayout(labelsSettings: VisualDataLabelsSettings, alternativeScale: number): ITreemapLayout {\r\n let formattersCache = dataLabelUtils.createColumnFormatterCacheManager();\r\n let majorLabelsEnabled = labelsSettings.showCategory;\r\n let minorLabelsEnabled = labelsSettings.show || labelsSettings.showCategory;\r\n\r\n return {\r\n shapeClass: (d) => Treemap.getNodeClass(d, false),\r\n shapeLayout: Treemap.createTreemapShapeLayout(false),\r\n highlightShapeClass: (d) => Treemap.getNodeClass(d, true),\r\n highlightShapeLayout: Treemap.createTreemapShapeLayout(true),\r\n zeroShapeLayout: Treemap.createTreemapZeroShapeLayout(),\r\n majorLabelClass: (d) => Treemap.MajorLabelClassName,\r\n majorLabelLayout: {\r\n x: (d) => d.x + Treemap.TextMargin,\r\n y: (d) => d.y + Treemap.TextMargin + Treemap.MajorLabelTextSize,\r\n },\r\n majorLabelText: (d) => Treemap.createMajorLabelText(d, labelsSettings, alternativeScale, formattersCache),\r\n\r\n minorLabelClass: (d) => Treemap.MinorLabelClassName,\r\n minorLabelLayout: {\r\n x: (d) => d.x + Treemap.TextMargin,\r\n y: (d) => d.y + d.dy - Treemap.TextMargin,\r\n },\r\n minorLabelText: (d) => Treemap.createMinorLabelText(d, labelsSettings, alternativeScale, formattersCache),\r\n areMajorLabelsEnabled: () => majorLabelsEnabled,\r\n areMinorLabelsEnabled: () => minorLabelsEnabled,\r\n };\r\n }\r\n\r\n constructor(options?: TreemapConstructorOptions) {\r\n this.tooltipsEnabled = options && options.tooltipsEnabled;\r\n if (options && options.animator) {\r\n this.animator = options.animator;\r\n this.isScrollable = options.isScrollable ? options.isScrollable : false;\r\n this.behavior = options.behavior;\r\n }\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.options = options;\r\n let element = options.element;\r\n\r\n // Ensure viewport is empty on init\r\n element.empty();\r\n\r\n this.svg = d3.select(element.get(0))\r\n .append('svg')\r\n .style('position', 'absolute')\r\n .classed(Treemap.ClassName, true);\r\n this.shapeGraphicsContext = this.svg\r\n .append('g')\r\n .classed(Treemap.ShapesClassName, true);\r\n this.labelGraphicsContext = this.svg\r\n .append('g')\r\n .classed(Treemap.LabelsGroupClassName, true);\r\n\r\n this.element = element;\r\n\r\n // avoid deep copy\r\n this.currentViewport = {\r\n height: options.viewport.height,\r\n width: options.viewport.width,\r\n };\r\n\r\n this.style = options.style;\r\n\r\n this.treemap = d3.layout.treemap()\r\n .sticky(false)\r\n .sort((a, b) => a.size - b.size)\r\n .value((d) => d.size)\r\n .round(false);\r\n\r\n if (this.behavior) {\r\n this.interactivityService = createInteractivityService(options.host);\r\n }\r\n this.legend = createLegend(element, options.interactivity && options.interactivity.isInteractiveLegend, this.interactivityService, this.isScrollable);\r\n this.colors = this.style.colorPalette.dataColors;\r\n\r\n this.hostService = options.host;\r\n }\r\n\r\n /**\r\n * Note: Public for testing purposes.\r\n */\r\n public static converter(dataView: DataView, colors: IDataColorPalette, labelSettings: VisualDataLabelsSettings, interactivityService: IInteractivityService, viewport: IViewport, legendObjectProperties?: DataViewObject, tooltipsEnabled: boolean = true): TreemapData {\r\n let reader = data.createIDataViewCategoricalReader(dataView);\r\n\r\n let rootNode: TreemapNode = {\r\n key: \"root\",\r\n name: \"root\",\r\n children: [],\r\n selected: false,\r\n highlightMultiplier: 0,\r\n identity: SelectionId.createNull(),\r\n color: undefined,\r\n };\r\n let allNodes: TreemapNode[] = [];\r\n let hasHighlights: boolean;\r\n let legendDataPoints: LegendDataPoint[] = [];\r\n let legendTitle = \"\";\r\n let colorHelper = new ColorHelper(colors, treemapProps.dataPoint.fill);\r\n let dataWasCulled = undefined;\r\n if (dataView && dataView.metadata && dataView.metadata.objects) {\r\n let objects = dataView.metadata.objects;\r\n\r\n labelSettings.show = DataViewObjects.getValue(objects, treemapProps.labels.show, labelSettings.show);\r\n labelSettings.labelColor = DataViewObjects.getFillColor(objects, treemapProps.labels.color, labelSettings.labelColor);\r\n labelSettings.displayUnits = DataViewObjects.getValue(objects, treemapProps.labels.labelDisplayUnits, labelSettings.displayUnits);\r\n labelSettings.precision = DataViewObjects.getValue(objects, treemapProps.labels.labelPrecision, labelSettings.precision);\r\n labelSettings.showCategory = DataViewObjects.getValue(objects, treemapProps.categoryLabels.show, labelSettings.showCategory);\r\n }\r\n\r\n if (dataView && dataView.categorical && dataView.categorical.values) {\r\n let categorical = dataView.categorical;\r\n let valueColumns = categorical.values;\r\n hasHighlights = !!(valueColumns.length > 0 && valueColumns[0].highlights);\r\n\r\n let formatStringProp = treemapProps.general.formatString;\r\n let result = Treemap.getValuesFromCategoricalDataView(categorical, hasHighlights);\r\n let values = result.values;\r\n let highlights = result.highlights;\r\n let totalValue = result.totalValue;\r\n if (result.highlightsOverflow) {\r\n hasHighlights = false;\r\n values = highlights;\r\n }\r\n\r\n let cullableValue = Treemap.getCullableValue(totalValue, viewport);\r\n\r\n let grouped = valueColumns.grouped();\r\n let isMultiSeries = grouped && grouped.length > 0 && grouped[0].values && grouped[0].values.length > 1;\r\n let hasDynamicSeries = !!valueColumns.source;\r\n dataWasCulled = false;\r\n let shouldCullValue = undefined;\r\n let gradientValueColumn: DataViewValueColumn = GradientUtils.getGradientValueColumn(categorical);\r\n if ((categorical.categories == null) && !_.isEmpty(values)) {\r\n // No categories, sliced by series and measures\r\n for (let i = 0, ilen = values[0].length; i < ilen; i++) {\r\n \r\n let valueColumn = valueColumns[i];\r\n \r\n if(!powerbi.data.DataRoleHelper.hasRoleInValueColumn(valueColumn, Treemap.ValuesRoleName)){\r\n continue;\r\n }\r\n\r\n let value = values[0][i];\r\n if (!Treemap.checkValueForShape(value)) {\r\n continue;\r\n }\r\n if (value < cullableValue) {\r\n dataWasCulled = dataWasCulled || shouldCullValue;\r\n continue;\r\n }\r\n \r\n let nodeName = hasDynamicSeries ? reader.getSeriesValueColumnGroup(i).name : converterHelper.formatFromMetadataColumn(reader.getValueDisplayName(\"Values\", i), valueColumn.source, formatStringProp);\r\n\r\n let identity = new SelectionIdBuilder()\r\n .withSeries(valueColumns, hasDynamicSeries ? valueColumns[i] : undefined)\r\n .withMeasure(valueColumns[i].source.queryName)\r\n .createSelectionId();\r\n\r\n let key = identity.getKey();\r\n\r\n let color = hasDynamicSeries\r\n ? colorHelper.getColorForSeriesValue(grouped[i] && grouped[i].objects, categorical.values.identityFields, converterHelper.getSeriesName(valueColumn.source))\r\n : colorHelper.getColorForMeasure(valueColumn.source.objects, valueColumn.source.queryName);\r\n\r\n let highlightedValue = hasHighlights ? highlights[0][i] : undefined;\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n\r\n if (hasDynamicSeries) {\r\n let seriesMetadataColumn = reader.getSeriesMetadataColumn();\r\n let seriesValue = reader.getSeriesValueColumnGroup(i).name;\r\n tooltipInfo.push({\r\n displayName: seriesMetadataColumn.displayName,\r\n value: converterHelper.formatFromMetadataColumn(seriesValue, seriesMetadataColumn, formatStringProp),\r\n });\r\n }\r\n\r\n if (value != null) {\r\n tooltipInfo.push({\r\n displayName: valueColumn.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(value, valueColumn.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (highlightedValue != null) {\r\n tooltipInfo.push({\r\n displayName: ToolTipComponent.localizationOptions.highlightedValueDisplayName,\r\n value: converterHelper.formatFromMetadataColumn(highlightedValue, valueColumn.source, formatStringProp),\r\n });\r\n }\r\n }\r\n \r\n let node: TreemapNode = {\r\n key: key,\r\n name: nodeName,\r\n size: value,\r\n color: color,\r\n selected: false,\r\n identity: identity,\r\n tooltipInfo: tooltipInfo,\r\n highlightedTooltipInfo: tooltipInfo,\r\n labelFormatString: valueFormatter.getFormatString(valueColumn.source, formatStringProp),\r\n };\r\n if (hasHighlights && highlights) {\r\n node.highlightMultiplier = value !== 0 ? highlights[0][i] / value : 0;\r\n node.highlightValue = highlights[0][i];\r\n }\r\n rootNode.children.push(node);\r\n allNodes.push(node);\r\n legendDataPoints.push({\r\n label: nodeName,\r\n color: color,\r\n icon: LegendIcon.Box,\r\n identity: identity,\r\n selected: false\r\n });\r\n }\r\n }\r\n else if (categorical.categories && categorical.categories.length > 0) {\r\n // Count the columns that have the value roles\r\n let valueColumnCount = _.filter(valueColumns, x => x.source && x.source.roles && x.source.roles[Treemap.ValuesRoleName] === true).length;\r\n\r\n // Do not add second level if it's one and only one data point per shape and it's not a group value\r\n // e.g. Category/Series group plus only one Value field (excluding the gradient)\r\n let omitSecondLevel = valueColumnCount === 1 && (valueColumns[0].source.groupName == null);\r\n\r\n // Create the first level from categories\r\n let categoryColumn = categorical.categories[0];\r\n\r\n legendTitle = categoryColumn.source.displayName;\r\n let categoryFormat = valueFormatter.getFormatString(categoryColumn.source, formatStringProp);\r\n\r\n for (let categoryIndex = 0, categoryLen = values.length; categoryIndex < categoryLen; categoryIndex++) {\r\n let objects = categoryColumn.objects && categoryColumn.objects[categoryIndex];\r\n\r\n let color = colorHelper.getColorForSeriesValue(objects, categoryColumn.identityFields, categoryColumn.values[categoryIndex]);\r\n \r\n let categoryValue = valueFormatter.format(categoryColumn.values[categoryIndex], categoryFormat);\r\n\r\n let currentValues = values[categoryIndex];\r\n\r\n // This section area builds the tooltip for the parent node. It's only displayed if the node doesn't have any children (essentially if omitSecondLevel is true).\r\n // seriesIndex is the index of the 1st series with the role Values.\r\n let seriesIndex = powerbi.data.DataRoleHelper.getMeasureIndexOfRole(grouped, Treemap.ValuesRoleName);\r\n let value = currentValues[seriesIndex];\r\n let highlightValue = hasHighlights && highlights ? highlights[categoryIndex][seriesIndex] : undefined;\r\n \r\n let tooltipInfo: TooltipDataItem[];\r\n let categoryTooltipItem: TooltipDataItem;\r\n\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n\r\n categoryTooltipItem = {\r\n displayName: categoryColumn.source.displayName,\r\n value: categoryValue,\r\n };\r\n tooltipInfo.push(categoryTooltipItem);\r\n\r\n let valueColumnMetadata: DataViewMetadataColumn; \r\n if (value != null) {\r\n valueColumnMetadata = valueColumns[seriesIndex].source;\r\n tooltipInfo.push({\r\n displayName: valueColumnMetadata.displayName,\r\n value: converterHelper.formatFromMetadataColumn(value, valueColumnMetadata, formatStringProp),\r\n });\r\n }\r\n\r\n if (highlightValue != null) {\r\n tooltipInfo.push({\r\n displayName: ToolTipComponent.localizationOptions.highlightedValueDisplayName,\r\n value: converterHelper.formatFromMetadataColumn(highlightValue, valueColumnMetadata, formatStringProp),\r\n });\r\n }\r\n\r\n let gradientValueColumnMetadata = gradientValueColumn ? gradientValueColumn.source : undefined;\r\n if (omitSecondLevel && gradientValueColumnMetadata && gradientValueColumnMetadata !== valueColumnMetadata && gradientValueColumn.values[categoryIndex] != null ) {\r\n tooltipInfo.push({\r\n displayName: gradientValueColumnMetadata.displayName,\r\n value: converterHelper.formatFromMetadataColumn(gradientValueColumn.values[categoryIndex] , gradientValueColumnMetadata, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n let identity: SelectionId = SelectionIdBuilder.builder()\r\n .withCategory(categoryColumn, categoryIndex)\r\n .withMeasure(omitSecondLevel ? valueColumns[seriesIndex].source.queryName : undefined)\r\n .createSelectionId();\r\n\r\n let key = JSON.stringify({ nodeKey: identity.getKey(), depth: 1 });\r\n\r\n let node: TreemapNode = {\r\n key: key,\r\n name: categoryValue,\r\n color: color,\r\n selected: false,\r\n identity: identity,\r\n tooltipInfo: tooltipInfo,\r\n highlightedTooltipInfo: tooltipInfo,\r\n labelFormatString: valueColumnCount === 1 ? valueFormatter.getFormatString(valueColumns[seriesIndex].source, formatStringProp) : categoryFormat,\r\n };\r\n if (hasHighlights) {\r\n node.highlightMultiplier = value !== 0 ? highlightValue / value : 0;\r\n node.highlightValue = highlightValue;\r\n }\r\n\r\n legendDataPoints.push({\r\n label: categoryValue,\r\n color: color,\r\n icon: LegendIcon.Box,\r\n identity: identity,\r\n selected: false\r\n });\r\n\r\n let total = 0;\r\n let highlightTotal = 0; // Used if omitting second level\r\n\r\n for (let j = 0, jlen = currentValues.length; j < jlen; j++) {\r\n\r\n let valueColumn = valueColumns[j];\r\n\r\n if (!powerbi.data.DataRoleHelper.hasRoleInValueColumn(valueColumn, Treemap.ValuesRoleName)) {\r\n continue;\r\n }\r\n\r\n let value = currentValues[j];\r\n let highlight: number;\r\n\r\n shouldCullValue = value < cullableValue;\r\n if (!Treemap.checkValueForShape(value) || shouldCullValue) {\r\n dataWasCulled = dataWasCulled || shouldCullValue;\r\n continue;\r\n }\r\n\r\n total += value;\r\n\r\n if (hasHighlights) {\r\n highlight = highlights[categoryIndex][j];\r\n highlightTotal += highlight;\r\n }\r\n\r\n if (!omitSecondLevel) {\r\n let childName: string = null;\r\n if (isMultiSeries) {\r\n // Measure: use name and index\r\n childName = valueColumn.source.displayName;\r\n }\r\n else {\r\n // Series group instance\r\n childName = valueColumn.source.groupName;\r\n }\r\n\r\n let categoricalValues = categorical ? categorical.values : null;\r\n let measureId = valueColumn.source.queryName;\r\n let childIdentity = SelectionIdBuilder.builder()\r\n .withCategory(categoryColumn, categoryIndex)\r\n .withSeries(categoricalValues, valueColumn)\r\n .withMeasure(measureId)\r\n .createSelectionId();\r\n let childKey = JSON.stringify({ nodeKey: childIdentity.getKey(), depth: 2 });\r\n\r\n let highlightedValue = hasHighlights && highlight !== 0 ? highlight : undefined;\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n\r\n tooltipInfo.push(categoryTooltipItem);\r\n\r\n if (hasDynamicSeries) {\r\n if (!categoryColumn || categoryColumn.source !== categoricalValues.source) {\r\n // Category/series on the same column -- don't repeat its value in the tooltip.\r\n tooltipInfo.push({\r\n displayName: categoricalValues.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(grouped[j].name, categoricalValues.source, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n if (value != null) {\r\n tooltipInfo.push({\r\n displayName: valueColumn.source.displayName,\r\n value: converterHelper.formatFromMetadataColumn(value, valueColumn.source, formatStringProp),\r\n });\r\n }\r\n\r\n if (highlightValue != null) {\r\n tooltipInfo.push({\r\n displayName: ToolTipComponent.localizationOptions.highlightedValueDisplayName,\r\n value: converterHelper.formatFromMetadataColumn(highlightedValue, valueColumn.source, formatStringProp),\r\n });\r\n }\r\n }\r\n\r\n let childNode: TreemapNode = {\r\n key: childKey,\r\n name: childName,\r\n size: value,\r\n color: color,\r\n selected: false,\r\n identity: childIdentity,\r\n tooltipInfo: tooltipInfo,\r\n highlightedTooltipInfo: tooltipInfo,\r\n labelFormatString: valueFormatter.getFormatString(valueColumn.source, formatStringProp),\r\n };\r\n if (hasHighlights) {\r\n childNode.highlightMultiplier = value !== 0 ? highlight / value : 0;\r\n childNode.highlightValue = highlight;\r\n }\r\n if (node.children == null)\r\n node.children = [];\r\n\r\n node.children.push(childNode);\r\n allNodes.push(childNode);\r\n }\r\n }\r\n\r\n if (Treemap.checkValueForShape(total)) {\r\n node.size = total;\r\n rootNode.children.push(node);\r\n allNodes.push(node);\r\n }\r\n if (hasHighlights)\r\n node.highlightMultiplier = total ? highlightTotal / total : 0;\r\n }\r\n }\r\n }\r\n\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(allNodes);\r\n interactivityService.applySelectionStateToData(legendDataPoints);\r\n }\r\n\r\n return {\r\n root: rootNode,\r\n hasHighlights: hasHighlights,\r\n legendData: { title: legendTitle, dataPoints: legendDataPoints, fontSize: SVGLegend.DefaultFontSizeInPt },\r\n dataLabelsSettings: labelSettings,\r\n legendObjectProperties: legendObjectProperties,\r\n dataWasCulled: dataWasCulled,\r\n };\r\n }\r\n\r\n private static getValuesFromCategoricalDataView(data: DataViewCategorical, hasHighlights: boolean): TreemapRawData {\r\n let valueColumns = data.values;\r\n let categoryValueCount: number;\r\n if (valueColumns && (data.categories == null)) {\r\n categoryValueCount = 1; // We only get the first value out of each valueColumn since we don't have a category\r\n }\r\n else if (valueColumns && data.categories && data.categories.length > 0) {\r\n categoryValueCount = data.categories[0].values.length;\r\n }\r\n\r\n let values: number[][] = [];\r\n let highlights: number[][] = [];\r\n let totalValue = 0;\r\n for (let i = 0; i < categoryValueCount; i++) {\r\n values.push([]);\r\n if (hasHighlights)\r\n highlights.push([]);\r\n }\r\n\r\n let highlightsOverflow: boolean;\r\n for (let j = 0; j < valueColumns.length; j++) {\r\n let valueColumn = valueColumns[j];\r\n for (let i = 0; i < categoryValueCount; i++) {\r\n let value = valueColumn.values[i];\r\n values[i].push(value);\r\n totalValue += isNaN(value) ? 0 : value;\r\n if (hasHighlights) {\r\n let highlight = valueColumn.highlights[i];\r\n if (!highlight)\r\n highlight = 0;\r\n highlights[i].push(highlight);\r\n if (highlight > value)\r\n highlightsOverflow = true;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n values: values,\r\n highlights: hasHighlights ? highlights : undefined,\r\n highlightsOverflow: hasHighlights ? highlightsOverflow : undefined,\r\n totalValue: totalValue,\r\n };\r\n }\r\n\r\n private static getCullableValue(totalValue: number, viewport: IViewport): number {\r\n let totalArea = viewport.width * viewport.height;\r\n let culledPercent = Treemap.CullableArea / totalArea;\r\n return culledPercent * totalValue;\r\n }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataViews = this.dataViews = options.dataViews;\r\n this.currentViewport = options.viewport;\r\n let dataViewCategorical = dataViews && dataViews.length > 0 && dataViews[0].categorical ? dataViews[0].categorical : undefined;\r\n let labelSettings = dataLabelUtils.getDefaultTreemapLabelSettings();\r\n let legendObjectProperties = null;\r\n\r\n if (dataViewCategorical) {\r\n let dataView = dataViews[0];\r\n let dataViewMetadata = dataView.metadata;\r\n let objects: DataViewObjects;\r\n if (dataViewMetadata)\r\n objects = dataViewMetadata.objects;\r\n\r\n if (objects) {\r\n legendObjectProperties = objects['legend'];\r\n }\r\n\r\n this.data = Treemap.converter(dataView, this.colors, labelSettings, this.interactivityService, this.currentViewport, legendObjectProperties, this.tooltipsEnabled);\r\n }\r\n else {\r\n let rootNode: TreemapNode = {\r\n key: \"root\",\r\n name: \"root\",\r\n children: [],\r\n selected: false,\r\n highlightMultiplier: 0,\r\n identity: SelectionId.createNull(),\r\n color: undefined,\r\n };\r\n let legendData: LegendData = { title: \"\", dataPoints: [] };\r\n let treeMapData: TreemapData = {\r\n root: rootNode,\r\n hasHighlights: false,\r\n legendData: legendData,\r\n dataLabelsSettings: labelSettings,\r\n dataWasCulled: false,\r\n };\r\n this.data = treeMapData;\r\n }\r\n\r\n this.updateInternal(options.suppressAnimations);\r\n\r\n if (dataViews) {\r\n let warnings = getInvalidValueWarnings(\r\n dataViews,\r\n false /*supportsNaN*/,\r\n false /*supportsNegativeInfinity*/,\r\n false /*supportsPositiveInfinity*/);\r\n\r\n this.hostService.setWarnings(warnings);\r\n }\r\n }\r\n\r\n // TODO: Remove this once all visuals have implemented update.\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n this.update({\r\n suppressAnimations: options.suppressAnimations,\r\n dataViews: options.dataViews,\r\n viewport: this.currentViewport\r\n });\r\n }\r\n\r\n // TODO: Remove this once all visuals have implemented update.\r\n public onResizing(viewport: IViewport): void {\r\n this.update({\r\n suppressAnimations: true,\r\n dataViews: this.dataViews,\r\n viewport: viewport\r\n });\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService)\r\n this.interactivityService.clearSelection();\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let data = this.data;\r\n if (!data)\r\n return;\r\n\r\n let objectName = options.objectName,\r\n enumeration = new ObjectEnumerationBuilder();\r\n\r\n let dataLabelsSettings = this.data.dataLabelsSettings\r\n ? this.data.dataLabelsSettings\r\n : dataLabelUtils.getDefaultTreemapLabelSettings();\r\n\r\n switch (objectName) {\r\n case 'dataPoint':\r\n let dataViewCat: DataViewCategorical = this.dataViews && this.dataViews.length > 0 && this.dataViews[0] && this.dataViews[0].categorical;\r\n let hasGradientRole = GradientUtils.hasGradientRole(dataViewCat);\r\n if (!hasGradientRole)\r\n this.enumerateDataPoints(enumeration, data);\r\n break;\r\n case 'legend':\r\n return this.enumerateLegend(data);\r\n case 'labels':\r\n let labelSettingOptions: VisualDataLabelsSettingsOptions = {\r\n enumeration: enumeration,\r\n dataLabelsSettings: dataLabelsSettings,\r\n show: true,\r\n displayUnits: true,\r\n precision: true,\r\n };\r\n dataLabelUtils.enumerateDataLabels(labelSettingOptions);\r\n break;\r\n case 'categoryLabels':\r\n dataLabelUtils.enumerateCategoryLabels(enumeration, dataLabelsSettings, false /* withFill */, true /* isShowCategory */);\r\n break;\r\n }\r\n\r\n return enumeration.complete();\r\n }\r\n\r\n private enumerateDataPoints(enumeration: ObjectEnumerationBuilder, data: TreemapData): void {\r\n let rootChildren = data.root.children;\r\n if (_.isEmpty(rootChildren))\r\n return;\r\n\r\n for (let y = 0; y < rootChildren.length; y++) {\r\n let treemapNode = <TreemapNode>rootChildren[y];\r\n enumeration.pushInstance({\r\n displayName: treemapNode.name,\r\n selector: ColorHelper.normalizeSelector(treemapNode.identity.getSelector()),\r\n properties: {\r\n fill: { solid: { color: treemapNode.color } }\r\n },\r\n objectName: 'dataPoint'\r\n });\r\n }\r\n }\r\n\r\n private enumerateLegend(data: TreemapData): VisualObjectInstance[] {\r\n let legendObjectProperties: DataViewObjects = { legend: data.legendObjectProperties };\r\n\r\n let show = DataViewObjects.getValue(legendObjectProperties, treemapProps.legend.show, this.legend.isVisible());\r\n let showTitle = DataViewObjects.getValue(legendObjectProperties, treemapProps.legend.showTitle, true);\r\n let titleText = DataViewObjects.getValue(legendObjectProperties, treemapProps.legend.titleText, this.data.legendData.title);\r\n let labelColor = DataViewObject.getValue(legendObjectProperties, legendProps.labelColor, this.data.legendData ? this.data.legendData.labelColor : LegendData.DefaultLegendLabelFillColor);\r\n let labelFontSize = DataViewObject.getValue(legendObjectProperties, legendProps.fontSize, this.data.legendData && this.data.legendData.fontSize ? this.data.legendData.fontSize : SVGLegend.DefaultFontSizeInPt);\r\n\r\n return [{\r\n selector: null,\r\n objectName: 'legend',\r\n properties: {\r\n show: show,\r\n position: LegendPosition[this.legend.getOrientation()],\r\n showTitle: showTitle,\r\n titleText: titleText,\r\n labelColor: labelColor,\r\n fontSize: labelFontSize,\r\n }\r\n }];\r\n }\r\n\r\n private static checkValueForShape(value: any): boolean {\r\n if (!value)\r\n return false;\r\n\r\n return value > 0;\r\n }\r\n\r\n private calculateTreemapSize(): IViewport {\r\n let legendMargins = this.legend.getMargins();\r\n return {\r\n height: this.currentViewport.height - legendMargins.height,\r\n width: this.currentViewport.width - legendMargins.width\r\n };\r\n }\r\n\r\n private initViewportDependantProperties(duration: number = 0): void {\r\n\r\n let viewport = this.calculateTreemapSize();\r\n\r\n this.svg.attr({\r\n width: viewport.width,\r\n height: viewport.height\r\n });\r\n Legend.positionChartArea(this.svg, this.legend);\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n }\r\n\r\n private static hasChildrenWithIdentity(node: D3.Layout.GraphNode): boolean {\r\n let children = node.children;\r\n if (!children)\r\n return false;\r\n\r\n let count = children.length;\r\n if (count === 0)\r\n return false;\r\n\r\n for (let i = count - 1; i >= 0; i--) {\r\n if ((<TreemapNode>children[i]).identity.hasIdentity())\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private static canDisplayMajorLabel(node: TreemapNode): boolean {\r\n // Only display major labels for level 1\r\n if (node.depth !== 1)\r\n return false;\r\n\r\n if (_.isEmpty(node.name))\r\n return false;\r\n\r\n // Check if the room is enough for text with or without ellipse\r\n let availableWidth = node.dx - Treemap.TextMargin * 2;\r\n if (availableWidth < Treemap.MinTextWidthForMajorLabel)\r\n return false;\r\n \r\n // Check if the shape is high enough for label\r\n let textHeightWithMargin = Treemap.MajorLabelTextSize + Treemap.TextMargin * 2;\r\n if (node.dy < textHeightWithMargin)\r\n return false;\r\n\r\n return true;\r\n }\r\n\r\n private static canDisplayMinorLabel(node: TreemapNode, labelSettings: VisualDataLabelsSettings): boolean {\r\n // Only display minor labels for level 1 and 2\r\n if (node.depth < 1 || node.depth > 2)\r\n return false;\r\n\r\n // If a depth 1 node has children or is not showing data labels, do not show minor labels\r\n if (node.depth === 1 && (node.children || !labelSettings.show)) {\r\n return false;\r\n }\r\n\r\n if (_.isEmpty(node.name))\r\n return false;\r\n \r\n // Check if the room is enough for text with or without ellipse\r\n let availableWidth = node.dx - Treemap.TextMargin * 2;\r\n if (availableWidth < Treemap.MinTextWidthForMinorLabel)\r\n return false;\r\n \r\n // Check if the shape is high enough for label\r\n let textHeightWithMargin = Treemap.MinorLabelTextSize + Treemap.TextMargin * 2;\r\n if (node.dy < textHeightWithMargin)\r\n return false;\r\n if (node.depth === 1) {\r\n let roomTop = node.y + Treemap.MajorLabelTextSize + Treemap.TextMargin * 2;\r\n if (node.y + node.dy - roomTop < textHeightWithMargin)\r\n return false;\r\n }\r\n else if (node.depth === 2) {\r\n let parent = node.parent;\r\n let roomTop = Math.max(parent.y + Treemap.MajorLabelTextSize + Treemap.TextMargin * 2, node.y);\r\n\r\n // Parent's label needs the room\r\n if (node.y + node.dy - roomTop < textHeightWithMargin)\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private static createMajorLabelText(node: TreemapNode, labelsSettings: VisualDataLabelsSettings, alternativeScale: number, formattersCache: IColumnFormatterCacheManager): string {\r\n let spaceAvaliableForLabels = node.dx - Treemap.TextMargin * 2;\r\n let baseTextProperties = Treemap.MajorLabelTextProperties;\r\n let textProperties: powerbi.TextProperties = {\r\n text: node.name,\r\n fontFamily: baseTextProperties.fontFamily,\r\n fontSize: baseTextProperties.fontSize\r\n };\r\n\r\n return TextMeasurementService.getTailoredTextOrDefault(textProperties, spaceAvaliableForLabels);\r\n }\r\n\r\n private static createMinorLabelText(node: TreemapNode, labelsSettings: VisualDataLabelsSettings, alternativeScale: number, formattersCache: IColumnFormatterCacheManager): string {\r\n let spaceAvaliableForLabels = node.dx - Treemap.TextMargin * 2;\r\n let label = node.name;\r\n if (labelsSettings.show) {\r\n let measureFormatter = formattersCache.getOrCreate(node.labelFormatString, labelsSettings, alternativeScale);\r\n // Create measure label\r\n label = dataLabelUtils.getLabelFormattedText({\r\n label: node.highlightValue != null ? node.highlightValue : node.value, maxWidth:\r\n spaceAvaliableForLabels, formatter: measureFormatter\r\n });\r\n // Add category if needed (we're showing category and the node depth is 2)\r\n if (labelsSettings.showCategory && node.depth === 2)\r\n label = dataLabelUtils.getLabelFormattedText({\r\n label: node.name,\r\n maxWidth: spaceAvaliableForLabels\r\n }) + \" \" + label;\r\n }\r\n\r\n return dataLabelUtils.getLabelFormattedText({\r\n label: label,\r\n maxWidth: spaceAvaliableForLabels,\r\n fontSize: labelsSettings.fontSize\r\n });\r\n }\r\n\r\n public static getFill(d: TreemapNode, isHighlightRect: boolean): string {\r\n // NOTE: only painted shapes will catch click event. We either paint children or their parent but not both.\r\n\r\n // If it's a leaf with no category, parent will be painted instead (and support interactivity)\r\n if (d.depth > 1 && !d.identity.hasIdentity() && !isHighlightRect)\r\n return CssConstants.noneValue;\r\n\r\n // If it's not a leaf and it has children with a category, children will be painted\r\n if (Treemap.hasChildrenWithIdentity(d))\r\n return CssConstants.noneValue;\r\n\r\n return d.color;\r\n }\r\n\r\n public static getFillOpacity(d: TreemapNode, hasSelection: boolean, hasHighlights: boolean, isHighlightRect: boolean): string {\r\n if (hasHighlights) {\r\n if (isHighlightRect)\r\n return null;\r\n return Treemap.DimmedShapeOpacity.toString();\r\n }\r\n\r\n if (!hasSelection || d.selected)\r\n return null;\r\n\r\n // Parent node is selected (as an optimization, we only check below level 1 because root node cannot be selected anyway)\r\n if (d.depth > 1 && (<TreemapNode>d.parent).selected)\r\n return null;\r\n\r\n // It's a parent node with interactive children, fall back to default opacity\r\n if (Treemap.hasChildrenWithIdentity(d))\r\n return null;\r\n\r\n return Treemap.DimmedShapeOpacity.toString();\r\n }\r\n\r\n private updateInternal(suppressAnimations: boolean): void {\r\n let data = this.data;\r\n let hasHighlights = data && data.hasHighlights;\r\n let labelSettings = data ? data.dataLabelsSettings : null;\r\n let duration = AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n\r\n if (!(this.options.interactivity && this.options.interactivity.isInteractiveLegend) && this.data) {\r\n this.renderLegend();\r\n }\r\n\r\n this.initViewportDependantProperties(duration);\r\n let viewport = this.calculateTreemapSize();\r\n\r\n this.treemap.size([viewport.width, viewport.height]);\r\n\r\n // Shapes are drawn for all nodes\r\n let nodes = (data && data.root) ? this.treemap.nodes(data.root) : [];\r\n // Highlight shapes are drawn only for nodes with non-null/undefed highlightMultipliers that have no children\r\n let highlightNodes = nodes.filter((value: TreemapNode) => value.highlightMultiplier != null && (!value.children || value.children.length === 0));\r\n let majorLabeledNodes = [];\r\n let minorLabeledNodes = [];\r\n let alternativeScale: number = null;\r\n\r\n // Only populate major labels if category labels are turned on\r\n if (labelSettings.showCategory) {\r\n majorLabeledNodes = nodes.filter((d: TreemapNode) => Treemap.canDisplayMajorLabel(d));\r\n }\r\n\r\n // Only populate minor labels if category or data labels are turned on\r\n if (labelSettings.show || labelSettings.showCategory) {\r\n minorLabeledNodes = nodes.filter((d: TreemapNode) => Treemap.canDisplayMinorLabel(d, labelSettings));\r\n\r\n // If the display unit is 0 we calculate the format scale using the maximum value available\r\n if (labelSettings.displayUnits === 0)\r\n alternativeScale = <number>d3.max(minorLabeledNodes, (d: TreemapNode) => Math.abs(d.value));\r\n }\r\n\r\n let treemapLayout = Treemap.getLayout(labelSettings, alternativeScale);\r\n let shapes: D3.UpdateSelection;\r\n let highlightShapes: D3.UpdateSelection;\r\n let majorLabels: D3.UpdateSelection;\r\n let minorLabels: D3.UpdateSelection;\r\n let result: TreemapAnimationResult;\r\n if (this.animator && !suppressAnimations) {\r\n let options: TreemapAnimationOptions = {\r\n viewModel: data,\r\n nodes: nodes,\r\n highlightNodes: highlightNodes,\r\n majorLabeledNodes: majorLabeledNodes,\r\n minorLabeledNodes: minorLabeledNodes,\r\n shapeGraphicsContext: this.shapeGraphicsContext,\r\n labelGraphicsContext: this.labelGraphicsContext,\r\n interactivityService: this.interactivityService,\r\n layout: treemapLayout,\r\n labelSettings: labelSettings,\r\n };\r\n result = this.animator.animate(options);\r\n shapes = result.shapes;\r\n highlightShapes = result.highlightShapes;\r\n majorLabels = result.majorLabels;\r\n minorLabels = result.minorLabels;\r\n }\r\n if (!this.animator || suppressAnimations || result.failed) {\r\n let hasSelection = this.interactivityService && this.interactivityService.hasSelection();\r\n let shapeGraphicsContext = this.shapeGraphicsContext;\r\n shapes = Treemap.drawDefaultShapes(shapeGraphicsContext, nodes, hasSelection, hasHighlights, treemapLayout);\r\n highlightShapes = Treemap.drawDefaultHighlightShapes(shapeGraphicsContext, highlightNodes, hasSelection, hasHighlights, treemapLayout);\r\n let labelGraphicsContext = this.labelGraphicsContext;\r\n majorLabels = Treemap.drawDefaultMajorLabels(labelGraphicsContext, majorLabeledNodes, labelSettings, treemapLayout);\r\n minorLabels = Treemap.drawDefaultMinorLabels(labelGraphicsContext, minorLabeledNodes, labelSettings, treemapLayout);\r\n }\r\n\r\n if (this.interactivityService) {\r\n let behaviorOptions: TreemapBehaviorOptions = {\r\n shapes: shapes,\r\n highlightShapes: highlightShapes,\r\n majorLabels: majorLabels,\r\n minorLabels: minorLabels,\r\n nodes: <TreemapNode[]>nodes,\r\n hasHighlights: data.hasHighlights,\r\n };\r\n\r\n this.interactivityService.bind(<TreemapNode[]>nodes, this.behavior, behaviorOptions);\r\n }\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(shapes, (tooltipEvent: TooltipEvent) => tooltipEvent.data.highlightedTooltipInfo ? tooltipEvent.data.highlightedTooltipInfo : tooltipEvent.data.tooltipInfo);\r\n TooltipManager.addTooltip(highlightShapes, (tooltipEvent: TooltipEvent) => tooltipEvent.data.highlightedTooltipInfo);\r\n }\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n }\r\n\r\n private renderLegend(): void {\r\n let legendObjectProperties = this.data.legendObjectProperties;\r\n if (legendObjectProperties) {\r\n let legendData = this.data.legendData;\r\n LegendData.update(legendData, legendObjectProperties);\r\n let position = <string>legendObjectProperties[legendProps.position];\r\n if (position)\r\n this.legend.changeOrientation(LegendPosition[position]);\r\n\r\n this.legend.drawLegend(legendData, this.currentViewport);\r\n } else {\r\n // TODO: Draw should be the only API. Visuals should only call that with orientation, props, etc \r\n // instead of managing state. Will follow up with another change.\r\n this.legend.changeOrientation(LegendPosition.Top);\r\n this.legend.drawLegend({ dataPoints: [] }, this.currentViewport);\r\n }\r\n }\r\n\r\n private static getNodeClass(d: TreemapNode, highlight?: boolean): string {\r\n let nodeClass: string;\r\n switch (d.depth) {\r\n case 1:\r\n nodeClass = Treemap.ParentGroupClassName;\r\n break;\r\n case 2:\r\n nodeClass = Treemap.NodeGroupClassName;\r\n break;\r\n case 0:\r\n nodeClass = Treemap.RootNodeClassName;\r\n break;\r\n default:\r\n debug.assertFail('Treemap only supports 2 levels maxiumum');\r\n }\r\n nodeClass += \" \" + (highlight ? Treemap.HighlightNodeClassName : Treemap.TreemapNodeClassName);\r\n return nodeClass;\r\n }\r\n\r\n private static createTreemapShapeLayout(isHighlightRect = false) {\r\n return {\r\n x: (d: TreemapNode) => d.x,\r\n y: (d: TreemapNode) => d.y + (isHighlightRect ? d.dy * (1 - d.highlightMultiplier) : 0),\r\n width: (d: TreemapNode) => Math.max(0, d.dx),\r\n height: (d: TreemapNode) => Math.max(0, d.dy * (isHighlightRect ? d.highlightMultiplier : 1)),\r\n };\r\n }\r\n\r\n private static createTreemapZeroShapeLayout() {\r\n return {\r\n x: (d: TreemapNode) => d.x,\r\n y: (d: TreemapNode) => d.y + d.dy,\r\n width: (d: TreemapNode) => Math.max(0, d.dx),\r\n height: (d: TreemapNode) => 0,\r\n };\r\n }\r\n\r\n public static drawDefaultShapes(context: D3.Selection, nodes: D3.Layout.GraphNode[], hasSelection: boolean, hasHighlights: boolean, layout: ITreemapLayout): D3.UpdateSelection {\r\n let isHighlightShape = false;\r\n let shapes = context.selectAll('.' + Treemap.TreemapNodeClassName)\r\n .data(nodes, (d: TreemapNode) => d.key);\r\n\r\n shapes.enter().append('rect')\r\n .attr('class', layout.shapeClass);\r\n\r\n shapes\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, isHighlightShape))\r\n .style(\"fill-opacity\", (d: TreemapNode) => Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape))\r\n .attr(layout.shapeLayout);\r\n\r\n shapes.exit().remove();\r\n\r\n return shapes;\r\n }\r\n\r\n public static drawDefaultHighlightShapes(context: D3.Selection, nodes: D3.Layout.GraphNode[], hasSelection: boolean, hasHighlights: boolean, layout: ITreemapLayout): D3.UpdateSelection {\r\n let isHighlightShape = true;\r\n let highlightShapes = context.selectAll('.' + Treemap.HighlightNodeClassName)\r\n .data(nodes, (d) => d.key + \"highlight\");\r\n\r\n highlightShapes.enter().append('rect')\r\n .attr('class', layout.highlightShapeClass);\r\n\r\n highlightShapes\r\n .style(\"fill\", (d: TreemapNode) => Treemap.getFill(d, isHighlightShape))\r\n .style(\"fill-opacity\", (d: TreemapNode) => Treemap.getFillOpacity(d, hasSelection, hasHighlights, isHighlightShape))\r\n .attr(layout.highlightShapeLayout);\r\n\r\n highlightShapes.exit().remove();\r\n return highlightShapes;\r\n }\r\n\r\n public static drawDefaultMajorLabels(context: D3.Selection, nodes: D3.Layout.GraphNode[], labelSettings: VisualDataLabelsSettings, layout: ITreemapLayout): D3.UpdateSelection {\r\n let labels = context\r\n .selectAll('.' + Treemap.MajorLabelClassName)\r\n .data(nodes, (d: TreemapNode) => d.key);\r\n\r\n labels.enter().append('text')\r\n .attr('class', layout.majorLabelClass);\r\n\r\n labels\r\n .attr(layout.majorLabelLayout)\r\n .text(layout.majorLabelText)\r\n .style('fill', () => labelSettings.labelColor);\r\n\r\n labels.exit().remove();\r\n\r\n return labels;\r\n }\r\n\r\n public static drawDefaultMinorLabels(context: D3.Selection, nodes: D3.Layout.GraphNode[], labelSettings: VisualDataLabelsSettings, layout: ITreemapLayout): D3.UpdateSelection {\r\n let labels = context\r\n .selectAll('.' + Treemap.MinorLabelClassName)\r\n .data(nodes, (d: TreemapNode) => d.key);\r\n\r\n labels.enter().append('text')\r\n .attr('class', layout.minorLabelClass);\r\n\r\n labels\r\n .attr(layout.minorLabelLayout)\r\n .text(layout.minorLabelText)\r\n .style('fill', () => labelSettings.labelColor);\r\n\r\n labels.exit().remove();\r\n\r\n return labels;\r\n }\r\n\r\n public static cleanMinorLabels(context: D3.Selection) {\r\n let empty = [];\r\n let labels = context\r\n .selectAll('.' + Treemap.LabelsGroupClassName)\r\n .selectAll('.' + Treemap.MinorLabelClassName)\r\n .data(empty);\r\n labels.exit().remove();\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved.\r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import KpiImageSize = powerbi.visuals.KpiUtil.KpiImageSize;\r\n import KpiImageMetadata = powerbi.visuals.KpiUtil.KpiImageMetadata;\r\n import getKpiImageMetadata = powerbi.visuals.KpiUtil.getKpiImageMetadata;\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n export interface CardStyleText {\r\n textSize: number;\r\n color: string;\r\n paddingTop?: number;\r\n }\r\n\r\n export interface CardStyleValue extends CardStyleText {\r\n fontFamily: string;\r\n }\r\n\r\n export interface CardStyle {\r\n card: {\r\n maxFontSize: number;\r\n };\r\n label: CardStyleText;\r\n value: CardStyleValue;\r\n }\r\n\r\n export interface CardConstructorOptions {\r\n isScrollable?: boolean;\r\n displayUnitSystemType?: DisplayUnitSystemType;\r\n animator?: IGenericAnimator;\r\n }\r\n\r\n export interface CardFormatSetting {\r\n textSize: number;\r\n labelSettings: VisualDataLabelsSettings;\r\n wordWrap: boolean;\r\n }\r\n\r\n export class Card extends AnimatedText implements IVisual {\r\n private static cardClassName: string = 'card';\r\n private static Label: ClassAndSelector = createClassAndSelector('label');\r\n private static Value: ClassAndSelector = createClassAndSelector('value');\r\n private static KPIImage: ClassAndSelector = createClassAndSelector('caption');\r\n\r\n private static cardTextProperties: TextProperties = {\r\n fontSize: null,\r\n text: null,\r\n fontFamily: dataLabelUtils.LabelTextProperties.fontFamily,\r\n };\r\n\r\n public static DefaultStyle: CardStyle = {\r\n card: {\r\n maxFontSize: 200\r\n },\r\n label: {\r\n textSize: 12,\r\n color: '#a6a6a6',\r\n paddingTop: 8\r\n },\r\n value: {\r\n textSize: 27,\r\n color: '#333333',\r\n fontFamily: 'wf_standard-font'\r\n }\r\n };\r\n\r\n private animationOptions: AnimationOptions;\r\n private displayUnitSystemType: DisplayUnitSystemType;\r\n private isScrollable: boolean;\r\n private graphicsContext: D3.Selection;\r\n private labelContext: D3.Selection;\r\n private cardFormatSetting: CardFormatSetting;\r\n private kpiImage: D3.Selection;\r\n\r\n public constructor(options?: CardConstructorOptions) {\r\n super(Card.cardClassName);\r\n this.isScrollable = false;\r\n this.displayUnitSystemType = DisplayUnitSystemType.WholeUnits;\r\n\r\n if (options) {\r\n this.isScrollable = !!options.isScrollable;\r\n if (options.animator)\r\n this.animator = options.animator;\r\n if (options.displayUnitSystemType != null)\r\n this.displayUnitSystemType = options.displayUnitSystemType;\r\n }\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n debug.assertValue(options, 'options');\r\n this.animationOptions = options.animation;\r\n let element = options.element;\r\n\r\n this.kpiImage = d3.select(element.get(0)).append('div')\r\n .classed(Card.KPIImage.class, true);\r\n let svg = this.svg = d3.select(element.get(0)).append('svg');\r\n this.graphicsContext = svg.append('g');\r\n this.currentViewport = options.viewport;\r\n this.hostServices = options.host;\r\n this.style = options.style;\r\n\r\n this.updateViewportProperties();\r\n\r\n if (this.isScrollable) {\r\n svg.attr('class', Card.cardClassName);\r\n this.labelContext = svg.append('g');\r\n }\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataView = options.dataViews[0];\r\n let value: any;\r\n if (dataView) {\r\n this.getMetaDataColumn(dataView);\r\n if (dataView.single) {\r\n value = dataView.single.value;\r\n }\r\n\r\n // Update settings based on new metadata column\r\n this.cardFormatSetting = this.getDefaultFormatSettings();\r\n\r\n let dataViewMetadata = dataView.metadata;\r\n if (dataViewMetadata) {\r\n let objects: DataViewObjects = dataViewMetadata.objects;\r\n if (objects) {\r\n let labelSettings = this.cardFormatSetting.labelSettings;\r\n\r\n labelSettings.labelColor = DataViewObjects.getFillColor(objects, cardProps.labels.color, labelSettings.labelColor);\r\n labelSettings.precision = DataViewObjects.getValue(objects, cardProps.labels.labelPrecision, labelSettings.precision);\r\n labelSettings.fontSize = DataViewObjects.getValue(objects, cardProps.labels.fontSize, labelSettings.fontSize);\r\n\r\n // The precision can't go below 0\r\n if (labelSettings.precision !== dataLabelUtils.defaultLabelPrecision && labelSettings.precision < 0) {\r\n labelSettings.precision = 0;\r\n }\r\n\r\n labelSettings.displayUnits = DataViewObjects.getValue(objects, cardProps.labels.labelDisplayUnits, labelSettings.displayUnits);\r\n\r\n //category labels\r\n labelSettings.showCategory = DataViewObjects.getValue(objects, cardProps.categoryLabels.show, labelSettings.showCategory);\r\n labelSettings.categoryLabelColor = DataViewObjects.getFillColor(objects, cardProps.categoryLabels.color, labelSettings.categoryLabelColor);\r\n\r\n this.cardFormatSetting.wordWrap = DataViewObjects.getValue(objects, cardProps.wordWrap.show, this.cardFormatSetting.wordWrap);\r\n this.cardFormatSetting.textSize = DataViewObjects.getValue(objects, cardProps.categoryLabels.fontSize, this.cardFormatSetting.textSize);\r\n }\r\n }\r\n }\r\n\r\n this.updateInternal(value, true /* suppressAnimations */, true /* forceUpdate */);\r\n }\r\n\r\n public onResizing(viewport: IViewport): void {\r\n this.currentViewport = viewport;\r\n this.updateViewportProperties();\r\n this.updateInternal(this.value, true /* suppressAnimations */, true /* forceUpdate */);\r\n }\r\n\r\n private updateViewportProperties() {\r\n let viewport = this.currentViewport;\r\n this.svg.attr('width', viewport.width)\r\n .attr('height', viewport.height);\r\n }\r\n\r\n private setTextProperties(text: string, fontSize: number): void {\r\n Card.cardTextProperties.fontSize = jsCommon.PixelConverter.fromPoint(fontSize);\r\n Card.cardTextProperties.text = text;\r\n }\r\n\r\n private getCardFormatTextSize(): number {\r\n return this.cardFormatSetting.textSize;\r\n }\r\n\r\n public getAdjustedFontHeight(availableWidth: number, textToMeasure: string, seedFontHeight: number) {\r\n let adjustedFontHeight = super.getAdjustedFontHeight(availableWidth, textToMeasure, seedFontHeight);\r\n\r\n return Math.min(adjustedFontHeight, Card.DefaultStyle.card.maxFontSize);\r\n }\r\n\r\n public clear(valueOnly: boolean = false) {\r\n this.svg.select(Card.Value.selector).text('');\r\n\r\n if (!valueOnly)\r\n this.svg.select(Card.Label.selector).text('');\r\n\r\n super.clear();\r\n }\r\n\r\n private updateInternal(target: any, suppressAnimations: boolean, forceUpdate: boolean = false) {\r\n let start = this.value;\r\n let duration = AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n\r\n if (target === undefined) {\r\n if (start !== undefined)\r\n this.clear();\r\n return;\r\n }\r\n\r\n let metaDataColumn = this.metaDataColumn;\r\n let labelSettings = this.cardFormatSetting.labelSettings;\r\n let isDefaultDisplayUnit = labelSettings.displayUnits === 0;\r\n let format = this.getFormatString(metaDataColumn);\r\n let formatter = valueFormatter.create({\r\n format: format,\r\n value: isDefaultDisplayUnit ? target : labelSettings.displayUnits,\r\n precision: dataLabelUtils.getLabelPrecision(labelSettings.precision, format),\r\n displayUnitSystemType: isDefaultDisplayUnit && labelSettings.precision === dataLabelUtils.defaultLabelPrecision ? this.displayUnitSystemType : DisplayUnitSystemType.WholeUnits, // keeps this.displayUnitSystemType as the displayUnitSystemType unless the user changed the displayUnits or the precision\r\n formatSingleValues: isDefaultDisplayUnit ? true : false,\r\n allowFormatBeautification: true,\r\n columnType: metaDataColumn ? metaDataColumn.type : undefined\r\n });\r\n\r\n let formatSettings = this.cardFormatSetting;\r\n let valueTextHeightInPx = jsCommon.PixelConverter.fromPointToPixel(labelSettings.fontSize);\r\n let valueStyles = Card.DefaultStyle.value;\r\n this.setTextProperties(target, this.getCardFormatTextSize());\r\n let labelTextHeightInPx = TextMeasurementService.estimateSvgTextHeight(Card.cardTextProperties);\r\n let labelHeightWithPadding = labelTextHeightInPx + Card.DefaultStyle.label.paddingTop;\r\n\r\n let width = this.currentViewport.width;\r\n let height = this.currentViewport.height;\r\n let translateX = this.getTranslateX(width);\r\n let translateY = (height - labelHeightWithPadding - valueTextHeightInPx) / 2;\r\n let statusGraphicInfo: KpiImageMetadata = getKpiImageMetadata(metaDataColumn, target, KpiImageSize.Big);\r\n\r\n if (this.isScrollable) {\r\n if (!forceUpdate && start === target)\r\n return;\r\n\r\n // We want to format for null/blank/empty string and anything that is not a string\r\n if (start !== target && (_.isEmpty(target) || typeof (target) !== \"string\"))\r\n target = formatter.format(target);\r\n\r\n let label: string = metaDataColumn ? metaDataColumn.displayName : undefined;\r\n let labelData = labelSettings.showCategory\r\n ? [label]\r\n : [];\r\n\r\n let translatedLabelY = this.getTranslateY(valueTextHeightInPx + labelHeightWithPadding + translateY);\r\n let labelElement = this.labelContext\r\n .attr('transform', SVGUtil.translate(translateX, translatedLabelY))\r\n .selectAll('text')\r\n .data(labelData);\r\n\r\n labelElement\r\n .enter()\r\n .append('text')\r\n .attr('class', Card.Label.class);\r\n\r\n labelElement\r\n .text((d) => d)\r\n .style({\r\n 'font-size': jsCommon.PixelConverter.fromPoint(this.getCardFormatTextSize()),\r\n 'fill': labelSettings.categoryLabelColor,\r\n 'text-anchor': this.getTextAnchor()\r\n });\r\n\r\n let labelElementNode = <SVGTextElement>labelElement.node();\r\n if (labelElementNode) {\r\n if (formatSettings.wordWrap)\r\n TextMeasurementService.wordBreak(labelElementNode, width / 2, height - translatedLabelY);\r\n else\r\n labelElement.call(AxisHelper.LabelLayoutStrategy.clip,\r\n width,\r\n TextMeasurementService.svgEllipsis);\r\n }\r\n\r\n labelElement\r\n .append('title')\r\n .text((d) => d);\r\n\r\n labelElement.exit().remove();\r\n\r\n if (statusGraphicInfo) {\r\n // Display card KPI icon\r\n this.graphicsContext.selectAll('text').remove();\r\n this.displayStatusGraphic(statusGraphicInfo, translateX, translateY, valueTextHeightInPx);\r\n }\r\n else {\r\n // Display card text value\r\n this.kpiImage.selectAll('div').remove();\r\n let valueElement = this.graphicsContext\r\n .attr('transform', SVGUtil.translate(translateX, this.getTranslateY(valueTextHeightInPx + translateY)))\r\n .selectAll('text')\r\n .data([target]);\r\n\r\n valueElement\r\n .enter()\r\n .append('text')\r\n .attr('class', Card.Value.class);\r\n\r\n valueElement\r\n .text((d: any) => d)\r\n .style({\r\n 'font-size': jsCommon.PixelConverter.fromPoint(labelSettings.fontSize),\r\n 'fill': labelSettings.labelColor,\r\n 'font-family': valueStyles.fontFamily,\r\n 'text-anchor': this.getTextAnchor(),\r\n });\r\n\r\n valueElement.call(AxisHelper.LabelLayoutStrategy.clip,\r\n width,\r\n TextMeasurementService.svgEllipsis);\r\n\r\n valueElement\r\n .append('title')\r\n .text((d) => d);\r\n\r\n valueElement.exit().remove();\r\n }\r\n }\r\n else {\r\n if (statusGraphicInfo) {\r\n // Display card KPI icon\r\n this.graphicsContext.selectAll('text').remove();\r\n this.displayStatusGraphic(statusGraphicInfo, translateX, translateY, valueTextHeightInPx);\r\n }\r\n else {\r\n this.kpiImage.selectAll('div').remove();\r\n this.doValueTransition(\r\n start,\r\n target,\r\n this.displayUnitSystemType,\r\n this.animationOptions,\r\n duration,\r\n forceUpdate,\r\n formatter\r\n );\r\n\r\n //in order to remove duplicated title values we first remove all and than add a new one\r\n this.graphicsContext.call(tooltipUtils.tooltipUpdate, [target]);\r\n }\r\n }\r\n\r\n this.value = target;\r\n }\r\n\r\n private displayStatusGraphic(statusGraphicInfo: KpiImageMetadata, translateX: number, translateY: number, labelTextSizeInPx: number) {\r\n // Remove existing text\r\n this.graphicsContext.selectAll('text').remove();\r\n\r\n // Create status graphic, if necessary\r\n let kpiImageDiv = this.kpiImage.select('div');\r\n if (!kpiImageDiv || kpiImageDiv.empty())\r\n kpiImageDiv = this.kpiImage.append('div');\r\n\r\n // Style status graphic\r\n kpiImageDiv\r\n .attr('class', statusGraphicInfo.class)\r\n .style('position', 'absolute')\r\n .style('font-size', labelTextSizeInPx + 'px');\r\n\r\n // Layout thrash to get image dimensions (could set as a const in future when icon font is fixed)\r\n let imageWidth = (<HTMLElement>kpiImageDiv.node()).offsetWidth;\r\n let imageHeight = (<HTMLElement>kpiImageDiv.node()).offsetHeight;\r\n\r\n // Position based on image height\r\n kpiImageDiv.style('transform', SVGUtil.translateWithPixels((translateX - (imageWidth / 2)), this.getTranslateY(labelTextSizeInPx + translateY) - imageHeight));\r\n }\r\n\r\n private getDefaultFormatSettings(): CardFormatSetting {\r\n return {\r\n labelSettings: dataLabelUtils.getDefaultCardLabelSettings(Card.DefaultStyle.value.color, Card.DefaultStyle.label.color, Card.DefaultStyle.value.textSize),\r\n wordWrap: false,\r\n textSize: Card.DefaultStyle.label.textSize,\r\n };\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n if (!this.cardFormatSetting)\r\n this.cardFormatSetting = this.getDefaultFormatSettings();\r\n\r\n let formatSettings = this.cardFormatSetting;\r\n let enumeration = new ObjectEnumerationBuilder();\r\n\r\n switch (options.objectName) {\r\n case 'categoryLabels':\r\n dataLabelUtils.enumerateCategoryLabels(enumeration, formatSettings.labelSettings, true /* withFill */, true /* isShowCategory */, formatSettings.textSize);\r\n break;\r\n case 'labels':\r\n let labelSettingOptions: VisualDataLabelsSettingsOptions = {\r\n enumeration: enumeration,\r\n dataLabelsSettings: formatSettings.labelSettings,\r\n show: true,\r\n displayUnits: true,\r\n precision: true,\r\n fontSize: true,\r\n };\r\n dataLabelUtils.enumerateDataLabels(labelSettingOptions);\r\n break;\r\n case 'wordWrap':\r\n enumeration.pushInstance({\r\n objectName: 'wordWrap',\r\n selector: null,\r\n properties: {\r\n show: formatSettings.wordWrap,\r\n },\r\n });\r\n break;\r\n }\r\n\r\n return enumeration.complete();\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n enum OwlHappiness {\r\n Sad = 0,\r\n Meh = 1,\r\n Happy = 2\r\n }\r\n\r\n export class OwlGauge implements IVisual {\r\n private static owlBodySvg = '<svg version=\"1.1\" class=\"owlGaugeBody\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 267.7 291.2\" style=\"enable-background:new 0 0 267.7 291.2;\" xml:space=\"preserve\"> <style type=\"text/css\"> .owlGaugeBody .st0{fill:#A87D50;} .owlGaugeBody .st1{fill:#C2B59B;} .owlGaugeBody .st2{fill:#EB2227;} .owlGaugeBody .st3{fill:#FFFFFF;} .owlGaugeBody .st4{fill:#F9D018;} .owlGaugeBody .st5{fill:none;} .owlGaugeBody .st6{fill:#83381B;} .owlGaugeBody .st7{fill:#231F20;} </style> <g id=\"XMLID_31_\"> <g id=\"XMLID_34_\"> <ellipse id=\"XMLID_21_\" transform=\"matrix(0.9998 1.947640e-02 -1.947640e-02 0.9998 2.8614 -2.5802)\" class=\"st0\" cx=\"133.9\" cy=\"145.6\" rx=\"133.9\" ry=\"145.6\"/> <polygon id=\"XMLID_20_\" class=\"st0\" points=\"199.2,32.8 184,11.3 209,9.7 \"/> <polygon id=\"XMLID_19_\" class=\"st0\" points=\"73.9,31.2 62.1,7.7 87.1,9.8 \"/> <circle id=\"XMLID_18_\" class=\"st1\" cx=\"134.8\" cy=\"189.2\" r=\"89.8\"/> <path id=\"XMLID_17_\" class=\"st2\" d=\"M140.1,88c-2.7,3.8-7.9,4.7-11.7,2c-2.7-1.9-3.9-5.1-3.4-8.1c0,0,9.6-41.8,9.6-41.8l6.9,40.8 C142,83.2,141.6,85.8,140.1,88z\"/> <path id=\"XMLID_16_\" class=\"st3\" d=\"M164.6,16.2c-14.2,0-26.3,9.2-30.6,21.9c-4.1-13.1-16.3-22.6-30.8-22.6 C85.4,15.6,71,30,71,47.8s14.4,32.3,32.3,32.3c14.2,0,26.3-9.2,30.6-21.9c4.1,13.1,16.3,22.6,30.8,22.6 c17.8,0,32.3-14.4,32.3-32.3S182.4,16.2,164.6,16.2z\"/> <path id=\"XMLID_15_\" class=\"st4\" d=\"M122,58.7l23.3-0.1c0,0-9,14.8-10.2,16.6c-1.2,1.9-2.2,0.1-2.2,0.1L122,58.7z\"/> <rect id=\"XMLID_14_\" x=\"-11.4\" y=\"-68.8\" class=\"st5\" width=\"288.3\" height=\"259.7\"/> <g id=\"XMLID_37_\"> <path id=\"XMLID_13_\" class=\"st6\" d=\"M121.6,125.5c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_12_\" class=\"st6\" d=\"M160.1,126.5c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_11_\" class=\"st6\" d=\"M142.4,148.1c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_10_\" class=\"st6\" d=\"M183.1,148.8c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_9_\" class=\"st6\" d=\"M160.9,177.4c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_8_\" class=\"st6\" d=\"M201.6,178c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_7_\" class=\"st6\" d=\"M76.4,177.4c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> <path id=\"XMLID_6_\" class=\"st6\" d=\"M117,178c0,3.7-3.5,6.6-7.7,6.6s-7.7-3-7.7-6.6\"/> <path id=\"XMLID_5_\" class=\"st6\" d=\"M98.6,148.1c0,3.7-3.5,6.6-7.7,6.6c-4.2,0-7.7-3-7.7-6.6\"/> </g> <circle id=\"XMLID_4_\" class=\"st7\" cx=\"164.1\" cy=\"49\" r=\"6.4\"/> <circle id=\"XMLID_3_\" class=\"st7\" cx=\"102.7\" cy=\"47.7\" r=\"6.4\"/> </g> <path id=\"XMLID_2_\" class=\"st0\" d=\"M160.1,140.9c11.1-8.4,55.6-36,55.6-36l4.7,0.8l10.2,38.8c0,0-3,3-9.2,3.1 c-5.1,0.1-45.9-2.6-60.2-3.5C158.1,143.9,157.7,142.7,160.1,140.9z\"/> <path id=\"XMLID_1_\" class=\"st0\" d=\"M110.6,140.8c-11.1-8.4-55.6-36-55.6-36l-4.7,0.8L40,144.4c0,0,3,3,9.2,3.1 c5.1,0.1,45.9-2.6,60.2-3.5C112.5,143.8,113,142.6,110.6,140.8z\"/> </g> </svg>';\r\n private static owlTailSvg = '<svg version=\"1.1\" class=\"owlGaugeTail\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 587.8 295.5\" style=\"enable-background:new 0 0 587.8 295.5;\" xml:space=\"preserve\"> <style type=\"text/css\"> .owlGaugeTail .st0{fill:#3B2416;} .owlGaugeTail .st1{fill:#5B4B43;} .owlGaugeTail .st2{fill:#603A17;} .owlGaugeTail .st3{fill:#726659;} </style> <g id=\"XMLID_55_\"> <path id=\"XMLID_29_\" class=\"st0\" d=\"M85.2,106.2c-27.1,0-49.2,22-49.2,49.2c0,19.1,10.9,35.7,26.9,43.8c0,0,231.2,95.9,231.2,95.9 l-171-171C114.1,113.2,100.5,106.2,85.2,106.2z\"/> <g id=\"XMLID_56_\"> <path id=\"XMLID_28_\" class=\"st1\" d=\"M482.5,86.4c0-27.1-22-49.2-49.2-49.2c-19.1,0-35.7,10.9-43.8,26.9c0,0-95.9,231.2-95.9,231.2 l171-171C475.5,115.3,482.5,101.7,482.5,86.4z\"/> <path id=\"XMLID_27_\" class=\"st2\" d=\"M573.5,281.3c19.2-19.2,19.2-50.3,0-69.5c-13.5-13.5-33-17.5-50-12c0,0-231.3,95.7-231.3,95.7 l241.8,0C548,296.9,562.6,292.1,573.5,281.3z\"/> <path id=\"XMLID_26_\" class=\"st3\" d=\"M279.9,14.4c-19.2-19.2-50.3-19.2-69.5,0c-13.5,13.5-17.5,33-12,50c0,0,95.7,231.3,95.7,231.3 L294,54C295.4,39.8,290.7,25.2,279.9,14.4z\"/> <path id=\"XMLID_25_\" class=\"st2\" d=\"M105.3,86.4c0-27.1,22-49.2,49.2-49.2c19.1,0,35.7,10.9,43.8,26.9c0,0,95.9,231.2,95.9,231.2 l-171-171C112.3,115.3,105.3,101.7,105.3,86.4z\"/> <path id=\"XMLID_24_\" class=\"st2\" d=\"M14.4,281.4c-19.2-19.2-19.2-50.3,0-69.5c13.5-13.5,33-17.5,50-12c0,0,231.3,95.7,231.3,95.7 l-241.8,0C39.8,297,25.2,292.3,14.4,281.4z\"/> <path id=\"XMLID_23_\" class=\"st2\" d=\"M308.2,14c19.2-19.2,50.3-19.2,69.5,0c13.5,13.5,17.5,33,12,50c0,0-95.7,231.3-95.7,231.3 l0-241.8C292.6,39.4,297.4,24.8,308.2,14z\"/> <path id=\"XMLID_22_\" class=\"st0\" d=\"M503.2,106c27.1,0,49.2,22,49.2,49.2c0,19.1-10.9,35.7-26.9,43.8c0,0-231.2,95.9-231.2,95.9 l171-171C474.2,113,487.8,106,503.2,106z\"/> </g> </g> </svg>';\r\n private static visualBgSvg = '<svg version=\"1.1\" class=\"owlGaugeBg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"123.8 94.9 349.1 175.3\" style=\"enable-background:new 123.8 94.9 349.1 175.3;\" xml:space=\"preserve\"> <style type=\"text/css\"> .owlGaugeBg .st0{fill:#EF4137;} .owlGaugeBg .st1{fill:#FAAF42;} .owlGaugeBg .st2{fill:#F15B2A;} .owlGaugeBg .st3{fill:#F69321;} </style> <g id=\"XMLID_10_\"> <path id=\"XMLID_8_\" class=\"st0\" d=\"M174.3,158c-16.1,0-29.2,13.1-29.2,29.2c0,11.4,6.5,21.2,16,26.1l137.3,57L196.9,168.7 C191.5,162.2,183.4,158,174.3,158z\"/> <g id=\"XMLID_11_\"> <path id=\"XMLID_7_\" class=\"st1\" d=\"M410.2,146.3c0-16.1-13.1-29.2-29.2-29.2c-11.4,0-21.2,6.5-26,16l-57,137.5L399.5,169 C406.1,163.5,410.2,155.4,410.2,146.3z\"/> <path id=\"XMLID_6_\" class=\"st0\" d=\"M464.3,262.2c11.4-11.4,11.4-29.9,0-41.3c-8-8-19.6-10.4-29.7-7.1l-137.4,56.9h143.6 C449.2,271.4,457.9,268.6,464.3,262.2z\"/> <path id=\"XMLID_5_\" class=\"st2\" d=\"M290,103.5c-11.4-11.4-29.9-11.4-41.3,0c-8,8-10.4,19.6-7.1,29.7l56.8,137.5V127 C299.2,118.6,296.4,109.9,290,103.5z\"/> <path id=\"XMLID_4_\" class=\"st3\" d=\"M186.3,146.3c0-16.1,13.1-29.2,29.2-29.2c11.4,0,21.2,6.5,26,16l57,137.5L197,168.8 C190.5,163.5,186.3,155.4,186.3,146.3z\"/> <path id=\"XMLID_3_\" class=\"st2\" d=\"M132.3,262.2c-11.4-11.4-11.4-29.9,0-41.3c8-8,19.6-10.4,29.7-7.1l137.4,56.9H155.8 C147.4,271.5,138.7,268.7,132.3,262.2z\"/> <path id=\"XMLID_2_\" class=\"st3\" d=\"M306.8,103.2c11.4-11.4,29.9-11.4,41.3,0c8,8,10.4,19.6,7.1,29.7l-56.8,137.5V126.7 C297.5,118.3,300.3,109.7,306.8,103.2z\"/> <path id=\"XMLID_1_\" class=\"st2\" d=\"M422.5,157.9c16.1,0,29.2,13.1,29.2,29.2c0,11.4-6.5,21.2-16,26.1l-137.3,57L400,168.6 C405.3,162.1,413.4,157.9,422.5,157.9z\"/> </g> </g> </svg>';\r\n\r\n private static owlBodyHeightMultiplier = 291.2 / 267.7;\r\n private static owlTailHeightMultiplier = 295.5 / 587.8;\r\n private static visualBgHeightMultiplier = 295.5 / 587.8;\r\n\r\n private static OwlDemoMode = false;\r\n\r\n public static capabilities: VisualCapabilities = {\r\n dataRoles: [\r\n {\r\n displayName: 'Category',\r\n name: 'Category',\r\n kind: powerbi.VisualDataRoleKind.Grouping,\r\n },\r\n {\r\n displayName: 'Y Axis',\r\n name: 'Y',\r\n kind: powerbi.VisualDataRoleKind.Measure,\r\n },\r\n ],\r\n dataViewMappings: [{\r\n categories: {\r\n for: { in: 'Category' },\r\n dataReductionAlgorithm: { top: {} }\r\n },\r\n values: {\r\n select: [{ bind: { to: 'Y' } }]\r\n },\r\n }]\r\n };\r\n\r\n public static converter(dataView: DataView): any {\r\n return {};\r\n }\r\n\r\n private static getGaugeData(dataView: DataView): GaugeTargetData {\r\n var settings: GaugeTargetData = {\r\n max: 100,\r\n min: 0,\r\n target: undefined,\r\n total: 0,\r\n tooltipItems: []\r\n };\r\n\r\n if (dataView && dataView.categorical && dataView.categorical.values && dataView.metadata && dataView.metadata.columns) {\r\n var values = dataView.categorical.values;\r\n var metadataColumns = dataView.metadata.columns;\r\n\r\n debug.assert(metadataColumns.length >= values.length, 'length');\r\n\r\n for (var i = 0; i < values.length; i++) {\r\n var col = metadataColumns[i],\r\n value = values[i].values[0] || 0;\r\n if (col && col.roles) {\r\n if (col.roles[gaugeRoleNames.y]) {\r\n settings.total = value;\r\n if (value)\r\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: converterHelper.formatFromMetadataColumn(value, values[i].source, Gauge.formatStringProp)});\r\n } else if (col.roles[gaugeRoleNames.minValue]) {\r\n settings.min = value;\r\n } else if (col.roles[gaugeRoleNames.maxValue]) {\r\n settings.max = value;\r\n } else if (col.roles[gaugeRoleNames.targetValue]) {\r\n settings.target = value;\r\n if (value)\r\n settings.tooltipItems.push({ displayName: values[i].source.displayName, value: converterHelper.formatFromMetadataColumn(value, values[i].source, Gauge.formatStringProp)});\r\n }\r\n }\r\n }\r\n }\r\n\r\n return settings;\r\n }\r\n\r\n private rootElem: JQuery;\r\n private svgBgElem: JQuery;\r\n private svgBodyElem: JQuery;\r\n private svgTailElem: JQuery;\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.rootElem = options.element;\r\n this.rootElem.addClass('owlGaugeVisual');\r\n\r\n this.svgTailElem = $(OwlGauge.owlTailSvg);\r\n this.svgBgElem = $(OwlGauge.visualBgSvg);\r\n this.svgBodyElem = $(OwlGauge.owlBodySvg);\r\n\r\n this.rootElem.append(this.svgBgElem).append(this.svgTailElem).append(this.svgBodyElem);\r\n\r\n if (OwlGauge.OwlDemoMode) {\r\n window.setInterval(() => {\r\n var randomPercentage = Math.random() * 100 + 1;\r\n this.updateGauge(randomPercentage);\r\n }, 2000);\r\n }\r\n\r\n this.updateViewportSize(options.viewport.width, options.viewport.height);\r\n }\r\n\r\n public update(options: VisualUpdateOptions) {\r\n this.updateViewportSize(options.viewport.width, options.viewport.height);\r\n\r\n var dataView = options.dataViews.length > 0 ? options.dataViews[0] : null;\r\n\r\n if (dataView) {\r\n var gaugeData = OwlGauge.getGaugeData(options.dataViews[0]);\r\n\r\n var percentage = (gaugeData.total - gaugeData.min) / (gaugeData.max - gaugeData.min);\r\n this.updateGauge(percentage * 100 | 0);\r\n }\r\n else this.updateGauge(0);\r\n }\r\n\r\n private updateGauge(percentage: number) {\r\n if (percentage >= 0 && percentage <= 100) {\r\n var rotationDeg = -180 + (180 * percentage/100);\r\n this.svgBgElem.css({ transform: 'rotate(' + rotationDeg + 'deg)' });\r\n\r\n if (percentage >= 66) {\r\n this.happinessLevel = OwlHappiness.Happy;\r\n }\r\n else if (percentage >= 33) {\r\n this.happinessLevel = OwlHappiness.Meh;\r\n }\r\n else {\r\n this.happinessLevel = OwlHappiness.Sad;\r\n }\r\n }\r\n }\r\n\r\n private set happinessLevel(level: OwlHappiness) {\r\n this.rootElem.removeClass('sad').removeClass('meh').removeClass('happy');\r\n\r\n switch (level) {\r\n case OwlHappiness.Sad:\r\n this.rootElem.addClass('sad');\r\n break;\r\n case OwlHappiness.Meh:\r\n this.rootElem.addClass('meh');\r\n break;\r\n case OwlHappiness.Happy:\r\n this.rootElem.addClass('happy');\r\n break;\r\n default:\r\n console.log('Well, this is interesting...');\r\n }\r\n }\r\n\r\n private updateViewportSize(width: number, height: number) {\r\n var smoothingFn = window.setImmediate || window.requestAnimationFrame;\r\n\r\n smoothingFn(() => {\r\n this.rootElem.css({\r\n height: height,\r\n width: width\r\n });\r\n\r\n this.svgBodyElem.height(this.svgBodyElem.width() * OwlGauge.owlBodyHeightMultiplier);\r\n this.svgBgElem.height(this.svgBgElem.width() * OwlGauge.visualBgHeightMultiplier);\r\n this.svgTailElem.height(this.svgTailElem.width() * OwlGauge.owlTailHeightMultiplier);\r\n });\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import IStringResourceProvider = jsCommon.IStringResourceProvider;\r\n\r\n export class NoMapLocationWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'NoMapLocation';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'NoMapLocationMessage';\r\n let titleKey: string = 'NoMapLocationKey';\r\n let detailKey: string = 'NoMapLocationValue';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: resourceProvider.get(titleKey),\r\n detail: resourceProvider.get(detailKey),\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class FilledMapWithoutValidGeotagCategoryWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'NoValidGeotaggedCategory';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'NoValidGeotaggedCategoryMessage';\r\n let titleKey: string = 'NoValidGeotaggedCategoryKey';\r\n let detailKey: string = 'NoValidGeotaggedCategoryValue';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: resourceProvider.get(titleKey),\r\n detail: resourceProvider.get(detailKey),\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class GeometryCulledWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'GeometryCulledWarning';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'GeometryCulledWarningMessage';\r\n let titleKey: string = 'GeometryCulledWarningKey';\r\n let detailKey: string = 'GeometryCulledWarningVal';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: resourceProvider.get(titleKey),\r\n detail: resourceProvider.get(detailKey),\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class NegativeValuesNotSupportedWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'NegativeValuesNotSupported';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n const messageKey: string = 'VisualWarning_NegativeValues';\r\n\r\n const visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: '',\r\n detail: '',\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class AllNegativeValuesWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'AllNegativeValuesNotSupported';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'VisualWarning_AllNegativeValues';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: '',\r\n detail: '',\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class NaNNotSupportedWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'NaNNotSupported';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'VisualWarning_NanValues';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: '',\r\n detail: '',\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class InfinityValuesNotSupportedWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'InfinityValuesNotSupported';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'VisualWarning_InfinityValues';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: '',\r\n detail: '',\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class ValuesOutOfRangeWarning implements IVisualWarning {\r\n public get code(): string {\r\n return 'ValuesOutOfRange';\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'VisualWarning_VisualizationOutOfRange';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: '',\r\n detail: '',\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class ZeroValueWarning implements IVisualWarning {\r\n public get code(): string {\r\n return \"ZeroValuesNotSupported\";\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'VisualWarning_ZeroValues'; \r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: '',\r\n detail: '',\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class VisualKPIDataMissingWarning implements IVisualWarning {\r\n public get code(): string {\r\n return \"VisualKPIDataMissing\";\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'Visual_KPI_DataMissing';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: '',\r\n detail: '',\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n export class ScriptVisualRefreshWarning implements IVisualWarning {\r\n public get code(): string {\r\n return \"ScriptVisualNotRefreshed\";\r\n }\r\n\r\n public getMessages(resourceProvider: IStringResourceProvider): IVisualErrorMessage {\r\n let messageKey: string = 'ScriptVisualRefreshWarningMessage';\r\n let detailKey: string = 'ScriptVisualRefreshWarningValue';\r\n\r\n let visualMessage: IVisualErrorMessage = {\r\n message: resourceProvider.get(messageKey),\r\n title: resourceProvider.get(messageKey),\r\n detail: resourceProvider.get(detailKey),\r\n };\r\n\r\n return visualMessage;\r\n }\r\n }\r\n\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in\r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import PixelConverter = jsCommon.PixelConverter;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n export interface WaterfallChartData extends CartesianData {\r\n series: WaterfallChartSeries[];\r\n categories: any[];\r\n valuesMetadata: DataViewMetadataColumn;\r\n legend: LegendData;\r\n hasHighlights: boolean;\r\n categoryMetadata: DataViewMetadataColumn;\r\n positionMax: number;\r\n positionMin: number;\r\n sentimentColors: WaterfallChartSentimentColors;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n axesLabels: ChartAxesLabels;\r\n }\r\n\r\n export interface WaterfallChartSeries extends CartesianSeries {\r\n data: WaterfallChartDataPoint[];\r\n }\r\n\r\n export interface WaterfallChartDataPoint extends CartesianDataPoint, SelectableDataPoint, TooltipEnabledDataPoint, LabelEnabledDataPoint {\r\n position: number;\r\n color: string;\r\n highlight: boolean;\r\n key: string;\r\n isTotal?: boolean;\r\n }\r\n\r\n export interface WaterfallChartConstructorOptions extends CartesianVisualConstructorOptions {\r\n }\r\n\r\n export interface WaterfallChartSentimentColors {\r\n increaseFill: Fill;\r\n decreaseFill: Fill;\r\n totalFill: Fill;\r\n }\r\n\r\n export interface WaterfallLayout extends CategoryLayout, ILabelLayout {\r\n categoryWidth: number;\r\n }\r\n\r\n export class WaterfallChart implements ICartesianVisual {\r\n public static formatStringProp: DataViewObjectPropertyIdentifier = { objectName: 'general', propertyName: 'formatString' };\r\n private static WaterfallClassName = 'waterfallChart';\r\n private static MainGraphicsContextClassName = 'mainGraphicsContext';\r\n private static IncreaseLabel = \"Waterfall_IncreaseLabel\";\r\n private static DecreaseLabel = \"Waterfall_DecreaseLabel\";\r\n private static TotalLabel = \"Waterfall_TotalLabel\";\r\n private static CategoryValueClasses: ClassAndSelector = createClassAndSelector('column');\r\n private static WaterfallConnectorClasses: ClassAndSelector = createClassAndSelector('waterfall-connector');\r\n\r\n private static defaultTotalColor = \"#00b8aa\";\r\n private static validLabelPositions = [RectLabelPosition.OutsideEnd, RectLabelPosition.InsideEnd];\r\n private static validZeroLabelPosition = [RectLabelPosition.OutsideEnd, RectLabelPosition.OutsideBase];\r\n\r\n private svg: D3.Selection;\r\n private mainGraphicsContext: D3.Selection;\r\n private labelGraphicsContext: D3.Selection;\r\n private mainGraphicsSVG: D3.Selection;\r\n private xAxisProperties: IAxisProperties;\r\n private yAxisProperties: IAxisProperties;\r\n private currentViewport: IViewport;\r\n private margin: IMargin;\r\n private data: WaterfallChartData;\r\n private element: JQuery;\r\n private isScrollable: boolean;\r\n private tooltipsEnabled: boolean;\r\n\r\n /**\r\n * Note: If we overflowed horizontally then this holds the subset of data we should render.\r\n */\r\n private clippedData: WaterfallChartData;\r\n\r\n private style: IVisualStyle;\r\n private colors: IDataColorPalette;\r\n private hostServices: IVisualHostServices;\r\n private cartesianVisualHost: ICartesianVisualHost;\r\n private interactivity: InteractivityOptions;\r\n private options: CartesianVisualInitOptions;\r\n private interactivityService: IInteractivityService;\r\n private layout: WaterfallLayout;\r\n\r\n constructor(options: WaterfallChartConstructorOptions) {\r\n this.isScrollable = options.isScrollable;\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n this.interactivityService = options.interactivityService;\r\n }\r\n\r\n public init(options: CartesianVisualInitOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n this.svg = options.svg;\r\n this.svg.classed(WaterfallChart.WaterfallClassName, true);\r\n this.style = options.style;\r\n this.currentViewport = options.viewport;\r\n this.hostServices = options.host;\r\n this.interactivity = options.interactivity;\r\n this.cartesianVisualHost = options.cartesianHost;\r\n this.options = options;\r\n this.element = options.element;\r\n this.colors = this.style.colorPalette.dataColors;\r\n this.mainGraphicsSVG = this.svg.append('svg');\r\n this.mainGraphicsContext = this.mainGraphicsSVG.append('g')\r\n .classed(WaterfallChart.MainGraphicsContextClassName, true);\r\n this.labelGraphicsContext = this.mainGraphicsSVG.append('g')\r\n .classed(NewDataLabelUtils.labelGraphicsContextClass.class, true);\r\n }\r\n\r\n public static converter(\r\n dataView: DataView,\r\n palette: IDataColorPalette,\r\n hostServices: IVisualHostServices,\r\n dataLabelSettings: VisualDataLabelsSettings,\r\n sentimentColors: WaterfallChartSentimentColors,\r\n interactivityService: IInteractivityService,\r\n tooltipsEnabled: boolean = true): WaterfallChartData {\r\n debug.assertValue(palette, 'palette');\r\n\r\n let reader = data.createIDataViewCategoricalReader(dataView);\r\n\r\n let formatStringProp = WaterfallChart.formatStringProp;\r\n let categories = dataView.categorical.categories || [];\r\n\r\n let increaseColor = sentimentColors.increaseFill.solid.color;\r\n let decreaseColor = sentimentColors.decreaseFill.solid.color;\r\n let totalColor = sentimentColors.totalFill.solid.color;\r\n\r\n let totalLabel = hostServices.getLocalizedString(WaterfallChart.TotalLabel);\r\n let increaseLabel = hostServices.getLocalizedString(WaterfallChart.IncreaseLabel);\r\n let decreaseLabel = hostServices.getLocalizedString(WaterfallChart.DecreaseLabel);\r\n\r\n let legend: LegendDataPoint[] = [\r\n {\r\n label: increaseLabel,\r\n color: increaseColor,\r\n icon: LegendIcon.Box,\r\n identity: SelectionIdBuilder.builder().withMeasure('increase').createSelectionId(),\r\n selected: false,\r\n }, {\r\n label: decreaseLabel,\r\n color: decreaseColor,\r\n icon: LegendIcon.Box,\r\n identity: SelectionIdBuilder.builder().withMeasure('decrease').createSelectionId(),\r\n selected: false,\r\n }, {\r\n label: totalLabel,\r\n color: totalColor,\r\n icon: LegendIcon.Box,\r\n identity: SelectionIdBuilder.builder().withMeasure('total').createSelectionId(),\r\n selected: false,\r\n }];\r\n\r\n /**\r\n * The position represents the starting point for each bar,\r\n * for any value it is the sum of all previous values.\r\n * Values > 0 are considered gains, values < 0 are losses.\r\n */\r\n let pos = 0, posMin = 0, posMax = 0;\r\n let dataPoints: WaterfallChartDataPoint[] = [];\r\n let categoryValues: any[] = [];\r\n let categoryMetadata: DataViewMetadataColumn;\r\n let valuesMetadata: DataViewMetadataColumn = undefined;\r\n if (reader.hasValues(\"Y\")) {\r\n valuesMetadata = reader.getValueMetadataColumn(\"Y\");\r\n let labelFormatString = valuesMetadata.format;\r\n if (_.isEmpty(categories)) {\r\n // We have values but no category, just show the total bar.\r\n pos = posMax = reader.getValue(\"Y\", 0);\r\n posMin = 0;\r\n }\r\n else {\r\n let categoryColumn = categories[0];\r\n categoryMetadata = categoryColumn.source;\r\n categoryValues = categoryColumn.values.slice();\r\n categoryValues.push(totalLabel);\r\n\r\n for (var categoryIndex = 0, catLen = reader.getCategoryCount(); categoryIndex < catLen; categoryIndex++) {\r\n let category = categoryValues[categoryIndex];\r\n let value = reader.getValue(\"Y\", categoryIndex) || 0;\r\n let identity = SelectionIdBuilder.builder()\r\n .withCategory(categoryColumn, categoryIndex)\r\n .withMeasure(valuesMetadata.queryName)\r\n .createSelectionId();\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n\r\n tooltipInfo.push({\r\n displayName: categoryMetadata.displayName,\r\n value: converterHelper.formatFromMetadataColumn(category, categoryMetadata, formatStringProp),\r\n });\r\n\r\n if (value != null) {\r\n tooltipInfo.push({\r\n displayName: valuesMetadata.displayName,\r\n value: converterHelper.formatFromMetadataColumn(value, valuesMetadata, formatStringProp),\r\n });\r\n }\r\n }\r\n let color = value > 0 ? increaseColor : decreaseColor;\r\n\r\n dataPoints.push({\r\n value: value,\r\n position: pos,\r\n color: color,\r\n categoryValue: category,\r\n categoryIndex: categoryIndex,\r\n seriesIndex: 0,\r\n selected: false,\r\n identity: identity,\r\n highlight: false,\r\n key: identity.getKey(),\r\n tooltipInfo: tooltipInfo,\r\n labelFill: dataLabelSettings.labelColor,\r\n labelFormatString: labelFormatString,\r\n });\r\n\r\n pos += value;\r\n if (pos > posMax)\r\n posMax = pos;\r\n if (pos < posMin)\r\n posMin = pos;\r\n }\r\n }\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n\r\n if (tooltipsEnabled) {\r\n tooltipInfo = [];\r\n if (categoryMetadata) {\r\n tooltipInfo.push({\r\n displayName: categoryMetadata.displayName,\r\n value: totalLabel,\r\n });\r\n }\r\n if (pos != null) {\r\n tooltipInfo.push({\r\n displayName: valuesMetadata.displayName,\r\n value: converterHelper.formatFromMetadataColumn(pos, valuesMetadata, formatStringProp),\r\n });\r\n }\r\n }\r\n let totalIdentity = SelectionId.createNull();\r\n dataPoints.push({\r\n value: pos,\r\n position: 0,\r\n color: totalColor,\r\n categoryValue: totalLabel,\r\n categoryIndex: categoryIndex,\r\n identity: totalIdentity,\r\n seriesIndex: 0,\r\n selected: false,\r\n highlight: false,\r\n key: totalIdentity.getKey(),\r\n tooltipInfo: tooltipInfo,\r\n labelFill: dataLabelSettings.labelColor,\r\n labelFormatString: labelFormatString,\r\n isTotal: true,\r\n });\r\n }\r\n\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(dataPoints);\r\n }\r\n\r\n let xAxisProperties = CartesianHelper.getCategoryAxisProperties(dataView.metadata);\r\n let yAxisProperties = CartesianHelper.getValueAxisProperties(dataView.metadata);\r\n let axesLabels = converterHelper.createAxesLabels(xAxisProperties, yAxisProperties, categoryMetadata, [valuesMetadata]);\r\n\r\n return {\r\n series: [{ data: dataPoints }],\r\n categories: categoryValues,\r\n categoryMetadata: categoryMetadata,\r\n valuesMetadata: valuesMetadata,\r\n legend: { dataPoints: legend },\r\n hasHighlights: false,\r\n positionMin: posMin,\r\n positionMax: posMax,\r\n dataLabelsSettings: dataLabelSettings,\r\n sentimentColors: sentimentColors,\r\n axesLabels: { x: axesLabels.xAxisLabel, y: axesLabels.yAxisLabel },\r\n };\r\n }\r\n\r\n public setData(dataViews: DataView[]): void {\r\n debug.assertValue(dataViews, \"dataViews\");\r\n\r\n let sentimentColors = this.getSentimentColorsFromObjects(null);\r\n let dataView = dataViews.length > 0 ? dataViews[0] : undefined;\r\n\r\n this.data = <WaterfallChartData> {\r\n series: [{ data: [] }],\r\n categories: [],\r\n valuesMetadata: null,\r\n legend: { dataPoints: [], },\r\n hasHighlights: false,\r\n categoryMetadata: null,\r\n scalarCategoryAxis: false,\r\n positionMax: 0,\r\n positionMin: 0,\r\n dataLabelsSettings: dataLabelUtils.getDefaultLabelSettings(/* show */ false, /* labelColor */ undefined),\r\n sentimentColors: sentimentColors,\r\n axesLabels: { x: null, y: null },\r\n };\r\n\r\n if (dataView) {\r\n if (dataView.metadata && dataView.metadata.objects) {\r\n let objects = dataView.metadata.objects;\r\n\r\n let labelsObj = <DataLabelObject>objects['labels'];\r\n if (labelsObj) {\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, this.data.dataLabelsSettings);\r\n }\r\n sentimentColors = this.getSentimentColorsFromObjects(objects);\r\n }\r\n\r\n if (dataView.categorical) {\r\n this.data = WaterfallChart.converter(dataView, this.colors, this.hostServices, this.data.dataLabelsSettings, sentimentColors, this.interactivityService, this.tooltipsEnabled);\r\n }\r\n }\r\n }\r\n\r\n public enumerateObjectInstances(enumeration: ObjectEnumerationBuilder, options: EnumerateVisualObjectInstancesOptions): void {\r\n switch (options.objectName) {\r\n case 'sentimentColors':\r\n this.enumerateSentimentColors(enumeration);\r\n break;\r\n case 'labels':\r\n let labelSettingOptions: VisualDataLabelsSettingsOptions = {\r\n enumeration: enumeration,\r\n dataLabelsSettings: this.data.dataLabelsSettings,\r\n show: true,\r\n displayUnits: true,\r\n precision: true,\r\n fontSize: true,\r\n };\r\n dataLabelUtils.enumerateDataLabels(labelSettingOptions);\r\n break;\r\n }\r\n }\r\n\r\n private enumerateSentimentColors(enumeration: ObjectEnumerationBuilder): void {\r\n let sentimentColors = this.data.sentimentColors;\r\n\r\n enumeration.pushInstance({\r\n selector: null,\r\n properties: {\r\n increaseFill: sentimentColors.increaseFill,\r\n decreaseFill: sentimentColors.decreaseFill,\r\n totalFill: sentimentColors.totalFill\r\n },\r\n objectName: 'sentimentColors'\r\n });\r\n }\r\n\r\n public calculateLegend(): LegendData {\r\n // TODO: support interactive legend\r\n return this.data.legend;\r\n }\r\n\r\n public hasLegend(): boolean {\r\n // Waterfall legend is more like a color-key, so just return true\r\n return true;\r\n }\r\n\r\n private static createClippedDataIfOverflowed(data: WaterfallChartData, renderableDataCount: number): WaterfallChartData {\r\n let clipped: WaterfallChartData = data;\r\n let dataPoints: WaterfallChartDataPoint[] = data.series[0].data;\r\n\r\n if (data && renderableDataCount < dataPoints.length) {\r\n clipped = Prototype.inherit(data);\r\n clipped.series = [{ data: dataPoints.slice(0, renderableDataCount) }];\r\n clipped.categories = data.categories.slice(0, renderableDataCount);\r\n }\r\n\r\n return clipped;\r\n }\r\n\r\n public calculateAxesProperties(options: CalculateScaleAndDomainOptions): IAxisProperties[] {\r\n debug.assertValue(options, 'options');\r\n\r\n this.currentViewport = options.viewport;\r\n this.margin = options.margin;\r\n let data = this.clippedData = this.data;\r\n let categoryCount = data.categories.length;\r\n let preferredPlotArea = this.getPreferredPlotArea(false, categoryCount, CartesianChart.MinOrdinalRectThickness);\r\n\r\n let cartesianLayout = CartesianChart.getLayout(\r\n null,\r\n {\r\n availableWidth: preferredPlotArea.width,\r\n categoryCount: categoryCount,\r\n domain: null,\r\n isScalar: false,\r\n isScrollable: this.isScrollable,\r\n trimOrdinalDataOnOverflow: options.trimOrdinalDataOnOverflow\r\n });\r\n\r\n // In the case that we have overflowed horizontally we want to clip the data and use that to calculate the axes on the dashboard. \r\n if (!this.isScrollable) {\r\n data = this.clippedData = WaterfallChart.createClippedDataIfOverflowed(data, cartesianLayout.categoryCount);\r\n }\r\n\r\n let xAxisCreationOptions = WaterfallChart.getXAxisCreationOptions(data, preferredPlotArea.width, cartesianLayout, options);\r\n let yAxisCreationOptions = WaterfallChart.getYAxisCreationOptions(data, preferredPlotArea.height, options);\r\n\r\n let xAxisProperties = this.xAxisProperties = AxisHelper.createAxis(xAxisCreationOptions);\r\n let yAxisProperties = this.yAxisProperties = AxisHelper.createAxis(yAxisCreationOptions);\r\n\r\n let categoryWidth = this.xAxisProperties.categoryThickness * (1 - CartesianChart.InnerPaddingRatio);\r\n\r\n let formattersCache = dataLabelUtils.createColumnFormatterCacheManager();\r\n let labelSettings = data.dataLabelsSettings;\r\n let value2: number = WaterfallChart.getDisplayUnitValueFromAxisFormatter(yAxisProperties, labelSettings);\r\n\r\n this.layout = {\r\n categoryCount: cartesianLayout.categoryCount,\r\n categoryThickness: cartesianLayout.categoryThickness,\r\n isScalar: cartesianLayout.isScalar,\r\n outerPaddingRatio: cartesianLayout.outerPaddingRatio,\r\n categoryWidth: categoryWidth,\r\n labelText: (d: WaterfallChartDataPoint) => {\r\n //total value has no identity\r\n let formatter = formattersCache.getOrCreate(d.labelFormatString, labelSettings, value2);\r\n return dataLabelUtils.getLabelFormattedText({ label: formatter.format(d.value) });\r\n },\r\n labelLayout: dataLabelUtils.getLabelLayoutXYForWaterfall(xAxisProperties, categoryWidth, yAxisProperties, yAxisCreationOptions.dataDomain),\r\n filter: (d: WaterfallChartDataPoint) => {\r\n return dataLabelUtils.doesDataLabelFitInShape(d, yAxisProperties, this.layout);\r\n },\r\n style: {\r\n 'fill': (d: WaterfallChartDataPoint) => {\r\n if (d.isLabelInside)\r\n return dataLabelUtils.defaultInsideLabelColor;\r\n return d.labelFill;\r\n },\r\n },\r\n };\r\n\r\n this.xAxisProperties.axisLabel = options.showCategoryAxisLabel ? data.axesLabels.x : null;\r\n this.yAxisProperties.axisLabel = options.showValueAxisLabel ? data.axesLabels.y : null;\r\n\r\n return [xAxisProperties, yAxisProperties];\r\n }\r\n\r\n private static getDisplayUnitValueFromAxisFormatter(yAxisProperties: IAxisProperties, labelSettings: VisualDataLabelsSettings): number {\r\n return (yAxisProperties.formatter && yAxisProperties.formatter.displayUnit && labelSettings.displayUnits === 0) ? yAxisProperties.formatter.displayUnit.value : null;\r\n }\r\n\r\n private static lookupXValue(data: WaterfallChartData, index: number, type: ValueType): any {\r\n let dataPoints: WaterfallChartDataPoint[] = data.series[0].data;\r\n\r\n if (index === dataPoints.length - 1)\r\n // Total\r\n return dataPoints[index].categoryValue;\r\n else\r\n return CartesianHelper.lookupXValue(data, index, type, false);\r\n }\r\n\r\n public static getXAxisCreationOptions(data: WaterfallChartData, width: number, layout: CategoryLayout, options: CalculateScaleAndDomainOptions): CreateAxisOptions {\r\n debug.assertValue(data, 'data');\r\n debug.assertValue(options, 'options');\r\n\r\n let categoryDataType: ValueType = AxisHelper.getCategoryValueType(data.categoryMetadata);\r\n\r\n let domain = AxisHelper.createDomain(data.series, categoryDataType, /* isScalar */ false, options.forcedXDomain, options.ensureXDomain);\r\n\r\n let categoryThickness = layout.categoryThickness;\r\n let outerPadding = categoryThickness * layout.outerPaddingRatio;\r\n\r\n return <CreateAxisOptions> {\r\n pixelSpan: width,\r\n dataDomain: domain,\r\n metaDataColumn: data.categoryMetadata,\r\n formatString: valueFormatter.getFormatString(data.categoryMetadata, WaterfallChart.formatStringProp),\r\n isScalar: false,\r\n outerPadding: outerPadding,\r\n categoryThickness: categoryThickness,\r\n getValueFn: (index, type) => WaterfallChart.lookupXValue(data, index, type),\r\n forcedTickCount: options.forcedTickCount,\r\n isCategoryAxis: true,\r\n axisDisplayUnits: options.categoryAxisDisplayUnits,\r\n axisPrecision: options.categoryAxisPrecision\r\n };\r\n }\r\n\r\n public static getYAxisCreationOptions(data: WaterfallChartData, height: number, options: CalculateScaleAndDomainOptions): CreateAxisOptions {\r\n debug.assertValue(data, 'data');\r\n debug.assertValue(options, 'options');\r\n\r\n let combinedDomain = AxisHelper.combineDomain(options.forcedYDomain, [data.positionMin, data.positionMax], options.ensureYDomain);\r\n\r\n return <CreateAxisOptions> {\r\n pixelSpan: height,\r\n dataDomain: combinedDomain,\r\n isScalar: true,\r\n isVertical: true,\r\n metaDataColumn: data.valuesMetadata,\r\n formatString: valueFormatter.getFormatString(data.valuesMetadata, WaterfallChart.formatStringProp),\r\n outerPadding: 0,\r\n forcedTickCount: options.forcedTickCount,\r\n useTickIntervalForDisplayUnits: true,\r\n isCategoryAxis: false,\r\n axisDisplayUnits: options.valueAxisDisplayUnits,\r\n axisPrecision: options.valueAxisPrecision\r\n };\r\n }\r\n\r\n public getPreferredPlotArea(isScalar: boolean, categoryCount: number, categoryThickness: number): IViewport {\r\n return CartesianChart.getPreferredPlotArea(\r\n categoryCount,\r\n categoryThickness,\r\n this.currentViewport,\r\n this.isScrollable,\r\n isScalar,\r\n this.margin);\r\n }\r\n\r\n public getVisualCategoryAxisIsScalar(): boolean {\r\n return false;\r\n }\r\n\r\n public overrideXScale(xProperties: IAxisProperties): void {\r\n this.xAxisProperties = xProperties;\r\n }\r\n\r\n public setFilteredData(startIndex: number, endIndex: number): any {\r\n let data = this.clippedData = Prototype.inherit(this.data);\r\n\r\n data.series = [{ data: data.series[0].data.slice(startIndex, endIndex) }];\r\n data.categories = data.categories.slice(startIndex, endIndex);\r\n\r\n return data;\r\n }\r\n\r\n private createRects(data: WaterfallChartDataPoint[]): D3.UpdateSelection {\r\n let mainGraphicsContext = this.mainGraphicsContext;\r\n let colsSelection = mainGraphicsContext.selectAll(WaterfallChart.CategoryValueClasses.selector);\r\n let cols = colsSelection.data(data, (d: WaterfallChartDataPoint) => d.key);\r\n\r\n cols\r\n .enter()\r\n .append('rect')\r\n .attr('class', (d: WaterfallChartDataPoint) => WaterfallChart.CategoryValueClasses.class.concat(d.highlight ? 'highlight' : ''));\r\n\r\n cols.exit().remove();\r\n\r\n return cols;\r\n }\r\n\r\n private createConnectors(data: WaterfallChartDataPoint[]): D3.UpdateSelection {\r\n let mainGraphicsContext = this.mainGraphicsContext;\r\n let connectorSelection = mainGraphicsContext.selectAll(WaterfallChart.WaterfallConnectorClasses.selector);\r\n\r\n let connectors = connectorSelection.data(data.slice(0, data.length - 1), (d: WaterfallChartDataPoint) => d.key);\r\n\r\n connectors\r\n .enter()\r\n .append('line')\r\n .classed(WaterfallChart.WaterfallConnectorClasses.class, true);\r\n\r\n connectors.exit().remove();\r\n\r\n return connectors;\r\n }\r\n\r\n public render(suppressAnimations: boolean): CartesianVisualRenderResult {\r\n let dataPoints = this.clippedData.series[0].data;\r\n let bars = this.createRects(dataPoints);\r\n let connectors = this.createConnectors(dataPoints);\r\n\r\n if (this.tooltipsEnabled)\r\n TooltipManager.addTooltip(bars, (tooltipEvent: TooltipEvent) => tooltipEvent.data.tooltipInfo);\r\n\r\n let hasSelection = this.interactivityService && this.interactivityService.hasSelection();\r\n\r\n let xScale = this.xAxisProperties.scale;\r\n let yScale = this.yAxisProperties.scale;\r\n let y0 = yScale(0);\r\n\r\n this.mainGraphicsSVG.attr('height', this.getAvailableHeight())\r\n .attr('width', this.getAvailableWidth());\r\n\r\n /**\r\n * The y-value is always at the top of the rect. If the data value is negative then we can\r\n * use the scaled position directly since we are drawing down. If the data value is positive\r\n * we have to calculate the top of the rect and use that as the y-value. Since the y-value \r\n * is always the top of the rect, height should always be positive.\r\n */\r\n bars\r\n .style('fill', (d: WaterfallChartDataPoint) => d.color)\r\n .style('fill-opacity', (d: WaterfallChartDataPoint) => d.isTotal ? ColumnUtil.DefaultOpacity : ColumnUtil.getFillOpacity(d.selected, d.highlight, hasSelection, this.data.hasHighlights))\r\n .attr('width', this.layout.categoryWidth)\r\n .attr('x', (d: WaterfallChartDataPoint) => xScale(d.categoryIndex))\r\n .attr('y', (d: WaterfallChartDataPoint) => WaterfallChart.getRectTop(yScale, d.position, d.value))\r\n .attr('height', (d: WaterfallChartDataPoint) => y0 - yScale(Math.abs(d.value)));\r\n\r\n connectors\r\n .attr({\r\n 'x1': (d: WaterfallChartDataPoint) => xScale(d.categoryIndex),\r\n 'y1': (d: WaterfallChartDataPoint) => yScale(d.position + d.value),\r\n 'x2': (d: WaterfallChartDataPoint) => xScale(d.categoryIndex + 1) + this.layout.categoryWidth,\r\n 'y2': (d: WaterfallChartDataPoint) => yScale(d.position + d.value),\r\n });\r\n\r\n let labelSettings = this.data.dataLabelsSettings;\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n if (labelSettings && labelSettings.show || labelSettings.showCategory) {\r\n labelDataPoints = this.createLabelDataPoints();\r\n }\r\n\r\n let behaviorOptions: WaterfallChartBehaviorOptions = undefined;\r\n if (this.interactivityService) {\r\n behaviorOptions = {\r\n bars: bars,\r\n datapoints: dataPoints,\r\n };\r\n }\r\n\r\n // This should always be the last line in the render code.\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n\r\n return { dataPoints: dataPoints, behaviorOptions: behaviorOptions, labelDataPoints: labelDataPoints, labelsAreNumeric: true };\r\n }\r\n\r\n public onClearSelection(): void {\r\n if (this.interactivityService)\r\n this.interactivityService.clearSelection();\r\n }\r\n\r\n public getSupportedCategoryAxisType(): string {\r\n return axisType.categorical;\r\n }\r\n\r\n public static getRectTop(scale: D3.Scale.GenericScale<any>, pos: number, value: number): number {\r\n if (value < 0)\r\n return scale(pos);\r\n else\r\n return scale(pos) - (scale(0) - scale(value));\r\n }\r\n\r\n private getAvailableWidth(): number {\r\n return this.currentViewport.width - (this.margin.left + this.margin.right);\r\n }\r\n\r\n private getAvailableHeight(): number {\r\n return this.currentViewport.height - (this.margin.top + this.margin.bottom);\r\n }\r\n\r\n private getSentimentColorsFromObjects(objects: DataViewObjects): WaterfallChartSentimentColors {\r\n let defaultSentimentColors = this.colors.getSentimentColors();\r\n let increaseColor = DataViewObjects.getFillColor(objects, waterfallChartProps.sentimentColors.increaseFill, defaultSentimentColors[2].value);\r\n let decreaseColor = DataViewObjects.getFillColor(objects, waterfallChartProps.sentimentColors.decreaseFill, defaultSentimentColors[0].value);\r\n let totalColor = DataViewObjects.getFillColor(objects, waterfallChartProps.sentimentColors.totalFill, WaterfallChart.defaultTotalColor);\r\n\r\n return <WaterfallChartSentimentColors> {\r\n increaseFill: { solid: { color: increaseColor } },\r\n decreaseFill: { solid: { color: decreaseColor } },\r\n totalFill: { solid: { color: totalColor } }\r\n };\r\n }\r\n\r\n // Public for testing\r\n public createLabelDataPoints(): LabelDataPoint[]{\r\n let labelDataPoints: LabelDataPoint[] = [];\r\n\r\n let data = this.data;\r\n let xScale = this.xAxisProperties.scale;\r\n let yScale = this.yAxisProperties.scale;\r\n let y0 = yScale(0);\r\n let series = data.series;\r\n let formattersCache = NewDataLabelUtils.createColumnFormatterCacheManager();\r\n let axisFormatter: number = NewDataLabelUtils.getDisplayUnitValueFromAxisFormatter(this.yAxisProperties.formatter, data.dataLabelsSettings);\r\n let labelSettings = this.data.dataLabelsSettings;\r\n\r\n for (let currentSeries of series) {\r\n for (let dataPoint of currentSeries.data) {\r\n // Calculate parent rectangle\r\n let parentRect: IRect = {\r\n left: xScale(dataPoint.categoryIndex),\r\n top: WaterfallChart.getRectTop(yScale, dataPoint.position, dataPoint.value),\r\n width: this.layout.categoryWidth,\r\n height: y0 - yScale(Math.abs(dataPoint.value)),\r\n };\r\n\r\n // Calculate label text\r\n let formatString = dataPoint.labelFormatString;\r\n let formatter = formattersCache.getOrCreate(formatString, this.data.dataLabelsSettings, axisFormatter);\r\n let text = NewDataLabelUtils.getLabelFormattedText(formatter.format(dataPoint.value));\r\n\r\n // Calculate text size\r\n let properties: TextProperties = {\r\n text: text,\r\n fontFamily: NewDataLabelUtils.LabelTextProperties.fontFamily,\r\n fontSize: PixelConverter.fromPoint(labelSettings.fontSize || NewDataLabelUtils.DefaultLabelFontSizeInPt),\r\n fontWeight: NewDataLabelUtils.LabelTextProperties.fontWeight,\r\n };\r\n\r\n let textWidth = TextMeasurementService.measureSvgTextWidth(properties);\r\n let textHeight = TextMeasurementService.estimateSvgTextHeight(properties, true /* tightFitForNumeric */);\r\n\r\n labelDataPoints.push({\r\n isPreferred: true,\r\n text: text,\r\n textSize: {\r\n width: textWidth,\r\n height: textHeight,\r\n },\r\n outsideFill: labelSettings.labelColor ? labelSettings.labelColor : NewDataLabelUtils.defaultLabelColor,\r\n insideFill: NewDataLabelUtils.defaultInsideLabelColor,\r\n parentType: LabelDataPointParentType.Rectangle,\r\n parentShape: {\r\n rect: parentRect,\r\n orientation: dataPoint.value >= 0 ? NewRectOrientation.VerticalBottomBased : NewRectOrientation.VerticalTopBased,\r\n validPositions: dataPoint.value === 0 ? WaterfallChart.validZeroLabelPosition : WaterfallChart.validLabelPositions,\r\n },\r\n fontSize: labelSettings.fontSize,\r\n identity: undefined,\r\n });\r\n }\r\n }\r\n\r\n return labelDataPoints;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n import TouchUtils = powerbi.visuals.controls.TouchUtils;\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n\r\n export interface TooltipDataItem {\r\n displayName: string;\r\n value: string;\r\n color?: string;\r\n header?: string;\r\n }\r\n\r\n export interface TooltipOptions {\r\n opacity: number;\r\n animationDuration: number;\r\n offsetX: number;\r\n offsetY: number;\r\n }\r\n\r\n export interface TooltipEnabledDataPoint {\r\n tooltipInfo?: TooltipDataItem[];\r\n }\r\n\r\n export interface TooltipCategoryDataItem {\r\n value?: any;\r\n metadata: DataViewMetadataColumn[];\r\n }\r\n\r\n export interface TooltipSeriesDataItem {\r\n value?: any;\r\n highlightedValue?: any;\r\n metadata: DataViewValueColumn;\r\n }\r\n\r\n export interface TooltipLocalizationOptions {\r\n highlightedValueDisplayName: string;\r\n }\r\n\r\n export interface TooltipEvent {\r\n data: any;\r\n coordinates: number[];\r\n elementCoordinates: number[];\r\n context: HTMLElement;\r\n isTouchEvent: boolean;\r\n }\r\n\r\n const enum ScreenArea {\r\n TopLeft,\r\n TopRight,\r\n BottomRight,\r\n BottomLeft\r\n };\r\n\r\n const ContainerClassName: ClassAndSelector = createClassAndSelector(\"tooltip-container\");\r\n const ContentContainerClassName: ClassAndSelector = createClassAndSelector(\"tooltip-content-container\");\r\n const ArrowClassName: ClassAndSelector = createClassAndSelector(\"arrow\");\r\n const TooltipHeaderClassName: ClassAndSelector = createClassAndSelector(\"tooltip-header\");\r\n const TooltipRowClassName: ClassAndSelector = createClassAndSelector(\"tooltip-row\");\r\n const TooltipColorCellClassName: ClassAndSelector = createClassAndSelector(\"tooltip-color-cell\");\r\n const TooltipTitleCellClassName: ClassAndSelector = createClassAndSelector(\"tooltip-title-cell\");\r\n const TooltipValueCellClassName: ClassAndSelector = createClassAndSelector(\"tooltip-value-cell\");\r\n\r\n export class ToolTipComponent {\r\n\r\n private static DefaultTooltipOptions: TooltipOptions = {\r\n opacity: 1,\r\n animationDuration: 250,\r\n offsetX: 10,\r\n offsetY: 10\r\n };\r\n\r\n private tooltipContainer: D3.Selection;\r\n private isTooltipVisible: boolean = false;\r\n private currentTooltipData: TooltipDataItem[];\r\n\r\n private customScreenWidth: number;\r\n private customScreenHeight: number;\r\n\r\n public static parentContainerSelector: string = \"body\";\r\n public static highlightedValueDisplayNameResorceKey: string = \"Tooltip_HighlightedValueDisplayName\";\r\n public static localizationOptions: TooltipLocalizationOptions;\r\n\r\n constructor(public tooltipOptions?: TooltipOptions) {\r\n if (!tooltipOptions) {\r\n this.tooltipOptions = ToolTipComponent.DefaultTooltipOptions;\r\n }\r\n }\r\n\r\n public isTooltipComponentVisible(): boolean {\r\n return this.isTooltipVisible;\r\n }\r\n\r\n /** Note: For tests only */\r\n public setTestScreenSize(width: number, height: number) {\r\n this.customScreenWidth = width;\r\n this.customScreenHeight = height;\r\n }\r\n\r\n public show(tooltipData: TooltipDataItem[], clickedArea: TouchUtils.Rectangle) {\r\n this.isTooltipVisible = true;\r\n\r\n if (!this.tooltipContainer) {\r\n this.tooltipContainer = this.createTooltipContainer();\r\n }\r\n\r\n this.setTooltipContent(tooltipData);\r\n\r\n this.tooltipContainer\r\n .style(\"visibility\", \"visible\")\r\n .transition()\r\n .duration(0) // Cancel previous transitions\r\n .style(\"opacity\", this.tooltipOptions.opacity);\r\n\r\n this.setPosition(clickedArea);\r\n }\r\n\r\n public move(tooltipData: TooltipDataItem[], clickedArea: TouchUtils.Rectangle) {\r\n if (this.isTooltipVisible) {\r\n if (tooltipData) {\r\n this.setTooltipContent(tooltipData);\r\n }\r\n\r\n this.setPosition(clickedArea);\r\n }\r\n }\r\n\r\n public hide() {\r\n if (this.isTooltipVisible) {\r\n this.isTooltipVisible = false;\r\n this.tooltipContainer\r\n .transition()\r\n .duration(this.tooltipOptions.animationDuration)\r\n .style(\"opacity\", 0)\r\n .each('end', function () { this.style.visibility = \"hidden\"; });\r\n }\r\n }\r\n\r\n private createTooltipContainer(): D3.Selection {\r\n let container: D3.Selection = d3.select(ToolTipComponent.parentContainerSelector)\r\n .append(\"div\")\r\n .attr(\"class\", ContainerClassName.class);\r\n\r\n container.append(\"div\").attr(\"class\", ArrowClassName.class);\r\n container.append(\"div\").attr(\"class\", ContentContainerClassName.class);\r\n\r\n return container;\r\n }\r\n\r\n private setTooltipContent(tooltipData: TooltipDataItem[]): void {\r\n if (_.isEqual(tooltipData, this.currentTooltipData))\r\n return;\r\n this.currentTooltipData = tooltipData;\r\n\r\n let rowsSelector: string = TooltipRowClassName.selector;\r\n let contentContainer = this.tooltipContainer.select(ContentContainerClassName.selector);\r\n\r\n // Clear existing content\r\n contentContainer.selectAll(TooltipHeaderClassName.selector).remove();\r\n contentContainer.selectAll(TooltipRowClassName.selector).remove();\r\n\r\n if (tooltipData.length === 0) return;\r\n\r\n if (tooltipData[0].header) {\r\n contentContainer.append(\"div\").attr(\"class\", TooltipHeaderClassName.class).text(tooltipData[0].header);\r\n }\r\n let tooltipRow: D3.UpdateSelection = contentContainer.selectAll(rowsSelector).data(tooltipData);\r\n let newRow: D3.Selection = tooltipRow.enter().append(\"div\").attr(\"class\", TooltipRowClassName.class);\r\n if (tooltipData[0].color) {\r\n let newColorCell: D3.Selection = newRow.append(\"div\").attr(\"class\", TooltipColorCellClassName.class);\r\n\r\n newColorCell\r\n .append('svg')\r\n .attr({\r\n 'width': '100%',\r\n 'height': '15px'\r\n })\r\n .append('circle')\r\n .attr({\r\n 'cx': '5',\r\n 'cy': '8',\r\n 'r': '5'\r\n })\r\n .style({\r\n 'fill': (d: TooltipDataItem) => d.color\r\n });\r\n }\r\n let newTitleCell: D3.Selection = newRow.append(\"div\").attr(\"class\", TooltipTitleCellClassName.class);\r\n let newValueCell: D3.Selection = newRow.append(\"div\").attr(\"class\", TooltipValueCellClassName.class);\r\n\r\n newTitleCell.text(function (d: TooltipDataItem) { return d.displayName; });\r\n newValueCell.text(function (d: TooltipDataItem) { return d.value; });\r\n }\r\n\r\n private getTooltipPosition(clickedArea: TouchUtils.Rectangle, clickedScreenArea: ScreenArea): TouchUtils.Point {\r\n let tooltipContainerBounds: ClientRect = this.tooltipContainer.node().getBoundingClientRect();\r\n let centerPointOffset: number = Math.floor(clickedArea.width / 2);\r\n let offsetX: number = 0;\r\n let offsetY: number = 0;\r\n let centerPoint: TouchUtils.Point = new TouchUtils.Point(clickedArea.x + centerPointOffset, clickedArea.y + centerPointOffset);\r\n let arrowOffset: number = 7;\r\n\r\n if (clickedScreenArea === ScreenArea.TopLeft) {\r\n offsetX += 3 * arrowOffset + centerPointOffset;\r\n offsetY -= 2 * arrowOffset + centerPointOffset;\r\n }\r\n else if (clickedScreenArea === ScreenArea.TopRight) {\r\n offsetX -= (2 * arrowOffset + tooltipContainerBounds.width + centerPointOffset);\r\n offsetY -= 2 * arrowOffset + centerPointOffset;\r\n }\r\n else if (clickedScreenArea === ScreenArea.BottomLeft) {\r\n offsetX += 3 * arrowOffset + centerPointOffset;\r\n offsetY -= (tooltipContainerBounds.height - 2 * arrowOffset + centerPointOffset);\r\n }\r\n else if (clickedScreenArea === ScreenArea.BottomRight) {\r\n offsetX -= (2 * arrowOffset + tooltipContainerBounds.width + centerPointOffset);\r\n offsetY -= (tooltipContainerBounds.height - 2 * arrowOffset + centerPointOffset);\r\n }\r\n\r\n centerPoint.offset(offsetX, offsetY);\r\n\r\n return centerPoint;\r\n }\r\n\r\n private setPosition(clickedArea: TouchUtils.Rectangle): void {\r\n let clickedScreenArea: ScreenArea = this.getClickedScreenArea(clickedArea);\r\n let tooltipPosition: TouchUtils.Point = this.getTooltipPosition(clickedArea, clickedScreenArea);\r\n\r\n this.tooltipContainer.style({ \"left\": tooltipPosition.x + \"px\", \"top\": tooltipPosition.y + \"px\" });\r\n this.setArrowPosition(clickedArea, clickedScreenArea);\r\n }\r\n\r\n private setArrowPosition(clickedArea: TouchUtils.Rectangle, clickedScreenArea: ScreenArea): void {\r\n let arrow: D3.Selection = this.getArrowElement();\r\n let arrowClassName: string;\r\n\r\n if (clickedScreenArea === ScreenArea.TopLeft) {\r\n arrowClassName = \"top left\";\r\n }\r\n else if (clickedScreenArea === ScreenArea.TopRight) {\r\n arrowClassName = \"top right\";\r\n }\r\n else if (clickedScreenArea === ScreenArea.BottomLeft) {\r\n arrowClassName = \"bottom left\";\r\n }\r\n else if (clickedScreenArea === ScreenArea.BottomRight) {\r\n arrowClassName = \"bottom right\";\r\n }\r\n\r\n arrow\r\n .attr('class', 'arrow') // Reset all classes\r\n .classed(arrowClassName, true);\r\n }\r\n\r\n private getArrowElement(): D3.Selection {\r\n return this.tooltipContainer.select(ArrowClassName.selector);\r\n }\r\n\r\n private getClickedScreenArea(clickedArea: TouchUtils.Rectangle): ScreenArea {\r\n let screenWidth: number = this.customScreenWidth || window.innerWidth;\r\n let screenHeight: number = this.customScreenHeight || window.innerHeight;\r\n let centerPointOffset: number = clickedArea.width / 2;\r\n let centerPoint: TouchUtils.Point = new TouchUtils.Point(clickedArea.x + centerPointOffset, clickedArea.y + centerPointOffset);\r\n let halfWidth: number = screenWidth / 2;\r\n let halfHeight: number = screenHeight / 2;\r\n\r\n if (centerPoint.x < halfWidth && centerPoint.y < halfHeight) {\r\n return ScreenArea.TopLeft;\r\n }\r\n else if (centerPoint.x >= halfWidth && centerPoint.y < halfHeight) {\r\n return ScreenArea.TopRight;\r\n }\r\n else if (centerPoint.x < halfWidth && centerPoint.y >= halfHeight) {\r\n return ScreenArea.BottomLeft;\r\n }\r\n else if (centerPoint.x >= halfWidth && centerPoint.y >= halfHeight) {\r\n return ScreenArea.BottomRight;\r\n }\r\n }\r\n }\r\n\r\n export module TooltipManager {\r\n\r\n export let ShowTooltips: boolean = true;\r\n export let ToolTipInstance: ToolTipComponent = new ToolTipComponent();\r\n let GlobalTooltipEventsAttached: boolean = false;\r\n const tooltipMouseOverDelay: number = 350;\r\n const tooltipMouseOutDelay: number = 500;\r\n const tooltipTouchDelay: number = 350;\r\n let tooltipTimeoutId: number;\r\n const handleTouchDelay: number = 1000;\r\n let handleTouchTimeoutId: number = 0;\r\n let mouseCoordinates: number[];\r\n let tooltipData: TooltipDataItem[];\r\n\r\n export function addTooltip(\r\n selection: D3.Selection,\r\n getTooltipInfoDelegate: (tooltipEvent: TooltipEvent) => TooltipDataItem[],\r\n reloadTooltipDataOnMouseMove?: boolean,\r\n onMouseOutDelegate?: () => void): void {\r\n\r\n if (!ShowTooltips) {\r\n return;\r\n }\r\n\r\n debug.assertValue(selection, \"selection\");\r\n\r\n let rootNode = d3.select(ToolTipComponent.parentContainerSelector).node();\r\n\r\n // Mouse events\r\n selection.on(\"mouseover\", () => {\r\n let target = <HTMLElement>d3.event.target;\r\n let data = d3.select(target).datum();\r\n \r\n // Ignore mouseover while handling touch events\r\n if (handleTouchTimeoutId || !canDisplayTooltip(d3.event))\r\n return;\r\n\r\n mouseCoordinates = getCoordinates(rootNode, true);\r\n let elementCoordinates: number[] = getCoordinates(target, true);\r\n let tooltipEvent: TooltipEvent = {\r\n data: data,\r\n coordinates: mouseCoordinates,\r\n elementCoordinates: elementCoordinates,\r\n context: target,\r\n isTouchEvent: false\r\n };\r\n\r\n clearTooltipTimeout();\r\n \r\n // if it is already visible, change contents immediately (use 16ms minimum perceivable frame rate to prevent thrashing)\r\n let delay = ToolTipInstance.isTooltipComponentVisible() ? 16 : tooltipMouseOverDelay;\r\n tooltipTimeoutId = showDelayedTooltip(tooltipEvent, getTooltipInfoDelegate, delay);\r\n });\r\n\r\n selection.on(\"mouseout\", () => {\r\n if (!handleTouchTimeoutId) {\r\n clearTooltipTimeout();\r\n tooltipTimeoutId = hideDelayedTooltip(tooltipMouseOutDelay);\r\n }\r\n\r\n if (onMouseOutDelegate) {\r\n onMouseOutDelegate();\r\n }\r\n });\r\n\r\n selection.on(\"mousemove\", () => {\r\n let target = <HTMLElement>d3.event.target;\r\n let data = d3.select(target).datum();\r\n \r\n // Ignore mousemove while handling touch events\r\n if (handleTouchTimeoutId || !canDisplayTooltip(d3.event))\r\n return;\r\n\r\n mouseCoordinates = getCoordinates(rootNode, true);\r\n let elementCoordinates: number[] = getCoordinates(target, true);\r\n let tooltipEvent: TooltipEvent = {\r\n data: data,\r\n coordinates: mouseCoordinates,\r\n elementCoordinates: elementCoordinates,\r\n context: target,\r\n isTouchEvent: false\r\n };\r\n\r\n moveTooltipEventHandler(tooltipEvent, getTooltipInfoDelegate, reloadTooltipDataOnMouseMove);\r\n });\r\n \r\n // --- Touch events ---\r\n \r\n // TODO: static?\r\n let touchStartEventName: string = getTouchStartEventName();\r\n let touchEndEventName: string = getTouchEndEventName();\r\n let isPointerEvent: boolean = touchStartEventName === \"pointerdown\" || touchStartEventName === \"MSPointerDown\";\r\n\r\n if (!GlobalTooltipEventsAttached) {\r\n // Add root container hide tooltip event\r\n attachGlobalEvents(touchStartEventName);\r\n GlobalTooltipEventsAttached = true;\r\n }\r\n\r\n selection.on(touchStartEventName, () => {\r\n let target = <HTMLElement>d3.event.target;\r\n let data = d3.select(target).datum();\r\n\r\n hideTooltipEventHandler();\r\n let coordinates: number[] = getCoordinates(rootNode, isPointerEvent);\r\n let elementCoordinates: number[] = getCoordinates(target, isPointerEvent);\r\n let tooltipEvent: TooltipEvent = {\r\n data: data,\r\n coordinates: coordinates,\r\n elementCoordinates: elementCoordinates,\r\n context: target,\r\n isTouchEvent: true\r\n };\r\n clearTooltipTimeout();\r\n tooltipTimeoutId = showDelayedTooltip(tooltipEvent, getTooltipInfoDelegate, tooltipTouchDelay);\r\n });\r\n\r\n selection.on(touchEndEventName, () => {\r\n\r\n clearTooltipTimeout();\r\n if (handleTouchTimeoutId)\r\n clearTimeout(handleTouchTimeoutId);\r\n\r\n // At the end of touch action, set a timeout that will let us ignore the incoming mouse events for a small amount of time\r\n handleTouchTimeoutId = setTimeout(() => {\r\n handleTouchTimeoutId = 0;\r\n }, handleTouchDelay);\r\n });\r\n }\r\n\r\n export function showDelayedTooltip(tooltipEvent: TooltipEvent, getTooltipInfoDelegate: (tooltipEvent: TooltipEvent) => TooltipDataItem[], delayInMs: number): number {\r\n return setTimeout(() => showTooltipEventHandler(tooltipEvent, getTooltipInfoDelegate), delayInMs);\r\n }\r\n\r\n export function hideDelayedTooltip(delayInMs: number): number {\r\n return setTimeout(() => hideTooltipEventHandler(), delayInMs);\r\n }\r\n\r\n export function setLocalizedStrings(localizationOptions: TooltipLocalizationOptions): void {\r\n ToolTipComponent.localizationOptions = localizationOptions;\r\n }\r\n\r\n function showTooltipEventHandler(tooltipEvent: TooltipEvent, getTooltipInfoDelegate: (tooltipEvent: TooltipEvent) => TooltipDataItem[]) {\r\n let tooltipInfo: TooltipDataItem[] = tooltipData || getTooltipInfoDelegate(tooltipEvent);\r\n if (!_.isEmpty(tooltipInfo)) {\r\n let coordinates: number[] = mouseCoordinates || tooltipEvent.coordinates;\r\n let clickedArea: TouchUtils.Rectangle = getClickedArea(coordinates[0], coordinates[1], tooltipEvent.isTouchEvent);\r\n ToolTipInstance.show(tooltipInfo, clickedArea);\r\n }\r\n }\r\n\r\n function moveTooltipEventHandler(tooltipEvent: TooltipEvent, getTooltipInfoDelegate: (tooltipEvent: TooltipEvent) => TooltipDataItem[], reloadTooltipDataOnMouseMove: boolean) {\r\n tooltipData = undefined;\r\n if (reloadTooltipDataOnMouseMove) {\r\n tooltipData = getTooltipInfoDelegate(tooltipEvent);\r\n }\r\n let clickedArea: TouchUtils.Rectangle = getClickedArea(tooltipEvent.coordinates[0], tooltipEvent.coordinates[1], tooltipEvent.isTouchEvent);\r\n ToolTipInstance.move(tooltipData, clickedArea);\r\n };\r\n\r\n function hideTooltipEventHandler() {\r\n ToolTipInstance.hide();\r\n };\r\n\r\n function clearTooltipTimeout() {\r\n if (tooltipTimeoutId) {\r\n clearTimeout(tooltipTimeoutId);\r\n }\r\n }\r\n\r\n function canDisplayTooltip(d3Event: any): boolean {\r\n let cadDisplay: boolean = true;\r\n let mouseEvent: MouseEvent = <MouseEvent>d3Event;\r\n if (mouseEvent.buttons !== undefined) {\r\n // Check mouse buttons state\r\n let hasMouseButtonPressed = mouseEvent.buttons !== 0;\r\n cadDisplay = !hasMouseButtonPressed;\r\n }\r\n return cadDisplay;\r\n }\r\n\r\n function getTouchStartEventName(): string {\r\n let eventName: string = \"touchstart\";\r\n\r\n if (window[\"PointerEvent\"]) {\r\n // IE11\r\n eventName = \"pointerdown\";\r\n } else if (window[\"MSPointerEvent\"]) {\r\n // IE10\r\n eventName = \"MSPointerDown\";\r\n }\r\n\r\n return eventName;\r\n }\r\n\r\n function getTouchEndEventName(): string {\r\n let eventName: string = \"touchend\";\r\n\r\n if (window[\"PointerEvent\"]) {\r\n // IE11\r\n eventName = \"pointerup\";\r\n } else if (window[\"MSPointerEvent\"]) {\r\n // IE10\r\n eventName = \"MSPointerUp\";\r\n }\r\n\r\n return eventName;\r\n }\r\n\r\n function getCoordinates(rootNode: Element, isPointerEvent: boolean): number[] {\r\n let coordinates: number[];\r\n\r\n if (isPointerEvent) {\r\n // DO NOT USE - WebKit bug in getScreenCTM with nested SVG results in slight negative coordinate shift\r\n // Also, IE will incorporate transform scale but WebKit does not, forcing us to detect browser and adjust appropriately.\r\n // Just use non-scaled coordinates for all browsers, and adjust for the transform scale later (see lineChart.findIndex)\r\n //coordinates = d3.mouse(rootNode);\r\n\r\n // copied from d3_eventSource (which is not exposed)\r\n let e = d3.event, s;\r\n while (s = e.sourceEvent) e = s;\r\n let rect = rootNode.getBoundingClientRect();\r\n coordinates = [e.clientX - rect.left - rootNode.clientLeft, e.clientY - rect.top - rootNode.clientTop];\r\n }\r\n else {\r\n let touchCoordinates = d3.touches(rootNode);\r\n if (touchCoordinates && touchCoordinates.length > 0) {\r\n coordinates = touchCoordinates[0];\r\n }\r\n }\r\n\r\n return coordinates;\r\n }\r\n\r\n function attachGlobalEvents(touchStartEventName: string): void {\r\n d3.select(ToolTipComponent.parentContainerSelector).on(touchStartEventName, function (d, i) {\r\n ToolTipInstance.hide();\r\n });\r\n }\r\n\r\n function getClickedArea(x: number, y: number, isTouchEvent: boolean): TouchUtils.Rectangle {\r\n let width: number = 0;\r\n let pointX: number = x;\r\n let pointY: number = y;\r\n\r\n if (isTouchEvent) {\r\n width = 12;\r\n let offset: number = width / 2;\r\n pointX = Math.max(x - offset, 0);\r\n pointY = Math.max(y - offset, 0);\r\n }\r\n\r\n return new TouchUtils.Rectangle(pointX, pointY, width, width);\r\n }\r\n }\r\n\r\n export module TooltipBuilder {\r\n\r\n // TODO: implement options bag as input parameter\r\n export function createTooltipInfo(\r\n formatStringProp: DataViewObjectPropertyIdentifier,\r\n dataViewCat: DataViewCategorical,\r\n categoryValue: any,\r\n value?: any,\r\n categories?: DataViewCategoryColumn[],\r\n seriesData?: TooltipSeriesDataItem[],\r\n seriesIndex?: number,\r\n categoryIndex?: number,\r\n highlightedValue?: any,\r\n gradientValueColumn?: DataViewValueColumn): TooltipDataItem[] {\r\n let categorySource: TooltipCategoryDataItem;\r\n let seriesSource: TooltipSeriesDataItem[] = [];\r\n let valuesSource: DataViewMetadataColumn = undefined;\r\n seriesIndex = seriesIndex | 0;\r\n\r\n let categoriesData = dataViewCat ? dataViewCat.categories : categories;\r\n if (categoriesData && categoriesData.length > 0) {\r\n if (categoriesData.length > 1) {\r\n let compositeCategoriesData = [];\r\n for (let i = 0, ilen = categoriesData.length; i < ilen; i++) {\r\n compositeCategoriesData.push(categoriesData[i].source);\r\n }\r\n categorySource = { value: categoryValue, metadata: compositeCategoriesData };\r\n }\r\n else {\r\n categorySource = { value: categoryValue, metadata: [categoriesData[0].source] };\r\n }\r\n }\r\n if (dataViewCat && dataViewCat.values) {\r\n if (categorySource && categorySource.metadata[0] === dataViewCat.values.source) {\r\n // Category/series on the same column -- don't repeat its value in the tooltip.\r\n }\r\n else {\r\n valuesSource = dataViewCat.values.source;\r\n }\r\n if (dataViewCat.values.length > 0) {\r\n let valueColumn: DataViewValueColumn = dataViewCat.values[seriesIndex];\r\n let isAutoGeneratedColumn: boolean = !!(valueColumn && valueColumn.source && (<DataViewMetadataAutoGeneratedColumn>valueColumn.source).isAutoGeneratedColumn);\r\n\r\n if (!isAutoGeneratedColumn) {\r\n seriesSource.push({ value: value, highlightedValue: highlightedValue, metadata: valueColumn });\r\n }\r\n }\r\n\r\n //Create Gradient tooltip value\r\n let gradientToolTipData = createGradientToolTipData(gradientValueColumn, categoryIndex);\r\n if (gradientToolTipData != null)\r\n seriesSource.push(gradientToolTipData);\r\n }\r\n if (seriesData) {\r\n for (let i: number = 0, len: number = seriesData.length; i < len; i++) {\r\n let singleSeriesData: TooltipSeriesDataItem = seriesData[i];\r\n if (categorySource && categorySource.metadata[0] === singleSeriesData.metadata.source)\r\n continue;\r\n\r\n seriesSource.push({ value: singleSeriesData.value, metadata: singleSeriesData.metadata });\r\n }\r\n }\r\n\r\n let tooltipInfo: TooltipDataItem[] = createTooltipData(formatStringProp, categorySource, valuesSource, seriesSource);\r\n\r\n return tooltipInfo;\r\n }\r\n\r\n export function createGradientToolTipData(gradientValueColumn: DataViewValueColumn, categoryIndex: number): TooltipSeriesDataItem {\r\n if (gradientValueColumn) {\r\n // Saturation color\r\n return { value: gradientValueColumn.values[categoryIndex], metadata: { source: gradientValueColumn.source, values: [] } };\r\n }\r\n return null;\r\n }\r\n\r\n function createTooltipData(\r\n formatStringProp: DataViewObjectPropertyIdentifier,\r\n categoryValue: TooltipCategoryDataItem,\r\n valuesSource: DataViewMetadataColumn,\r\n seriesValues: TooltipSeriesDataItem[]): TooltipDataItem[] {\r\n\r\n debug.assertValue(seriesValues, \"seriesSource\");\r\n debug.assertValue(ToolTipComponent.localizationOptions, \"ToolTipComponent.localizationOptions\");\r\n debug.assertAnyValue(formatStringProp, 'formatStringProp');\r\n\r\n let items: TooltipDataItem[] = [];\r\n\r\n if (categoryValue) {\r\n if (categoryValue.metadata.length > 1) {\r\n let displayName = '';\r\n // This is being done simply for lat/long for now, as that's the only composite category we use. If we ever have tooltips\r\n // involving other composite categories, we need to do a more thorough design and be more careful here.\r\n for (let i = 0, ilen = categoryValue.metadata.length; i < ilen; i++) {\r\n if (i !== 0)\r\n displayName += '/';\r\n displayName += categoryValue.metadata[i].displayName;\r\n }\r\n let categoryFormattedValue: string = getFormattedValue(categoryValue.metadata[0], formatStringProp, categoryValue.value);\r\n items.push({ displayName: displayName, value: categoryFormattedValue });\r\n }\r\n else {\r\n let categoryFormattedValue: string = getFormattedValue(categoryValue.metadata[0], formatStringProp, categoryValue.value);\r\n items.push({ displayName: categoryValue.metadata[0].displayName, value: categoryFormattedValue });\r\n }\r\n }\r\n\r\n if (valuesSource) {\r\n // Dynamic series value\r\n let dynamicValue: string;\r\n if (seriesValues.length > 0) {\r\n let dynamicValueMetadata: DataViewMetadataColumn = seriesValues[0].metadata.source;\r\n dynamicValue = getFormattedValue(valuesSource, formatStringProp, dynamicValueMetadata.groupName);\r\n }\r\n items.push({ displayName: valuesSource.displayName, value: dynamicValue });\r\n }\r\n\r\n for (let i = 0; i < seriesValues.length; i++) {\r\n let seriesData = seriesValues[i];\r\n\r\n if (seriesData && seriesData.metadata) {\r\n let seriesMetadataColumn = seriesData.metadata.source;\r\n let value = seriesData.value;\r\n let highlightedValue = seriesData.highlightedValue;\r\n\r\n if (value || value === 0) {\r\n let formattedValue: string = getFormattedValue(seriesMetadataColumn, formatStringProp, value);\r\n items.push({ displayName: seriesMetadataColumn.displayName, value: formattedValue });\r\n }\r\n\r\n if (highlightedValue || highlightedValue === 0) {\r\n let formattedHighlightedValue: string = getFormattedValue(seriesMetadataColumn, formatStringProp, highlightedValue);\r\n let displayName = ToolTipComponent.localizationOptions.highlightedValueDisplayName;\r\n items.push({ displayName: displayName, value: formattedHighlightedValue });\r\n }\r\n }\r\n }\r\n\r\n return items;\r\n }\r\n\r\n function getFormattedValue(column: DataViewMetadataColumn, formatStringProp: DataViewObjectPropertyIdentifier, value: any) {\r\n let formatString: string = getFormatStringFromColumn(column, formatStringProp);\r\n return valueFormatter.format(value, formatString);\r\n }\r\n\r\n function getFormatStringFromColumn(column: DataViewMetadataColumn, formatStringProp: DataViewObjectPropertyIdentifier): string {\r\n if (column) {\r\n let formatString: string = valueFormatter.getFormatString(column, formatStringProp, true);\r\n return formatString || column.format;\r\n }\r\n return null;\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n export module visualStyles {\r\n export function create(dataColors?: IDataColorPalette): IVisualStyle {\r\n if (dataColors === undefined)\r\n dataColors = new visuals.DataColorPalette();\r\n\r\n return {\r\n titleText: {\r\n color: { value: 'rgba(51,51,51,1)' }\r\n },\r\n subTitleText: {\r\n color: { value: 'rgba(145,145,145,1)' }\r\n },\r\n colorPalette: {\r\n dataColors: dataColors,\r\n },\r\n labelText: {\r\n color: {\r\n value: 'rgba(51,51,51,1)',\r\n },\r\n fontSize: '11px'\r\n },\r\n isHighContrast: false,\r\n };\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import ClassAndSelector = jsCommon.CssConstants.ClassAndSelector;\r\n import createClassAndSelector = jsCommon.CssConstants.createClassAndSelector;\r\n import ISize = shapes.ISize;\r\n import IDataViewCategoricalReader = data.IDataViewCategoricalReader;\r\n\r\n export interface DonutSmallViewPortProperties {\r\n maxHeightToScaleDonutLegend: number;\r\n }\r\n\r\n export interface DonutConstructorOptions {\r\n sliceWidthRatio?: number;\r\n animator?: IDonutChartAnimator;\r\n isScrollable?: boolean;\r\n disableGeometricCulling?: boolean;\r\n behavior?: IInteractiveBehavior;\r\n tooltipsEnabled?: boolean;\r\n smallViewPortProperties?: DonutSmallViewPortProperties;\r\n }\r\n\r\n /**\r\n * Used because data points used in D3 pie layouts are placed within a container with pie information.\r\n */\r\n export interface DonutArcDescriptor extends D3.Layout.ArcDescriptor {\r\n data: DonutDataPoint;\r\n }\r\n\r\n export interface DonutDataPoint extends SelectableDataPoint, TooltipEnabledDataPoint {\r\n measure: number;\r\n measureFormat?: string;\r\n percentage: number;\r\n highlightRatio?: number;\r\n highlightValue?: number;\r\n label: string;\r\n index: number;\r\n /** Data points that may be drilled into */\r\n internalDataPoints?: DonutDataPoint[];\r\n color: string;\r\n strokeWidth: number;\r\n //taken from column metadata\r\n labelFormatString: string;\r\n /** This is set to true only when it's the last slice and all slices have the same color*/\r\n isLastInDonut?: boolean;\r\n }\r\n\r\n export interface DonutData {\r\n dataPointsToDeprecate: DonutDataPoint[];\r\n dataPoints: DonutArcDescriptor[]; // The data points will be culled based on viewport size to remove invisible slices\r\n unCulledDataPoints: DonutDataPoint[]; // The unculled data points will never be culled\r\n dataPointsToEnumerate?: LegendDataPoint[];\r\n legendData: LegendData;\r\n hasHighlights: boolean;\r\n dataLabelsSettings: VisualDataLabelsSettings;\r\n legendObjectProperties?: DataViewObject;\r\n maxValue?: number;\r\n visibleGeometryCulled?: boolean;\r\n defaultDataPointColor?: string;\r\n }\r\n\r\n interface DonutChartSettings {\r\n /**\r\n * The duration for a long animation displayed after a user interaction with an interactive chart. \r\n */\r\n chartRotationAnimationDuration?: number;\r\n /**\r\n * The duration for a short animation displayed after a user interaction with an interactive chart.\r\n */\r\n legendTransitionAnimationDuration?: number;\r\n }\r\n\r\n interface InteractivityState {\r\n interactiveLegend: DonutChartInteractiveLegend;\r\n valueToAngleFactor: number; // Ratio between 360 and the sum of the angles\r\n sliceAngles: number[]; // Saves the angle to rotate of each slice\r\n currentRotate: number; // Keeps how much the donut is rotated by\r\n interactiveChosenSliceFinishedSetting: boolean; // flag indicating whether the chosen interactive slice was set\r\n lastChosenInteractiveSliceIndex: number; // keeps the index of the selected slice\r\n donutCenter: { // center of the chart\r\n x: number; y: number;\r\n };\r\n totalDragAngleDifference: number; // keeps how much of a rotation happened in the drag\r\n previousDragAngle: number; // previous angle of the drag event\r\n currentIndexDrag: number; // index of the slice that is currently showing in the legend \r\n previousIndexDrag: number; // index of the slice that was showing in the legend before current drag event\r\n }\r\n\r\n export interface DonutLayout {\r\n shapeLayout: {\r\n d: (d: DonutArcDescriptor) => string;\r\n };\r\n highlightShapeLayout: {\r\n d: (d: DonutArcDescriptor) => string;\r\n };\r\n zeroShapeLayout: {\r\n d: (d: DonutArcDescriptor) => string;\r\n };\r\n }\r\n\r\n /**\r\n * Renders a donut chart.\r\n */\r\n export class DonutChart implements IVisual {\r\n private static ClassName = 'donutChart';\r\n private static InteractiveLegendClassName = 'donutLegend';\r\n private static InteractiveLegendArrowClassName = 'donutLegendArrow';\r\n private static DrillDownAnimationDuration = 1000;\r\n private static OuterArcRadiusRatio = 0.9;\r\n private static InnerArcRadiusRatio = 0.8;\r\n private static OpaqueOpacity = 1.0;\r\n private static SemiTransparentOpacity = 0.6;\r\n private static defaultSliceWidthRatio: number = 0.48;\r\n private static invisibleArcLengthInPixels: number = 3;\r\n private static sliceClass: ClassAndSelector = createClassAndSelector('slice');\r\n private static sliceHighlightClass: ClassAndSelector = createClassAndSelector('slice-highlight');\r\n private static twoPi = 2 * Math.PI;\r\n\r\n public static InteractiveLegendContainerHeight = 70;\r\n public static EffectiveZeroValue = 0.000000001; // Very small multiplier so that we have a properly shaped zero arc to animate to/from.\r\n public static PolylineOpacity = 0.5;\r\n\r\n private dataViews: DataView[];\r\n private sliceWidthRatio: number;\r\n private svg: D3.Selection;\r\n private mainGraphicsContext: D3.Selection;\r\n private labelGraphicsContext: D3.Selection;\r\n private clearCatcher: D3.Selection;\r\n private legendContainer: D3.Selection;\r\n private interactiveLegendArrow: D3.Selection;\r\n private parentViewport: IViewport;\r\n private currentViewport: IViewport;\r\n private formatter: ICustomValueFormatter;\r\n private data: DonutData;\r\n private pie: D3.Layout.PieLayout;\r\n private arc: D3.Svg.Arc;\r\n private outerArc: D3.Svg.Arc;\r\n private radius: number;\r\n private previousRadius: number;\r\n private key: any;\r\n private colors: IDataColorPalette;\r\n private style: IVisualStyle;\r\n private drilled: boolean;\r\n private allowDrilldown: boolean;\r\n private options: VisualInitOptions;\r\n private isInteractive: boolean;\r\n private interactivityState: InteractivityState;\r\n private chartRotationAnimationDuration: number;\r\n private interactivityService: IInteractivityService;\r\n private behavior: IInteractiveBehavior;\r\n private legend: ILegend;\r\n private hasSetData: boolean;\r\n private isScrollable: boolean;\r\n private disableGeometricCulling: boolean;\r\n private hostService: IVisualHostServices;\r\n private settings: DonutChartSettings;\r\n private tooltipsEnabled: boolean;\r\n private donutProperties: DonutChartProperties;\r\n private maxHeightToScaleDonutLegend: number;\r\n\r\n /**\r\n * Note: Public for testing.\r\n */\r\n public animator: IDonutChartAnimator;\r\n\r\n constructor(options?: DonutConstructorOptions) {\r\n if (options) {\r\n this.sliceWidthRatio = options.sliceWidthRatio;\r\n this.animator = options.animator;\r\n this.isScrollable = options.isScrollable ? options.isScrollable : false;\r\n this.disableGeometricCulling = options.disableGeometricCulling ? options.disableGeometricCulling : false;\r\n this.behavior = options.behavior;\r\n this.tooltipsEnabled = options.tooltipsEnabled;\r\n if (options.smallViewPortProperties) {\r\n this.maxHeightToScaleDonutLegend = options.smallViewPortProperties.maxHeightToScaleDonutLegend;\r\n }\r\n }\r\n if (this.sliceWidthRatio == null) {\r\n this.sliceWidthRatio = DonutChart.defaultSliceWidthRatio;\r\n }\r\n }\r\n\r\n public static converter(dataView: DataView, colors: IDataColorPalette, defaultDataPointColor?: string, viewport?: IViewport, disableGeometricCulling?: boolean, interactivityService?: IInteractivityService, tooltipsEnabled: boolean = true): DonutData {\r\n let converter = new DonutChartConversion.DonutChartConverter(dataView, colors, defaultDataPointColor, tooltipsEnabled);\r\n converter.convert();\r\n let d3PieLayout = d3.layout.pie()\r\n .sort(null)\r\n .value((d: DonutDataPoint) => {\r\n return d.percentage;\r\n });\r\n\r\n if (interactivityService) {\r\n interactivityService.applySelectionStateToData(converter.dataPoints);\r\n interactivityService.applySelectionStateToData(converter.legendData.dataPoints);\r\n }\r\n\r\n let culledDataPoints = (!disableGeometricCulling && viewport) ? DonutChart.cullDataByViewport(converter.dataPoints, converter.maxValue, viewport) : converter.dataPoints;\r\n return {\r\n dataPointsToDeprecate: culledDataPoints,\r\n dataPoints: d3PieLayout(culledDataPoints),\r\n unCulledDataPoints: converter.dataPoints,\r\n dataPointsToEnumerate: converter.legendData.dataPoints,\r\n legendData: converter.legendData,\r\n hasHighlights: converter.hasHighlights,\r\n dataLabelsSettings: converter.dataLabelsSettings,\r\n legendObjectProperties: converter.legendObjectProperties,\r\n maxValue: converter.maxValue,\r\n visibleGeometryCulled: converter.dataPoints.length !== culledDataPoints.length,\r\n };\r\n }\r\n\r\n public init(options: VisualInitOptions) {\r\n this.options = options;\r\n let element = options.element;\r\n // Ensure viewport is empty on init\r\n element.empty();\r\n this.parentViewport = options.viewport;\r\n // avoid deep copy\r\n this.currentViewport = {\r\n height: options.viewport.height,\r\n width: options.viewport.width,\r\n };\r\n\r\n this.formatter = valueFormatter.format;\r\n this.data = {\r\n dataPointsToDeprecate: [],\r\n dataPointsToEnumerate: [],\r\n dataPoints: [],\r\n unCulledDataPoints: [],\r\n legendData: { title: \"\", dataPoints: [], fontSize: SVGLegend.DefaultFontSizeInPt },\r\n hasHighlights: false,\r\n dataLabelsSettings: dataLabelUtils.getDefaultDonutLabelSettings(),\r\n };\r\n this.drilled = false;\r\n // Leaving this false for now, will depend on the datacategory in the future\r\n this.allowDrilldown = false;\r\n this.style = options.style;\r\n this.colors = this.style.colorPalette.dataColors;\r\n this.radius = 0;\r\n this.isInteractive = options.interactivity && options.interactivity.isInteractiveLegend;\r\n let donutChartSettings = this.settings;\r\n\r\n if (this.behavior) {\r\n this.interactivityService = createInteractivityService(options.host);\r\n }\r\n this.legend = createLegend(element, options.interactivity && options.interactivity.isInteractiveLegend, this.interactivityService, this.isScrollable);\r\n\r\n this.hostService = options.host;\r\n\r\n if (this.isInteractive) {\r\n this.chartRotationAnimationDuration = (donutChartSettings && donutChartSettings.chartRotationAnimationDuration) ? donutChartSettings.chartRotationAnimationDuration : 0;\r\n\r\n // Create interactive legend\r\n let legendContainer = this.legendContainer = d3.select(element.get(0))\r\n .append('div')\r\n .classed(DonutChart.InteractiveLegendClassName, true);\r\n this.interactivityState = {\r\n interactiveLegend: new DonutChartInteractiveLegend(this, legendContainer, this.colors, options, this.settings),\r\n valueToAngleFactor: 0,\r\n sliceAngles: [],\r\n currentRotate: 0,\r\n interactiveChosenSliceFinishedSetting: false,\r\n lastChosenInteractiveSliceIndex: 0,\r\n totalDragAngleDifference: 0,\r\n currentIndexDrag: 0,\r\n previousIndexDrag: 0,\r\n previousDragAngle: 0,\r\n donutCenter: { x: 0, y: 0 },\r\n };\r\n }\r\n\r\n this.svg = d3.select(element.get(0))\r\n .append('svg')\r\n .style('position', 'absolute')\r\n .classed(DonutChart.ClassName, true);\r\n\r\n if (this.behavior)\r\n this.clearCatcher = appendClearCatcher(this.svg);\r\n\r\n this.mainGraphicsContext = this.svg.append('g');\r\n this.mainGraphicsContext.append(\"g\")\r\n .classed('slices', true);\r\n\r\n this.labelGraphicsContext = this.svg\r\n .append(\"g\")\r\n .classed(NewDataLabelUtils.labelGraphicsContextClass.class, true);\r\n\r\n this.pie = d3.layout.pie()\r\n .sort(null)\r\n .value((d: DonutDataPoint) => {\r\n return d.percentage;\r\n });\r\n }\r\n\r\n public update(options: VisualUpdateOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n // Viewport resizing\r\n let viewport = options.viewport;\r\n this.parentViewport = viewport;\r\n\r\n let dataViews = this.dataViews = options.dataViews;\r\n if (dataViews && dataViews.length > 0 && dataViews[0].categorical) {\r\n let dataViewMetadata = dataViews[0].metadata;\r\n let defaultDataPointColor = undefined;\r\n if (dataViewMetadata) {\r\n let objects: DataViewObjects = dataViewMetadata.objects;\r\n\r\n if (objects) {\r\n defaultDataPointColor = DataViewObjects.getFillColor(objects, donutChartProps.dataPoint.defaultColor);\r\n }\r\n }\r\n\r\n this.data = DonutChart.converter(dataViews[0], this.colors, defaultDataPointColor, this.currentViewport, this.disableGeometricCulling, this.interactivityService, this.tooltipsEnabled);\r\n this.data.defaultDataPointColor = defaultDataPointColor;\r\n if (!(this.options.interactivity && this.options.interactivity.isInteractiveLegend))\r\n this.renderLegend();\r\n }\r\n\r\n else {\r\n this.data = {\r\n dataPointsToDeprecate: [],\r\n dataPointsToEnumerate: [],\r\n dataPoints: [],\r\n unCulledDataPoints: [],\r\n legendData: { title: \"\", dataPoints: [] },\r\n hasHighlights: false,\r\n dataLabelsSettings: dataLabelUtils.getDefaultDonutLabelSettings(),\r\n };\r\n }\r\n\r\n this.initViewportDependantProperties();\r\n this.initDonutProperties();\r\n this.updateInternal(this.data, options.suppressAnimations);\r\n this.hasSetData = true;\r\n\r\n if (dataViews) {\r\n let warnings = getInvalidValueWarnings(\r\n dataViews,\r\n false /*supportsNaN*/,\r\n false /*supportsNegativeInfinity*/,\r\n false /*supportsPositiveInfinity*/);\r\n\r\n this.hostService.setWarnings(warnings);\r\n }\r\n }\r\n\r\n public onDataChanged(options: VisualDataChangedOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n this.update({\r\n dataViews: options.dataViews,\r\n suppressAnimations: options.suppressAnimations,\r\n viewport: this.currentViewport,\r\n });\r\n }\r\n\r\n public onResizing(viewport: IViewport): void {\r\n this.update({\r\n dataViews: this.dataViews,\r\n suppressAnimations: true,\r\n viewport: viewport,\r\n });\r\n }\r\n\r\n public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {\r\n let enumeration = new ObjectEnumerationBuilder();\r\n\r\n let dataLabelsSettings = this.data && this.data.dataLabelsSettings\r\n ? this.data.dataLabelsSettings\r\n : dataLabelUtils.getDefaultDonutLabelSettings();\r\n\r\n switch (options.objectName) {\r\n case 'legend':\r\n this.enumerateLegend(enumeration);\r\n break;\r\n case 'dataPoint':\r\n this.enumerateDataPoints(enumeration);\r\n break;\r\n case 'labels':\r\n let labelSettingOptions: VisualDataLabelsSettingsOptions = {\r\n enumeration: enumeration,\r\n dataLabelsSettings: dataLabelsSettings,\r\n show: true,\r\n displayUnits: true,\r\n precision: true,\r\n fontSize: true,\r\n labelStyle: true,\r\n };\r\n dataLabelUtils.enumerateDataLabels(labelSettingOptions);\r\n break;\r\n }\r\n return enumeration.complete();\r\n }\r\n\r\n private enumerateDataPoints(enumeration: ObjectEnumerationBuilder): void {\r\n let data = this.data;\r\n if (!data)\r\n return;\r\n\r\n let dataPoints = data.dataPointsToEnumerate;\r\n let dataPointsLength = dataPoints.length;\r\n\r\n for (let i = 0; i < dataPointsLength; i++) {\r\n let dataPoint = dataPoints[i];\r\n enumeration.pushInstance({\r\n objectName: 'dataPoint',\r\n displayName: dataPoint.label,\r\n selector: ColorHelper.normalizeSelector(dataPoint.identity.getSelector()),\r\n properties: {\r\n fill: { solid: { color: dataPoint.color } }\r\n },\r\n });\r\n }\r\n }\r\n\r\n private enumerateLegend(enumeration: ObjectEnumerationBuilder): ObjectEnumerationBuilder {\r\n let data = this.data;\r\n if (!data)\r\n return;\r\n\r\n let legendObjectProperties: DataViewObjects = { legend: data.legendObjectProperties };\r\n\r\n let show = DataViewObjects.getValue(legendObjectProperties, donutChartProps.legend.show, this.legend.isVisible());\r\n let showTitle = DataViewObjects.getValue(legendObjectProperties, donutChartProps.legend.showTitle, true);\r\n let titleText = DataViewObjects.getValue(legendObjectProperties, donutChartProps.legend.titleText, this.data.legendData.title);\r\n let labelColor = DataViewObject.getValue(legendObjectProperties, legendProps.labelColor, this.data.legendData.labelColor);\r\n let labelFontSize = DataViewObject.getValue(legendObjectProperties, legendProps.fontSize, this.data.legendData.fontSize);\r\n\r\n enumeration.pushInstance({\r\n selector: null,\r\n objectName: 'legend',\r\n properties: {\r\n show: show,\r\n position: LegendPosition[this.legend.getOrientation()],\r\n showTitle: showTitle,\r\n titleText: titleText,\r\n labelColor: labelColor,\r\n fontSize: labelFontSize\r\n }\r\n });\r\n }\r\n\r\n public setInteractiveChosenSlice(sliceIndex: number): void {\r\n if (this.interactivityState.sliceAngles.length === 0) return;\r\n\r\n this.interactivityState.lastChosenInteractiveSliceIndex = sliceIndex;\r\n this.interactivityState.interactiveChosenSliceFinishedSetting = false;\r\n let viewport = this.currentViewport;\r\n let moduledIndex = sliceIndex % this.data.dataPoints.length;\r\n let angle = this.interactivityState.sliceAngles[moduledIndex];\r\n\r\n this.svg.select('g')\r\n .transition()\r\n .duration(this.chartRotationAnimationDuration)\r\n .ease('elastic')\r\n .attr('transform', SVGUtil.translateAndRotate(viewport.width / 2, viewport.height / 2, 0, 0, angle))\r\n .each('end', () => { this.interactivityState.interactiveChosenSliceFinishedSetting = true; });\r\n\r\n this.interactivityState.currentRotate = angle;\r\n this.interactivityState.interactiveLegend.updateLegend(moduledIndex);\r\n // Set the opacity of chosen slice to full and the others to semi-transparent\r\n this.svg.selectAll('.slice').attr('opacity', (d, index) => {\r\n return index === moduledIndex ? 1 : 0.6;\r\n });\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n }\r\n\r\n private calculateRadius(): number {\r\n let viewport = this.currentViewport;\r\n if (!this.isInteractive && this.data && this.data.dataLabelsSettings.show) {\r\n // if we have category or data labels, use a sigmoid to blend the desired denominator from 2 to 3.\r\n // if we are taller than we are wide, we need to use a larger denominator to leave horizontal room for the labels.\r\n let hw = viewport.height / viewport.width;\r\n let denom = 2 + (1 / (1 + Math.exp(-5 * (hw - 1))));\r\n return Math.min(viewport.height, viewport.width) / denom;\r\n }\r\n\r\n // no labels (isInteractive does not have labels since the interactive legend shows extra info)\r\n return Math.min(viewport.height, viewport.width) / 2;\r\n }\r\n\r\n private getScaleForLegendArrow() {\r\n let ratio = 1.0;\r\n if (this.maxHeightToScaleDonutLegend && this.currentViewport.height < this.maxHeightToScaleDonutLegend) {\r\n ratio = this.currentViewport.height / this.maxHeightToScaleDonutLegend;\r\n }\r\n return ratio;\r\n }\r\n\r\n private initViewportDependantProperties(duration: number = 0) {\r\n this.currentViewport.height = this.parentViewport.height;\r\n this.currentViewport.width = this.parentViewport.width;\r\n let viewport = this.currentViewport;\r\n\r\n if (this.isInteractive) {\r\n viewport.height -= DonutChart.InteractiveLegendContainerHeight; // leave space for the legend\r\n }\r\n else {\r\n let legendMargins = this.legend.getMargins();\r\n viewport.height -= legendMargins.height;\r\n viewport.width -= legendMargins.width;\r\n }\r\n\r\n this.svg.attr({\r\n 'width': viewport.width,\r\n 'height': viewport.height\r\n });\r\n\r\n if (this.isInteractive) {\r\n this.legendContainer\r\n .style({\r\n 'width': '100%',\r\n 'height': DonutChart.InteractiveLegendContainerHeight + 'px',\r\n 'overflow': 'hidden',\r\n 'top': 0\r\n });\r\n this.svg\r\n .style('top', DonutChart.InteractiveLegendContainerHeight);\r\n } else {\r\n Legend.positionChartArea(this.svg, this.legend);\r\n }\r\n\r\n this.previousRadius = this.radius;\r\n let radius = this.radius = this.calculateRadius();\r\n let halfViewportWidth = viewport.width / 2;\r\n let halfViewportHeight = viewport.height / 2;\r\n\r\n this.arc = d3.svg.arc();\r\n\r\n this.outerArc = d3.svg.arc()\r\n .innerRadius(radius * DonutChart.OuterArcRadiusRatio)\r\n .outerRadius(radius * DonutChart.OuterArcRadiusRatio);\r\n\r\n if (this.isInteractive) {\r\n this.mainGraphicsContext.attr('transform', SVGUtil.translate(halfViewportWidth, halfViewportHeight));\r\n this.labelGraphicsContext.attr('transform', SVGUtil.translate(halfViewportWidth, halfViewportHeight));\r\n } else {\r\n this.mainGraphicsContext.transition().duration(duration).attr('transform', SVGUtil.translate(halfViewportWidth, halfViewportHeight));\r\n this.labelGraphicsContext.transition().duration(duration).attr('transform', SVGUtil.translate(halfViewportWidth, halfViewportHeight));\r\n }\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n }\r\n\r\n private initDonutProperties() {\r\n this.donutProperties = {\r\n viewport: this.currentViewport,\r\n radius: this.radius,\r\n arc: this.arc.innerRadius(0).outerRadius(this.radius * DonutChart.InnerArcRadiusRatio),\r\n outerArc: this.outerArc,\r\n innerArcRadiusRatio: DonutChart.InnerArcRadiusRatio,\r\n outerArcRadiusRatio: DonutChart.OuterArcRadiusRatio,\r\n dataLabelsSettings: this.data.dataLabelsSettings,\r\n };\r\n }\r\n\r\n private mergeDatasets(first: any[], second: any[]): any[] {\r\n let secondSet = d3.set();\r\n second.forEach((d) => {\r\n secondSet.add(d.identity ? d.identity.getKey() : d.data.identity.getKey());\r\n });\r\n\r\n let onlyFirst = first.filter((d) => {\r\n return !secondSet.has(d.identity ? d.identity.getKey() : d.data.identity.getKey());\r\n }).map((d) => {\r\n let derived = Prototype.inherit(d);\r\n derived.percentage === undefined ? derived.data.percentage = 0 : derived.percentage = 0;\r\n return derived;\r\n });\r\n\r\n return d3.merge([second, onlyFirst]);\r\n }\r\n\r\n private updateInternal(data: DonutData, suppressAnimations: boolean, duration: number = 0) {\r\n let viewport = this.currentViewport;\r\n duration = duration || AnimatorCommon.GetAnimationDuration(this.animator, suppressAnimations);\r\n if (this.animator) {\r\n let layout = DonutChart.getLayout(this.radius, this.sliceWidthRatio, viewport);\r\n let result: DonutChartAnimationResult;\r\n let shapes: D3.UpdateSelection;\r\n let highlightShapes: D3.UpdateSelection;\r\n let labelSettings = data.dataLabelsSettings;\r\n let labels: Label[] = [];\r\n if (labelSettings && labelSettings.show) {\r\n labels = this.createLabels();\r\n }\r\n if (!suppressAnimations) {\r\n let animationOptions: DonutChartAnimationOptions = {\r\n viewModel: data,\r\n colors: this.colors,\r\n graphicsContext: this.mainGraphicsContext,\r\n labelGraphicsContext: this.labelGraphicsContext,\r\n interactivityService: this.interactivityService,\r\n layout: layout,\r\n radius: this.radius,\r\n sliceWidthRatio: this.sliceWidthRatio,\r\n viewport: viewport,\r\n labels: labels,\r\n innerArcRadiusRatio: DonutChart.InnerArcRadiusRatio,\r\n };\r\n result = this.animator.animate(animationOptions);\r\n shapes = result.shapes;\r\n highlightShapes = result.highlightShapes;\r\n }\r\n if (suppressAnimations || result.failed) {\r\n shapes = DonutChart.drawDefaultShapes(this.svg, data, layout, this.colors, this.radius, this.interactivityService && this.interactivityService.hasSelection(), this.sliceWidthRatio, this.data.defaultDataPointColor);\r\n highlightShapes = DonutChart.drawDefaultHighlightShapes(this.svg, data, layout, this.colors, this.radius, this.sliceWidthRatio);\r\n NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, labels, false, true, true /*has tooltip */);\r\n NewDataLabelUtils.drawLabelLeaderLines(this.labelGraphicsContext, labels);\r\n }\r\n\r\n this.assignInteractions(shapes, highlightShapes, data);\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(shapes, (tooltipEvent: TooltipEvent) => tooltipEvent.data.data.tooltipInfo);\r\n TooltipManager.addTooltip(highlightShapes, (tooltipEvent: TooltipEvent) => tooltipEvent.data.data.tooltipInfo);\r\n }\r\n }\r\n else {\r\n this.updateInternalToMove(data, duration);\r\n }\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n }\r\n\r\n private createLabels(): Label[] {\r\n let labelLayout = new DonutLabelLayout({\r\n maximumOffset: NewDataLabelUtils.maxLabelOffset,\r\n startingOffset: NewDataLabelUtils.startingLabelOffset\r\n }, this.donutProperties);\r\n\r\n let labelDataPoints: DonutLabelDataPoint[] = this.createLabelDataPoints();\r\n\r\n return labelLayout.layout(labelDataPoints);\r\n }\r\n\r\n private createLabelDataPoints(): DonutLabelDataPoint[] {\r\n let data = this.data;\r\n let labelDataPoints: DonutLabelDataPoint[] = [];\r\n let measureFormatterCache = dataLabelUtils.createColumnFormatterCacheManager();\r\n let alternativeScale: number = null;\r\n if (data.dataLabelsSettings.displayUnits === 0)\r\n alternativeScale = <number>d3.max(data.dataPoints, d => Math.abs(d.data.measure));\r\n\r\n for (let i = 0; i < this.data.dataPoints.length; i++) {\r\n let label = this.createLabelDataPoint(data.dataPoints[i], alternativeScale, measureFormatterCache);\r\n labelDataPoints.push(label);\r\n }\r\n return labelDataPoints;\r\n }\r\n\r\n private createLabelDataPoint(d: DonutArcDescriptor, alternativeScale: number, measureFormatterCache: IColumnFormatterCacheManager): DonutLabelDataPoint {\r\n let labelPoint = this.outerArc.centroid(d);\r\n let labelX = DonutLabelUtils.getXPositionForDonutLabel(labelPoint[0]);\r\n let labelY = labelPoint[1];\r\n let labelSettings = this.data.dataLabelsSettings;\r\n let measureFormatter = measureFormatterCache.getOrCreate(d.data.labelFormatString, labelSettings, alternativeScale);\r\n\r\n let position = labelX < 0 ? NewPointLabelPosition.Left : NewPointLabelPosition.Right;\r\n let pointPosition: LabelParentPoint = {\r\n point: {\r\n x: labelX,\r\n y: labelY,\r\n },\r\n validPositions: [position],\r\n radius: 0,\r\n };\r\n\r\n let outsideFill = labelSettings.labelColor ? labelSettings.labelColor : NewDataLabelUtils.defaultLabelColor;\r\n\r\n let dataLabel: string;\r\n let dataLabelSize: ISize;\r\n let categoryLabel: string;\r\n let categoryLabelSize: ISize;\r\n let textSize: ISize;\r\n let labelSettingsStyle = labelSettings.labelStyle;\r\n let fontSize = labelSettings.fontSize;\r\n let tooltip: string = \"\";\r\n\r\n if (labelSettingsStyle === labelStyle.both || labelSettingsStyle === labelStyle.data) {\r\n dataLabel = measureFormatter.format(d.data.highlightValue != null ? d.data.highlightValue : d.data.measure);\r\n dataLabelSize = NewDataLabelUtils.getTextSize(dataLabel, fontSize);\r\n }\r\n\r\n if (labelSettingsStyle === labelStyle.both || labelSettingsStyle === labelStyle.category) {\r\n categoryLabel = d.data.label;\r\n categoryLabelSize = NewDataLabelUtils.getTextSize(categoryLabel, fontSize);\r\n }\r\n\r\n switch (labelSettingsStyle) {\r\n case labelStyle.both:\r\n let text = categoryLabel + \" (\" + dataLabel + \")\";\r\n tooltip = text;\r\n textSize = NewDataLabelUtils.getTextSize(text, fontSize);\r\n break;\r\n case labelStyle.category:\r\n textSize = _.clone(categoryLabelSize);\r\n tooltip = categoryLabel;\r\n break;\r\n case labelStyle.data:\r\n textSize = _.clone(dataLabelSize);\r\n tooltip = dataLabel;\r\n break;\r\n }\r\n\r\n let leaderLinePoints = DonutLabelUtils.getLabelLeaderLineForDonutChart(d, this.donutProperties, pointPosition.point);\r\n let leaderLinesSize: ISize[] = DonutLabelUtils.getLabelLeaderLinesSizeForDonutChart(leaderLinePoints);\r\n\r\n return {\r\n isPreferred: true,\r\n text: \"\",\r\n tooltip: tooltip,\r\n textSize: textSize,\r\n outsideFill: outsideFill,\r\n fontSize: fontSize,\r\n identity: d.data.identity,\r\n parentShape: pointPosition,\r\n insideFill: NewDataLabelUtils.defaultInsideLabelColor,\r\n parentType: LabelDataPointParentType.Point,\r\n alternativeScale: alternativeScale,\r\n donutArcDescriptor: d,\r\n angle: (d.startAngle + d.endAngle) / 2 - (Math.PI / 2),\r\n dataLabel: dataLabel,\r\n dataLabelSize: dataLabelSize,\r\n categoryLabel: categoryLabel,\r\n categoryLabelSize: categoryLabelSize,\r\n leaderLinePoints: leaderLinePoints,\r\n linesSize: leaderLinesSize,\r\n };\r\n }\r\n\r\n private renderLegend(): void {\r\n if (!this.isInteractive) {\r\n let legendObjectProperties = this.data.legendObjectProperties;\r\n if (legendObjectProperties) {\r\n let legendData = this.data.legendData;\r\n LegendData.update(legendData, legendObjectProperties);\r\n let position = <string>legendObjectProperties[legendProps.position];\r\n if (position)\r\n this.legend.changeOrientation(LegendPosition[position]);\r\n\r\n this.legend.drawLegend(legendData, this.parentViewport);\r\n } else {\r\n this.legend.changeOrientation(LegendPosition.Top);\r\n this.legend.drawLegend({ dataPoints: [] }, this.parentViewport);\r\n }\r\n }\r\n }\r\n\r\n private addInteractiveLegendArrow(): void {\r\n if (!this.data || !this.data.dataPoints || this.data.dataPoints.length === 0) return;\r\n\r\n const arrowHeightOffset = 11;\r\n const arrowWidthOffset = 33 / 2;\r\n if (!this.interactiveLegendArrow) {\r\n let interactiveLegendArrow = this.svg.append('g');\r\n interactiveLegendArrow.append('path')\r\n .classed(DonutChart.InteractiveLegendArrowClassName, true)\r\n .attr('d', 'M1.5,2.6C0.65,1.15,1.85,0,3,0l27,0c1.65,0,2.35,1.15,1.5,2.6L18,26.45c-0.8,1.45-2.15,1.45-2.95,0L1.95,2.6z');\r\n this.interactiveLegendArrow = interactiveLegendArrow;\r\n }\r\n let viewport = this.currentViewport;\r\n // Calculate the offsets from the legend container to the arrow.\r\n let scaleRatio = this.getScaleForLegendArrow();\r\n\r\n let distanceBetweenLegendAndArrow = (viewport.height - 2 * this.radius) / 2 + (arrowHeightOffset * scaleRatio);\r\n let middleOfChart = viewport.width / 2 - (arrowWidthOffset * scaleRatio);\r\n\r\n this.interactiveLegendArrow.attr('transform', SVGUtil.translateAndScale(middleOfChart, distanceBetweenLegendAndArrow, scaleRatio));\r\n }\r\n\r\n private calculateSliceAngles(): void {\r\n let angles: number[] = [];\r\n let data = this.data.dataPoints;\r\n\r\n if (data.length === 0) {\r\n this.interactivityState.valueToAngleFactor = 0;\r\n this.interactivityState.sliceAngles = [];\r\n return;\r\n }\r\n\r\n let sum = 0;\r\n for (let i = 0, ilen = data.length; i < ilen; i++) {\r\n sum += data[i].data.percentage; // value is an absolute number\r\n }\r\n debug.assert(sum !== 0, 'sum of slices values cannot be zero');\r\n this.interactivityState.valueToAngleFactor = 360 / sum; // Calculate the ratio between 360 and the sum to know the angles to rotate by\r\n\r\n let currentAngle = 0;\r\n for (let i = 0, ilen = data.length; i < ilen; i++) {\r\n let relativeAngle = data[i].data.percentage * this.interactivityState.valueToAngleFactor;\r\n currentAngle += relativeAngle;\r\n angles.push((relativeAngle / 2) - currentAngle);\r\n }\r\n\r\n this.interactivityState.sliceAngles = angles;\r\n }\r\n\r\n private assignInteractions(slices: D3.Selection, highlightSlices: D3.Selection, data: DonutData): void {\r\n // assign interactions according to chart interactivity type\r\n if (this.isInteractive) {\r\n this.assignInteractiveChartInteractions(slices);\r\n }\r\n else if (this.interactivityService) {\r\n let dataPoints = data.dataPoints.map((value: DonutArcDescriptor) => value.data);\r\n let behaviorOptions: DonutBehaviorOptions = {\r\n clearCatcher: this.clearCatcher,\r\n slices: slices,\r\n highlightSlices: highlightSlices,\r\n allowDrilldown: this.allowDrilldown,\r\n visual: this,\r\n hasHighlights: data.hasHighlights,\r\n svg: this.svg,\r\n };\r\n\r\n this.interactivityService.bind(dataPoints, this.behavior, behaviorOptions);\r\n }\r\n }\r\n\r\n public setDrilldown(selection?: DonutDataPoint): void {\r\n if (selection) {\r\n let d3PieLayout = d3.layout.pie()\r\n .sort(null)\r\n .value((d: DonutDataPoint) => {\r\n return d.percentage;\r\n });\r\n // Drill into the current selection.\r\n let legendDataPoints: LegendDataPoint[] = [{ label: selection.label, color: selection.color, icon: LegendIcon.Box, identity: selection.identity, selected: selection.selected }];\r\n let legendData: LegendData = { title: \"\", dataPoints: legendDataPoints };\r\n let drilledDataPoints = d3PieLayout(selection.internalDataPoints);\r\n this.updateInternal({\r\n dataPointsToDeprecate: selection.internalDataPoints,\r\n dataPoints: drilledDataPoints,\r\n unCulledDataPoints: drilledDataPoints.map((value) => value.data),\r\n legendData: legendData,\r\n hasHighlights: false,\r\n dataLabelsSettings: this.data.dataLabelsSettings,\r\n }, false /* suppressAnimations */, DonutChart.DrillDownAnimationDuration);\r\n } else {\r\n // Pop out of drill down to view the \"outer\" data.\r\n this.updateInternal(this.data, false /* suppressAnimations */, DonutChart.DrillDownAnimationDuration);\r\n }\r\n }\r\n\r\n private assignInteractiveChartInteractions(slice: D3.Selection) {\r\n let svg = this.svg;\r\n\r\n this.interactivityState.interactiveChosenSliceFinishedSetting = true;\r\n let svgRect = svg.node().getBoundingClientRect();\r\n this.interactivityState.donutCenter = { x: svgRect.left + svgRect.width / 2, y: svgRect.top + svgRect.height / 2 }; // Center of the donut chart\r\n this.interactivityState.totalDragAngleDifference = 0;\r\n this.interactivityState.currentRotate = 0;\r\n\r\n this.calculateSliceAngles();\r\n\r\n // Set the on click method for the slices so thsete pie chart will turn according to each slice's corresponding angle [the angle its on top]\r\n slice.on('click', (d: DonutArcDescriptor, clickedIndex: number) => {\r\n if (d3.event.defaultPrevented) return; // click was suppressed, for example from drag event\r\n this.setInteractiveChosenSlice(clickedIndex);\r\n });\r\n\r\n // Set the drag events\r\n let drag = d3.behavior.drag()\r\n .origin(Object)\r\n .on('dragstart', () => this.interactiveDragStart())\r\n .on('drag', () => this.interactiveDragMove())\r\n .on('dragend', () => this.interactiveDragEnd());\r\n svg\r\n .style('touch-action', 'none')\r\n .call(drag);\r\n }\r\n\r\n /**\r\n * Get the angle (in degrees) of the drag event coordinates.\r\n * The angle is calculated against the plane of the center of the donut\r\n * (meaning, when the center of the donut is at (0,0) coordinates).\r\n */\r\n private getAngleFromDragEvent(): number {\r\n let interactivityState = this.interactivityState;\r\n\r\n // get pageX and pageY (coordinates of the drag event) according to event type\r\n let pageX, pageY;\r\n let sourceEvent = <any>d3.event.sourceEvent;\r\n // check if that's a touch event or not\r\n if (sourceEvent.type.toLowerCase().indexOf('touch') !== -1) {\r\n if (sourceEvent.touches.length !== 1) return null; // in case there isn't a single touch - return null and do nothing.\r\n // take the first, single, touch surface.\r\n let touch = sourceEvent.touches[0];\r\n pageX = touch.pageX;\r\n pageY = touch.pageY;\r\n } else {\r\n pageX = sourceEvent.pageX;\r\n pageY = sourceEvent.pageY;\r\n }\r\n\r\n // Adjust the coordinates, putting the donut center as the (0,0) coordinates\r\n let adjustedCoordinates = { x: pageX - interactivityState.donutCenter.x, y: -pageY + interactivityState.donutCenter.y };\r\n // Move to polar axis - take only the angle (theta), and convert to degrees\r\n let angleToThePlane = Math.atan2(adjustedCoordinates.y, adjustedCoordinates.x) * 180 / Math.PI;\r\n return angleToThePlane;\r\n }\r\n\r\n private interactiveDragStart(): void {\r\n this.interactivityState.totalDragAngleDifference = 0;\r\n this.interactivityState.previousDragAngle = this.getAngleFromDragEvent();\r\n }\r\n\r\n private interactiveDragMove(): void {\r\n let data = this.data.dataPoints;\r\n let viewport = this.currentViewport;\r\n\r\n let interactivityState = this.interactivityState;\r\n\r\n if (interactivityState.interactiveChosenSliceFinishedSetting === true) {\r\n // get current angle from the drag event\r\n let currentDragAngle = this.getAngleFromDragEvent();\r\n if (!currentDragAngle) return; // if no angle was returned, do nothing\r\n // compare it to the previous drag event angle\r\n let angleDragDiff = interactivityState.previousDragAngle - currentDragAngle;\r\n\r\n interactivityState.totalDragAngleDifference += angleDragDiff;\r\n interactivityState.previousDragAngle = currentDragAngle;\r\n\r\n // Rotate the chart by the difference in angles\r\n interactivityState.currentRotate += angleDragDiff;\r\n\r\n // Rotate the chart to the current rotate angle\r\n this.svg.select('g')\r\n .attr('transform', SVGUtil.translateAndRotate(viewport.width / 2, viewport.height / 2, 0, 0, this.interactivityState.currentRotate));\r\n\r\n let currentHigherLimit = data[0].data.percentage * interactivityState.valueToAngleFactor;\r\n let currentAngle = interactivityState.currentRotate <= 0 ? (interactivityState.currentRotate * -1) % 360 : (360 - (interactivityState.currentRotate % 360));\r\n\r\n interactivityState.currentIndexDrag = 0;\r\n //consider making this ++interactivityState.currentIndexDrag ? then you don't need the if statement, the interactivityState.currentIndexDrag +1 and interactivityState.currentIndexDrag++\r\n // Check the current index according to the angle \r\n let dataLength = data.length;\r\n while ((interactivityState.currentIndexDrag < dataLength) && (currentAngle > currentHigherLimit)) {\r\n if (interactivityState.currentIndexDrag < (dataLength - 1)) {\r\n currentHigherLimit += (data[interactivityState.currentIndexDrag + 1].data.percentage * interactivityState.valueToAngleFactor);\r\n }\r\n interactivityState.currentIndexDrag++;\r\n }\r\n\r\n // If the index changed update the legend and opacity\r\n if (interactivityState.currentIndexDrag !== interactivityState.previousIndexDrag) {\r\n interactivityState.interactiveLegend.updateLegend(interactivityState.currentIndexDrag);\r\n // set the opacticity of the top slice to full and the others to semi-transparent\r\n this.svg.selectAll('.slice').attr('opacity', (d, index) => {\r\n return index === interactivityState.currentIndexDrag ? DonutChart.OpaqueOpacity : DonutChart.SemiTransparentOpacity;\r\n });\r\n interactivityState.previousIndexDrag = interactivityState.currentIndexDrag;\r\n }\r\n }\r\n }\r\n\r\n private interactiveDragEnd(): void {\r\n // If totalDragDifference was changed, means we have a drag event (compared to a click event)\r\n if (this.interactivityState.totalDragAngleDifference !== 0) {\r\n this.setInteractiveChosenSlice(this.interactivityState.currentIndexDrag);\r\n // drag happened - disable click event\r\n d3.event.sourceEvent.stopPropagation();\r\n }\r\n }\r\n\r\n private updateInternalToMove(data: DonutData, duration: number = 0) {\r\n // Cache for performance\r\n let svg = this.svg;\r\n let pie = this.pie;\r\n let key = this.key;\r\n let arc = this.arc;\r\n let radius = this.radius;\r\n let previousRadius = this.previousRadius;\r\n let sliceWidthRatio = this.sliceWidthRatio;\r\n\r\n let existingData = this.svg.select('.slices')\r\n .selectAll('path' + DonutChart.sliceClass.selector)\r\n .data().map((d: DonutArcDescriptor) => d.data);\r\n\r\n if (existingData.length === 0) {\r\n existingData = data.dataPointsToDeprecate;\r\n }\r\n\r\n let is = this.mergeDatasets(existingData, data.dataPointsToDeprecate);\r\n\r\n let slice = svg.select('.slices')\r\n .selectAll('path' + DonutChart.sliceClass.selector)\r\n .data(pie(data.dataPointsToDeprecate), key);\r\n\r\n slice.enter()\r\n .insert('path')\r\n .classed(DonutChart.sliceClass.class, true)\r\n .each(function (d) { this._current = d; });\r\n\r\n slice = svg.select('.slices')\r\n .selectAll('path' + DonutChart.sliceClass.selector)\r\n .data(pie(is), key);\r\n\r\n let innerRadius = radius * sliceWidthRatio;\r\n DonutChart.isSingleColor(data.dataPoints);\r\n\r\n slice\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, false, false, data.hasHighlights))\r\n .style('stroke', 'white')\r\n .style('stroke-dasharray', (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio))\r\n .style('stroke-width', (d: DonutArcDescriptor) => d.data.strokeWidth)\r\n .transition().duration(duration)\r\n .attrTween('d', function (d) {\r\n let i = d3.interpolate(this._current, d),\r\n k = d3.interpolate(previousRadius * DonutChart.InnerArcRadiusRatio\r\n , radius * DonutChart.InnerArcRadiusRatio);\r\n\r\n this._current = i(0);\r\n\r\n return function (t) {\r\n return arc.innerRadius(innerRadius).outerRadius(k(t))(i(t));\r\n };\r\n });\r\n\r\n slice = svg.select('.slices')\r\n .selectAll('path' + DonutChart.sliceClass.selector)\r\n .data(pie(data.dataPointsToDeprecate), key);\r\n\r\n slice.exit()\r\n .transition()\r\n .delay(duration)\r\n .duration(0)\r\n .remove();\r\n\r\n // For interactive chart, there shouldn't be slice labels (as you have the legend).\r\n if (!this.isInteractive) {\r\n let labelSettings = data.dataLabelsSettings;\r\n let labels: Label[] = [];\r\n if (labelSettings && labelSettings.show) {\r\n labels = this.createLabels();\r\n }\r\n NewDataLabelUtils.drawDefaultLabels(this.labelGraphicsContext, labels, false, true);\r\n NewDataLabelUtils.drawLabelLeaderLines(this.labelGraphicsContext, labels);\r\n }\r\n let highlightSlices = undefined;\r\n if (data.hasHighlights) {\r\n // Draw partial highlight slices.\r\n highlightSlices = svg\r\n .select('.slices')\r\n .selectAll('path' + DonutChart.sliceHighlightClass.selector)\r\n .data(pie(data.dataPointsToDeprecate), key);\r\n\r\n highlightSlices\r\n .enter()\r\n .insert('path')\r\n .classed(DonutChart.sliceHighlightClass.class, true)\r\n .each(function (d) { this._current = d; });\r\n\r\n DonutChart.isSingleColor(data.dataPoints);\r\n\r\n highlightSlices\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color)\r\n .style('fill-opacity', 1.0)\r\n .style('stroke', 'white')\r\n .style('stroke-dasharray', (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio, d.data.highlightRatio))\r\n .style('stroke-width', (d: DonutArcDescriptor) => d.data.highlightRatio === 0 ? 0 : d.data.strokeWidth)\r\n .transition().duration(duration)\r\n .attrTween('d', function (d: DonutArcDescriptor) {\r\n let i = d3.interpolate(this._current, d),\r\n k = d3.interpolate(\r\n previousRadius * DonutChart.InnerArcRadiusRatio,\r\n DonutChart.getHighlightRadius(radius, sliceWidthRatio, d.data.highlightRatio));\r\n\r\n this._current = i(0);\r\n\r\n return function (t) {\r\n return arc.innerRadius(innerRadius).outerRadius(k(t))(i(t));\r\n };\r\n });\r\n\r\n highlightSlices\r\n .exit()\r\n .transition()\r\n .delay(duration)\r\n .duration(0)\r\n .remove();\r\n }\r\n else {\r\n svg\r\n .selectAll('path' + DonutChart.sliceHighlightClass.selector)\r\n .transition()\r\n .delay(duration)\r\n .duration(0)\r\n .remove();\r\n }\r\n\r\n this.assignInteractions(slice, highlightSlices, data);\r\n\r\n if (this.tooltipsEnabled) {\r\n TooltipManager.addTooltip(slice, (tooltipEvent: TooltipEvent) => tooltipEvent.data.data.tooltipInfo);\r\n if (data.hasHighlights) {\r\n TooltipManager.addTooltip(highlightSlices, (tooltipEvent: TooltipEvent) => tooltipEvent.data.data.tooltipInfo);\r\n }\r\n }\r\n\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.options);\r\n\r\n if (this.isInteractive) {\r\n this.addInteractiveLegendArrow();\r\n this.interactivityState.interactiveLegend.drawLegend(this.data.dataPointsToDeprecate);\r\n this.setInteractiveChosenSlice(this.interactivityState.lastChosenInteractiveSliceIndex ? this.interactivityState.lastChosenInteractiveSliceIndex : 0);\r\n }\r\n }\r\n\r\n public static drawDefaultShapes(graphicsContext: D3.Selection, donutData: DonutData, layout: DonutLayout, colors: IDataColorPalette, radius: number, hasSelection: boolean, sliceWidthRatio: number, defaultColor?: string): D3.UpdateSelection {\r\n let shapes = graphicsContext.select('.slices')\r\n .selectAll('path' + DonutChart.sliceClass.selector)\r\n .data(donutData.dataPoints, (d: DonutArcDescriptor) => d.data.identity.getKey());\r\n\r\n shapes.enter()\r\n .insert('path')\r\n .classed(DonutChart.sliceClass.class, true);\r\n\r\n DonutChart.isSingleColor(donutData.dataPoints);\r\n\r\n shapes\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, false, hasSelection, donutData.hasHighlights))\r\n .style('stroke-dasharray', (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio))\r\n .style('stroke-width', (d: DonutArcDescriptor) => d.data.strokeWidth)\r\n .attr(layout.shapeLayout);\r\n\r\n shapes.exit()\r\n .remove();\r\n\r\n return shapes;\r\n }\r\n\r\n public static drawDefaultHighlightShapes(graphicsContext: D3.Selection, donutData: DonutData, layout: DonutLayout, colors: IDataColorPalette, radius: number, sliceWidthRatio: number): D3.UpdateSelection {\r\n let shapes = graphicsContext.select('.slices')\r\n .selectAll('path' + DonutChart.sliceHighlightClass.selector)\r\n .data(donutData.dataPoints.filter((value: DonutArcDescriptor) => value.data.highlightRatio != null), (d: DonutArcDescriptor) => d.data.identity.getKey());\r\n\r\n shapes.enter()\r\n .insert('path')\r\n .classed(DonutChart.sliceHighlightClass.class, true)\r\n .each(function (d) { this._current = d; });\r\n\r\n DonutChart.isSingleColor(donutData.dataPoints);\r\n\r\n shapes\r\n .style('fill', (d: DonutArcDescriptor) => d.data.color)\r\n .style('fill-opacity', (d: DonutArcDescriptor) => ColumnUtil.getFillOpacity(d.data.selected, true, false, donutData.hasHighlights))\r\n .style('stroke', 'white')\r\n .style('stroke-dasharray', (d: DonutArcDescriptor) => DonutChart.drawStrokeForDonutChart(radius, DonutChart.InnerArcRadiusRatio, d, sliceWidthRatio, d.data.highlightRatio))\r\n .style('stroke-width', (d: DonutArcDescriptor) => d.data.highlightRatio === 0 ? 0 : d.data.strokeWidth)\r\n .attr(layout.highlightShapeLayout);\r\n\r\n shapes.exit()\r\n .remove();\r\n\r\n return shapes;\r\n }\r\n \r\n /**\r\n Set true to the last data point when all slices have the same color\r\n */\r\n public static isSingleColor(dataPoints: DonutArcDescriptor[]): void {\r\n if (dataPoints.length > 1) {\r\n let lastPoint = dataPoints.length - 1;\r\n dataPoints[lastPoint].data.isLastInDonut = dataPoints[lastPoint].data.color === dataPoints[0].data.color;\r\n }\r\n }\r\n\r\n public static drawStrokeForDonutChart(radius: number, innerArcRadiusRatio: number, d: DonutArcDescriptor, sliceWidthRatio: number, highlightRatio: number = 1): string {\r\n let sliceRadius = radius * innerArcRadiusRatio * highlightRatio;\r\n let sliceArc = (d.endAngle - d.startAngle) * sliceRadius;\r\n let sectionWithoutStroke: number;\r\n let sectionWithStroke: number;\r\n\r\n /*Donut chart*/\r\n if (sliceWidthRatio) {\r\n let innerRadius = radius * sliceWidthRatio;\r\n let outerRadius = highlightRatio * radius * (DonutChart.InnerArcRadiusRatio - sliceWidthRatio);\r\n let innerSliceArc = (d.endAngle - d.startAngle) * innerRadius;\r\n if (d.data.highlightRatio)\r\n sliceArc = (d.endAngle - d.startAngle) * (outerRadius + innerRadius);\r\n\r\n if (d.data.isLastInDonut) {\r\n //if all slices have the same color, the stroke of the last slice needs to be drawn on both radiuses\r\n return 0 + \" \" + sliceArc + \" \" + outerRadius + \" \" + innerSliceArc + \" \" + outerRadius;\r\n }\r\n sectionWithoutStroke = sliceArc + outerRadius + innerSliceArc;\r\n sectionWithStroke = outerRadius;\r\n }\r\n\r\n /*Pie Chart*/\r\n else {\r\n if (d.data.isLastInDonut) {\r\n //if all slices have the same color, the stroke of the last slice needs to be drawn on both radiuses\r\n sectionWithoutStroke = sliceArc;\r\n sectionWithStroke = sliceRadius * 2;\r\n }\r\n else {\r\n sectionWithoutStroke = sliceArc + sliceRadius;\r\n sectionWithStroke = sliceRadius;\r\n }\r\n }\r\n\r\n return 0 + \" \" + sectionWithoutStroke + \" \" + sectionWithStroke;\r\n }\r\n\r\n public onClearSelection() {\r\n if (this.interactivityService)\r\n this.interactivityService.clearSelection();\r\n }\r\n\r\n public static getLayout(radius: number, sliceWidthRatio: number, viewport: IViewport): DonutLayout {\r\n let innerRadius = radius * sliceWidthRatio;\r\n let arc = d3.svg.arc().innerRadius(innerRadius);\r\n let arcWithRadius = arc.outerRadius(radius * DonutChart.InnerArcRadiusRatio);\r\n return {\r\n shapeLayout: {\r\n d: (d: DonutArcDescriptor) => {\r\n return arcWithRadius(d);\r\n }\r\n },\r\n highlightShapeLayout: {\r\n d: (d: DonutArcDescriptor) => {\r\n let highlightArc = arc.outerRadius(DonutChart.getHighlightRadius(radius, sliceWidthRatio, d.data.highlightRatio));\r\n return highlightArc(d);\r\n }\r\n },\r\n zeroShapeLayout: {\r\n d: (d: DonutArcDescriptor) => {\r\n let zeroWithZeroRadius = arc.outerRadius(innerRadius || DonutChart.EffectiveZeroValue);\r\n return zeroWithZeroRadius(d);\r\n }\r\n },\r\n };\r\n }\r\n\r\n private static getHighlightRadius(radius: number, sliceWidthRatio: number, highlightRatio: number): number {\r\n let innerRadius = radius * sliceWidthRatio;\r\n return innerRadius + highlightRatio * radius * (DonutChart.InnerArcRadiusRatio - sliceWidthRatio);\r\n }\r\n\r\n public static cullDataByViewport(dataPoints: DonutDataPoint[], maxValue: number, viewport: IViewport): DonutDataPoint[] {\r\n let estimatedRadius = Math.min(viewport.width, viewport.height) / 2;\r\n // Ratio of slice too small to show (invisible) = invisbleArcLength / circumference\r\n let cullRatio = this.invisibleArcLengthInPixels / (estimatedRadius * DonutChart.twoPi);\r\n let cullableValue = cullRatio * maxValue;\r\n let culledDataPoints: DonutDataPoint[] = [];\r\n let prevPointColor: string;\r\n for (let datapoint of dataPoints) {\r\n if (datapoint.measure >= cullableValue) {\r\n //updates the stroke width\r\n datapoint.strokeWidth = prevPointColor === datapoint.color ? 1 : 0;\r\n prevPointColor = datapoint.color;\r\n culledDataPoints.push(datapoint);\r\n }\r\n }\r\n\r\n return culledDataPoints;\r\n }\r\n }\r\n\r\n /**\r\n * This class is an interactive legend for the Donut Chart. \r\n * \r\n * Features: It is scrollable indefinitely, using drag gesture\r\n * when you interact with it, it updates the donut chart itself.\r\n */\r\n class DonutChartInteractiveLegend {\r\n\r\n private static LegendContainerClassName = 'legend-container';\r\n private static LegendContainerSelector = '.legend-container';\r\n private static LegendItemClassName = 'legend-item';\r\n private static LegendItemSelector = '.legend-item';\r\n private static LegendItemCategoryClassName = 'category';\r\n private static LegendItemPercentageClassName = 'percentage';\r\n private static LegendItemValueClassName = 'value';\r\n\r\n private static MaxLegendItemBoxSize = 160;\r\n private static ItemMargin = 30; // Margin between items\r\n private static MinimumSwipeDX = 15; // Minimup swipe gesture to create a change in the legend\r\n private static MinimumItemsInLegendForCycled = 3; // Minimum items in the legend before we cycle it\r\n\r\n private donutChart: DonutChart;\r\n private legendContainerParent: D3.Selection;\r\n private legendContainer: D3.Selection;\r\n private legendContainerWidth: number;\r\n private data: DonutDataPoint[];\r\n private colors: IDataColorPalette;\r\n private visualInitOptions: VisualInitOptions;\r\n\r\n private currentNumberOfLegendItems: number;\r\n private currentIndex: number;\r\n private leftMostIndex: number;\r\n private rightMostIndex: number;\r\n private currentXOffset: number;\r\n private legendItemsPositions: { startX: number; boxWidth: number; }[];\r\n private legendTransitionAnimationDuration: number;\r\n\r\n constructor(donutChart: DonutChart, legendContainer: D3.Selection, colors: IDataColorPalette, visualInitOptions: VisualInitOptions, settings?: DonutChartSettings) {\r\n this.legendContainerParent = legendContainer;\r\n this.colors = colors;\r\n this.donutChart = donutChart;\r\n this.visualInitOptions = visualInitOptions;\r\n this.legendItemsPositions = [];\r\n\r\n this.legendTransitionAnimationDuration = settings && settings.legendTransitionAnimationDuration ? settings.legendTransitionAnimationDuration : 0;\r\n }\r\n\r\n public drawLegend(data: DonutDataPoint[]): void {\r\n this.data = data;\r\n\r\n this.currentNumberOfLegendItems = data.length;\r\n this.currentIndex = 0;\r\n this.leftMostIndex = 0;\r\n this.rightMostIndex = data.length - 1;\r\n\r\n if (this.legendContainerParent.select(DonutChartInteractiveLegend.LegendContainerSelector).empty()) {\r\n this.legendContainer = this.legendContainerParent.append('div').classed(DonutChartInteractiveLegend.LegendContainerClassName, true);\r\n }\r\n\r\n let legendItems = this.legendContainer.selectAll(DonutChartInteractiveLegend.LegendItemSelector).data(data);\r\n let legendContainerWidth = this.legendContainerWidth = this.legendContainer.node().getBoundingClientRect().width;\r\n let initialXOffset = legendContainerWidth / 2 - (legendContainerWidth * 0.4 / 2) + DonutChartInteractiveLegend.ItemMargin;\r\n let currX = initialXOffset;\r\n this.currentXOffset = initialXOffset;\r\n\r\n // Given the legend item div, create the item values (category, percentage and measure) on top of it.\r\n let createLegendItem = (itemDiv: JQuery, datum: DonutDataPoint) => {\r\n // position the legend item\r\n itemDiv\r\n .attr('data-legend-index', datum.index) // assign index for later use\r\n .css({\r\n 'position': 'absolute',\r\n 'left': currX,\r\n //'margin-right': DonutChartInteractiveLegend.ItemMargin + 'px',\r\n });\r\n\r\n // Add the category, percentage and value\r\n let itemCategory = valueFormatter.format(datum.label);\r\n let itemValue = valueFormatter.format(datum.measure, datum.measureFormat);\r\n let itemPercentage = valueFormatter.format(datum.percentage, '0.00 %;-0.00 %;0.00 %');\r\n let itemColor = datum.color;\r\n\r\n // Create basic spans for width calculations\r\n let itemValueSpan = DonutChartInteractiveLegend.createBasicLegendItemSpan(DonutChartInteractiveLegend.LegendItemValueClassName, itemValue, 11);\r\n let itemCategorySpan = DonutChartInteractiveLegend.createBasicLegendItemSpan(DonutChartInteractiveLegend.LegendItemCategoryClassName, itemCategory, 11);\r\n let itemPercentageSpan = DonutChartInteractiveLegend.createBasicLegendItemSpan(DonutChartInteractiveLegend.LegendItemPercentageClassName, itemPercentage, 20);\r\n\r\n // Calculate Legend Box size according to widths and set the width accordingly\r\n let valueSpanWidth = DonutChartInteractiveLegend.spanWidth(itemValueSpan);\r\n let categorySpanWidth = DonutChartInteractiveLegend.spanWidth(itemCategorySpan);\r\n let precentageSpanWidth = DonutChartInteractiveLegend.spanWidth(itemPercentageSpan);\r\n let currentLegendBoxWidth = DonutChartInteractiveLegend.legendBoxSize(valueSpanWidth, categorySpanWidth, precentageSpanWidth);\r\n itemDiv.css('width', currentLegendBoxWidth);\r\n\r\n // Calculate margins so that all the spans will be placed in the middle\r\n let getLeftValue = (spanWidth: number) => {\r\n return currentLegendBoxWidth - spanWidth > 0 ? (currentLegendBoxWidth - spanWidth) / 2 : 0;\r\n };\r\n let marginLeftValue = getLeftValue(valueSpanWidth);\r\n let marginLeftCategory = getLeftValue(categorySpanWidth);\r\n let marginLeftPrecentage = getLeftValue(precentageSpanWidth);\r\n\r\n // Create the actual spans with the right styling and margins so it will be center aligned and add them\r\n DonutChartInteractiveLegend.createLegendItemSpan(itemCategorySpan, marginLeftCategory);\r\n DonutChartInteractiveLegend.createLegendItemSpan(itemValueSpan, marginLeftValue);\r\n DonutChartInteractiveLegend.createLegendItemSpan(itemPercentageSpan, marginLeftPrecentage).css('color', itemColor);\r\n\r\n itemDiv.append(itemCategorySpan);\r\n itemDiv.append(itemPercentageSpan);\r\n itemDiv.append(itemValueSpan);\r\n\r\n this.legendItemsPositions.push({\r\n startX: currX,\r\n boxWidth: currentLegendBoxWidth,\r\n });\r\n currX += currentLegendBoxWidth + DonutChartInteractiveLegend.ItemMargin;\r\n };\r\n\r\n // Create the Legend Items\r\n legendItems.enter()\r\n .insert('div')\r\n .classed(DonutChartInteractiveLegend.LegendItemClassName, true)\r\n .each(function (d: DonutDataPoint) {\r\n createLegendItem($(this), d);\r\n });\r\n\r\n legendItems.exit().remove();\r\n\r\n // Assign interactions on the legend\r\n this.assignInteractions();\r\n }\r\n\r\n public updateLegend(sliceIndex): void {\r\n let legendContainerWidth = this.legendContainerWidth;\r\n\r\n this.currentIndex = sliceIndex;\r\n // \"rearrange\" legend items if needed, so we would have contnious endless scrolling\r\n this.updateLabelBlocks(sliceIndex);\r\n let legendTransitionAnimationDuration = this.legendTransitionAnimationDuration;\r\n // Transform the legend so that the selected slice would be in the middle\r\n let nextXOffset = (this.legendItemsPositions[sliceIndex].startX + (this.legendItemsPositions[sliceIndex].boxWidth / 2) - (legendContainerWidth / 2)) * (-1);\r\n this.legendContainer\r\n .transition()\r\n .styleTween('-webkit-transform', (d: any, i: number, a: any) => {\r\n return d3.interpolate(\r\n SVGUtil.translateWithPixels(this.currentXOffset, 0),\r\n SVGUtil.translateWithPixels(nextXOffset, 0));\r\n })\r\n .styleTween('transform', (d: any, i: number, a: any) => {\r\n return d3.interpolate(\r\n SVGUtil.translateWithPixels(this.currentXOffset, 0),\r\n SVGUtil.translateWithPixels(nextXOffset, 0));\r\n })\r\n .duration(legendTransitionAnimationDuration)\r\n .ease('bounce')\r\n .each('end', () => {\r\n this.currentXOffset = nextXOffset;\r\n });\r\n SVGUtil.flushAllD3TransitionsIfNeeded(this.visualInitOptions);\r\n }\r\n\r\n private assignInteractions() {\r\n let currentDX = 0; // keep how much drag had happened\r\n let hasChanged = false; // flag to indicate if we changed the \"center\" value in the legend. We only change it once per swipe.\r\n\r\n let dragStart = () => {\r\n currentDX = 0; // start of drag gesture\r\n hasChanged = false;\r\n };\r\n\r\n let dragMove = () => {\r\n currentDX += d3.event.dx;\r\n // Detect if swipe occured and if the index already changed in this drag\r\n if (hasChanged || Math.abs(currentDX) < DonutChartInteractiveLegend.MinimumSwipeDX) return;\r\n\r\n let dragDirectionLeft = (currentDX < 0);\r\n this.dragLegend(dragDirectionLeft);\r\n hasChanged = true;\r\n };\r\n\r\n let drag = d3.behavior.drag()\r\n .origin(Object)\r\n .on('drag', dragMove)\r\n .on('dragstart', dragStart);\r\n\r\n this.legendContainer\r\n .style({\r\n 'touch-action': 'none',\r\n 'cursor': 'pointer'\r\n })\r\n .call(drag);\r\n }\r\n\r\n private dragLegend(dragDirectionLeft: boolean): void {\r\n\r\n if (this.currentNumberOfLegendItems > (DonutChartInteractiveLegend.MinimumItemsInLegendForCycled - 1)) {\r\n this.currentIndex = this.getCyclingCurrentIndex(dragDirectionLeft);\r\n } else {\r\n if (this.shouldChangeIndexInNonCycling(dragDirectionLeft)) {\r\n if (dragDirectionLeft) {\r\n this.currentIndex++;\r\n } else {\r\n this.currentIndex--;\r\n }\r\n }\r\n }\r\n this.donutChart.setInteractiveChosenSlice(this.currentIndex);\r\n }\r\n\r\n private shouldChangeIndexInNonCycling(dragDirectionLeft: boolean): boolean {\r\n if ((this.currentIndex === 0 && !dragDirectionLeft) || (this.currentIndex === (this.currentNumberOfLegendItems - 1) && dragDirectionLeft)) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n private getCyclingCurrentIndex(dragDirectionLeft: boolean): number {\r\n let dataLen = this.data.length;\r\n let delta = dragDirectionLeft ? 1 : -1;\r\n let newIndex = (this.currentIndex + delta) % (dataLen || 1); // modolu of negative number stays negative on javascript\r\n return (newIndex < 0) ? newIndex + dataLen : newIndex;\r\n }\r\n\r\n private updateLegendItemsBlocks(rightSidedShift: boolean, numberOfLegendItemsBlocksToShift: number) {\r\n let legendContainer$ = $(this.legendContainer[0]);\r\n\r\n if (rightSidedShift) {\r\n let smallestItem = legendContainer$.find('[data-legend-index=' + this.leftMostIndex + ']');\r\n smallestItem.remove().insertAfter(legendContainer$.find('[data-legend-index=' + this.rightMostIndex + ']'));\r\n let newX = this.legendItemsPositions[this.rightMostIndex].startX + this.legendItemsPositions[this.rightMostIndex].boxWidth + DonutChartInteractiveLegend.ItemMargin;\r\n this.legendItemsPositions[this.leftMostIndex].startX = newX;\r\n smallestItem.css('left', newX);\r\n\r\n this.rightMostIndex = this.leftMostIndex;\r\n this.leftMostIndex = (this.leftMostIndex + 1) % this.data.length;\r\n } else {\r\n let highestItem = legendContainer$.find('[data-legend-index=' + this.rightMostIndex + ']');\r\n highestItem.remove().insertBefore(legendContainer$.find('[data-legend-index=' + this.leftMostIndex + ']'));\r\n let newX = this.legendItemsPositions[this.leftMostIndex].startX - this.legendItemsPositions[this.rightMostIndex].boxWidth - DonutChartInteractiveLegend.ItemMargin;\r\n this.legendItemsPositions[this.rightMostIndex].startX = newX;\r\n highestItem.css('left', newX);\r\n\r\n this.leftMostIndex = this.rightMostIndex;\r\n this.rightMostIndex = (this.rightMostIndex - 1) === -1 ? (this.legendItemsPositions.length - 1) : (this.rightMostIndex - 1);\r\n }\r\n\r\n if ((numberOfLegendItemsBlocksToShift - 1) !== 0) {\r\n this.updateLegendItemsBlocks(rightSidedShift, (numberOfLegendItemsBlocksToShift - 1));\r\n }\r\n }\r\n\r\n /** Update the legend items, allowing for endless rotation */\r\n private updateLabelBlocks(index: number) {\r\n\r\n if (this.currentNumberOfLegendItems > DonutChartInteractiveLegend.MinimumItemsInLegendForCycled) {\r\n // The idea of the four if's is to keep two labels before and after the current one so it will fill the screen.\r\n\r\n // If the index of the slice is the highest currently availble add 2 labels \"ahead\" of it\r\n if (this.rightMostIndex === index) this.updateLegendItemsBlocks(true, 2);\r\n\r\n // If the index of the slice is the lowest currently availble add 2 labels \"before\" it\r\n if (this.leftMostIndex === index) this.updateLegendItemsBlocks(false, 2);\r\n\r\n // If the index of the slice is the second highest currently availble add a labels \"ahead\" of it\r\n if (this.rightMostIndex === (index + 1) || ((this.rightMostIndex === 0) && (index === (this.currentNumberOfLegendItems - 1)))) this.updateLegendItemsBlocks(true, 1);\r\n\r\n // If the index of the slice is the second lowest currently availble add a labels \"before\" it\r\n if (this.leftMostIndex === (index - 1) || ((this.leftMostIndex === (this.currentNumberOfLegendItems - 1) && (index === 0)))) this.updateLegendItemsBlocks(false, 1);\r\n\r\n } else {\r\n\r\n if (this.currentNumberOfLegendItems === DonutChartInteractiveLegend.MinimumItemsInLegendForCycled) {\r\n // If the index of the slice is the highest currently availble add a label \"ahead\" of it\r\n if (this.rightMostIndex === index) this.updateLegendItemsBlocks(true, 1);\r\n\r\n // If the index of the slice is the lowest currently availble add a label \"before\" it\r\n if (this.leftMostIndex === index) this.updateLegendItemsBlocks(false, 1);\r\n }\r\n }\r\n }\r\n\r\n private static createBasicLegendItemSpan(spanClass: string, text: string, fontSize: number): JQuery {\r\n return $('<span/>')\r\n .addClass(spanClass)\r\n .css({\r\n 'white-space': 'nowrap',\r\n 'font-size': fontSize + 'px',\r\n })\r\n .text(text);\r\n }\r\n\r\n /** This method alters the given span and sets it to the final legen item span style. */\r\n private static createLegendItemSpan(existingSpan: JQuery, marginLeft: number): JQuery {\r\n existingSpan\r\n .css({\r\n 'overflow': 'hidden',\r\n 'text-overflow': 'ellipsis',\r\n 'display': 'inline-block',\r\n 'width': '100%',\r\n 'margin-left': marginLeft\r\n });\r\n return existingSpan;\r\n }\r\n\r\n /** Caclulte entire legend box size according to its building spans */\r\n private static legendBoxSize(valueSpanWidth: number, categorySpanWidth: number, precentageSpanWidth: number): number {\r\n let boxSize = valueSpanWidth > categorySpanWidth ? valueSpanWidth : categorySpanWidth;\r\n boxSize = boxSize > precentageSpanWidth ? boxSize : precentageSpanWidth;\r\n boxSize = boxSize > DonutChartInteractiveLegend.MaxLegendItemBoxSize ? DonutChartInteractiveLegend.MaxLegendItemBoxSize : (boxSize + 2);\r\n return boxSize;\r\n }\r\n\r\n private static FakeElementSpan: JQuery;\r\n private static spanWidth(span: JQuery): any {\r\n if (!this.FakeElementSpan) {\r\n this.FakeElementSpan = $('<span>').hide().appendTo(document.body);\r\n }\r\n this.FakeElementSpan.empty();\r\n this.FakeElementSpan.append(span);\r\n return this.FakeElementSpan.width();\r\n }\r\n }\r\n\r\n module DonutChartConversion {\r\n\r\n interface ConvertedDataPoint {\r\n identity: SelectionId;\r\n measureFormat: string;\r\n measureValue: MeasureAndValue;\r\n highlightMeasureValue: MeasureAndValue;\r\n index: number;\r\n label: any;\r\n categoryLabel: string;\r\n color: string;\r\n seriesIndex?: number;\r\n };\r\n\r\n interface MeasureAndValue {\r\n measure: number;\r\n value: number;\r\n }\r\n\r\n export class DonutChartConverter {\r\n private reader: IDataViewCategoricalReader;\r\n private dataViewCategorical: DataViewCategorical;\r\n private dataViewMetadata: DataViewMetadata;\r\n private highlightsOverflow: boolean;\r\n private total: number;\r\n private highlightTotal: number;\r\n private grouped: DataViewValueColumnGroup[];\r\n private isMultiMeasure: boolean;\r\n private isSingleMeasure: boolean;\r\n private isDynamicSeries: boolean;\r\n private seriesCount: number;\r\n private categoryIdentities: DataViewScopeIdentity[];\r\n private categoryValues: any[];\r\n private allCategoryObjects: DataViewObjects[];\r\n private categoryColumnRef: data.SQExpr[];\r\n private legendDataPoints: LegendDataPoint[];\r\n private colorHelper: ColorHelper;\r\n private categoryFormatString: string;\r\n private tooltipsEnabled;\r\n public hasHighlights: boolean;\r\n public dataPoints: DonutDataPoint[];\r\n public legendData: LegendData;\r\n public dataLabelsSettings: VisualDataLabelsSettings;\r\n public legendObjectProperties: DataViewObject;\r\n public maxValue: number;\r\n\r\n public constructor(dataView: DataView, colors: IDataColorPalette, defaultDataPointColor?: string, tooltipsEnabled: boolean = true) {\r\n let reader = this.reader = data.createIDataViewCategoricalReader(dataView);\r\n let dataViewCategorical = dataView.categorical;\r\n this.dataViewCategorical = dataViewCategorical;\r\n this.dataViewMetadata = dataView.metadata;\r\n this.tooltipsEnabled = tooltipsEnabled;\r\n this.colorHelper = new ColorHelper(colors, donutChartProps.dataPoint.fill, defaultDataPointColor);\r\n this.maxValue = 0;\r\n\r\n if (dataViewCategorical.categories && dataViewCategorical.categories.length > 0) {\r\n let category = dataViewCategorical.categories[0];\r\n this.categoryIdentities = category.identity;\r\n this.categoryValues = category.values;\r\n this.allCategoryObjects = category.objects;\r\n this.categoryColumnRef = <data.SQExpr[]>category.identityFields;\r\n this.categoryFormatString = valueFormatter.getFormatString(category.source, donutChartProps.general.formatString);\r\n }\r\n\r\n let grouped = this.grouped = dataViewCategorical && dataViewCategorical.values ? dataViewCategorical.values.grouped() : undefined;\r\n this.isMultiMeasure = grouped && grouped.length > 0 && grouped[0].values && grouped[0].values.length > 1;\r\n this.isSingleMeasure = grouped && grouped.length === 1 && grouped[0].values && grouped[0].values.length === 1;\r\n this.isDynamicSeries = !!(dataViewCategorical.values && dataViewCategorical.values.source);\r\n\r\n this.highlightsOverflow = false;\r\n this.total = 0;\r\n this.highlightTotal = 0;\r\n this.dataPoints = [];\r\n this.legendDataPoints = [];\r\n this.dataLabelsSettings = null;\r\n\r\n if (reader.hasValues(\"Y\")) {\r\n let seriesCount = this.seriesCount = reader.getSeriesCount(\"Y\");\r\n this.hasHighlights = this.seriesCount > 0 && !_.isEmpty(dataViewCategorical.values) && !!dataViewCategorical.values[0].highlights;\r\n // We iterate over all categories, or if we have no categories, we just iterate over the series (category index = 0 is fine in that case)\r\n for (let categoryIndex = 0, categoryCount = reader.getCategoryCount() || 1; categoryIndex < categoryCount; categoryIndex++) {\r\n for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {\r\n this.total += Math.abs(reader.getValue(\"Y\", categoryIndex, seriesIndex));\r\n this.highlightTotal += this.hasHighlights ? Math.abs(reader.getHighlight(\"Y\", categoryIndex, seriesIndex)) : 0;\r\n }\r\n }\r\n }\r\n\r\n this.total = AxisHelper.normalizeNonFiniteNumber(this.total);\r\n this.highlightTotal = AxisHelper.normalizeNonFiniteNumber(this.highlightTotal);\r\n }\r\n\r\n private static normalizedMeasureAndValue(measureAndValue: MeasureAndValue): MeasureAndValue {\r\n let normalized: MeasureAndValue = $.extend(true, {}, measureAndValue);\r\n normalized.measure = AxisHelper.normalizeNonFiniteNumber(normalized.measure);\r\n normalized.value = AxisHelper.normalizeNonFiniteNumber(normalized.value);\r\n\r\n return normalized;\r\n }\r\n\r\n public convert(): void {\r\n let reader = this.reader;\r\n let convertedData: ConvertedDataPoint[];\r\n if (this.total !== 0) {\r\n // We render based on categories, series, or measures in that order of preference\r\n if (this.categoryValues) {\r\n convertedData = this.convertCategoricalWithSlicing();\r\n }\r\n else if (this.isDynamicSeries) {\r\n // Series but no category.\r\n convertedData = this.convertSeries();\r\n }\r\n else {\r\n // No category or series; only measures.\r\n convertedData = this.convertMeasures();\r\n }\r\n }\r\n else {\r\n convertedData = [];\r\n }\r\n\r\n // Check if any of the highlight values are > non-highlight values\r\n let highlightsOverflow = false;\r\n for (let i = 0, dataPointCount = convertedData.length; i < dataPointCount && !highlightsOverflow; i++) {\r\n let point = convertedData[i];\r\n if (Math.abs(point.highlightMeasureValue.measure) > Math.abs(point.measureValue.measure)) {\r\n highlightsOverflow = true;\r\n }\r\n }\r\n\r\n // Create data labels settings\r\n this.dataLabelsSettings = this.convertDataLabelSettings();\r\n\r\n let dataViewMetadata = this.dataViewMetadata;\r\n if (dataViewMetadata) {\r\n let objects: DataViewObjects = dataViewMetadata.objects;\r\n if (objects) {\r\n this.legendObjectProperties = <DataViewObject>objects['legend'];\r\n }\r\n }\r\n\r\n let category = !_.isEmpty(this.dataViewCategorical.categories) ? this.dataViewCategorical.categories[0] : null;\r\n this.dataPoints = [];\r\n let formatStringProp = donutChartProps.general.formatString;\r\n let prevPointColor: string;\r\n let pctFormatString = valueFormatter.getLocalizedString('Percentage');\r\n\r\n for (let i = 0, dataPointCount = convertedData.length; i < dataPointCount; i++) {\r\n let point = convertedData[i];\r\n\r\n // Normalize the values here and then handle tooltip value as infinity\r\n let normalizedHighlight = DonutChartConverter.normalizedMeasureAndValue(point.highlightMeasureValue);\r\n let normalizedNonHighlight = DonutChartConverter.normalizedMeasureAndValue(point.measureValue);\r\n\r\n let measure = normalizedNonHighlight.measure;\r\n let percentage = (this.total > 0) ? normalizedNonHighlight.value / this.total : 0.0;\r\n let highlightRatio: number;\r\n let highlightPercentage: number;\r\n if (normalizedNonHighlight.value > this.maxValue)\r\n this.maxValue = normalizedNonHighlight.value;\r\n if (normalizedHighlight.value > this.maxValue)\r\n this.maxValue = normalizedHighlight.value;\r\n\r\n if (this.hasHighlights) {\r\n // When any highlight value is greater than the corresponding non-highlight value\r\n // we just render all of the highlight values and discard the non-highlight values.\r\n if (highlightsOverflow) {\r\n measure = normalizedHighlight.measure;\r\n\r\n percentage = (this.highlightTotal > 0) ? normalizedHighlight.value / this.highlightTotal : 0.0;\r\n highlightRatio = 1;\r\n }\r\n else {\r\n highlightRatio = normalizedNonHighlight.value !== 0 ? normalizedHighlight.value / normalizedNonHighlight.value : 0;\r\n }\r\n\r\n if (!highlightRatio) {\r\n highlightRatio = DonutChart.EffectiveZeroValue;\r\n }\r\n highlightPercentage = percentage * highlightRatio;\r\n }\r\n\r\n let categoryValue = point.categoryLabel;\r\n let categorical = this.dataViewCategorical;\r\n let valueIndex: number;\r\n if (point.seriesIndex != null) {\r\n valueIndex = point.seriesIndex;\r\n }\r\n else {\r\n // Static series with no categories\r\n valueIndex = i;\r\n }\r\n\r\n let valuesMetadata = reader.getValueMetadataColumn(\"Y\", valueIndex);\r\n let value: number = this.hasHighlights && highlightsOverflow ? point.highlightMeasureValue.measure : point.measureValue.measure;\r\n let highlightValue: number = this.hasHighlights && !highlightsOverflow ? point.highlightMeasureValue.measure : undefined;\r\n let formatString = valueFormatter.getFormatString(valuesMetadata, formatStringProp);\r\n let pct: string = valueFormatter.format(percentage, pctFormatString);\r\n let valueAndPct: string;\r\n valueAndPct = valueFormatter.format(value, formatString) + ' (' + pct + ')';\r\n\r\n let highlightValueAndPct: string;\r\n if (this.hasHighlights && highlightValue != null && highlightPercentage != null) {\r\n let highlightedPct: string = valueFormatter.format(highlightPercentage, pctFormatString); \r\n highlightValueAndPct = valueFormatter.format(highlightValue, formatString) + ' (' + highlightedPct + ')';\r\n }\r\n\r\n let tooltipInfo: TooltipDataItem[];\r\n if (this.tooltipsEnabled) {\r\n tooltipInfo = [];\r\n\r\n if (category) {\r\n tooltipInfo.push({\r\n displayName: category.source.displayName,\r\n value: categoryValue,\r\n });\r\n }\r\n\r\n if (this.isDynamicSeries) {\r\n if (!category || category.source !== categorical.values.source) {\r\n // Category/series on the same column -- don't repeat its value in the tooltip.\r\n tooltipInfo.push({\r\n displayName: categorical.values.source.displayName,\r\n value: point.label,\r\n });\r\n }\r\n }\r\n\r\n if (valueAndPct != null) {\r\n tooltipInfo.push({\r\n displayName: valuesMetadata.displayName,\r\n value: valueAndPct,\r\n });\r\n }\r\n\r\n if (highlightValueAndPct != null) {\r\n tooltipInfo.push({\r\n displayName: ToolTipComponent.localizationOptions.highlightedValueDisplayName,\r\n value: highlightValueAndPct,\r\n });\r\n }\r\n }\r\n\r\n let strokeWidth = prevPointColor === point.color && value && value > 0 ? 1 : 0;\r\n prevPointColor = value && value > 0 ? point.color : prevPointColor;\r\n this.dataPoints.push({\r\n identity: point.identity,\r\n measure: measure,\r\n measureFormat: point.measureFormat,\r\n percentage: percentage,\r\n index: point.index,\r\n label: point.label,\r\n highlightRatio: highlightRatio,\r\n highlightValue: highlightValue,\r\n selected: false,\r\n tooltipInfo: tooltipInfo,\r\n color: point.color,\r\n strokeWidth: strokeWidth,\r\n labelFormatString: valuesMetadata.format,\r\n });\r\n }\r\n\r\n this.legendData = this.convertLegendData();\r\n }\r\n\r\n private getLegendTitle(): string {\r\n if (this.total !== 0) {\r\n // If category exists, we render title using category source. If not, we render title\r\n // using measure.\r\n let dvValuesSourceName = this.dataViewCategorical.values && this.dataViewCategorical.values.source\r\n ? this.dataViewCategorical.values.source.displayName : \"\";\r\n let dvCategorySourceName = this.dataViewCategorical.categories && this.dataViewCategorical.categories.length > 0 && this.dataViewCategorical.categories[0].source\r\n ? this.dataViewCategorical.categories[0].source.displayName : \"\";\r\n if (this.categoryValues) {\r\n return dvCategorySourceName;\r\n }\r\n else {\r\n return dvValuesSourceName;\r\n }\r\n }\r\n else {\r\n return \"\";\r\n }\r\n }\r\n\r\n private convertCategoricalWithSlicing(): ConvertedDataPoint[] {\r\n let reader = this.reader;\r\n let dataViewCategorical = this.dataViewCategorical;\r\n let formatStringProp = donutChartProps.general.formatString;\r\n let dataPoints: ConvertedDataPoint[] = [];\r\n\r\n for (let categoryIndex = 0, categoryCount = this.categoryValues.length; categoryIndex < categoryCount; categoryIndex++) {\r\n let categoryValue = this.categoryValues[categoryIndex];\r\n let thisCategoryObjects = this.allCategoryObjects ? this.allCategoryObjects[categoryIndex] : undefined;\r\n\r\n let legendIdentity = SelectionId.createWithId(this.categoryIdentities[categoryIndex]);\r\n let color = this.colorHelper.getColorForSeriesValue(thisCategoryObjects, this.categoryColumnRef, categoryValue);\r\n let categoryLabel = valueFormatter.format(categoryValue, this.categoryFormatString);\r\n\r\n // Series are either measures in the multi-measure case, or the single series otherwise\r\n for (let seriesIndex = 0; seriesIndex < this.seriesCount; seriesIndex++) {\r\n let valueColumn = reader.getValueColumn(\"Y\", seriesIndex);\r\n\r\n let label = this.isSingleMeasure\r\n ? categoryLabel\r\n : converterHelper.getFormattedLegendLabel(valueColumn.source, dataViewCategorical.values, formatStringProp);\r\n\r\n let nonHighlight = reader.getValue(\"Y\", categoryIndex, seriesIndex) || 0;\r\n let highlight: number;\r\n if (this.hasHighlights) {\r\n highlight = reader.getHighlight(\"Y\", categoryIndex, seriesIndex);\r\n }\r\n\r\n let measure: string = valueColumn.source.queryName;\r\n let identity: SelectionId = SelectionIdBuilder.builder()\r\n .withCategory(dataViewCategorical.categories[0], categoryIndex)\r\n .withSeries(dataViewCategorical.values, this.isDynamicSeries ? valueColumn : undefined)\r\n .withMeasure(measure)\r\n .createSelectionId();\r\n\r\n let dataPoint: ConvertedDataPoint = {\r\n identity: identity,\r\n measureFormat: valueFormatter.getFormatString(valueColumn.source, formatStringProp, true),\r\n measureValue: <MeasureAndValue> {\r\n measure: nonHighlight,\r\n value: Math.abs(nonHighlight),\r\n },\r\n highlightMeasureValue: <MeasureAndValue> {\r\n measure: highlight,\r\n value: highlight != null ? Math.abs(highlight) : null,\r\n },\r\n index: categoryIndex * this.seriesCount + seriesIndex,\r\n label: label,\r\n categoryLabel: categoryLabel,\r\n color: color,\r\n seriesIndex: seriesIndex\r\n };\r\n dataPoints.push(dataPoint);\r\n }\r\n\r\n this.legendDataPoints.push({\r\n label: categoryLabel,\r\n color: color,\r\n icon: LegendIcon.Box,\r\n identity: legendIdentity,\r\n selected: false\r\n });\r\n }\r\n\r\n return dataPoints;\r\n }\r\n\r\n private convertMeasures(): ConvertedDataPoint[] {\r\n let reader = this.reader;\r\n let dataPoints: ConvertedDataPoint[] = [];\r\n let formatStringProp = donutChartProps.general.formatString;\r\n\r\n for (let measureIndex = 0; measureIndex < this.seriesCount; measureIndex++) {\r\n let valueColumn = reader.getValueColumn(\"Y\", measureIndex);\r\n let measureFormat = valueFormatter.getFormatString(valueColumn.source, formatStringProp, true);\r\n let measureLabel = valueColumn.source.displayName;\r\n let identity = SelectionId.createWithMeasure(valueColumn.source.queryName);\r\n\r\n let nonHighlight = reader.getValue(\"Y\", 0, measureIndex) || 0;\r\n let highlight = this.hasHighlights ? reader.getHighlight(\"Y\", 0, measureIndex) : 0;\r\n\r\n let color = this.colorHelper.getColorForMeasure(valueColumn.source.objects, valueColumn.source.queryName);\r\n\r\n let dataPoint: ConvertedDataPoint = {\r\n identity: identity,\r\n measureFormat: measureFormat,\r\n measureValue: <MeasureAndValue> {\r\n measure: nonHighlight,\r\n value: Math.abs(nonHighlight),\r\n },\r\n highlightMeasureValue: <MeasureAndValue> {\r\n measure: highlight,\r\n value: Math.abs(highlight),\r\n },\r\n index: measureIndex,\r\n label: measureLabel,\r\n categoryLabel: measureLabel,\r\n color: color\r\n };\r\n dataPoints.push(dataPoint);\r\n\r\n this.legendDataPoints.push({\r\n label: dataPoint.label,\r\n color: dataPoint.color,\r\n icon: LegendIcon.Box,\r\n identity: dataPoint.identity,\r\n selected: false\r\n });\r\n }\r\n\r\n return dataPoints;\r\n }\r\n\r\n private convertSeries(): ConvertedDataPoint[] {\r\n let reader = this.reader;\r\n let dataViewCategorical = this.dataViewCategorical;\r\n let dataPoints: ConvertedDataPoint[] = [];\r\n let formatStringProp = donutChartProps.general.formatString;\r\n\r\n for (let seriesIndex = 0; seriesIndex < this.seriesCount; seriesIndex++) {\r\n let valueColumn = reader.getValueColumn(\"Y\", seriesIndex);\r\n let seriesFormat = valueFormatter.getFormatString(valueColumn.source, formatStringProp, true);\r\n let label = converterHelper.getFormattedLegendLabel(valueColumn.source, dataViewCategorical.values, formatStringProp);\r\n let identity = new SelectionIdBuilder()\r\n .withSeries(dataViewCategorical.values, valueColumn)\r\n .withMeasure(valueColumn.source.queryName)\r\n .createSelectionId();\r\n let seriesName = converterHelper.getSeriesName(valueColumn.source);\r\n let objects = this.grouped && this.grouped[seriesIndex] && this.grouped[seriesIndex].objects;\r\n \r\n let nonHighlight = reader.getValue(\"Y\", 0, seriesIndex) || 0;\r\n let highlight = this.hasHighlights ? reader.getHighlight(\"Y\", 0, seriesIndex) || 0 : 0;\r\n\r\n let color = this.colorHelper.getColorForSeriesValue(objects, dataViewCategorical.values.identityFields, seriesName);\r\n\r\n let dataPoint: ConvertedDataPoint = {\r\n identity: identity,\r\n measureFormat: seriesFormat,\r\n measureValue: <MeasureAndValue> {\r\n measure: nonHighlight,\r\n value: Math.abs(nonHighlight),\r\n },\r\n highlightMeasureValue: <MeasureAndValue> {\r\n measure: highlight,\r\n value: Math.abs(highlight),\r\n },\r\n index: seriesIndex,\r\n label: label,\r\n categoryLabel: label,\r\n color: color,\r\n seriesIndex: seriesIndex\r\n };\r\n dataPoints.push(dataPoint);\r\n\r\n this.legendDataPoints.push({\r\n label: dataPoint.label,\r\n color: dataPoint.color,\r\n icon: LegendIcon.Box,\r\n identity: dataPoint.identity,\r\n selected: false\r\n });\r\n }\r\n\r\n return dataPoints;\r\n }\r\n\r\n private convertDataLabelSettings(): VisualDataLabelsSettings {\r\n let dataViewMetadata = this.dataViewMetadata;\r\n let dataLabelsSettings = dataLabelUtils.getDefaultDonutLabelSettings();\r\n\r\n if (dataViewMetadata) {\r\n let objects: DataViewObjects = dataViewMetadata.objects;\r\n if (objects) {\r\n // Handle lables settings\r\n let labelsObj = <DataLabelObject>objects['labels'];\r\n if (labelsObj) {\r\n dataLabelUtils.updateLabelSettingsFromLabelsObject(labelsObj, dataLabelsSettings);\r\n }\r\n }\r\n }\r\n\r\n return dataLabelsSettings;\r\n }\r\n\r\n private convertLegendData(): LegendData {\r\n return {\r\n dataPoints: this.legendDataPoints,\r\n labelColor: LegendData.DefaultLegendLabelFillColor,\r\n title: this.getLegendTitle(),\r\n fontSize: SVGLegend.DefaultFontSizeInPt,\r\n };\r\n }\r\n }\r\n }\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n import Utility = jsCommon.Utility;\r\n\r\n export interface ScriptVisualDataViewObjects extends DataViewObjects {\r\n script: ScriptObject;\r\n }\r\n\r\n export interface ScriptObject extends DataViewObject {\r\n provider: string;\r\n source: string;\r\n }\r\n\r\n export interface ScriptVisualOptions {\r\n canRefresh: boolean;\r\n }\r\n\r\n export class ScriptVisual implements IVisual {\r\n private element: JQuery;\r\n private imageBackgroundElement: JQuery;\r\n private hostServices: IVisualHostServices;\r\n private canRefresh: boolean;\r\n\r\n public constructor(options: ScriptVisualOptions) {\r\n this.canRefresh = options.canRefresh;\r\n }\r\n\r\n public init(options: VisualInitOptions): void {\r\n this.element = options.element;\r\n this.hostServices = options.host;\r\n\r\n if (!this.canRefresh) {\r\n this.hostServices.setWarnings([new ScriptVisualRefreshWarning()]);\r\n }\r\n }\r\n\r\n public update(options: VisualUpdateOptions): void {\r\n debug.assertValue(options, 'options');\r\n\r\n let dataViews = options.dataViews;\r\n if (!dataViews || dataViews.length === 0)\r\n return;\r\n\r\n let dataView = dataViews[0];\r\n if (!dataView || !dataView.metadata)\r\n return;\r\n\r\n let imageUrl = this.getImageUrl(dataView);\r\n let div = this.ensureHtmlElement();\r\n\r\n if (imageUrl && Utility.isValidImageDataUrl(imageUrl)) {\r\n let viewport = options.viewport;\r\n\r\n div.css({ height: viewport.height, width: viewport.width, backgroundImage: 'url(' + imageUrl + ')' });\r\n } else {\r\n div.css({ backgroundImage: 'none' });\r\n }\r\n }\r\n\r\n public onResizing(finalViewport: IViewport): void {\r\n let div = this.ensureHtmlElement();\r\n div.css({ height: finalViewport.height, width: finalViewport.width });\r\n }\r\n\r\n private getImageUrl(dataView: DataView): string {\r\n debug.assertValue(dataView, 'dataView');\r\n\r\n if (dataView.scriptResult && dataView.scriptResult.imageBase64) {\r\n return \"data:image/png;base64,\" + dataView.scriptResult.imageBase64;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private ensureHtmlElement(): JQuery {\r\n let div: JQuery = this.imageBackgroundElement;\r\n if (!div) {\r\n div = $(\"<div class='imageBackground' />\");\r\n this.imageBackgroundElement = div;\r\n this.imageBackgroundElement.appendTo(this.element);\r\n }\r\n\r\n return div;\r\n }\r\n }\r\n}\r\n","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals.plugins {\r\n // This file registers the built-in visualizations\r\n\r\n export const animatedNumber: IVisualPlugin = {\r\n name: 'animatedNumber',\r\n capabilities: capabilities.animatedNumber,\r\n create: () => new AnimatedNumber()\r\n };\r\n\r\n export let areaChart: IVisualPlugin = {\r\n name: 'areaChart',\r\n watermarkKey: 'area',\r\n capabilities: capabilities.lineChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.Area }),\r\n customizeQuery: LineChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let barChart: IVisualPlugin = {\r\n name: 'barChart',\r\n watermarkKey: 'bar',\r\n capabilities: capabilities.barChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.StackedBar }),\r\n customizeQuery: ColumnChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let basicShape: IVisualPlugin = {\r\n name: 'basicShape',\r\n capabilities: basicShapeCapabilities,\r\n create: () => new BasicShapeVisual()\r\n };\r\n\r\n export let card: IVisualPlugin = {\r\n name: 'card',\r\n watermarkKey: 'card',\r\n capabilities: capabilities.card,\r\n create: () => new Card()\r\n };\r\n\r\n export let multiRowCard: IVisualPlugin = {\r\n name: 'multiRowCard',\r\n watermarkKey: 'multiRowCard',\r\n capabilities: capabilities.multiRowCard,\r\n create: () => new MultiRowCard(),\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => MultiRowCard.getSortableRoles(visualSortableOptions),\r\n };\r\n\r\n export let clusteredBarChart: IVisualPlugin = {\r\n name: 'clusteredBarChart',\r\n watermarkKey: 'clusteredBar',\r\n capabilities: capabilities.clusteredBarChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.ClusteredBar }),\r\n customizeQuery: ColumnChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let clusteredColumnChart: IVisualPlugin = {\r\n name: 'clusteredColumnChart',\r\n watermarkKey: 'clusteredColumn',\r\n capabilities: capabilities.clusteredColumnChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.ClusteredColumn }),\r\n customizeQuery: ColumnChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let columnChart: IVisualPlugin = {\r\n name: 'columnChart',\r\n watermarkKey: 'column',\r\n capabilities: capabilities.columnChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.StackedColumn }),\r\n customizeQuery: ColumnChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let comboChart: IVisualPlugin = {\r\n name: 'comboChart',\r\n watermarkKey: 'combo',\r\n capabilities: capabilities.comboChart,\r\n customizeQuery: ComboChart.customizeQuery,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.ComboChart }),\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ComboChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let dataDotChart: IVisualPlugin = {\r\n name: 'dataDotChart',\r\n capabilities: capabilities.dataDotChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.DataDot }),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let dataDotClusteredColumnComboChart: IVisualPlugin = {\r\n name: 'dataDotClusteredColumnComboChart',\r\n watermarkKey: 'combo',\r\n capabilities: capabilities.dataDotClusteredColumnComboChart,\r\n customizeQuery: ComboChart.customizeQuery,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.DataDotClusteredColumnCombo }),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let dataDotStackedColumnComboChart: IVisualPlugin = {\r\n name: 'dataDotStackedColumnComboChart',\r\n watermarkKey: 'combo',\r\n capabilities: capabilities.dataDotStackedColumnComboChart,\r\n customizeQuery: ComboChart.customizeQuery,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.DataDotStackedColumnCombo }),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let donutChart: IVisualPlugin = {\r\n name: 'donutChart',\r\n watermarkKey: 'donut',\r\n capabilities: capabilities.donutChart,\r\n create: () => new DonutChart()\r\n };\r\n\r\n export let funnel: IVisualPlugin = {\r\n name: 'funnel',\r\n watermarkKey: 'funnel',\r\n capabilities: capabilities.funnel,\r\n create: () => new FunnelChart()\r\n };\r\n\r\n export let gauge: IVisualPlugin = {\r\n name: 'gauge',\r\n watermarkKey: 'gauge',\r\n capabilities: capabilities.gauge,\r\n create: () => new Gauge()\r\n };\r\n\r\n export let hundredPercentStackedBarChart: IVisualPlugin = {\r\n name: 'hundredPercentStackedBarChart',\r\n watermarkKey: '100stackedbar',\r\n capabilities: capabilities.hundredPercentStackedBarChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.HundredPercentStackedBar }),\r\n customizeQuery: ColumnChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let hundredPercentStackedColumnChart: IVisualPlugin = {\r\n name: 'hundredPercentStackedColumnChart',\r\n watermarkKey: '100stackedcolumn',\r\n capabilities: capabilities.hundredPercentStackedColumnChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.HundredPercentStackedColumn }),\r\n customizeQuery: ColumnChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let image: IVisualPlugin = {\r\n name: 'image',\r\n capabilities: capabilities.image,\r\n create: () => new ImageVisual()\r\n };\r\n\r\n export let lineChart: IVisualPlugin = {\r\n name: 'lineChart',\r\n watermarkKey: 'line',\r\n capabilities: capabilities.lineChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.Line }),\r\n customizeQuery: LineChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => LineChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let lineStackedColumnComboChart: IVisualPlugin = {\r\n name: 'lineStackedColumnComboChart',\r\n watermarkKey: 'combo',\r\n capabilities: capabilities.lineStackedColumnComboChart,\r\n customizeQuery: ComboChart.customizeQuery,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.LineStackedColumnCombo }),\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ComboChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let lineClusteredColumnComboChart: IVisualPlugin = {\r\n name: 'lineClusteredColumnComboChart',\r\n watermarkKey: 'combo',\r\n capabilities: capabilities.lineClusteredColumnComboChart,\r\n customizeQuery: ComboChart.customizeQuery,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.LineClusteredColumnCombo }),\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ComboChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let map: IVisualPlugin = {\r\n name: 'map',\r\n watermarkKey: 'map',\r\n capabilities: capabilities.map,\r\n create: () => new Map({ filledMap: false })\r\n };\r\n\r\n export let filledMap: IVisualPlugin = {\r\n name: 'filledMap',\r\n watermarkKey: 'filledMap',\r\n capabilities: capabilities.filledMap,\r\n create: () => new Map({ filledMap: true })\r\n };\r\n\r\n export let treemap: IVisualPlugin = {\r\n name: 'treemap',\r\n watermarkKey: 'tree',\r\n capabilities: capabilities.treemap,\r\n create: () => new Treemap()\r\n };\r\n\r\n export let pieChart: IVisualPlugin = {\r\n name: 'pieChart',\r\n watermarkKey: 'pie',\r\n capabilities: capabilities.donutChart,\r\n create: () => new DonutChart({ sliceWidthRatio: 0 })\r\n };\r\n\r\n export let scatterChart: IVisualPlugin = {\r\n name: 'scatterChart',\r\n watermarkKey: 'scatterplot',\r\n capabilities: capabilities.scatterChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.Scatter }),\r\n getAdditionalTelemetry: (dataView: DataView) => ScatterChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let stackedAreaChart: IVisualPlugin = {\r\n name: 'stackedAreaChart',\r\n watermarkKey: 'stackedarea',\r\n capabilities: capabilities.lineChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.StackedArea }),\r\n customizeQuery: LineChart.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => ColumnChart.getSortableRoles(visualSortableOptions),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let table: IVisualPlugin = {\r\n name: 'table',\r\n watermarkKey: 'table',\r\n capabilities: capabilities.table,\r\n create: () => new Table(),\r\n customizeQuery: Table.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => Table.getSortableRoles(),\r\n };\r\n\r\n export let matrix: IVisualPlugin = {\r\n name: 'matrix',\r\n watermarkKey: 'matrix',\r\n capabilities: capabilities.matrix,\r\n create: () => new Matrix(),\r\n customizeQuery: Matrix.customizeQuery,\r\n getSortableRoles: (visualSortableOptions?: VisualSortableOptions) => Matrix.getSortableRoles(),\r\n };\r\n\r\n export let slicer: IVisualPlugin = {\r\n name: 'slicer',\r\n watermarkKey: 'slicer',\r\n capabilities: capabilities.slicer,\r\n create: () => new Slicer()\r\n };\r\n\r\n export let textbox: IVisualPlugin = {\r\n name: 'textbox',\r\n capabilities: capabilities.textbox,\r\n create: () => new Textbox()\r\n };\r\n\r\n export let waterfallChart: IVisualPlugin = {\r\n name: 'waterfallChart',\r\n watermarkKey: 'waterfall',\r\n capabilities: capabilities.waterfallChart,\r\n create: () => new CartesianChart({ chartType: CartesianChartType.Waterfall }),\r\n getAdditionalTelemetry: (dataView) => CartesianChart.getAdditionalTelemetry(dataView),\r\n };\r\n\r\n export let cheerMeter: IVisualPlugin = {\r\n name: 'cheerMeter',\r\n capabilities: CheerMeter.capabilities,\r\n create: () => new CheerMeter()\r\n };\r\n\r\n export let consoleWriter: IVisualPlugin = {\r\n name: 'consoleWriter',\r\n capabilities: samples.consoleWriterCapabilities,\r\n create: () => new samples.ConsoleWriter()\r\n };\r\n\r\n export let helloIVisual: IVisualPlugin = {\r\n name: 'helloIVisual',\r\n capabilities: samples.HelloIVisual.capabilities,\r\n create: () => new samples.HelloIVisual()\r\n };\r\n\r\n export let owlGauge: IVisualPlugin = {\r\n name: 'owlGauge',\r\n watermarkKey: 'gauge',\r\n capabilities: OwlGauge.capabilities,\r\n create: () => new OwlGauge()\r\n };\r\n\r\n export let scriptVisual: IVisualPlugin = {\r\n name: 'scriptVisual',\r\n watermarkKey: 'scriptvisual',\r\n capabilities: capabilities.scriptVisual,\r\n create: () => new ScriptVisual({ canRefresh: false })\r\n };\r\n\r\n export let kpi: IVisualPlugin = {\r\n name: 'kpi',\r\n watermarkKey: 'kpi',\r\n capabilities: capabilities.kpi,\r\n create: () => new KPIStatusWithHistory()\r\n };\r\n}","/*\r\n * Power BI Visualizations\r\n *\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. \r\n * MIT License\r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"\"Software\"\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in \r\n * all copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n * THE SOFTWARE.\r\n */\r\n\r\nmodule powerbi.visuals {\r\n\r\n export module CanvasBackgroundHelper {\r\n export function getDefaultColor(): string {\r\n return '#FFFFFF';\r\n }\r\n\r\n export function getDefaultValues() {\r\n return {\r\n color: getDefaultColor(),\r\n };\r\n }\r\n }\r\n} "],"sourceRoot":"/source/"}
\No newline at end of file