91哥在留言裡出了個jQuery考題:

清單的項目有1,2,3,4,5,單選上下都沒問題了。

多選OK的情況:

(A) 選了2,3,按上,清單會變成2,3,1,4,5。
(B) 選了1,3,按上,清單會變成1,3,2,4,5。
(C) 選了2,5,按上,清單會變成2,1,3,5,4。

小的現在碰到的情況是:
選了1,2,按上,清單會變成2,1,3,4,5。原因是因為 each會從依序從最前面開始判斷,當1不做事時,下一個2則會跟1換位置,需求應該是「選了1,2,按上,清單仍維持1,2,3,4,5」。

不曉得針對這樣的需求,黑大有沒建議的作法?

好一個難易適中的挑戰題,忍不住手癢,就試解如下: (程式行數較單選版稍有增加,但仍維持jQuery慣有的簡潔性。)

<html>
<head>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js'></script>
<script type='text/javascript'>
    $(function() {
    
        //宣告jQuery陣列逆轉函數, 這是網路上找到的寫法
        //借了Array.reverse的native function來用(哇哩咧,這樣也行)
        $.fn.reverse = [].reverse;
        
        $("#bUp,#bDown").click(function() {
            var $opt = $("#selList option:selected");
            if (!$opt.length) return;
            var bGoUp = (this.id == "bUp");
            //向下移時, 逆轉結果陣列,由下往上做
            if (!bGoUp) $opt.reverse();
            $opt.each(function(i) {
                var $src = $(this);
                var $dst = $src[bGoUp ? "prev" : "next"]();
                //移動對象若也被選取,則不動
    if ($dst.length && $dst[0].selected) return;
                $dst[bGoUp ? "before" : "after"]($src);
            });
        });
    });
</script>
</head><body>
<select id='selList' size='7' style='width: 100px' multiple>
<option>Item 1</option>
<option>Item 2</option>
<option>Item 3</option>
<option>Item 4</option>
<option>Item 5</option>
</select><br />
<input type="button" id="bUp" value="Up" />
<input type="button" id="bDown" value="Down" />
</body>
</html>

Comments

# by 91

「reverse」跟「移動對象若也被選取,則不動」好棒啊.... 對黑大的景仰真是有如滔滔江水,連綿不絕啊.... var $dst = $src[bGoUp ? "prev" : "next"](); 看來我是卡在這一點,應該把prev額外抓出來判斷有沒有選取 XD 感謝黑大的指導 ^____^

# by Ark

http://quasipartikel.at/multiselect/ 檢現成的

# by 91

Dear Ark, MultiSelect那一篇我已經有採用也分享過了, 小的當時PO在這邊:http://www.dotblogs.com.tw/hatelove/archive/2009/11/18/12041.aspx 不過效率不是頗好,而且因為小的得要能用在Webform上, 所以那一篇的作法,postback之後順序會被還原, 原因是他是以原本的Select為底子, Postback之後只能讀到原始Select哪一些option有被selected, 依序排下來,那麼user自己調整的就記不住。 當然是也可以自己手動加工去改,不過由於還是有一點效率問題,後來才想說直接作的跟黑大一樣的方式,未來要客製化任何東西也比較有彈性,順便當個jQuery的練習例子 :)

# by Ark

91哥 我也在google 中文搜尋看到你那篇~我的看法是~用jquery就應該避開postback 非得要用~就得多花心思處理 ScriptManager.RegisterStartupScript 或是改 live的綁法 UpdatePanel 內要綁的才不會跑掉 避開postback那要怎傳值? 可用[WebMethod] 傳json 回去 1. 初始化$.ajaxSetup( { type: "POST", contentType: "application/json;utf-8", dataType: 'json', cache: true, async: false, beforeSend: function(a) { a.setRequestHeader("Content-Type", "application/json;utf-8") }, error: function(a, b) { if (b == 'error') { try { var c = eval('(' + a.responseText + ')'); alert(c.Message + '\n' + c.StackTrace) } catch (e) { } } else { alert(b) } } } ); 然後 $.ajax( { url: window.location + "/ur method name", data: JSON.stringify(object method's args), success: function(a) { //do ur job with a.d ... } } ); 2.或是懶一點 拉ScriptManager EnablePageMethods="True" ....那只能async

# by 91

Dear 黑大, 想請教一下, 用您的sample code,用Firefox跑很順, 不過用IE跑的時候,就會卡卡的, 按了按鈕之後(option會有錯亂), 得將滑鼠mouseover經過Select之後才會正常顯示option的結果。 (我的IE是IE7) 不曉得黑大測試會這樣嗎? (還以為是webform的問題,我錯怪他了...)

# by Jeffrey

to 91, 我是在Mini jQuery Lab(http://www.darkthread.net/minijquerylab)中用IE8做的測試,沒遇到卡卡或錯亂的問題。為排除其他干擾,建議你先用相同的測試環境玩看看。

# by Jeff-Yeh

91哥遇到的問題,我也玩了一下我的環境,我的是IE8,也是會卡卡的,而且很卡...用相容模式也是一樣~ Firefox跟chrome就很順~~

# by Jeffrey

to 91, Jeff-Yeh, 我測試了在IE7上確實會有移動option後要onmouseover才會repaint成正確順序的問題,我猜算是IE7的Bug, 有空再來研究一下。

Post a comment