从上方或下方获取元素

时间:2015-01-16 01:36:52

标签: javascript css

有没有办法让视觉元素位于某个元素的下方或上方?

元素是列表的一部分,我希望能够使用箭头键在列表中导航。左/右移动到上一个/下一个兄弟,但我不知道如何处理上/下。

$(document).on('keydown', function(e) {
  console.log(e.which);

  var current = $('li.selected');

  switch (e.which) {
    case 37:
      current.prev().addClass('selected').siblings().removeClass('selected');
      break;

    case 39:
      current.next().addClass('selected').siblings().removeClass('selected');
      break;

    default:
      return true;
  }

  e.preventDefault();
});

$('li').on('click', function(e) {
  $(this).addClass('selected').siblings().removeClass('selected');
});
ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
}
li {
  width: 50px;
  height: 50px;
  margin: 5px;
  border: 1px solid red;
}
li.selected {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="selected"></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

3 个答案:

答案 0 :(得分:3)

我写了一个函数来搜索兄弟节点并检查它们在元素宽度范围内的左边位置。

function findDown(node) {
  return findInSiblings(node, node.nextAll());
}

function findUp(node) {
  return findInSiblings(node, node.prevAll());
}

function findInSiblings(node, siblings) {
  var x = node.offset().left,
    w = node.width() / 2;
  for (var i = 0; i < siblings.length; i++) {
    var sibling = $(siblings[i]);
    if (sibling[0].nodeType === 1) {
      var offset = sibling.offset().left;
      if (offset - w < x && offset + w > x) {
        return sibling;
      }
    }
  }
  return null;
}

演示

$(document).on('keydown', function(e) {
  var current = $('li.selected');
  var node = getNode(current, e.which);
  if (node == null) {
    return true;
  }
  select(node);
  e.preventDefault();
});

$('li').on('click', function(e) {
  select($(this));
});

function select(node) {
  node.addClass('selected').siblings().removeClass('selected');
}

function getNode(selected, direction) {
  switch (direction) {
    case 37: // Left
      return selected.prev();
    case 38: // Up
      return findUp(selected);
    case 39: // Right
      return selected.next();
    case 40: // Down
      return findDown(selected);
  }
  return null;
}

function findDown(node) {
  return findInSiblings(node, node.nextAll());
}

function findUp(node) {
  return findInSiblings(node, node.prevAll());
}

function findInSiblings(node, siblings) {
  var x = node.offset().left,
    w = node.width() / 2;
  for (var i = 0; i < siblings.length; i++) {
    var sibling = $(siblings[i]);
    if (sibling[0].nodeType === 1) {
      var offset = sibling.offset().left;
      if (offset - w < x && offset + w > x) {
        return sibling;
      }
    }
  }
  return null;
}
ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
}
li {
  width: 50px;
  height: 50px;
  margin: 5px;
  border: 1px solid red;
}
li.selected {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="selected"></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

答案 1 :(得分:1)

一些想法:

1)您可以随时计算每行显示的数字,因为您可以获得页面的宽度。

2)您可以使用document.elementFromPoint并测试低于当前元素的点。

答案 2 :(得分:1)

获取当前元素的offsetLeft属性。

var currentLeft = current.prop("offsetLeft");

查看每个下一个或上一个元素,直到找到具有相同offsetLeft属性的元素。

case 38:
  var el = current.prev();
  while (el.length && el.prop("offsetLeft") != currentLeft) {
    el = el.prev();
  }
  if (el.length) {
    current.removeClass("selected");
    el.addClass("selected");
  }
  break;

&#13;
&#13;
$(document).on('keydown', function(e) {
  console.log(e.which);

  var current = $('li.selected');
  var currentLeft = current.prop("offsetLeft");

  switch (e.which) {
case 37:
  current.prev().addClass('selected').siblings().removeClass('selected');
  break;

case 39:
  current.next().addClass('selected').siblings().removeClass('selected');
  break;

case 38:
  var el = current.prev();
  while (el.length && el.prop("offsetLeft") != currentLeft) {
    el = el.prev();
  }
  if (el.length) {
    current.removeClass("selected");
    el.addClass("selected");
  }
  break;

case 40:
  var el = current.next();
  while (el.length && el.prop("offsetLeft") != currentLeft) {
    el = el.next();
  }
  if (el.length) {
    current.removeClass("selected");
    el.addClass("selected");
  }
  break;

default:
  return true;
  }

  e.preventDefault();
});

$('li').on('click', function(e) {
  $(this).addClass('selected').siblings().removeClass('selected');
});
&#13;
ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
}
li {
  width: 50px;
  height: 50px;
  margin: 5px;
  border: 1px solid red;
}
li.selected {
  background: red;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="selected"></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>
&#13;
&#13;
&#13;