mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-17 11:11:05 +00:00
input select-one now works
This commit is contained in:
parent
b814c79b58
commit
4fa166866b
7 changed files with 93 additions and 58 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
<head>
|
<head>
|
||||||
<script type="text/javascript" src="../lib/underscore/underscore.js"></script>
|
<script type="text/javascript" src="../lib/underscore/underscore.js"></script>
|
||||||
<script type="text/javascript" src="../lib/jquery/jquery-1.3.2.js"></script>
|
<script type="text/javascript" src="../lib/jquery/jquery-1.4.2.js"></script>
|
||||||
<script type="text/javascript" src="../src/angular-bootstrap.js"></script>
|
<script type="text/javascript" src="../src/angular-bootstrap.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
|
|
@ -18,15 +18,20 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<input type="checkbox" name="form.checked" ng-format="boolean" value="true" checked="checked" />
|
<input type="checkbox" name="form.checked" ng-format="boolean" value="true" checked="checked" />
|
||||||
<input ng-show="form.checked" name="form.required" ng-required/>
|
<input ng-show="form.checked" name="form.required" ng-required/>
|
||||||
|
<hr/>
|
||||||
|
<input name="form.list" ng-format="list" ng-required/>
|
||||||
|
<input name="form.list" ng-format="list" />
|
||||||
<hr/>
|
<hr/>
|
||||||
<input name="form.list" ng-format="list" ng-required/>
|
|
||||||
<input name="form.list" ng-format="list" />
|
|
||||||
<hr/>
|
|
||||||
<input type="checkbox" name="form.boolean" ng-format="boolean" value="true" checked="checked" />
|
<input type="checkbox" name="form.boolean" ng-format="boolean" value="true" checked="checked" />
|
||||||
<input type="checkbox" name="form.boolean" ng-format="boolean" value="true" />
|
<input type="checkbox" name="form.boolean" ng-format="boolean" value="true" />
|
||||||
<hr/>
|
<hr/>
|
||||||
<input type="text" name="form.async" ng-validate="asynchronous:$window.asyncValidate" />
|
<input type="text" name="form.async" ng-validate="asynchronous:$window.asyncValidate" />
|
||||||
|
<hr/>
|
||||||
|
<select name="select">
|
||||||
|
<option>A</option>
|
||||||
|
<option selected>B</option>
|
||||||
|
</select>
|
||||||
<pre>
|
<pre>
|
||||||
form={{form}}
|
form={{form}}
|
||||||
$invalidWidgets.length={{$invalidWidgets.length}}
|
$invalidWidgets.length={{$invalidWidgets.length}}
|
||||||
|
|
|
||||||
|
|
@ -32,24 +32,13 @@ function extensionMap(angular, name) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function extensionList(angular, name) {
|
|
||||||
var extPoint, length = 0;
|
|
||||||
return angular[name] || (extPoint = angular[name] = function (fn, prop){
|
|
||||||
if (isDefined(fn)) {
|
|
||||||
extPoint[length] = extend(fn, prop || {});
|
|
||||||
length++;
|
|
||||||
}
|
|
||||||
return extPoint;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var consoleNode, msie,
|
var consoleNode, msie,
|
||||||
NOOP = 'noop',
|
NOOP = 'noop',
|
||||||
jQuery = window['jQuery'] || window['$'], // weirdness to make IE happy
|
jQuery = window['jQuery'] || window['$'], // weirdness to make IE happy
|
||||||
slice = Array.prototype.slice,
|
slice = Array.prototype.slice,
|
||||||
angular = window['angular'] || (window['angular'] = {}),
|
angular = window['angular'] || (window['angular'] = {}),
|
||||||
angularTextMarkup = extensionList(angular, 'textMarkup'),
|
angularTextMarkup = extensionMap(angular, 'textMarkup'),
|
||||||
angularAttrMarkup = extensionList(angular, 'attrMarkup'),
|
angularAttrMarkup = extensionMap(angular, 'attrMarkup'),
|
||||||
angularDirective = extensionMap(angular, 'directive'),
|
angularDirective = extensionMap(angular, 'directive'),
|
||||||
angularWidget = extensionMap(angular, 'widget'),
|
angularWidget = extensionMap(angular, 'widget'),
|
||||||
angularValidator = extensionMap(angular, 'validator'),
|
angularValidator = extensionMap(angular, 'validator'),
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ Compiler.prototype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (widget) {
|
if (widget) {
|
||||||
|
descend = false;
|
||||||
template.addInit(widget.call(selfApi, element));
|
template.addInit(widget.call(selfApi, element));
|
||||||
} else {
|
} else {
|
||||||
// process markup for text nodes only
|
// process markup for text nodes only
|
||||||
|
|
@ -152,12 +153,12 @@ Compiler.prototype = {
|
||||||
template.addInit(directive());
|
template.addInit(directive());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Process non text child nodes
|
}
|
||||||
if (descend) {
|
// Process non text child nodes
|
||||||
eachNode(element, function(child, i){
|
if (descend) {
|
||||||
template.addChild(i, self.templatize(child));
|
eachNode(element, function(child, i){
|
||||||
});
|
template.addChild(i, self.templatize(child));
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
return template.empty() ? null : template;
|
return template.empty() ? null : template;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,30 +27,42 @@ function hasBindings(bindings) {
|
||||||
return bindings.length > 1 || Binder.binding(bindings[0]) !== null;
|
return bindings.length > 1 || Binder.binding(bindings[0]) !== null;
|
||||||
};
|
};
|
||||||
|
|
||||||
angularTextMarkup(function(text, textNode, parentElement) {
|
angularTextMarkup('{{}}', function(text, textNode, parentElement) {
|
||||||
var bindings = parseBindings(text),
|
var bindings = parseBindings(text),
|
||||||
self = this;
|
self = this;
|
||||||
if (isLeafNode(parentElement[0])) {
|
if (hasBindings(bindings)) {
|
||||||
parentElement.attr('ng-bind-template', text);
|
if (isLeafNode(parentElement[0])) {
|
||||||
} else {
|
parentElement.attr('ng-bind-template', text);
|
||||||
var cursor = textNode, newElement;
|
} else {
|
||||||
foreach(parseBindings(text), function(text){
|
var cursor = textNode, newElement;
|
||||||
var exp = binding(text);
|
foreach(parseBindings(text), function(text){
|
||||||
if (exp) {
|
var exp = binding(text);
|
||||||
newElement = self.element('span');
|
if (exp) {
|
||||||
newElement.attr('ng-bind', exp);
|
newElement = self.element('span');
|
||||||
} else {
|
newElement.attr('ng-bind', exp);
|
||||||
newElement = self.text(text);
|
} else {
|
||||||
}
|
newElement = self.text(text);
|
||||||
cursor.after(newElement);
|
}
|
||||||
cursor = newElement;
|
cursor.after(newElement);
|
||||||
});
|
cursor = newElement;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
textNode.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
angularTextMarkup('OPTION', function(text, textNode, parentElement){
|
||||||
|
if (parentElement[0].nodeName == "OPTION") {
|
||||||
|
var select = document.createElement('select');
|
||||||
|
select.insertBefore(parentElement[0].cloneNode(true), null);
|
||||||
|
if (!select.innerHTML.match(/<option(\s.*\s|\s)value\s*=\s*.*>.*<\/\s*option\s*>/gi)) {
|
||||||
|
parentElement.attr('value', text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
textNode.remove();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var NG_BIND_ATTR = 'ng-bind-attr';
|
var NG_BIND_ATTR = 'ng-bind-attr';
|
||||||
angularAttrMarkup(function(value, name, element){
|
angularAttrMarkup('{{}}', function(value, name, element){
|
||||||
if (name.substr(0, 3) != 'ng-') {
|
if (name.substr(0, 3) != 'ng-') {
|
||||||
var bindings = parseBindings(value),
|
var bindings = parseBindings(value),
|
||||||
bindAttr;
|
bindAttr;
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ var NG_ERROR = 'ng-error',
|
||||||
'reset': buttonWidget,
|
'reset': buttonWidget,
|
||||||
'image': buttonWidget,
|
'image': buttonWidget,
|
||||||
'checkbox': inputWidget('click', modelAccessor, checkedAccessor, false),
|
'checkbox': inputWidget('click', modelAccessor, checkedAccessor, false),
|
||||||
'radio': inputWidget('click', modelAccessor, radioAccessor, undefined)
|
'radio': inputWidget('click', modelAccessor, radioAccessor, undefined),
|
||||||
// 'select-one': [null, 'change'],
|
'select-one': inputWidget('click', modelAccessor, valueAccessor, null)
|
||||||
// 'select-multiple': [[], 'change'],
|
// 'select-multiple': [[], 'change'],
|
||||||
// 'file': [{}, 'click']
|
// 'file': [{}, 'click']
|
||||||
};
|
};
|
||||||
|
|
@ -84,9 +84,10 @@ function inputWidget(events, modelAccessor, viewAccessor, initValue) {
|
||||||
var scope = this,
|
var scope = this,
|
||||||
model = modelAccessor(scope, element),
|
model = modelAccessor(scope, element),
|
||||||
view = viewAccessor(element),
|
view = viewAccessor(element),
|
||||||
action = element.attr('ng-action') || '';
|
action = element.attr('ng-action') || '',
|
||||||
var value = view.get() || initValue;
|
value = view.get() || initValue;
|
||||||
if (isDefined(value)) model.set(value);
|
if (isDefined(value)) model.set(value);
|
||||||
|
this.$eval(element.attr('ng-init')||'');
|
||||||
element.bind(events, function(){
|
element.bind(events, function(){
|
||||||
model.set(view.get());
|
model.set(view.get());
|
||||||
scope.$eval(action);
|
scope.$eval(action);
|
||||||
|
|
@ -95,13 +96,14 @@ function inputWidget(events, modelAccessor, viewAccessor, initValue) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
angularWidget('INPUT', function input(element){
|
function inputWidgetSelector(element){
|
||||||
return function(element) {
|
return INPUT_TYPE[lowercase(element[0].type)] || noop;
|
||||||
this.$eval(element.attr('ng-init')||'');
|
}
|
||||||
(INPUT_TYPE[lowercase(element[0].type)] || noop).call(this, element);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
angularWidget('TEXTAREA', function(){
|
angularWidget('INPUT', inputWidgetSelector);
|
||||||
return textWidget;
|
angularWidget('TEXTAREA', inputWidgetSelector);
|
||||||
|
angularWidget('BUTTON', inputWidgetSelector);
|
||||||
|
angularWidget('SELECT', function(element){
|
||||||
|
this.descend(true);
|
||||||
|
return inputWidgetSelector.call(this, element);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,11 @@ describe("markups", function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should translate {{}} in terminal nodes', function(){
|
it('should translate {{}} in terminal nodes', function(){
|
||||||
compile('<select><option>Greet {{name}}!</option></select>');
|
compile('<select name="x"><option value="">Greet {{name}}!</option></select>');
|
||||||
expect(element.html()).toEqual('<option ng-bind-template="Greet {{name}}!"></option>');
|
expect(element.html()).toEqual('<option ng-bind-template="Greet {{name}}!" value=""></option>');
|
||||||
scope.set('name', 'Misko');
|
scope.set('name', 'Misko');
|
||||||
scope.updateView();
|
scope.updateView();
|
||||||
expect(element.html()).toEqual('<option ng-bind-template="Greet {{name}}!">Greet Misko!</option>');
|
expect(element.html()).toEqual('<option ng-bind-template="Greet {{name}}!" value="">Greet Misko!</option>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should translate {{}} in attributes', function(){
|
it('should translate {{}} in attributes', function(){
|
||||||
|
|
@ -46,4 +46,9 @@ describe("markups", function(){
|
||||||
expect(element.attr('src')).toEqual("http://server/a/b.png");
|
expect(element.attr('src')).toEqual("http://server/a/b.png");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should populate value attribute on OPTION', function(){
|
||||||
|
compile('<select name="x"><option>A</option></select>');
|
||||||
|
expect(element.html()).toEqual('<option value="A">A</option>');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,12 @@ describe("input widget", function(){
|
||||||
expect(scope.get('clicked')).toEqual(true);
|
expect(scope.get('clicked')).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support button alias', function(){
|
||||||
|
compile('<button ng-action="clicked = true">Click Me</button>');
|
||||||
|
element.click();
|
||||||
|
expect(scope.get('clicked')).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('should type="checkbox"', function(){
|
it('should type="checkbox"', function(){
|
||||||
compile('<input type="checkbox" name="checkbox" checked ng-action="action = true"/>');
|
compile('<input type="checkbox" name="checkbox" checked ng-action="action = true"/>');
|
||||||
expect(scope.get('checkbox')).toEqual(true);
|
expect(scope.get('checkbox')).toEqual(true);
|
||||||
|
|
@ -142,6 +148,21 @@ describe("input widget", function(){
|
||||||
expect(model.clicked).toEqual(1);
|
expect(model.clicked).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should type="radio"', function(){
|
||||||
|
compile(
|
||||||
|
'<select name="selection">' +
|
||||||
|
'<option>A</option>' +
|
||||||
|
'<option selected>B</option>' +
|
||||||
|
'</select>');
|
||||||
|
expect(element[0].selectedIndex).toEqual(1);
|
||||||
|
expect(element[0].value).toEqual('B');
|
||||||
|
expect(model.selection).toEqual('B');
|
||||||
|
model.selection = 'A';
|
||||||
|
model.$updateView();
|
||||||
|
expect(model.selection).toEqual('A');
|
||||||
|
expect(element[0].childNodes[0].selected).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('should report error on missing field', function(){
|
it('should report error on missing field', function(){
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue