2012-10-24 233 views
11

我有一個select元素,分組option s。當單擊option時,我需要在optgroup中選擇(或取消選擇)所有option。我還需要能夠一次選擇多個optgroup選擇optgroup中的所有選項

我希望它的工作方式是這樣的:

  • 如果沒有選擇,我想點擊一個選項,並得到所有的選項中選擇的相同OPTGROUP。
  • 如果已經選擇了一個或多個optgroup,我想單擊另一個optgroup中的一個選項,然後選擇所有這些選項。
  • 如果已經選擇了一個或多個optgroup,我希望能夠按住Ctrl鍵並單擊未選擇的optgroup中的某個選項,並且也可以選擇該optgroup中的所有選項。
  • 如果已經選擇了一個或多個optgroup,我希望能夠在所選optgroup中按住Ctrl鍵單擊一個選項,並取消選擇該組中的所有選項。

看着堆棧溢出其他答案我創建了以下內容:

HTML:

<select multiple="multiple" size="10"> 
    <optgroup label="Queen"> 
     <option value="Mercury">Freddie</option> 
     <option value="May">Brian</option> 
     <option value="Taylor">Roger</option> 
     <option value="Deacon">John</option> 
    </optgroup> 
    <optgroup label="Pink Floyd"> 
     <option value="Waters">Roger</option> 
     <option value="Gilmour">David</option>  
     <option value="Mason">Nick</option>     
     <option value="Wright">Richard</option> 
    </optgroup> 
</select> 

的jQuery:

$('select').click(selectSiblings); 
function selectSiblings(ev) { 
    var clickedOption = $(ev.target); 
    var siblings = clickedOption.siblings(); 
    if (clickedOption.is(":selected")) { 
     siblings.attr("selected", "selected"); 
    } else { 
     siblings.removeAttr("selected"); 
    } 
}​ 

我做了這裏一個例子:http://jsfiddle.net/mflodin/Ndkct/ (可悲的是jsFiddle似乎不再支持IE8)。

這在Firefox(16.0)中按預期工作,但在IE8中根本不起作用。從其他答案中我發現IE8無法處理optgroupoption上的click事件,這就是我將其綁定到select然後使用$(ev.target)的原因。但在IE8中,$(ev.target)仍然指向整個select而不是點擊的option。如何找出哪個option(或包含optgroup)被點擊以及它是否被選中或取消選擇?

另一個意想不到的行爲,但比較小的是,在Chrome(20.0)中,取消選擇不會發生,直到鼠標離開select。有人知道這個解決方法嗎?

回答

-1

根據您的問題選擇/取消選擇所有選項。 你可以嘗試下面的代碼,可能會對你有所幫助。

代碼:

JavaScript代碼:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"> 

 $(function(){ 

       $('#allcheck').click(function(){ 
       var chk=$('#select_option >optgroup > option'); 
       chk.each(function(){ 
        $(this).attr('selected','selected'); 
      }); 
    }); 
$('#alluncheck').click(function(){ 

       var chk=$('#select_option >optgroup > option'); 
       chk.each(function(){ 
       $(this).removeAttr('selected'); 
      }); 
    });}); 

HTML代碼:

 <select multiple="multiple" size="10" id="select_option" name="option_value[]"> 
      <optgroup label="Queen"> 
      <option value="Mercury">Freddie</option> 
      <option value="May">Brian</option> 
      <option value="Taylor">Roger</option> 
      <option value="Deacon">John</option> 
     </optgroup> 
     <optgroup label="Pink Floyd"> 
      <option value="Waters">Roger</option> 
      <option value="Gilmour">David</option>  
      <option value="Mason">Nick</option>     
      <option value="Wright">Richard</option> 
     </optgroup> 
</select> 
<br> 
     <strong>Select&nbsp;&nbsp;<a style="cursor:pointer;" id="allcheck">All</a> 
    &nbsp;|&nbsp;<a style="cursor:pointer;" id="alluncheck">None</a></strong> 
+0

這有什麼做我想做的。我想單擊一個'選項'而不是一個鏈接來選擇所有'選項' – mflodin

-1

希望這將工作

$("#SelectID").live("click",function() { 
var elements = this.options; //or document.getElementById("SelectID").options; 
for(var i = 0; i < elements.length; i++){ 
    if(!elements[i].selected) 
    elements[i].selected = true; 
} 
} 
+0

這不是我想要的。這將選擇所有'optgroup'中的所有'option'元素。它應該只選擇那些與被點擊的選項相同的'optgroup'。 – mflodin

+0

您還缺少實時功能的結束括號。 – mflodin

0

此問題解決了,你只需要選擇初始化後,添加此代碼。

$('.chzn-results .group-result').each(function() { 
    var self  = $(this) 
     , options = $('~li', self) 
     , next = options.filter('.group-result').get(0) 
    ; 
    self.data('chzn-options', options.slice(0, options.index(next))); 
}) 
.click(function() { 
    $(this).data('chzn-options').mouseup() 
}) 
.hover(function() { 
    $(this).data('chzn-options').addClass('highlighted'); 
}, function() { 
    $(this).data('chzn-options').removeClass('highlighted'); 
}) 
.css({ cursor: 'pointer' }) 

由於adriengibrat是發佈此修復程序在GitHub上:
https://github.com/harvesthq/chosen/issues/323

+0

但我沒有使用選擇... – mflodin

1

由於Internet Explorer作爲第10版中仍然不支持optgroupoption,任何跨瀏覽器的解決方案,任何有用的事件這個問題不能依賴於這些要素的直接事件。

注: MSDN文檔聲稱optgroup支持click事件,但作爲IE 10的仍似乎沒有成爲現實:http://msdn.microsoft.com/en-us/library/ie/ms535876(v=vs.85).aspx

我測試在鉻27,火狐20,Safari瀏覽器6以下,IE 9和IE 10(我目前無法訪問IE 8)。

這裏是你可以玩一個例子:http://jsfiddle.net/potatosalad/Ndkct/38/

// Detect toggle key (toggle selection) 
$('select') 
    .on('mousedown', function(event) { 
     // toggleKey = Command for Mac OS X; Control for others 
     var toggleKey = (!event.metaKey && event.ctrlKey && !(/Mac OS/.test(navigator.userAgent))) ? event.ctrlKey : event.metaKey; 
     if (toggleKey === true) { 
      $(this).data('toggleKey', true); 
     } 
     $(this).data('_mousedown', true); 
    }) 
    .on('mouseup', function() { 
     $(this).data('_mousedown', null); 
    }); 
// Chrome fix for mouseup outside select 
$(document).on('mouseup', ':not(select)', function() { 
    var $select = $('select'); 
    if ($select.data('_mousedown') === true) { 
     $select.data('_mousedown', null); 
     $select.trigger('change'); 
    } 
}); 

$('select') 
    .on('focus', storeState) 
    .on('change', changeState); 

function storeState() { 
    $(this).data('previousGroup', $('option:selected', this).closest('optgroup')); 
    $(this).data('previousVal', $(this).val()); 
}; 

function changeState() { 
    var select = this, 
     args = Array.prototype.slice.call(arguments); 

    var previousGroup = $(select).data('previousGroup'), 
     previousVal = $(select).data('previousVal'); 
    var currentGroup = null, 
     currentVal = $(select).val(); 

    var selected = $('option:selected', select), 
     groups = selected.closest('optgroup'); 

    console.log("[change] %o -> %o", previousVal, currentVal); 

    if ((previousVal === currentVal) && (groups && groups.length == 1)) { 
     // selected options have not changed 
     // AND 
     // only 1 optgroup is selected 
     // -> do nothing 
    } else if (currentVal === null || currentVal.length === 0) { 
     // zero options selected 
     // -> store state and do nothing 
     storeState.apply(select, args); 
    } else { // a select/deselect change has occurred 
     if ($(select).data('toggleKey') === true 
      && (previousVal !== null && previousGroup !== null && groups !== null) 
      && (previousVal.length > currentVal.length) 
      && (previousGroup.length === groups.length) 
      && (previousGroup.get(0) === groups.get(0))) { 
      // options within the same optgroup have been deselected 
      // -> deselect all and store state 
      $(select).val(null); 
      storeState.apply(select, args); 
     } else if (currentVal.length === 1) { 
      // single option selected 
      // -> use groups 
      currentGroup = groups; 
     } else if (groups.length === 1) { 
      // multiple options selected within same optgroup 
      // -> use groups 
      currentGroup = groups; 
     } else { 
      // multiple options selected spanning multiple optgroups 
      // -> use last optgroup 
      currentGroup = groups.last(); 
     } 
    } 

    $(select).data('toggleKey', null); 

    if (currentGroup !== null) { 
     $('optgroup', select).not(currentGroup).children(':selected').attr('selected', false); 
     $(currentGroup).children(':not(:selected)').attr('selected', true); 
     storeState.apply(select, args); 
    } 
}; 

它通過存儲select元件上的先前選擇的組和選項以及確定哪些optgroup應選擇(或取消選擇)。

某些行爲可以根據開發人員的需求進行更改。例如,在選擇多個options的情況下跨越多個optgroups(通過點擊和拖動下如屏幕截圖所示):

multiple options selected spanning multiple optgroups

默認的衝突解決這種情況是要始終使用最後optgroup,但可以更改爲始終使用第一個選項或具有最多已選選項的optgroup

+0

這對於選擇單個optgroup非常適用,但不適用於多個。我會更新我的問題,使其更清楚我所需要的。根據我的需要修改代碼可能很簡單,但不幸的是我現在沒有時間查看它。儘管如此,我還是會爲您的工作獎勵+1,以獲取有關IE兼容性的信息。 – mflodin

0
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 


$(document).ready(function() { 
    $('select').click(function(tar) { 
     var justClickValue = tar.target.value; 

     var selectedGroup = $('option[value="'+justClickValue+'"]').parent(); 

     if (selectedGroup.hasClass("allSelected")) { 
      selectedGroup.removeClass("allSelected"); 
      $("option").each(function() { 
       $(this).removeAttr("selected"); 
      }); 
     } else { 
      $(".allSelected").removeClass("allSelected"); 
      selectedGroup.addClass("allSelected"); 
      $(".allSelected option").each(function() { 
       $(this).attr("selected", "selected"); 
      }); 
     } 
    }); 
}); 
3

不是一個答案的選擇選項跨瀏覽器的問題,具體的問題,我認爲這是已經回答了,但在選擇數據並將其傳遞迴服務器的問題,一個解決辦法是改變你標記到一些東西,更適合多選擇

,如果你使用複選框來代替,你可以把它們放在一個列表,並添加enhanching JS選擇所有和取消所有

http://jsfiddle.net/Ndkct/43/

<dl> 
<dt>Queen</dt> 
<dd> 
    <ul> 
     <li> 
      <input id="Mercury" name="bandmembers" value="Mercury" type="checkbox" /> 
      <label for="Mercury">Freddie</label> 
     </li>  
     <li> 
      <input id="May" name="bandmembers" value="May" type="checkbox" /> 
      <label for="May">Brian</label> 
     </li>  
     <li> 
      <input id="Taylor" name="bandmembers" value="Taylor" type="checkbox" /> 
      <label for="Taylor">Roger</label> 
     </li>  
     <li> 
      <input id="Deacon" name="bandmembers" value="Deacon" type="checkbox" /> 
      <label for="Deacon">John</label> 
     </li>  
    </ul> 
</dd> 
<dt>Pink Floyd</dt> ... 

的JS現在是很簡單的

$("dt") 
    .css("cursor","pointer") 
    .click(function(){ 
     var $el = $(this).next(); 
     var $checks = $el.find(":checkbox"); 
     if($checks.is(":not(:checked)")){ 
      $checks.attr("checked",true); 
     }else{ 
      $checks.attr("checked",false); 
     } 
    }); 

(這撥弄http://jsfiddle.net/Ndkct/44/增加了家長複選框,使它更可用)

+0

不錯的替代解決方案!它甚至可能對用戶更清晰。 – mflodin

+0

ta,我也這麼認爲。列表框和整個左移/控制按鈕多選擇的東西也不是用戶友好的。您具有層次結構的優勢,可以在此快速選擇多個項目,只需查看它即可瞭解發生的情況 –