This sample demonstrates how to apply themes to GanttSheet using both workbook-level themes and table-specific themes.
Workbook Theme
You can apply a complete workbook theme using the currentTheme method. SpreadJS provides 22 built-in themes in GC.Spread.Sheets.Themes.
Theme Colors
You can customize theme colors by creating a new theme and applying a color scheme from GC.Spread.Sheets.ThemeColors:
Theme Fonts
Similarly, you can customize theme fonts using GC.Spread.Sheets.ThemeFonts:
GanttSheet Theme
GanttSheet inherits from TableSheet and provides the applyTableTheme method, which accepts a GC.Spread.Sheets.Tables.TableTheme instance.
The following styles of TableTheme would be applied to GanttSheet:
Styles
Apply To
headerRowStyle
apply to the default style of column header area
wholeTableStyle
apply to the default style of viewport area and column header area
firstRowStripStyle
apply to the alternatingRowOptions style of viewport area
secondRowStripStyle
apply to the alternatingRowOptions style of viewport area
firstRowStripSize
apply to the alternatingRowOptions step of viewport area
secondRowStripSize
apply to the alternatingRowOptions step of viewport area
Besides previous built-in table themes, 21 light themes, 28 medium themes and 11 dark themes, GanttSheet also supports 24 new themes with the "professional" prefix.
/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
var myTable;
var ganttSheet;
window.onload = function() {
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
initSpread(spread);
initSplitView(spread);
};
function initSpread(spread) {
spread.suspendPaint();
spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader;
initDataSource(spread);
initGanttSheet(spread);
spread.resumePaint();
}
function initDataSource(spread) {
var tableName = "Gantt_Id";
var baseApiUrl = getBaseApiUrl();
var apiUrl = baseApiUrl + "/" + tableName;
var dataManager = spread.dataManager();
myTable = dataManager.addTable("myTable", {
batch: true,
remote: {
read: {
url: apiUrl
}
},
schema: {
hierarchy: {
type: "Parent",
column: "parentId"
},
columns: {
id: { isPrimaryKey: true },
taskNumber: { dataType: "rowOrder" }
}
}
});
}
function initGanttSheet(spread) {
ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet);
ganttSheet.options.allowAddNew = false;
ganttSheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
ganttSheet.applyTableTheme(GC.Spread.Sheets.Tables.TableThemes.light2);
ganttSheet.project.timescale.nonWorkingTime.color = 'Accent 4 60';
ganttSheet.project.timescale.nonWorkingTime.pattern = 'darkFil';
var view = myTable.addView("ganttView", [
{ value: "taskNumber", caption: "NO.", width: 60 },
{ value: "name", caption: "Task Name", width: 200 },
{ value: "duration", caption: "Duration", width: 90 },
{ value: "predecessors", caption: "Predecessors", width: 120 }
]);
view.fetch().then(function() {
ganttSheet.bindGanttView(view);
}).then(function(){
var taskStyle = ganttSheet.project.taskStyleRules.getRule('task');
taskStyle.style.taskbarStyle.middleColor = 'Accent 1';
taskStyle.style.taskbarStyle.topText = 'name';
var taskStyleIndex = ganttSheet.project.taskStyleRules.getIndexByItem(taskStyle);
ganttSheet.project.taskStyleRules.setItemAt(taskStyleIndex, taskStyle);
});
// Populate Workbook Theme options
var workbookThemeSelect = document.getElementById("workbookTheme");
Object.keys(GC.Spread.Sheets.Themes).forEach(function(themeName) {
var option = document.createElement("option");
option.value = themeName;
option.text = themeName;
if (themeName === "Office") {
option.selected = true;
}
workbookThemeSelect.appendChild(option);
});
workbookThemeSelect.addEventListener("change", function () {
let selectedTheme = workbookThemeSelect.value;
let theme = GC.Spread.Sheets.Themes[selectedTheme];
ganttSheet.currentTheme(theme);
});
// Populate Theme Colors options
var themeColorsSelect = document.getElementById("themeColors");
Object.keys(GC.Spread.Sheets.ThemeColors).forEach(function(colorName) {
var option = document.createElement("option");
option.value = colorName;
option.text = colorName;
if (colorName === "Office") {
option.selected = true;
}
themeColorsSelect.appendChild(option);
});
themeColorsSelect.addEventListener("change", function () {
let selectedColorScheme = themeColorsSelect.value;
let currentTheme = ganttSheet.currentTheme();
let newTheme = new GC.Spread.Sheets.Theme();
newTheme.fromJSON(currentTheme.toJSON());
newTheme.colors(GC.Spread.Sheets.ThemeColors[selectedColorScheme]);
newTheme.name('custom-theme');
ganttSheet.currentTheme(newTheme);
});
// Populate Theme Fonts options
var themeFontsSelect = document.getElementById("themeFonts");
var overrideGanttFontCheckbox = document.getElementById("override-gantt-font");
var shouldOverrideGanttFont = false;
var currentGanttThemeName = "light2"; // Track current gantt theme
Object.keys(GC.Spread.Sheets.ThemeFonts).forEach(function(fontName) {
var option = document.createElement("option");
option.value = fontName;
option.text = fontName;
if (fontName === "Office") {
option.selected = true;
}
themeFontsSelect.appendChild(option);
});
overrideGanttFontCheckbox.addEventListener("click", function() {
if (overrideGanttFontCheckbox.classList.contains("active")) {
overrideGanttFontCheckbox.classList.remove("active");
shouldOverrideGanttFont = false;
} else {
overrideGanttFontCheckbox.classList.add("active");
shouldOverrideGanttFont = true;
}
applyGanttTableTheme();
});
themeFontsSelect.addEventListener("change", function () {
applyThemeFont();
});
function applyThemeFont() {
let selectedFont = themeFontsSelect.value;
let currentTheme = ganttSheet.currentTheme();
let newTheme = new GC.Spread.Sheets.Theme();
newTheme.fromJSON(currentTheme.toJSON());
newTheme.font(GC.Spread.Sheets.ThemeFonts[selectedFont]);
newTheme.name('custom-theme');
ganttSheet.currentTheme(newTheme);
if (shouldOverrideGanttFont) {
applyGanttTableTheme();
}
}
function applyGanttTableTheme() {
if (shouldOverrideGanttFont) {
// Clone the current table theme
var baseTheme = GC.Spread.Sheets.Tables.TableThemes[currentGanttThemeName];
var customTableTheme = new GC.Spread.Sheets.Tables.TableTheme();
customTableTheme.fromJSON(baseTheme.toJSON());
// Get and modify the highlightLastColumnStyle
var lastColStyle = customTableTheme.highlightLastColumnStyle();
if (!lastColStyle) {
lastColStyle = new GC.Spread.Sheets.Tables.TableStyle();
}
// Set font and fontFamily to undefined to use theme font
lastColStyle.font = undefined;
lastColStyle.fontFamily = undefined;
customTableTheme.highlightLastColumnStyle(lastColStyle);
// Apply the modified theme
ganttSheet.applyTableTheme(customTableTheme);
} else {
// Apply the original table theme
ganttSheet.applyTableTheme(GC.Spread.Sheets.Tables.TableThemes[currentGanttThemeName]);
}
}
// GanttSheet Theme selector
var ganttThemeSelect = document.getElementById("ganttSheetTheme");
ganttThemeSelect.addEventListener("change", function () {
let selectedTheme = ganttThemeSelect.value;
currentGanttThemeName = selectedTheme;
applyGanttTableTheme();
});
}
function getBaseApiUrl() {
var url = window.location.href;
return url.match(/http.+spreadjs\/demos\//)[0] + 'server/api';
}
function initSplitView(spread) {
var host = document.getElementById("split-view");
var content = host.getElementsByClassName("split-content")[0];
var panel = host.getElementsByClassName("split-panel")[0];
new SplitView({
host: host,
content: content,
panel: panel,
refreshContent: function() {
spread.refresh();
}
});
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/spread/source/splitView/splitView.css">
<!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/splitView/splitView.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div id="split-view" class="sample-tutorial">
<div id="ss" class="sample-spreadsheets split-content"></div>
<div class="options-container split-panel">
<div class="option-block">
<div class="option-row option-title">
Workbook Theme
</div>
<div class="option-row selection-box">
<label>Theme</label>
<select id="workbookTheme"></select>
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
Theme Colors
</div>
<div class="option-row selection-box">
<label>Colors</label>
<select id="themeColors"></select>
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
Theme Fonts
</div>
<div class="option-row selection-box">
<label>Fonts</label>
<select id="themeFonts"></select>
</div>
<div class="option-row">
<label class="option-checkbox" id="override-gantt-font">Override GanttSheet Theme Font</label>
<div class="option-info">* Override highlightLastColumn fontFamily with theme font.</div>
</div>
</div>
<div class="option-block">
<div class="option-row option-title">
GanttSheet Theme
</div>
<div class="option-row selection-box">
<label>Theme</label>
<select id="ganttSheetTheme">
<optgroup label="Light Themes">
<option value="light1">light1</option>
<option value="light2" selected>light2</option>
<option value="light3">light3</option>
<option value="light4">light4</option>
<option value="light5">light5</option>
<option value="light6">light6</option>
<option value="light7">light7</option>
<option value="light8">light8</option>
<option value="light9">light9</option>
<option value="light10">light10</option>
<option value="light11">light11</option>
<option value="light12">light12</option>
<option value="light13">light13</option>
<option value="light14">light14</option>
<option value="light15">light15</option>
<option value="light16">light16</option>
<option value="light17">light17</option>
<option value="light18">light18</option>
<option value="light19">light19</option>
<option value="light20">light20</option>
<option value="light21">light21</option>
</optgroup>
<optgroup label="Medium Themes">
<option value="medium1">medium1</option>
<option value="medium2">medium2</option>
<option value="medium3">medium3</option>
<option value="medium4">medium4</option>
<option value="medium5">medium5</option>
<option value="medium6">medium6</option>
<option value="medium7">medium7</option>
<option value="medium8">medium8</option>
<option value="medium9">medium9</option>
<option value="medium10">medium10</option>
<option value="medium11">medium11</option>
<option value="medium12">medium12</option>
<option value="medium13">medium13</option>
<option value="medium14">medium14</option>
<option value="medium15">medium15</option>
<option value="medium16">medium16</option>
<option value="medium17">medium17</option>
<option value="medium18">medium18</option>
<option value="medium19">medium19</option>
<option value="medium20">medium20</option>
<option value="medium21">medium21</option>
<option value="medium22">medium22</option>
<option value="medium23">medium23</option>
<option value="medium24">medium24</option>
<option value="medium25">medium25</option>
<option value="medium26">medium26</option>
<option value="medium27">medium27</option>
<option value="medium28">medium28</option>
</optgroup>
<optgroup label="Dark Themes">
<option value="dark1">dark1</option>
<option value="dark2">dark2</option>
<option value="dark3">dark3</option>
<option value="dark4">dark4</option>
<option value="dark5">dark5</option>
<option value="dark6">dark6</option>
<option value="dark7">dark7</option>
<option value="dark8">dark8</option>
<option value="dark9">dark9</option>
<option value="dark10">dark10</option>
<option value="dark11">dark11</option>
</optgroup>
<optgroup label="Professional Themes">
<option value="professional1">professional1</option>
<option value="professional2">professional2</option>
<option value="professional3">professional3</option>
<option value="professional4">professional4</option>
<option value="professional5">professional5</option>
<option value="professional6">professional6</option>
<option value="professional7">professional7</option>
<option value="professional8">professional8</option>
<option value="professional9">professional9</option>
<option value="professional10">professional10</option>
<option value="professional11">professional11</option>
<option value="professional12">professional12</option>
<option value="professional13">professional13</option>
<option value="professional14">professional14</option>
<option value="professional15">professional15</option>
<option value="professional16">professional16</option>
<option value="professional17">professional17</option>
<option value="professional18">professional18</option>
<option value="professional19">professional19</option>
<option value="professional20">professional20</option>
<option value="professional21">professional21</option>
<option value="professional22">professional22</option>
<option value="professional23">professional23</option>
<option value="professional24">professional24</option>
</optgroup>
</select>
</div>
</div>
</div>
</html>
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
.sample-spreadsheets {
width: calc(100% - 280px);
height: 100%;
overflow: hidden;
float: left;
}
.options-container {
float: right;
width: 280px;
padding: 12px;
height: 100%;
box-sizing: border-box;
background: #fbfbfb;
overflow: auto;
box-shadow: inset 0px 0 4px 0 rgba(0,0,0,0.4);
}
.option-block {
background: #fff;
padding: 8px;
margin: 12px 0;
border-radius: 4px;
border: 1px dashed #82bc00;
box-shadow: 0px 0 6px 0 rgba(0,0,0,0.1);
}
.option-row {
font-size: 14px;
box-sizing: border-box;
padding: 4px 0;
}
.option-title {
font-weight: bold;
color: #656565;
}
.option-info {
font-size: 12px;
color: #919191;
margin-top: 6px;
font-weight: normal;
}
.option-checkbox {
background: #fff;
border: 1px dashed #f7a711;
color: #f7a711;
padding: 2px 4px;
transition: 0.3s;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
}
.option-checkbox.active {
color: #fff;
background: #f7a711;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3);
border-radius: 4px;
}
.selection-box {
position: relative;
}
.selection-box > select {
text-align: left;
width: 100%;
height: 20px;
padding: 0;
line-height: 20px;
background: transparent;
border: none;
border-bottom: 2px solid #656565;
color: #656565;
transition: 0.3s;
cursor: pointer;
outline: none;
box-sizing: border-box;
}
.selection-box > select > option {
background: white;
}
.selection-box > select:focus {
border-bottom: 2px solid #82bc00;
color: #82bc00;
box-shadow: 0 2px 6px 0 rgba(0,0,0,0.3);
}
.selection-box > label {
position: absolute;
cursor: pointer;
font-size: 12px;
color: #fff;
background: #656565;
padding: 0 4px;
right: 0;
top: 6px;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3);
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}