2015-11-03 95 views
6

選擇突出顯示的選項我通過AJAX獲取用戶ID和名稱,並使用Select2搜索它們,但我的用戶已請求通過按Tab鍵從下拉菜單中進行選擇的功能按Enter鍵處理它。這是我的選擇2聲明:Select2 4.0.0 AJAX - 通過標籤

$("#user-select").select2({ 
    ajax: { 
     url: "/api/User", 
     method: "get", 
     data: function (params) { 
      return { 
       search: params.term 
      }; 
     }, 
     beforeSend: function() { 
      $(".loading-results").text("Loading..."); 
     }, 
     processResults: function (data) { 
      return { 
       results: data 
      }; 
     }, 
     cache: true 
    }, 
    allowClear: true, 
    placeholder: "Enter a User ID or Name", 
    templateResult: function (data) { 
     return "(" + data.id + ") " + data.name; 
    }, 
    templateSelection: function (data) { 
     return "(" + data.id + ") " + data.name; 
    } 

「.select2-search__field」似乎是每當下拉的可見的,突出顯示的元素獲取類聚焦元素‘選擇2 - results__option - 突出’。

我試過一些解決方案,但似乎沒有任何工作,特別是因爲這個元素出現並隨時打開下拉菜單消失。不幸的是,我從我的嘗試中丟失了代碼,但是他們主要是通過在焦點輸入上點擊Tab時執行preventDefault,然後在突出顯示的元素上觸發單擊事件或觸發輸入上的Enter鍵。

我也嘗試調整selectOnClose選項,但似乎越野車在一般情況下,導致無盡的循環,當我有它正常運行,更少嘗試覆蓋它基於什麼鍵被按下。

[編輯]
所選解決方案的工作,但不考慮指定的templateResult,而不是顯示 「()未定義」。所以,我調整它作爲覆蓋選擇的選定選項添加突出顯示的答案,然後在該選擇上直接調用更改事件。

...(同初始選擇2)

}).on('select2:close', function (evt) { 
    var context = $(evt.target); 

    $(document).on('keydown.select2', function (e) { 
     if (e.which === 9) { // tab 
      var highlighted = context.data('select2').$dropdown.find('.select2-results__option--highlighted'); 

      if (highlighted) { 
       var data = highlighted.data('data'); 

       var id = data.id; 
       var display = data.name; 

       $("#user-select").html("<option value='" + id + "' selected='selected'>" + display + "</option>"); 
       $("#user-select").change(); 
      } 
      else { 
       context.val("").change(); 
      } 
     } 
    }); 
+0

你有想過嗎?遇到相同的問題。 – grant

+0

沒有骰子,在我發佈之前,我已經用盡了大部分的故障排除功能。如果你知道我應該在此標記以幫助人們找到可以回答的人,請告訴我,我會將其編輯到帖子中。 – MikeOShay

+1

非常感謝 - 我花了一些時間敲打它,也沒有運氣。我會讓你知道如果我想出任何東西:) – grant

回答

9

我一直在試圖找到一個解決這個問題爲好。
主要問題是,select2事件不能提供任何關於哪個鍵被按下的信息。

所以我想出了這個黑客來訪問select2上下文中的keydown事件。
我一直在測試它,以盡我所能,並且它看起來很完美。

selectElement 
.select2({ options ... }) 
.on('select2:close', function(evt) { 
    var context = $(evt.target); 

    $(document).on('keydown.select2', function(e) { 
     if (e.which === 9) { // tab 
      var highlighted = context 
           .data('select2') 
           .$dropdown 
           .find('.select2-results__option--highlighted'); 
      if (highlighted) { 
       var id = highlighted.data('data').id; 
       context.val(id).trigger('change'); 
      } 
     } 
    }); 

    // unbind the event again to avoid binding multiple times 
    setTimeout(function() { 
     $(document).off('keydown.select2'); 
    }, 1); 
}); 
+0

聰明!所以,當關閉事件正在進行時,您仍然捕獲關鍵事件,然後以編程方式進行設置。您仍然需要手動設置templateresult的值(如果您對其進行模板化)。我會接受你的並更新問題以顯示我的修改。 – MikeOShay

+0

是的,這是hacky地獄,但它現在的作品:) – Sniffdk

+0

OOF這是醜陋的,但似乎仍然是最好的選擇(如果我知道更好)。非常感謝。 – neanderslob

2

對於任何人希望得到片選工作與多選,這個工作對我來說:

$("#selected_ids").select2({ multiple: true }).on('select2:open', function(e) { selectOnTab(e) }); 

function selectOnTab(event){ 

    var $selected_id_field = $(event.target); 

    $(".select2-search__field").on('keydown', function (e) { 
    if (e.which === 9) { 
     var highlighted = $('.select2-results__option--highlighted'); 

     if (highlighted) { 
     var data = highlighted.data('data'); 
     var vals = $selected_id_field.val(); 
     if (vals === null){ 
      vals = []; 
     } 
     vals.push(data.id) 
     $selected_id_field.val(vals).trigger("change") 
     } 
    } 
    }); 
} 

目前,這限制了我每頁一個領域,但它做的工作。

謝謝MikeOShay和Sniffdk爲此深入探討。
目前有可能解決這個對我們來說是開放的問題:

https://github.com/select2/select2/issues/3359

+1

感謝您的解決方案。對於其他人而言,調用'trigger(「change」)'不會觸發通常在選擇選項時看到的DOM事件('select2:open','select2:close'等)。 – Marklar

+0

我看到一些iffy keydown行爲,有時在按下按鍵時會調用五次,有時候根本不會。你有什麼想法嗎? – mmking

+0

@mmking有趣的是,從引用像[this]這樣的討論(https://stackoverflow.com/questions/9098168/jquery-keypress-event-fires-repeatedly-when-key-is-held-but-not-on-所有鍵)我相信這是keydown事件的正常行爲。 –

7

的selectOnClose功能似乎是穩定的4.0.3,和更簡單的解決方案:

$("#user-select").select2({ 
    ... 
    selectOnClose: true 
}); 

這是可能的模板的使用干擾了這個功能,我沒有使用它,所以我沒有測試過。

+0

with selectOnClose,即使您單擊頁面正文中的其他位置(未單擊select中的選項),也會選擇該選項。如果這對你來說是個問題,你能找到解決辦法嗎? – Marklar

+0

在我的情況下,這不是一個問題,所以我沒有看到解決方法。我的猜測是,你將不得不使用@Sniffdk的解決方案,以便只響應TAB,而不是關閉選擇的其他方式。 –

+0

感謝您花時間回覆。對於處於同一情況的其他人,Sniffdk的解決方案不適用於多選。 JP的解決方案,但通常的DOM事件不會被解僱。 – Marklar

0

您可以簡單地改變選擇二源頭控制,只有一行:如果

其他(關鍵=== KEYS.ENTER)

否則,如果(鍵=== KEYS.ENTER | | 關鍵=== KEYS.TAB

從這:

this.on('keypress', function (evt) { 
    var key = evt.which; 

    if (self.isOpen()) { 
    if (key === KEYS.ESC || key === KEYS.TAB || 
     (key === KEYS.UP && evt.altKey)) { 
     self.close(); 

     evt.preventDefault(); 
    } else if (key === KEYS.ENTER) { 
     self.trigger('results:select', {}); 

     evt.preventDefault(); 

對此

this.on('keypress', function (evt) { 
    var key = evt.which; 

    if (self.isOpen()) { 
    if (key === KEYS.ESC || (key === KEYS.UP && evt.altKey)) { 
     self.close(); 

     evt.preventDefault(); 
    } else if (key === KEYS.ENTER || key === KEYS.TAB) { 
     self.trigger('results:select', {}); 

     evt.preventDefault(); 

的變化可以在源文件的src/JS /選擇2/core.js中完成,或在編譯的版本。當我應用此更改時,我修改了src/js/select2/core.js並執行gruntfile.js來再次編譯select2庫。這個解決方案不是一種解決方法,但是對於select2來說卻是很好的功能。

+0

我相信這個解決方案是作爲pull請求提交的,但select2的維護者說這是一個突破性變化,不會合並:https://github.com/select2/select2/pull/4325#issuecomment-229234605 – Marklar

+0

@Marklar ,所有的測試和一切似乎都沒有問題,完全沒有問題。我不知道是誰稱之爲「突變」,爲什麼。到目前爲止,我一直在使用提出的解決方案沒有任何問 –

+0

感謝您花時間回覆並提供解決方案。如果你遇到任何不明原因的問題,我想這可能是一個突破性的變化是需要記住的。如果你看看我在上次評論中提供的鏈接,可以看到Kevin Brown(select2的維護者)表示這是一個突破性改變,而selectOnClose是他的推薦。 – Marklar

0

玩過所有這些解決方案後,這一個似乎趕上了大多數案件,併爲我工作最好。注意我正在使用select2 4.0.3但是不喜歡selectOnClose,如果你有多個select2盒子有多個它會造成嚴重破壞!

var fixSelect2MissingTab = function (event) { 
    var $selected_id_field = $(event.target); 

    var selectHighlighted = function (e) { 
     if (e.which === 9) { 
      var highlighted = $selected_id_field.data('select2').$dropdown.find('.select2-results__option--highlighted'); 

      if (highlighted) { 
       var data = highlighted.data('data'); 
       if (data) { 
        var vals = $selected_id_field.val(); 
        if (vals === null) { 
         vals = []; 
        } 
        if (vals.constructor === Array) { 
         vals.push(data.id); 
        } else { 
         vals = data.id; 
        } 
        $selected_id_field.val(vals).trigger("change"); 
       } 
      } 
     } 
    }; 

    $('.select2-search__field').on('keydown', selectHighlighted);  
} 

$(document).on('select2:open', 'select', function (e) { fixSelect2MissingTab(e) }); 
$(document).on('select2:close', 'select', function (e) { 
    //unbind to prevent multiple 
    setTimeout(function() { 
     $('.select2-search__field').off('keydown'); 
    }, 10); 
}); 

這個解決方案的好處是,它是通用的,可以在框架代碼應用於將連工作動態添加選擇2盒。