| 14633 | scope.$watch(render); |
| 14634 | |
| 14635 | function render() { |
| 14636 | var optionGroups = {'':[]}, // Temporary location for the option groups before we render them |
| 14637 | optionGroupNames = [''], |
| 14638 | optionGroupName, |
| 14639 | optionGroup, |
| 14640 | option, |
| 14641 | existingParent, existingOptions, existingOption, |
| 14642 | modelValue = ctrl.$modelValue, |
| 14643 | values = valuesFn(scope) || [], |
| 14644 | keys = keyName ? sortedKeys(values) : values, |
| 14645 | groupLength, length, |
| 14646 | groupIndex, index, |
| 14647 | locals = {}, |
| 14648 | selected, |
| 14649 | selectedSet = false, // nothing is selected yet |
| 14650 | lastElement, |
| 14651 | element, |
| 14652 | label; |
| 14653 | |
| 14654 | if (multiple) { |
| 14655 | selectedSet = new HashMap(modelValue); |
| 14656 | } |
| 14657 | |
| 14658 | // We now build up the list of options we need (we merge later) |
| 14659 | for (index = 0; length = keys.length, index < length; index++) { |
| 14660 | locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index]; |
| 14661 | optionGroupName = groupByFn(scope, locals) || ''; |
| 14662 | if (!(optionGroup = optionGroups[optionGroupName])) { |
| 14663 | optionGroup = optionGroups[optionGroupName] = []; |
| 14664 | optionGroupNames.push(optionGroupName); |
| 14665 | } |
| 14666 | if (multiple) { |
| 14667 | selected = selectedSet.remove(valueFn(scope, locals)) != undefined; |
| 14668 | } else { |
| 14669 | selected = modelValue === valueFn(scope, locals); |
| 14670 | selectedSet = selectedSet || selected; // see if at least one item is selected |
| 14671 | } |
| 14672 | label = displayFn(scope, locals); // what will be seen by the user |
| 14673 | label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values |
| 14674 | optionGroup.push({ |
| 14675 | id: keyName ? keys[index] : index, // either the index into array or key from object |
| 14676 | label: label, |
| 14677 | selected: selected // determine if we should be selected |
| 14678 | }); |
| 14679 | } |
| 14680 | if (!multiple) { |
| 14681 | if (nullOption || modelValue === null) { |
| 14682 | // insert null option if we have a placeholder, or the model is null |
| 14683 | optionGroups[''].unshift({id:'', label:'', selected:!selectedSet}); |
| 14684 | } else if (!selectedSet) { |
| 14685 | // option could not be found, we have to insert the undefined item |
| 14686 | optionGroups[''].unshift({id:'?', label:'', selected:true}); |
| 14687 | } |
| 14688 | } |
| 14689 | |
| 14690 | // Now we need to update the list of DOM nodes to match the optionGroups we computed above |
| 14691 | for (groupIndex = 0, groupLength = optionGroupNames.length; |
| 14692 | groupIndex < groupLength; |