Format your data card into sections
Update the sections map at the top for this to function correctly on your grid.
Type: Javascript
/* This creates rows with headers within the data card of the parent AND/OR the child object */
GBDataCard = (function(window, document, jq) {
var sectionsMap = {
Account: { /*this is the object from which these fields come*/
licenses: {/*this section name for your first data card row. It should match the below title */
title: 'Licenses', /*this is the label that appears in the grid above the fields for this data card row*/
fields: ['of_GB_Licenses__c', 'of_SFDC_Licenses__c'] /*these are the fields that appear within the row*/
},
/*Repeat same structure as above, for as many rows as you need.
Replace the language (account/licenses/billing/created/hierarchy) in this extension to align with the objects and rows you want in your grid.
Every data card field must be included and API names must be exactly correct*/
billing: {
title: 'Billing',
fields: ['BillingCity', 'BillingCountry']
},
created: {
title: 'Created',
fields: ['CreatedById', 'CreatedDate']
},
hierarchy: {
title: 'Hierarchy',
fields: ['Account_Hierarchy_Level__c', 'Hierarchy_Link__c']
},
},
Contact: {
Contact_Fields: {
title: 'Contact Fields' ,
fields: [ 'Email' , 'MobilePhone' ]
},
MailingAddress: {
title: 'Mailing Address' ,
fields: [ 'MailingStreet' , 'MailingCity' , 'MailingPostalCode' , 'MailingCountry' ]
}
}
};
///// DON'T CHANGE ANYTHING BELOW THIS LINE /////
var sidebarEnabled,
sidebarCellWidth;
function init() {
sidebarEnabled = (window.location.href.indexOf('&ssb=1') > 0),
sidebarCell = jq('#sidebarCell'),
sidebarCellWidth = sidebarCell.outerWidth();
_initEventHandlers();
}
function getDataCardIcon(gridInfo) {
if (gridInfo.hasDataCardFields) {
return '<span class="icon-wrap"></span>';
}
return '';
}
function getDataCardCellHtml(gridInfo, metaCol, cellHtml, cellClasses) {
var dataCardClasses = ['cardItem', cellClasses],
dataCardHtmlArr = [],
gridInfoToUse = gridInfo;
if (metaCol.gridInfoGridId != gridInfo.gridId) {
// this metaCol is for a denormalized view child object
gridInfoToUse = gridInfoMap[metaCol.gridInfoGridId];
}
dataCardHtmlArr.push('<div class="'+ dataCardClasses.join(' ')+'" name="'+ metaCol.fieldId +'">');
dataCardHtmlArr.push('<label class="cardLabel">'+
metaCol.fieldLabelForDisplay(gridInfoToUse) +'</label>');
dataCardHtmlArr.push('<div class="cardCell">'+ cellHtml +'</div>');
dataCardHtmlArr.push('</div>');
return dataCardHtmlArr;
}
function getDataCardRowHtml(gridInfo, rowId, rowName, classes,dataCardHtmlArr, showByDefault, childRowId, childRowName) {
var childIdAttr = (childRowId ? ' data-childId="'+ childRowId +'"' : ''),
childRowNameAttr = (childRowName ? ' data-childRowName="'+ childRowName +'"' : ''),
colspan = GBRowHelper.getColCount(gridInfo, true),
htmlArr = [];
if (!showByDefault) {
classes.push('none');
}
htmlArr.push('<tr id="'+ rowId +'" class="' + classes.join(' ')
+ ' dataCard" name="'+ rowName +'"'
+ childIdAttr + childRowNameAttr + '>');
htmlArr.push('<td class="firstCol"></td>');
htmlArr.push('<td class="dataCardCell" colspan="'+ colspan +'">');
htmlArr.push('<div class="cardTable">'+ dataCardHtmlArr.join('') +'</div>');
htmlArr.push('</td></tr>');
// THIS BELOW CODE IS THE ONLY PART THAT HAS CHANGED
setTimeout(function(){
var sections = sectionsMap[gridInfo.gridApiName];
var section;
var sectionIndex = 0;
var metaCol;
var cardSelector;
var isLastSection;
var sectionStyle;
for(var k in sections) {
section = sections[k];
cardSelector = [];
sectionIndex ++;
if(section.fields === undefined) continue;
for (var i = 0; i < section.fields.length; i++) {
metaCol = getMetaColByFieldName(gridInfo, section.fields[i]);
isLastSection = sectionIndex == Object.keys(sections).length;
if(metaCol) {
cardSelector.push('[name=' + metaCol.fieldId + ']');
}
}
sectionStyle = isLastSection ? '' : 'margin-bottom: 8px; border-bottom: 1px solid #d4dadc;';
jq('#'+ rowId + '.dataCard').find(cardSelector.join(',')).wrapAll('<div class="dataCardCustomSection ' + k + '" style="'+sectionStyle+'"/>');
if(section.info && section.info !== '') {
jq('#'+ rowId + '.dataCard').find('.dataCardCustomSection.'+k).prepend('<h3 style="display: block;">' + section.info + '</h3>');
}
jq('#'+ rowId + '.dataCard').find('.dataCardCustomSection.'+k).prepend('<h1 style="display: block;">' + section.title + '</h1>');
}
}, 0);
return htmlArr.join('');
}
function openDataCard(dataCardCell) {
if (dataCardCell.closest('.dataCard').hasClass('none')) {
dataCardCell.closest('.dataCard').prev('tr.dr').find('.icon-wrap').click();
}
}
function addEventHandlerForMassUpdate() {
jq('#massUpdatesTable').on('click', '.icon-wrap', _onIconClicked);
}
function removeCollapsedDataCards(rows) {
rows = rows.filter(function() {
if (jq(this).hasClass('dataCard')
&& !jq(this).prev('.dr').find('.icon-wrap').hasClass('on')) {
// this is a data card and it was collapsed
return false;
}
return true;
});
return rows;
}
function _initEventHandlers() {
jqFrozenAndUnfrozenTables.on('click', '.icon-wrap', _onIconClicked);
jq(window).resize(function() {
jq('.dataCard:visible').each(function() {
var dataCardRow = jq(this),
primaryRow = dataCardRow.prev('#'+dataCardRow.attr('id')),
datCardCell = dataCardRow.find('.dataCardCell'),
cardTable = dataCardRow.find('.cardTable'),
firstColumnWidth = primaryRow.find('td:eq(0)').outerWidth(),
lastColumnWidth = primaryRow.find('td.lastCol').outerWidth(),
primaryRowWidth = _getPrimaryRowWidth(primaryRow, dataCardRow,
firstColumnWidth, lastColumnWidth),
dataCardRowWidth = _getDataCardRowWidth(primaryRowWidth, firstColumnWidth);
datCardCell.css('width', primaryRowWidth);
cardTable.css('width', dataCardRowWidth);
});
});
}
function _onIconClicked() {
var jqThis = jq(this),
elemInFrozenTable = GBFreezeCols.isElementInFrozenTable(jqThis),
isInEditableColumnWidget = (jqThis.closest('#relatedColumnWidget').length > 0),
primaryRow,
iconWrap,
firstPrimaryCol;
if (!isInEditableColumnWidget && elemInFrozenTable) {
if (GBFreezeCols.isFreezeColsEnabled()) {
GBFreezeCols.unfreezeColumns(false, GBFreezeCols.dataCardsNotSupportedMsg);
}
var parentRow = jqThis.closest('tr'),
parentRowId = parentRow.attr('id'),
parentTd = jqThis.closest('td'),
rowToUpdate,
tableToUpdate;
primaryRow = GBFreezeCols.getRowToUpdate(parentRow, parentRowId,
jq(mainTableJqueryId));
iconWrap = primaryRow.find('.icon-wrap');
firstPrimaryCol = primaryRow.find('td[name="' + parentTd.attr('name') + '"]');
} else {
// This case covers if there is an empty required field in the data card and freeze columns is enabled.
// The validateRemainingRequiredRowFields fn would've clicked the .icon-wrap icon in the unfrozen table in this case.
if (GBFreezeCols.isFreezeColsEnabled() && !jqThis.is(':visible')) {
GBFreezeCols.unfreezeColumns(false, GBFreezeCols.dataCardsNotSupportedMsg);
}
primaryRow = jqThis.closest('tr.dr');
iconWrap = jqThis;
firstPrimaryCol = jqThis.closest('td');
}
var dataCardRow = primaryRow.next('#'+ primaryRow.attr('id') +'.dataCard');
// hide the data card row
if (!dataCardRow.hasClass('none')) {
GBMixpanel.track('Change Grid Display', {
'Display Control': 'Data Card',
'Option': '',
'State': 'Collapse'
});
dataCardRow.addClass('none');
iconWrap.removeClass('on');
// remove a border between the primary and data card row on the first column
firstPrimaryCol.removeClass('borderBottomNone');
if (!isInEditableColumnWidget) {
GBFreezeCols.freezeColumnsIfEnabled();
}
} else {
// show the data card row
var cardTable = dataCardRow.find('.cardTable'),
dataCardCell = dataCardRow.find('.dataCardCell'),
firstColumnWidth = primaryRow.find('td:eq(0)').outerWidth(),
lastColumnWidth = primaryRow.find('td.lastCol').outerWidth(),
primaryRowWidth = _getPrimaryRowWidth(primaryRow, dataCardRow, firstColumnWidth, lastColumnWidth),
dataCardRowWidth = _getDataCardRowWidth(primaryRowWidth, firstColumnWidth);
GBMixpanel.track('Change Grid Display', {
'Display Control': 'Data Card',
'Option': '',
'State': 'Expand'
});
addAutocompleteToLookupFields(dataCardRow, false);
// initialize picklists when the data card is opened
dataCardRow.find('.plTxt').click();
dataCardRow.removeClass('none');
iconWrap.addClass('on');
// add a border between the primary and data card row on the first column
firstPrimaryCol.addClass('borderBottomNone');
dataCardCell.css('width', primaryRowWidth);
cardTable.css('width', dataCardRowWidth);
}
if (!isInEditableColumnWidget && !GBFreezeCols.isFreezeColsEnabled()) {
GBFreezeCols.updateHeightOfTablesWithNoFrozenCols();
}
}
function _getPrimaryRowWidth(primaryRow, dataCardRow, firstColumnWidth,
lastColumnWidth) {
var primaryRowWidth;
primaryRowWidth = primaryRow.width()-(firstColumnWidth+lastColumnWidth);
// data card row is in child table
if (dataCardRow.closest('.childTable').length > 0) {
var parentPrimaryRow = jq(mainTableJqueryId).find('tbody > tr').eq(0),
parentfirstColumnWidth = parentPrimaryRow.find('td:eq(0)').outerWidth(),
parentlastColumnWidth = parentPrimaryRow.find('td.lastCol').outerWidth(),
parentPrimaryRowWidth =
parentPrimaryRow.width()-(parentfirstColumnWidth+parentlastColumnWidth);
// if parent primary row is shorter than the child data car row, use the parent primary row for calculation
primaryRowWidth = (parentPrimaryRowWidth < primaryRowWidth) ? primaryRowWidth : parentPrimaryRowWidth;
}
return primaryRowWidth;
}
function _getDataCardRowWidth(primaryRowWidth, firstColumnWidth) {
var gridViewportWidth;
if (sidebarEnabled && sidebarCell.is(':visible')) {
gridViewportWidth = window.innerWidth-(sidebarCellWidth+firstColumnWidth);
} else {
gridViewportWidth = window.innerWidth-firstColumnWidth;
}
gridViewportWidth -= firstColumnWidth;
return (primaryRowWidth > gridViewportWidth) ? gridViewportWidth+'px' : '100%';
}
return {
init: init,
getDataCardIcon: getDataCardIcon,
getDataCardCellHtml: getDataCardCellHtml,
getDataCardRowHtml: getDataCardRowHtml,
openDataCard: openDataCard,
addEventHandlerForMassUpdate: addEventHandlerForMassUpdate,
removeCollapsedDataCards: removeCollapsedDataCards
};
})(window, document, jq); // end GBDataCard