@glu-dimaz

Кто может помочь с написанием скрипта для компоновки блоков в расписании занятий?

Приветствую. Написал верстку для расписания:
$body .= '
			<div class="lessons-per-group" id="mask-per-day">
				<div class="lessons-per-grid-day">
					<div class="lessons-per-time"></div>
					<div class="lessons-per-content">';
		
		$z = 2;

		foreach($lessons as $lesson){

			if(($lesson['time'] >= $time1) AND ($lesson['time'] <= $time2)){

				$top = ($lesson['time'] - $time1) / 1800 * 22;

				$height = $lesson['duration'] / 30 * 22;

				$time_end = $lesson['time'] + $lesson['duration'] * 60;

				$body .= '
					<div class="body-table-block-lesson" style="height:'.$height.'px; inset: '.$top.'px  0px 0px 0%;border-color:'.$_LTYPES[$lesson['type']]['color'].';z-index:'.$z.';width:'.$w.'%;" data-admin="'.$lesson['admin'].'" data-user="'.$lesson['user'].'" data-type="'.$lesson['type'].'" data-status="'.$lesson['status'].'" data-lessonid="'.$lesson['id'].'">
						<b>'.$_LTYPES[$lesson['type']]['title'].'</b> ('.date('H:i',$lesson['time']).' - '.date('H:i',$time_end).')
		            	'.$lsinfo.'
		            </div>';
			}
		}

		$body .= '</div>
				</div>';

с вот такими параметрами css:
.lessons-per-group{
	position: absolute;
	top: 0;
	width: 100%;
	bottom: 0;
	z-index: 1;
}
.lessons-per-grid-day{
	display: grid;
	grid-template-columns: 85px auto;
	padding-top: 35.5px;
	height: calc(100% - 35.5px);
}.body-table-block-lesson{
	position: absolute;
	border-width: 1px;
	padding: 1px;
	overflow: hidden;
	right: 0;
	border-bottom-width: 6px;
	box-sizing: border-box;
	border-style: solid;
	background-color: white;
	border-bottom-left-radius: 5px;
	font-size: 0.8em;
	cursor: pointer;
}

Соответственно, исходя из времени и длительности занятия выставляется высота и отступ блока. Но столкнулся с задачей, что в случае - когда в 1 час более 2-х занятий( а то их может быть и 6-7) - элементы попросту накладываются друг на друга. В итоге - в таблице виден только 1 элемент, который самый крайний из цикла.

Попробовал написать небольшой JS:
const elements = document.querySelectorAll('.body-table-block-lesson');

		let previousInsetValue = null;

		let y = 0;

		let z = 3;

		let sy = 0;

		elements.forEach((element, index) => {

			const insetValue = element.style.inset.split(' ')[0];

			if (index > 0) {

		        const previousElement = elements[index - 1];
		        const previousinsetValue = previousElement.style.inset.split(' ')[0];

		        if (insetValue == previousinsetValue) {

		        	y = y + 14;
		        	z++;

		        	if (y > 84) {

		        		y = 84;
		        		sy = insetValue + 10;

		        		element.style.inset = `${sy} 0px 0px ${y}%`;
			        	element.style.zIndex = z;

		        	} else {

		        		previousElement.style.width = (100 - y),'%';

			        	element.style.inset = `${insetValue} 0px 0px ${y}%`;
			        	element.style.zIndex = z;

			        	console.log('Current z:', z, 'Current y:', y);

		        	}

		        } else {

		        	y = 0;
		        	z = 3;

		        }

		    } else {

		    }

		});

Но, финальной картинкой, если честно не совсем удовлетворен. Если занятий более 3-4 штук - это выглядит еще приемлемо, но, например, когда их 2 - хотелось бы, чтобы они просто занимали 50% от ширины. Или если их 3 - то по 33.3%. Финал получился вот так:
66e91b140309f445128240.jpeg

Может кто работал с аналогами или знает какие-нибудь готовые решения - для организации нормальной структуры этих блоков?
  • Вопрос задан
  • 192 просмотра
Решения вопроса 1
IvanU7n
@IvanU7n
nothing interesting here
не понимаю зачем такие сложности, если теоретически можно заставить grid делать всё самостоятельно


понятно, этот пример ещё нужно доработать напильником, но основная мысль, думаю, ясна

если хочется страдать вручную, тогда крайне примерно алгоритм вижу так:
1) делаем ассоциативный массив, который будет содержать время => [ количество-блоков, есть-переходящие, ]
2) проходимся по всем блокам и заполняем массив, в том числе переходящими значениями, т.е. если блок с 10:00 до 11:30, а деление по полчаса, то прибавляем 1 к количество-блоков для 10:00, 10:30 и 11:00, а для 10:30 и 11:00 дополнительно ставим флаг есть-переходящие, возможно дополняя ссылками на данные блока для удобства дальнейшей работы
3) сортируем массив по ключам
4) (наверное самый сложный шаг) проходимся по массиву и берём максимальное значение количество-блоков в сериях !есть-переходящие, есть-переходящие... (т.е. это максимальное значение присваиваем всей серии)
5) окончательно проходимся по массиву и рисуем блоки опираясь на количество-блоков
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@glu-dimaz Автор вопроса
В общем, надоело, сделал все как говорил автор предыдущего ответа в самом 1 сообщение, только слегка доработал:
/// Уроки за день
					
$body .= '<table id="lessons-per-day">
			<tr style="border-top:none;">
				<td style="text-align:center;" colspan="500">
					'.date('d.m ',$time1).'<b>'.$_weekDN[date('w', $time1)]['title'].'</b>
				</td>
			</tr>';

for ($i = $time1; $i <= $time2; $i += 1800) {

	$d = date('Y-m-d-H-i', $i);
	$settime = date('H:i', $i);
	$st = explode(':',$settime);

	if ($st[1] == '30'){
		    	
		$body .= '<tr>';

	} else {

		$body .= '
			  <tr>
			        <td style="width:80px;padding:2px;border:1px solid #e7eaec;text-align:center;vertical-align:top;" rowspan="2">'.$settime.' </td>';

        }

	$body .= '<td style="border:1px solid #e7eaec;height:5px;"></td></tr>';
    
}

$body .= '</table>
		<div class="lessons-per-group" id="mask-per-day">
			<div class="lessons-per-grid-day">
				<div class="lessons-per-time"></div>
				<div class="lessons-per-content">';
		$z = 2;

		for ($i = $time1; $i <= $time2; $i += 1800) {

			$body .= '<div class="lessons-per-writes">';

			$d = date('Y-m-d-H-i', $i);

			if (isset($lessons[$d])) {

				foreach($lessons[$d] as $lesson){

					$z++;

					$height = $lesson['duration'] / 30 * 22;

					$time_end = $lesson['time'] + $lesson['duration'] * 60;

					$body .= '
						<div class="lessons-per-blocks">
							<div class="body-table-block-lesson" style="height:'.$height.'px;border-color:'.$_LTYPES[$lesson['type']]['color'].';z-index:'.$z.';" data-admin="'.$lesson['admin'].'" data-user="'.$lesson['user'].'" data-type="'.$lesson['type'].'" data-status="'.$lesson['status'].'" data-lessonid="'.$lesson['id'].'">

				            	<b>'.$_LSTATUSVG[$lesson['status']].' '.$_LTYPES[$lesson['type']]['title'].'</b> ('.date('H:i',$lesson['time']).' - '.date('H:i',$time_end).')
				            	'.$lsinfo.'
				            	</div>
		        		</div>';
				}

			}

			$body .= '</div>';

		}

		$body .= '</div>
				</div>
			</div>';


Вот такие стили:

.lessons-per-content{
 position: relative;
}
.lessons-per-writes{
 height: 22px;
 display: flex; 
    justify-content: space-between; 
}
.lessons-per-blocks{
 flex: 1;
 position: relative;
}
.body-table-block-lesson{
 position: absolute;
 width: 100%;
 border-width: 1px;
 padding: 1px;
 overflow: hidden;
 border-bottom-width: 6px;
 box-sizing: border-box;
 border-style: solid;
 background-color: white;
 border-bottom-left-radius: 5px;
 font-size: 0.8em;
}


Ну и финальная картина:
66ea7d2981c89791980311.png
Не пуля в пулю - но структура сохранилась. Предложу еще при наведении, поднимать z-index до 200, чтобы урок был выше остальных. Буду сдавать сегодня... надеюсь, удовлетворю заказчика.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы