... newly selected items are not configured to contain the selected attribute = "selected" ...
Right You will also notice that the value attribute in input not updated when the user updates its value (for example, if you look at outerHTML ).
Here's how it works. This is not a mistake or something that you are doing wrong. The execution state of the control is simply not reflected in the model of the HTML attribute of the element.
What is the expected behavior?
This is the expected behavior. If you want to know which elements are selected, do not look at the attributes, look at the selected property (not an attribute) of the parameter.
If you need an array of selected instances of HTMLOptionElement :
var selected = Array.prototype.filter.call($("id_form-0-project")[0].options, function(option) { return option.selected; });
If you want the actual values, combine them with .map :
var selected = Array.prototype.filter.call($("#id_form-0-project")[0].options, function(option) { return option.selected; }).map(function(option) { return option.value; });
You can, of course, easily wrap this in your own minimal jQuery plugin:
jQuery.fn.selectedValues = function() { if (!this[0] || !this[0].options) { return undefined; } return Array.prototype.filter.call(this[0].options, function(option) { return option.selected; }).map(function(option) { return option.value; }); };
then
var values = $("#id_form-0-project").selectedValues();
Your (good) question covers one of the (many) dark corners of how DOM and HTML serialization and browsers evolved over the years. Nobody would have designed this. :-) And yet, quirks and all this works surprisingly well.