1

I have a table full of select elements, some of which are prefilled with suggestions for a data migration project I'm working on. I know how to listen for a change event (jQuery) but I also want to listen for when the user selects the suggested option. Is that possible?

I tried listening for a click but that only gets called when the select box is opened not when its closed.

Update

A simple reproduction of the problem -

HTML -

<select>
  <option value="">One</option>
  <option value="" selected>Two</option>
  <option value="">Three</option>
</select>

<p></p>

JS

$('select').change(function() {
    $('p').append('x');
});

https://jsfiddle.net/sh9n2cvg/

Update 2

The best I've found so far is this, but its still a little buggy -

$('select').click(function() {
    $(this).val("");
    $(this).trigger('change');
});

Update 3 I don't think what I'm trying to do is possible. This is my workaround - https://stackoverflow.com/a/5859221/772309

Community
  • 1
  • 1
Ryan Grush
  • 2,076
  • 3
  • 37
  • 64
  • I'm not sure that detecting that is useful. The user doesn't select the value that's showing, it's already selected. Open and closing the select element without picking something else doesn't change anything. – Ouroborus Dec 09 '16 at 03:38
  • Possible duplicate of [Is there a DOM event that fires when an HTML select element is closed?](http://stackoverflow.com/questions/6207929/is-there-a-dom-event-that-fires-when-an-html-select-element-is-closed) – Ouroborus Dec 09 '16 at 03:40
  • If you provide some example code, we might have enough context to be a bit more helpful. – gyre Dec 09 '16 at 03:41
  • @gyre I updated the question with a simple way to reproduce the problem – Ryan Grush Dec 09 '16 at 03:47
  • Are you expecting `change` event to be dispatched to `select` element when `document` is loaded due to second `option` having `selected` attribute set at `html`? – guest271314 Dec 09 '16 at 04:07
  • I'm trying the have `change` or some event get triggered when the selected option, or any option, gets selected. Its not a problem for any other `option` because that would trigger a `change` but if its the pre-filled selected option it won't. – Ryan Grush Dec 09 '16 at 04:10
  • The `change` event is called when an `option` is selected by user action at `javascript` at jsfiddle. Are you expecting the `change` event to be called, without user action, at `.ready()` handler because the second `option` element has `selected` attribute set? Does your actual ` – guest271314 Dec 09 '16 at 04:12
  • @guest271314 can you give me a fiddle or something to show me what you mean? – Ryan Grush Dec 09 '16 at 04:14
  • @RyanGrush https://jsfiddle.net/sh9n2cvg/2/ . Note, set actual value at `value` attribute, instead of empty string. – guest271314 Dec 09 '16 at 04:18
  • @guest271314 I don't think its possible, this is what I'm trying to do - http://recordit.co/dGV5oSGseD. It should be outputting an "x" every time I select "Two". – Ryan Grush Dec 09 '16 at 04:20
  • @RyanGrush You can use `mouseup` event https://jsfiddle.net/sh9n2cvg/4/ – guest271314 Dec 09 '16 at 04:22
  • I need to get the value when it closes though, not when it opens – Ryan Grush Dec 09 '16 at 04:25
  • @RyanGrush What do you mean? `mouseup` is called when user action releases mouse. The `select` menu closes after user selection. – guest271314 Dec 09 '16 at 04:26
  • @guest271314 I need the event when the user makes a selection - "The select menu closes after user selection" – Ryan Grush Dec 09 '16 at 04:31

5 Answers5

1

I'm not sure that it's possible with the default select element. If you don't mind using a simulated select element, you could do something like this:

var was = $('select').val();
$('select')
  .selectmenu()
  .on('selectmenuclose',function(event){
    var is = $('select').val();
    if(was == is) {
      $('p').append("<br>reselected "+is);
    }
    else {
      $('p').append("<br>changed to "+is);
    }
    was = is;
  });
<link href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

<select>
  <option value="one">One</option>
  <option value="two" selected>Two</option>
  <option value="three">Three</option>
</select>

<p></p>

If you just want it such that the trigger only happens when an option is selected (rather than also on blur, etc.), this would do the trick:

var was = $('select').val();
$('select')
  .selectmenu()
  .on('selectmenuselect',function(event, ui){
    var is = ui.item.value;
    if(was == is) {
      $('p').append("<br>reselected "+is);
    }
    else {
      $('p').append("<br>changed to "+is);
    }
    was = is;
  });
<link href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

<select>
  <option value="one">One</option>
  <option value="two" selected>Two</option>
  <option value="three">Three</option>
</select>

<p></p>
Ouroborus
  • 16,237
  • 4
  • 39
  • 62
1

You could do something like this.

If you need to do something always on default selected option, you need to identify the default option so, whenever, the option is selected, you could trigger appending x.

// I want it to output "x" when "Two" is reselected
$(function() {
  $('select').change(function(e) {
    if ($("option:selected", $(e.currentTarget)).attr("data-default")) {
      $('p').append('x');
    }
  });

  $('select').each(function(idx, ele) {
    $("option:selected", $(ele)).attr("data-default", "true")
  });

  $('select').change();



});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
  <option value="">One</option>
  <option value="" selected>Two</option>
  <option value="">Three</option>
</select>

<p></p>

If you are looking to append x to p for all change events and for the initial default selection, here is what you could do.

// I want it to output "x" when "Two" is reselected
$(function() {
  $('select').change(function(e) {
    $('p').append('x');
  });

  $('select').change();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
  <option value="">One</option>
  <option value="" selected>Two</option>
  <option value="">Three</option>
</select>

<p></p>
Sreekanth
  • 3,110
  • 10
  • 22
1

You can substitute <ul>, <li> elements for <select>, <option> elements; style ul, li elements to be displayed as select, option menu, use click event to select li element

$(function() {

  var p = $("#select + p");
  
  var options = ["One", "Two", "Three"];
  
  $.each(options, function(index, option) {
    $("<li>", {    
      html: "\n" + option,
      appendTo:"#select",
      css: {
        listStyle: "none",
        width: "142px",
        padding: "8px",
        margin: "1px",
        outline: "1px solid #000",
        fontFamily: "arial",
        height:"16px",
        backgroundColor:"#eee"
      },
      on: {
        "mouseenter": function() {
          if (!$(this).is("li:first")) {
            $(this).css("backgroundColor", "orange")
          }
        },
        "mouseleave": function() {
          $(this).css("backgroundColor", "#eee")
        }
      }
    })
  });

  $("#select li:not(:first)")
    .hide()
    .siblings(":first")
    .clone(true)
    .hide()
    .insertAfter("#select li:first")
    .parent()
    .click(function(e) {
      if ($(e.target).is("li:first")) {
        $(e.target).closest("li").siblings().toggle()
      } else {
        $(e.target).closest("ul")
        .find(":first")
        .html($(e.target).closest("li").html())
        .trigger("mouseleave")
        .siblings().toggle();
        p.append("x" + $("li:first").text() + "<br>")
      }
    })
});
ul {
  appearance: button;
  -moz-appearance: button;
  -webkit-appearance: button;
  -webkit-padding-start: 0px;
  width: 160px;
  height: 32px;
  left: 24px;
  position: relative;
}
ul li:nth-child(1) {
  background-color:buttonface !important;
}
ul li:nth-child(1):after {
  position: absolute;
  content: "▼";
  right: 10px;
  top: 10px;
  font-size: 12px;
  opacity: .75;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<ul id="select" class="select"></ul>
<p></p>
guest271314
  • 1
  • 15
  • 104
  • 177
  • 1
    Doesn't behave well in Firefox. – Ouroborus Dec 09 '16 at 05:52
  • @Ouroborus Are you referring to the styling of the `ul` parent element and `li` elements? – guest271314 Dec 09 '16 at 06:06
  • Note, to select `li` having text `"Two"` at `.ready()` call `$("#select li:contains(Two)").trigger("click");$("#select li:not(:first)").toggle()`. As indicated by @Ouroborus the styling of `ul`, `li` elements still needs further adjustment for firefox. – guest271314 Dec 09 '16 at 06:17
  • @guest271314 Was hoping to keep with the default browser elements, but thanks this does work! – Ryan Grush Dec 09 '16 at 06:17
  • 1
    @guest271314 There's a perimeter (the `ul`) around the selection view (the first `li`). It includes a larger "border" on the left. Clicking in the `ul` (anywhere along that border or the gap) causes a message to be added (on both open and close). – Ouroborus Dec 09 '16 at 06:18
  • @Ouroborus Yes, the `css` should be able to be adjusted at to be comparable with and render similarly to webkit browsers. – guest271314 Dec 09 '16 at 06:21
  • @Ouroborus Adjusted `css` for firefox by applying `position:relative` to `li` elements; added selection of `li` having text `"Two"` at `.ready()` https://plnkr.co/edit/LQf3rwHx7tKvuYw4YeLK?p=preview – guest271314 Dec 09 '16 at 06:51
  • @Ouroborus Good job. This is also a good illustration of why the various select plugins use a hidden ` – Ouroborus Dec 09 '16 at 06:54
  • @Ouroborus Substituting `css` `@supports` for `$.extend()` to set `position:relative` at firefox https://plnkr.co/edit/k76MoQAoPHsad9xm8R1g?p=preview – guest271314 Dec 09 '16 at 07:04
0

Using the jQuery change event, you can check to see whether the user's selection choice matches the suggested option that the system has in mind by using $('yourselect').val() to see what the select option selected value is.

$('yourselect').on('change', function() {
    var selected = $(this).val();
    if(selected === 'Expected') {
        // do this
    }
});
msafi
  • 377
  • 1
  • 5
  • 19
0

You can use the native DOM APIs, as an alternative to jQuery, to test the value of your select quite easily. This approach does require that you set the value of each option to some unique string; below I just used whatever you had as the display text.

document.getElementById('example-select').addEventListener('change', function () {
    console.log(this.value)
    
    if (this.value === 'Two') {
        // do stuff
        document.getElementById('example-output').textContent += 'x'
    }
});
<select id="example-select">
  <option value="One">One</option>
  <option value="Two" selected>Two</option>
  <option value="Three">Three</option>
</select>

<p id="example-output"></p>
gyre
  • 16,369
  • 3
  • 37
  • 47