Charts: can I stack one series and not the other?

  • 1
  • Question
  • Updated 1 year ago
  • Answered
Hi! I want to create a column chart with one series being a quarterly target and one series being actual closed-won opportunity amounts. I want the closed-won opportunity column to be split and stacked by opportunity type. 

Is it possible to stack a series and leave the other series as a separate column?
Photo of Kaede Holland

Kaede Holland

  • 3,176 Points 3k badge 2x thumb
  • hopeful!

Posted 1 year ago

  • 1
Photo of Pat Vachon

Pat Vachon, Champion

  • 45,258 Points 20k badge 2x thumb
I daresay probably. Most likely a before render and a matter of finding what to extend using Highcharts options. I'd take a look if I weren't slammed. ;)
Photo of Kaede Holland

Kaede Holland

  • 3,176 Points 3k badge 2x thumb
Yes - i see how it's done in highcharts - i've just never tried to do before render code things so I don't know where to start! Any good examples you can think of that show other people modifying highcharts in skuid with before render snippets? 
Photo of Pat Vachon

Pat Vachon, Champion

  • 45,258 Points 20k badge 2x thumb
Oof ... I can copy paste a couple functions I use constantly.

function reverseStacks(chartObj) {
$.extend(true, chartObj.yAxis[0], {
reversedStacks: false
});
}
function reverseLegend(chartObj) {
$.extend(true, chartObj, {
legend: {
reversed: true
}
});
} function enableLegendClick(chartObj) {
$.extend(true, chartObj, {
plotOptions: {
series: {
events: {
legendItemClick: function (clickParams) {

var splitsStack = [],
splits = [],
pathArray = clickParams.browserEvent.path,
chartId,
editorStack = Array.prototype.slice.call($(".nx-editor:visible")),
editors = [],
splitField,
outerHTML,
conditionName;

function addEditorOrNot(editorStackElement) {
if (editorStackElement.className.indexOf('nx-basicfieldeditor') !== -1 || editorStackElement.className.indexOf('nx-skootable') !== -1) {
editors.push(editorStackElement);
}
}

$.each(editorStack, function (es, editorStackElement) {
if (editorStackElement.className.indexOf('mid_level_table') !== -1) {
editors.push(editorStackElement);
}
});

$.each(pathArray, function (p, path) {
$.each(path.classList, function (c, pathClass) {
if (pathClass == 'highcharts-container') {
chartId = (pathArray[p + 3].id);
return false;
}
});
});

outerHTML = skuid.$C(chartId).seriesListNode["0"].outerHTML;

splitField = outerHTML.substring(outerHTML.indexOf('splittemplate="{{') + 17, outerHTML.length - outerHTML.indexOf('splittemplate="{{') + 17);

splitField = splitField.substring(0, splitField.indexOf('}}"'));

conditionName = '_chartClick_'.concat(splitField);

setTimeout(function () {
splitsStack = Array.prototype.slice.call($(".highcharts-legend-item-hidden:visible"));
$.each(splitsStack, function (s, split) {
splits.push(split.textContent);
});

// loop trough stack to update all conditions except chart
$.each(editors, function (e, editor) {
$.each(editor, function (propertyName, property) {
if (propertyName.startsWith("jQuery") && typeof property.editor !== 'undefined') {

$.each(property.component.list.conditions, function (c, condition) {
if (condition.name === conditionName) {
property.component.list.conditions.splice(c, 1);
}
});
if (property.component.list.model.id === "ActivityCategoriesSplits") {
splitField = "split";
}
property.component.list.conditions.push(
{
type: 'multiple',
field: splitField,
operator: 'not in',
values: splits,
inactive: false,
name: conditionName,
encloseValueInQuotes: true,
encloseValueInParens: false
}
);
property.component.list.render();

// update all fields on last editor
if (e + 1 === editors.length) {
$.each(property.component.list.model.registeredFields, function (f, field) {
field.handleChange();
});
}
}
});
});

}, 1);
}
}
}
},
});
}
function setChartSplitColours(chartObj, color_model_or_color_array, color_index, color_field) {
var chartcolors = [],
colorIndex = [],
ind,
series = chartObj.series;


// check to see if color_model_or_color_array is a model or array of colors
if (typeof color_model_or_color_array.fields !== 'undefined') {
$.each(color_model_or_color_array.getRows(), function (r, row) {

index = row[color_index].replace(/[\n\r]+/g, '');

if (typeof row[color_field] !== 'undefined') {
chartcolors.push('#' + row[color_field]);
colorIndex.push({ index: index, color: row[color_field] });
} else {
chartcolors.push('#000000');
colorIndex.push({ index: index, color: '000000' });
}
});

$.each(series, function (i, s_point) {

$.each(colorIndex, function (c, cIndex) {
if (s_point.id.replace(/[\n\r]+/g, '') == cIndex.index) {
ind = c;
return false;
}
});

// update series index number and color index with ind variable.
$.extend(true, series[i], {
index: ind,
_colorIndex: ind
},
{
index: ind,
_colorIndex: ind
});
});

} else {
$.each(color_model_or_color_array, function (c, array_element) {
chartcolors.push(array_element.color);
});

$.each(series, function (i, s_point) {

$.each(color_model_or_color_array, function (c, array_element) {
if (s_point.id.replace(/[\n\r]+/g, '') == array_element.name) {
ind = c;
return false;
}
});

// update series index number and color index with ind variable.
$.extend(true, series[i], {
index: ind,
_colorIndex: ind
},
{
index: ind,
_colorIndex: ind
});
});
}

$.extend(true, chartObj, {
colors: chartcolors
});

}