(function ($) { var DonutChart = function (element, options) { this.init(element, options); }; var settings = { "type": "pie", "theme": "light", "addClassNames": true, "titleField": "Label", "valueField": "Cost", "bringToFront": true, "labelsEnabled": false, "marginBottom": 0, "marginTop": 30, "pullOutRadius": 0, "balloon": { "fixedPosition": false }, "fontFamily": "Open Sans", "numberFormatter": { precision: 0, decimalSeparator: ".", thousandsSeparator: "," } }; var outerDonutSettings = { "radius": 120, "innerRadius": 100, "allLabels": [{ "id": "label-title", "size": 14, "text": "Projects by Goal and Type", "color": "#555", "align": "center", "bold": true, "x": 0, "y": 14 }] }; var innerDonutSettings = { "alpha": 0.8, "radius": 100, "innerRadius": 80 }; DonutChart.prototype = { init: function (element, options) { AmCharts.addInitHandler(initChartHandler, ["pie"]); var innerChartDiv = $(element).append("
"), outerChartDiv = $(element).append("
"), containerId = $(element).attr("id"); var btnSize = 18; this.donutClearFilterBtn = $("") .appendTo($(element)) .css({ height: btnSize, width: btnSize, left: "49%",//$(element).width() / 2 - btnSize / 2, top: $(element).height() / 2 - btnSize / 2 + 40, "z-index": 4, position: "absolute", border: "none", display: "none", "background-image": "url('" + options.clearFilterButtonBackground + "')" }) .click(function () { $("#" + containerId).data('donutChart').totalClickHandler(); $("#donutClearFilterBtn").hide(); }); outerDonutSettings = $.extend(true, outerDonutSettings, settings); innerDonutSettings = $.extend(true, innerDonutSettings, settings); this.options = options; this.containerId = containerId; this.costMode = options.costMode || true; this.mode = options.mode || "goalType"; this.related = options.related || false; this.projectsFilterArray = this.options.projectsFilterArray || []; this.goalsFilterArray = this.options.goalsFilterArray || []; this.innerDonut = AmCharts.makeChart("innerChartDiv", innerDonutSettings); this.outerDonut = AmCharts.makeChart("outerChartDiv", outerDonutSettings); this.outerDonut.addListener("drawn", this.onDrawn); this.innerDonut.balloonFunction = function (gi) { return getBalloonText(gi, containerId); }; this.outerDonut.balloonFunction = function (gi) { return getBalloonText(gi, containerId); }; // Set data fields for sectors custom display color this.innerDonut.colorField = "PresetColor"; this.outerDonut.colorField = "PresetColor"; this.colorCache = {}; this.lastUsedPaletteColor = -1; this.outerDonut.addListener("clickSlice", function (event) { var dataContext = event.dataItem.dataContext; var donut = $("#chartDonut1").data("donutChart"); donut.itemClick(dataContext, true); }); this.innerDonut.addListener("clickSlice", function (event) { var dataContext = event.dataItem.dataContext; var donut = $("#chartDonut1").data("donutChart"); donut.itemClick(dataContext, false); }); }, onDrawn: function (event) { }, getLegendItemHtml: function (dataItem, color, index) { var unit = this.costMode ? "$" : ""; var value = this.costMode ? dataItem.Cost.formatNumber(0) : dataItem.Duration.formatNumber(0); value = unit + value; var label = formatLegendLabel(dataItem.Label); var groupType = dataItem.GroupType; var donutSelector = "$(\"#" + this.containerId + "\").data(\"donutChart\")"; var id = dataItem.TypeId.length == 1 ? "id='legend-item-" + dataItem.TypeId[0] + "'" : ""; var result = "" + "
" + "" + label + "
" + value + "
"; return result; }, onLegendItemMouseEnter: function (event, groupType, index) { var chart = getChart(groupType, this); chart.div.style.zIndex = 2; chart.rollOverSlice(index); }, onLegendItemMouseLeave: function (event, groupType, index) { var chart = getChart(groupType, this); chart.div.style.zIndex = 1; chart.rollOutSlice(index); }, onLegendItemClick: function (index, groupType) { var chart = getChart(groupType, this); //var isOuter = true; //if (this.mode === "goalType" && groupType == "ProjectType") { // isOuter = false; //} else if (this.mode === "typeGoal" && groupType == "Goal") { // isOuter = false; //} var dataItem = chart.dataProvider[index]; this.options.onLegendItemClick(dataItem, index, groupType); //this.itemClick(dataItem, isOuter); }, loadData: function (filter) { var that = this; if (this.options.onLoadBegin) { this.options.onLoadBegin(); } $.post(this.options.dataSourceUrl, filter) .done(function (response) { var chartData = response, total = that.costMode ? chartData.TotalCost : chartData.TotalDuration; that.chartData = chartData; that.costData = chartData.CostData; that.durationData = chartData.DurationData; that.totalCost = chartData.TotalCost; that.totalDuration = chartData.TotalDuration; that.mode = that.options.mode; that.costMode = that.options.costMode; // Set colors for donut sectors manually that.setCustomColors(that.costData); that.setCustomColors(that.durationData); that.updateData(); that.updateTotal(); that.createLegend(); if (that.options.onLoadEnd) { that.options.onLoadEnd(); } }); }, getData: function () { var data = this.costMode ? this.costData : this.durationData return data; }, createLegend: function () { var chart = this.outerDonut, data = this.getData(), legendDiv = $("#" + this.options.legendDivId), allData = []; if (this.mode === "goalType" || this.mode === "typeGoal") { allData = this.outerDonut.dataProvider.concat(this.innerDonut.dataProvider); } else { allData = this.outerDonut.dataProvider; } var goals, projectTypes; if (this.mode === "goalType" || this.mode === "goal") { goals = this.outerDonut.dataProvider; projectTypes = this.innerDonut.dataProvider; } else if (this.mode == "typeGoal" || this.mode === "type") { projectTypes = this.outerDonut.dataProvider; goals = this.innerDonut.dataProvider; } legendDiv.empty(); chart.customLegend = legendDiv; var legendHtml = "", colCount = 2; for (var i = 0; i < allData.length; i++) { var row = Math.floor(i / colCount), col = i % colCount, dataItem = allData[i]; if (col == 0) { legendHtml += ""; } var index = dataItem.GroupType == "Goal" ? goals.indexOf(dataItem) : projectTypes.indexOf(dataItem); var color = dataItem.PresetColor; if (this.related && (dataItem.Alpha !== undefined)) { color = this.getSliceColor(dataItem); } else { if (this.innerDonut.dataProvider.indexOf(dataItem) >= 0) { color = this.getColorWithOpacity(dataItem.PresetColor, innerDonutSettings.alpha); } } legendHtml += this.getLegendItemHtml(dataItem, color, index); if (col == colCount - 1) { legendHtml += ""; } } legendHtml += "
"; legendDiv.append(legendHtml); var allFilter = this.projectsFilterArray.concat(this.goalsFilterArray); $.each(allFilter, function (index, id) { $("#legend-item-" + id).css("text-decoration", "underline"); $("#legend-item-" + id).css("cursor", "pointer"); }); }, totalClickHandler: function () { if (this.options.onTotalClick && typeof this.options.onTotalClick === "function") { this.options.onTotalClick(); } }, updateTotal: function () { var total = this.costMode ? this.totalCost : this.totalDuration; //var valueField = this.costMode ? "Cost" : "Duration"; //$.each(this.outerDonut.dataProvider, function (index, dataItem) { // total += dataItem[valueField]; //}); if (this.options.formatTotal && typeof this.options.formatTotal === "function") { total = this.options.formatTotal(total); } if (this.innerDonut.allLabels.length == 0) { var fn = "javascript:$('#" + this.containerId + "').data('donutChart').totalClickHandler();"; this.innerDonut.addLabel(null, "46%", "Total", "center", 14, "#000000", 0, 1, false, fn); this.innerDonut.addLabel(null, "53%", total, "center", 12, "#000000", 0, 1, true, fn); this.outerDonut.addLabel(null, "46%", "Total", "center", 14, "#000000", 0, 1, false, fn); this.outerDonut.addLabel(null, "53%", total, "center", 12, "#000000", 0, 1, true, fn); } else { this.innerDonut.allLabels[1].text = total; this.outerDonut.allLabels[2].text = total; } this.innerDonut.validateNow(); this.outerDonut.validateNow(); }, setDonutData: function (donut, data) { var valueField = this.costMode ? "Cost" : "Duration"; if (data.length > 0 && data[0].Value != undefined && data[0].Value != null) { valueField = "Value"; } this.innerDonut.alphaField = this.related ? "Alpha" : ""; donut.valueField = valueField; donut.dataProvider = data; donut.validateData(); }, updateData: function () { var data = this.getData(), outerData = [], innerData = []; if (this.mode === "goalType") { outerData = data.Goals; innerData = this.related ? this.getRelatedData(outerData) : data.ProjectTypes; } else if (this.mode === "typeGoal") { outerData = data.ProjectTypes; innerData = this.related ? this.getRelatedData(data.ProjectTypes) : data.Goals; } else if (this.mode === "goal") { outerData = data.Goals; innerData = []; } else if (this.mode === "type") { outerData = data.ProjectTypes; innerData = []; } this.setDonutData(this.outerDonut, outerData); this.setDonutData(this.innerDonut, innerData); }, getRelatedData: function (outerData) { var result = []; var costMode = this.costMode; $.each(outerData, function (i, parent) { var childItems = parent.ChildItems; var alpha = 0.8; var colorAlphaStep = (alpha - 0.2) / childItems.length; var baseColor = parent.PresetColor; childItems = childItems.sort(function (a, b) { if (b.Label == "Other") { return -2; } if (a.Label == "Other") { return 2; } var field = costMode ? "Cost" : "Duration"; return b[field] == a[field] ? 0 : ((b[field] > a[field]) ? 1 : -1); }); var otherDataItem = null; $.each(childItems, function (j, child) { child.Alpha = alpha; child.PresetColor = baseColor; alpha -= colorAlphaStep; if (child.PieDatas && (child.PieDatas.length > 0)) { // Among child items of current outer sector we found Other element otherDataItem = child; } }); if (otherDataItem != null) { // Set colors to items, packed into Other element in inner donut var otherInnerAlpha = 0.8; var otherInnerAlphaStep = (otherInnerAlpha - 0.2) / otherDataItem.PieDatas.length; $.each(otherDataItem.PieDatas, function (j, otherItemChild) { otherItemChild.Alpha = otherInnerAlpha; otherItemChild.PresetColor = baseColor; otherInnerAlpha -= otherInnerAlphaStep; }); } result = $.merge(result, childItems || []); }); return result; }, setCustomColors: function (data) { if (!data || !this.options || !this.options.colors) return; if (this.options.colors.length < 1) return; if (this.lastUsedPaletteColor === undefined) this.lastUsedPaletteColor = -1; var otherDataItem = null; if (data.Goals && (data.Goals.length > 0)) { // Set colors for general Goals sectors for (var index = 0; index < data.Goals.length; index++) { var itemId = data.Goals[index].GoalId; this.setItemColor(itemId, data.Goals[index]); if (data.Goals[index].PieDatas && (data.Goals[index].PieDatas.length > 0)) { otherDataItem = data.Goals[index]; } } } if (data.OtherGoals && (data.OtherGoals.length > 0)) { // Set colors for Goals sectors, packed into Other sector for (var index = 0; index < data.OtherGoals.length; index++) { var itemId = data.OtherGoals[index].GoalId; this.setItemColor(itemId, data.OtherGoals[index]); } } if (otherDataItem != null) { // Set colors for Goals sectors, packed into Other sector (alternative data struct) for (var index = 0; index < otherDataItem.PieDatas.length; index++) { var itemId = otherDataItem.PieDatas[index].GoalId; this.setItemColor(itemId, otherDataItem.PieDatas[index]); } otherDataItem = null; } if (data.ProjectTypes && (data.ProjectTypes.length > 0)) { // Set colors for general ProjectTypes sectors for (var index = 0; index < data.ProjectTypes.length; index++) { var itemId = data.ProjectTypes[index].ProjectTypeId; this.setItemColor(itemId, data.ProjectTypes[index]); if (data.ProjectTypes[index].PieDatas && (data.ProjectTypes[index].PieDatas.length > 0)) { otherDataItem = data.ProjectTypes[index]; } } } if (data.OtherProjectTypes && (data.OtherProjectTypes.length > 0)) { // Set colors for ProjectTypes sectors, packed into Other sector for (var index = 0; index < data.OtherProjectTypes.length; index++) { var itemId = data.OtherProjectTypes[index].ProjectTypeId; this.setItemColor(itemId, data.OtherProjectTypes[index]); } } if (otherDataItem != null) { // Set colors for ProjectTypes sectors, packed into Other sector (alternative data struct) for (var index = 0; index < otherDataItem.PieDatas.length; index++) { var itemId = otherDataItem.PieDatas[index].ProjectTypeId; this.setItemColor(itemId, otherDataItem.PieDatas[index]); } } }, // Sets color for individual sector. Uses cached data (if found) or picks the next color from palette setItemColor: function (itemId, item) { if (Object.keys(this.colorCache).indexOf(itemId) >= 0) item.PresetColor = this.colorCache[itemId]; else { this.lastUsedPaletteColor++; var itemColor = getColor(this.options.colors, this.lastUsedPaletteColor); item.PresetColor = itemColor; this.colorCache[itemId] = itemColor; } }, setMode: function (mode) { this.mode = mode; this.updateData(); this.updateTotal(); this.createLegend(); }, setCostMode: function (costMode) { this.costMode = costMode; this.updateData(); this.updateTotal(); this.createLegend(); }, setRelation: function (related) { this.related = related; this.updateData(); this.createLegend(); }, itemClick_: function (dataContext, isOuter) { var isOtherClicked = dataContext.PieDatas != null && dataContext.PieDatas.length > 0; this.singleSliceData = [dataContext]; if (isOtherClicked) { this.showOtherMode = true; } else { this.singleSliceMode = true; } if (isOuter) { this.singleOuterSliceMode = true; this.singleInnerSliceMode = false; } else { this.singleOuterSliceMode = false; this.singleInnerSliceMode = true; } this.updateData(); this.createLegend(); }, itemClick: function (dataContext, isOuter) { if (dataContext.Label == "No Goal") { return null; } var array = [dataContext]; var donut = $("#chartDonut1").data("donutChart"); if (dataContext.PieDatas != null && dataContext.PieDatas.length > 0) { var data = this.costMode ? this.costData : this.durationData; if (this.mode === "goalType") { if (isOuter) { clickOther(data.Goals, this.outerDonut, dataContext.PieDatas); if (this.related) { var childrenData = this.getRelatedData(dataContext.PieDatas); this.setDonutData(this.innerDonut, childrenData); } } else { disableDonutReload = true; clickOther(data.ProjectTypes, this.innerDonut, dataContext.PieDatas); } } else if (this.mode === "typeGoal") { if (isOuter) { clickOther(data.ProjectTypes, this.outerDonut, dataContext.PieDatas); if (this.related) { var childrenData = this.getRelatedData(dataContext.PieDatas); this.setDonutData(this.innerDonut, childrenData); } } else { disableDonutReload = true; clickOther(data.Goals, this.innerDonut, dataContext.PieDatas); } } else if (this.mode === "goal") { clickOther(data.Goals, this.outerDonut, dataContext.PieDatas); } else if (this.mode === "type") { clickOther(data.ProjectTypes, this.outerDonut, dataContext.PieDatas); } } else { var typeId = dataContext.TypeId; var itemColor = null; if (typeId.length > 0) { if (isOuter) { for (var i = 0; i < donut.outerDonut.chartData.length; i++) { if (typeId == donut.outerDonut.chartData[i].dataContext.TypeId[0]) { itemColor = donut.outerDonut.chartData[i].dataContext.PresetColor; break; } } if (itemColor == null) { this.lastUsedPaletteColor++; itemColor = getColor(this.options.colors, this.lastUsedPaletteColor); } array[0].PresetColor = itemColor; array[0].Alpha = 1; this.setDonutData(this.outerDonut, array); if (this.related) { var childrenData = this.getRelatedData(array, itemColor); this.setDonutData(this.innerDonut, childrenData); } } else { if (!this.related) { for (var i = 0; i < donut.innerDonut.chartData.length; i++) { if (typeId == donut.innerDonut.chartData[i].dataContext.TypeId[0]) { //colorIndex = colorIndex + i; itemColor = donut.innerDonut.chartData[i].dataContext.PresetColor; break; } } if (itemColor == null) { this.lastUsedPaletteColor++; itemColor = getColor(this.options.colors, this.lastUsedPaletteColor); } array[0].PresetColor = itemColor; array[0].Alpha = 1; this.setDonutData(this.innerDonut, array); } else { //TODO: inner slice clicked. filter data here if don't want to reload data from server } } var groupType = dataContext.GroupType; this.options.addFilter(typeId[0], groupType); } } this.createLegend(); this.updateTotal(); }, getSliceColor: function (dataItem) { var color = dataItem.PresetColor; var rgb = hexToRgb(dataItem.PresetColor); color = "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + "," + dataItem.Alpha + ")"; return color; }, getColorWithOpacity: function (color, opacity) { var rgb = hexToRgb(color); var result = "rgba(" +rgb.r + "," +rgb.g + "," + rgb.b + "," + opacity + ")"; return result; }, changeFromFilterPanel: function () { var curentData = this.getData(); var goals = getChartDataItems("Goal", this.goalsFilterArray, curentData); var projectType = getChartDataItems("ProjectType", this.projectsFilterArray, curentData); if (!this.related) { if (this.mode === "goalType") { if (goals.length > 0) { this.setDonutData(this.outerDonut, goals); } else { this.setDonutData(this.outerDonut, curentData.Goals); } if (projectType.length > 0) { this.setDonutData(this.innerDonut, projectType); } else { this.setDonutData(this.innerDonut, curentData.ProjectTypes); } } else if (this.mode === "typeGoal") { if (projectType.length > 0) { this.setDonutData(this.outerDonut, projectType); } else { this.setDonutData(this.outerDonut, curentData.ProjectTypes); } if (goals.length > 0) { this.setDonutData(this.innerDonut, goals); } else { this.setDonutData(this.innerDonut, curentData.Goals); } } else if (this.mode === "goal") { if (goals.length > 0) { this.setDonutData(this.outerDonut, goals); } else { this.setDonutData(this.outerDonut, curentData.Goals); } } else if (this.mode === "type") { if (projectType.length > 0) { this.setDonutData(this.outerDonut, projectType); } else { this.setDonutData(this.outerDonut, curentData.ProjectTypes); } } } else { if (this.mode === "goalType") { if (goals.length > 0) { var outerCollection = projectType.length > 0 ? getRelatedItemsOuther(goals, projectType) : curentData.Goals; this.setDonutData(this.outerDonut, outerCollection); } else { var outerCollection = goals.length > 0 ? getRelatedItemsOuther(projectType, curentData.Goals) : curentData.Goals; this.setDonutData(this.outerDonut, outerCollection); } var childItems = this.getRelatedData(outerCollection); if (projectType.length > 0) { var collection = getRelatedItemsInner(outerCollection, projectType, this); this.setDonutData(this.innerDonut, collection); } else { this.setDonutData(this.innerDonut, childItems); } } else if (this.mode === "typeGoal") { if (projectType.length > 0) { var outerCollection = goals.length > 0 ? getRelatedItemsOuther(projectType, goals) : curentData.ProjectTypes; this.setDonutData(this.outerDonut, outerCollection); } else { var outerCollection = goals.length > 0 ? getRelatedItemsOuther(curentData.ProjectTypes, goals) : curentData.ProjectTypes; this.setDonutData(this.outerDonut, outerCollection); } var childItems = this.getRelatedData(outerCollection); if (goals.length > 0) { var collection = getRelatedItemsInner(outerCollection, goals, this); this.setDonutData(this.innerDonut, collection); } else { this.setDonutData(this.innerDonut, childItems); } } else if (this.mode === "goal") { if (goals.length > 0) { this.setDonutData(this.outerDonut, goals); } else { this.setDonutData(this.outerDonut, curentData.Goals); } } else if (this.mode === "type") { if (projectType.length > 0) { this.setDonutData(this.outerDonut, projectType); } else { this.setDonutData(this.outerDonut, curentData.ProjectTypes); } } } this.createLegend(); } }; function getProjectTypesForGoal(allProjectTypes, goal) { var projectTypes = []; $.each(allProjectTypes, function (i, projectType) { if (goal.ChildItems) { projectTypes = goal.ChildItems.filter(function (item) { return item.TypeId[0] == projectType.TypeId[0]; }); } }); return projectTypes; }; function formatLegendLabel(label) { if (label.length > 15) { label = label.substring(0, 15) + "..."; } return label; } function getColor(palette, index) { return palette[index % (palette.length - 1)]; } function getBalloonText(graphDataItem, containerId) { //no more ways to get costMode var chart = $("#" + containerId).data('donutChart'); var costMode = chart.costMode; var unit = chart.costMode ? "$" : ""; with (graphDataItem) { var valueStr = unit + (chart.costMode ? dataContext.Cost.formatNumber() : dataContext.Duration.formatNumber()); var balloonText = dataContext.Label + "
" + valueStr + " (" + percents.formatNumber() + "%)"; return balloonText; } }; function getChart(groupType, item) { var chart; if (groupType == "Goal" && item.mode == "typeGoal") { chart = item.innerDonut; } else if (groupType == "ProjectType" && item.mode == "goalType") { chart = item.innerDonut; } else { chart = item.outerDonut; } return chart; }; function getChartDataItems(groupType, collection, data) { var dataCollection = []; if (groupType == "Goal") { for (var i = 0; i <= data.Goals.length - 1; i++) { if (collection.includes(data.Goals[i].TypeId[0]) && data.Goals[i].PieDatas == null) { dataCollection.push(data.Goals[i]); } } for (var i = 0; i <= data.OtherGoals.length - 1; i++) { if (collection.includes(data.OtherGoals[i].TypeId[0])) { dataCollection.push(data.OtherGoals[i]); } } } else if (groupType == "ProjectType") { for (var i = 0; i <= data.ProjectTypes.length - 1; i++) { if (collection.includes(data.ProjectTypes[i].TypeId[0]) && data.ProjectTypes[i].PieDatas == null) { dataCollection.push(data.ProjectTypes[i]); } } for (var i = 0; i <= data.OtherProjectTypes.length - 1; i++) { if (collection.includes(data.OtherProjectTypes[i].TypeId[0])) { dataCollection.push(data.OtherProjectTypes[i]); } } } return dataCollection; }; function getRelatedItemsOuther(mainCollection, relatedCollection) { var returnCollection = []; for (var i = 0; i < mainCollection.length; i++) { var isContains = false; for (var j = 0; j < mainCollection[i].ChildItems.length; j++) { for (var k = 0; k < relatedCollection.length; k++) { if (relatedCollection[k].TypeId[0] == mainCollection[i].ChildItems[j].TypeId[0]) { isContains = true; } } } if (isContains) { returnCollection.push(mainCollection[i]); } } return returnCollection; }; function getRelatedItemsInner(mainCollection, relatedCollection, thet) { var returnCollection = []; var values = []; for (var i = 0; i < mainCollection.length; i++) { var mainValue = thet.costMode ? mainCollection[i].Cost : mainCollection[i].Duration; var childCollection = []; for (var j = 0; j < mainCollection[i].ChildItems.length; j++) { for (var k = 0; k < relatedCollection.length; k++) { if (relatedCollection[k].TypeId[0] == mainCollection[i].ChildItems[j].TypeId[0]) { var str = JSON.stringify(mainCollection[i].ChildItems[j]); var obj = JSON.parse(str); childCollection.push(obj); } } } var childValueSumm = 0; for (var m = 0; m < childCollection.length; m++) { var curentVal = thet.costMode ? childCollection[m].Cost : childCollection[m].Duration; childValueSumm += curentVal; } var dif = mainValue / childValueSumm; for (var m = 0; m < childCollection.length; m++) { var childValue = thet.costMode ? childCollection[m].Cost : childCollection[m].Duration; values.push(childValue * dif); } returnCollection = returnCollection.concat(childCollection); } for (var l = 0; l < returnCollection.length; l++) { returnCollection[l].Value = values[l]; } return returnCollection; }; function clickOther(data, donut, otherDatas) { var donutData = otherDatas.slice(); //donutData.splice(donutData.length - 1, 1); //donutData = donutData.concat(otherDatas); var donutElement = $("#chartDonut1").data("donutChart"); donutElement.setDonutData(donut, donutData); }; function hexToRgb(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; }; //http://www.amcharts.com/tips/nested-donut-chart/ function initChartHandler(chart) { // init holder for nested charts if (AmCharts.nestedChartHolder === undefined) AmCharts.nestedChartHolder = {}; if (chart.bringToFront === true) { chart.addListener("init", function (event) { // chart inited var chart = event.chart; var div = chart.div; var parent = div.parentNode; // add to holder if (AmCharts.nestedChartHolder[parent] === undefined) AmCharts.nestedChartHolder[parent] = []; AmCharts.nestedChartHolder[parent].push(chart); chart.div.addEventListener('mousemove', function (event) { var x = Math.abs(chart.mouseX - (chart.realWidth / 2)); var y = Math.abs(chart.mouseY - (chart.realHeight / 2)); var r = Math.sqrt(x * x + y * y); //TODO: refactor if (r < 70) { $("#donutClearFilterBtn").show(); } }); chart.div.addEventListener('mouseleave', function (event) { //TODO: hide when mouse will out of circle with radius equals to inner radius of ther inner donut if (event.relatedTarget && event.relatedTarget.id != "donutClearFilterBtn") { $("#donutClearFilterBtn").hide(); } }); // add mouse move event chart.div.addEventListener('mousemove', function () { // calculate current radius var x = Math.abs(chart.mouseX -(chart.realWidth / 2)); var y = Math.abs(chart.mouseY -(chart.realHeight / 2)); var r = Math.sqrt(x * x +y * y); // check which chart smallest chart still matches this radius var smallChart; var smallRadius; for (var i = 0; i < AmCharts.nestedChartHolder[parent].length; i++) { var checkChart = AmCharts.nestedChartHolder[parent][i]; if ((checkChart.radiusReal < r) || (smallRadius < checkChart.radiusReal)) { checkChart.div.style.zIndex = 1; } else { if (smallChart !== undefined) smallChart.div.style.zIndex = 1; checkChart.div.style.zIndex = 2; smallChart = checkChart; smallRadius = checkChart.radiusReal; } } }, false); }); } } $.fn.donutChart = function (option, args) { return this.each(function () { var $this = $(this), data = $this.data('donutChart'), options = $.extend({}, $.fn.donutChart.defaults, $this.data(), typeof option === 'object' && option); if (!data) $this.data('donutChart', (data = new DonutChart(this, options))); if (typeof option === 'string') data[option].apply(data, [].concat(args)); }); }; $.fn.donutChart.defaults = { costMode: true }; $.fn.donutChart.Constructor = DonutChart; }(jQuery)); if (!Array.prototype.includes) { Array.prototype.includes = function (searchElement /*, fromIndex*/) { 'use strict'; var O = Object(this); var len = parseInt(O.length, 10) || 0; if (len === 0) { return false; } var n = parseInt(arguments[1], 10) || 0; var k; if (n >= 0) { k = n; } else { k = len + n; if (k < 0) { k = 0; } } var currentElement; while (k < len) { currentElement = O[k]; if (searchElement === currentElement || (searchElement !== searchElement && currentElement !== currentElement)) { // NaN !== NaN return true; } k++; } return false; }; }