/** * Created by mm28969 on 5/19/17. */ import * as d3 from "d3"; import {convertValueToAttribute} from "../mmviz-common/index"; import {createViewModel} from "./layout"; import {LayoutScale} from "./scale"; export function waterfallLayoutCreator(colorScaleKey = "color") { // layout extender return function(dataModel, layoutScale: LayoutScale){ let d, type, value, minValue, maxValue, xDomain = dataModel.dataArray.map(dataModel.keyMap), yDomain, dNext = (dataModel.getNext) ? dataModel.getNext() : undefined, hasNext = (dNext !== undefined), dPrevious = (dataModel.getPrevious) ? dataModel.getPrevious() : undefined, hasPrevious = (dPrevious !== undefined), dVariance$ = (dataModel.getVariance$) ? dataModel.getVariance$() : undefined, hasVariance$ = (dVariance$ !== undefined); if(!hasNext || !hasPrevious || !hasVariance$){ for (d of dataModel.dataArray) { type = dataModel.typeMap(d); if(!hasNext && "next" === type) { dNext = d; } if(!hasPrevious && "previous" === type) { dPrevious = d; } if(!hasVariance$ && "variance_$" === type) { dVariance$ = d; } } } minValue = dPrevious.value; maxValue = dPrevious.value; value = dPrevious.value; for (d of dataModel.dataArray) { type = dataModel.typeMap(d); if("net" === type){ value = value + d.value; if(value < minValue){ minValue = value; } else if(value > maxValue){ maxValue = value; } } } minValue = (dNext.value < minValue) ? dNext.value : minValue; maxValue = (dNext.value > maxValue) ? dNext.value : maxValue; minValue = (dVariance$.value < minValue) ? dVariance$.value : minValue; maxValue = (dVariance$.value > maxValue) ? dVariance$.value : maxValue; if(minValue < 0 && maxValue < 0){ maxValue = 0; } else if(minValue > 0 && maxValue > 0){ minValue = 0; } yDomain = [minValue, maxValue]; layoutScale.extendDomainX(xDomain).extendDomainY(yDomain); //utility function to layout datum function layoutDatum(d, baseValue){ let key = dataModel.keyMap(d), value = baseValue + dataModel.valueMap(d), isPositive = (value > baseValue), vTop = (isPositive) ? value : baseValue, vBottom = (isPositive) ? baseValue : value, color, dLayout: any = {}; dLayout.key = key; dLayout.x = layoutScale.xScale(key); dLayout.y = layoutScale.yScale(vTop); dLayout.y0 = layoutScale.yScale(vBottom); dLayout.width = layoutScale.xScale.bandwidth(); dLayout.height = Math.abs(dLayout.y0 - dLayout.y); color = layoutScale.mapValue(colorScaleKey, dataModel, d); dLayout.color = color; dLayout.category = color.key; dLayout.categoryAttr = "category-" + convertValueToAttribute(color.key); if(dataModel.detailsMap){ dLayout.details = dataModel.detailsMap(d); } return dLayout; } // view layouter return function(){ let dLayout, key, color, bValue = 0, bValueLayout = layoutScale.yScale(bValue), viewModel = createViewModel(); dLayout = layoutDatum(dPrevious, 0); viewModel.dataArray.push(dLayout); bValue = dataModel.valueMap(dPrevious); for (d of dataModel.dataArray) { type = dataModel.typeMap(d); if("net" === type){ dLayout = layoutDatum(d, bValue); viewModel.dataArray.push(dLayout); bValue = bValue + dataModel.valueMap(d); } } dLayout = layoutDatum(dNext, 0); viewModel.dataArray.push(dLayout); if(dVariance$) { dLayout = layoutDatum(dVariance$, 0); viewModel.dataArray.push(dLayout); } return viewModel; } } }