1

div의 집합이 모두 같고 높이/너비가 float:left 인 목록이 있으므로 서로 옆에 앉아 그 부모가 항목과 결합 된 것보다 작 으면 아래로 접을 수 있습니다.jQuery를 사용하여 위/아래/왼쪽/오른쪽 키보드 탐색?

꽤 표준입니다. 그러나 당신이 위/아래 화살표 키는 것을 알 것이다, 나는 아래의 코드를 사용하여 이전/다음 키보드 탐색을 추가 한 enter image description here

: 이것은 이런 식으로 뭔가를 제공, 트위터 부트 스트랩 아이콘의 목록을 만드는 것입니다 왼쪽/오른쪽 함수를 호출하도록 매핑됩니다. 내가 어떻게 해야할지 모르겠지만 위/아래 탐색을 실제로하는 것입니다. 이 같은

JsFiddle

(function ($) { 
    $.widget("ui.iconSelect", { 

     // default options 
     options: { 

     }, 

     $select: null, 

     $wrapper: null, 

     $list: null, 

     $filter: null, 

     $active: null, 

     icons: {}, 

     keys: { 
      left: 37, 
      up: 38, 
      right: 39, 
      down: 40 

     }, 

     //initialization function 
     _create: function() { 

      var that = this; 
      that.$select = that.element; 

      that.$wrapper = $('<div class="select-icon" tabindex="0"></div>'); 
      that.$filter = $('<input class="span12" tabindex="-1" placeholder="Filter by class name..."/>').appendTo(that.$wrapper); 
      that.$list = $('<div class="select-icon-list"></div>').appendTo(that.$wrapper); 


      //build the list of icons 
      that.element.find('option').each(function() { 
       var $option = $(this); 
       var icon = $option.val(); 

       that.icons[icon] = $('<a data-class="' + icon + '"><i class="icon ' + icon + '"></i></a>'); 

       if ($option.is(':selected')) { 
        that.icons[icon].addClass('selected active'); 
       } 

       that.$list.append(that.icons[icon]); 
      }); 

      that.$wrapper.insertBefore(that.$select); 
      that.$select.addClass('hide'); 



      that._setupArrowKeysHandler(); 
      that._setupClickHandler(); 
      that._setupFilter(); 
      that.focus('selected'); 
     }, 

     focus: function (type) { 
      var that = this; 
      if (that.$active === null || that.$active.length == 0) { 
       if (type == 'first') { 
        that.$active = that.$list.find('a:visible:first'); 
       } else if (type == 'last') { 
        that.$active = that.$list.find('a:visible:last'); 
       } else if (type == 'selected') { 
        that.$active = that.$list.find('a.selected:visible:first'); 
        that.focus('first'); 
       } 
      } 
      that.$active.addClass('active'); 
      var toScroll = ((that.$list.scrollTop() + that.$active.position().top)-that.$list.height()/2)+that.$active.height()/2; 
      //that.$list.scrollTop((that.$list.scrollTop() + top)-that.$list.height()/2); 
      that.$list.stop(true).animate({ 
       scrollTop: toScroll, 
       queue: false, 
       easing: 'linear' 
      }, 200); 

      if (type === 'selected') { 
       return false; 
      } 

      that.$select.val(that.$active.data('class')); 
      that.$select.trigger('change'); 

     }, 

     _setupArrowKeysHandler: function() { 
      var that = this; 

      that.$wrapper.on('keydown', function (e) { 
       switch (e.which) { 
        case that.keys.left: 
         that.moveLeft(); 
         break; 
        case that.keys.up: 
         that.moveUp(); 
         break; 
        case that.keys.right: 
         that.moveRight(); 
         break; 
        case that.keys.down: 
         that.moveDown(); 
         break; 
        case 16: 
         return true; 
        case 9: 
         return true; 
        break; 
        default: 
         that.$filter.focus(); 
         return true; 
       } 
       return false; 
      }); 
     }, 

     _setupFilter: function(){ 
      var that = this; 

      that.$filter.on('keydown keyup keypress paste cut change', function(e){ 
       that.filter(that.$filter.val()); 
      }); 
     }, 

     _setupClickHandler: function() { 
      var that = this; 
      that.$list.on('click', 'a', function() { 
       that.$wrapper.focus(); 
       that.$active.removeClass('active'); 
       that.$active = $(this); 
       that.focus('first'); 
      }); 
     }, 

     moveUp: function() { 
      var that = this; 
      return that.moveLeft(); 
     }, 

     moveDown: function() { 
      var that = this; 
      return that.moveRight(); 
     }, 

     moveLeft: function() { 
      var that = this; 
      that.$active.removeClass('active'); 
      that.$active = that.$active.prevAll(':visible:first'); 
      that.focus('last'); 
      return false; 
     }, 

     moveRight: function() { 
      var that = this; 
      that.$active.removeClass('active'); 
      that.$active = that.$active.nextAll(':visible:first'); 
      that.focus('first'); 
      return false; 
     }, 

     filter: function(word){ 
      var that = this; 
      var regexp = new RegExp(word.toLowerCase()); 
      var found = false; 
      $.each(that.icons, function(i, $v){ 
       found = regexp.test(i); 
       if(found && !$v.is(':visible')){ 
        $v.show(); 
       } else if(!found && $v.is(':visible')){ 
        $v.hide(); 
       } 
      }); 
     } 

    }); 
})(jQuery); 
+0

각 행에 많은 항목이 포함되어 있기 때문에 왼쪽/오른쪽 기능을 자주 호출 할 수 있습니다. 코드를 살펴 보지 않고도 가장 쉬운 방법입니다.) 이제 수행 할 것입니다 ... – luk2302

+0

@ luk2302, 가능한 해결책 예 하지만 행에 몇 개의 항목이 포함되는지 계산하는 방법은 무엇입니까? 나는'$ wrapper.width() mod $ element.width()'를 할 수 있다고 생각하지만, 전체적인 접근법은 나에게 다소 해로운 것처럼 보인다. 나는 http://www.zehnet.de/2010/11/19/document-elementfrompoint-a-jquery-solution/을 조사해 왔지만 래퍼와 관련된 점을 만드는 방법을 찾을 수 없다 ... – Hailwood

+0

링크에서 제공 한 코드 만 사용하면 무엇이 잘못됩니까? 만약 당신이 코드를 붙여 넣기 만하면된다. 위의 요소를'$ .elementFromPoint ($.) .offset(). left, $ (that. $ active) .offset.() .top-10);'. 아래의 경우에는 하나의 항목 자체의 높이를 10 + 높이를 추가해야하지만 고정되어 있습니다. 코드에서 활성 속성을 변경하는 방법을 모르므로 응답을 제공하지 않고 주석 만 제공합니다. – luk2302

답변

2

은 아마 뭔가 : 기본적으로 http://jsfiddle.net/QFzCY/

var blocksPerRow = 4; 

$("body").on("keydown", function(e){ 
    var thisIndex = $(".selected").index(); 
    var newIndex = null; 
    if(e.keyCode === 38) { 
     // up 
     newIndex = thisIndex - blocksPerRow; 
    } 
    else if(e.keyCode === 40) { 
     // down 
     newIndex = thisIndex + blocksPerRow;  
    } 
    if(newIndex !== null) { 
     $(".test").eq(newIndex).addClass("selected").siblings().removeClass("selected"); 
    }  
}); 

, 거기 행에 다음 현재 인덱스를 찾아 빼기 나에 그 금액을 추가 얼마나 많은 항목 설정 새 색인을 통해 다음 요소를 선택하십시오.

당신이 얼마나 많은 블록 행당 알고 싶다면, 당신이 할 수 있습니다 : 당신의 '엣지'의 경우에 대처하기 위해

var offset = null; 
var blocksPerRow = 0; 
$(".test").each(function(){ 
    if(offset === null) { 
     offset = $(this).offset().top; 
    } 
    else if($(this).offset().top !== offset) { 
     return false; 
    } 
    blocksPerRow++; 
}); 

을, 당신은 할 수 :

if(newIndex >= $(".test").length) { 
    newIndex = $(".test").length - newIndex; 
} 
+0

이것은 좋을 것입니다. 그러나 사용자가 맨 아래 줄에 있고 아래로 누르면 우리는 맨 위 줄에 상대적인 항목을 선택하고 위로 올라가는 경우에도 "말 그대로"가장자리 경우를 어떻게 처리할까요? ? – Hailwood

+0

'가장자리'사례로 답변이 업데이트되었습니다. – mibbler

+0

데모에서 볼 수 있듯이, 필터 상자가 하나 더 있으므로 필터 상자가있어 사용자가 항목을 필터링하면 어떻게 든 필터 상자를 제외해야합니다. – Hailwood

1
moveUp: function() { 
     var that = this; 
     var index = $(this).index(); 
     var containerWidth = parseInt($('.select-icon-list').innerWidth(), 10); 
     var iconWidth = parseInt($('.select-icon-list > a').width(), 10); 
     var noOfCols = Math.floor(containerWidth/iconWidth); 
     var newIndex = ((index - noOfCols) < 0) ? index : (index - noOfCols); 
     var elem = $('.select-icon-list > a')[index]; 
    }, 

정적 인 캐시를 캐시합니다.

+0

이것은 좋을 것입니다. 그러나 사용자가 맨 아래 행에 있고 아래로 누를 경우 우리는 맨 위 행에 상대 항목을 선택하고 올라 가기 위해 상대 항목을 선택하려는 경우 어떻게 "말 그대로"가장자리 경우를 처리합니까? ? – Hailwood

+0

난 그냥 그런 가장자리 사건 위트'((인덱스 - noOfCols) <0) 방지입니까? 색인 : (색인 - noOfCols)'와 같은 항목에 남아 있습니다. – sabithpocker