2013-06-19 2 views
0

Я создаю сетку, которая может иметь n rows и разделена на два вида: leftChild и rightChild. У leftChild есть такое же количество строк, что и rightChild, но leftChild остается на своем месте. Единственное отличие от rightChild заключается в том, что его можно прокручивать по горизонтали. Когда я наводил элемент leftChild или rightChild, я хочу добавить какой-то зависающий эффект ... это легко, но я хочу добавить эффект зависания во всей строке. Поэтому, если я навешиваю над третьей строкой в ​​leftChild, я хочу выделить третью строку в rightChild.CSS/JS: Наведите указатель мыши на элемент выделяет другой элемент

Теперь, в идеале, мне бы понравилось полное решение для CSS, подобное this, но это невозможно, потому что мои строки не следуют сразу друг за другом. Я пытался подумать о другом способе решения этого вопроса, но это не представляется возможным с помощью прямого CSS.

Введите JavaScript. Я думаю, что следующий шаг - объединить JavaScript с CSS. Я могу добавить эффект зависания в строку, а затем использовать JavaScript для добавления класса зависания в соответствующую строку в другом дочернем элементе. Это довольно просто с jQuery, но я ищу собственный подход к JavaScript.

Основной подход, о котором я думаю, заключается в добавлении mouseenter и mouseleave к каждому элементу класса строки. Мне не нравится этот подход, потому что тогда я настраиваю 2 прослушивателя событий для каждого элемента строки ... что кажется немного неэффективным. Во всяком случае, когда вы входите, вы захватываете номер строки того, что вы наведете, а затем добавьте класс hover ко всем этим элементам номера строки. Когда вы уезжаете, вы просто находите все элементы с зависанием и удаляете соответственно. Соответствующий код выглядит следующим образом:

HTML

<body onload="loaded()"> 
    <div id="parent"> 
     <div id="leftChild"> 
      <div>left child</div> 
      <div class="row row1">some content</div> 
      <div class="row row2">other content</div> 
      <div class="row row3">more content</div> 
     </div> 
     <div id="rightChild"> 
      <div>right child</div> 
      <div class="row row1"> 
       <span class="col1">column 1 content</span> 
       <span class="col2">column 2 content</span> 
       <span class="col3">column 3 content</span> 
       <span class="col4">column 4 content</span> 
       <span class="col5">column 5 content some really long content to trigger scrolling just for the purpose of this example</span> 
      </div> 
      <div class="row row2"> 
       <span class="col1">column 1 content</span> 
       <span class="col2">column 2 content</span> 
       <span class="col3">column 3 content</span> 
       <span class="col4">column 4 content</span> 
       <span class="col5">column 5 content some really long content to trigger scrolling just for the purpose of this example</span> 
      </div> 
      <div class="row row3"> 
       <span class="col1">column 1 content</span> 
       <span class="col2">column 2 content</span> 
       <span class="col3">column 3 content</span> 
       <span class="col4">column 4 content</span> 
       <span class="col5">column 5 content some really long content to trigger scrolling just for the purpose of this example</span> 
      </div> 
     </div> 
    </div> 
</body> 

JS

function loaded() { 
    /*var parent = document.getElementById('parent'); 
    parent.onmouseenter = function(event) { 
     console.log(event.target); 
    }; 
    parent.onmouseleave = function(event) { 
     console.log(event.target); 
    };*/ 

    var rows = document.getElementsByClassName('row'); 
    for (var i = 0; i < rows.length; i++) { 
     rows[i].onmouseenter = function(event) { 
      var splits = event.target.className.split(" "); 
      var elems = document.getElementsByClassName(splits[splits.length - 1]); 
      for (var j = 0; j < elems.length; j++) { 
       elems[j].className += " hover"; 
      } 
     }; 

     rows[i].onmouseleave = function(event) { 
      var hovers = document.getElementsByClassName('hover'); 
      var len = hovers.length; 
      for (var j = 0; j < len; j++) { 
       hovers[0].className = hovers[0].className.replace(/\shover(\s|$)/, ''); 
      } 
     }; 
    } 
} 

CSS

.row:hover, .hover { 
    background-color: lightblue; 
} 

.row { 
    height: 50px; 
    padding: 5px; 
    white-space: nowrap; 
} 

.row > span { 
    display: inline-block; 
    border: 5px solid black; 
} 

#leftChild, #rightChild { 
    float: left; 
} 

#rightChild { 
    width: 300px; 
    overflow: auto; 
} 

#rightChild .row { 
    display: inline-block; 
} 

jsFiddle: Here

Так что я хотел бы знать несколько вещей.

  1. Возможно ли это с помощью простого CSS?
  2. Если нет, то как я могу сделать мой подход более эффективным?
  3. Эффективно ли иметь один обработчик событий или несколько обработчиков событий?

Я знаю, что много задаю здесь, но мне не нравится задавать несколько вопросов, особенно если мне придется повториться. Буду признателен за любую помощь. Благодаря!

+0

Мм .. использовать таблицу? :/ –

+0

Я бы предпочел, и я на самом деле пытаюсь использовать SlickGrid (который использует divs/spans) ... это просто проблема с игрушкой. – incutonez

ответ

0

на основе this jsPerf, прямой подход JavaScript, что я есть самый быстрый, гибридный подход подходит к концу второй - и я имею в виду действительно близкий к натурному JS-подходу - и (почти полностью) подход jQuery приходит в мертвом последнем - и он очень медленный по сравнению с другим два.

Все они видны на this jsFiddle.

JS

// Native JS approach... fastest (according to my jsPerf http://jsperf.com/removeclass-vs-native-js-remove-class/2) 
function loaded() { 
    var rows = document.getElementsByClassName('row'); 
    for (var i = 0; i < rows.length; i++) { 
     rows[i].onmouseenter = function(event) { 
      var row = this.className.match(/row-[\d]+/); 
      var elems = document.getElementsByClassName(row[0]); 
      for (var j = 0; j < elems.length; j++) { 
       elems[j].className += " hover"; 
      } 
     }; 

     rows[i].onmouseleave = function(event) { 
      var hovers = document.getElementsByClassName('hover'); 
      var len = hovers.length; 
      for (var j = 0; j < len; j++) { 
       hovers[0].className = hovers[0].className.replace(/\shover(\s|$)/, ''); 
      } 
     }; 
    } 
} 

// jQuery approach (slowest) 
/*$(document).ready(function() { 
    $('.row').on('mouseenter', function(event) { 
     var row = this.className.match(/row-[\d]+/); 
     $('.' + row).addClass('hover'); 
    }); 

    $('.row').on('mouseleave', function(event) { 
     $('.hover').removeClass('hover'); 
    }); 
});*/ 

// Hybrid approach (basically as fast as native JS approach) 
/*$(document).ready(function() { 
    var rows = document.getElementsByClassName('row'); 
    for (var i = 0; i < rows.length; i++) { 
    rows[i].onmouseenter = function(event) { 
     var row = this.className.match(/row-[\d]+/); 
     $('.' + row[0]).addClass('hover'); 
    }; 

     rows[i].onmouseleave = function(event) { 
      $('.hover').removeClass('hover'); 
     }; 
    } 
});*/ 
0
  1. через css с этой структурой: нет, не до того, как css уровень 4 можно использовать.
  2. использовать this и проверить className приложить к ней в то время как новое правило
  3. moouse зависания & мышь уходящую?

я получаю это: с помощью JQuery, но для теста я удалил класс .row и сохранил пронумерованный один

$("[class*='row']").hover(
    function() { 
     $('head').append('<style class="'+this.className+'" rel="stylesheet" > .'+this.className+' {background-color:lightblue;} </style>'); 
$(this).mouseleave(function() { $('style.'+this.className).remove();}); 
}); 

http://codepen.io/gcyrillus/pen/bhglr

+0

Но это более эффективно, чем мой родной подход к JavaScript? Я думаю, что ответ «нет». Кроме того, он не выделяет всю строку ... он прыгает через разделительную панель. – incutonez

+0

Я поставил разницу между ними, чтобы показать, что это были два разных элемента. Я использовал jQuery, потому что вы можете использовать простой CSS-подобный селектор. Конечно, если вам нужен jQuery для этой единственной функции на вашем сайте, это будет avearge 30KO для одного раза для посетителя, если он еще не находится в кеше браузера. –

+0

Правильно, но jQuery добавляет немного накладных расходов, поэтому я думаю, что прямое решение JS по-прежнему лучше ... в основном все это складывается, как только моя сетка достаточно велика. – incutonez

Смежные вопросы