UNPKG

bardelman-dhtmlx-gantt-redux

Version:

An open source JavaScript Gantt chart that helps you illustrate a project schedule in a nice-looking chart.

1,008 lines (872 loc) 29 kB
<!DOCTYPE html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>Performance tweaks</title> <script src="../../codebase/dhtmlxgantt.js?v=9.0.10"></script> <link rel="stylesheet" href="../../codebase/dhtmlxgantt.css?v=9.0.10"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link rel="stylesheet" href="../common/controls_styles.css?v=9.0.10"> <script src="../common/testdata.js?v=9.0.10"></script> <style> html, body { height: 100%; padding: 0px; margin: 0px; overflow: hidden; } .controls { font-family: "Arial"; width:910px; margin: 0 auto; } .controls td { text-align: right; line-height: 20px; color: #535353; font-size: 14px; } .controls th { font-size: 14px; } .controls input { max-width: 60px; padding: 2px 7px; text-align: right; border: 1px solid #d6d6d6; } .controls table { border-collapse: collapse; } .controls td, .controls th { border: 1px solid #d6d6d6; padding: 0 10px; } .dhtmlx-intro div { background-color: #FEFFEA; border: 1px solid #A2A0A0; } .gantt_control button{ margin: 0 5px!important; padding: 3px 10px!important; } .gantt_task_cell.week_end, .gantt_task_cell.no_work_hour { background-color: var(--dhx-gantt-base-colors-background-alt); } .gantt_task_row.gantt_selected .gantt_task_cell.week_end { background-color: var(--dhx-gantt-base-colors-select); } .resource_marker{ text-align: center; } .resource_marker div{ color: black; background: none; } .resource_marker.resource_cell div{ font-weight: bold; background-color: #d6d6d6; } .resource_marker.workday_ok div { } .resource_marker.workday_over div{ color: red; } .owner-label{ width: 20px; height: 20px; line-height: 20px; font-size: 12px; display: inline-block; border: 1px solid #cccccc; border-radius: 25px; background: #e6e6e6; color: #6f6f6f; margin: 0 3px; font-weight: bold; } /** custom layers css */ .drag_date { color: #454545; font-size: 13px; text-align: center; z-index: 1; } .drag_date.drag_move_start { margin-left: -15px; } .drag_date.drag_move_end { margin-left: 15px; } .drag_move_vertical, .drag_move_horizontal { background-color: #9DE19E; opacity: 0.7; box-sizing: border-box; } .drag_move_vertical { border-right: 1px #6AC666 solid; border-left: 1px #6AC666 solid; } .drag_move_horizontal { border-top: 1px #6AC666 solid; border-bottom: 1px #6AC666 solid; } .cooldown { position: absolute; border-radius: 0; opacity: 0.7; border: none; border-right: 1px solid #b6b6b6; margin-left: -2px; background: #b6b6b6; background: repeating-linear-gradient( 45deg, #FFFFFF, #FFFFFF 5px, #b6b6b6 5px, #b6b6b6 10px ); } .deadline { position: absolute; border-radius: 12px; border: 2px solid #585858; -moz-box-sizing: border-box; box-sizing: border-box; width: 22px; height: 22px; margin-left: -11px; margin-top: 6px; z-index: 1; } .floating_icon { position: absolute; font-size: 30px; z-index: 1; } .baseline { position: absolute; border-radius: 20px; opacity: 0.6; background: #89b4e1; border: 1px solid rgba(0,0,0,0.38); } /* custom layers css end */ </style> </head> <body> <div class="gantt_control" style="padding-top: 0"> <div class="controls" id="controls_wrapper"> <table> <tr> <th>Background Mode</th> <th>Features</th> <th>Task element</th> <th>Scales</th> <th>Data</th> </tr> <tr> <td><label>Default <input type="radio" id="default" name="mode"><i class="material-icons">radio_button_unchecked</i></label></td> <td><label>Work Time<input type="checkbox" id="work_time"><i class="material-icons ">check_box_outline_blank</i></label></td> <td><label class="checked_label">Show progress <input type="checkbox" id="progress" checked><i class="material-icons icon_color">check_box</i></label></td> <td><label style="color: rgba(0,0,0,0.38)">Year scale <input type="checkbox" id="year" checked disabled="disabled"><i class="material-icons md-inactive icon_color">check_box</i></label></td> <td><label>Tasks <input id="tasks" value="100"></label></td> </tr> <tr> <td><label>Simplified <input type="radio" id="no_cells" name="mode"><i class="material-icons">radio_button_unchecked</i></label></td> <td><label>Auto scheduling<input type="checkbox" id="auto_scheduling"><i class="material-icons">check_box_outline_blank</i></label></td> <td><label class="checked_label">Allow resize <input type="checkbox" id="resize" checked><i class="material-icons icon_color">check_box</i></label></td> <td><label class="checked_label">Month scale <input type="checkbox" id="month" checked><i class="material-icons icon_color">check_box</i></label></td> <td> <label>Range <input id="from" value="2023">&ndash;<input id="to" value="2024"></label> </td> </tr> <tr> <td><label class="checked_label">Dynamic image <input type="radio" id="canvas" name="mode" checked><i class="material-icons icon_color">radio_button_checked</i></label></td> <td><label>Build links<input type="checkbox" id="build_links"><i class="material-icons">check_box_outline_blank</i></label></td> <td><label class="checked_label">Show links <input type="checkbox" id="links" checked><i class="material-icons icon_color">check_box</i></label></td> <td><label>Week scale <input type="checkbox" id="week"><i class="material-icons">check_box_outline_blank</i></label></td> <td><label title="Works when 'Resources' checkbox is activated">Resources<input id="max_resources" value="10" type="number" min="1"></label></td> </tr> <tr> <td><label class="checked_label">Smart rendering <input type="checkbox" id="smart_render" name="mode" checked><i class="material-icons icon_color">check_box</i></label></td> <td><label>Resources<input type="checkbox" id="resources"><i class="material-icons">check_box_outline_blank</i></label></td> <td><label>Task Layers<select id="layers"> <option selected value=''>Default</option> <option value='1'>1</option> <option value='2'>2</option> <option value='3'>3</option> <option value='4'>4</option> <option value='5'>5</option> </select></label></td> <td><label class="checked_label">Day scale <input type="checkbox" id="day" checked><i class="material-icons icon_color">check_box</i></label></td> <td><label title="Works when 'Resources' checkbox is activated">Res. per task (max)<input id="max_assignments" value="3" type="number" min="0"></label></td> </tr> <tr> <td colspan="5" style="text-align: center;"> <button id="refresh" onclick="toggleChange()">Refresh</button> </td> </tr> </table> </div> <div id="gantt_here" style='width:100%; height:calc(100vh - 171px);'></div> <script> var text = ["Gantt chart with the data generated for client-side performance testing.", "Change settings and <b>press 'Refresh'</b> to see how it works on different configurations and amounts of data.", "See browser console for test logs."]; for (var i = 0; i < text.length; i++) { gantt.message({ text: text[i], expire: 30 * 1000, type: "intro" }); } function byId(id) { return document.getElementById(id); } function getState(){ return { progress: byId("progress").checked, resize: byId("resize").checked, links: byId("links").checked, smart_render: byId("smart_render").checked, work_time: byId("work_time").checked, auto_scheduling: byId("auto_scheduling").checked, canvas: byId("canvas").checked, no_cells: byId("no_cells").checked, build_links: byId("build_links").checked, resources: byId("resources").checked, week: byId("week").checked, day: byId("day").checked, month: byId("month").checked, from: byId("from").value, to: byId("to").value, tasks: byId("tasks").value, max_resources: byId("max_resources").value, max_assignments: byId("max_assignments").value, layers: byId("layers").value }; } var currentState = getState(); function applySettings(state){ gantt.config.static_background = state.canvas; gantt.config.show_task_cells = !state.no_cells; gantt.config.show_progress = state.progress; gantt.config.drag_resize = state.resize; gantt.config.show_links = state.links; gantt.config.smart_rendering = state.smart_render; gantt.config.work_time = state.work_time; gantt.config.auto_scheduling = state.auto_scheduling; var buildLinks = state.build_links; var useResources = state.resources; gantt.config.scales = [ { unit: "year", step: 1, format: "%Y"} ]; if (state.week) { var dateToStr = gantt.date.date_to_str("%d %M"); gantt.config.scales.push({unit: "week", step: 1, format: function (date) { var endDate = gantt.date.add(date, 7 - date.getDay(), "day"); return dateToStr(date) + " - " + dateToStr(endDate); }}); } if (state.day) { gantt.config.scales.push({unit: "day", step: 1, format: "%d %M"}); } if (state.month) { gantt.config.scales.push({unit: "month", step: 1, format: "%F, %Y"}); } gantt.config.scale_height = 22 * gantt.config.scales.length; if (state.canvas) { gantt.config.static_background = true; } else if (state.no_cells) { gantt.config.show_task_cells = false; } if(initNeeded(currentState, state)){ gantt.attachEvent("onGanttReady", function(){ var layersNum = Number(state.layers); if(!isNaN(layersNum) && layersNum > 0){ var layers = getCustomLayers().slice(0, layersNum); layers.forEach(function(layer){gantt.addTaskLayer(layer.render);}); } }, {once: true}); } applyResources(state); } function featureState(state) { return (state ? "Display" : "Hide"); } function getCustomLayers(){ var dragDateFormat = gantt.date.date_to_str("%Y‐%m‐%d"); return [ { name: "baselines", render: function baselineLayer(task) { if (task.planned_start && task.planned_end) { var sizes = gantt.getTaskPosition(task, task.planned_start, task.planned_end); var el = document.createElement('div'); el.className = 'baseline'; el.style.left = sizes.left + 'px'; el.style.width = sizes.width + 'px'; el.style.top = (sizes.top + 3) + 'px'; el.style.height = (sizes.height - 4) + 'px'; return el; } return false; } }, { name: "deadlines", render: function deadlineLayer(task) { if (task.deadline) { var el = document.createElement('div'); el.className = 'deadline'; var sizes = gantt.getTaskPosition(task, task.deadline); el.innerHTML = "&check;"; el.style.left = sizes.left + 'px'; el.style.top = sizes.top + 'px'; el.setAttribute('title', gantt.templates.task_date(task.deadline)); return el; } return false; } }, { name: "rejection time", render: function deadlineLayer(task) { if (task.reject_time) { var el = document.createElement('div'); el.className = 'floating_icon'; var sizes = gantt.getTaskPosition(task, task.reject_time); el.innerHTML = "&#x2717;"; el.style.color = "red"; el.style.left = sizes.left + 'px'; el.style.top = sizes.top + 'px'; el.setAttribute('title', gantt.templates.task_date(task.reject_time)); return el; } return false; } }, { name: "cooldown time", render: function cooldownTime(task) { var cooldownTime = task.cooldown_time; if (!cooldownTime) { return null; } var markStart = new Date(task.end_date); var markEnd = gantt.calculateEndDate({task: task, start_date: markStart, duration: cooldownTime}); var sizes = gantt.getTaskPosition(task, markStart, markEnd); var el = document.createElement('div'); el.className = 'cooldown'; el.style.left = sizes.left + 'px'; el.style.top = sizes.top + 2 + 'px'; el.style.width = sizes.width + 'px'; el.style.height = sizes.height + 'px'; return el; } }, { name: "misc icons", render: function deadlineLayer(task) { if (task.misc_icon) { var el = document.createElement('div'); el.className = 'floating_icon'; var sizes = gantt.getTaskPosition(task); el.innerHTML = task.misc_icon; el.style.left = (sizes.left + sizes.width + 20) + 'px'; el.style.top = (sizes.top - 5) + 'px'; el.setAttribute('title', "Random icon in the task layer"); return el; } return false; } }, ]; function addElement(config) { var div = document.createElement('div'); div.style.position = "absolute"; div.className = config.css || ""; div.style.left = config.left; div.style.width = config.width; div.style.height = config.height; div.style.lineHeight = config.height; div.style.top = config.top; if (config.html) div.innerHTML = config.html; if (config.wrapper) config.wrapper.appendChild(div); return div; } } function customLayersReport(){ currentState var layersNum = Number(currentState.layers); if(!isNaN(layersNum) && layersNum > 0){ return getCustomLayers().slice(0, layersNum).map(function(layerInfo){ return layerInfo.name; }).join(", "); }else{ return "None"; } } function printStat(time) { var mode = ""; var report = []; if (gantt.config.static_background) { mode = "Canvas background rendering"; } else if (!gantt.config.show_task_cells) { mode = "Simplified background rendering"; } else { mode = "Default rendering"; } report.push("Rendered in <b>" + (time) + "</b> seconds"); report.push(mode); report.push(featureState(gantt.config.show_progress) + " progress"); report.push(featureState(gantt.config.drag_resize) + " drag handles"); report.push(featureState(gantt.config.show_links) + " link handles"); report.push("Work time:" + String(gantt.config.work_time)); report.push("Auto Scheduling:" + String(gantt.config.auto_scheduling)); report.push("Custom Layers: " + customLayersReport()); var scales = []; for (var i = 0; i < gantt.config.scales.length; i++) { scales.push(gantt.config.scales[i].unit); } var resourceCount = 0; if(gantt.getDatastore(gantt.config.resource_store)){ gantt.getDatastore(gantt.config.resource_store).eachItem(function(item){ if(item.$role !== "task"){// assigned tasks are loaded into resource store, do not count them here resourceCount++; } }); } report.push("Scales : <b>" + scales.join(", ") + "</b> "); var scale = gantt.getScale(); report.push(gantt.getTaskCount() + " tasks, " + gantt.getLinkCount() + " links, " + resourceCount + " resources, " + (scale.count) + " columns in a time scale"); gantt.message({text: report.join("<br>"), expire: 10000}); console.log("================"); console.log(report.join("\n")); } function settingsChanged(oldState, newState){ for(var i in oldState){ if(newState[i] !== oldState[i]){ return true; } } return false; } function initNeeded(oldState, newState){ return oldState.resources !== newState.resources || oldState.layers !== newState.layers; } function toggleChange(){ var oldState = currentState; var newState = getState(); if(!settingsChanged(oldState, newState)){ noteTime(gantt.render); }else{ var reinitialize = initNeeded(oldState, newState); noteTime(function(){ gantt.clearAll(); applySettings(newState); if(reinitialize){ gantt.init("gantt_here"); }else{ gantt.render(); } resetData(newState); currentState = newState; }); } } function noteTime(method) { gantt.message("Rendering..."); var start = Date.now(); method.call(gantt); var end = Date.now(); printStat((end - start) / 1000); var selectedId = gantt.getSelectedId(); if (selectedId) gantt.showTask(selectedId); } function applyResources(state){ if(state.resources){ if(!gantt.getDatastore(gantt.config.resource_store)){ gantt.createDatastore({ name: gantt.config.resource_store, type: "treeDatastore", fetchTasks: true, initItem: function (item) { item.parent = item.parent || gantt.config.root_id; item[gantt.config.resource_property] = item.parent; item.open = true; return item; } }); } gantt.config.layout = { css: "gantt_container", rows: [ { cols: [ {view: "grid", group:"grids", scrollY: "scrollVer"}, {resizer: true, width: 1}, {view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"}, {view: "scrollbar", id: "scrollVer", group:"vertical"} ], gravity:2 }, {resizer: true, width: 1}, { config: { columns: [ { name: "name", label: "Name", tree:true, template: function (resource) { return resource.text; } }, { name: "workload", label: "Workload", template: function (resource) { var totalDuration = 0; if (resource.$role === "task"){ gantt.getResourceAssignments(resource.$resource_id, resource.$task_id).forEach(function(a){ totalDuration += a.value * a.duration; }); }else{ getResourceAssignments(resource.id).forEach(function (assignment) { totalDuration += Number(assignment.value) * assignment.duration; }); } return (totalDuration || 0) + "h"; } } ] }, cols: [ {view: "resourceGrid", group:"grids", width: 435, scrollY: "resourceVScroll" }, {resizer: true, width: 1}, {view: "resourceTimeline", scrollX: "scrollHor", scrollY: "resourceVScroll"}, {view: "scrollbar", id: "resourceVScroll", group:"vertical"} ], gravity:1 }, {view: "scrollbar", id: "scrollHor"} ] }; gantt.config.resource_render_empty_cells = true; gantt.config.columns = [ {name: "text", tree: true, width: 200, resize: true}, {name: "start_date", align: "center", width: 90, resize: true}, {name: "owner", align: "center", width: 75, label: "Owner", template: function (task) { if (task.type == gantt.config.types.project) { return ""; } var store = gantt.getDatastore("resource"); var assignments = gantt.getTaskAssignments(task.id); var uniqueResources = {}; var resourceCount = 0; assignments.forEach(function(a){ if(!uniqueResources[a.resource_id]){ uniqueResources[a.resource_id] = a.resource_id; resourceCount++; } }); if(!resourceCount){ return "Unassigned"; }else if(resourceCount === 1){ return store.getItem(assignments[0].resource_id).text; }else{ var result = ""; for(var i in uniqueResources){ var owner = store.getItem(uniqueResources[i]); if (!owner) continue; result += "<div class='owner-label' title='" + owner.text + "'>" + owner.text.substr(0, 1) + "</div>"; } return result; } return result; }, resize: true }, {name: "duration", width: 60, align: "center", resize: true}, {name: "add", width: 44} ]; function getResourceAssignments(resourceId) { var assignments; var store = gantt.getDatastore(gantt.config.resource_store); var resource = store.getItem(resourceId); if(resource.$role === "task"){ assignments = gantt.getResourceAssignments(resource.$resource_id, resource.$task_id); }else{ assignments = gantt.getResourceAssignments(resourceId); if(store.eachItem){ store.eachItem(function(childResource){ if(childResource.$role !== "task"){ assignments = assignments.concat(gantt.getResourceAssignments(childResource.id)); } }, resourceId); } } return assignments; } gantt.templates.resource_cell_class = function(start_date, end_date, resource, tasks, assignments){ var css = []; css.push("resource_marker"); if(resource.$role === "task"){ css.push("task_cell"); }else{ css.push("resource_cell"); } var sum = assignments.reduce(function(total, assignment){ return total + Number(assignment.value); }, 0); if (sum <= 8) { css.push("workday_ok"); } else { css.push("workday_over"); } return css.join(" "); }; gantt.templates.resource_cell_value = function(start_date, end_date, resource, tasks, assignments){ if(resource.$role === "task"){ if(start_date < resource.end_date && end_date > resource.start_date){ for(var i = 0; i < assignments.length; i++){ var a = assignments[i]; return "<div data-assignment-cell data-assignment-id='"+a.id+"'"+ " data-row-id='"+resource.id+"'"+ " data-task='"+resource.$task_id+"'"+ " data-start-date='"+gantt.templates.format_date(start_date)+"'"+ " data-end-date='"+gantt.templates.format_date(end_date)+"'>" + a.value + "</div>" } return "<div data-assignment-cell data-empty "+ " data-row-id='"+resource.id+"'"+ " data-resource-id='"+resource.$resource_id+"'"+ " data-task='"+resource.$task_id+"'"+ " data-start-date='"+gantt.templates.format_date(start_date)+"'"+ "' data-end-date='"+gantt.templates.format_date(end_date)+"'>-</div>"; } }else{ var sum = assignments.reduce(function(total, assignment){ return total + Number(assignment.value); }, 0); if(sum % 1){ sum = Math.round(sum * 10)/10; } if(sum){ return "<div>" + sum + "</div>"; } return ""; } }; }else{ gantt.config.layout = { css: "gantt_container", rows: [ { cols: [ {view: "grid", scrollX: "scrollHor", scrollY: "scrollVer"}, {resizer: true, width: 1}, {view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"}, {view: "scrollbar", id: "scrollVer"} ] }, {view: "scrollbar", id: "scrollHor", height: 20} ] }; gantt.config.columns = [ {name: "text", tree: true, width: "*", resize: true}, {name: "start_date", align: "center", resize: true}, {name: "duration", align: "center", resize: true}, {name: "add", width: 44} ]; } } function resetData(state) { var count = state.tasks, from = state.from, to = state.to; var buildLinks = state.build_links; var buildResources = state.resources; var start = Date.now(); gantt.message("Generating random data"); var data = generateData(count, from, to, buildLinks, buildResources, state.max_resources, state.max_assignments); gantt.clearAll(); if(buildResources){ gantt.getDatastore(gantt.config.resource_store).clearAll(); gantt.getDatastore(gantt.config.resource_store).parse(data.resources); } gantt.parse(data); var end = Date.now(); gantt.message("Generated and parsed <b>" + gantt.getTaskByTime().length + "</b> tasks and "+gantt.getLinkCount()+" links in <b>" + (end - start) / 1000 + "</b> seconds"); } function randomDate(start, end) { return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); } function getDateRange(from, to) { from = parseInt(from, 10) || 2023; to = parseInt(to, 10) || (from + 1); if (to < from) { to = from + 1; } return { start_date: new Date(from, 0, 1), end_date: new Date(to, 0, 0) }; } function generateData(count, from, to, buildLinks, buildResources, resourcesCount, maxAssignmentsPerTask) { var tasks = { data: [], links: [] }; var range = getDateRange(from, to); count = parseInt(count, 10) || 100; var resources = null; if(buildResources){ tasks.resources = generateResources(resourcesCount || Math.floor(count / 10)); } var date = new Date(range.start_date.getFullYear(), 5, 1); var project_id = 1; tasks.data.push({ id: project_id, text: "Project1", type: gantt.config.types.project, open: true }); for (var i = 1; i < count; i++) { date = gantt.date.add(date, 1, "day"); var baselineStart = gantt.date.add(date, getRandomInt(0, 20) - 10, "day"); var task = { id: i + 1, start_date: date, text: "Task " + (i + 1), duration: 8, parent: project_id, deadline: gantt.date.add(date, 8 + getRandomInt(0, 8), "day"), reject_time: gantt.date.add(date, 8 + getRandomInt(8, 15), "day"), planned_start: baselineStart, planned_end: gantt.date.add(baselineStart, getRandomInt(1, 15), "day"), cooldown_time: getRandomInt(0, 5), misc_icon: getRandomElement(["", "&#9728;", "&#9729;", "&#9730;", "&#9731;"]) }; if (gantt.date.add(date, 8, "day").valueOf() > range.end_date.valueOf()) { date = new Date(range.start_date); project_id = i + 1; delete task.parent; task.open = true; }else if(buildLinks && tasks.data[i - 1] && tasks.data[i-1].parent === project_id){ tasks.links.push({ id: `FS-${i}`, source: i, target: i+1, type: gantt.config.links.finish_to_start }); } if(buildResources && task.parent){ var resourcesInTask = getRandomIntInclusive(0,maxAssignmentsPerTask); task[gantt.config.resource_property] = []; for(var r = 0; r < resourcesInTask; r++){ var res = getRandomResource(tasks.resources); if(res){ task[gantt.config.resource_property].push({ resource_id: res.id, value: getRandomIntInclusive(1, 8) }); } } } tasks.data.push(task); } return tasks; } function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min) + min); //The maximum is exclusive and the minimum is inclusive } function getRandomIntInclusive(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1) + min); //The maximum is inclusive and the minimum is inclusive } function getRandomElement(array){ return array[getRandomInt(0, array.length)]; } function getRandomResource(resources){ var maxTries = 100; var currentTries = 0; var randomRes = getRandomElement(resources); while(!randomRes.parent && currentTries < maxTries){// select resource which is not a category randomRes = getRandomElement(resources); currentTries ++; } return randomRes; } function generateResources(count){ var categories = Math.max(Math.floor(count / 10), 1); var items = count; var result = []; for(var i = 0; i < categories; i++){ var currentCategory = "department:" + i; var itemsInCategory = Math.floor(items / (categories - i)); items = items - itemsInCategory; result.push({id: currentCategory, text: "Department " + (i + 1)}); for(var j = 0; j < itemsInCategory; j++){ result.push({id: currentCategory + ";item:" + j, text: "Dep:" + (i + 1) + ";Item:" + (j +1), parent: currentCategory}); } } return result; } gantt.plugins({ auto_scheduling: true }); gantt.config.work_time = false; gantt.config.auto_scheduling = false; gantt.config.resources.resource_store.fetchTasks = true; gantt.templates.timeline_cell_class = function (task, date) { if (!gantt.isWorkTime(date)) return "week_end"; return ""; }; gantt.config.min_column_width = 50; applySettings(currentState); gantt.init("gantt_here"); resetData(currentState); var control_inputs = document.getElementById("controls_wrapper").getElementsByTagName("input"); for (var i = 0; i < control_inputs.length; i++) { var control_input = control_inputs[i]; if (control_input.type == "checkbox") control_input.onchange = function() { updCheckboxLabel(this); } if (control_input.type == "radio") control_input.onclick = function() { updRadio(this); } } function updCheckboxLabel(el){ el.parentElement.classList.toggle("checked_label"); var iconEl = el.parentElement.querySelector("i"), checked = "check_box", unchecked = "check_box_outline_blank", className = "icon_color"; iconEl.textContent = iconEl.textContent==checked?unchecked:checked; iconEl.classList.toggle(className); } function updRadio(el){ var els = document.querySelectorAll("input[type=radio]"), checked = "radio_button_checked", unchecked = "radio_button_unchecked"; for (var i = 0; i < els.length; i++) { var parentEl = els[i].parentElement; parentEl.querySelector("i").textContent = els[i]==el?checked:unchecked; if(els[i]==el) { parentEl.classList.add("checked_label"); parentEl.querySelector("i").classList.add("icon_color"); } else { parentEl.classList.remove("checked_label") parentEl.querySelector("i").classList.remove("icon_color"); } } } </script> </body>