Таблица на связанных списках

26.08.2012
Связанные списки - это два или более списков, где выбор значения в одном из них влияет на содержание остальных. Например, в одном списке хранятся названия разделов каталога товаров, а в другом - названия товаров. Пользователь выбирает в первом списке раздел каталога (книги, DVD, компьютерные игры), а во втором списке отображаются товары, которые входят в выбранный раздел каталога. Эта связь похожа на связь между таблицами в базах данных. Для реализации таблицы на связанных списках необходимо осуществить синхронизацию данных по строкам. Рассмотрим простую таблицу со столбцами “Код”, ”Наименование” и “ Цена”. Необходимо сделать так, чтобы при выборе записи в любом списке выделялась вся строка. Для определения индекса выбранного элемента списка служит свойство selectedIndex. Значение этого свойства изменяется после отпускания кнопки мыши, что приводит к большим сложностям, так как в обычных таблицах выбор записи осуществляется при нажатии на кнопку мыши. То есть, подсветка выбранного элемента активного списка будет осуществляться при нажатии кнопки, а подсветка элементов неактивных списков - при отпускании кнопки, что ломает строку выделения. Что делать? Определить индекс выбранного элемента списка можно так:
  1. Получить относительную координату курсора мыши в области списка при помощи свойства layerY (для FF) или offsetY (для IE)
  2. Разделить полученную координату на высоту строки: (offsetHeight списка-толщина верхней и нижней рамок списка)/количество видимых строк в списке и округлить до целого значения
  3. Прибавить к полученному индексу величину прокрутки списка, полученную при помощи свойства scrollTop
К сожалению, Opera 12 не работает со свойством scrollTop для списка.
IE 9 поддерживает scrollTop, но неверно определяет выделенный индекс, если это свойство меняется программно для неактивного списка.
FireFox 14 и Chrome 21... с прокруткой работают адекватно, но в FireFox прокрутка осуществляется плавно, а в Chrom - дискретно по строкам.
То есть, только Chrome более или менее нормально может работать со связанными списками в этом плане.
Для адекватной работы таблицы при использовании мыши выход один - создать дополнительный список, который будет синхронизировать работу списков при прокрутке и задавать текущую выделенную строку. То есть, записи выбираются в этом дополнительном пустом списке. А события мыши для всех остальных списков блокируем.
Что касается работы клавиатуры, то с этим проблем нет.
Таблицу на связанных списках можно было бы создать быстро и легко, если бы все основные браузеры адекватно работали с прокруткой и индекс выбранного элемента списка определялся ещё и по нажатию кнопки мыши. Но приходится констатировать, что мы опять попали.
Пример реализации таблицы на связанных списках для экспериментов:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Документ без названия</title>
<script type="text/javascript">
var U_Scroll=0;
function AS_Scroll(A_Value)
{
document.getElementById("idSel_0").scrollTop=A_Value;
document.getElementById("idSel_1").scrollTop=A_Value;
document.getElementById("idSel_2").scrollTop=A_Value;
document.getElementById("idSel_3").scrollTop=A_Value;
U_Scroll=A_Value;
}
function AS_Change(A_Id,event)
{
var L_Index;
var L_Src;
if (window.event)
event=window.event;
L_Src=A_Id.split("_");
L_Index=document.getElementById("idSel_"+L_Src[1]).selectedIndex;
for (var L_i=0;L_i<4;L_i++)
document.getElementById("idSel_"+L_i).selectedIndex=L_Index;
}
function AS_BlockScroll(e)
{
e.preventDefault();
}
function AS_Block(e)
{
e.stopPropagation();
e.preventDefault();
}
</script>
<style type="text/css">
body {
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
}
.cl_div{float:left;overflow:hidden;}
.cl_sel{font:10pt arial;}
input, textarea {
outline: none;
}
input:active, textarea:active {
outline: none;
}
:focus {
outline: none;
}
</style>
</head>
<body>
<div class="cl_div" style="width:45px;">
<select class="cl_sel" size="5" id="idSel_0" style="width:70px;" onchange="AS_Change(this.id,event)" onmousedown="return false;" onmousewheel="return false;">
<option selected="selected">Код1</option>
<option>Код2</option>
<option>Код3</option>
<option>Код4</option>
<option>Код5</option>
<option>Код6</option>
<option>Код7</option>
<option>Код8</option>
<option>Код9</option>
<option>Код10</option>
<option>Код11</option>
</select>
</div>
<div class="cl_div" style="width:174px;">
<select class="cl_sel" id="idSel_1" size="5" style="width:200px;" onchange="AS_Change(this.id,event)" onmousedown="return false;" onmousewheel="return false;">
<option selected="selected">Товар_1</option>
<option>Товар_2</option>
<option>Товар_3</option>
<option>Товар_4</option>
<option>Товар_5</option>
<option>Товар_6</option>
<option>Товар_7</option>
<option>Товар_8</option>
<option>Товар_9</option>
<option>Товар_10</option>
<option>Товар_11</option>
</select>
</div>
<div class="cl_div" style="width:65px;">
<select class="cl_sel" id="idSel_2" size="5" style="width:90px;" onchange="AS_Change(this.id,event)" onmousedown="return false;" onmousewheel="return false;">
<option selected="selected">Цена_1</option>
<option>Цена_2</option>
<option>Цена_3</option>
<option>Цена_4</option>
<option>Цена_5</option>
<option>Цена_6</option>
<option>Цена_7</option>
<option>Цена_8</option>
<option>Цена_9</option>
<option>Цена_10</option>
<option>Цена_11</option>
</select>
</div>
<div class="cl_div" style="width:41px;">
<select class="cl_sel" id="idSel_3" size="5" style="width:41px;" onscroll="AS_Scroll(this.scrollTop);" onchange="AS_Change(this.id,event)">
<option selected="selected">&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
<option>&nbsp;</option>
</select>
</div>
<script>
document.getElementById("idSel_0").addEventListener('mouseup', AS_Block, false);
document.getElementById("idSel_1").addEventListener('mouseup', AS_Block, false);
document.getElementById("idSel_2").addEventListener('mouseup', AS_Block, false);
document.getElementById("idSel_0").addEventListener('mousedown', AS_Block, true);
document.getElementById("idSel_1").addEventListener('mousedown', AS_Block, true);
document.getElementById("idSel_2").addEventListener('mousedown', AS_Block, true);
document.getElementById("idSel_0").addEventListener('DOMMouseScroll', AS_BlockScroll, false);
document.getElementById("idSel_1").addEventListener('DOMMouseScroll', AS_BlockScroll, false);
document.getElementById("idSel_2").addEventListener('DOMMouseScroll', AS_BlockScroll, false);
</script>
</body>
</html>
Оглавление
Copyright © 2016