const trendResult= [ { date: "2020-03-17 23:59:59", value: 10, dataTip:"55% decrease from 27th March" }, { date: "2020-03-18 23:59:59", value: 15, // dataTip:"55% decrease from 27th March" }, { date: "2020-03-19 23:59:59", value: 8, // dataTip:"22% increase from 18th March" }, { date: "2020-03-20 23:59:59", value: 22, // dataTip:"20% increase from 19th March" }, { date: "2020-03-21 23:59:59", value: 18, dataTip:"55% decrease from 27th March" }, { date: "2020-03-22 23:59:59", value: 9, // dataTip:"55% decrease from 27th March" }, { date: "2020-03-23 23:59:59", value: 20, dataTip:"55% decrease from 27th March" }, { date: "2020-03-24 23:59:59", value: 26, // dataTip:"55% decrease from 27th March" }, { date: "2020-03-25 23:59:59", value: 28, dataTip:"5% decrease from 24th March" }, { date: "2020-03-26 23:59:59", value: 5, // dataTip:"55% decrease from 27th March" }, { date: "2020-03-27 23:59:59", value: 32, dataTip:"55% decrease from 27th March" }, { date: "2020-03-28 23:59:59", value: 25, // dataTip:"55% decrease from 27th March" }, { date: "2020-03-29 23:59:59", value: 17, // dataTip:"55% decrease from 28th March" }, { date: "2020-03-30 23:59:59", value: 13, dataTip:"55% decrease from 29th March" }, { date: "2020-03-31 23:59:59", value: 29, dataTip:"20% decrease from 30th March" } ]; const calculateMinMaxValue = (minValue, maxValue, zeroBase, ticks) => { if (minValue == maxValue && minValue == 0) { maxValue = 10; } if (minValue == maxValue && minValue > 0) { minValue = minValue - minValue * 0.25; maxValue = maxValue + maxValue * 0.25; } if (minValue > 0 && zeroBase === true) { minValue = 0; } var num = (maxValue - minValue) / ((ticks || 10) - 1); var binSize = getSmootherBinSize(num); if (zeroBase == false && minValue < 0) { minValue = -1 * getNextDivisible(minValue * -1, binSize); } else if (zeroBase == false && minValue > 0) { minValue = getPrevDivisible(minValue, binSize); } maxValue = getNextDivisible(maxValue, binSize); if (ticks != null) { const missingTicks = ticks - ((maxValue - minValue) / binSize + 1); if (missingTicks > 0) { minValue -= Math.floor(missingTicks / 2) * binSize; maxValue += (Math.floor(missingTicks / 2) + missingTicks % 2) * binSize; } } return { minValue: minValue, maxValue: maxValue }; }; function getTicksCalculation(minDate, maxDate, typeOfTicks, startPoint, ticksFormat) { const distinctTicks = []; let startPointDate = d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startPoint)); let startPointIndex = 0; if (minDate != null && maxDate != null && typeOfTicks != null) { let startDate = new Date(minDate); let endDate = new Date(maxDate); switch (typeOfTicks) { case "month": { startDate = new Date(startDate.getFullYear(), startDate.getMonth(), 1, 23, 59, 59); endDate = new Date(endDate.getFullYear(), endDate.getMonth() + 1, 0); let startTime = startDate.getTime(); while (startTime <= endDate.getTime()) { const month = d3.timeFormat("%b")(new Date(startTime)); if (new Date(startTime).getMonth() == 0) { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)) }) : [`${month}`, `${new Date(startTime).getFullYear()}`]; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(startTime))}`, data: `${d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime))}`, displayName: displayName }); } else { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)) }) : `${month}`; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(startTime))}`, data: `${d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime))}`, displayName: displayName }); } startTime = new Date(startTime); startTime = new Date(startTime.setMonth(startTime.getMonth() + 1)).getTime(); } startPointDate = d3.timeFormat("%Y-%m-01 00:00:00")(new Date(startPoint)); break; } case "day": { let startTime = startDate.getTime(); let count=0; while (startTime <= endDate.getTime()) { const date = d3.timeFormat("%d")(new Date(startTime)); const month = d3.timeFormat("%b")(new Date(startTime)); const monthYear = d3.timeFormat("%b-%Y")(new Date(startTime)); if (new Date(startTime).getDate() == 1 && new Date(startTime).getMonth() == 0) { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)) }) : [`${date}`, `${monthYear}`]; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(startTime))}`, data: `${d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime))}`, displayName: displayName }); } else if (new Date(startTime).getDate() == 1 || count==0) { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)) }) : [`${date}`, `${month}`]; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(startTime))}`, data: `${d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime))}`, displayName: displayName }); } else { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(startTime)) }) : `${date}`; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(startTime))}`, data: `${d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime))}`, displayName: displayName }); } startTime = new Date(startTime); startTime = new Date(startTime.setDate(startTime.getDate() + 1)).getTime(); count++; } startPointDate = d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startPoint)); break; } case "week-sunday": { let startTime = startDate.getTime(); while (startTime <= endDate.getTime()) { const date = d3.timeFormat("%d")(new Date(startTime)); const month = d3.timeFormat("%b")(new Date(startTime)); startTime = new Date(startTime); const weekNumber = Math.abs(d3.timeFormat("%U")(new Date(startTime))) % 4; const dataValueForStartDate = d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime)); const nextDayCount = 7; const currentDayNumber = Math.abs(d3.timeFormat("%w")(startTime)); const weekEndDay = new Date(startTime.setDate(startTime.getDate() + (nextDayCount - 1 - currentDayNumber))).getTime(); const weekEndDate = d3.timeFormat("%d %b")(new Date(weekEndDay)); if (weekNumber == 0) { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(dataValueForStartDate)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(weekEndDay)) }) : [`${date}-${weekEndDate}`, `${startTime.getFullYear()}`]; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(dataValueForStartDate))}`, data: `${dataValueForStartDate}`, displayName: displayName }); } else { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(dataValueForStartDate)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(weekEndDay)) }) : `${date}-${weekEndDate}`; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(dataValueForStartDate))}`, data: `${dataValueForStartDate}`, displayName: displayName }); } startTime = new Date(startTime.setDate(startTime.getDate() + 1)).getTime(); } //CBT:for calculate start Point index startPointDate = new Date(startPointDate); const weekOfTheDay = startPointDate.getDay(); startPointDate = d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startPointDate.setDate(startPointDate.getDate() - weekOfTheDay))); break; } case "week-monday": { let startTime = startDate.getTime(); while (startTime <= endDate.getTime()) { const date = d3.timeFormat("%d")(new Date(startTime)); const month = d3.timeFormat("%b")(new Date(startTime)); startTime = new Date(startTime); const dataValueForStartDate = d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime)); const nextDayCount = 7; const currentDayNumber = Math.abs(d3.timeFormat("%u")(startTime)); const weekEndDay = new Date(startTime.setDate(startTime.getDate() + (nextDayCount - currentDayNumber))).getTime(); const WeekEndDateNumber = Math.abs(d3.timeFormat("%V")(new Date(weekEndDay))) % 4; const weekEndDate = d3.timeFormat("%d %b")(new Date(weekEndDay)); if (WeekEndDateNumber == 1) { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(dataValueForStartDate)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(weekEndDay)) }) : [`${date}-${weekEndDate}`, `${startTime.getFullYear()}`]; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(dataValueForStartDate))}`, data: `${dataValueForStartDate}`, displayName: displayName }); } else { const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(dataValueForStartDate)), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(new Date(weekEndDay)) }) : `${date}-${weekEndDate}`; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(dataValueForStartDate))}`, data: `${dataValueForStartDate}`, displayName: displayName }); } startTime = new Date(startTime.setDate(startTime.getDate() + 1)).getTime(); } //CBT:for calculate start Point index startPointDate = new Date(startPointDate); const weekOfTheDay = startPointDate.getDay(); const diffInDate = startPointDate.getDate() - weekOfTheDay + (weekOfTheDay == 0 ? -6 : 1); startPointDate = d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startPointDate.setDate(diffInDate))); break; } case "yearly-january": { let startYear = Math.abs(d3.timeFormat("%Y")(new Date(startDate))); const endYear = Math.abs(d3.timeFormat("%Y")(new Date(endDate))); while (startYear <= endYear) { const startTime = new Date(startYear, 0, 1, 0, 0, 0, 0); const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-01-01 23:59:59")(startTime), endPoint: d3.timeFormat("%Y-12-31 23:59:59")(startTime) }) : `${startYear}`; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(startTime))}`, data: `${d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime))}`, displayName: displayName }); startYear = startYear + 1; } startPointDate = d3.timeFormat("%Y-01-01 00:00:00")(new Date(startPoint)); break; } case "yearly-march": { let startYear = Math.abs(d3.timeFormat("%Y")(new Date(startDate))); if (startDate.getMonth() < 3) { startYear = startYear - 1; } let endYear = Math.abs(d3.timeFormat("%Y")(new Date(endDate))); if (endDate.getMonth() >= 3) { endYear = endYear + 1; } while (startYear < endYear) { const startTime = new Date(startYear, 3, 1, 0, 0, 0, 0); const endTime = new Date(startYear + 1, 2, 31, 23, 59, 59, 100); const displayName = ticksFormat != null && typeof ticksFormat == "function" ? ticksFormat({ startPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(startTime), endPoint: d3.timeFormat("%Y-%m-%d 23:59:59")(endTime) }) : [`${startYear}-`, `${startYear + 1}`]; distinctTicks.push({ title: `${d3.timeFormat("%d %b,%Y")(new Date(startTime))}`, data: `${d3.timeFormat("%Y-%m-%d 00:00:00")(new Date(startTime))}`, displayName: displayName }); startYear = startYear + 1; } //CBT:for calculate start Point index startPointDate = new Date(startPointDate); if (startPointDate.getMonth() < 3) { startPointDate = new Date(startPointDate.setFullYear(startPointDate.getFullYear() - 1)); startPointDate = d3.timeFormat("%Y-04-01 00:00:00")(new Date(startPointDate)); } else { startPointDate = d3.timeFormat("%Y-04-01 00:00:00")(new Date(startPointDate)); } break; } } } startPointIndex = distinctTicks .map(d => { return d.data; }) .indexOf(startPointDate); startPointIndex = startPointIndex == -1 ? 0 : startPointIndex; return { distinctTicks: distinctTicks, startPointIndex: startPointIndex }; } // function getPrepareChartData(chartData, category, measureFieldName) { // const preparedData = {}; // const allPercentageValues = []; // category.map((categoryPoint, baseIndex) => { // preparedData[categoryPoint] = {}; // Object.keys(chartData).forEach(lineDimension => { // preparedData[categoryPoint][lineDimension] = []; // const basePoint = chartData[lineDimension][baseIndex][measureFieldName]; // chartData[lineDimension].forEach(data => { // const value = basePoint == 0 || basePoint == null || data[measureFieldName] == null ? 0 : +parseFloat((data[measureFieldName] - basePoint) / basePoint * 100).toFixed(2); // preparedData[categoryPoint][lineDimension].push(value); // allPercentageValues.push(value); // }); // }); // }); // return { resultData: preparedData, minMax: d3.extent(allPercentageValues) }; // } const getNextDivisible = (maxNumber, binSize) => { if (maxNumber % binSize === 0) return maxNumber; return maxNumber + binSize - maxNumber % binSize; }; const getPrevDivisible = (minNumber, binSize) => { return minNumber - minNumber % binSize; }; const getSmootherBinSize = num => { if (num > 1) { var pow = 0; while (num / Math.pow(10, pow) > 9) pow += 1; return getNextDivisible(num, Math.pow(10, pow)); } else { var pow = 0; while (num / Math.pow(10, pow) <= 0.09) { pow -= 1; } return Math.round(getNextDivisible(num, Math.pow(10, pow)) * Math.pow(10, -pow)) / Math.pow(10, -pow); } }; const minMaxValueData=d3.extent(trendResult.map(d=>d.value)); const legendBucketSize=5; const resultOfMinMax= calculateMinMaxValue(minMaxValueData[0], minMaxValueData[1], false, legendBucketSize); const minValueData=resultOfMinMax.minValue; const maxValueData =resultOfMinMax.maxValue; let binSizeData = ( maxValueData - minValueData) / (legendBucketSize - 1); binSizeData=Math.abs(binSizeData); const legendBuckets = []; let currentValueData = minValueData; while(currentValueData <= maxValueData) { legendBuckets.push(Math.ceil(currentValueData)); currentValueData = currentValueData + binSizeData; } var colorScale = d3.scaleThreshold() .domain(legendBuckets) .range(["#FFE19B","#FFC85B","#F8623C","#D51F1F","#A70202"]); //CBT:Legend Start $("#charts").before( "
" ); const keys=[]; colorScale.domain().forEach((d,index)=>{ keys.push({ color: colorScale(d), label: (index==colorScale.domain().length-1) ? (">="+d+ " (Current Sales Value in Lacs)"):(">="+d) }) }) keys.forEach(function(d) { var cloloCode = d.color; $("#Legend_chart").append( "\  \ " + d.label + " \ " ); }); //CBT:Legend End const preparedChartData=[]; let pastValue=0; trendResult.forEach(data=>{ const dataObj={...data}; dataObj.pastValue=pastValue; dataObj.color=colorScale(data.value); pastValue=pastValue+data.value; preparedChartData.push(dataObj); }); const getDataValue = data => { if (data != null && typeof data == "object") { return data.data; } else { return data; } }; const getTranslation=(transform)=>{ // Create a dummy g for calculation purposes only. This will never // be appended to the DOM and will be discarded once this function // returns. var g = document.createElementNS("http://www.w3.org/2000/svg", "g"); // Set the transform attribute to the provided string value. g.setAttributeNS(null, "transform", transform); // consolidate the SVGTransformList containing all transformations // to a single SVGTransform of type SVG_TRANSFORM_MATRIX and get // its SVGMatrix. var matrix = g.transform.baseVal.consolidate().matrix; // As per definition values e and f are the ones for the translation. return [matrix.e, matrix.f]; } function CustomXAxis(xScale,width,rangeValuesTicksData,height,preparedChartData){ const axesContainer=".range-slider-axis"; const dataValues=rangeValuesTicksData; d3.select(axesContainer).html(""); let fontHeight; let maxYPositionForRectBox=0; dataValues.forEach((data, index) => { let values = data; let titleValue=data; if (data != null && typeof data == "object") { if (data.displayName) { values = data.displayName; } else if (data.formatter != null && typeof data.formatter == "function") { values = data.formatter(data.data); } else { values = data.data; } titleValue=data.data; if(data.title!=null){ titleValue=data.title; } } const ticksG = d3.select(axesContainer) .append("g") .attr("class", "ticks") .attr("transform", `translate(${xScale(getDataValue(data))},0)`); let wrappedTexts = []; if (Array.isArray(values)==true) { const textData = values; const textG = ticksG.append("text").style("text-anchor", "middle"); wrappedTexts = textData.map(textD => { const tspan= textG .append("tspan") .classed("ticks-text", true) .style("font-size", "var(--small-text-size)") .attr("x", xScale.bandwidth() / 2) .text(textD); tspan.append("svg:title") .text(titleValue); return tspan; }); fontHeight = wrappedTexts[0].node().getBBox().height; } else { const text=ticksG .append("text") .classed("ticks-text", true) .style("text-anchor", "middle") .style("font-size", "var(--small-text-size)") .attr("x", xScale.bandwidth() / 2) .text(values); text.append("svg:title") .text(titleValue); fontHeight = d3 .select(axesContainer) .select(".ticks text.ticks-text") .node() .getBBox().height; text.attr("y",fontHeight); if(fontHeight>maxYPositionForRectBox) maxYPositionForRectBox=fontHeight; } if (wrappedTexts.length > 0) { let yPosition = fontHeight; wrappedTexts.forEach(textPoint => { textPoint.attr("y", yPosition); yPosition = yPosition + fontHeight; }); if((yPosition-fontHeight)>maxYPositionForRectBox) maxYPositionForRectBox=yPosition-fontHeight; } ticksG.append("rect") .attr("class","rectangle-box") .attr("x",1.5) .attr("width",xScale.bandwidth()-1.5) .attr("height",20) .style("fill",preparedChartData[index].color); //CBT:tick line start ticksG .append("line") .attr("class", "tick-line") .attr("x1", 0) .attr("y1", 0) .attr("x2", 0) .attr("y2", -(height)); if (index == dataValues.length - 1) { ticksG .append("line") .attr("class", "tick-line") .attr("x1", xScale.bandwidth() - 1) .attr("y1", 0) .attr("x2", xScale.bandwidth() - 1) .attr("y2", -height); } //CBT:tick line end }); //CBT: pull rectangle-box bellow to text of x -axis ticks d3.selectAll(".rectangle-box").attr("y",(maxYPositionForRectBox+5)); //CBT:put axis down as font size //CBT:add ticks line d3.select(axesContainer) .append("line") .attr("class", "tick-line") .attr("x1", xScale(getDataValue(dataValues[0]))) .attr("y1", 0) .attr("x2", xScale(getDataValue(dataValues[dataValues.length - 1])) + xScale.bandwidth()) .attr("y2", 0); //CBT:Hide Overlapping Ticks text var selectedTextWidth = ''; let previousElement=null; d3.select(axesContainer).selectAll(".ticks").each(function(text, i) { var that = this; let textWidth=d3.select(that).select(".ticks-text").node().getBBox().width; d3.select(that).select(".ticks-text").style("display","block"); var position =getTranslation(that.getAttribute("transform")); if (i == 0 || d3.select(that).select("text tspan").empty()==false) { selectedTextWidth = position[0] + textWidth; if(previousElement!=null && d3.select(previousElement).select("text tspan").empty()==true) { //CBT:hide previous ticks text if it doesn't contain tspan and it's text overlapped current text const positionPre =getTranslation(previousElement.getAttribute("transform")); const textWidthPre=d3.select(previousElement).select(".ticks-text").node().getBBox().width; if(positionPre[0]+textWidthPre+5>position[0]){ d3.select(previousElement).select(".ticks-text").style("display","none") } }; previousElement=that; } else { var currentTextStart = position[0]; if (currentTextStart <= (selectedTextWidth + 10) || currentTextStart > width) { d3.select(that).select(".ticks-text").style("display","none"); } else { selectedTextWidth = position[0] + textWidth; previousElement=that; } } }); } function callShowTooltip(topPosition,leftPosition,childrenData,mainDivRef){ d3.select(mainDivRef).select(".custom-tooltip").remove(); const tooltipMain=d3.select(mainDivRef).append("div") .attr("class","custom-tooltip"); tooltipMain.style("left","0px"); tooltipMain.append("div").html(childrenData); tooltipMain.append("div") .attr("class","rectangle-container") .append("div") .attr("class","rectangle-div"); tooltipMain.style("top",(topPosition-(tooltipMain.node().getBoundingClientRect().height+20))+"px") .style("left",(leftPosition-(tooltipMain.node().getBoundingClientRect().width/2))+"px"); } function callHideTooltip(mainDivRef){ d3.select(mainDivRef).select(".custom-tooltip").remove(); } function setDrawDataTips(dataTips,xScale,yScale,distinctTicks,svgRef,margin,preparedChartData,mainDivRef){ const dataTipsReverse=[...dataTips]; const preparedChartDataReverse=[...preparedChartData].reverse(); const ticksCalculationDataPointReverse=[...distinctTicks].reverse(); d3.select(svgRef).select(".y-axis").select(".data-tip-g").remove(); const dataTipG=d3.select(svgRef).select(".y-axis").append("g") .attr("class","data-tip-g"); dataTipG.html(""); const minimumLineSize=10; const dataTipRectHeight=40; const dataTipRectWidth=150; const dataTipDateRectWidth=45; const dataTipsDivCoordinates=[]; dataTipsReverse.forEach((dataTip)=>{ if(dataTip.isRendered==false || dataTip.isRendered==null){ preparedChartDataReverse.forEach((chartData,index)=>{ const ticksCalculationDataPoint=ticksCalculationDataPointReverse[index]; if(yScale(chartData.value+chartData.pastValue)+margin.top>(dataTipRectHeight+minimumLineSize) && (dataTip.isRendered==null || dataTip.isRendered==false) && index>=dataTip.index){ const divTopPosition= 40; const divLeftPosition= d3 .select(mainDivRef) .node() .getBoundingClientRect().left+margin.left; let top=(divTopPosition); let left=divLeftPosition+ xScale(ticksCalculationDataPoint.data)+(xScale.bandwidth()/2)-(dataTipRectWidth-(dataTipDateRectWidth/2)); let isOverLapped=false; let currentCoordinates; let differenceOfLeftAndZero=0; if(left<0){ differenceOfLeftAndZero=0-left; left=0; } currentCoordinates={ x1:left, y1:top, x2:left+dataTipRectWidth, y2:top+dataTipRectHeight } dataTipsDivCoordinates.forEach(point=>{ let isYAxisOverlapped=false; let isXAxisOverlapped=false; if((currentCoordinates.x1>=point.x1 && currentCoordinates.x1<=point.x2) || (currentCoordinates.x2>=point.x1 && currentCoordinates.x2<=point.x2)){ isXAxisOverlapped=true; } if((currentCoordinates.y1>=point.y1 && currentCoordinates.y1<=point.y2) || (currentCoordinates.y2>=point.y1 && currentCoordinates.y2<=point.y2)){ isYAxisOverlapped=true; } if(isYAxisOverlapped==true && isXAxisOverlapped==true){ isOverLapped=true; } }); //CBT:check bellow position from current tip if(isOverLapped==true){ top=top+dataTipRectHeight+10; currentCoordinates={ x1:left, y1:top, x2:left+dataTipRectWidth, y2:top+dataTipRectHeight } if(Math.round(yScale(chartData.value+chartData.pastValue)+(margin.top -margin.bottom))>=Math.round(top)){ isOverLapped=false; } dataTipsDivCoordinates.forEach(point=>{ let isYAxisOverlapped=false; let isXAxisOverlapped=false; if((currentCoordinates.x1>=point.x1 && currentCoordinates.x1<=point.x2) || (currentCoordinates.x2>=point.x1 && currentCoordinates.x2<=point.x2)){ isXAxisOverlapped=true; } if((currentCoordinates.y1>=point.y1 && currentCoordinates.y1<=point.y2) || (currentCoordinates.y2>=point.y1 && currentCoordinates.y2<=point.y2)){ isYAxisOverlapped=true; } if(isYAxisOverlapped==true && isXAxisOverlapped==true){ isOverLapped=true; } }); } if(isOverLapped==true){ top=top+dataTipRectHeight+10; currentCoordinates={ x1:left, y1:top, x2:left+dataTipRectWidth, y2:top+dataTipRectHeight } if(Math.round(yScale(chartData.value+chartData.pastValue)+(margin.top -margin.bottom))>=Math.round(top)){ isOverLapped=false; } dataTipsDivCoordinates.forEach(point=>{ let isYAxisOverlapped=false; let isXAxisOverlapped=false; if((currentCoordinates.x1>=point.x1 && currentCoordinates.x1<=point.x2) || (currentCoordinates.x2>=point.x1 && currentCoordinates.x2<=point.x2)){ isXAxisOverlapped=true; } if((currentCoordinates.y1>=point.y1 && currentCoordinates.y1<=point.y2) || (currentCoordinates.y2>=point.y1 && currentCoordinates.y2<=point.y2)){ isYAxisOverlapped=true; } if(isYAxisOverlapped==true && isXAxisOverlapped==true){ isOverLapped=true; } }); } if(differenceOfLeftAndZero>0 && isOverLapped==true){ ///CBT:this is for first bar tip top=yScale(chartData.value+chartData.pastValue)-(dataTipRectHeight+minimumLineSize)+margin.top; currentCoordinates={ x1:left, y1:top, x2:left+dataTipRectWidth, y2:top+dataTipRectHeight } isOverLapped=false; } if(isOverLapped==false){ const mainDivDataTip=d3 .select(mainDivRef) .append("div") .style("top",top+"px") .style("left",left+"px") .style("width",dataTipRectWidth+"px") .style("height",dataTipRectHeight+"px") .attr("class","data-tip-div"); mainDivDataTip.append("div") .attr("class","text-div") .html(dataTip.dataTip); const dateDiv=mainDivDataTip.append("div") .attr("class","date-div"); dateDiv.append("div") .attr("class","date-top-div") .html(d3.timeFormat("%B")(new Date(dataTip.date))); dateDiv.append("div") .attr("class","date-bottom-div") .html(d3.timeFormat("%d")(new Date(dataTip.date))); //CBT:draw Horizontal line const lineStart=top; const x1=xScale(ticksCalculationDataPoint.data)+(xScale.bandwidth()/2); let x2=x1; if(dataTip.index!=index){ const ticksCalculationDataPointActual=ticksCalculationDataPointReverse[dataTip.index]; x2=xScale(ticksCalculationDataPointActual.data)+(xScale.bandwidth()/2); } dataTipG .append("line") .attr("class","data-tip-line") .attr("x1",x1+differenceOfLeftAndZero) .attr("x2",x2) .attr("y1",lineStart+dataTipRectHeight-margin.top) .attr("y2",yScale(dataTip.value+dataTip.pastValue)); dataTip.isRendered=true; dataTipsDivCoordinates.push({ x1:left, y1:top, x2:left+dataTipRectWidth, y2:top+dataTipRectHeight }) } }else{ } }) } }); }