Расписание мероприятий для сайта на jQuery

Простой шаблон, который позволяет отображать события на временной шкале, а также организовывать их группами (дни недели, конференц-залы и т. Д.).

 

ДЕМО
ИСХОДНИКИ

 

Мы часто сталкивались с этим веб-компонентом: когда мы проверяем график конференции или расписание занятий в нашем спортзале. С точки зрения веб-дизайнера, удобно использовать простой, отзывчивый шаблон, если вам нужно создать таблицу расписания. Итак, мы построили один!

 

Создание структуры

Структура HTML состоит из трех различных элементов: div.timeline для временной шкалы событий (09:00, 09:30, ..), div.events, которая включает список событий и div.event-modal для модального окна Используется для предоставления более подробной информации о выбранном событии.

<div class="cd-schedule">
<div class="timeline">
<ul>
<li><span>09:00</span></li>
<li><span>09:30</span></li>
<!-- additional elements here -->
</ul>
</div>

<div class="events">
<ul>
<li class="events-group">
<div class="top-info"><span>Monday</span></div>

<ul>
<li class="single-event" data-start="09:30" data-end="10:30" data-content="event-abs-circuit" data-event="event-1">
<a href="#0">
<em class="event-name">Abs Circuit</em>
</a>
</li>

<!-- other events here -->
</ul>
</li>

<li class="events-group">
<div class="top-info"><span>Tuesday</span></div>

<ul>
<!-- events here -->
</ul>
</li>

<!-- additional li.events-group here -->
</ul>
</div>

<div class="event-modal">
<header class="header">
<div class="content">
<span class="event-date"></span>
<h3 class="event-name"></h3>
</div>

<div class="header-bg"></div>
</header>

<div class="body">
<div class="event-info"></div>
<div class="body-bg"></div>
</div>

<a href="#0" class="close">Close</a>
</div>
</div>

 

Добавление стиля

На небольших устройствах (ширина окна меньше 800 пикселей) все события внутри .events-group выстраиваются горизонтально: мы устанавливаем display: flex в элемент .events-group > ul и overflow-x: scroll, чтобы события прокручивались.

.cd-schedule .events .events-group > ul {
  position: relative;
  padding: 0 5%;
  /* force its children to stay on one line */
  display: flex;
  overflow-x: scroll;
  -webkit-overflow-scrolling: touch;
}
 
.cd-schedule .events .single-event {
  /* force them to stay on one line */
  flex-shrink: 0;
  float: left;
  height: 150px;
  width: 70%;
  max-width: 300px;
}

Что касается мода .event-modal, он имеет фиксированное положение и перемещается вправо вне окна просмотра. Когда пользователь выбирает событие, класс .modal-is-open используется для перевода .event-modal обратно в область просмотра.

.cd-schedule .event-modal {
  position: fixed;
  z-index: 3;
  top: 0;
  right: 0;
  height: 100%;
  width: 100%;
  visibility: hidden;
  transform: translateX(100%);
  transition: transform .4s, visibility .4s;
}
 
.cd-schedule.modal-is-open .event-modal {
  /* .modal-is-open class is added as soon as an event is selected */
  transform: translateX(0);
  visibility: visible;
}

На больших устройствах все события находятся в абсолютном положении и помещаются в расписание: верхнее положение и высота каждого события оцениваются с использованием атрибутов data-start и data-end самого события и задаются с использованием JavaScript (больше в Раздел обработки событий).

@media only screen and (min-width: 800px) {
  .cd-schedule .events {
    float: left;
    width: 100%;
  }
  .cd-schedule .events .events-group {
    width: 20%;
    float: left;
  }
  .cd-schedule .events .single-event {
    position: absolute;
    z-index: 3;
    /* top position and height will be set using js */
    width: calc(100% + 2px);
    left: -1px;
  }
}

Что касается .event-modal, анимация открытия / закрытия создается с использованием jQuery в сочетании с переходами и преобразованиями CSS (подробнее в разделе Обработка событий).

 

Обработка событий

Чтобы реализовать это расписание событий, мы создали объект SchedulePlan и использовали функции scheduleReset() и initEvents(), чтобы запустить расписание и присоединить обработчики событий к соответствующим элементам.

function SchedulePlan( element ) {
  this.element = element;
  this.timeline = this.element.find('.timeline');
  //...
  
  this.eventsWrapper = this.element.find('.events');
  this.eventsGroup = this.eventsWrapper.find('.events-group');
  this.singleEvents = this.eventsGroup.find('.single-event');
  //..
 
  this.scheduleReset();
  this.initEvents();
}

На больших устройствах метод scheduleReset() позволяет размещать события внутри расписания и устанавливать их высоту. Например, для оценки высоты мы вычисляем продолжительность события (конец-минус данных), делим его на «eventUnit» (в нашем случае это 30 минут), а затем умножаем его на высоту «временной шкалы» Единица (в нашем случае 50 пикселей).

var self = this;
this.singleEvents.each(function(){
  //place each event in the grid -> need to set top position and height
  var start = getScheduleTimestamp($(this).attr('data-start')), //getScheduleTimestamp converts hh:mm to timestamp
    duration = getScheduleTimestamp($(this).attr('data-end')) - start;
 
  var eventTop = self.eventUnitHeight*(start - self.timelineStart)/self.timelineUnitDuration,
    eventHeight = self.eventUnitHeight*duration/self.timelineUnitDuration;
  
  $(this).css({
    top: (eventTop -1) +'px',
    height: (eventHeight+1)+'px'
  });
});

Когда пользователь выбирает событие, функция load() jQuery используется для загрузки содержимого только что выбранного события (data-content используется для определения загружаемого содержимого файла).
В дополнение к этому, на больших устройствах .event-modal анимируется, чтобы показать содержимое события. Во-первых, .event-modal помещается поверх выбранного события, а его высота и ширина изменяются так, чтобы они были равны единицам выбранного события; То элементы .header-bg и .body-bg масштабируются для создания анимации морфинга; В конце этой анимации обнаруживается модальный контент.

SchedulePlan.prototype.openModal = function(event) {
	var self = this;
	var mq = self.mq();
	this.animating = true;
 
	//update event name and time
	this.modalHeader.find('.event-name').text(event.find('.event-name').text());
	this.modalHeader.find('.event-date').text(event.find('.event-date').text());
	this.modal.attr('data-event', event.parent().attr('data-event'));
 
	//update event content
	this.modalBody.find('.event-info').load(event.parent().attr('data-content')+'.html .event-info > *', function(data){
		//once the event content has been loaded
		self.element.addClass('content-loaded');
	});
 
	this.element.addClass('modal-is-open');
 
	if( mq == 'mobile' ) {
		self.modal.one(transitionEnd, function(){
			self.modal.off(transitionEnd);
			self.animating = false;
		});
	} else {
		//change modal height/width and translate it
		self.modal.css({
			top: eventTop+'px', //this is the selected event top position
			left: eventLeft+'px', //this is the selected event left position
			height: modalHeight+'px', //this is the modal final height
			width: modalWidth+'px', //this is the modal final width
		});
		transformElement(self.modal, 'translateY('+modalTranslateY+'px) translateX('+modalTranslateX+'px)');
 
		//set modalHeader width
		self.modalHeader.css({
			width: eventWidth+'px',  //this is the selected event width
		});
		//set modalBody left margin
		self.modalBody.css({
			marginLeft: eventWidth+'px',
		});
 
		//change modalBodyBg height/width and scale it
		self.modalBodyBg.css({
			height: eventHeight+'px',
			width: '1px',
		});
		transformElement(self.modalBodyBg, 'scaleY('+HeaderBgScaleY+') scaleX('+BodyBgScaleX+')');
 
		//change modal modalHeaderBg height/width and scale it
		self.modalHeaderBg.css({
			height: eventHeight+'px',
			width: eventWidth+'px',
		});
		transformElement(self.modalHeaderBg, 'scaleY('+HeaderBgScaleY+')');
		
		self.modalHeaderBg.one(transitionEnd, function(){
			//wait for the  end of the modalHeaderBg transformation and show the modal content
			self.modalHeaderBg.off(transitionEnd);
			self.animating = false;
			self.element.addClass('animation-completed');
		});
	}
};

Примечание:

Мы выполнили простую функцию load(), чтобы загрузить новый html-контент, но вы можете заменить его вызовом $.ajax, чтобы обрабатывать ошибки, запрос sendSend и т. Д. В соответствии с вашим проектом.

 

Вот и всё!


Top

🔖 Выбор по тегам ×

💌 Написать сообщение ×

Все поля обязательны для заполнения!