(scope, selectElement, attr, ctrls)
| 31240 | optGroupTemplate = window.document.createElement('optgroup'); |
| 31241 | |
| 31242 | function ngOptionsPostLink(scope, selectElement, attr, ctrls) { |
| 31243 | |
| 31244 | var selectCtrl = ctrls[0]; |
| 31245 | var ngModelCtrl = ctrls[1]; |
| 31246 | var multiple = attr.multiple; |
| 31247 | |
| 31248 | // The emptyOption allows the application developer to provide their own custom "empty" |
| 31249 | // option when the viewValue does not match any of the option values. |
| 31250 | for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) { |
| 31251 | if (children[i].value === '') { |
| 31252 | selectCtrl.hasEmptyOption = true; |
| 31253 | selectCtrl.emptyOption = children.eq(i); |
| 31254 | break; |
| 31255 | } |
| 31256 | } |
| 31257 | |
| 31258 | // The empty option will be compiled and rendered before we first generate the options |
| 31259 | selectElement.empty(); |
| 31260 | |
| 31261 | var providedEmptyOption = !!selectCtrl.emptyOption; |
| 31262 | |
| 31263 | var unknownOption = jqLite(optionTemplate.cloneNode(false)); |
| 31264 | unknownOption.val('?'); |
| 31265 | |
| 31266 | var options; |
| 31267 | var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope); |
| 31268 | // This stores the newly created options before they are appended to the select. |
| 31269 | // Since the contents are removed from the fragment when it is appended, |
| 31270 | // we only need to create it once. |
| 31271 | var listFragment = $document[0].createDocumentFragment(); |
| 31272 | |
| 31273 | // Overwrite the implementation. ngOptions doesn't use hashes |
| 31274 | selectCtrl.generateUnknownOptionValue = function(val) { |
| 31275 | return '?'; |
| 31276 | }; |
| 31277 | |
| 31278 | // Update the controller methods for multiple selectable options |
| 31279 | if (!multiple) { |
| 31280 | |
| 31281 | selectCtrl.writeValue = function writeNgOptionsValue(value) { |
| 31282 | // The options might not be defined yet when ngModel tries to render |
| 31283 | if (!options) return; |
| 31284 | |
| 31285 | var selectedOption = selectElement[0].options[selectElement[0].selectedIndex]; |
| 31286 | var option = options.getOptionFromViewValue(value); |
| 31287 | |
| 31288 | // Make sure to remove the selected attribute from the previously selected option |
| 31289 | // Otherwise, screen readers might get confused |
| 31290 | if (selectedOption) selectedOption.removeAttribute('selected'); |
| 31291 | |
| 31292 | if (option) { |
| 31293 | // Don't update the option when it is already selected. |
| 31294 | // For example, the browser will select the first option by default. In that case, |
| 31295 | // most properties are set automatically - except the `selected` attribute, which we |
| 31296 | // set always |
| 31297 | |
| 31298 | if (selectElement[0].value !== option.selectValue) { |
| 31299 | selectCtrl.removeUnknownOption(); |
nothing calls this directly
no test coverage detected