From 9ee2cdff44e7d496774b340de816344126c457b3 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Tue, 22 Nov 2011 21:28:39 -0800 Subject: refactor(directives): connect new compiler - turn everything into a directive --- src/widget/select.js | 554 ++++++++++++++++++++++++++------------------------- 1 file changed, 284 insertions(+), 270 deletions(-) (limited to 'src/widget/select.js') diff --git a/src/widget/select.js b/src/widget/select.js index a3633ddd..ae9e1b7c 100644 --- a/src/widget/select.js +++ b/src/widget/select.js @@ -112,321 +112,335 @@ it('should check ng:options', function() { - expect(binding('color')).toMatch('red'); + expect(binding('{selected_color:color}')).toMatch('red'); select('color').option('0'); - expect(binding('color')).toMatch('black'); + expect(binding('{selected_color:color}')).toMatch('black'); using('.nullable').select('color').option(''); - expect(binding('color')).toMatch('null'); + expect(binding('{selected_color:color}')).toMatch('null'); }); */ - - //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777 -var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/; - - -angularWidget('select', function(element){ - this.directives(true); - this.descend(true); - return element.attr('ng:model') && - ['$formFactory', '$compile', '$parse', '$element', - function($formFactory, $compile, $parse, selectElement){ - var modelScope = this, - match, - form = $formFactory.forElement(selectElement), - multiple = selectElement.attr('multiple'), - optionsExp = selectElement.attr('ng:options'), - modelExp = selectElement.attr('ng:model'), - widget = form.$createWidget({ - scope: modelScope, - model: modelExp, - onChange: selectElement.attr('ng:change'), - alias: selectElement.attr('name'), - controller: ['$scope', optionsExp ? Options : (multiple ? Multiple : Single)]}); - - selectElement.bind('$destroy', function() { widget.$destroy(); }); - - widget.$pristine = !(widget.$dirty = false); - - watchElementProperty(modelScope, widget, 'required', selectElement); - watchElementProperty(modelScope, widget, 'readonly', selectElement); - watchElementProperty(modelScope, widget, 'disabled', selectElement); - - widget.$on('$validate', function() { - var valid = !widget.$required || !!widget.$modelValue; - if (valid && multiple && widget.$required) valid = !!widget.$modelValue.length; - if (valid !== !widget.$error.REQUIRED) { - widget.$emit(valid ? '$valid' : '$invalid', 'REQUIRED'); - } - }); - - widget.$on('$viewChange', function() { - widget.$pristine = !(widget.$dirty = true); - }); - - forEach(['valid', 'invalid', 'pristine', 'dirty'], function(name) { - widget.$watch('$' + name, function(value) { - selectElement[value ? 'addClass' : 'removeClass']('ng-' + name); +var ngOptionsDirective = valueFn({ terminal: true }); +var selectDirective = ['$formFactory', '$compile', '$parse', + function($formFactory, $compile, $parse){ + //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777 + var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/; + + return { + restrict: 'E', + link: function(modelScope, selectElement, attr) { + if (!attr.ngModel) return; + var form = $formFactory.forElement(selectElement), + multiple = attr.multiple, + optionsExp = attr.ngOptions, + modelExp = attr.ngModel, + widget = form.$createWidget({ + scope: modelScope, + model: modelExp, + onChange: attr.ngChange, + alias: attr.name, + controller: ['$scope', optionsExp ? Options : (multiple ? Multiple : Single)]}); + + selectElement.bind('$destroy', function() { widget.$destroy(); }); + + widget.$pristine = !(widget.$dirty = false); + + widget.$on('$validate', function() { + var valid = !attr.required || !!widget.$modelValue; + if (valid && multiple && attr.required) valid = !!widget.$modelValue.length; + if (valid !== !widget.$error.REQUIRED) { + widget.$emit(valid ? '$valid' : '$invalid', 'REQUIRED'); + } }); - }); - //////////////////////////// + widget.$on('$viewChange', function() { + widget.$pristine = !(widget.$dirty = true); + }); - function Multiple(widget) { - widget.$render = function() { - var items = new HashMap(widget.$viewValue); - forEach(selectElement.children(), function(option){ - option.selected = isDefined(items.get(option.value)); + forEach(['valid', 'invalid', 'pristine', 'dirty'], function(name) { + widget.$watch('$' + name, function(value) { + selectElement[value ? 'addClass' : 'removeClass']('ng-' + name); }); - }; + }); + + //////////////////////////// - selectElement.bind('change', function() { - widget.$apply(function() { - var array = []; + function Multiple(widget) { + widget.$render = function() { + var items = new HashMap(this.$viewValue); forEach(selectElement.children(), function(option){ - if (option.selected) { - array.push(option.value); - } + option.selected = isDefined(items.get(option.value)); + }); + }; + + selectElement.bind('change', function() { + widget.$apply(function() { + var array = []; + forEach(selectElement.children(), function(option){ + if (option.selected) { + array.push(option.value); + } + }); + widget.$emit('$viewChange', array); }); - widget.$emit('$viewChange', array); }); - }); - } + } - function Single(widget) { - widget.$render = function() { - selectElement.val(widget.$viewValue); - }; + function Single(widget) { + widget.$render = function() { + selectElement.val(widget.$viewValue); + }; - selectElement.bind('change', function() { - widget.$apply(function() { - widget.$emit('$viewChange', selectElement.val()); + selectElement.bind('change', function() { + widget.$apply(function() { + widget.$emit('$viewChange', selectElement.val()); + }); }); - }); - - widget.$viewValue = selectElement.val(); - } - - function Options(widget) { - var match; - if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) { - throw Error( - "Expected ng:options in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + - " but got '" + optionsExp + "'."); + widget.$viewValue = selectElement.val(); } - var displayFn = $parse(match[2] || match[1]), - valueName = match[4] || match[6], - keyName = match[5], - groupByFn = $parse(match[3] || ''), - valueFn = $parse(match[2] ? match[1] : valueName), - valuesFn = $parse(match[7]), - // we can't just jqLite('