Available only in PRO Edition
Данный вид доступен только в версии Scheduler PRO.
Вид Timeline отображает события по горизонтали, организуя отдельные временные линии (таймлайны) бок о бок слева направо.
Чтобы добавить вид Timeline в планировщик, выполните следующие шаги:
scheduler.plugins({
timeline: true,
treetimeline: true,
daytimeline: true
});
<div id="scheduler_here" class="dhx_cal_container" ...>
<div class="dhx_cal_navline">
...
<div class="dhx_cal_tab" name="timeline_tab" style="right:280px;"></div>
</div>
...
</div>
//'timeline_tab' соответствует имени нашего div
scheduler.locale.labels.timeline_tab ="Timeline";
scheduler.createTimelineView({
name:"timeline",
x_unit:"minute", // единица измерения по оси X
x_date:"%H:%i", // формат даты на оси X
x_step:30, // шаг на оси X в 'x_unit'
x_size:24, // общее количество шагов 'x_step' на оси X
x_start:16, // смещение по оси X в 'x_unit'
x_length:48, // количество шагов 'x_step' для прокрутки за раз
y_unit: // секции, отображаемые по оси Y
[{key:1, label:"Section A"},
{key:2, label:"Section B"},
{key:3, label:"Section C"},
{key:4, label:"Section D"}],
y_property:"section_id", // свойство для сопоставления данных с секциями
render:"bar" // режим отображения
});
При использовании режима 'Days' временная шкала должна охватывать ровно один день. Если в конфигурации указана более короткая или длинная длительность, таймлайн будет отображаться некорректно.
Хотя метод createTimelineView включает множество параметров, его использование довольно просто.
Пример: временная шкала с 09:00 до 15:00 с шагом 30 минут и прокруткой по дням.
{
x_unit:"minute",// единицы шкалы — минуты
x_step:30, // шаг 30 минут, например, 09:00 - 09:30
x_size:12, // количество 30-минутных интервалов между 09:00 и 15:00
// 15 - 9 = 6 часов = 360 минут = 360/30 = 12
x_start:18, // шкала начинается с 09:00, это 9 часов от 00:00
// 9 часов = 540 минут = 540/30 = 18 шагов 'x_step'
x_length:48,// прокрутка на один день: 1 день = 24 часа = 1440 минут = 1440/30 = 48 шагов 'x_step'
...
}
Все функции-шаблоны с именами, содержащими {timeline}_some, должны определяться после создания вида, так как они динамически назначаются конструктором таймлайна и будут перезаписаны вызовом createTimelineView.
Например, вот как установить начальную дату для вида Timeline.
Начальная дата любого вида управляется функцией scheduler.date[
// неделя начинается с понедельника
scheduler.config.start_on_monday = true;
// создаём таймлайн
scheduler.createTimelineView({
name: "timeline",
render: "tree",
days: 7,
folder_dy: 20,
x_unit: "day",
x_date: "%D %j %F",
x_step: 1,
x_size: 7,
x_start: 0,
x_length: 7,
y_unit:[],
y_property: "section_id"
});
// переопределяем функцию начальной даты после создания
scheduler.date.timeline_start = scheduler.date.week_start;
// инициализируем планировщик
scheduler.init("timeline_tree", new Date(), "timeline");
Существует несколько методов для взаимодействия с видом Timeline.
Для начала создайте экземпляр таймлайна в планировщике:
scheduler.createTimelineView({
name:'timeline',
...
});
var timeline = scheduler.matrix.timeline;
После создания можно использовать приведённые ниже методы.
Чтобы получить объект таймлайна, используйте метод getView. Он принимает имя вида в качестве параметра. Если параметр не передан, возвращается текущий вид.
var timeline = scheduler.getView();
timeline.x_size = 8;
scheduler.setCurrentView();
Для задания диапазона шкалы используйте метод setRange(). Требуется два параметра:
timeline.setRange(startDate, endDate);
Содержимое левой панели можно задать двумя способами.
По умолчанию она содержит одну колонку. Подписи секций берутся из свойства label объекта y_unit, который можно настроить с помощью шаблона timeline_scale_label.
Чтобы определить несколько колонок, используйте свойство columns в методе createTimelineView:
scheduler.createTimelineView({
name: "timeline",
x_unit: "minute",
x_date: "%H:%i",
x_step: 30,
x_size: 24,
x_start: 16,
x_length: 48,
y_unit: sections,
event_dy: "full",
y_property: "section_id",
render:"bar",
columns: [
{ label: "Room #", width: 70, template: function(obj){ return obj.room_no; } },
{ label: "Type", width: 90, template: function(obj){ return obj.room_type; } },
{ label: "Status", width: 90, template: function(obj){ return obj.room_status; } }
]
});
Каждый объект колонки может иметь следующие свойства:
string
- необязательная подпись заголовкаnumber
- необязательная ширина колонкиfunction
- шаблон ячейки, получает объект секцииRelated sample: Timeline Sidebar columns
Эта функциональность работает только при включённой горизонтальной прокрутке Timeline.
Для прокрутки к определённой точке используйте метод scrollTo(). Поддерживаются различные типы параметров:
timeline.scrollTo(new Date());
timeline.scrollTo(500);
timeline.scrollTo({date:new Date(), section:4});
timeline.scrollTo({left:300, top:500});
var left = timeline.posFromDate(new Date());
Этот метод возвращает 0 или максимальную X-координату, если дата вне шкалы.
var top = timeline.getSectionTop(section.key);
Возвращает -1, если строка не найдена.
{left: number, top: number}
:const position = timeline.resolvePosition({top: 120, left: 400});
Date
по определённой координате left
на временной шкале используйте dateFromPos():const date = timeline.dateFromPos(300);
top
определённого события используйте getEventTop() с объектом события:const top = timeline.getEventTop(scheduler.getEvent(event.id));
Чтобы узнать текущую позицию скроллбара, вызовите timeline.getScrollPosition(), который возвращает объект с координатами прокрутки:
var timeline = scheduler.getView();
timeline.getScrollPosition(); // { left: 0, top: 0 }
Возвращаемый объект содержит:
Также можно отслеживать изменения скролла через событие onScroll, которое получает новые значения left и top:
var timeline = scheduler.getView();
timeline.attachEvent("onScroll", function(left, top){});
Чтобы получить массив событий, назначенных определённой секции, используйте timeline.selectEvents() с объектом конфигурации:
{
section: string|number,
date: Date,
selectNested: boolean
}
где:
Метод возвращает массив объектов событий.
var timeline = scheduler.getView();
var events = timeline.selectEvents({
section: section.key,
date: date,
selectNested: true
});
Все объекты таймлайна хранятся в объекте scheduler.matrix. Вы можете получить доступ к любому виду таймлайна по имени и обновить его свойства. Изменения вступают в силу после обновления планировщика:
scheduler.getView('timeline').x_size = 12;
scheduler.setCurrentView(); // перерисовывает планировщик
Здесь 'timeline' соответствует имени, заданному в методе createTimelineView:
scheduler.createTimelineView({
name:'timeline',
...
});
Когда возникает необходимость обновить список ресурсов в представлении Timeline на лету, рекомендуется использовать методы serverList и updateCollection.
В отличие от более простых представлений, таких как День, Месяц или Год, многоресурсные представления, такие как Units и Timeline, требуют наличия в каждом элементе данных дополнительного обязательного поля:
scheduler.createTimelineView({
name:"timeline",
...
y_unit:
[{key:1, label:"Room 1"},
{key:2, label:"Room 2"},
{key:3, label:"Room 3"}],
y_property:"room_id",
});
scheduler.init('scheduler_here');
scheduler.parse([
{text:"Conference", start_date:"17/09/2012 12:00", end_date:"18/09/2012 21:00",
room_id:"1"},
{text:"Meeting", start_date:"17/09/2012 09:00", end_date:"17/09/2012 21:00",
room_id:"2"},
{text:"Conference", start_date:"17/09/2012 15:00", end_date:"18/09/2012 15:00",
room_id:"3"}
]);
Планировщик поддерживает назначение событий сразу нескольким секциям.
Чтобы включить эту возможность:
<script src="codebase/dhtmlxscheduler.js"></script>
<link rel="stylesheet" href="codebase/dhtmlxscheduler.css" type="text/css">
<script> scheduler.plugins({
multisection: true, multiselect: true,
timeline: true
});
scheduler.config.multisection = true; scheduler.init('scheduler_here');
</script>
После настройки вы можете перечислить несколько секций (по умолчанию, разделённых запятыми, как указано в section_delimiter) в соответствующем свойстве данных события, и событие будет отображаться во всех этих секциях:
scheduler.createTimelineView({
name: "timeline",
y_unit: [
{key: 1, label: "James Smith"},
{key: 2, label: "John Williams"},
{key: 3, label: "David Miller"},
{key: 4, label: "Linda Brown"}],
y_property: "section_id", ...
});
scheduler.init('scheduler_here', new Date(2012, 5, 30), "timeline");
scheduler.parse([
{ id:1, text:"Task A", section_id:'1', ...}, { id:2, text:"Task B", section_id:'1,3', ...}, { id:3, text:"Task C", section_id:'4', ...}, { id:4, text:"Task D", section_id:'2,3,4', ...}]);
Related sample: Multisection events in Timeline and Units view
В представлении Timeline доступны четыре режима:
Желаемый режим можно выбрать с помощью параметра render:
scheduler.createTimelineView({
name: "timeline",
render: "bar"
});
При использовании режима Days учитывайте следующее:
scheduler.createTimelineView({
name:"timeline",
render:"days",
days:7,
// шкала времени настроена на 1 день x_unit:"minute", x_date:"%H:%i", x_step:30, x_size:24, x_start:16 });
scheduler.templates.timeline_scale_label = function(key, label, section){
// используются те же подписи, что и в представлении Day
return scheduler.templates.day_date(label);
};
scheduler.date.timeline_start = function (date) {
date = scheduler.date.week_start(date);
date = scheduler.date.add(date, config.x_step*config.x_start, config.x_unit);
return date;
};
По умолчанию каждая ячейка охватывает интервал в один день, и события располагаются соответственно. Чтобы изменить этот интервал, например, чтобы сосредоточиться на рабочих часах и исключить менее актуальное время, можно воспользоваться одним из следующих способов:
// интервал ячейки ограничен днем с 10:00 до 18:00
scheduler.createTimelineView({
name:"timeline",
first_hour:10,
last_hour:18
});
Related sample: Changing the time interval for the view cells
// интервал ячейки ограничен днем с 10:00 до 18:00
scheduler.ignore_timeline = function(date){ // "timeline" — имя представления
// исключить нерабочие часы
if (date.getHours() < 10 || date.getHours() > 18) return true;
};
Подробнее о методе ignore_{viewName} см. в разделе Скрытие единиц времени на оси X в представлении.
Related sample: Hiding hours in the scale of Timeline view
Имейте в виду, что игнорируемый интервал не может быть равен или больше общего интервала, установленного для timeline.
Например, если timeline охватывает полный день и вы попытаетесь исключить весь день через функцию ignore_{viewName}, это не даст ожидаемого эффекта. Планировщик всё равно отобразит этот день, но без шкалы и событий.
Чтобы полностью исключить такие интервалы, необходимо динамически изменять настройку x_length внутри функции scheduler._click.dhx_cal_next_button. Например, чтобы полностью исключить выходные из timeline, используйте следующий подход:
scheduler._click.dhx_cal_next_button = function(dummy,step){
var mode = scheduler.getState().mode;
var minDate = scheduler.getState().min_date;
var formFunc = scheduler.date.date_to_str("%D");
// пропустить выходные
if(mode=='timeline'){
if((formFunc(minDate)=='Fri' && step!=-1) || (formFunc(minDate)=='Mon' && step==-1))
scheduler.matrix['timeline'].x_length = 24*3;
else
scheduler.matrix['timeline'].x_length = 24;
}
scheduler.setCurrentView(scheduler.date.add(
scheduler.date[scheduler._mode+"_start"](scheduler._date),(step||1),scheduler._mode));
};
Related sample: Игнорирование выходных
Для указания значений Y-оси в режимах 'Bar' и 'Cell' используйте параметр y_unit:
scheduler.createTimelineView({
name:"timeline",
...
y_unit:[
{key:1, label:"James Smith"},
{key:2, label:"John Williams"},
{key:3, label:"David Miller"},
{key:4, label:"Linda Brown"}
]
});
Каждый элемент y_unit должен содержать два обязательных свойства:
Режим 'Tree' позволяет группировать элементы в многоуровневые папки, что не только улучшает организацию, но и позволяет назначать события на целые папки на любом уровне иерархии.
Для настройки 'Tree' timeline используйте тот же параметр y_unit, что и в режимах 'Bar' и 'Cell', но с дополнительными свойствами:
scheduler.createTimelineView({
name: "timeline",
render:"tree",
...
y_unit:[
{key:"production", label:"Production Department", children:[
{key:"p1", label:"Managers", children:[
{key:"pm1", label:"John Williams"},
{key:"pm2", label:"David Miller"}
]},
{key:"p2", label:"Linda Brown"},
{key:"p3", label:"George Lucas"}
]},
{key:"sales", label:"Sales and Marketing", children:[
{key:"s1", label:"Kate Moss"},
{key:"s2", label:"Dian Fossey"}
]}
]
});
Элементы y_unit включают:
Для режима 'Days' укажите количество дней на Y-оси с помощью параметра days:
scheduler.createTimelineView({
name:"timeline",
...
days:7 // количество дней на Y-оси
});
Для загрузки секций Y-оси с сервера используйте:
scheduler.createTimelineView({
name:"timeline",
...
y_unit:scheduler.serverList("sections"),
});
Здесь serverList получает список опций с именем 'sections'.
Ответ для метода load должен включать коллекцию с именем server list в формате JSON, как описано в Примеры форматов данных.
Также можно использовать коннектор OptionsConnector:
<?php
include('connector-php/codebase/scheduler_connector.php');// подключение файла
$res=mysql_connect("localhost","root","");// подключение к серверу БД
mysql_select_db("sampleDB");// выбор БД
$list = new OptionsConnector($res, $dbtype);
$list->render_table("types","type_id","type_id(value),name(label)");
$scheduler = new schedulerConnector($res, $dbtype);
// задаём то же имя, что и на клиенте — 'sections'
$scheduler->set_options("sections", $list);
$scheduler->render_table("events","id","start_date,end_date,text,type_id");
?>
Ответ должен соответствовать формату JSON и включать объект "collections" с необходимыми коллекциями, на которые ссылается serverList.
Можно также создавать коллекции вручную без использования dhtmlxConnector. В этом случае для обновления коллекции используйте метод updateCollection:
scheduler.updateCollection("sections", new_sections_array);
Related sample: Loading Units sections from the server
Для динамического добавления или удаления секций доступны методы:
scheduler.createTimelineView({
name: "timeline",
render:"tree",
...
y_unit:[
{key:"production", label:"Production Department", children:[
{key:"p1", label:"Managers", children:[
{key:"pm1", label:"John Williams"},
{key:"pm2", label:"David Miller"}
]},
{key:"p2", label:"Linda Brown"},
{key:"p3", label:"George Lucas"}
]},
{key:"sales", label:"Sales and Marketing", children:[
{key:"s1", label:"Kate Moss"},
{key:"s2", label:"Dian Fossey"}
]}
]
});
scheduler.addSection( {key:"pm3", label:"James Smith"}, "p1");
scheduler.addSection( {key:"s3", label:"Alex White"}, "sales");
scheduler.deleteSection("p3");
Методы addSection и deleteSection требуют активного режима 'Tree' в timeline.
Верхнюю часть основной оси времени можно дополнительно сгруппировать, добавив вторую ось X.
Для добавления второй шкалы используйте параметр second_scale:
scheduler.createTimelineView({
name: "timeline",
...
second_scale:{
x_unit: "day", // единица измерения оси (по умолчанию 'minute')
x_date: "%F %d" // формат даты ("July 01")
}
});
Related sample: Second time scale (X-Axis)
Чтобы событие занимало всю ширину ячейки вне зависимости от своей длительности, включите параметр round_position:
scheduler.createTimelineView({
name:"timeline",
render:"bar",
...
round_position:true
});
С round_position:false (по умолчанию):
С round_position:true:
По умолчанию события в Timeline сортируются по дате начала. Чтобы применить свою логику сортировки, передайте функцию в параметр sort.
Эта функция получает пару соседних событий и возвращает:
Сортировка по длине текста
scheduler.createTimelineView({
name: "timeline",
render:"bar",
...
sort:function(a, b){
if (a.text.length > b.text.length) {
// a идёт перед b
return -1;
} else if(a.text.length < b.text.length) {
return 1;
} else{
return +a.start_date > +b.start_date ? 1 : -1;
}
}
});
В Timeline поддерживается горизонтальная прокрутка для навигации по дням, неделям или месяцам без использования кнопок навигации.
Чтобы включить горизонтальный скроллинг, задайте свойство scrollable в методе createTimelineView. Также можно настроить column_width и scroll_position как показано ниже:
scheduler.createTimelineView({
name: "timeline",
x_unit: "minute",
x_date: "%H:%i",
x_step: 30,
x_size: 24*7,
x_start: 16,
x_length: 48,
y_unit: sections,
y_property: "section_id",
render: "bar",
scrollable: true, column_width: 70, scroll_position:new Date(2018, 0, 15) });
timeline.scrollTo()
.В режиме scrollable в Timeline по умолчанию включён smart rendering. Это оптимизирует производительность за счёт отрисовки только видимых строк, колонок и событий, остальные подгружаются по мере прокрутки.
Related sample: Horizontal scroll for Timeline view
Имейте в виду, что прокрутка timeline не бесконечна, диапазон времени ограничен. Для перехода между интервалами времени всё равно нужны элементы навигации.
Автоскролл активируется по умолчанию при перемещении или изменении размера события возле краёв видимой области timeline.
Вы можете настроить чувствительность и скорость автоскролла через объект autoscroll внутри метода createTimelineView:
scheduler.createTimelineView({
name:"timeline",
...
autoscroll: { range_x: 200, range_y: 100, speed_x: 20, speed_y: 10 } });
По умолчанию заголовок над колонкой секций пустой. Добавить метку можно через объект locale следующим образом:
scheduler.locale.labels.<timelineName>_scale_header = "Label";
Замените
scheduler.locale.labels.timeline_scale_header = "Users";
Возможно отображение собственного контента внутри ячеек Timeline, не только в режиме Cell, как показано в этом примере:
Также можно определить шаблон для содержимого ячеек во всех режимах Timeline.
Related sample: Display labels in timeline cells
Чтобы включить эту возможность для конкретного timeline, задайте свойство cell_template при создании timeline через createTimelineView:
scheduler.createTimelineView({
cell_template: true,
...
});
После этого будет вызван указанный шаблон. Например, следующий пример показывает количество событий на дату в режиме "tree":
<style>
.dhx_matrix_cell div.load-marker{
position: absolute;
width: 40%;
height: 25px;
transform: translate(70%, 20%);
line-height: 25px;
text-align: center;
border-radius: 7px;
color: white;
}
.load-marker-no{
background: #e0e0e0;
}
.load-marker-light{
background: #aed581;
}
.load-marker-high{
background: #ff8a65;
}
</style>
scheduler.templates.timeline_cell_value = function (evs, date, section){
if(section.children){
var timeline = scheduler.getView();
var events = timeline.selectEvents({
section: section.key,
date: date,
selectNested: true
});
var className = "";
if(!events.length){
className = "load-marker-no";
}else if(events.length < 3){
className = "load-marker-light";
}else{
className = "load-marker-high";
}
return "<div class='load-marker "+className+"'>"+
events.length
+"</div>";
}
return "";
};
Related sample: Display labels in timeline cells
По умолчанию высота секций и событий задаётся настройками dy и event_dy в createTimelineView.
Если объект секции содержит свойство height, его значение переопределит настройку dy:
scheduler.createTimelineView({
name: "timeline",
...
y_unit: [
{key: 1, label: "Room 1", height: 60},
{key: 2, label: "Room 2", height: 60},
{key: 3, label: "Room 3", height: 120},
{key: 4, label: "Room 4", height: 900},
],
Также можно динамически изменять свойство height после инициализации планировщика.
Related sample: Collapse timeline rows