Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 09.06.2012, 19:39
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

Скроллинг клавишами и липкие блоки
Решая на чистом js задачу скроллинга клавишами, а также липких блоков из Перемещение блока при скроллинге столкнулся с рядом проблем.
Основа: набор таблиц, в каждой из которой набор строк, в первой ячейке каждой строки произвольное содержимое, вторая ячейка - контейнер для липкого блока.
Липкие блоки: (см ссылку).
Скроллинг: по нажатию символьных клавиш, которые символизируют "вверх" и "вниз" последовательно перемещаться по ячейкам всей совокупности таблиц.

Взял за основу метод document.elementFromPoint(x, y), с помощью которого получаю блок и далее работаю с ним (либо перемещаю к нужной ячейке при скроллинге, либо контролирую положение соответствующего липкого блока).

По скроллингу: перемещения производятся, но в некоторые моменты document.elementFromPoint(x, y) возвращает не нужный блок, а саму таблицу (даже если не учитывать, что специально прокрутили, чтобы попасть в margin между ячейками, тоже пока не соображу как это обойти), хотя вроде бы чётко смещаю при каждом нажатии клавиши левый верхний угол блока в точку, в которой находился первый блок при загрузке страницы.
По липким блокам: задача вроде бы тоже не сложная, но не получается cформировать условия (совладать с координатами, рисование пока не помогает).
Может быть у кого есть соображения на эту тему по моей логике решения (необходимый, на мой взгляд, функционал я включил в код), или может быть альтернативные подходы к решению этих задач.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Скроллинг клавишами и липкие блоки</title>
  </head>

<style>
  .menu {
    position: fixed; 
    left: 0%; 
    top: 0%; 
    background: maroon; 
    width: 100%; 
    height: 10%; 
    z-index: 10;
  }

 #content {
    position: absolute;
    left: 0%;
    top: 10%;
 }

 .table {
    position: relative;
    background: gray;
  }

  .left {
    width: 500px;
    background: lightgray;
    border: 1px solid black;
  }

 .right {
    background: gray;
    border: 1px solid black;
    width: 200px;
    vertical-align: top;
  }

  .sticker {
    position: relative;
    background: whitesmoke; 
    height: 100px;    
  }

</style>

<div class="menu"></div>
<div id="content"></div>


<script>
window.onload = function () {//onload begin
  var content = document.getElementById('content'); 

  //код создания таблиц
  var inner = '';
  var str = '';
  for (var i = 0; i < 3; i++) {
    str += '<table class="table">'
    for (var j = 0; j < 3; j++) {
      str += '<tr><td class="left">';
      for (var k = 0; k < 31; k++) {
        inner += 'таблица ' + i + '; строка ' + j + '<br>'; 
      }
      str += inner + '</td><td class="right"><div class="sticker">sticker' + i + ' - ' + j + '</div></td></tr>';
      inner = '';
    }
    str += '</table>'
  }
  content.innerHTML = str;
 

  //функция получения координат элемента (и не только) относительно документа
   var getCoords = function (element) {//getCoords begin
    var elementRect = element.getBoundingClientRect();
    var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
    var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
    var clientLeft = document.documentElement.clientLeft || document.body.clientLeft || 0;
    var clientTop = document.documentElement.clientTop || document.body.clientTop || 0;
    var left = elementRect.left + scrollLeft - clientLeft;
    var top  = elementRect.top +  scrollTop - clientTop;

    var obj = {
      left: Math.round(left), top: Math.round(top), 
       scrollTop: Math.round(scrollTop), scrollLeft: Math.round(scrollLeft),
       clientLeft: Math.round(clientLeft), clientTop: Math.round(clientTop)
    }
    return obj;
  }//getCoords end


  //функция получения номера по элементу, если элемент не в коллекции -1
  var getN = function (element, collection) {//getN begin
    for (var i = 0; i < length; i++) {
      if (element == collection[i]) {
        return i
      } 
    }
    return -1;
  }//getN end


  //функция получения элемента по номеру, если нет такого элемента -1
  var getElement = function (n, collection) {//getElement begin
    for (var i = 0; i < length; i++) {
      if (collection[i] == collection[n]) {
        return collection[i];
      }
    }
    return -1;
  }//getElement end


  //необходимые переменные
  var leftBlocks = content.getElementsByClassName('left'); //колллекция блоков слева
  var rightBlocks = content.getElementsByClassName('right');//коллекция блоков справа
  var stickers = content.getElementsByClassName('sticker');//коллекция липких блоков
  var length = leftBlocks.length; // = rightBlocks.length; //= stickers.length;

   var firstLeft = leftBlocks[0]; //первый элемент слева
  //его координаты - точка отсчёта
   var upperBound = getCoords(leftBlocks[0]).top;//верхняя граница
   var leftBound = getCoords(leftBlocks[0]).left; //левая граница

   var lastLeft = leftBlocks[length - 1]; //последний элемент слева
   var lastLeftCoords = getCoords(lastLeft); //его координаты




//скроллинг клавишами++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  document.onkeyup = function (e) {//onkeyup begin
    var e = e || window.event; //для IE

    //получаем элемент на верхней границе и его параметры
    var element = document.elementFromPoint(leftBound, upperBound);

   /****************************************************
   вот в этих двух функциях getToUp и getToDown не получается заложить 
   необходиму логику решения***********************************/

   var getToUp = function (element) {//getToUp begin
      var n = getN(element, leftBlocks);
      var coords = getCoords(element); 
      if ( n != -1 ) {//если элемент действительно тот //if begin
        //если элемент пересекает верхнюю границу
        if ( coords.top < coords.scrollTop + upperBound ) {
          return element; //возвращаем сам элемент
        } else if ( n != 0 ) {
          return element = getElement(n - 1, leftBlocks);//возвращаем предыдущий элемент, если он не первый
        } 
      } else {//если элемент не тот //if else
        if ( coords.scrollTop > upperBound) {
          return element = firstLeft;//возвращаем первый элемент
        } else {
          return element = lastLeft;//возвращаем последний элемент
        }
      }//if end
  }//getToUp end


    var getToDown = function (element) {//getToDown begin
      var n = getN(element, leftBlocks);
      var coords = getCoords(element); 
      if ( n != -1 ) { //if begin
        if ( coords.top < coords.scrollTop + upperBound &&  n != length ) {
          return element; //возвращаем последующий элемент, если он не последний
        } else {
          return element;//возвращаем сам элемент
        } 
      } else {//if else
        if ( coords.scrollTop > upperBound) {
          //return element = ;
        } else {
         //return element = ;
        }
      }//if end
  }//getToDown end


    //проверяем клавиши и получаем нужный блок
    switch ( e.keyCode ) {
      case 65: {//нажата клавиша "вверх" (Ф, ф - рус., A, a - eng.)
        getToUp (element);
        break;
      }
      case 83: {//нажата клавиша "вниз" (В, в - рус., S, s - eng.)
        getToDown(element);
       break;   
      }
      default: return; //вышли, если не та клавиша
    }//switch end

    //если дошли, то прокрутили страницу, поместив блок в точку остчёта
    window.scrollTo(getCoords(element).left - leftBound, getCoords(element).top - upperBound);

  }//onkeyup end



//липкие блоки+++++++++++++++++++++++++++++++++++++++++

   window.onscroll = function () {//onscroll begin
    //получаем элемент 
    var element = document.elementFromPoint(leftBound, upperBound); 
    //var rect = element.getBoundingClientRect();
    var n = getN(element, leftBlocks); 
    var elementCoords = getCoords(element);//координаты элемента относительно документа
    var elementHeight = element.clientHeight;//высота элемента

    var sticker = getElement(n, stickers);//текущий липкий блок
    var stickerCoords = getCoords(sticker);//координаты липкого блока относительно документа
    var stickerHeight = sticker.clientHeight;//высота липкого блока

    var scroll = elementCoords.scrollTop;//= stickerCoords.scrollTop //величина прокрутки
    var scrollAndUpperBound = scroll + upperBound; //величина прокуртки с учётом верхней границы
    var displacement = scrollAndUpperBound - elementCoords.top; //величина смещения

     //выравнивание по верхней границе
    if ( stickerCoords.top < scrollAndUpperBound || stickerCoords.top  > scrollAndUpperBound)  {
      sticker.style.top = displacement + 'px'; 
    }

    //получение новых координат
    stickerCoords = getCoords(sticker);
    scrollAndUpperBound = stickerCoords.scrollTop + upperBound;
    elementCoords = getCoords(element);
    displacement = scrollAndUpperBound - elementCoords.top;

    //выравнивание по нижней границе
    if ( stickerCoords.top + stickerHeight >= elementCoords.top + elementHeight )  {
      sticker.style.top = elementHeight - stickerHeight + 'px';
    } else if (stickerCoords.top  > scrollAndUpperBound )  {
      sticker.style.top = displacement + 'px'; 
    } 

    if (element != lastLeft) {
      var nextSticker = getElement(n + 1, stickers);
      nextSticker.style.top = '0 px'; 
    }

    if ( element == firstLeft && displacement  == 0 ) {
      sticker.style.top = '0 px'; 
    }
    


  }//onscroll end


}//onload end


</script>
</body>
</html>

Последний раз редактировалось bes, 12.06.2012 в 22:28.
Ответить с цитированием
  #2 (permalink)  
Старый 09.06.2012, 23:58
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от bes
вторая ячейка - контейнер для липкого блока.
зачем? div с абсолютным позиционированием, не?

Что надо в целом вообще не понял. Правильно сформулированная задача уже часть решения
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук

Последний раз редактировалось nerv_, 10.06.2012 в 00:00.
Ответить с цитированием
  #3 (permalink)  
Старый 10.06.2012, 00:29
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

nerv_, посмотрите подредактированный пример, в принципе, хотя пока и коряво, удалось частично решить вторую часть задачи - блоки начали двигаться примерно так как надо, то есть липнуть при прокрутке к нижней части строки меню (тут можно и с position: relative, главное правильно рассчитать координаты, что собственно и не получается).
Насчёт скроллинга клавишами - когда нажимаете клавишу "вверх" должно прокручиваться на предыдущую строку от той, которая в данный момент сразу под строкой меню, "вниз" - на следующую строку, для прокрутки здесь используются клавиши A - вверх, S - вниз.
Ответить с цитированием
  #4 (permalink)  
Старый 10.06.2012, 12:26
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

Липкие блоки более-менее работают (в FF наиболее плавно, в хроме и IE видны подёргивания при прокрутке), но остаётся проблема попадания на нужный блок при помощи document.elementFromPoint(x, y).
Кто-нибудь знает как отследить ближайший блок, если этот метод выдал в качестве элемента, например, не ячейку таблицы, а саму таблицу (например, когда попал в margin между ячейками)?

Специально стал использовал document.elementFromPoint(x, y), чтобы обойтись без цикла, но при таком раскладе проще будет всё рассчитать, если за основу поиска взять именно цикл, а не этот метод. Может быть можно как-нибудь обойтись без цикла?
Ответить с цитированием
  #5 (permalink)  
Старый 10.06.2012, 13:00
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

bes, добрый день

obj = {
      left: Math.round(left), top: Math.round(top), 
       scrollTop: Math.round(scrollTop), scrollLeft: Math.round(scrollLeft),
       clientLeft: Math.round(clientLeft), clientTop: Math.round(clientTop)
    }

obj - глобальная переменная
getN = function (element, collection) {//getN begin

getN - глобальная
getElement = function (n, collection) {//getElement begin

getElement - глобальная
getCoords = function (element) {//getCoords begin

getCoords - глобальная

Дальше продолжать? )

Сообщение от bes
главное правильно рассчитать координаты, что собственно и не получается
Кстати в IE8 не работает. При загрузки страницы один раз вычисляешь положение каждого блока (при ресайзе перевычисляешь), при скроллине смотришь, какой блок ближе (первое, что приходит в голову)
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #6 (permalink)  
Старый 10.06.2012, 13:30
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

nerv_, спасибо, подправил, попробую и этот способ.
В IE8 не работает из-за getElementsByClassName().
Ответить с цитированием
  #7 (permalink)  
Старый 10.06.2012, 14:14
без статуса
Отправить личное сообщение для Deff Посмотреть профиль Найти все сообщения от Deff
 
Регистрация: 25.05.2012
Сообщений: 8,219

bes,
Мож стоит типо:
1. Выяснем, какие блоки находяться в зоне видимости,
2. Тестируем расстояние нижнего края верхнего видимого блока(посколь их может быть и два) от
верха экрана, ежели оно менее его высоты, даем липкому блоку спецфическое id и позицию fixed , ежели оно менее высоты липкого блока, вычислем его координаты и закрепляем позицией absolute убираем id
id - удобно для ie
Ответить с цитированием
  #8 (permalink)  
Старый 11.06.2012, 13:15
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

Deff, я взял за основу несколько другой способ, его уж и закончу))

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Скроллинг клавишами и липкие блоки</title>
  </head>

<style>
  .menu {
    position: fixed; 
    left: 0%; 
    top: 0%; 
    background: maroon; 
    width: 100%; 
    height: 10%; 
    z-index: 10;
  }

 #content {
    position: absolute;
    left: 0%;
    top: 10%;
 }

 .table {
    position: relative;
    background: gray;
  }

  .left {
    width: 500px;
    background: lightgray;
    border: 1px solid black;
  }

 .right {
    background: gray;
    border: 1px solid black;
    width: 200px;
    vertical-align: top;
  }

  .sticker {
    position: relative;
    background: whitesmoke; 
    height: 100px;
  }

</style>

<div class="menu"></div>
<div id="content"></div>


<script>
window.onload = function () {//onload begin
  var content = document.getElementById('content'); 

  //код создания таблиц
  var inner = '';
  var str = '';
  for (var i = 0; i < 3; i++) {
    str += '<table class="table">'
    for (var j = 0; j < 3; j++) {
      str += '<tr><td class="left">';
      for (var k = 0; k < 31; k++) {
        inner += 'таблица ' + i + '; строка ' + j + '<br>'; 
      }
      str += inner + '</td><td class="right"><div class="sticker">sticker ' + i + ' - ' + j + '</div></td></tr>';
      inner = '';
    }
    str += '</table>';
  }
  content.innerHTML = str;
 
  
  //функция получения координат элемента относительно документа
  var getCoords = function (element) {//getCoords begin
    var elementRect = element.getBoundingClientRect();
    var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
    var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
    var clientLeft = document.documentElement.clientLeft || document.body.clientLeft || 0;
    var clientTop = document.documentElement.clientTop || document.body.clientTop || 0;
    var left = elementRect.left + scrollLeft - clientLeft;
    var top  = elementRect.top +  scrollTop - clientTop;
    var bottom = elementRect.bottom + scrollTop - clientTop;

    var obj = {
       left: Math.round(left), 
       top: Math.round(top), 
       bottom: Math.round(bottom),
    }
    return obj;
  }//getCoords end


 //функция получения координат всех элементов 
  var getAllCoords = function (collection) {//getAllCoords begin
    var allCoords = [];
    for (var i = 0; i < length; i++) {
      allCoords[i] = getCoords(collection[i]);
    }
    return allCoords;
  }//getAllCoords end


  if (!content.getElementsByClassName) { //if begin
    content.getElementsByClassName = function(cl) {//getElementsByClassName begin
      var retnode = []; 
      var myclass = new RegExp('\\b'+cl+'\\b'); 
      var elem = this.getElementsByTagName('*'); 
      for (var i = 0; i < elem.length; i++) { 
         var classes = elem[i].className; 
         if (myclass.test(classes)) { 
            retnode.push(elem[i]); 
         } 
      } 
      return retnode; 
   }//if end
}//getElementsByClassName end

  //необходимые переменные
  var leftBlocks = content.getElementsByClassName('left'); //колллекция блоков слева
  var rightBlocks = content.getElementsByClassName('right');//коллекция блоков справа
  var stickers = content.getElementsByClassName('sticker');//коллекция липких блоков
  var length = leftBlocks.length; // = rightBlocks.length; //= stickers.length;

  //получаем координаты всех элементов слева
  var allCoords = getAllCoords(leftBlocks);
  var upperBound = allCoords[0].top;//верхняя граница

  //пересчитываем координаты при масштабировании страницы
  window.onresize = function () {
    allCoords = getAllCoords(leftBlocks);
    upperBound = allCoords[0].top;
  }



//скроллинг клавишами++++++++++++++++++++++++++++++++++++++++++++++++++++++

  document.onkeyup = function (e) {//onkeyup begin
    var e = e || window.event; //для IE

    //получаем прокрутку
    var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;

    //функция получения номера элемента на верхней границе для движения вверх
    var getNUp = function(coords, boundary) {//getNUp begin
      //расстояние от начала документа до верхней границы
      var sum = scrollTop + boundary;

      for (var i = 0; i < length; i++) {//for begin
        //если элемент ниже верхней границы и не первый, возвращаем номер предыдущего элемента
        if (coords[i].top >= sum && i != 0) {
          return (i - 1);
        } else
        //иначе, если элемент пересекает верхнюю границу, возвращаем его номер
        if (coords[i].bottom > sum) {
          return i;
        }  
      }//for end

      //если дошли, то возвращаем номер самого элемента (он будет последним при полной прокрутке)
      return (i - 1);

  }//getNUp end


    //функция получения номера элемента на верхней границе для движения вниз
    var getNDown = function (coords, boundary) {//getNDown begin
      //расстояние от начала документа до верхней границы
      var sum = scrollTop + boundary; 

      for (var i = 0; i < length; i++) {//for begin
        //если элемент пересекает верхнюю границу, возвращаем номер последующего элемента, если он не последний
        if (coords[i].bottom > sum && i != length - 1) {
          return (i + 1);
        } else //иначе, если элемент ниже верхней границы, возвращаем его номер
        if (coords[i].top > sum) {
          return i; //(i - 1), так как i в цикле увеличивается при выходе
        } 
    }//for end

    //если дошли, то возвращаем номер самого элемента (он будет последним при полной прокрутке)
    return (i - 1);//

  }//getNDown end



    //проверяем клавиши и получаем номер нужного блока
    var n = 0; 
    switch ( e.keyCode ) {
      case 65: {//нажата клавиша "вверх" (Ф, ф - рус., A, a - eng.)
        var n = getNUp(allCoords, upperBound);
        break;
      }
      case 83: {//нажата клавиша "вниз" (В, в - рус., S, s - eng.)
        var n = getNDown(allCoords, upperBound);
       break;   
      }
      default: return; //вышли, если не та клавиша
    }//switch end

    //если дошли, то прокрутили страницу, поместив начало блока на верхнюю границу
    window.scrollTo(0, allCoords[n].top - upperBound); 

  }//onkeyup end




//липкие блоки+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

   window.onscroll = function () {//onscroll begin
    var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
    var sum = scrollTop + upperBound;
    var stickerCoords = {};

    //получаем липкий блок и задаём ему нужные координаты относительно родительского контейнера
    for (var i = 0; i < length; i++) {//for begin
      stickerCoords = getCoords(stickers[i]);

     //если липкий блок в границах своего контейнера, то выровнять липкий блок по верхней границе
      if (stickerCoords.top >= allCoords[i].top && stickerCoords.bottom <= allCoords[i].bottom ) {
        stickers[i].style.top = sum - allCoords[i].top + 'px';
        //return;
      }

  //корректирование предыдущего действия
      stickerCoords = getCoords(stickers[i]);

     //если липкий блок зашёл за верхнюю границу своего контейнера, то выровнять по верхнему краю своего контейнера
     if (stickerCoords.top < allCoords[i].top) {
        stickers[i].style.top = 0 + 'px';
      }

      //если контейнер липкого блока ниже верхней границы, то выровнять его липкий блок по его верхнему краю
      if (allCoords[i].top > sum) {
        stickers[i].style.top = 0 + 'px';
        return;
      } 
/*
    if (window.getComputedStyle) {
      var stickerMarginBottom = parseInt(getComputedStyle(stickers[i], null).marginBottom);
    } else {
      var stickerMarginBottom = stickers[i].currentStyle.marginBottom;
    }
*/

     //если липкий блок зашёл за нижнюю границу своего контейнера, то выровнять по нижнему краю своего контейнера
     if (stickerCoords.bottom > allCoords[i].bottom) {
       stickers[i].style.top = (allCoords[i].bottom - allCoords[i].top) - (stickerCoords.bottom - stickerCoords.top) - 2 + 'px';
     }

    }//for end
  }//onscroll end


}//onload end


</script>
</body>
</html>

Последний раз редактировалось bes, 12.06.2012 в 22:33.
Ответить с цитированием
  #9 (permalink)  
Старый 11.06.2012, 20:50
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

Подредактировал предыдущий пример, теперь рабочий (в IE<9 не будет работать из-за getElementsByClassName и getComputedStyle, тут нужно эмулировать, остальное вроде бы кроссбраузерно).
Лучше сформулировать логику установки координат для липких блоков пока не могу, тут если умные люди подключатся, подскажут, но, главное, работает.
nerv_, Deff, спасибо за помощь и участие.
Ответить с цитированием
  #10 (permalink)  
Старый 12.06.2012, 20:45
Аватар для bes
bes bes вне форума
Профессор
Отправить личное сообщение для bes Посмотреть профиль Найти все сообщения от bes
 
Регистрация: 22.03.2012
Сообщений: 3,744

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Скроллинг клавишами и липкие блоки</title>
  </head>

<style>
  .menu {
    position: fixed; 
    left: 0%; 
    top: 0%; 
    background: maroon; 
    width: 100%; 
    height: 10%; 
    z-index: 10;
  }

 #content {
    position: absolute;
    left: 0%;
    top: 10%;
 }

 .table {
    position: relative;
    background: gray;
  }

  .block {
    position: relative;
    width: 500px;
    background: lightgray;
    border: 1px solid black;
  }

 .stickerBlock {
    background: gray;
    border: 1px solid black;
    width: 200px;
    vertical-align: top;
  }

  .sticker {
    position: relative;
    background: whitesmoke; 
    height: 100px;
    width: 200px;
  }

</style>

<div class="menu"></div>
<div id="content"></div>



<script>
window.onload = function () {//onload begin
  var content = document.getElementById('content'); 

  var inner = '';
  var str = '';
  for (var i = 0; i < 3; i++) {
    str += '<table class="table">'
    for (var j = 0; j < 3; j++) {
      str += '<tr><td class="block">';
      for (var k = 0; k < 31; k++) {
        inner += 'таблица ' + i + '; строка ' + j + '<br>'; 
      }
      str += inner + '</td><td class="stickerBlock"><div class="sticker">sticker ' + i + ' - ' + j + '</div></td></tr>';
      inner = '';
    }
    str += '</table>';
  }
  content.innerHTML = str;


  var getCoords = function (element) {//getCoords begin
    var rect = element.getBoundingClientRect();
    var docEl = document.documentElement;
    var body = document.body;
    var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
    var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
    var clientLeft = docEl.clientLeft || body.clientLeft || 0;
    var clientTop = docEl.clientTop || body.clientTop || 0;
    var left = rect.left + scrollLeft - clientLeft;
    var top  = rect.top +  scrollTop - clientTop;
    var right = rect.right + scrollLeft - clientLeft;
    var bottom = rect.bottom + scrollTop - clientTop;
    return {left: left, top: top, bottom: bottom, right: right}
  }//getCoords end


  if (!content.getElementsByClassName) { //if begin
    content.getElementsByClassName = function(cl) {//getElementsByClassName begin
      var retnode = []; 
      var myclass = new RegExp('\\b'+cl+'\\b'); 
      var elem = this.getElementsByTagName('*'); 
      for (var i = 0; i < elem.length; i++) { 
         var classes = elem[i].className; 
         if (myclass.test(classes)) { 
            retnode.push(elem[i]); 
         } 
      } 
      return retnode; 
   }//getElementsByClassName end
}//if end


/*
 if (!content.getElementsByClassName) { //if begin

    content.getElementsByClassName = function(nameOfClass) {//getElementsByClassName begin
      var mas = []; 
      var elements = this.getElementsByTagName('*'); 
      var length = elements.length;

      for (var i = 0; i < length; i++) { 
        if (elements[i].className == nameOfClass) { 
            mas.push(elements[i]); 
         } 
      } 

      return mas; 
    }//getElementsByClassName end

  }//if end
*/


//скроллинг клавишами++++++++++++++++++++++++++++++++++++++++++++++++++++++

  document.onkeyup = function (e) {//onkeyup begin
    var e = e || window.event; //для IE

    var getNUp = function(collection, boundary) {//getNUp begin
      var scroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
      var sum = scroll + boundary;
      var length = collection.length;
      var coords = {};

      for (var i = 0; i < length; i++) {//for begin
        coords = getCoords(collection[i]);
        if (coords.top >= sum && i != 0) {
          return (i - 1);
        } else if (coords.bottom > sum) {
          return i;
        }  
      }//for end

      return (i - 1);
  }//getNUp end


    var getNDown = function (collection, boundary) {//getNDown begin
      var scroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
      var sum = scroll + boundary;
      var length = collection.length; 
      var coords = {};

      for (var i = 0; i < length; i++) {//for begin
        coords = getCoords(collection[i]);
        if (i == 0 && coords.top > sum + 1) {return i}
        if (coords.bottom > sum && i != length - 1) {
          return (i + 1);
        } else if (coords.top > sum) {
          return i; 
        } 
    }//for end

    return (i - 1);
  }//getNDown end


  var blocks = content.getElementsByClassName('block');
  var upperBound = getCoords(blocks[0]).top;
  var leftBound = getCoords(blocks[0]).left;
  var n = 0; 

    switch ( e.keyCode ) {//switch begin
      case 65: {
        var n = getNUp(blocks, upperBound);
        break;
      }
      case 83: {
        var n = getNDown(blocks, upperBound);
       break;   
      }
      default: return; 
    }//switch begin

    window.scrollTo(getCoords(blocks[n]).left - leftBound, getCoords(blocks[n]).top - upperBound); 

  }//onkeyup end



//липкие блоки+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
   window.onscroll = function () {//onscroll begin
     var stickerBlocks = content.getElementsByClassName('stickerBlock');
     var stickers = content.getElementsByClassName('sticker');
     var length = stickers.length;
     var upperBound = getCoords(stickerBlocks[0]).top;
     var leftBound = getCoords(stickerBlocks[0]).left;
     var scroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
     var sum = scroll + upperBound;
     var coords = {};
     var stickerCoords = {};
     var condition;

    for (var i = 0; i < length; i++) {//for begin
      coords = getCoords(stickerBlocks[i]);
      stickerCoords = getCoords(stickers[i]);
      condition = parseInt(stickers[i].style.top) != parseInt(coords.bottom - coords.top - (stickerCoords.bottom - stickerCoords.top) - 1);

    if (coords.bottom < sum) {
       continue;    
    }

    if (coords.top < sum && stickers[i].style.position != 'fixed' && condition) {
      stickers[i].style.position = 'fixed';  
      stickers[i].style.top = upperBound + 'px';
    } 

     coords = getCoords(stickerBlocks[i]);
     stickerCoords = getCoords(stickers[i]);

    if (stickerCoords.bottom > coords.bottom) {
       stickers[i].style.position = 'relative'; 
       stickers[i].style.top = parseInt(coords.bottom - coords.top - (stickerCoords.bottom - stickerCoords.top) - 1) + 'px';
     } 

     coords = getCoords(stickerBlocks[i]);
     stickerCoords = getCoords(stickers[i]);
   
     if (stickerCoords.top < coords.top && i != 0) {
       stickers[i].style.position = 'relative';  
       stickers[i].style.top = 0 + 'px';
     }    
  
     condition = parseInt(stickers[i].style.top) == parseInt(coords.bottom - coords.top - (stickerCoords.bottom - stickerCoords.top) - 1);
     coords = getCoords(stickerBlocks[i]);
     stickerCoords = getCoords(stickers[i]);

     if (stickerCoords.top > sum && condition) {
       stickers[i].style.position = 'fixed';  
       stickers[i].style.top = upperBound + 'px';
       break;
     }

    }//for end

  }//onscroll end

}//onload end

</script>
</body>
</html>

Последний раз редактировалось bes, 15.06.2012 в 23:12.
Ответить с цитированием
Ответ


Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
скроллинг фотографий. haligali jQuery 1 13.09.2011 09:03
Скроллинг на javascript Armen Общие вопросы Javascript 3 12.05.2011 12:04
Скроллинг с задержкой vladpro Работа 1 24.01.2011 22:12
Скроллинг с задержкой vladpro Общие вопросы Javascript 3 24.01.2011 14:00