@@ -25,9 +25,7 @@ module.exports = {
2525
2626 // attach listener
2727 this . on ( 'change' , function ( ) {
28- var value = self . multiple
29- ? getMultiValue ( el )
30- : el . value
28+ var value = getValue ( el , self . multiple )
3129 value = self . number
3230 ? _ . isArray ( value )
3331 ? value . map ( _ . toNumber )
@@ -58,13 +56,16 @@ module.exports = {
5856 var multi = this . multiple && _ . isArray ( value )
5957 var options = el . options
6058 var i = options . length
61- var option
59+ var op , val
6260 while ( i -- ) {
63- option = options [ i ]
61+ op = options [ i ]
62+ val = op . hasOwnProperty ( '_value' )
63+ ? op . _value
64+ : op . value
6465 /* eslint-disable eqeqeq */
65- option . selected = multi
66- ? indexOf ( value , option . value ) > - 1
67- : value == option . value
66+ op . selected = multi
67+ ? indexOf ( value , val ) > - 1
68+ : equals ( value , val )
6869 /* eslint-enable eqeqeq */
6970 }
7071 } ,
@@ -139,10 +140,13 @@ function buildOptions (parent, options) {
139140 if ( typeof op === 'string' ) {
140141 el . text = el . value = op
141142 } else {
142- if ( op . value != null ) {
143+ if ( op . value != null && ! _ . isObject ( op . value ) ) {
143144 el . value = op . value
144145 }
145- el . text = op . text || op . value || ''
146+ // object values gets serialized when set as value,
147+ // so we store the raw value as a different property
148+ el . _value = op . value
149+ el . text = op . text || ''
146150 if ( op . disabled ) {
147151 el . disabled = true
148152 }
@@ -181,29 +185,36 @@ function checkInitialValue () {
181185}
182186
183187/**
184- * Helper to extract a value array for select[multiple]
188+ * Get select value
185189 *
186190 * @param {SelectElement } el
187- * @return {Array }
191+ * @param {Boolean } multi
192+ * @return {Array|* }
188193 */
189194
190- function getMultiValue ( el ) {
191- return Array . prototype . filter
192- . call ( el . options , filterSelected )
193- . map ( getOptionValue )
194- }
195-
196- function filterSelected ( op ) {
197- return op . selected
198- }
199-
200- function getOptionValue ( op ) {
201- return op . value || op . text
195+ function getValue ( el , multi ) {
196+ var i = el . options . length
197+ var res = multi ? [ ] : null
198+ var op , val
199+ for ( var i = 0 , l = el . options . length ; i < l ; i ++ ) {
200+ op = el . options [ i ]
201+ if ( op . selected ) {
202+ val = op . hasOwnProperty ( '_value' )
203+ ? op . _value
204+ : op . value
205+ if ( multi ) {
206+ res . push ( val )
207+ } else {
208+ return val
209+ }
210+ }
211+ }
212+ return res
202213}
203214
204215/**
205216 * Native Array.indexOf uses strict equal, but in this
206- * case we need to match string/numbers with soft equal.
217+ * case we need to match string/numbers with custom equal.
207218 *
208219 * @param {Array } arr
209220 * @param {* } val
@@ -212,9 +223,19 @@ function getOptionValue (op) {
212223function indexOf ( arr , val ) {
213224 var i = arr . length
214225 while ( i -- ) {
215- /* eslint-disable eqeqeq */
216- if ( arr [ i ] == val ) return i
217- /* eslint-enable eqeqeq */
226+ if ( equals ( arr [ i ] , val ) ) {
227+ return i
228+ }
218229 }
219230 return - 1
220231}
232+
233+ /**
234+ * Check if two values are loosely equal. If two objects
235+ * have the same shape, they are considered equal too:
236+ * equals({a: 1}, {a: 1}) => true
237+ */
238+
239+ function equals ( a , b ) {
240+ return a == b || JSON . stringify ( a ) == JSON . stringify ( b )
241+ }
0 commit comments