Repository: sveltejs/svelte (JavaScript)
Date: 2017-05-01 19:06:20+00:00
Task type: Bug Fix

Issue:
Use `querySelector(':checked')` instead of `selectedOptions`
From [Gitter](https://gitter.im/sveltejs/svelte?at=59061335d32c6f2f0955d234) — it seems `selectedOptions` isn't supported in IE, and using `querySelector` means we could enable `<select>` tests without waiting for a new version of JSDOM.

[This is the relevant file.](https://github.com/sveltejs/svelte/blob/7f9d91f4351a105d6003cdb841b39e2d12bcf035/src/generators/dom/visitors/Element/Binding.js)

Thanks for the info @Zirro!


Issue discussion:
I believe I'll have time to submit a PR for this tomorrow. Some of the disabled tests need minor tweaks to pass (not directly related to the selectedOptions/:checked-replacement).

Solution patch:
diff --git a/src/generators/dom/visitors/Element/Binding.js b/src/generators/dom/visitors/Element/Binding.js
--- a/src/generators/dom/visitors/Element/Binding.js
+++ b/src/generators/dom/visitors/Element/Binding.js
@@ -30,7 +30,7 @@ export default function visitBinding ( generator, block, state, node, attribute
 	// <select> special case
 	if ( node.name === 'select' ) {
 		if ( !isMultipleSelect ) {
-			setter = `var selectedOption = ${state.parentNode}.selectedOptions[0] || ${state.parentNode}.options[0];\n${setter}`;
+			setter = `var selectedOption = ${state.parentNode}.querySelector(':checked') || ${state.parentNode}.options[0];\n${setter}`;
 		}
 
 		const value = block.getUniqueName( 'value' );
@@ -160,7 +160,7 @@ function getBindingEventName ( node, attribute ) {
 function getBindingValue ( generator, block, state, node, attribute, isMultipleSelect, bindingGroup, type ) {
 	// <select multiple bind:value='selected>
 	if ( isMultipleSelect ) {
-		return `[].map.call( ${state.parentNode}.selectedOptions, function ( option ) { return option.__value; })`;
+		return `[].map.call( ${state.parentNode}.querySelectorAll(':checked'), function ( option ) { return option.__value; })`;
 	}
 
 	// <select bind:value='selected>


Test patch:
diff --git a/test/runtime/samples/binding-select-initial-value/_config.js b/test/runtime/samples/binding-select-initial-value/_config.js
--- a/test/runtime/samples/binding-select-initial-value/_config.js
+++ b/test/runtime/samples/binding-select-initial-value/_config.js
@@ -1,6 +1,4 @@
 export default {
-	skip: true, // selectedOptions doesn't work in JSDOM???
-
 	html: `
 		<p>selected: b</p>
 
diff --git a/test/runtime/samples/binding-select-initial-value/main.html b/test/runtime/samples/binding-select-initial-value/main.html
--- a/test/runtime/samples/binding-select-initial-value/main.html
+++ b/test/runtime/samples/binding-select-initial-value/main.html
@@ -1,9 +1,9 @@
 <p>selected: {{selected}}</p>
 
 <select bind:value='selected'>
-	<option value="a">a</option>
-	<option value="b">b</option>
-	<option value="c">c</option>
+	<option>a</option>
+	<option>b</option>
+	<option>c</option>
 </select>
 
 <p>selected: {{selected}}</p>
\ No newline at end of file
diff --git a/test/runtime/samples/binding-select-multiple/_config.js b/test/runtime/samples/binding-select-multiple/_config.js
--- a/test/runtime/samples/binding-select-multiple/_config.js
+++ b/test/runtime/samples/binding-select-multiple/_config.js
@@ -1,12 +1,12 @@
 export default {
-	skip: true, // selectedOptions doesn't work in JSDOM???
+	skip: true, // JSDOM
 
 	data: {
 		selected: [ 'two', 'three' ]
 	},
 
 	html: `
-		<select>
+		<select multiple>
 			<option>one</option>
 			<option>two</option>
 			<option>three</option>
@@ -26,7 +26,7 @@ export default {
 
 		assert.deepEqual( component.get( 'selected' ), [ 'three' ] );
 		assert.htmlEqual( target.innerHTML, `
-			<select>
+			<select multiple>
 				<option>one</option>
 				<option>two</option>
 				<option>three</option>
@@ -40,7 +40,7 @@ export default {
 
 		assert.deepEqual( component.get( 'selected' ), [ 'one', 'three' ] );
 		assert.htmlEqual( target.innerHTML, `
-			<select>
+			<select multiple>
 				<option>one</option>
 				<option>two</option>
 				<option>three</option>
@@ -56,7 +56,7 @@ export default {
 		assert.ok( !options[2].selected );
 
 		assert.htmlEqual( target.innerHTML, `
-			<select>
+			<select multiple>
 				<option>one</option>
 				<option>two</option>
 				<option>three</option>
diff --git a/test/runtime/samples/binding-select/_config.js b/test/runtime/samples/binding-select/_config.js
--- a/test/runtime/samples/binding-select/_config.js
+++ b/test/runtime/samples/binding-select/_config.js
@@ -1,6 +1,4 @@
 export default {
-	skip: true, // selectedOptions doesn't work in JSDOM???
-
 	html: `
 		<p>selected: one</p>
 
@@ -13,6 +11,10 @@ export default {
 		<p>selected: one</p>
 	`,
 
+	data: {
+		selected: 'one'
+	},
+
 	test ( assert, component, target, window ) {
 		const select = target.querySelector( 'select' );
 		const options = [ ...target.querySelectorAll( 'option' ) ];
diff --git a/test/runtime/samples/select-change-handler/_config.js b/test/runtime/samples/select-change-handler/_config.js
--- a/test/runtime/samples/select-change-handler/_config.js
+++ b/test/runtime/samples/select-change-handler/_config.js
@@ -1,6 +1,4 @@
 export default {
-	skip: true, // JSDOM
-
 	data: {
 		options: [ { id: 'a' }, { id: 'b' }, { id: 'c' } ],
 		selected: 'b'
diff --git a/test/runtime/samples/select-one-way-bind-object/_config.js b/test/runtime/samples/select-one-way-bind-object/_config.js
--- a/test/runtime/samples/select-one-way-bind-object/_config.js
+++ b/test/runtime/samples/select-one-way-bind-object/_config.js
@@ -1,8 +1,6 @@
 const items = [ {}, {} ];
 
 export default {
-	skip: true, // JSDOM quirks
-
 	'skip-ssr': true,
 
 	data: {