Чтобы создать пользовательский элемент управления для лайтбокса, необходимо определить новый объект следующим образом:
gantt.form_blocks["my_editor"] = {
render: function(sns) { // sns - объект конфигурации секции
return "html код редактора здесь";
},
set_value: function(node, value, task, section) {
// node - HTML элемент, связанный с кодом выше
// value - значение из свойства map_to
// task - объект задачи
// section - объект конфигурации секции
... код для установки значения элемента ...
},
get_value: function(node, task, section) {
// node - HTML элемент, связанный с кодом выше
// task - объект задачи
// section - объект конфигурации секции
return "текущее значение из редактора";
},
focus: function(node) {
// node - HTML элемент, связанный с кодом выше
... код для установки фокуса на элемент ...
}
}
Важно избегать использования короткого синтаксиса закрытия тегов в HTML, возвращаемом функцией render
. Это может привести к проблемам с разбором в браузере:
// Избегайте этого
render: function() {
return "<div id='box'/>";
}
// Используйте это вместо
render: function() {
return "<div id='box'></div>"; // рекомендуется
}
Related sample: Custom control in the lightbox
Элементы управления лайтбоксом включают следующие типы:
Вот пример создания пользовательского редактора с двумя полями ввода:
gantt.form_blocks["my_editor"] = {
render: function (sns) {
return "<div class='dhx_cal_ltext' style='height:60px;'>"+
"Текст <input class='editor_description' type='text'>"+
"<br/>Держатели <input class='editor_holders' type='text'>"+
"</div>";
},
set_value: function (node, value, task) {
node.querySelector(".editor_description").value = value || "";
node.querySelector(".editor_holders").value = task.users || "";
},
get_value: function (node, task) {
task.users = node.querySelector(".editor_holders").value;
return node.querySelector(".editor_description").value;
},
focus: function (node) {
var a = node.querySelector(".editor_description");
a.select();
a.focus();
}
};
gantt.config.lightbox.sections = [
{ name:"description", height:200, map_to:"text", type:"my_editor", focus:true},
{ name:"time", height:72, type:"duration", map_to:"auto"}
];
Related sample: Custom control in the lightbox
Вы можете добавить элемент управления multiselect для выбора нескольких значений. Например, элемент управления на основе jQuery Chosen plugin может использоваться для назначения нескольких ресурсов задаче. Это отличается от стандартного ресурсного элемента управления Gantt, так как не обрабатывает количество ресурсов. Это более простой вариант для некоторых случаев использования.
Related sample: 3rd party multiselect control
Чтобы интегрировать элемент управления на основе jQuery Chosen в диаграмму Ганта:
<script
src="https://code.jquery.com/jquery-3.3.1.min.js?v=5.2.4"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.js?v=5.2.4"></script>
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.css?v=5.2.4">
gantt.form_blocks["multiselect"] = {
render: function (sns) {
var height = (sns.height || "23") + "px";
var html = "<div class='gantt_cal_ltext gantt_cal_chosen gantt_cal_multiselect'"+
"style='height:"+ height + ";'><select data-placeholder='...'"+
"class='chosen-select' multiple>";
if (sns.options) {
for (var i = 0; i < sns.options.length; i++) {
if(sns.unassigned_value !== undefined && sns.options[i].key==sns.unassigned_value){
continue;
}
html+="<option value='" +sns.options[i].key+ "'>"+sns.options[i].label+"</option>";
}
}
html += "</select></div>";
return html;
},
set_value: function (node, value, ev, sns) {
node.style.overflow = "visible";
node.parentNode.style.overflow = "visible";
node.style.display = "inline-block";
var select = $(node.firstChild);
if (value) {
value = (value + "").split(",");
select.val(value);
}
else {
select.val([]);
}
select.chosen();
if(sns.onchange){
select.change(function(){
sns.onchange.call(this);
})
}
select.trigger('chosen:updated');
select.trigger("change");
},
get_value: function (node, ev) {
var value = $(node.firstChild).val();
//value = value ? value.join(",") : null
return value;
},
focus: function (node) {
$(node.firstChild).focus();
}
};
gantt.config.lightbox.sections = [
{name:"description",height:38,map_to:"text",type:"textarea",focus: true},
{name:"owner",height:60, type:"multiselect", options:gantt.serverList("people"),
map_to:"owner_id", unassigned_value:5 },
{name: "time", type: "duration", map_to: "auto"}
];
Свойство unassigned_value скрывает ресурсы, которые не должны быть доступны для выбора. Установите id ресурса в качестве значения этого свойства. В приведенном выше примере ресурс с id=5 не будет отображаться в качестве опции.
Вы можете включить пользовательский datepicker в лайтбокс для установки длительности задачи путем выбора начальной и конечной дат.
Вот пример создания элемента управления Datepicker с использованием jQuery UI Datepicker.
Related sample: 3rd party Datepicker control
Чтобы интегрировать элемент управления jQuery Datepicker в диаграмму Ганта:
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css"
href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
(function () {
function startDatepicker(node){
return $(node).find("input[name='start']");
}
function endDateInput(node){
return $(node).find("input[name='end']");
}
gantt.form_blocks["datepicker"] = {
render: function (sns) { // sns - объект конфигурации секции
return "<div class='gantt-lb-datepicker'>"+
"<input type='text' name='start'>"+
"<input type='text' name='end'>"+
"</div>";;
},
set_value: function (node, value, task, section) {
// node - HTML элемент, связанный с кодом выше
// value - значение из свойства map_to
// task - объект задачи
// section - объект конфигурации секции
startDatepicker(node).datepicker({
dateFormat: "yy-mm-dd",
onSelect: function (dateStr) {
var endValue = endDateInput(node).datepicker('getDate');
var startValue = startDatepicker(node).datepicker('getDate');
if(startValue && endValue){
if(endValue.valueOf() <= startValue.valueOf()){
endDateInput(node).datepicker("setDate",
gantt.calculateEndDate({
start_date: startValue, duration: 1, task:task
})
);
}
}
}
});
startDatepicker(node).datepicker("setDate", task.start_date);
endDateInput(node).datepicker({
dateFormat: "yy-mm-dd",
onSelect: function (dateStr) {
// gantt.ext.inlineEditors.save()
}
});
endDateInput(node).datepicker("setDate", task.end_date);
},
get_value: function (node, task, section) {
if(task.start_date && task.end_date) {
var start = startDatepicker(node).datepicker('getDate');
var end = endDateInput(node).datepicker('getDate');
if(end.valueOf() <= start.valueOf()){
end = gantt.calculateEndDate({
start_date: start, duration: 1, task:task
});
}
task.start_date = start;
task.end_date = end;
}
task.duration = gantt.calculateDuration(task);
},
focus: function (node) {
}
}
})();
gantt.config.lightbox.sections = [
{ name: "description", height: 70, map_to: "text", type: "textarea", focus: true },
{ name: "time", height: 72, map_to: "auto", type: "datepicker" }
];
Вы можете интегрировать Bootstrap Datepicker в лайтбокс так же, как и jQuery Datepicker.
Related sample: Bootstrap Datepicker control
Чтобы включить элемент управления Bootstrap Datepicker в диаграмму Ганта:
Убедитесь, что добавили исходные файлы библиотеки Bootstrap на свою страницу.
Определите логику для элемента управления:
(function () {
const startDatepicker = (node) => $(node).find("input[name='start']");
const endDateInput = (node) => $(node).find("input[name='end']");
gantt.form_blocks["datepicker"] = {
render: (sns) => {
const height = sns.height || 45;
return "<div class='gantt-lb-datepicker' style='height:" + height + "px;'>"+
"<input type='text' name='start'> - "+
"<input type='text' name='end'>"+
"</div>";;
},
set_value: (node, value, task, section) => {
const datepickerConfig = {
format: 'yyyy-mm-dd',
autoclose: true,
container: gantt.$container
};
startDatepicker(node).datepicker(datepickerConfig);
startDatepicker(node).datepicker('setDate',
value ? value.start_date : task.start_date
);
endDateInput(node).datepicker(datepickerConfig);
endDateInput(node).datepicker('setDate',
value ? value.end_date : task.end_date
);
startDatepicker(node).datepicker().on('changeDate', function(e) {
const endValue = endDateInput(node).datepicker('getDate');
const startValue = startDatepicker(node).datepicker('getDate');
if (startValue && endValue) {
if (endValue.valueOf() <= startValue.valueOf()) {
endDateInput(node).datepicker('setDate',
gantt.calculateEndDate({
start_date: startValue, duration: 1, task:task
})
);
}
}
});
},
get_value: (node, task, section) => {
const start = startDatepicker(node).datepicker('getDate');
let end = endDateInput(node).datepicker('getDate');
if (end.valueOf() <= start.valueOf()) {
end = gantt.calculateEndDate({
start_date: start,
duration: 1,
task:task
});
}
if (task.start_date && task.end_date) {
task.start_date = start;
task.end_date = end;
}
task.duration = gantt.calculateDuration(task);
return {
start_date: start,
end_date: end,
duration: task.duration
};
},
focus: (node) => {
}
}
})();
type:"datepicker"
:gantt.config.lightbox.sections = [
{ name: "description", height: 70, map_to: "text", type: "textarea", focus: true },
{ name: "time", height: 45, map_to: "auto", type: "datepicker" }
];
Вы также можете добавить пользовательский контрол длительности в лайтбокс. Этот контрол позволяет установить начальную дату задачи и указать ее длительность в днях.
Related sample: 3rd party Duration control
Чтобы создать пользовательский контрол длительности с использованием jQuery:
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css"
href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
(function () {
function startDatepicker(node){
return $(node).find("input[name='start']");
}
function durationInput(node){
return $(node).find("input[name='duration']");
}
function endDateLabel(node){
return $(node).find("span.gantt-lb-datepicker-label");
}
var formatter = gantt.ext.formatters.durationFormatter({
enter: "day",
store: "day",
format: "auto"
});
gantt.form_blocks["datepicker_duration"] = {
render: function (sns) { //sns - объект конфигурации секции
return "<div class='gantt-lb-datepicker'>"+
"<label>Начало:<input type='text' name='start'></label>"+
"<label>Длительность: <input type='text' name='duration'></label>"+
"<span class='gantt-lb-datepicker-label'></span>"
"</div>";
},
set_value: function (node, value, task, section) {
//node - HTML объект, связанный с определенным выше HTML
//value - значение, определяемое свойством map_to
//task - объект задачи
//section- объект конфигурации секции
startDatepicker(node).datepicker({
dateFormat: "yy-mm-dd",
onSelect: function (dateStr) {
var endValue = durationInput(node).datepicker('getDate');
var startValue = startDatepicker(node).datepicker('getDate');
if(startValue && endValue){
if(endValue.valueOf() <= startValue.valueOf()){
durationInput(node).datepicker("setDate",
gantt.calculateEndDate({
start_date: startValue, duration: 1, task:task
})
);
}
}
}
});
startDatepicker(node).datepicker("setDate", task.start_date);
durationInput(node).val(formatter.format(task.duration));
endDateLabel(node).text(
"Конец: " + gantt.templates.task_date(task.end_date)
);
},
get_value: function (node, task, section) {
if(task.start_date && task.end_date) {
var start = startDatepicker(node).datepicker('getDate');
var end = task.end_date;
var duration = formatter.parse(durationInput(node).val());
if(duration && !isNaN(Number(duration))){
end = gantt.calculateEndDate({
start_date: start, duration: duration, task:task
});
}
task.start_date = start;
task.duration = duration;
task.end_date = end;
}
task.duration = gantt.calculateDuration(task);
return {
start_date: task.start_date,
end_date: task.end_date,
duration: task.duration
}
},
focus: function (node) {
}
}
})();
type:"datepicker_duration"
:gantt.config.lightbox.sections = [
{ name: "description", height: 70, map_to: "text", type: "textarea", focus: true },
{ name: "time", height: 72, map_to: "auto", type: "datepicker_duration" }
];
К началу