มีเหตุการณ์ onSelect หรือเทียบเท่าสำหรับ HTML <select> หรือไม่


214

ฉันมีรูปแบบการป้อนข้อมูลที่ให้ฉันเลือกจากตัวเลือกหลายตัวและทำบางสิ่งเมื่อผู้ใช้เปลี่ยนการเลือก เช่น,

<select onChange="javascript:doSomething();">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

ตอนนี้doSomething()เพียง แต่ได้รับการเรียกเมื่อเลือกการเปลี่ยนแปลง

ฉันต้องการทริกเกอร์doSomething()เมื่อผู้ใช้เลือกตัวเลือกใด ๆ อาจเป็นแบบเดียวกันอีกครั้ง

ฉันได้ลองใช้ตัวจัดการ "onClick" แต่นั่นจะถูกทริกเกอร์ก่อนที่ผู้ใช้จะเริ่มกระบวนการคัดเลือก

ดังนั้นมีวิธีที่จะเรียกใช้ฟังก์ชั่นในทุกการเลือกโดยผู้ใช้หรือไม่?

ปรับปรุง:

คำตอบที่ Darryl แนะนำดูเหมือนจะใช้ได้ แต่ก็ไม่ได้ผลอย่างสม่ำเสมอ บางครั้งกิจกรรมจะถูกเรียกใช้ทันทีที่ผู้ใช้คลิกเมนูแบบเลื่อนลงแม้กระทั่งก่อนที่ผู้ใช้จะเสร็จสิ้นกระบวนการคัดเลือก!


1
ฉันเข้าใจว่าทำไมคุณถึงคิดอย่างนั้น ฉันจะทำให้มันสั้น มีสองอินพุตในแบบฟอร์มของฉัน เมือง (ช่องข้อความ) และรัฐ (ตัวเลือก) เริ่มแรกเมืองและรัฐจะปรากฏขึ้น เมื่อผู้ใช้เลือกสถานะตัวกรองการค้นหาจะขยายขอบเขตไปที่ "ทั่วทั้งรัฐ" แทน "เฉพาะเมือง"
ePharaoh

9
strager ไม่ใช่องค์ประกอบ UI ที่ผิดปกติ ทำให้รู้สึกที่สมบูรณ์แบบในบางสถานการณ์ ตัวอย่างเช่นอับละอองเกสรจะเขียนอีเมลมวลแล้วคุณมีแบบเลื่อนลงทางด้านขวาด้วย "เขตพิเศษ" คุณสามารถเพิ่มได้อย่างรวดเร็วในอีเมลชื่อแรกเลือกไม่เชื่อมโยง ฯลฯ
ไบรอันอาร์มสตรอง

2
เช่นเดียวกับหมายเหตุด้านข้าง ... สำหรับกิจกรรมแบบอินไลน์เช่น onclick, onchange เป็นต้นคุณไม่จำเป็นต้องใช้คำนำหน้าโปรโตคอล "javascript:" เมื่อวันที่ {event} = "doSomething ();" ไม่เป็นไร
scunliffe

ยังไม่ทดลอง: วิธีการเกี่ยวกับคลิก แต่นำไปใช้กับแท็กตัวเลือก? เห็นได้ชัดผ่านชั้นเรียนในทางที่ไม่เป็นการรบกวน
Disintegrator

6
@The Disintegrator ใช้การคลิกเหตุการณ์เท่านั้นที่ล้มเหลวในการจัดการกรณีการใช้งานที่คุณเลือกตัวเลือกผ่านแป้นพิมพ์ (ตระหนักว่านี่เป็นคำถามโบราณ - เพิ่มสำหรับผู้เยี่ยมชมในอนาคต ... )
peteorpeter

คำตอบ:


85

นี่คือวิธีที่ง่ายที่สุด:

<select name="ab" onchange="if (this.selectedIndex) doSomething();">
    <option value="-1">--</option>
    <option value="1">option 1</option> 
    <option value="2">option 2</option>
    <option value="3">option 3</option>
</select>

ทำงานได้ทั้งกับการเลือกเมาส์และแป้นขึ้น / ลงปุ่มที่เลือกจะถูกเน้น


36
แต่สิ่งนี้จะไม่ทำอะไรเลย "เมื่อผู้ใช้เลือก ... สิ่งเดียวกันอีกครั้ง" ใช่ไหม
LarsH

3
โปรดทราบว่าความคิดเห็นจาก @KayZhu นั้นถูกต้องเพียงครึ่งเดียวสิ่งที่ต้องทำคือการตรวจสอบว่า "selectedIndex" มากกว่าหรือเท่ากับศูนย์ (หรือมากกว่า -1) ไม่มีฟังก์ชั่น "type ()" และ "selectedIndex" จะไม่เป็นundefinedเช่นนั้น
Pointy

2
@TJCrowder คุณถูกต้อง - ไม่แน่ใจว่าฉันคิดอะไรเมื่อฉันเขียนครึ่งหลัง ฉันได้ลบความคิดเห็นดั้งเดิมและเพื่อไม่ให้ผู้อื่นสับสนนี่คือความคิดเห็นดั้งเดิม (โปรดทราบว่าครึ่งแรกนั้นถูกต้องและส่วนที่สองไม่ถูกต้อง): นี่จะไม่ทำงานตามที่คาดไว้สำหรับตัวเลือกแรกซึ่ง มีดัชนี 0: 0 เป็นเท็จใน JS ดังนั้น doSomething () จะไม่ถูกดำเนินการ ใช้แทนif(type(this.selectedIndex) != undefined; doSomething()
KZ

14
คำตอบนี้มี upvotes มากที่สุด แต่ก็ไม่ได้แก้ปัญหา! doSomething()ฟังก์ชั่นไม่ได้เรียกเมื่อผู้ใช้เลือกตัวเลือกแล้วเลือก ดูเสียงดังปังนี้ที่สีพื้นหลังเปลี่ยนเฉพาะเมื่อคุณเลือกตัวเลือกที่แตกต่างจากสีที่เลือก
skot

FWIW: หากคุณต้องการเรียกใช้เฉพาะdoSomething()เมื่อมีการเลือกตัวเลือกหนึ่งตัวเลือกตัวอย่างเช่น "ตัวเลือก 3" ในตัวอย่างข้างต้นให้ใช้if (this.selectedIndex==4)โดยตัวเลข "4" หมายถึงดัชนีตัวเลขของตัวเลือกไม่ใช่ตัวระบุvalue! (เช่น "ตัวเลือก 3" เป็นตัวเลือกที่สี่ของ<select name="ab">)
rvrvrv

66

ฉันต้องการบางสิ่งเหมือนกันทุกประการ นี่คือสิ่งที่ได้ผลสำหรับฉัน:

<select onchange="doSomething();" onfocus="this.selectedIndex = -1;">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

รองรับสิ่งนี้:

เมื่อผู้ใช้เลือกตัวเลือกใด ๆอาจเป็นตัวเดียวกันอีกครั้ง


4
jsfiddle.net/ecmanaut/335XKทำงานใน osx Chrome 30, Safari 6, Firefox 17.
ecmanaut

2
ยังทำงานใน Win8 IE10, Win7 IE9, Win7 IE8, WinXP IE7 และ IE6 Jsfiddle หรือ IE shenanigans บังคับให้คุณใช้fiddle.jshell.net/ecmanaut/335XK/show/lightโดยตรงเพียงแค่การทดสอบแม้ว่า - มุมมองเอดิเตอร์ของพวกเขาล้มเหลวในการโหลด jQuery ที่ใช้ในตัวอย่างสำหรับการอ่านได้ ทั้งหมดข้างต้นเพิ่งทดสอบกับการโต้ตอบของเมาส์; เพื่อให้แป้นพิมพ์นี้เป็นมิตรกับการแฮ็คนี้อาจต้องใช้งานเพิ่มเติมเนื่องจากอย่างน้อย IEs เก่าจะเรียกการเปลี่ยนแปลงอย่างมีความสุขก่อนที่คุณจะมีโอกาสเลือก "C"
ecmanaut

3
เคล็ดลับที่ดีจริงๆ ช่วยฉันแก้ไขปัญหาการไม่สามารถเลือกตัวเลือกแรก
naoru

7
หากมีการเลือกค่าไว้การแท็บผ่านสิ่งนี้จะทำให้เกิดปัญหา ทันทีที่เขตข้อมูลถูกนำทางไปที่ค่าจะหายไปซึ่งเป็นพฤติกรรมของผู้ใช้ที่ไม่คาดคิด นอกจากนี้เมื่อคุณปิดแท็บคุณจะสูญเสียการเลือกแม้ว่าคุณจะไม่ได้ทำอะไรเลย มิฉะนั้นความคิดที่ดี
KyleMit

1
ใช้เช่น jQuery .blur () เพื่อคืนค่าการเลือกดั้งเดิมหากเป็น -1 เมื่อถึงจุดโฟกัส
mheinzerling

12

ฉันมีปัญหาเดียวกันเมื่อฉันสร้างการออกแบบไม่กี่เดือนหลัง วิธีแก้ปัญหาที่ฉันพบคือใช้.live("change", function())ร่วมกับ.blur()องค์ประกอบที่คุณใช้

หากคุณต้องการให้มันทำอะไรบางอย่างเมื่อผู้ใช้เพียงคลิกแทนที่จะเปลี่ยนเพียงแค่แทนที่changeด้วยclickด้วย

ฉันกำหนด ID แบบเลื่อนลงของฉันselectedและใช้สิ่งต่อไปนี้:

$(function () {
    $("#selected").live("change", function () {

    // do whatever you need to do

    // you want the element to lose focus immediately
    // this is key to get this working.
    $('#selected').blur();
    });
});

ฉันเห็นสิ่งนี้ไม่มีคำตอบที่เลือกดังนั้นฉันจึงคิดว่าจะให้ข้อมูลของฉัน วิธีนี้ใช้ได้ดีสำหรับฉันดังนั้นหวังว่าคนอื่นจะสามารถใช้รหัสนี้เมื่อพวกเขาติดขัด

http://api.jquery.com/live/

แก้ไข: ใช้ตัวเลือกเมื่อเทียบกับon .liveดูjQuery .on ()


ขอบคุณ! .blur () ช่วย ใน IE7 เหตุการณ์การเปลี่ยนแปลงของ jQuery จะถูกทริกเกอร์สองครั้งหากไม่มี. blur () ในรหัส
วาด

7
สิ่งนี้ช่วยได้อย่างไรกับปัญหาที่เกิดขึ้นในคำถามนั่นคือไม่มีอะไรเกิดขึ้นจนกว่าการเลือกจะเปลี่ยนไป ?
LarsH

2
@ LarsH เป็นเวลาหลายปีแล้วตั้งแต่คำถามนี้ไม่แน่ใจ - ฉันอาจอ่านคำถามผิดและสับสน
โคดี้

สำหรับคนที่ต้องการตอนนี้ .live ได้ถูกลบออกอย่างเป็น 1.9 api.jquery.com/live/#live-events-handler ใช้. change เป็นช็อตคัต api.jquery.com/change/#change-handler
parttimeturtle

9

แค่ไอเดีย แต่เป็นไปได้ไหมที่จะวางออนคลิกบนแต่ละ<option>องค์ประกอบ?

<select>
  <option onclick="doSomething(this);">A</option>
  <option onclick="doSomething(this);">B</option>
  <option onclick="doSomething(this);">C</option>
</select>

ตัวเลือกอื่นอาจใช้ onblur ในการเลือก สิ่งนี้จะเริ่มทำงานเมื่อใดก็ตามที่ผู้ใช้คลิกออกไปจากตัวเลือก ณ จุดนี้คุณสามารถกำหนดตัวเลือกที่เลือกได้ หากต้องการให้สิ่งนี้ทำงานในเวลาที่ถูกต้อง onclick ของตัวเลือกอาจทำให้สนามพร่ามัว


1
ยี้! "ทำไมฉันไม่คิดอย่างนั้น" ช่วงเวลา ขอบคุณ!
ePharaoh

@Darryl สิ่งนี้ใช้งานไม่ได้ตามที่คาดไว้ บางครั้งเหตุการณ์จะถูกเรียกใช้ก่อนที่ผู้ใช้จะทำการเลือกให้เสร็จสิ้น ดูการอัปเดตที่ฉันเพิ่มไว้ในคำถาม
ePharaoh

8
การวางตัวจัดการเหตุการณ์บนตัวเลือกจะล้มเหลวใน IE ทุกรุ่น! webbugtrack.blogspot.com/2007/11/…
scunliffe

8
ล้มเหลวในการโครเมี่ยมมากเกินไป :)
thinklinux

ทำงานใน firefox
lezsakdomi

6

วิธีการ onclick นั้นไม่ได้เลวร้ายอย่างสิ้นเชิง แต่อย่างที่กล่าวมามันจะไม่ถูกทริกเกอร์เมื่อไม่มีการเปลี่ยนแปลงค่าโดยการคลิกเมาส์
อย่างไรก็ตามเป็นไปได้ที่จะทริกเกอร์เหตุการณ์ onclick ในเหตุการณ์ onchange

<select onchange="{doSomething(...);if(this.options[this.selectedIndex].onclick != null){this.options[this.selectedIndex].onclick(this);}}">
    <option onclick="doSomethingElse(...);" value="A">A</option>
    <option onclick="doSomethingElse(..);" value="B">B</option>
    <option onclick="doSomethingElse(..);" value="Foo">C</option>
</select>

5

จะขยายคำตอบของ jitbit ฉันพบว่ามันแปลกเมื่อคุณคลิกที่เลื่อนลงแล้วคลิกที่เลื่อนลงโดยไม่ต้องเลือกอะไร จบลงด้วยบางสิ่งตามแนวของ:

var lastSelectedOption = null;

DDChange = function(Dd) {
  //Blur after change so that clicking again without 
  //losing focus re-triggers onfocus.
  Dd.blur();

  //The rest is whatever you want in the change.
  var tcs = $("span.on_change_times");
  tcs.html(+tcs.html() + 1);
  $("span.selected_index").html(Dd.prop("selectedIndex"));
  return false;
};

DDFocus = function(Dd) {
  lastSelectedOption = Dd.prop("selectedIndex");
  Dd.prop("selectedIndex", -1);

  $("span.selected_index").html(Dd.prop("selectedIndex"));
  return false;
};

//On blur, set it back to the value before they clicked 
//away without selecting an option.
//
//This is what is typically weird for the user since they 
//might click on the dropdown to look at other options,
//realize they didn't what to change anything, and 
//click off the dropdown.
DDBlur = function(Dd) {
  if (Dd.prop("selectedIndex") === -1)
    Dd.prop("selectedIndex", lastSelectedOption);

  $("span.selected_index").html(Dd.prop("selectedIndex"));
  return false;
}; 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select id="Dd" onchange="DDChange($(this));" onfocus="DDFocus($(this));" onblur="DDBlur($(this));">
  <option>1</option>
  <option>2</option>
</select>
<br/>
<br/>Selected index: <span class="selected_index"></span>
<br/>Times onchange triggered: <span class="on_change_times">0</span>

สิ่งนี้ทำให้ผู้ใช้มีความรู้สึกเพิ่มขึ้นเล็กน้อยและอนุญาตให้ JavaScript รันทุกครั้งที่พวกเขาเลือกตัวเลือกใด ๆ รวมถึงตัวเลือกก่อนหน้า

ข้อเสียของวิธีนี้คือการแบ่งความสามารถในการแท็บลงบนรายการแบบหล่นลงและใช้ปุ่มลูกศรเพื่อเลือกค่า สิ่งนี้เป็นที่ยอมรับสำหรับฉันเนื่องจากผู้ใช้ทุกคนคลิกทุกสิ่งตลอดเวลาจนกระทั่งสิ้นสุดนิรันดร์


คุณสามารถกำจัดของคำเตือนเสาโดยผ่านในแทนthis $(this)อย่างไรก็ตามฉันไม่ได้รับพฤติกรรมที่ตั้งใจทั้งหมดจากเรื่องนี้ ไม่แจ้งเตือนเมื่อฉันเลือกตัวเลือกเดียวกันอีกครั้ง
Noumenon

1
หมายเหตุ: onchangeถูกเรียกใช้งานเมื่อเพิ่มตัวเลือกการลบในกล่องที่เลือกผ่าน JS ไม่เพียง แต่เมื่อผู้ใช้เลือกรายการ
zanderwar

@Noumenon ฉันแก้ไขข้อผิดพลาดในเรื่องนี้หากยังคงมีประโยชน์ ฉันคิดว่าฉันกำลังทดสอบสิ่งนี้ในแอปพลิเคชันและเมื่อฉันคัดลอกมันออกไปฉันลืมเปลี่ยนชื่อตัวแปร ควรทำงานในโปรแกรมแก้ไขและเข้าใจเพิ่มเติมในตอนนี้
Tyler Stahlhuth

4

ถ้าคุณต้องการให้มันทำงานแบบนี้ฉันจะทำมัน (เพื่อให้แน่ใจว่ามันใช้งานได้ด้วยแป้นพิมพ์และเมาส์)

  • เพิ่มตัวจัดการเหตุการณ์ onfocus ไปยังตัวเลือกเพื่อตั้งค่า "ปัจจุบัน"
  • เพิ่มตัวจัดการเหตุการณ์ onclick ให้กับตัวเลือกเพื่อจัดการกับการเปลี่ยนแปลงของเมาส์
  • เพิ่มตัวจัดการเหตุการณ์ onkeypress ให้กับตัวเลือกเพื่อจัดการกับการเปลี่ยนแปลงของแป้นพิมพ์

น่าเสียดายที่ onclick จะทำงานหลายครั้ง (เช่นเมื่อเปิดการเลือก ... และเมื่อเลือก / ปิด) และ onkeypress อาจเริ่มทำงานเมื่อไม่มีอะไรเปลี่ยนแปลง ...

<script>
  function setInitial(obj){
    obj._initValue = obj.value;
  }
  function doSomething(obj){
    //if you want to verify a change took place...
    if(obj._initValue == obj.value){
      //do nothing, no actual change occurred...
      //or in your case if you want to make a minor update
      doMinorUpdate();
    } else {
      //change happened
      getNewData(obj.value);
    }
  }
</script>


<select onfocus="setInitial(this);" onclick="doSomething();" onkeypress="doSomething();">
  ...
</select>

4

ในการเริ่มต้นเหตุการณ์อย่างถูกต้องทุกครั้งที่ผู้ใช้เลือกบางสิ่ง (แม้แต่ตัวเลือกเดียวกัน) คุณเพียงแค่ต้องหลอกกล่องที่เลือก

เช่นเดียวกับที่คนอื่น ๆ ได้กล่าวไว้ให้ระบุลบselectedIndexในการมุ่งเน้นเพื่อบังคับให้เหตุการณ์การเปลี่ยนแปลง แม้ว่าสิ่งนี้จะช่วยให้คุณหลอกกล่องที่เลือกได้ แต่มันจะไม่ทำงานหลังจากนั้นตราบใดที่ยังมีโฟกัสอยู่ การแก้ไขอย่างง่ายคือการบังคับให้กล่องเลือกเบลอดังที่แสดงด้านล่าง

JS / HTML มาตรฐาน:

<select onchange="myCallback();" onfocus="this.selectedIndex=-1;this.blur();">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

ปลั๊กอิน jQuery:

<select>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

<script type="text/javascript">
    $.fn.alwaysChange = function(callback) {
        return this.each(function(){
            var elem = this;
            var $this = $(this);

            $this.change(function(){
                if(callback) callback($this.val());
            }).focus(function(){
                elem.selectedIndex = -1;
                elem.blur();
            });
        });
    }


    $('select').alwaysChange(function(val){
        // Optional change event callback,
        //    shorthand for $('select').alwaysChange().change(function(){});
    });
</script>

คุณสามารถดูการสาธิตการทำงานที่นี่


สิ่งนี้ใช้ได้กับ Chrome แต่ไม่ใช่กับ IE9: เมื่อฉันคลิกที่ตัวควบคุมข้อความของมันจะหายไปและมันจะไม่ดรอปดาวน์
ChrisW

ปัญหาเกี่ยวกับสิ่งนี้คือมันเป็นตัวเลือกปัจจุบัน หากการเลือกปัจจุบันคือ B และฉันคลิกที่แบบเลื่อนลงเครื่องหมายถูกจะปรากฏขึ้นถัดจาก A! แต่ไม่ได้เลือก A จริงๆเพราะถ้าฉันเลื่อนเมนูออกและปล่อยปุ่มเมาส์ (ยกเลิกเมนู) การเลือกจะว่างเปล่า การเลือกจะว่างเปล่าหากคุณแท็บไปยัง pulldown ซึ่งคุณสามารถทำได้อย่างง่ายดายหากคุณกำลังแท็บผ่านไปยังส่วนอื่น ๆ ของแบบฟอร์มโดยไม่คาดหวังว่าจะเกิดความเสียหายใด ๆ ตามทาง (กดแท็บ jsfiddle ของคุณและคุณจะเห็นสิ่งที่ผมหมายถึง.)
SKOT

3

ที่จริงแล้วเหตุการณ์ onclick จะไม่ทำงานเมื่อผู้ใช้ใช้แป้นพิมพ์เพื่อเปลี่ยนการเลือกในตัวควบคุมที่เลือก คุณอาจต้องใช้การรวมกันของ onChange และ onClick เพื่อรับพฤติกรรมที่คุณกำลังมองหา


ใช่ฉันจะต้อง .. แต่ปัญหาที่ฉันกำลังเผชิญอยู่นั้นเป็นมุมฉากที่แยกต่างหากจากความกังวลของคุณ เหตุการณ์ onclick ใน <option> กำลังเริ่มต้นแม้ว่าผู้ใช้จะทำการเลือกเสร็จสิ้นซึ่งดูเหมือนจะทำให้ไม่สามารถใช้งานได้
ePharaoh

เหตุการณ์เกิดขึ้นใน Chrome เมื่อคุณกด Enter หลังจากย้ายการเลือกไปยังรายการใหม่
Gene Golovchinsky

3

สิ่งนี้อาจไม่ตอบคำถามของคุณโดยตรง แต่ปัญหานี้สามารถแก้ไขได้โดยการปรับระดับการออกแบบที่เรียบง่าย ฉันเข้าใจว่าอาจไม่สามารถใช้กับกรณีการใช้งานได้ทั้งหมด 100% แต่ฉันขอแนะนำให้คุณลองนึกถึงการไหลของผู้ใช้แอปพลิเคชันของคุณอีกครั้ง

ฉันตัดสินใจที่จะทำสิ่งที่ง่ายกว่าการแฮ็กทางเลือกสำหรับการonChange()ใช้กิจกรรมอื่น ๆ ที่ไม่ได้มีไว้สำหรับวัตถุประสงค์นี้ ( blur,clickฯลฯ )

วิธีที่ฉันแก้ไขมัน:

เพียงก่อนแท็กตัวเลือกตัวแทนจองล่วงหน้าเช่นเลือกที่ไม่มีค่า

ดังนั้นแทนที่จะใช้โครงสร้างต่อไปนี้ซึ่งต้องการทางเลือก hack-y:

<select>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

พิจารณาใช้สิ่งนี้:

<select>
  <option selected="selected">Select...</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

ดังนั้นวิธีนี้รหัสของคุณจะง่ายขึ้นมากและonChangeจะทำงานตามที่คาดไว้ทุกครั้งที่ผู้ใช้ตัดสินใจที่จะเลือกอย่างอื่นที่ไม่ใช่ค่าเริ่มต้น คุณสามารถเพิ่มแอdisabledททริบิวต์ลงในตัวเลือกแรกได้หากคุณไม่ต้องการให้พวกมันเลือกอีกครั้งและบังคับให้พวกเขาเลือกบางอย่างจากตัวเลือกซึ่งจะทำให้เกิดonChange()ไฟไหม้

ในช่วงเวลาของคำตอบนี้ฉันกำลังเขียนแอปพลิเคชัน Vue ที่ซับซ้อนและฉันพบว่าตัวเลือกการออกแบบนี้ทำให้รหัสของฉันง่ายขึ้นมาก ฉันใช้เวลาหลายชั่วโมงในการแก้ไขปัญหานี้ก่อนที่จะตัดสินใจด้วยโซลูชันนี้และฉันไม่จำเป็นต้องเขียนโค้ดอีกมาก อย่างไรก็ตามถ้าฉันไปกับทางเลือกที่แฮ็กฉันจะต้องพิจารณากรณีขอบเพื่อป้องกันการยิงสองครั้งของการร้องขอ ajax ฯลฯ นี่ยังไม่ยุ่งพฤติกรรมเบราว์เซอร์เริ่มต้นเป็นโบนัสที่ดี (ทดสอบบนมือถือ เบราว์เซอร์เช่นกัน)

บางครั้งคุณเพียงแค่ต้องย้อนกลับไปและคิดเกี่ยวกับภาพรวมเพื่อหาทางออกที่ง่ายที่สุด


2

สิ่งที่ฉันทำเมื่อประสบกับปัญหาที่คล้ายกันคือฉันเพิ่ม 'onFocus' ลงในกล่องเลือกซึ่งจะผนวกตัวเลือกทั่วไปใหม่ ('เลือกตัวเลือก' หรือบางอย่างที่คล้ายกัน) และเริ่มต้นเป็นตัวเลือกที่เลือก


2

ดังนั้นเป้าหมายของฉันคือเพื่อให้สามารถเลือกค่าเดียวกันหลายครั้งซึ่งเป็นหลักแทนที่ฟังก์ชั่น onchange () และเปลี่ยนเป็นวิธีการที่มีประโยชน์ onclick ()

จากคำแนะนำข้างต้นฉันพบสิ่งนี้ซึ่งเหมาะกับฉัน

<select name="ab" id="hi" onchange="if (typeof(this.selectedIndex) != undefined) {alert($('#hi').val()); this.blur();}" onfocus="this.selectedIndex = -1;">
    <option value="-1">--</option>
    <option value="1">option 1</option>
    <option value="2">option 2</option>
    <option value="3">option 3</option>
</select>

http://jsfiddle.net/dR9tH/19/


2
ข้อเสียเปรียบเช่นเดียวกับคนอื่น ๆ onfocus="this.selectedIndex=-1"แก้ปัญหา : การเลือกปัจจุบันได้รับการอบถ้าคุณแท็บองค์ประกอบหรือถ้าคุณเมาส์ปิดเมนูโดยไม่เลือกอะไร กดแท็บบนซอของคุณเพื่อดูว่าฉันหมายถึงอะไร (โปรดสังเกตว่าคุณได้รับค่าว่างและไม่ใช่ '-' เมื่อคุณทำเช่นนี้นั่นเป็นเพราะคุณselectedIndex=-1ไม่ได้รับ<option value="-1">มันจะเป็นการปรับปรุงเล็กน้อยที่นี่เพื่อใช้onfocus="this.selectedIndex=0"นี่เป็นวิธีแก้ปัญหาที่เหมาะสมครึ่ง แต่ฉันไม่ เหมือนกับการสูญเสียตัวเลือกปัจจุบันเพียงเพราะฉันดูเมนูหรือแม้แต่แท็บมัน
skot

2

ก่อนอื่นคุณใช้ onChange เป็นตัวจัดการเหตุการณ์แล้วใช้ตัวแปร flag เพื่อทำหน้าที่คุณต้องการทุกครั้งที่มีการเปลี่ยนแปลง

<select

var list = document.getElementById("list");
var flag = true ; 
list.onchange = function () {
if(flag){
document.bgColor ="red";
flag = false;

}else{
document.bgColor ="green";
flag = true;
}
}
<select id="list"> 
<option>op1</option>
<option>op2</option>
<option>op3</option>
</select>


2

เพิ่มตัวเลือกพิเศษเป็นตัวแรกเช่นส่วนหัวของคอลัมน์ซึ่งจะเป็นค่าเริ่มต้นของปุ่มดรอปดาวน์ก่อนคลิกและตั้งค่าใหม่เมื่อสิ้นสุดdoSomething()ดังนั้นเมื่อเลือก A / B / C เหตุการณ์ onchange จะ trigs เสมอ เมื่อการเลือกคือStateทำอะไรและกลับมา onclickไม่แน่นอนอย่างที่หลายคนพูดไว้ก่อนหน้านี้ ดังนั้นสิ่งที่เราต้องทำคือการสร้างป้ายปุ่มเริ่มต้นซึ่งแตกต่างจากตัวเลือกที่แท้จริงของคุณดังนั้นการเปลี่ยนจะทำงานกับตัวเลือกใด ๆ

<select id="btnState" onchange="doSomething(this)">
  <option value="State" selected="selected">State</option>  
  <option value="A">A</option>
  <option value="B">B</option>
  <option value="C">C</option>
</select>


function doSomething(obj)
{
    var btnValue = obj.options[obj.selectedIndex].value;

    if (btnValue == "State")
    {
      //do nothing
      return;
    }

    // Do your thing here

    // reset 
    obj.selectedIndex = 0;
}

1

สิ่งที่ยอดเยี่ยมเกี่ยวกับแท็กเลือก (ในสถานการณ์นี้) คือมันจะรับค่าจากแท็กตัวเลือก

ลอง:

<select onChange="javascript:doSomething(this.value);">
<option value="A">A</option>
<option value="B">B</option>
<option value="Foo">C</option>
</select>

ทำงานได้ดีสำหรับฉัน


1

ใช้ jquery:

<select class="target">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

<script>
    $('.target').change(function() { doSomething(); });
</script>

1

นี่คือทางออกของฉันแตกต่างอย่างสิ้นเชิงกับที่อื่นที่นี่ มันใช้ตำแหน่งของเมาส์เพื่อคิดออกว่ามีการคลิกตัวเลือกเหมือนกับที่คลิกที่กล่องเลือกเพื่อเปิดดรอปดาวน์หรือไม่ มันทำให้การใช้งานของ event.screenY ตำแหน่งนี้เป็นตัวแปรข้ามเบราว์เซอร์ที่เชื่อถือได้เท่านั้น จะต้องแนบเหตุการณ์โฮเวอร์ก่อนเพื่อให้สามารถเข้าใจตำแหน่งการควบคุมที่สัมพันธ์กับหน้าจอก่อนเหตุการณ์คลิก

var select = $("select");

var screenDif = 0;
select.bind("hover", function (e) {
    screenDif = e.screenY - e.clientY;
});
select.bind("click", function (e) {
    var element = $(e.target);
    var eventHorizon = screenDif + element.offset().top + element.height() - $(window).scrollTop();
    if (e.screenY > eventHorizon)
        alert("option clicked");
});

นี่คือ jsFiddle ของฉัน http://jsfiddle.net/sU7EV/4/


1
ไม่ทำงานใน Safari หรือ Chrome สำหรับ OS X การแจ้งเตือนจะไม่เริ่มขึ้น
skot


1

อะไรที่เหมาะกับฉัน:

<select id='myID' onchange='doSomething();'>
    <option value='0' selected> Select Option </option>
    <option value='1' onclick='if (!document.getElementById("myID").onchange()) doSomething();' > A </option>
    <option value='2' onclick='if (!document.getElementById("myID").onchange()) doSomething();' > B </option>
</select>

ด้วยวิธีดังกล่าวการเรียก onchange 'doSomething ()' เมื่อตัวเลือกเปลี่ยนแปลงและ onclick call 'doSomething ()' เมื่อเหตุการณ์ onchange เป็นเท็จหรืออีกนัยหนึ่งเมื่อคุณเลือกตัวเลือกเดียวกัน


ใช้งานไม่ได้กับฉันใน Safari หรือ Chrome สำหรับ OS X jsfiddle.net/drskot/wLvL4pkw
skot

1

ลองนี้ (เหตุการณ์จะเริ่มขึ้นเมื่อคุณเลือกตัวเลือกโดยไม่ต้องเปลี่ยนตัวเลือก)

$("select").mouseup(function() {
    var open = $(this).data("isopen");
    if(open) {
        alert('selected');
    }
    $(this).data("isopen", !open);
});

http://jsbin.com/dowoloka/4


1
<script>
function abc(selectedguy) {
alert(selectedguy);
}
</script>

<select onchange="abc(this.selectedIndex);">
<option>option one</option>
<option>option two</option>
</select>

ที่นี่คุณมีดัชนีที่ส่งคืนและในรหัส js คุณสามารถใช้การส่งคืนนี้ด้วยสวิตช์เดียวหรืออะไรก็ได้ที่คุณต้องการ


0

ลองสิ่งนี้:

<select id="nameSelect" onfocus="javascript:document.getElementById('nameSelect').selectedIndex=-1;" onchange="doSomething(this);">
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
</select>

0

เมื่อไม่นานมานี้ แต่ในการตอบคำถามเดิมจะช่วยได้หรือไม่ เพียงแค่ใส่onClickเข้าไปในSELECTเส้น จากนั้นใส่สิ่งที่คุณต้องการให้แต่ละคนOPTIONทำในOPTIONบรรทัด เช่น:

<SELECT name="your name" onClick>
<option value ="Kilometres" onClick="YourFunction()">Kilometres
-------
-------
</SELECT>

0
<select name="test[]" 
onchange="if(this.selectedIndex < 1){this.options[this.selectedIndex].selected = !1}">
<option>1</option>
<option>2</option>
<option>3</option>
</select>

0

ฉันต้องเผชิญกับความต้องการที่คล้ายกันและจบลงด้วยการเขียนคำสั่ง angularjs สำหรับเดียวกัน -

ลิงค์ guthub - เลือกเชิงมุม

ใช้element[0].blur();เพื่อลบโฟกัสออกจากแท็กที่เลือก ตรรกะคือการเรียกความพร่ามัวนี้เมื่อคลิกครั้งที่สองของเมนู

as-select ได้รับการเรียกแม้ว่าผู้ใช้เลือกค่าเดียวกันในแบบเลื่อนลง

DEMO - ลิงก์


0

หนึ่งคำตอบที่แท้จริงคือไม่ใช้ฟิลด์เลือก (ถ้าคุณต้องการทำอะไรเมื่อคุณเลือกคำตอบเดียวกันซ้ำ)

สร้างเมนูแบบเลื่อนลงด้วย div, ปุ่ม, เมนูแสดง / ซ่อน ลิงก์: https://www.w3schools.com/howto/howto_js_dropdown.asp

สามารถหลีกเลี่ยงได้หนึ่งสามารถเพิ่มฟังเหตุการณ์ไปยังตัวเลือก หากมีผู้ฟัง onSelect สำหรับองค์ประกอบที่เลือก และหากการคลิกที่ฟิลด์ที่เลือกไม่ได้เป็นการดับ mousedown, การวางเมาส์และคลิกทั้งหมดในเวลาเดียวกันกับ mousedown


0

มีบางสิ่งที่คุณต้องการทำที่นี่เพื่อให้แน่ใจว่าจำค่าที่เก่ากว่าและทริกเกอร์เหตุการณ์ onchange แม้ว่าตัวเลือกเดียวกันจะถูกเลือกอีกครั้ง

สิ่งแรกที่คุณต้องการคือเหตุการณ์ onChange ปกติ:

$("#selectbox").on("change", function(){
    console.log($(this).val());
    doSomething();
});

หากต้องการให้ทริกเกอร์เหตุการณ์ onChange แม้ว่าจะมีการเลือกตัวเลือกเดิมอีกครั้งคุณสามารถยกเลิกการตั้งค่าตัวเลือกที่เลือกเมื่อรายการแบบเลื่อนลงได้รับโฟกัสโดยการตั้งค่าเป็นค่าที่ไม่ถูกต้อง แต่คุณต้องการเก็บค่าที่เลือกไว้ก่อนหน้านี้เพื่อเรียกคืนในกรณีที่ผู้ใช้ไม่ได้เลือกตัวเลือกใหม่:

prev_select_option = ""; //some kind of global var

$("#selectbox").on("focus", function(){
    prev_select_option = $(this).val(); //store currently selected value
    $(this).val("unknown"); //set to an invalid value
});

รหัสด้านบนจะช่วยให้คุณสามารถทริกเกอร์การเปลี่ยนแม้จะเลือกค่าเดียวกัน อย่างไรก็ตามหากผู้ใช้คลิกที่นอกช่องเลือกคุณต้องการคืนค่าก่อนหน้า เราทำบน blur:

$("#selectbox").on("blur", function(){
    if ($(this).val() == null) { 
       //because we previously set an invalid value 
       //and user did not select any option
        $(this).val(prev_select_option);
    }
});

-1

โปรดทราบว่าตัวจัดการเหตุการณ์ไม่ได้รับการสนับสนุนสำหรับแท็ก OPTION บน IE ด้วยความคิดที่รวดเร็ว .. ฉันมาพร้อมกับโซลูชันนี้ลองและให้ข้อเสนอแนะกับฉัน:

<script>
var flag = true;
function resetIndex(selObj) {
    if(flag) selObj.selectedIndex = -1;
    flag = true;
}
function doSomething(selObj) {
    alert(selObj.value)
    flag = false;
}
</script>
<select onchange="doSomething(this)" onclick="resetIndex(this)">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>

สิ่งที่ฉันทำที่นี่จริง ๆ แล้วคือการรีเซ็ตดัชนีที่เลือกเพื่อให้เหตุการณ์ onchange จะถูกเรียกใช้เสมอความจริงที่ว่าคุณเราสูญเสียรายการที่เลือกเมื่อคุณคลิกและมันอาจจะน่ารำคาญถ้ารายการของคุณยาว แต่อาจช่วยคุณได้ ..


-1

สิ่งที่เกี่ยวกับการเปลี่ยนค่าของตัวเลือกเมื่อองค์ประกอบได้รับโฟกัสเช่น (ด้วย jquery):

$("#locationtype").focus(function() {
    $("#locationtype").val('');
});

$("#locationtype").change(function() {
    if($("#locationtype").val() == 1) {
        $(".bd #mapphp").addClass('show');
        $("#invoerform").addClass('hide');
    }
    if($("#locationtype").val() == 2) {
        $(".lat").val('');
        $(".lon").val('');
    }
});

-1

ฉันพบทางออกนี้

ตั้งค่า selectedIndex ขององค์ประกอบที่เลือกเป็น 0 เริ่มต้น

//set selected Index to 0

doSomethingOnChange(){

     blah ..blah ..

     set selected Index to 0

}

เรียกวิธีการนี้กับเหตุการณ์ที่เปลี่ยน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.