Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Как получить предыдущую ячейку при rowspan? (https://javascript.ru/forum/events/29709-kak-poluchit-predydushhuyu-yachejjku-pri-rowspan.html)

Cepin 08.07.2012 10:14

Как получить предыдущую ячейку при rowspan?
 
Есть огромная таблица с данными, в которой частенько встречаются ячейки со атрибутами rowspan и colspan.
Дана определенная ячейка из таблицы и нужно найти содержимое ее соседей (слева и справа).


Вот набросал мини-пример:
http://jsfiddle.net/zj7RU/

Вот таблица. Задача получить содержимое соседа слева(ячейка с номером 0) от ячейки с номером 5.


Как костыльный вариант использую следующую схему:
1) Создаю копию таблицы, где разворачиваю все colspan и rowspan (бью на ячейки с копированием содержимым)
2) Осуществляю переходы используя rowIndex и cellIndex

Вариант рабочий, но жутко тормозит на больших таблицах. Хотелось бы без глобального перебора.

Aetae 08.07.2012 10:46

Хитро.
Пока на ум приходит только построение виртуальной модели таблицы при загрузке и навигация уже по оной.

lord2kim 08.07.2012 11:00

а если nextSibling и previousSibling заюзать если известна требуемая (а она известна?)

Deff 08.07.2012 12:44

Cepin,
1.Проставить в каждой ячейке свой индивидуальный класс
2. сделать первичный обход таблицы по строкам - добавить класс предыдущей ячейки к следущей(для добавления фиксируем ток первый класс в списке
3. Аналогичный обход сделать по столбцам и тоже добавлять только первый текущий класс в списке к последующей ячейке

4. При выборе данной ячейки -ищем все ячейки с классами прописанными в ней

bes 08.07.2012 15:00

Как насчёт того, чтобы сохранять общее количество ячеек в строках, а неиспользуемым ячейкам ставить display: none

<table border=1 id="table" style="cursor: pointer;">
    <tr>
        <td rowspan="3">0</td>
        <td>1</td>
        <td rowspan="3">2</td>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td style="display: none"></td>
        <td id="td">5</td>
        <td style="display: none"></td>
        <td>6</td> 
        <td>7</td>
    </tr>
    <tr>
        <td style="display: none"></td>
        <td id="td">8</td>
        <td style="display: none"></td>
        <td>9</td> 
        <td>0</td>
    </tr>
</table>​
<script>
window.onload = function (e) {
  var table = document.getElementById('table');
  var len;
  var index;

  table.onclick = function(e) {
    e = e || event;
    var target = e.target || e.srcElement; 
    if (target.parentNode.tagName == 'TR') {
      if (target.previousElementSibling == null) {
        alert('нет предыдущей ячейки')
      } else {
         index = target.parentNode.rowIndex; 
        for (var i = index; i >= 0; i--) {
          if (target.previousElementSibling.style.display != 'none') {
            alert(target.previousElementSibling.innerHTML);
            break;
          } else {
            index--;
            target = table.rows[index].cells[target.cellIndex];
          }
        }
      }
    }
  }

}
</script>

Cepin 08.07.2012 15:55

К сожалению, но нет возможности как-то повлиять на вывод этой таблицы.
Вообщем, по совету Aetae решил делать не копию таблицу, а модель (в каждой ячейке хранит лишь запись о соотвествующих координатах первой таблицы)

Что сделано для оптимизации:
1) Заранее определен максимальный rowspan (в моем случае это 3)
2) Сканировать теперь всю таблицу не обязательно.

Стартовую строку для обработки можно начинать не с 0, а строка заданной ячейки - 5 (из-за максимального rowspan для избежания глюков).
Правую и нижнюю сторону ограничиваем координатами известной ячейки + 1

Все это делает довольно сильно сокращает объем таблицы и дает высокую скорость обработки.

Вроде даже работает, но чувствую, что могут быть камни в таком подходе.

bes 08.07.2012 16:49

Цитата:

Сообщение от Cepin
К сожалению, но нет возможности как-то повлиять на вывод этой таблицы.

Тогда проверять входит ли ячейка в строку, на которую распространён rowspan: последовательно проверяется есть ли в строках выше (до первой найденной) предыдущая по номеру ячейка с rowspan (getAttribute('rowspan')), значение которой распространяется до строки данной ячейки, если есть, значит предыдущее значение - это значение именно этой ячейки с rowspan.

Deff 08.07.2012 19:25

Вообще говоря задача типично решаемая в "Игре морской бой" тут где то было решение

bes 09.07.2012 15:50

<style>
  table, td {border: solid 1px; cursor: pointer}
</style>

<table id="table">
    <tr>
        <td rowspan="3">0</td>
        <td>1</td>
        <td rowspan="3">2</td>
        <td colspan="2">3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>5</td>
        <td  rowspan="2">6</td> 
        <td>7</td>
        <td>8</td>
    </tr>
    <tr>
        <td id="td">9</td>
        <td>10</td> 
        <td>11</td> 
    </tr>
</table>​

<script>
window.onload = function () {//onload begin
  var table = document.getElementById('table');
  var coord, left, top, right, previous, next;
  var d = 5;//здесь можно уточнить
  var p, n;

  table.onclick = function(e) {//onclick begin
    e = e || event;
    var target = e.target || e.srcElement;

    if (target.parentNode.tagName == 'TR') {//if begin
      coord = target.getBoundingClientRect();
      left = coord.left + 1; 
      top = coord.top + 1; 
      right = coord.right; 
      previous = document.elementFromPoint(left - d, top);
      next = document.elementFromPoint(right + d, top);
   
      if (previous.parentNode.tagName == 'TR')  {
        p = previous.innerHTML;
      } else {
        p = 'нет';
      }

       if (next.parentNode.tagName == 'TR')  {
         n = next.innerHTML;
       } else {
         n = 'нет';
       }
      
       alert('предыдущий: ' + p + '\nследующий: ' + n)

      }//if end

  }//onclick end
   
}//onload end
</script>

Deff 09.07.2012 16:14

bes,
Плюс! - ток в универсальном варианте нун искать все элементы по каждой из 4-x сторон: в порядке(обхода) прилегания и Учитываешь ли - что эл-т может быть одновременно и rowspan и colspan ?
(*Ксать скрипт весьма востребованный в бугалтерских расчетах - если exel таблы переносят в брауз,
Его бы добить и вылизать

bes 09.07.2012 16:39

Цитата:

Сообщение от Deff
Плюс! - ток в универсальном варианте нун искать все элементы по каждой из 4-x сторон: в порядке(обхода) прилегания

Да, в универсальном варианте придётся делать дополнительные расчёты: например, если не первая в столбце ячейка с rowspan="2" придётся высчитать для неё двух дополнительных соседей.
Цитата:

Сообщение от Deff
учитываешь ли - что эл-т может быть одновременно и rowspan и colspan

здесь это не важно, для универсального варианта придётся учесть

Aetae 09.07.2012 16:39

Так и знал что кто-нить использует пиксельный метод.
Главный минус его в том, что малейшее изменение стиля - и он перестанет работать.

bes 09.07.2012 16:41

Цитата:

Сообщение от Aetae
Так и знал что кто-нить использует пиксельный метод.
Главный минус его в том, что малейшее изменение стиля - и он перестанет работать.

Можно продемонстрировать на данном примере

Aetae 09.07.2012 16:53

Цитата:

Сообщение от bes (Сообщение 187501)
Можно продемонстрировать на данном примере

Самое простое:
<style>
  table, td {border: solid 1px; cursor: pointer}
 *!* table{border-spacing:6px}*/!*
</style>
 
<table id="table">
    <tr>
        <td rowspan="3">0</td>
        <td>1</td>
        <td rowspan="3">2</td>
        <td colspan="2">3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>5</td>
        <td  rowspan="2">6</td>
        <td>7</td>
        <td>8</td>
    </tr>
    <tr>
        <td id="td">9</td>
        <td>10</td>
        <td>11</td>
    </tr>
</table>​
 
<script>
window.onload = function () {//onload begin
  var table = document.getElementById('table');
  var coord, left, top, right, previous, next;
  var d = 5;//здесь можно уточнить
  var p, n;
 
  table.onclick = function(e) {//onclick begin
    e = e || event;
    var target = e.target || e.srcElement;
 
    if (target.parentNode.tagName == 'TR') {//if begin
      coord = target.getBoundingClientRect();
      left = coord.left + 1;
      top = coord.top + 1;
      right = coord.right;
      previous = document.elementFromPoint(left - d, top);
      next = document.elementFromPoint(right + d, top);
    
      if (previous.parentNode.tagName == 'TR')  {
        p = previous.innerHTML;
      } else {
        p = 'нет';
      }
 
       if (next.parentNode.tagName == 'TR')  {
         n = next.innerHTML;
       } else {
         n = 'нет';
       }
       
       alert('предыдущий: ' + p + '\nследующий: ' + n)
 
      }//if end
 
  }//onclick end
    
}//onload end
</script>

bes 09.07.2012 17:05

Я поэтому и закомментировал строчку (var d = 5;//здесь можно уточнить), имея в виду, что можно более точно рассчитать расстояние между ячейками (задача чётко попасть в ячейку, а не в промежуток между ними).
Допустим рассчитали, какие могут быть ещё варианты изменения стилей, чтобы скрипт потерял работоспособность?

Deff 09.07.2012 18:14

Ну пиксельный имхо не АЙС, суть в том что Фактически, еще раз Фактичекси - все пикселы и координаты определяются столбцом и строкой якобы встроенных в ячейку - одного или нескольких ячеек с colspan и rowspan =1, поэтому на пикселы разменивацо смысла нет

координаты "Писксела" в таблице - есть координаты ячейки(столбец-строка) с размерами colspan-rowspan 1Х1 вписанного реального(если элемент соответствует 1Х1) или псевдо(если размеры больше) подобного элемента

И ширина - высота тоже в ячейках

bes 09.07.2012 19:43

Ячейки таблицы не такие уж и маленькие, чтобы в них не попасть.
Чем меньше размер ячейки, тем выше вероятность промаха, но вероятность того, что будут работать с чрезвычайно уменьшенной таблицей мала (естественно, данный способ не подходит для скрытых таблиц).
Если нужна абсолютная точность, можно подстраховаться, попиксельно (в смысле, увеличивая или уменьшая координату на 1) пройдя в цикле от самой ячейки до первой встретившейся (если такая есть) в нужном направлении.
Проще решения для произвольной таблицы с ячейками с rowspan и colspan, на мой взгляд, пока не видно.

Deff 09.07.2012 20:18

bes,
я имхо не про размер -
Я про идеологию
Ну взять подложить под текущую таблицу такую же, но чисто с одно ячеистой структурой

bes 09.07.2012 20:48

Цитата:

Сообщение от Deff
Ну взять подложить под текущую таблицу такую же, но чисто с одно ячеистой структурой

Для огромных (как пишет ТС) таблиц хотелось бы более элегантного решения.
PS: я выше также предлагал выровнять структуру, что, кстати, наверное реально (пройтись по таблице и добавить недостающие ячейки с display: none).

А, кстати, это наверное неплохое решение, только проходя по таблице, добавлять не просто ячейки с display: none, а также и с соответствующим содержимым (тогда расчёт вообще простой).

Deff 09.07.2012 20:57

bes,
Ну моё предложение прозвучало - проставить каждой ячейке индивидуальный класс
затем обойти и добавить классы соседских, добавляем только первый класс в списке, тады у нас классы всех сторон в атрибуте класс и поиск соседних перебором всех классов в текущей ячейке, нaчиная со второго в списке

Создание уникального класса элемента - номер строки + через букву номер столбца

Выяснить отсутствие соседей, зная класс текущего элемента и общее колво строк и столбцов и его соllspan, rowspan - тоже сложностей не представляет

bes 09.07.2012 21:13

Цитата:

Сообщение от Deff
bes,
Ну моё предложение прозвучало - проставить каждой ячейке индивидуальный класс
затем обойти и добавить классы соседских, добавляем только первый класс в списке, тады у нас классы всех сторон в атрибуте класс и поиск соседних перебором всех классов в текущей ячейке, нaчиная со второго в списке

Честно говоря, не совсем понял как это будет работать для ячеек с rowspan: например, в таблице из моего последнего примера, как добавить классы соседних ячеек к ячейке, в которой значение 5 (эта ячейка первая в строке, следующая за ней в строке ячейка со значением 6, но не 2).

Deff 09.07.2012 21:19

Цитата:

Сообщение от bes
эта ячейка первая в строке, следующая за ней в строке ячейка со значением 6, но не 2

Дык и класс у нее будет соответствующий
Яж написал как классы проставить - номер строки ячейки и номер столбца... (Да забить - просто по себе заю - что тяжело перейти к иным идеям , при наличии достаточно удачных своих

Твоя реализация тоже интересна

bes 09.07.2012 21:28

Цитата:

Сообщение от Deff
Дык и класс у нее будет соответствующий
Яж написал как классы проставить - номер строки ячейки и номер столбца... (Да забить - просто по себе заю - что тяжело перейти к иным идеям , при наличии достаточно удачных своих

Дело не в этом, в данном случае кодом было бы понятнее, чем словами :)

bes 10.07.2012 10:49

<!doctype html>
<style>
  table, td {border: solid 1px; cursor: pointer}
</style>

<table id="table">
    <tr>
        <td rowspan="3">0</td>
        <td>1</td>
        <td>16</td>
        <td rowspan="2" colspan="2">2</td>
        <td colspan="3">3</td>
        <td>4</td>
    </tr>
    <tr>
        <td colspan="2">5</td>
        <td  rowspan="2">6</td> 
        <td colspan="2">7</td>
        <td>17</td>
    </tr>
    <tr>
        <td>9</td>
        <td>10</td> 
        <td>11</td> 
        <td>12</td>
        <td>14</td>
        <td>15</td>
        <td>18</td>
    </tr>
</table>​


<script>
window.onload = function () {//onload begin
  var table = document.getElementById('table');
  var len = table.rows.length;
  var row, cell, td, colspan, rowspan, m;

  for (var i = 0; i < len; i++) {
    row = table.rows[i];
    for (var j = 0; j < row.children.length; j++) {
      cell = row.children[j];
      colspan = cell.getAttribute('colspan');
      if (colspan) {
        for (var k = 1; k < colspan; k++) {
          td = row.insertCell(j + k); 
          td.innerHTML = cell.innerHTML; 
          td.style.display = 'none';
        }
        j += colspan - 1;
      }
    }
  }

  for (var i = 0; i < len; i++) {
    row = table.rows[i];
    for (var j = 0; j < row.children.length; j++) {
      cell = row.children[j];
      rowspan = cell.getAttribute('rowspan');
      if (rowspan) {
        colspan = cell.getAttribute('colspan');
        if (!colspan) {
          colspan = 1; 
        }
        for (var m = 1; m < rowspan; m++) {
          for (var k = 0; k < colspan; k++) {
            td = table.rows[i+m].insertCell(j + k); 
            td.innerHTML = cell.innerHTML; 
            td.style.display = 'none';
          }
          j += colspan - 1;
        }
      }
    }
  }


  table.onclick = function(e) {//onclick begin
    e = e || event;
    var target = e.target || e.srcElement; 
    var previous, colspan, index, next, p, n;

    if (target.parentNode.tagName == 'TR') {//if begin
      previous = target.previousElementSibling;
      if (previous) {
        p = previous.innerHTML;
      } else {
        p = 'нет';
      }

      colspan = target.getAttribute('colspan');
      if (!colspan) {
        colspan = 1; 
      }
      index = target.cellIndex + parseInt(colspan);
      next = target.parentNode.children[index];
      if (next) {
        n = next.innerHTML;
      } else {
        n = 'нет';
      }
           
      alert('предыдущий: ' + p + '\nследующий: ' + n);

    }//if end    

  }//onclick end
   
}//onload end
</script>

Deff 11.07.2012 21:36

Гы -
Табло-навигатор по соседним ячейкам от выбранной
*на выходе имеем массив из 4-х подмассивов указывающих на классы:слево, сверху,справо, снизу.
все ячейки промаркированы классами вида: tr_Y_col_X


<script type="text/javascript" src="http://yandex.st/jquery/1.4.4/jquery.min.js"></script>
<style>
  table, td {border: solid 1px; cursor: pointer}
</style>
*Кликаем по первой таблице 

<br><br>

<table id="table">
<!--    <tr>
        <td>01</td>
        <td>00</td>
        <td>01</td>
        <td>02</td>
        <td>03</td>
        <td>04</td>
    </tr>-->
    <tr>
        <td rowspan="3">00</td>
        <td>01</td>
        <td rowspan="3">02</td>
        <td colspan="2">03</td>
        <td>04</td>
    </tr>
    <tr>
        <td>05</td>
        <td  rowspan="2">06</td> 
        <td colspan="2">07</td>
    </tr>
    <tr>
        <td id="td">09</td>
        <td>10</td> 
        <td>11</td> 
    </tr>
</table>

<br><br>

<div id=Ftore></div>


<script>
//Данные Функции лишь для раскраски:
//(Можно их удалить,- удалив и 5 строк в основном теле скрипта.

//=Раскраска=
var NewColorTd = [];
function setColor(){
  var ColorsBank='00,11,22,33,44,55,66,77,88,99,aa,bb,cc,dd,ee,ff';
  ColorsBank=ColorsBank.split(',')
  var ColorArray = [];var i=0;

  for(var r=15;r>=0;r--){
  for(var g=0;g<=15;g++){
  for(var b=0;b<=15;b++){
    ColorArray[i]=ColorsBank[r]+''+ColorsBank[g]+''+ColorsBank[b];
    i++;
  }}}
   var N =  ColorArray.length;
   for(i=0; i<MaxTD; i++){
   var ColorTD = Math.round(Math.random()*(N-1));
   NewColorTd[i] = ColorArray[ColorTD];
   }
}
</script>


<script>
var colsNext=0;
var Maxrows = $("#table tr").length;
var MaxTD = $("#table td").length;
var MaxCols = 0;

$("#table tr:first td").each(function(i) {
  MaxCols+=parseInt($(this).attr('colspan'));
});

function setTable(a,b){
  var i=0,j=0,str="";
  var S="", TDst='<td>'
  var Tde='</td>\n',Ntd;

  for(j=0; j<a; j++){
    var str='\n<tr>\n'+str;
    for (i=0; i<b; i++){ Ntd=b*j+i;str+=TDst+(Ntd+1)+Tde; }
    str+="</tr>\n";S+=str;str="";
  }
    str='<table>'+S+'</table>';
    return str;
}
var TabL=setTable(Maxrows,MaxCols);

var CloneTbL = $("#Ftore") //.remove()  //Временно Показал Для Дзен
CloneTbL.append(TabL);


//Clone Class in TD Double Table
var TBL2 = CloneTbL.find("table");

function setAnalogTd (j,col,rowspan,colspan,set_Class) {
   for(x=j; x<j+rowspan; x++){
      for(z=col; z<col+colspan; z++){
         var TR=TBL2.find("tr").eq(x);
         var TD=TR.find("td").eq(z);
         TD.addClass("V "+set_Class);
      }
   }
}

//Calculate next column;
var colsNext=0;
function tstcolsNext(j){//
     var TR=TBL2.find("tr").eq(j);//alert(j)
     TR.find("td").each(function(v){
        if(!$(this).hasClass("V")){/*alert(j+"Colonka="+v);*/colsNext=v;return false;}
        });return colsNext;
}

//Crawling cells and setting Class;

setColor();    //Цвет - можно выкинуть
var ColorTD=0; //Цвет - можно выкинуть
$("#table tr").each(function(j) {
  $(this).find("td").each(function(i) {
    var color = "#"+NewColorTd[ColorTD];      //Цвет - можно выкинуть
    $(this).css({"background-color":color});  //Цвет - можно выкинуть

    if(!i&&!j)colsNext=0;
    if(j)tstcolsNext(j);//alert(colsNext);

    var col=colsNext;

    var colspan = parseInt($(this).attr('colspan'));
    colsNext = colsNext + colspan;

    if(colsNext>=MaxCols)colsNext=0;
 
    var rowspan = parseInt($(this).attr('rowspan'));

    var set_Class = 'tr_'+j+'_col_'+col
    $(this).addClass(set_Class);
    setAnalogTd (j,col,rowspan,colspan,set_Class)

    ColorTD++;				    //Цвет - можно выкинуть
  });
}); TBL2.find("td").removeClass("V");

</script><!-- Конец Setting-действий -->

<script><!-- Тестирующая часть выбранной ячейки -->

function extract_TR_andCol(klass) {
   var  tr =  parseInt(klass.replace(/tr_(\d+)[^\d].*/ig,'$1'));
   var col = parseInt(klass.replace(/.*?col_(\d+)(?:\s|$)/ig,'$1'));
return [tr,col]
}


// =Обход периметра ячейки!
var TBL1=$("#table tr");

// Тест Реального rowspan - если обе или более строки,
// если обе или более строк (таблицы) подряд полностью заняты элементами с rowspan > 1;
//=====================================
function TstRealrowspan(klass,a,rowspan) {
  for(var i=1;i<rowspan; i++){
    if(!TBL2.find("tr").eq(a[0]-1+i).find("td").eq(a[1]).hasClass(klass)){
       rowspan=i-1; break;
    }
  }  return rowspan;
}


function bypassing_perimeter(klass,colspan,rowspan) {

   var a=extract_TR_andCol(klass);
   if(rowspan>1){rowspan=TstRealrowspan(klass,a,rowspan)};//
   var Leftarray=[];
   var Toparray=[];
   var Rightarray=[];
   var Bottomarray=[];

//Считываем все левые прилегающие элементы(сверху вниз)
   if(a[1]==0){ Leftarray=[];
   } else {
   for(var i=0; i<rowspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+i).find("td").eq(a[1]-1).attr("class")
     if(i&&(Leftarray[i-1]!=elem))Leftarray.push(elem);
     if(i==0)Leftarray.push(elem);
   }}

//Считываем верхние прилегающие элементы(слево-направо)
   if(a[0]==0){ Toparray=[];
   } else {
   for(var i=0; i<colspan; i++){
     var elem=TBL2.find("tr").eq(a[0]-1).find("td").eq(a[1]+i).attr("class")
     if(i&&(Toparray[i-1]!=elem))Toparray.push(elem);
     if(i==0)Toparray.push(elem);
   }}

//Считываем все правые прилегающие элементы(сверху вниз)
   if((a[1]+colspan-1)==MaxCols-1){ Rightarray=[];
   } else {
   for(var i=0; i<rowspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+i).find("td").eq(a[1]+1).attr("class")
     if(i&&(Rightarray[i-1]!=elem))Rightarray.push(elem);
     if(i==0)Rightarray.push(elem);
   }}

//Считываем нижние прилегающие элементы(слево-направо)
   if((a[0]+rowspan-1)==Maxrows-1){ Bottomarray=[];
   } else {
   for(var i=0; i<colspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+1).find("td").eq(a[1]+i).attr("class")
     if(i&&(Bottomarray[i-1]!=elem))Bottomarray.push(elem);
     if(i==0)Bottomarray.push(elem);
   }}

   return [Leftarray,Toparray,Rightarray,Bottomarray]
}
  $("#table").find("td").each(function(i) {
     var color = $(this).css("background-color");
     var klass = $(this).attr("class");
     $("#Ftore table ."+klass).css({"background-color":color});
  })



 //=== Клик по ячейке ====//
$("#table td").click(function() {
   var klass=$(this).attr('class');
   var colspan=$(this).attr('colspan');
   var rowspan=$(this).attr('rowspan');
   var ALLArray = bypassing_perimeter(klass,colspan,rowspan)
   alert('Левые прилегающие элементы:\n' + ALLArray[0]+'\n\nВерхние прилегающие элементы:\n' +  ALLArray[1]+'\n\nПравые прилегающие элементы:\n'+ALLArray[2]+'\n\nНижние прилегающие элементы:\n'+ALLArray[3])
})
</script>

Aetae 11.07.2012 21:49

Код:

class is a reserved identifier

function extract_TR_andCol(class) {
showhtml (line 145, col 27)


Deff 11.07.2012 22:05

Aetae,
CПС - (*В опере не кажет ошибку

Aetae 11.07.2012 22:58

Цитата:

Сообщение от Deff (Сообщение 188187)
Aetae,
CПС - (*В опере не кажет ошибку

На самом деле ваш вариант с классами - тот же вариант виртуальной модели, только с лишними телодвижениями.
Куда менее затратно составить виртуальный массив содержащий только индексы соседей и обращаться к нему напрямую при запросе.

Deff 11.07.2012 23:08

Цитата:

Сообщение от Aetae
Куда менее затратно составить виртуальный массив содержащий только индексы соседей и обращаться к нему напрямую при запросе.

Ну первое - для ускорения можно и по id поскольку класс единственный
Второе Чтобы составить индексы соседей нун знать начальный номер колонки для первой ячейки в строке(что для варианта перекрытия с rowspan лесенкой Скрин весьма и весьма - непросто - которую простейшей методой не определишь, есть еще камень: Если все ячейки в строке имеют rowspan более единицы -считыванием индекcа tr, то вроде как последущей строки tr вроде как и нет
Так что считаю - кроме простановки id, а не класса - шустрее и универсальнее - не выполнить (хотя может я ошибаюсь - но пока доволен результатом проделанного

Deff 12.07.2012 00:04

:) На 1000 ячеек
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Табленавигатор</title>
<script type="text/javascript" src="http://yandex.st/jquery/1.4.4/jquery.min.js"></script>
</head>
<body>

<style id=Mystyle>
  table, td {border: solid 1px; cursor: pointer}
</style>

<script>
function setTable(a,b){
  var i=0,j=0,str="";
  var S="", TDst='<td>'
  var Tde='</td>\n',Ntd;

  for(j=0; j<a; j++){
    var str='\n<tr>\n'+str;
    for (i=0; i<b; i++){ Ntd=b*j+i;str+=TDst+(Ntd+1)+Tde; }
    str+="</tr>\n";S+=str;str="";
  }
    str='<table id=table>'+S+'</table>';
    return str;
}
var str=setTable(33,33)
$("style#Mystyle").after(str)
</script>

<div id=Ftore></div>

<script>
//Данные Функции лишь для раскраски:
//(Можно их удалить,- удалив и 5 строк в основном теле скрипта.

//=Раскраска=
var NewColorTd = [];
function setColor(){
  var ColorsBank='00,11,22,33,44,55,66,77,88,99,aa,bb,cc,dd,ee,ff';
  ColorsBank=ColorsBank.split(',')
  var ColorArray = [];var i=0;

  for(var r=15;r>=0;r--){
  for(var g=0;g<=15;g++){
  for(var b=0;b<=15;b++){
    ColorArray[i]=ColorsBank[r]+''+ColorsBank[g]+''+ColorsBank[b];
    i++;
  }}}
   var N =  ColorArray.length;
   for(i=0; i<MaxTD; i++){
   var ColorTD = Math.round(Math.random()*(N-1));
   NewColorTd[i] = ColorArray[ColorTD];
   }
}
</script>


<script>
var colsNext=0;
var Maxrows = $("#table tr").length;
var MaxTD = $("#table td").length;
var MaxCols = 0;

$("#table tr:first td").each(function(i) {
  MaxCols=MaxCols+ parseInt($(this).attr('colspan'));
});

function setTable(a,b){
  var i=0,j=0,str="";
  var S="", TDst='<td>'
  var Tde='</td>\n',Ntd;

  for(j=0; j<a; j++){
    var str='\n<tr>\n'+str;
    for (i=0; i<b; i++){ Ntd=b*j+i;str+=TDst+(Ntd+1)+Tde; }
    str+="</tr>\n";S+=str;str="";
  }
    str='<table>'+S+'</table>';
    return str;
}
var TabL=setTable(Maxrows,MaxCols);

var CloneTbL = $("#Ftore").remove()
CloneTbL.append(TabL);


//Clone Class in TD Double Table
var TBL2 = CloneTbL.find("table");

function setAnalogTd (j,col,rowspan,colspan,set_Class) {
   for(x=j; x<j+rowspan; x++){
      for(z=col; z<col+colspan; z++){
         var TR=TBL2.find("tr").eq(x);
         var TD=TR.find("td").eq(z);
         TD.addClass("V "+set_Class);
      }
   }
}

//Calculate next column;
var colsNext=0;
function tstcolsNext(j){//
     var TR=TBL2.find("tr").eq(j);//alert(j)
     TR.find("td").each(function(v){
        if(!$(this).hasClass("V")){/*alert(j+"Colonka="+v);*/colsNext=v;return false;}
        });return colsNext;
}

//Crawling cells and setting Class;

setColor();    //Цвет - можно выкинуть
var ColorTD=0; //Цвет - можно выкинуть
$("#table tr").each(function(j) {
  $(this).find("td").each(function(i) {
    var color = "#"+NewColorTd[ColorTD];      //Цвет - можно выкинуть
    $(this).css({"background-color":color});  //Цвет - можно выкинуть

    if(!i&&!j)colsNext=0;
    if(j)tstcolsNext(j);//alert(colsNext);

    var col=colsNext;

    var colspan = parseInt($(this).attr('colspan'));
    colsNext = colsNext + colspan;

    if(colsNext>=MaxCols)colsNext=0;
 
    var rowspan = parseInt($(this).attr('rowspan'));

    var set_Class = 'tr_'+j+'_col_'+col
    $(this).addClass(set_Class);
    setAnalogTd (j,col,rowspan,colspan,set_Class)

    ColorTD++;				    //Цвет - можно выкинуть
  });
}); TBL2.find("td").removeClass("V");

</script><!-- Конец Setting-действий -->

<script><!-- Тестирующая часть выбранной ячейки -->

function extract_TR_andCol(klass) {
   var  tr =  parseInt(klass.replace(/tr_(\d+)[^\d].*/ig,'$1'));
   var col = parseInt(klass.replace(/.*?col_(\d+)(?:\s|$)/ig,'$1'));
return [tr,col]
}


// =Обход периметра ячейки!
var TBL1=$("#table tr");

// Тест Реального rowspan - если обе или более строки,
// если обе или более строк (таблицы) подряд полностью заняты элементами с rowspan > 1;
//=====================================
function TstRealrowspan(klass,a,rowspan) {
  for(var i=1;i<rowspan; i++){
    if(!TBL2.find("tr").eq(a[0]-1+i).find("td").eq(a[1]).hasClass(klass)){
       rowspan=i-1; break;
    }
  }  return rowspan;
}


function bypassing_perimeter(klass,colspan,rowspan) {

   var a=extract_TR_andCol(klass);
   if(rowspan>1){rowspan=TstRealrowspan(klass,a,rowspan)};//
   var Leftarray=[];
   var Toparray=[];
   var Rightarray=[];
   var Bottomarray=[];

//Считываем все левые прилегающие элементы(сверху вниз)
   if(a[1]==0){ Leftarray=[];
   } else {
   for(var i=0; i<rowspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+i).find("td").eq(a[1]-1).attr("class")
     if(i&&(Leftarray[i-1]!=elem))Leftarray.push(elem);
     if(i==0)Leftarray.push(elem);
   }}

//Считываем верхние прилегающие элементы(слево-направо)
   if(a[0]==0){ Toparray=[];
   } else {
   for(var i=0; i<colspan; i++){
     var elem=TBL2.find("tr").eq(a[0]-1).find("td").eq(a[1]+i).attr("class")
     if(i&&(Toparray[i-1]!=elem))Toparray.push(elem);
     if(i==0)Toparray.push(elem);
   }}

//Считываем все правые прилегающие элементы(сверху вниз)
   if((a[1]+colspan-1)==MaxCols-1){ Rightarray=[];
   } else {
   for(var i=0; i<rowspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+i).find("td").eq(a[1]+1).attr("class")
     if(i&&(Rightarray[i-1]!=elem))Rightarray.push(elem);
     if(i==0)Rightarray.push(elem);
   }}

//Считываем нижние прилегающие элементы(слево-направо)
   if((a[0]+rowspan-1)==Maxrows-1){ Bottomarray=[];
   } else {
   for(var i=0; i<colspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+1).find("td").eq(a[1]+i).attr("class")
     if(i&&(Bottomarray[i-1]!=elem))Bottomarray.push(elem);
     if(i==0)Bottomarray.push(elem);
   }}

   return [Leftarray,Toparray,Rightarray,Bottomarray]
}

 //=== Клик по ячейке ====//
$("#table td").click(function() {
   var klass=$(this).attr('class');
   var colspan=$(this).attr('colspan');
   var rowspan=$(this).attr('rowspan');
   var ALLArray = bypassing_perimeter(klass,colspan,rowspan)
   alert('Левые прилегающие элементы:\n' + ALLArray[0]+'\n\nВерхние прилегающие элементы:\n' +  ALLArray[1]+'\n\nПравые прилегающие элементы:\n'+ALLArray[2]+'\n\nНижние прилегающие элементы:\n'+ALLArray[3])
})
</script>

</body>
</html>

Aetae 12.07.2012 00:27

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Табленавигатор</title>
<script type="text/javascript" src="http://yandex.st/jquery/1.4.4/jquery.min.js"></script>
</head>
<body>

<style id=Mystyle>
  table, td {border: solid 1px; cursor: pointer}
</style>

<script>


function setTable(a,b){
  var i=0,j=0,str="";
  var S="", TDst=function(){return '<td colspan="'+Math.floor(Math.random()*3+1)+'" rowspan="'+Math.floor(Math.random()*3+1)+'">'};

  var Tde='</td>\n',Ntd;

  for(j=0; j<a; j++){
    var str='\n<tr>\n'+str;
    for (i=0; i<b; i++){ Ntd=b*j+i;str+=TDst()+(Ntd+1)+Tde; }
    str+="</tr>\n";S+=str;str="";
  }
    str='<table id=table>'+S+'</table>';
    return str;
}
var str=setTable(33,33)
$("style#Mystyle").after(str)
</script>

<div id=Ftore></div>

<script>
//Данные Функции лишь для раскраски:
//(Можно их удалить,- удалив и 5 строк в основном теле скрипта.

//=Раскраска=
var NewColorTd = [];
function setColor(){
  var ColorsBank='00,11,22,33,44,55,66,77,88,99,aa,bb,cc,dd,ee,ff';
  ColorsBank=ColorsBank.split(',')
  var ColorArray = [];var i=0;

  for(var r=15;r>=0;r--){
  for(var g=0;g<=15;g++){
  for(var b=0;b<=15;b++){
    ColorArray[i]=ColorsBank[r]+''+ColorsBank[g]+''+ColorsBank[b];
    i++;
  }}}
   var N =  ColorArray.length;
   for(i=0; i<MaxTD; i++){
   var ColorTD = Math.round(Math.random()*(N-1));
   NewColorTd[i] = ColorArray[ColorTD];
   }
}
</script>


<script>
var colsNext=0;
var Maxrows = $("#table tr").length;
var MaxTD = $("#table td").length;
var MaxCols = 0;

$("#table tr:first td").each(function(i) {
  MaxCols=MaxCols+ parseInt($(this).attr('colspan'));
});

function setTable(a,b){
  var i=0,j=0,str="";
  var S="", TDst=function(){return '<td colspan="'+Math.floor(Math.random()*3+1)+'" rowspan="'+Math.floor(Math.random()*3+1)+'">'};
  var Tde='</td>\n',Ntd;

  for(j=0; j<a; j++){
    var str='\n<tr>\n'+str;
    for (i=0; i<b; i++){ Ntd=b*j+i;str+=TDst()+(Ntd+1)+Tde; }
    str+="</tr>\n";S+=str;str="";
  }
    str='<table>'+S+'</table>';
    return str;
}
var TabL=setTable(Maxrows,MaxCols);

var CloneTbL = $("#Ftore").remove()
CloneTbL.append(TabL);


//Clone Class in TD Double Table
var TBL2 = CloneTbL.find("table");

function setAnalogTd (j,col,rowspan,colspan,set_Class) {
   for(x=j; x<j+rowspan; x++){
      for(z=col; z<col+colspan; z++){
         var TR=TBL2.find("tr").eq(x);
         var TD=TR.find("td").eq(z);
         TD.addClass("V "+set_Class);
      }
   }
}

//Calculate next column;
var colsNext=0;
function tstcolsNext(j){//
     var TR=TBL2.find("tr").eq(j);//alert(j)
     TR.find("td").each(function(v){
        if(!$(this).hasClass("V")){/*alert(j+"Colonka="+v);*/colsNext=v;return false;}
        });return colsNext;
}

//Crawling cells and setting Class;

setColor();    //Цвет - можно выкинуть
var ColorTD=0; //Цвет - можно выкинуть
$("#table tr").each(function(j) {
  $(this).find("td").each(function(i) {
    var color = "#"+NewColorTd[ColorTD];      //Цвет - можно выкинуть
    $(this).css({"background-color":color});  //Цвет - можно выкинуть

    if(!i&&!j)colsNext=0;
    if(j)tstcolsNext(j);//alert(colsNext);

    var col=colsNext;

    var colspan = parseInt($(this).attr('colspan'));
    colsNext = colsNext + colspan;

    if(colsNext>=MaxCols)colsNext=0;
 
    var rowspan = parseInt($(this).attr('rowspan'));

    var set_Class = 'tr_'+j+'_col_'+col
    $(this).addClass(set_Class);
    setAnalogTd (j,col,rowspan,colspan,set_Class)

    ColorTD++;				    //Цвет - можно выкинуть
  });
}); TBL2.find("td").removeClass("V");

</script><!-- Конец Setting-действий -->

<script><!-- Тестирующая часть выбранной ячейки -->

function extract_TR_andCol(klass) {
   var  tr =  parseInt(klass.replace(/tr_(\d+)[^\d].*/ig,'$1'));
   var col = parseInt(klass.replace(/.*?col_(\d+)(?:\s|$)/ig,'$1'));
return [tr,col]
}


// =Обход периметра ячейки!
var TBL1=$("#table tr");

// Тест Реального rowspan - если обе или более строки,
// если обе или более строк (таблицы) подряд полностью заняты элементами с rowspan > 1;
//=====================================
function TstRealrowspan(klass,a,rowspan) {
  for(var i=1;i<rowspan; i++){
    if(!TBL2.find("tr").eq(a[0]-1+i).find("td").eq(a[1]).hasClass(klass)){
       rowspan=i-1; break;
    }
  }  return rowspan;
}


function bypassing_perimeter(klass,colspan,rowspan) {

   var a=extract_TR_andCol(klass);
   if(rowspan>1){rowspan=TstRealrowspan(klass,a,rowspan)};//
   var Leftarray=[];
   var Toparray=[];
   var Rightarray=[];
   var Bottomarray=[];

//Считываем все левые прилегающие элементы(сверху вниз)
   if(a[1]==0){ Leftarray=[];
   } else {
   for(var i=0; i<rowspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+i).find("td").eq(a[1]-1).attr("class")
     if(i&&(Leftarray[i-1]!=elem))Leftarray.push(elem);
     if(i==0)Leftarray.push(elem);
   }}

//Считываем верхние прилегающие элементы(слево-направо)
   if(a[0]==0){ Toparray=[];
   } else {
   for(var i=0; i<colspan; i++){
     var elem=TBL2.find("tr").eq(a[0]-1).find("td").eq(a[1]+i).attr("class")
     if(i&&(Toparray[i-1]!=elem))Toparray.push(elem);
     if(i==0)Toparray.push(elem);
   }}

//Считываем все правые прилегающие элементы(сверху вниз)
   if((a[1]+colspan-1)==MaxCols-1){ Rightarray=[];
   } else {
   for(var i=0; i<rowspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+i).find("td").eq(a[1]+1).attr("class")
     if(i&&(Rightarray[i-1]!=elem))Rightarray.push(elem);
     if(i==0)Rightarray.push(elem);
   }}

//Считываем нижние прилегающие элементы(слево-направо)
   if((a[0]+rowspan-1)==Maxrows-1){ Bottomarray=[];
   } else {
   for(var i=0; i<colspan; i++){
     var elem=TBL2.find("tr").eq(a[0]+1).find("td").eq(a[1]+i).attr("class")
     if(i&&(Bottomarray[i-1]!=elem))Bottomarray.push(elem);
     if(i==0)Bottomarray.push(elem);
   }}

   return [Leftarray,Toparray,Rightarray,Bottomarray]
}

 //=== Клик по ячейке ====//
$("#table td").click(function() {
   var klass=$(this).attr('class');
   var colspan=$(this).attr('colspan');
   var rowspan=$(this).attr('rowspan');
   var ALLArray = bypassing_perimeter(klass,colspan,rowspan)
   alert('Левые прилегающие элементы:\n' + ALLArray[0]+'\n\nВерхние прилегающие элементы:\n' +  ALLArray[1]+'\n\nПравые прилегающие элементы:\n'+ALLArray[2]+'\n\nНижние прилегающие элементы:\n'+ALLArray[3])
})
</script>

</body>
</html>



Вот так, для полного испытания.))

Deff 12.07.2012 00:34

Aetae,
:) А пояснения - можно ? - табла весьма кривая создана
Воть ее вид в дебагере (и то Опера часть тегов Выправила:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru" dir="ltr">
    <head></head>
    <body>
      <style id="Mystyle"></style>
      <table id="table">
        <tbody>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr>
            <td colspan="0" rowspan="3" style="background-color: rgb(102, 51, 34)" class="tr_3_col_3"></td>
            <td colspan="0" rowspan="2" style="background-color: rgb(102, 255, 153)" class="tr_3_col_3"></td>
            <td colspan="1" rowspan="3" style="background-color: rgb(85, 136, 102)" class="tr_3_col_3"></td>
            <td colspan="2" rowspan="2" style="background-color: rgb(221, 204, 68)" class="tr_3_col_4"></td>
            <td colspan="3" rowspan="0" style="background-color: rgb(102, 0, 204)" class="tr_3_col_6"></td>
            <td colspan="2" rowspan="2" style="background-color: rgb(204, 221, 119)" class="tr_3_col_6"></td>
            <td colspan="1" rowspan="1" style="background-color: rgb(153, 153, 187)" class="tr_3_col_9"></td>
            <td colspan="3" rowspan="3" style="background-color: rgb(85, 102, 255)" class="tr_3_col_18"></td>
            <td colspan="1" rowspan="1" style="background-color: rgb(51, 187, 51)" class="tr_3_col_33"></td>
            <td colspan="1" rowspan="1" style="background-color: rgb(68, 238, 255)" class="tr_3_col_34"></td>
            <td colspan="0" rowspan="3" style="background-color: rgb(85, 204, 85)" class="tr_3_col_35"></td>
            <td colspan="3" rowspan="1" style="background-color: rgb(238, 34, 153)" class="tr_3_col_35"></td>
            <td colspan="2" rowspan="0" style="background-color: rgb(102, 34, 17)" class="tr_3_col_0"></td>
            <td colspan="1" rowspan="0" style="background-color: rgb(187, 102, 136)" class="tr_3_col_2"></td>
            <td colspan="2" rowspan="0" style="background-color: rgb(68, 255, 51)" class="tr_3_col_3"></td>
            <td colspan="0" rowspan="1" style="background-color: rgb(68, 255, 68)" class="tr_3_col_5"></td>
            <td colspan="0" rowspan="1" style="background-color: rgb(0, 102, 255)" class="tr_3_col_5"></td>
            <td colspan="2" rowspan="0" style="background-color: rgb(102, 255, 255)" class="tr_3_col_5"></td>
            <td colspan="1" rowspan="1" style="background-color: rgb(170, 238, 34)" class="tr_3_col_7"></td>
            <td colspan="0" rowspan="0" style="background-color: rgb(255, 187, 221)" class="tr_3_col_8"></td>
            <td colspan="2" rowspan="3" style="background-color: rgb(0, 119, 221)" class="tr_3_col_8"></td>
            <td colspan="0" rowspan="1" style="background-color: rgb(17, 153, 238)" class="tr_3_col_10"></td>
            <td colspan="2" rowspan="2" style="background-color: rgb(238, 255, 187)" class="tr_3_col_10"></td>
            <td colspan="3" rowspan="0" style="background-color: rgb(17, 17, 68)" class="tr_3_col_12"></td>
            <td colspan="0" rowspan="3" style="background-color: rgb(187, 0, 204)" class="tr_3_col_15"></td>
            <td colspan="1" rowspan="2" style="background-color: rgb(85, 85, 85)" class="tr_3_col_15"></td>
            <td colspan="2" rowspan="3" style="background-color: rgb(0, 170, 0)" class="tr_3_col_16"></td>
            <td colspan="0" rowspan="0" style="background-color: rgb(68, 255, 204)" class="tr_3_col_18"></td>
            <td colspan="3" rowspan="0" style="background-color: rgb(136, 17, 119)" class="tr_3_col_18"></td>
            <td colspan="2" rowspan="3" style="background-color: rgb(34, 238, 238)" class="tr_3_col_21"></td>
            <td colspan="3" rowspan="0" style="background-color: rgb(85, 51, 85)" class="tr_3_col_23"></td>
            <td colspan="1" rowspan="1" style="background-color: rgb(187, 136, 85)" class="tr_3_col_26"></td>
            <td colspan="3" rowspan="0" style="background-color: rgb(204, 238, 255)" class="tr_3_col_27"></td>
          </tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
          <tr></tr>
        </tbody>
      </table>
      <script></script>
      <script></script>
      <script></script>
      <!-- Конец Setting-действий -->
      <script></script>
    </body>
  </html>

Deff 12.07.2012 00:40

Ксать могу отметить - что при увеличении colspan и rowspan скорость даже слегка растет

Aetae 12.07.2012 02:19

Пофиксил. Не идеально, конечно, но мне лень писать правильный код.
Суть в том что просто поменял
TDst='<td>'

на
TDst=function(){return '<td colspan="'+Math.floor(Math.random()*3+1)+'" rowspan="'+Math.floor(Math.random()*3+1)+'">'};

И добавил вызов соответственно.
Тупо рандом.)

Deff 12.07.2012 02:21

Aetae,
Да мну понял - бу время нарисую - хотя на деле есть готовый рандом таблица - на который тестил (но тут, в топике, тупо ограничение на символы

Deff 16.07.2012 19:08

:) Минималистическое решение тут http://javascript.ru/forum/offtopic/...tml#post189280 пост 13 от Raed!


Часовой пояс GMT +3, время: 19:55.