mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
changed the documentation @example to use <doc:example>
This commit is contained in:
parent
ed768ebc53
commit
ba6b68b6ae
20 changed files with 1841 additions and 1653 deletions
|
|
@ -46,12 +46,13 @@ You can use these variables in the function:
|
|||
the DOM in addition to transforming the input.
|
||||
|
||||
|
||||
@exampleDescription
|
||||
@example
|
||||
The following example filter reverses a text string. In addition, it conditionally makes the
|
||||
text upper-case (to demonstrate optional arguments) and assigns color (to demonstrate DOM
|
||||
modification).
|
||||
|
||||
@example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script type="text/javascript">
|
||||
angular.filter('reverse', function(input, uppercase, color) {
|
||||
var out = "";
|
||||
|
|
@ -73,4 +74,14 @@ You can use these variables in the function:
|
|||
Reverse: {{text|reverse}}<br>
|
||||
Reverse + uppercase: {{text|reverse:true}}<br>
|
||||
Reverse + uppercase + blue: {{text|reverse:true:"blue"}}
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should reverse text', function(){
|
||||
expect(binding('text|reverse')).toEqual('olleh');
|
||||
input('text').enter('ABC');
|
||||
expect(binding('text|reverse')).toEqual('CBA');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,42 +37,46 @@ angular.formatter('reverse', {
|
|||
</pre>
|
||||
|
||||
@example
|
||||
<script type="text/javascript">
|
||||
function reverse(text) {
|
||||
var reversed = [];
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
reversed.unshift(text.charAt(i));
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script type="text/javascript">
|
||||
function reverse(text) {
|
||||
var reversed = [];
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
reversed.unshift(text.charAt(i));
|
||||
}
|
||||
return reversed.join('');
|
||||
}
|
||||
return reversed.join('');
|
||||
}
|
||||
|
||||
angular.formatter('reverse', {
|
||||
parse: function(value){
|
||||
return reverse(value||'').toUpperCase();
|
||||
},
|
||||
format: function(value){
|
||||
return reverse(value||'').toLowerCase();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
angular.formatter('reverse', {
|
||||
parse: function(value){
|
||||
return reverse(value||'').toUpperCase();
|
||||
},
|
||||
format: function(value){
|
||||
return reverse(value||'').toLowerCase();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
Formatted:
|
||||
<input type="text" name="data" value="angular" ng:format="reverse"/>
|
||||
<br/>
|
||||
Formatted:
|
||||
<input type="text" name="data" value="angular" ng:format="reverse"/>
|
||||
<br/>
|
||||
|
||||
Stored:
|
||||
<input type="text" name="data"/><br/>
|
||||
<pre>{{data}}</pre>
|
||||
Stored:
|
||||
<input type="text" name="data"/><br/>
|
||||
<pre>{{data}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should store reverse', function(){
|
||||
expect(element('.doc-example input:first').val()).toEqual('angular');
|
||||
expect(element('.doc-example input:last').val()).toEqual('RALUGNA');
|
||||
|
||||
this.addFutureAction('change to XYZ', function($window, $document, done){
|
||||
$document.elements('.doc-example input:last').val('XYZ').trigger('change');
|
||||
done();
|
||||
});
|
||||
expect(element('.doc-example input:first').val()).toEqual('zyx');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
|
||||
@scenario
|
||||
it('should store reverse', function(){
|
||||
expect(element('.doc-example input:first').val()).toEqual('angular');
|
||||
expect(element('.doc-example input:last').val()).toEqual('RALUGNA');
|
||||
|
||||
this.addFutureAction('change to XYZ', function($window, $document, done){
|
||||
$document.elements('.doc-example input:last').val('XYZ').trigger('change');
|
||||
done();
|
||||
});
|
||||
expect(element('.doc-example input:first').val()).toEqual('zyx');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,22 +17,22 @@ services if needed.
|
|||
|
||||
Like other core angular variables and identifiers, the built-in services always start with `$`.
|
||||
|
||||
* `{@link angular.service.$browser $browser}`
|
||||
* `{@link angular.service.$window $window}`
|
||||
* `{@link angular.service.$document $document}`
|
||||
* `{@link angular.service.$location $location}`
|
||||
* `{@link angular.service.$log $log}`
|
||||
* `{@link angular.service.$exceptionHandler $exceptionHandler}`
|
||||
* `{@link angular.service.$hover $hover}`
|
||||
* `{@link angular.service.$invalidWidgets $invalidWidgets}`
|
||||
* `{@link angular.service.$route $route}`
|
||||
* `{@link angular.service.$xhr $xhr}`
|
||||
* `{@link angular.service.$xhr.error $xhr.error}`
|
||||
* `{@link angular.service.$xhr.bulk $xhr.bulk}`
|
||||
* `{@link angular.service.$xhr.cache $xhr.cache}`
|
||||
* `{@link angular.service.$resource $resource}`
|
||||
* `{@link angular.service.$cookies $cookies}`
|
||||
* `{@link angular.service.$cookieStore $cookieStore}`
|
||||
* {@link angular.service.$browser $browser}
|
||||
* {@link angular.service.$window $window}
|
||||
* {@link angular.service.$document $document}
|
||||
* {@link angular.service.$location $location}
|
||||
* {@link angular.service.$log $log}
|
||||
* {@link angular.service.$exceptionHandler $exceptionHandler}
|
||||
* {@link angular.service.$hover $hover}
|
||||
* {@link angular.service.$invalidWidgets $invalidWidgets}
|
||||
* {@link angular.service.$route $route}
|
||||
* {@link angular.service.$xhr $xhr}
|
||||
* {@link angular.service.$xhr.error $xhr.error}
|
||||
* {@link angular.service.$xhr.bulk $xhr.bulk}
|
||||
* {@link angular.service.$xhr.cache $xhr.cache}
|
||||
* {@link angular.service.$resource $resource}
|
||||
* {@link angular.service.$cookies $cookies}
|
||||
* {@link angular.service.$cookieStore $cookieStore}
|
||||
|
||||
# Writing your own custom services
|
||||
angular provides only set of basic services, so for any nontrivial application it will be necessary
|
||||
|
|
@ -138,29 +138,38 @@ myController.$inject = ['$location', '$log'];
|
|||
</pre>
|
||||
|
||||
@example
|
||||
<script type="text/javascript">
|
||||
angular.service('notify', function(win) {
|
||||
var msgs = [];
|
||||
return function(msg) {
|
||||
msgs.push(msg);
|
||||
if (msgs.length == 3) {
|
||||
win.alert(msgs.join("\n"));
|
||||
msgs = [];
|
||||
}
|
||||
};
|
||||
}, {$inject: ['$window']});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script type="text/javascript">
|
||||
angular.service('notify', function(win) {
|
||||
var msgs = [];
|
||||
return function(msg) {
|
||||
msgs.push(msg);
|
||||
if (msgs.length == 3) {
|
||||
win.alert(msgs.join("\n"));
|
||||
msgs = [];
|
||||
}
|
||||
};
|
||||
}, {$inject: ['$window']});
|
||||
|
||||
function myController(notifyService) {
|
||||
this.callNotify = function(msg) {
|
||||
notifyService(msg);
|
||||
};
|
||||
}
|
||||
function myController(notifyService) {
|
||||
this.callNotify = function(msg) {
|
||||
notifyService(msg);
|
||||
};
|
||||
}
|
||||
|
||||
myController.$inject = ['notify'];
|
||||
</script>
|
||||
myController.$inject = ['notify'];
|
||||
</script>
|
||||
|
||||
<div ng:controller="myController">
|
||||
<p>Let's try this simple notify service, injected into the controller...</p>
|
||||
<input ng:init="message='test'" type="text" name="message" />
|
||||
<button ng:click="callNotify(message);">NOTIFY</button>
|
||||
</div>
|
||||
<div ng:controller="myController">
|
||||
<p>Let's try this simple notify service, injected into the controller...</p>
|
||||
<input ng:init="message='test'" type="text" name="message" />
|
||||
<button ng:click="callNotify(message);">NOTIFY</button>
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should test service', function(){
|
||||
expect(element(':input[name=message]').val()).toEqual('test');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
|
|
|
|||
|
|
@ -50,24 +50,28 @@ UPS tracking number.
|
|||
default.
|
||||
|
||||
@example
|
||||
<script>
|
||||
angular.validator('upsTrackingNo', function(input, format) {
|
||||
var regexp = new RegExp("^" + format.replace(/9/g, '\\d') + "$");
|
||||
return input.match(regexp)?"":"The format must match " + format;
|
||||
});
|
||||
</script>
|
||||
<input type="text" name="trackNo" size="40"
|
||||
ng:validate="upsTrackingNo:'1Z 999 999 99 9999 999 9'"
|
||||
value="1Z 123 456 78 9012 345 6"/>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
angular.validator('upsTrackingNo', function(input, format) {
|
||||
var regexp = new RegExp("^" + format.replace(/9/g, '\\d') + "$");
|
||||
return input.match(regexp)?"":"The format must match " + format;
|
||||
});
|
||||
</script>
|
||||
<input type="text" name="trackNo" size="40"
|
||||
ng:validate="upsTrackingNo:'1Z 999 999 99 9999 999 9'"
|
||||
value="1Z 123 456 78 9012 345 6"/>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should validate correct UPS tracking number', function() {
|
||||
expect(element('input[name=trackNo]').attr('class')).
|
||||
not().toMatch(/ng-validation-error/);
|
||||
});
|
||||
|
||||
@scenario
|
||||
it('should validate correct UPS tracking number', function() {
|
||||
expect(element('input[name=trackNo]').attr('class')).
|
||||
not().toMatch(/ng-validation-error/);
|
||||
});
|
||||
|
||||
it('should not validate in correct UPS tracking number', function() {
|
||||
input('trackNo').enter('foo');
|
||||
expect(element('input[name=trackNo]').attr('class')).
|
||||
toMatch(/ng-validation-error/);
|
||||
});
|
||||
it('should not validate in correct UPS tracking number', function() {
|
||||
input('trackNo').enter('foo');
|
||||
expect(element('input[name=trackNo]').attr('class')).
|
||||
toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
|
|
|
|||
|
|
@ -57,17 +57,22 @@ angular.widget('@my:watch', function(expression, compileElement) {
|
|||
</pre>
|
||||
|
||||
@example
|
||||
<script>
|
||||
angular.widget('my:time', function(compileElement){
|
||||
compileElement.css('display', 'block');
|
||||
return function(linkElement){
|
||||
function update(){
|
||||
linkElement.text('Current time is: ' + new Date());
|
||||
setTimeout(update, 1000);
|
||||
}
|
||||
update();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
<my:time></my:time>
|
||||
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
angular.widget('my:time', function(compileElement){
|
||||
compileElement.css('display', 'block');
|
||||
return function(linkElement){
|
||||
function update(){
|
||||
linkElement.text('Current time is: ' + new Date());
|
||||
setTimeout(update, 1000);
|
||||
}
|
||||
update();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
<my:time></my:time>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
|
|
|
|||
|
|
@ -7,34 +7,6 @@ describe('dom', function(){
|
|||
dom = new DOM();
|
||||
});
|
||||
|
||||
describe('example', function(){
|
||||
it('should render code, live, test', function(){
|
||||
dom.example('desc', 'src', 'scenario');
|
||||
expect(dom.toString()).toEqual(
|
||||
'<h1>Example</h1>\n' +
|
||||
'<div class="example">' +
|
||||
'desc<doc:example><doc:source>src</doc:source>\n' +
|
||||
'<doc:scenario>scenario</doc:scenario>\n'+
|
||||
'</doc:example>\n' +
|
||||
'</div>\n');
|
||||
});
|
||||
|
||||
it('should render non-live, test with description', function(){
|
||||
dom.example('desc', 'src', false);
|
||||
expect(dom.toString()).toEqual('<h1>Example</h1>\n' +
|
||||
'<div class="example">' +
|
||||
'desc<div ng:non-bindable="">' +
|
||||
'<pre class="brush: js; html-script: true;">src</pre>\n' +
|
||||
'</div>\n' +
|
||||
'</div>\n');
|
||||
});
|
||||
|
||||
it('should render non-live, test', function(){
|
||||
dom.example('desc', 'src', false);
|
||||
expect(dom.toString()).toContain('<pre class="brush: js; html-script: true;">src</pre>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('h', function(){
|
||||
|
||||
it('should render using function', function(){
|
||||
|
|
|
|||
|
|
@ -74,12 +74,6 @@ describe('ngdoc', function(){
|
|||
});
|
||||
});
|
||||
|
||||
it('should not remove extra line breaks', function(){
|
||||
var doc = new Doc('@example\nA\n\nB');
|
||||
doc.parse();
|
||||
expect(doc.example).toEqual('A\n\nB');
|
||||
});
|
||||
|
||||
it('should parse filename', function(){
|
||||
var doc = new Doc('@name friendly name', 'docs/a.b.ngdoc', 1);
|
||||
doc.parse(0);
|
||||
|
|
@ -128,32 +122,14 @@ describe('ngdoc', function(){
|
|||
});
|
||||
});
|
||||
|
||||
describe('scenario', function(){
|
||||
it('should render from @example/@scenario and <doc:example>', function(){
|
||||
var doc = new Doc(
|
||||
'@id id\n' +
|
||||
'@description <doc:example><doc:scenario>scenario0</doc:scenario></doc:example>' +
|
||||
'@example exempleText\n' +
|
||||
'@scenario scenario1\n' +
|
||||
'@scenario scenario2').parse();
|
||||
expect(ngdoc.scenarios([doc])).toContain('describe("id"');
|
||||
expect(ngdoc.scenarios([doc])).toContain('navigateTo("index.html#!id")');
|
||||
expect(ngdoc.scenarios([doc])).toContain('\n scenario0\n');
|
||||
expect(ngdoc.scenarios([doc])).toContain('\n scenario1\n');
|
||||
expect(ngdoc.scenarios([doc])).toContain('\n scenario2\n');
|
||||
});
|
||||
});
|
||||
|
||||
describe('markdown', function(){
|
||||
var markdown = ngdoc.markdown;
|
||||
|
||||
it('should replace angular in markdown', function(){
|
||||
expect(markdown('<angular/>')).
|
||||
expect(new Doc().markdown('<angular/>')).
|
||||
toEqual('<p><tt><angular/></tt></p>');
|
||||
});
|
||||
|
||||
it('should not replace anything in <pre>, but escape the html escape the content', function(){
|
||||
expect(markdown('bah x\n<pre>\n<b>angular</b>.k\n</pre>\n asdf x')).
|
||||
expect(new Doc().markdown('bah x\n<pre>\n<b>angular</b>.k\n</pre>\n asdf x')).
|
||||
toEqual(
|
||||
'<p>bah x</p>' +
|
||||
'<div ng:non-bindable><pre class="brush: js; html-script: true;">\n' +
|
||||
|
|
@ -163,7 +139,7 @@ describe('ngdoc', function(){
|
|||
});
|
||||
|
||||
it('should replace text between two <pre></pre> tags', function() {
|
||||
expect(markdown('<pre>x</pre># One<pre>b</pre>')).
|
||||
expect(new Doc().markdown('<pre>x</pre># One<pre>b</pre>')).
|
||||
toMatch('</div><h1>One</h1><div');
|
||||
});
|
||||
|
||||
|
|
@ -340,38 +316,20 @@ describe('ngdoc', function(){
|
|||
it('should not remove {{}}', function(){
|
||||
var doc = new Doc('@example text {{ abc }}');
|
||||
doc.parse();
|
||||
expect(doc.example).toEqual('text {{ abc }}');
|
||||
});
|
||||
});
|
||||
|
||||
describe('@exampleDescription', function(){
|
||||
it('should render example description', function(){
|
||||
var doc = new Doc('@exampleDescription some\n text');
|
||||
doc.ngdoc = "filter";
|
||||
doc.parse();
|
||||
expect(doc.html()).toContain('<p>some\n text');
|
||||
expect(doc.example).toEqual('<p>text {{ abc }}</p>');
|
||||
});
|
||||
|
||||
it('should alias @exampleDescription to @exampleDesc', function(){
|
||||
var doc = new Doc('@exampleDesc some\n text');
|
||||
doc.ngdoc = "filter";
|
||||
doc.parse();
|
||||
expect(doc.html()).toContain('<p>some\n text');
|
||||
it('should support doc:example', function(){
|
||||
var doc = new Doc('@ngdoc overview\n@example \n' +
|
||||
'<doc:example>\n' +
|
||||
' <doc:source><escapeme></doc:source>\n' +
|
||||
' <doc:scenario><scenario></doc:scenario>\n' +
|
||||
'</doc:example>').parse();
|
||||
var html = doc.html();
|
||||
expect(html).toContain('<doc:source><escapeme></doc:source>');
|
||||
expect(html).toContain('<doc:scenario><scenario></doc:scenario>');
|
||||
expect(doc.scenarios).toEqual(['<scenario>']);
|
||||
});
|
||||
|
||||
it('should render description in related method', function(){
|
||||
var doc = new Doc('').parse();
|
||||
doc.ngdoc = 'service';
|
||||
doc.methods = [
|
||||
new Doc('@ngdoc method\n@exampleDescription MDesc\n@example MExmp').parse()];
|
||||
doc.properties = [
|
||||
new Doc('@ngdoc property\n@exampleDescription PDesc\n@example PExmp').parse()];
|
||||
expect(doc.html()).toContain('<p>MDesc</p><div ng:non-bindable="">' +
|
||||
'<pre class="brush: js; html-script: true;">MExmp</pre>');
|
||||
expect(doc.html()).toContain('<p>PDesc</p><div ng:non-bindable="">' +
|
||||
'<pre class="brush: js; html-script: true;">PExmp</pre>');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('@depricated', function() {
|
||||
|
|
|
|||
|
|
@ -74,25 +74,8 @@ DOM.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
example: function(description, source, scenario) {
|
||||
if (description || source || scenario) {
|
||||
this.h('Example', function(){
|
||||
if (description)
|
||||
this.html(description);
|
||||
if (scenario === false) {
|
||||
this.code(source);
|
||||
} else {
|
||||
this.tag('doc:example', function(){
|
||||
if (source) this.tag('doc:source', source);
|
||||
if (scenario) this.tag('doc:scenario', scenario);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
h: function(heading, content, fn){
|
||||
if (content==undefined || content && content.legth == 0) return;
|
||||
if (content==undefined || (content instanceof Array && content.length == 0)) return;
|
||||
this.headingDepth++;
|
||||
this.tag('h' + this.headingDepth, heading);
|
||||
var className = typeof heading == 'string'
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ var DOM = require('dom.js').DOM;
|
|||
var htmlEscape = require('dom.js').htmlEscape;
|
||||
var NEW_LINE = /\n\r?/;
|
||||
|
||||
exports.markdown = markdown;
|
||||
exports.trim = trim;
|
||||
exports.metadata = metadata;
|
||||
exports.scenarios = scenarios;
|
||||
|
|
@ -25,6 +24,11 @@ function Doc(text, file, line) {
|
|||
this.file = file;
|
||||
this.line = line;
|
||||
}
|
||||
this.scenarios = this.scenarios || [];
|
||||
this.requires = this.requires || [];
|
||||
this.param = this.param || [];
|
||||
this.properties = this.properties || [];
|
||||
this.methods = this.methods || [];
|
||||
}
|
||||
Doc.METADATA_IGNORE = (function(){
|
||||
var words = require('fs').readFileSync(__dirname + '/ignore.words', 'utf8');
|
||||
|
|
@ -53,16 +57,53 @@ Doc.prototype = {
|
|||
return words.join(' ');
|
||||
},
|
||||
|
||||
markdown: function (text) {
|
||||
var self = this;
|
||||
var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:)/;
|
||||
var IS_ANGULAR = /^angular\./;
|
||||
if (!text) return text;
|
||||
var parts = text.split(/(<pre>[\s\S]*?<\/pre>|<doc:example>[\s\S]*?<\/doc:example>)/),
|
||||
match;
|
||||
|
||||
parts.forEach(function(text, i){
|
||||
if (text.match(/^<pre>/)) {
|
||||
text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){
|
||||
return '<div ng:non-bindable><pre class="brush: js; html-script: true;">' +
|
||||
content.replace(/</g, '<').replace(/>/g, '>') +
|
||||
'</pre></div>';
|
||||
});
|
||||
} else if (text.match(/^<doc:example>/)) {
|
||||
text = text.replace(/(<doc:source>)([\s\S]*)(<\/doc:source>)/mi,
|
||||
function(_, before, content, after){
|
||||
return before + htmlEscape(content) + after;
|
||||
});
|
||||
text = text.replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi,
|
||||
function(_, before, content, after){
|
||||
self.scenarios.push(content);
|
||||
return before + htmlEscape(content) + after;
|
||||
});
|
||||
} else {
|
||||
text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>');
|
||||
text = text.replace(/{@link ([^\s}]+)((\s|\n)+(.+?))?\s*}/gm,
|
||||
function(_all, url, _2, _3, title){
|
||||
return '<a href="' + (url.match(IS_URL) ? '' : '#!') + url + '">'
|
||||
+ (url.match(IS_ANGULAR) ? '<code>' : '')
|
||||
+ (title || url)
|
||||
+ (url.match(IS_ANGULAR) ? '</code>' : '')
|
||||
+ '</a>';
|
||||
});
|
||||
text = new Showdown.converter().makeHtml(text);
|
||||
}
|
||||
parts[i] = text;
|
||||
});
|
||||
return parts.join('');
|
||||
},
|
||||
|
||||
parse: function(){
|
||||
var atName;
|
||||
var atText;
|
||||
var match;
|
||||
var self = this;
|
||||
this.scenarios = [];
|
||||
this.requires = [];
|
||||
this.param = [];
|
||||
this.properties = [];
|
||||
this.methods = [];
|
||||
self.text.split(NEW_LINE).forEach(function(line){
|
||||
if (match = line.match(/^\s*@(\w+)(\s+(.*))?/)) {
|
||||
// we found @name ...
|
||||
|
|
@ -82,9 +123,9 @@ Doc.prototype = {
|
|||
this.id = this.id // if we have an id just use it
|
||||
|| (((this.file||'').match(/.*\/([^\/]*)\.ngdoc/)||{})[1]) // try to extract it from file name
|
||||
|| this.name; // default to name
|
||||
this.description = markdown(this.description);
|
||||
this['this'] = markdown(this['this']);
|
||||
this.exampleDescription = markdown(this.exampleDescription || this.exampleDesc);
|
||||
this.description = this.markdown(this.description);
|
||||
this.example = this.markdown(this.example);
|
||||
this['this'] = this.markdown(this['this']);
|
||||
return this;
|
||||
|
||||
function flush(){
|
||||
|
|
@ -98,7 +139,7 @@ Doc.prototype = {
|
|||
}
|
||||
var param = {
|
||||
name: match[5] || match[4],
|
||||
description:markdown(text.replace(match[0], match[7])),
|
||||
description:self.markdown(text.replace(match[0], match[7])),
|
||||
type: match[1],
|
||||
optional: !!match[2],
|
||||
'default':match[6]
|
||||
|
|
@ -111,18 +152,10 @@ Doc.prototype = {
|
|||
}
|
||||
self.returns = {
|
||||
type: match[1],
|
||||
description: markdown(text.replace(match[0], match[2]))
|
||||
description: self.markdown(text.replace(match[0], match[2]))
|
||||
};
|
||||
} else if(atName == 'description') {
|
||||
text.replace(/<doc:scenario>([\s\S]*?)<\/doc:scenario>/gmi,
|
||||
function(_, scenario){
|
||||
self.scenarios.push(scenario);
|
||||
});
|
||||
self.description = text;
|
||||
} else if(atName == 'requires') {
|
||||
self.requires.push(text);
|
||||
} else if(atName == 'scenario') {
|
||||
self.scenarios.push(text);
|
||||
} else if(atName == 'property') {
|
||||
var match = text.match(/^({(\S+)}\s*)?(\S+)(\s+(.*))?/);
|
||||
if (!match) {
|
||||
|
|
@ -154,7 +187,7 @@ Doc.prototype = {
|
|||
throw new Error("Don't know how to format @ngdoc: " + self.ngdoc);
|
||||
}).call(self, dom);
|
||||
|
||||
dom.example(self.exampleDescription, self.example, self.scenarios[0]);
|
||||
dom.h('Example', self.example, dom.html);
|
||||
});
|
||||
|
||||
return dom.toString();
|
||||
|
|
@ -407,13 +440,13 @@ Doc.prototype = {
|
|||
dom.h(method.shortName + '(' + signature.join(', ') + ')', method, function(){
|
||||
dom.html(method.description);
|
||||
method.html_usage_parameters(dom);
|
||||
dom.example(method.exampleDescription, method.example, false);
|
||||
dom.h('Example', method.example, dom.html);
|
||||
});
|
||||
});
|
||||
dom.h('Properties', this.properties, function(property){
|
||||
dom.h(property.name, function(){
|
||||
dom.text(property.description);
|
||||
dom.example(property.exampleDescription, property.example, false);
|
||||
dom.h('Example', property.example, dom.html);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
@ -436,47 +469,6 @@ Doc.prototype = {
|
|||
//////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
function markdown (text) {
|
||||
var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:)/;
|
||||
var IS_ANGULAR = /^angular\./;
|
||||
if (!text) return text;
|
||||
var parts = text.split(/(<pre>[\s\S]*?<\/pre>|<doc:example>[\s\S]*?<\/doc:example>)/),
|
||||
match;
|
||||
|
||||
parts.forEach(function(text, i){
|
||||
if (text.match(/^<pre>/)) {
|
||||
text = text.replace(/^<pre>([\s\S]*)<\/pre>/mi, function(_, content){
|
||||
return '<div ng:non-bindable><pre class="brush: js; html-script: true;">' +
|
||||
content.replace(/</g, '<').replace(/>/g, '>') +
|
||||
'</pre></div>';
|
||||
});
|
||||
} else if (text.match(/^<doc:example>/)) {
|
||||
text = text.replace(/(<doc:source>)([\s\S]*)(<\/doc:source>)/mi,
|
||||
function(_, before, content, after){
|
||||
return before + htmlEscape(content) + after;
|
||||
});
|
||||
text = text.replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi,
|
||||
function(_, before, content, after){
|
||||
return before + htmlEscape(content) + after;
|
||||
});
|
||||
} else {
|
||||
text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>');
|
||||
text = text.replace(/{@link ([^\s}]+)((\s|\n)+(.+?))?\s*}/gm,
|
||||
function(_all, url, _2, _3, title){
|
||||
return '<a href="' + (url.match(IS_URL) ? '' : '#!') + url + '">'
|
||||
+ (url.match(IS_ANGULAR) ? '<code>' : '')
|
||||
+ (title || url)
|
||||
+ (url.match(IS_ANGULAR) ? '</code>' : '')
|
||||
+ '</a>';
|
||||
});
|
||||
text = new Showdown.converter().makeHtml(text);
|
||||
}
|
||||
parts[i] = text;
|
||||
});
|
||||
return parts.join('');
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
function scenarios(docs){
|
||||
var specs = [];
|
||||
|
|
|
|||
|
|
@ -484,14 +484,18 @@ function map(obj, iterator, context) {
|
|||
* @returns {number} The size of `obj` or `0` if `obj` is neither an object or an array.
|
||||
*
|
||||
* @example
|
||||
* Number of items in array: {{ [1,2].$size() }}<br/>
|
||||
* Number of items in object: {{ {a:1, b:2, c:3}.$size() }}<br/>
|
||||
*
|
||||
* @scenario
|
||||
it('should print correct sizes for an array and an object', function() {
|
||||
expect(binding('[1,2].$size()')).toBe('2');
|
||||
expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3');
|
||||
});
|
||||
* <doc:example>
|
||||
* <doc:source>
|
||||
* Number of items in array: {{ [1,2].$size() }}<br/>
|
||||
* Number of items in object: {{ {a:1, b:2, c:3}.$size() }}<br/>
|
||||
* </doc:source>
|
||||
* <doc:scenario>
|
||||
* it('should print correct sizes for an array and an object', function() {
|
||||
* expect(binding('[1,2].$size()')).toBe('2');
|
||||
* expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3');
|
||||
* });
|
||||
* </doc:scenario>
|
||||
* </doc:example>
|
||||
*/
|
||||
function size(obj) {
|
||||
var size = 0, key;
|
||||
|
|
@ -556,17 +560,19 @@ function isLeafNode (node) {
|
|||
* @returns {*} The copy or updated `destination` if `destination` was specified.
|
||||
*
|
||||
* @example
|
||||
Salutation: <input type="text" name="master.salutation" value="Hello" /><br/>
|
||||
Name: <input type="text" name="master.name" value="world"/><br/>
|
||||
<button ng:click="form = master.$copy()">copy</button>
|
||||
<hr/>
|
||||
* <doc:example>
|
||||
* <doc:source>
|
||||
Salutation: <input type="text" name="master.salutation" value="Hello" /><br/>
|
||||
Name: <input type="text" name="master.name" value="world"/><br/>
|
||||
<button ng:click="form = master.$copy()">copy</button>
|
||||
<hr/>
|
||||
|
||||
The master object is <span ng:hide="master.$equals(form)">NOT</span> equal to the form object.
|
||||
The master object is <span ng:hide="master.$equals(form)">NOT</span> equal to the form object.
|
||||
|
||||
<pre>master={{master}}</pre>
|
||||
<pre>form={{form}}</pre>
|
||||
|
||||
* @scenario
|
||||
<pre>master={{master}}</pre>
|
||||
<pre>form={{form}}</pre>
|
||||
* </doc:source>
|
||||
* <doc:scenario>
|
||||
it('should print that initialy the form object is NOT equal to master', function() {
|
||||
expect(element('.doc-example input[name=master.salutation]').val()).toBe('Hello');
|
||||
expect(element('.doc-example input[name=master.name]').val()).toBe('world');
|
||||
|
|
@ -577,6 +583,8 @@ function isLeafNode (node) {
|
|||
element('.doc-example button').click();
|
||||
expect(element('.doc-example span').css('display')).toBe('none');
|
||||
});
|
||||
* </doc:scenario>
|
||||
* </doc:example>
|
||||
*/
|
||||
function copy(source, destination){
|
||||
if (!destination) {
|
||||
|
|
@ -633,27 +641,31 @@ function copy(source, destination){
|
|||
* @returns {boolean} True if arguments are equal.
|
||||
*
|
||||
* @example
|
||||
Salutation: <input type="text" name="greeting.salutation" value="Hello" /><br/>
|
||||
Name: <input type="text" name="greeting.name" value="world"/><br/>
|
||||
<hr/>
|
||||
* <doc:example>
|
||||
* <doc:source>
|
||||
Salutation: <input type="text" name="greeting.salutation" value="Hello" /><br/>
|
||||
Name: <input type="text" name="greeting.name" value="world"/><br/>
|
||||
<hr/>
|
||||
|
||||
The <code>greeting</code> object is
|
||||
<span ng:hide="greeting.$equals({salutation:'Hello', name:'world'})">NOT</span> equal to
|
||||
<code>{salutation:'Hello', name:'world'}</code>.
|
||||
The <code>greeting</code> object is
|
||||
<span ng:hide="greeting.$equals({salutation:'Hello', name:'world'})">NOT</span> equal to
|
||||
<code>{salutation:'Hello', name:'world'}</code>.
|
||||
|
||||
<pre>greeting={{greeting}}</pre>
|
||||
<pre>greeting={{greeting}}</pre>
|
||||
* </doc:source>
|
||||
* <doc:scenario>
|
||||
it('should print that initialy greeting is equal to the hardcoded value object', function() {
|
||||
expect(element('.doc-example input[name=greeting.salutation]').val()).toBe('Hello');
|
||||
expect(element('.doc-example input[name=greeting.name]').val()).toBe('world');
|
||||
expect(element('.doc-example span').css('display')).toBe('none');
|
||||
});
|
||||
|
||||
@scenario
|
||||
it('should print that initialy greeting is equal to the hardcoded value object', function() {
|
||||
expect(element('.doc-example input[name=greeting.salutation]').val()).toBe('Hello');
|
||||
expect(element('.doc-example input[name=greeting.name]').val()).toBe('world');
|
||||
expect(element('.doc-example span').css('display')).toBe('none');
|
||||
});
|
||||
|
||||
it('should say that the objects are not equal when the form is modified', function() {
|
||||
input('greeting.name').enter('kitty');
|
||||
expect(element('.doc-example span').css('display')).toBe('inline');
|
||||
});
|
||||
it('should say that the objects are not equal when the form is modified', function() {
|
||||
input('greeting.name').enter('kitty');
|
||||
expect(element('.doc-example span').css('display')).toBe('inline');
|
||||
});
|
||||
* </doc:scenario>
|
||||
* </doc:example>
|
||||
*/
|
||||
function equals(o1, o2) {
|
||||
if (o1 == o2) return true;
|
||||
|
|
|
|||
|
|
@ -139,40 +139,44 @@ Compiler.prototype = {
|
|||
* @element ANY
|
||||
* @param {integer|string=} [priority=0] priority integer, or FIRST, LAST constant
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* try changing the invoice and see that the Total will lag in evaluation
|
||||
* @example
|
||||
<div>TOTAL: without ng:eval-order {{ items.$sum('total') | currency }}</div>
|
||||
<div ng:eval-order='LAST'>TOTAL: with ng:eval-order {{ items.$sum('total') | currency }}</div>
|
||||
<table ng:init="items=[{qty:1, cost:9.99, desc:'gadget'}]">
|
||||
<tr>
|
||||
<td>QTY</td>
|
||||
<td>Description</td>
|
||||
<td>Cost</td>
|
||||
<td>Total</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr ng:repeat="item in items">
|
||||
<td><input name="item.qty"/></td>
|
||||
<td><input name="item.desc"/></td>
|
||||
<td><input name="item.cost"/></td>
|
||||
<td>{{item.total = item.qty * item.cost | currency}}</td>
|
||||
<td><a href="" ng:click="items.$remove(item)">X</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"><a href="" ng:click="items.$add()">add</a></td>
|
||||
<td>{{ items.$sum('total') | currency }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:format', function(){
|
||||
expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99');
|
||||
expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$9.99');
|
||||
input('item.qty').enter('2');
|
||||
expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99');
|
||||
expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$19.98');
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div>TOTAL: without ng:eval-order {{ items.$sum('total') | currency }}</div>
|
||||
<div ng:eval-order='LAST'>TOTAL: with ng:eval-order {{ items.$sum('total') | currency }}</div>
|
||||
<table ng:init="items=[{qty:1, cost:9.99, desc:'gadget'}]">
|
||||
<tr>
|
||||
<td>QTY</td>
|
||||
<td>Description</td>
|
||||
<td>Cost</td>
|
||||
<td>Total</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr ng:repeat="item in items">
|
||||
<td><input name="item.qty"/></td>
|
||||
<td><input name="item.desc"/></td>
|
||||
<td><input name="item.cost"/></td>
|
||||
<td>{{item.total = item.qty * item.cost | currency}}</td>
|
||||
<td><a href="" ng:click="items.$remove(item)">X</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"><a href="" ng:click="items.$add()">add</a></td>
|
||||
<td>{{ items.$sum('total') | currency }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:format', function(){
|
||||
expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99');
|
||||
expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$9.99');
|
||||
input('item.qty').enter('2');
|
||||
expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99');
|
||||
expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$19.98');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
|
||||
templatize: function(element, elementIndex, priority){
|
||||
|
|
|
|||
46
src/Scope.js
46
src/Scope.js
|
|
@ -202,7 +202,7 @@ function errorHandlerFor(element, error) {
|
|||
* @returns {Object} Newly created scope.
|
||||
*
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* This example demonstrates scope inheritance and property overriding.
|
||||
*
|
||||
* In this example, the root scope encompasses the whole HTML DOM tree. This scope has `salutation`,
|
||||
|
|
@ -216,27 +216,29 @@ function errorHandlerFor(element, error) {
|
|||
* - The child scope inherits the salutation property from the root scope.
|
||||
* - The $index property does not leak from the child scope to the root scope.
|
||||
*
|
||||
* @example
|
||||
<ul ng:init="salutation='Hello'; name='Misko'; names=['World', 'Earth']">
|
||||
<li ng:repeat="name in names">
|
||||
{{$index}}: {{salutation}} {{name}}!
|
||||
</li>
|
||||
</ul>
|
||||
<pre>
|
||||
$index={{$index}}
|
||||
salutation={{salutation}}
|
||||
name={{name}}</pre>
|
||||
|
||||
@scenario
|
||||
it('should inherit the salutation property and override the name property', function() {
|
||||
expect(using('.doc-example-live').repeater('li').row(0)).
|
||||
toEqual(['0', 'Hello', 'World']);
|
||||
expect(using('.doc-example-live').repeater('li').row(1)).
|
||||
toEqual(['1', 'Hello', 'Earth']);
|
||||
expect(using('.doc-example-live').element('pre').text()).
|
||||
toBe('$index=\nsalutation=Hello\nname=Misko');
|
||||
});
|
||||
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<ul ng:init="salutation='Hello'; name='Misko'; names=['World', 'Earth']">
|
||||
<li ng:repeat="name in names">
|
||||
{{$index}}: {{salutation}} {{name}}!
|
||||
</li>
|
||||
</ul>
|
||||
<pre>
|
||||
$index={{$index}}
|
||||
salutation={{salutation}}
|
||||
name={{name}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should inherit the salutation property and override the name property', function() {
|
||||
expect(using('.doc-example-live').repeater('li').row(0)).
|
||||
toEqual(['0', 'Hello', 'World']);
|
||||
expect(using('.doc-example-live').repeater('li').row(1)).
|
||||
toEqual(['1', 'Hello', 'Earth']);
|
||||
expect(using('.doc-example-live').element('pre').text()).
|
||||
toBe('$index=\nsalutation=Hello\nname=Misko');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
function createScope(parent, providers, instanceCache) {
|
||||
function Parent(){}
|
||||
|
|
|
|||
28
src/angular-mocks.js
vendored
28
src/angular-mocks.js
vendored
|
|
@ -239,10 +239,10 @@ angular.service('$exceptionHandler', function(e) {
|
|||
*/
|
||||
angular.service('$log', function() {
|
||||
var $log = {
|
||||
log: function(){ $log.logs.push(arguments) },
|
||||
warn: function(){ $log.logs.push(arguments) },
|
||||
info: function(){ $log.logs.push(arguments) },
|
||||
error: function(){ $log.logs.push(arguments) }
|
||||
log: function(){ $log.logs.push(arguments); },
|
||||
warn: function(){ $log.logs.push(arguments); },
|
||||
info: function(){ $log.logs.push(arguments); },
|
||||
error: function(){ $log.logs.push(arguments); }
|
||||
};
|
||||
|
||||
$log.log.logs = [];
|
||||
|
|
@ -265,15 +265,6 @@ angular.service('$log', function() {
|
|||
* @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
|
||||
*
|
||||
* @example
|
||||
* var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
|
||||
* newYearInBratislava.getTimezoneOffset() => -60;
|
||||
* newYearInBratislava.getFullYear() => 2010;
|
||||
* newYearInBratislava.getMonth() => 0;
|
||||
* newYearInBratislava.getDate() => 1;
|
||||
* newYearInBratislava.getHours() => 0;
|
||||
* newYearInBratislava.getMinutes() => 0;
|
||||
*
|
||||
*
|
||||
* !!!! WARNING !!!!!
|
||||
* This is not a complete Date object so only methods that were implemented can be called safely.
|
||||
* To make matters worse, TzDate instances inherit stuff from Date via a prototype.
|
||||
|
|
@ -281,6 +272,17 @@ angular.service('$log', function() {
|
|||
* We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
|
||||
* incomplete we might be missing some non-standard methods. This can result in errors like:
|
||||
* "Date.prototype.foo called on incompatible Object".
|
||||
*
|
||||
* <pre>
|
||||
* var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
|
||||
* newYearInBratislava.getTimezoneOffset() => -60;
|
||||
* newYearInBratislava.getFullYear() => 2010;
|
||||
* newYearInBratislava.getMonth() => 0;
|
||||
* newYearInBratislava.getDate() => 1;
|
||||
* newYearInBratislava.getHours() => 0;
|
||||
* newYearInBratislava.getMinutes() => 0;
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
function TzDate(offset, timestamp) {
|
||||
if (angular.isString(timestamp)) {
|
||||
|
|
|
|||
490
src/apis.js
490
src/apis.js
|
|
@ -79,22 +79,26 @@ var angularArray = {
|
|||
* @returns {number} The position of the element in `array`. The position is 0-based. `-1` is returned if the value can't be found.
|
||||
*
|
||||
* @example
|
||||
<div ng:init="books = ['Moby Dick', 'Great Gatsby', 'Romeo and Juliet']"></div>
|
||||
<input name='bookName' value='Romeo and Juliet'> <br>
|
||||
Index of '{{bookName}}' in the list {{books}} is <em>{{books.$indexOf(bookName)}}</em>.
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="books = ['Moby Dick', 'Great Gatsby', 'Romeo and Juliet']"></div>
|
||||
<input name='bookName' value='Romeo and Juliet'> <br>
|
||||
Index of '{{bookName}}' in the list {{books}} is <em>{{books.$indexOf(bookName)}}</em>.
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should correctly calculate the initial index', function() {
|
||||
expect(binding('books.$indexOf(bookName)')).toBe('2');
|
||||
});
|
||||
|
||||
@scenario
|
||||
it('should correctly calculate the initial index', function() {
|
||||
expect(binding('books.$indexOf(bookName)')).toBe('2');
|
||||
});
|
||||
it('should recalculate', function() {
|
||||
input('bookName').enter('foo');
|
||||
expect(binding('books.$indexOf(bookName)')).toBe('-1');
|
||||
|
||||
it('should recalculate', function() {
|
||||
input('bookName').enter('foo');
|
||||
expect(binding('books.$indexOf(bookName)')).toBe('-1');
|
||||
|
||||
input('bookName').enter('Moby Dick');
|
||||
expect(binding('books.$indexOf(bookName)')).toBe('0');
|
||||
});
|
||||
input('bookName').enter('Moby Dick');
|
||||
expect(binding('books.$indexOf(bookName)')).toBe('0');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
'indexOf': indexOf,
|
||||
|
||||
|
|
@ -117,42 +121,46 @@ var angularArray = {
|
|||
* @returns {number} Sum of items in the array.
|
||||
*
|
||||
* @example
|
||||
<table ng:init="invoice= {items:[{qty:10, description:'gadget', cost:9.95}]}">
|
||||
<tr><th>Qty</th><th>Description</th><th>Cost</th><th>Total</th><th></th></tr>
|
||||
<tr ng:repeat="item in invoice.items">
|
||||
<td><input name="item.qty" value="1" size="4" ng:required ng:validate="integer"></td>
|
||||
<td><input name="item.description"></td>
|
||||
<td><input name="item.cost" value="0.00" ng:required ng:validate="number" size="6"></td>
|
||||
<td>{{item.qty * item.cost | currency}}</td>
|
||||
<td>[<a href ng:click="invoice.items.$remove(item)">X</a>]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href ng:click="invoice.items.$add()">add item</a></td>
|
||||
<td></td>
|
||||
<td>Total:</td>
|
||||
<td>{{invoice.items.$sum('qty*cost') | currency}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<table ng:init="invoice= {items:[{qty:10, description:'gadget', cost:9.95}]}">
|
||||
<tr><th>Qty</th><th>Description</th><th>Cost</th><th>Total</th><th></th></tr>
|
||||
<tr ng:repeat="item in invoice.items">
|
||||
<td><input name="item.qty" value="1" size="4" ng:required ng:validate="integer"></td>
|
||||
<td><input name="item.description"></td>
|
||||
<td><input name="item.cost" value="0.00" ng:required ng:validate="number" size="6"></td>
|
||||
<td>{{item.qty * item.cost | currency}}</td>
|
||||
<td>[<a href ng:click="invoice.items.$remove(item)">X</a>]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href ng:click="invoice.items.$add()">add item</a></td>
|
||||
<td></td>
|
||||
<td>Total:</td>
|
||||
<td>{{invoice.items.$sum('qty*cost') | currency}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
//TODO: these specs are lame because I had to work around issues #164 and #167
|
||||
it('should initialize and calculate the totals', function() {
|
||||
expect(repeater('.doc-example-live table tr', 'item in invoice.items').count()).toBe(3);
|
||||
expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(1)).
|
||||
toEqual(['$99.50']);
|
||||
expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50');
|
||||
expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50');
|
||||
});
|
||||
|
||||
@scenario
|
||||
//TODO: these specs are lame because I had to work around issues #164 and #167
|
||||
it('should initialize and calculate the totals', function() {
|
||||
expect(repeater('.doc-example-live table tr', 'item in invoice.items').count()).toBe(3);
|
||||
expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(1)).
|
||||
toEqual(['$99.50']);
|
||||
expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50');
|
||||
expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50');
|
||||
});
|
||||
it('should add an entry and recalculate', function() {
|
||||
element('.doc-example a:contains("add item")').click();
|
||||
using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20');
|
||||
using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100');
|
||||
|
||||
it('should add an entry and recalculate', function() {
|
||||
element('.doc-example a:contains("add item")').click();
|
||||
using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20');
|
||||
using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100');
|
||||
|
||||
expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(2)).
|
||||
toEqual(['$2,000.00']);
|
||||
expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50');
|
||||
});
|
||||
expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(2)).
|
||||
toEqual(['$2,000.00']);
|
||||
expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
'sum':function(array, expression) {
|
||||
var fn = angular['Function']['compile'](expression);
|
||||
|
|
@ -185,33 +193,37 @@ var angularArray = {
|
|||
* @returns {*} The removed element.
|
||||
*
|
||||
* @example
|
||||
<ul ng:init="tasks=['Learn Angular', 'Read Documentation',
|
||||
'Check out demos', 'Build cool applications']">
|
||||
<li ng:repeat="task in tasks">
|
||||
{{task}} [<a href="" ng:click="tasks.$remove(task)">X</a>]
|
||||
</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
tasks = {{tasks}}
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<ul ng:init="tasks=['Learn Angular', 'Read Documentation',
|
||||
'Check out demos', 'Build cool applications']">
|
||||
<li ng:repeat="task in tasks">
|
||||
{{task}} [<a href="" ng:click="tasks.$remove(task)">X</a>]
|
||||
</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
tasks = {{tasks}}
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should initialize the task list with for tasks', function() {
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(4);
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').column('task')).
|
||||
toEqual(['Learn Angular', 'Read Documentation', 'Check out demos',
|
||||
'Build cool applications']);
|
||||
});
|
||||
|
||||
@scenario
|
||||
it('should initialize the task list with for tasks', function() {
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(4);
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').column('task')).
|
||||
toEqual(['Learn Angular', 'Read Documentation', 'Check out demos',
|
||||
'Build cool applications']);
|
||||
});
|
||||
it('should initialize the task list with for tasks', function() {
|
||||
element('.doc-example ul li a:contains("X"):first').click();
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(3);
|
||||
|
||||
it('should initialize the task list with for tasks', function() {
|
||||
element('.doc-example ul li a:contains("X"):first').click();
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(3);
|
||||
element('.doc-example ul li a:contains("X"):last').click();
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(2);
|
||||
|
||||
element('.doc-example ul li a:contains("X"):last').click();
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(2);
|
||||
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').column('task')).
|
||||
toEqual(['Read Documentation', 'Check out demos']);
|
||||
});
|
||||
expect(repeater('.doc-example ul li', 'task in tasks').column('task')).
|
||||
toEqual(['Read Documentation', 'Check out demos']);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
'remove':function(array, value) {
|
||||
var index = indexOf(array, value);
|
||||
|
|
@ -254,48 +266,52 @@ var angularArray = {
|
|||
* the predicate returned true for.
|
||||
*
|
||||
* @example
|
||||
<div ng:init="friends = [{name:'John', phone:'555-1276'},
|
||||
{name:'Mary', phone:'800-BIG-MARY'},
|
||||
{name:'Mike', phone:'555-4321'},
|
||||
{name:'Adam', phone:'555-5678'},
|
||||
{name:'Julie', phone:'555-8765'}]"></div>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="friends = [{name:'John', phone:'555-1276'},
|
||||
{name:'Mary', phone:'800-BIG-MARY'},
|
||||
{name:'Mike', phone:'555-4321'},
|
||||
{name:'Adam', phone:'555-5678'},
|
||||
{name:'Julie', phone:'555-8765'}]"></div>
|
||||
|
||||
Search: <input name="searchText"/>
|
||||
<table id="searchTextResults">
|
||||
<tr><th>Name</th><th>Phone</th><tr>
|
||||
<tr ng:repeat="friend in friends.$filter(searchText)">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<tr>
|
||||
</table>
|
||||
<hr>
|
||||
Any: <input name="search.$"/> <br>
|
||||
Name only <input name="search.name"/><br>
|
||||
Phone only <input name="search.phone"/><br>
|
||||
<table id="searchObjResults">
|
||||
<tr><th>Name</th><th>Phone</th><tr>
|
||||
<tr ng:repeat="friend in friends.$filter(search)">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<tr>
|
||||
</table>
|
||||
Search: <input name="searchText"/>
|
||||
<table id="searchTextResults">
|
||||
<tr><th>Name</th><th>Phone</th><tr>
|
||||
<tr ng:repeat="friend in friends.$filter(searchText)">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<tr>
|
||||
</table>
|
||||
<hr>
|
||||
Any: <input name="search.$"/> <br>
|
||||
Name only <input name="search.name"/><br>
|
||||
Phone only <input name="search.phone"/><br>
|
||||
<table id="searchObjResults">
|
||||
<tr><th>Name</th><th>Phone</th><tr>
|
||||
<tr ng:repeat="friend in friends.$filter(search)">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<tr>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should search across all fields when filtering with a string', function() {
|
||||
input('searchText').enter('m');
|
||||
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
||||
toEqual(['Mary', 'Mike', 'Adam']);
|
||||
|
||||
@scenario
|
||||
it('should search across all fields when filtering with a string', function() {
|
||||
input('searchText').enter('m');
|
||||
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
||||
toEqual(['Mary', 'Mike', 'Adam']);
|
||||
input('searchText').enter('76');
|
||||
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
||||
toEqual(['John', 'Julie']);
|
||||
});
|
||||
|
||||
input('searchText').enter('76');
|
||||
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
||||
toEqual(['John', 'Julie']);
|
||||
});
|
||||
|
||||
it('should search in specific fields when filtering with a predicate object', function() {
|
||||
input('search.$').enter('i');
|
||||
expect(repeater('#searchObjResults tr', 'friend in friends').column('name')).
|
||||
toEqual(['Mary', 'Mike', 'Julie']);
|
||||
});
|
||||
it('should search in specific fields when filtering with a predicate object', function() {
|
||||
input('search.$').enter('i');
|
||||
expect(repeater('#searchObjResults tr', 'friend in friends').column('name')).
|
||||
toEqual(['Mary', 'Mike', 'Julie']);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
'filter':function(array, expression) {
|
||||
var predicates = [];
|
||||
|
|
@ -398,53 +414,55 @@ var angularArray = {
|
|||
*
|
||||
* @TODO simplify the example.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* This example shows how an initially empty array can be filled with objects created from user
|
||||
* input via the `$add` method.
|
||||
*
|
||||
* @example
|
||||
[<a href="" ng:click="people.$add()">add empty</a>]
|
||||
[<a href="" ng:click="people.$add({name:'John', sex:'male'})">add 'John'</a>]
|
||||
[<a href="" ng:click="people.$add({name:'Mary', sex:'female'})">add 'Mary'</a>]
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
[<a href="" ng:click="people.$add()">add empty</a>]
|
||||
[<a href="" ng:click="people.$add({name:'John', sex:'male'})">add 'John'</a>]
|
||||
[<a href="" ng:click="people.$add({name:'Mary', sex:'female'})">add 'Mary'</a>]
|
||||
|
||||
<ul ng:init="people=[]">
|
||||
<li ng:repeat="person in people">
|
||||
<input name="person.name">
|
||||
<select name="person.sex">
|
||||
<option value="">--chose one--</option>
|
||||
<option>male</option>
|
||||
<option>female</option>
|
||||
</select>
|
||||
[<a href="" ng:click="people.$remove(person)">X</a>]
|
||||
</li>
|
||||
</ul>
|
||||
<pre>people = {{people}}</pre>
|
||||
<ul ng:init="people=[]">
|
||||
<li ng:repeat="person in people">
|
||||
<input name="person.name">
|
||||
<select name="person.sex">
|
||||
<option value="">--chose one--</option>
|
||||
<option>male</option>
|
||||
<option>female</option>
|
||||
</select>
|
||||
[<a href="" ng:click="people.$remove(person)">X</a>]
|
||||
</li>
|
||||
</ul>
|
||||
<pre>people = {{people}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
beforeEach(function() {
|
||||
expect(binding('people')).toBe('people = []');
|
||||
});
|
||||
|
||||
@scenario
|
||||
beforeEach(function() {
|
||||
expect(binding('people')).toBe('people = []');
|
||||
});
|
||||
it('should create an empty record when "add empty" is clicked', function() {
|
||||
element('.doc-example a:contains("add empty")').click();
|
||||
expect(binding('people')).toBe('people = [{\n "name":"",\n "sex":null}]');
|
||||
});
|
||||
|
||||
it('should create an empty record when "add empty" is clicked', function() {
|
||||
element('.doc-example a:contains("add empty")').click();
|
||||
expect(binding('people')).toBe('people = [{\n "name":"",\n "sex":null}]');
|
||||
});
|
||||
it('should create a "John" record when "add \'John\'" is clicked', function() {
|
||||
element('.doc-example a:contains("add \'John\'")').click();
|
||||
expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]');
|
||||
});
|
||||
|
||||
it('should create a "John" record when "add \'John\'" is clicked', function() {
|
||||
element('.doc-example a:contains("add \'John\'")').click();
|
||||
expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]');
|
||||
});
|
||||
it('should create a "Mary" record when "add \'Mary\'" is clicked', function() {
|
||||
element('.doc-example a:contains("add \'Mary\'")').click();
|
||||
expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]');
|
||||
});
|
||||
|
||||
it('should create a "Mary" record when "add \'Mary\'" is clicked', function() {
|
||||
element('.doc-example a:contains("add \'Mary\'")').click();
|
||||
expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]');
|
||||
});
|
||||
|
||||
it('should delete a record when "X" is clicked', function() {
|
||||
element('.doc-example a:contains("add empty")').click();
|
||||
element('.doc-example li a:contains("X"):first').click();
|
||||
expect(binding('people')).toBe('people = []');
|
||||
});
|
||||
it('should delete a record when "X" is clicked', function() {
|
||||
element('.doc-example a:contains("add empty")').click();
|
||||
element('.doc-example li a:contains("X"):first').click();
|
||||
expect(binding('people')).toBe('people = []');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
'add':function(array, value) {
|
||||
array.push(isUndefined(value)? {} : value);
|
||||
|
|
@ -471,29 +489,33 @@ var angularArray = {
|
|||
* @returns {number} Number of elements in the array (for which the condition evaluates to true).
|
||||
*
|
||||
* @example
|
||||
<pre ng:init="items = [{name:'knife', points:1},
|
||||
{name:'fork', points:3},
|
||||
{name:'spoon', points:1}]"></pre>
|
||||
<ul>
|
||||
<li ng:repeat="item in items">
|
||||
{{item.name}}: points=
|
||||
<input type="text" name="item.points"/> <!-- id="item{{$index}} -->
|
||||
</li>
|
||||
</ul>
|
||||
<p>Number of items which have one point: <em>{{ items.$count('points==1') }}</em></p>
|
||||
<p>Number of items which have more than one point: <em>{{items.$count('points>1')}}</em></p>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<pre ng:init="items = [{name:'knife', points:1},
|
||||
{name:'fork', points:3},
|
||||
{name:'spoon', points:1}]"></pre>
|
||||
<ul>
|
||||
<li ng:repeat="item in items">
|
||||
{{item.name}}: points=
|
||||
<input type="text" name="item.points"/> <!-- id="item{{$index}} -->
|
||||
</li>
|
||||
</ul>
|
||||
<p>Number of items which have one point: <em>{{ items.$count('points==1') }}</em></p>
|
||||
<p>Number of items which have more than one point: <em>{{items.$count('points>1')}}</em></p>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should calculate counts', function() {
|
||||
expect(binding('items.$count(\'points==1\')')).toEqual(2);
|
||||
expect(binding('items.$count(\'points>1\')')).toEqual(1);
|
||||
});
|
||||
|
||||
@scenario
|
||||
it('should calculate counts', function() {
|
||||
expect(binding('items.$count(\'points==1\')')).toEqual(2);
|
||||
expect(binding('items.$count(\'points>1\')')).toEqual(1);
|
||||
});
|
||||
|
||||
it('should recalculate when updated', function() {
|
||||
using('.doc-example li:first-child').input('item.points').enter('23');
|
||||
expect(binding('items.$count(\'points==1\')')).toEqual(1);
|
||||
expect(binding('items.$count(\'points>1\')')).toEqual(2);
|
||||
});
|
||||
it('should recalculate when updated', function() {
|
||||
using('.doc-example li:first-child').input('item.points').enter('23');
|
||||
expect(binding('items.$count(\'points==1\')')).toEqual(1);
|
||||
expect(binding('items.$count(\'points>1\')')).toEqual(2);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
'count':function(array, condition) {
|
||||
if (!condition) return array.length;
|
||||
|
|
@ -535,52 +557,56 @@ var angularArray = {
|
|||
* @returns {Array} Sorted copy of the source array.
|
||||
*
|
||||
* @example
|
||||
<div ng:init="friends = [{name:'John', phone:'555-1212', age:10},
|
||||
{name:'Mary', phone:'555-9876', age:19},
|
||||
{name:'Mike', phone:'555-4321', age:21},
|
||||
{name:'Adam', phone:'555-5678', age:35},
|
||||
{name:'Julie', phone:'555-8765', age:29}]"></div>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="friends = [{name:'John', phone:'555-1212', age:10},
|
||||
{name:'Mary', phone:'555-9876', age:19},
|
||||
{name:'Mike', phone:'555-4321', age:21},
|
||||
{name:'Adam', phone:'555-5678', age:35},
|
||||
{name:'Julie', phone:'555-8765', age:29}]"></div>
|
||||
|
||||
<pre>Sorting predicate = {{predicate}}</pre>
|
||||
<hr/>
|
||||
<table ng:init="predicate='-age'">
|
||||
<tr>
|
||||
<th><a href="" ng:click="predicate = 'name'">Name</a>
|
||||
(<a href ng:click="predicate = '-name'">^</a>)</th>
|
||||
<th><a href="" ng:click="predicate = 'phone'">Phone</a>
|
||||
(<a href ng:click="predicate = '-phone'">^</a>)</th>
|
||||
<th><a href="" ng:click="predicate = 'age'">Age</a>
|
||||
(<a href ng:click="predicate = '-age'">^</a>)</th>
|
||||
<tr>
|
||||
<tr ng:repeat="friend in friends.$orderBy(predicate)">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<td>{{friend.age}}</td>
|
||||
<tr>
|
||||
</table>
|
||||
<pre>Sorting predicate = {{predicate}}</pre>
|
||||
<hr/>
|
||||
<table ng:init="predicate='-age'">
|
||||
<tr>
|
||||
<th><a href="" ng:click="predicate = 'name'">Name</a>
|
||||
(<a href ng:click="predicate = '-name'">^</a>)</th>
|
||||
<th><a href="" ng:click="predicate = 'phone'">Phone</a>
|
||||
(<a href ng:click="predicate = '-phone'">^</a>)</th>
|
||||
<th><a href="" ng:click="predicate = 'age'">Age</a>
|
||||
(<a href ng:click="predicate = '-age'">^</a>)</th>
|
||||
<tr>
|
||||
<tr ng:repeat="friend in friends.$orderBy(predicate)">
|
||||
<td>{{friend.name}}</td>
|
||||
<td>{{friend.phone}}</td>
|
||||
<td>{{friend.age}}</td>
|
||||
<tr>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should be reverse ordered by aged', function() {
|
||||
expect(binding('predicate')).toBe('Sorting predicate = -age');
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.age')).
|
||||
toEqual(['35', '29', '21', '19', '10']);
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
|
||||
toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);
|
||||
});
|
||||
|
||||
@scenario
|
||||
it('should be reverse ordered by aged', function() {
|
||||
expect(binding('predicate')).toBe('Sorting predicate = -age');
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.age')).
|
||||
toEqual(['35', '29', '21', '19', '10']);
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
|
||||
toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);
|
||||
});
|
||||
it('should reorder the table when user selects different predicate', function() {
|
||||
element('.doc-example a:contains("Name")').click();
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
|
||||
toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.age')).
|
||||
toEqual(['35', '10', '29', '19', '21']);
|
||||
|
||||
it('should reorder the table when user selects different predicate', function() {
|
||||
element('.doc-example a:contains("Name")').click();
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
|
||||
toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.age')).
|
||||
toEqual(['35', '10', '29', '19', '21']);
|
||||
|
||||
element('.doc-example a:contains("Phone")+a:contains("^")').click();
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')).
|
||||
toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
|
||||
toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);
|
||||
});
|
||||
element('.doc-example a:contains("Phone")+a:contains("^")').click();
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')).
|
||||
toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);
|
||||
expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
|
||||
toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
//TODO: WTH is descend param for and how/when it should be used, how is it affected by +/- in
|
||||
// predicate? the code below is impossible to read and specs are not very good.
|
||||
|
|
@ -648,21 +674,25 @@ var angularArray = {
|
|||
* @returns {Array} A new sub-array of length `limit`.
|
||||
*
|
||||
* @example
|
||||
<div ng:init="numbers = [1,2,3,4,5,6,7,8,9]">
|
||||
Limit [1,2,3,4,5,6,7,8,9] to: <input name="limit" value="3"/>
|
||||
<p>Output: {{ numbers.$limitTo(limit) | json }}</p>
|
||||
</div>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="numbers = [1,2,3,4,5,6,7,8,9]">
|
||||
Limit [1,2,3,4,5,6,7,8,9] to: <input name="limit" value="3"/>
|
||||
<p>Output: {{ numbers.$limitTo(limit) | json }}</p>
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should limit the numer array to first three items', function() {
|
||||
expect(element('.doc-example input[name=limit]').val()).toBe('3');
|
||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]');
|
||||
});
|
||||
|
||||
* @scenario
|
||||
it('should limit the numer array to first three items', function() {
|
||||
expect(element('.doc-example input[name=limit]').val()).toBe('3');
|
||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]');
|
||||
});
|
||||
|
||||
it('should update the output when -3 is entered', function() {
|
||||
input('limit').enter(-3);
|
||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]');
|
||||
});
|
||||
it('should update the output when -3 is entered', function() {
|
||||
input('limit').enter(-3);
|
||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
limitTo: function(array, limit) {
|
||||
limit = parseInt(limit, 10);
|
||||
|
|
|
|||
|
|
@ -4,22 +4,26 @@
|
|||
* @name angular.directive.ng:init
|
||||
*
|
||||
* @description
|
||||
* `ng:init` attribute allows the for initialization tasks to be executed
|
||||
* `ng:init` attribute allows the for initialization tasks to be executed
|
||||
* before the template enters execution mode during bootstrap.
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="greeting='Hello'; person='World'">
|
||||
{{greeting}} {{person}}!
|
||||
</div>
|
||||
*
|
||||
* @scenario
|
||||
it('should check greeting', function(){
|
||||
expect(binding('greeting')).toBe('Hello');
|
||||
expect(binding('person')).toBe('World');
|
||||
});
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check greeting', function(){
|
||||
expect(binding('greeting')).toBe('Hello');
|
||||
expect(binding('person')).toBe('World');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:init", function(expression){
|
||||
return function(element){
|
||||
|
|
@ -33,66 +37,70 @@ angularDirective("ng:init", function(expression){
|
|||
* @name angular.directive.ng:controller
|
||||
*
|
||||
* @description
|
||||
* To support the Model-View-Controller design pattern, it is possible
|
||||
* to assign behavior to a scope through `ng:controller`. The scope is
|
||||
* the MVC model. The HTML (with data bindings) is the MVC view.
|
||||
* To support the Model-View-Controller design pattern, it is possible
|
||||
* to assign behavior to a scope through `ng:controller`. The scope is
|
||||
* the MVC model. The HTML (with data bindings) is the MVC view.
|
||||
* The `ng:controller` directive specifies the MVC controller class
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @example
|
||||
<script type="text/javascript">
|
||||
function SettingsController() {
|
||||
this.name = "John Smith";
|
||||
this.contacts = [
|
||||
{type:'phone', value:'408 555 1212'},
|
||||
{type:'email', value:'john.smith@example.org'} ];
|
||||
}
|
||||
SettingsController.prototype = {
|
||||
greet: function(){
|
||||
alert(this.name);
|
||||
},
|
||||
addContact: function(){
|
||||
this.contacts.push({type:'email', value:'yourname@example.org'});
|
||||
},
|
||||
removeContact: function(contactToRemove) {
|
||||
angular.Array.remove(this.contacts, contactToRemove);
|
||||
},
|
||||
clearContact: function(contact) {
|
||||
contact.type = 'phone';
|
||||
contact.value = '';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<div ng:controller="SettingsController">
|
||||
Name: <input type="text" name="name"/>
|
||||
[ <a href="" ng:click="greet()">greet</a> ]<br/>
|
||||
Contact:
|
||||
<ul>
|
||||
<li ng:repeat="contact in contacts">
|
||||
<select name="contact.type">
|
||||
<option>phone</option>
|
||||
<option>email</option>
|
||||
</select>
|
||||
<input type="text" name="contact.value"/>
|
||||
[ <a href="" ng:click="clearContact(contact)">clear</a>
|
||||
| <a href="" ng:click="removeContact(contact)">X</a> ]
|
||||
</li>
|
||||
<li>[ <a href="" ng:click="addContact()">add</a> ]</li>
|
||||
</ul>
|
||||
</div>
|
||||
*
|
||||
* @scenario
|
||||
it('should check controller', function(){
|
||||
expect(element('.doc-example-live div>:input').val()).toBe('John Smith');
|
||||
expect(element('.doc-example-live li[ng\\:repeat-index="0"] input').val()).toBe('408 555 1212');
|
||||
expect(element('.doc-example-live li[ng\\:repeat-index="1"] input').val()).toBe('john.smith@example.org');
|
||||
element('.doc-example-live li:first a:contains("clear")').click();
|
||||
expect(element('.doc-example-live li:first input').val()).toBe('');
|
||||
element('.doc-example-live li:last a:contains("add")').click();
|
||||
expect(element('.doc-example-live li[ng\\:repeat-index="2"] input').val()).toBe('yourname@example.org');
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script type="text/javascript">
|
||||
function SettingsController() {
|
||||
this.name = "John Smith";
|
||||
this.contacts = [
|
||||
{type:'phone', value:'408 555 1212'},
|
||||
{type:'email', value:'john.smith@example.org'} ];
|
||||
}
|
||||
SettingsController.prototype = {
|
||||
greet: function(){
|
||||
alert(this.name);
|
||||
},
|
||||
addContact: function(){
|
||||
this.contacts.push({type:'email', value:'yourname@example.org'});
|
||||
},
|
||||
removeContact: function(contactToRemove) {
|
||||
angular.Array.remove(this.contacts, contactToRemove);
|
||||
},
|
||||
clearContact: function(contact) {
|
||||
contact.type = 'phone';
|
||||
contact.value = '';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<div ng:controller="SettingsController">
|
||||
Name: <input type="text" name="name"/>
|
||||
[ <a href="" ng:click="greet()">greet</a> ]<br/>
|
||||
Contact:
|
||||
<ul>
|
||||
<li ng:repeat="contact in contacts">
|
||||
<select name="contact.type">
|
||||
<option>phone</option>
|
||||
<option>email</option>
|
||||
</select>
|
||||
<input type="text" name="contact.value"/>
|
||||
[ <a href="" ng:click="clearContact(contact)">clear</a>
|
||||
| <a href="" ng:click="removeContact(contact)">X</a> ]
|
||||
</li>
|
||||
<li>[ <a href="" ng:click="addContact()">add</a> ]</li>
|
||||
</ul>
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check controller', function(){
|
||||
expect(element('.doc-example-live div>:input').val()).toBe('John Smith');
|
||||
expect(element('.doc-example-live li[ng\\:repeat-index="0"] input').val()).toBe('408 555 1212');
|
||||
expect(element('.doc-example-live li[ng\\:repeat-index="1"] input').val()).toBe('john.smith@example.org');
|
||||
element('.doc-example-live li:first a:contains("clear")').click();
|
||||
expect(element('.doc-example-live li:first input').val()).toBe('');
|
||||
element('.doc-example-live li:last a:contains("add")').click();
|
||||
expect(element('.doc-example-live li[ng\\:repeat-index="2"] input').val()).toBe('yourname@example.org');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:controller", function(expression){
|
||||
this.scope(true);
|
||||
|
|
@ -112,36 +120,38 @@ angularDirective("ng:controller", function(expression){
|
|||
* @name angular.directive.ng:eval
|
||||
*
|
||||
* @description
|
||||
* The `ng:eval` allows you to execute a binding which has side effects
|
||||
* The `ng:eval` allows you to execute a binding which has side effects
|
||||
* without displaying the result to the user.
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @exampleDescription
|
||||
* Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning
|
||||
* a value to `obj.multiplied` and displaying the result to the user. Sometimes,
|
||||
* however, it is desirable to execute a side effect without showing the value to
|
||||
* the user. In such a case `ng:eval` allows you to execute code without updating
|
||||
* the display.
|
||||
*
|
||||
* @example
|
||||
* <input name="obj.a" value="6" >
|
||||
* * <input name="obj.b" value="2">
|
||||
* = {{obj.multiplied = obj.a * obj.b}} <br>
|
||||
* <span ng:eval="obj.divide = obj.a / obj.b"></span>
|
||||
* <span ng:eval="obj.updateCount = 1 + (obj.updateCount||0)"></span>
|
||||
* <tt>obj.divide = {{obj.divide}}</tt><br/>
|
||||
* <tt>obj.updateCount = {{obj.updateCount}}</tt>
|
||||
*
|
||||
* @scenario
|
||||
it('should check eval', function(){
|
||||
expect(binding('obj.divide')).toBe('3');
|
||||
expect(binding('obj.updateCount')).toBe('2');
|
||||
input('obj.a').enter('12');
|
||||
expect(binding('obj.divide')).toBe('6');
|
||||
expect(binding('obj.updateCount')).toBe('3');
|
||||
});
|
||||
* Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning
|
||||
* a value to `obj.multiplied` and displaying the result to the user. Sometimes,
|
||||
* however, it is desirable to execute a side effect without showing the value to
|
||||
* the user. In such a case `ng:eval` allows you to execute code without updating
|
||||
* the display.
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<input name="obj.a" value="6" >
|
||||
* <input name="obj.b" value="2">
|
||||
= {{obj.multiplied = obj.a * obj.b}} <br>
|
||||
<span ng:eval="obj.divide = obj.a / obj.b"></span>
|
||||
<span ng:eval="obj.updateCount = 1 + (obj.updateCount||0)"></span>
|
||||
<tt>obj.divide = {{obj.divide}}</tt><br/>
|
||||
<tt>obj.updateCount = {{obj.updateCount}}</tt>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check eval', function(){
|
||||
expect(binding('obj.divide')).toBe('3');
|
||||
expect(binding('obj.updateCount')).toBe('2');
|
||||
input('obj.a').enter('12');
|
||||
expect(binding('obj.divide')).toBe('6');
|
||||
expect(binding('obj.updateCount')).toBe('3');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:eval", function(expression){
|
||||
return function(element){
|
||||
|
|
@ -155,27 +165,30 @@ angularDirective("ng:eval", function(expression){
|
|||
* @name angular.directive.ng:bind
|
||||
*
|
||||
* @description
|
||||
* The `ng:bind` attribute asks <angular/> to replace the text content of this
|
||||
* HTML element with the value of the given expression and kept it up to
|
||||
* date when the expression's value changes. Usually you just write
|
||||
* {{expression}} and let <angular/> compile it into
|
||||
* The `ng:bind` attribute asks <angular/> to replace the text content of this
|
||||
* HTML element with the value of the given expression and kept it up to
|
||||
* date when the expression's value changes. Usually you just write
|
||||
* {{expression}} and let <angular/> compile it into
|
||||
* `<span ng:bind="expression"></span>` at bootstrap time.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @exampleDescription
|
||||
* Try it here: enter text in text box and watch the greeting change.
|
||||
* @example
|
||||
* Enter name: <input type="text" name="name" value="Whirled">. <br>
|
||||
* Hello <span ng:bind="name" />!
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:bind', function(){
|
||||
expect(using('.doc-example-live').binding('name')).toBe('Whirled');
|
||||
using('.doc-example-live').input('name').enter('world');
|
||||
expect(using('.doc-example-live').binding('name')).toBe('world');
|
||||
});
|
||||
* Try it here: enter text in text box and watch the greeting change.
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter name: <input type="text" name="name" value="Whirled">. <br>
|
||||
Hello <span ng:bind="name" />!
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:bind', function(){
|
||||
expect(using('.doc-example-live').binding('name')).toBe('Whirled');
|
||||
using('.doc-example-live').input('name').enter('world');
|
||||
expect(using('.doc-example-live').binding('name')).toBe('world');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:bind", function(expression, element){
|
||||
element.addClass('ng-binding');
|
||||
|
|
@ -259,32 +272,35 @@ function compileBindTemplate(template){
|
|||
* @name angular.directive.ng:bind-template
|
||||
*
|
||||
* @description
|
||||
* The `ng:bind-template` attribute specifies that the element
|
||||
* text should be replaced with the template in ng:bind-template.
|
||||
* Unlike ng:bind the ng:bind-template can contain multiple `{{` `}}`
|
||||
* expressions. (This is required since some HTML elements
|
||||
* The `ng:bind-template` attribute specifies that the element
|
||||
* text should be replaced with the template in ng:bind-template.
|
||||
* Unlike ng:bind the ng:bind-template can contain multiple `{{` `}}`
|
||||
* expressions. (This is required since some HTML elements
|
||||
* can not have SPAN elements such as TITLE, or OPTION to name a few.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {string} template of form
|
||||
* <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
|
||||
*
|
||||
* @exampleDescription
|
||||
* Try it here: enter text in text box and watch the greeting change.
|
||||
* @example
|
||||
Salutation: <input type="text" name="salutation" value="Hello"><br/>
|
||||
Name: <input type="text" name="name" value="World"><br/>
|
||||
<pre ng:bind-template="{{salutation}} {{name}}!"></pre>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:bind', function(){
|
||||
expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
|
||||
toBe('Hello World!');
|
||||
using('.doc-example-live').input('salutation').enter('Greetings');
|
||||
using('.doc-example-live').input('name').enter('user');
|
||||
expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
|
||||
toBe('Greetings user!');
|
||||
});
|
||||
* Try it here: enter text in text box and watch the greeting change.
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Salutation: <input type="text" name="salutation" value="Hello"><br/>
|
||||
Name: <input type="text" name="name" value="World"><br/>
|
||||
<pre ng:bind-template="{{salutation}} {{name}}!"></pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:bind', function(){
|
||||
expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
|
||||
toBe('Hello World!');
|
||||
using('.doc-example-live').input('salutation').enter('Greetings');
|
||||
using('.doc-example-live').input('name').enter('user');
|
||||
expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
|
||||
toBe('Greetings user!');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:bind-template", function(expression, element){
|
||||
element.addClass('ng-binding');
|
||||
|
|
@ -313,49 +329,52 @@ var REMOVE_ATTRIBUTES = {
|
|||
* @name angular.directive.ng:bind-attr
|
||||
*
|
||||
* @description
|
||||
* The `ng:bind-attr` attribute specifies that the element attributes
|
||||
* which should be replaced by the expression in it. Unlike `ng:bind`
|
||||
* the `ng:bind-attr` contains a JSON key value pairs representing
|
||||
* which attributes need to be changed. You don’t usually write the
|
||||
* `ng:bind-attr` in the HTML since embedding
|
||||
* <tt ng:non-bindable>{{expression}}</tt> into the
|
||||
* The `ng:bind-attr` attribute specifies that the element attributes
|
||||
* which should be replaced by the expression in it. Unlike `ng:bind`
|
||||
* the `ng:bind-attr` contains a JSON key value pairs representing
|
||||
* which attributes need to be changed. You don’t usually write the
|
||||
* `ng:bind-attr` in the HTML since embedding
|
||||
* <tt ng:non-bindable>{{expression}}</tt> into the
|
||||
* attribute directly is the preferred way. The attributes get
|
||||
* translated into `<span ng:bind-attr="{attr:expression}"/>` at
|
||||
* bootstrap time.
|
||||
*
|
||||
*
|
||||
* This HTML snippet is preferred way of working with `ng:bind-attr`
|
||||
* <pre>
|
||||
* <a href="http://www.google.com/search?q={{query}}">Google</a>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* The above gets translated to bellow during bootstrap time.
|
||||
* <pre>
|
||||
* <a ng:bind-attr='{"href":"http://www.google.com/search?q={{query}}"}'>Google</a>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {string} attribute_json a JSON key-value pairs representing
|
||||
* the attributes to replace. Each key matches the attribute
|
||||
* which needs to be replaced. Each value is a text template of
|
||||
* the attribute with embedded
|
||||
* <tt ng:non-bindable>{{expression}}</tt>s. Any number of
|
||||
* @param {string} attribute_json a JSON key-value pairs representing
|
||||
* the attributes to replace. Each key matches the attribute
|
||||
* which needs to be replaced. Each value is a text template of
|
||||
* the attribute with embedded
|
||||
* <tt ng:non-bindable>{{expression}}</tt>s. Any number of
|
||||
* key-value pairs can be specified.
|
||||
*
|
||||
* @exampleDescription
|
||||
* Try it here: enter text in text box and click Google.
|
||||
* @example
|
||||
Google for:
|
||||
<input type="text" name="query" value="AngularJS"/>
|
||||
<a href="http://www.google.com/search?q={{query}}">Google</a>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:bind-attr', function(){
|
||||
expect(using('.doc-example-live').element('a').attr('href')).
|
||||
toBe('http://www.google.com/search?q=AngularJS');
|
||||
using('.doc-example-live').input('query').enter('google');
|
||||
expect(using('.doc-example-live').element('a').attr('href')).
|
||||
toBe('http://www.google.com/search?q=google');
|
||||
});
|
||||
* Try it here: enter text in text box and click Google.
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Google for:
|
||||
<input type="text" name="query" value="AngularJS"/>
|
||||
<a href="http://www.google.com/search?q={{query}}">Google</a>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:bind-attr', function(){
|
||||
expect(using('.doc-example-live').element('a').attr('href')).
|
||||
toBe('http://www.google.com/search?q=AngularJS');
|
||||
using('.doc-example-live').input('query').enter('google');
|
||||
expect(using('.doc-example-live').element('a').attr('href')).
|
||||
toBe('http://www.google.com/search?q=google');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:bind-attr", function(expression){
|
||||
return function(element){
|
||||
|
|
@ -396,23 +415,28 @@ angularDirective("ng:bind-attr", function(expression){
|
|||
* @name angular.directive.ng:click
|
||||
*
|
||||
* @description
|
||||
* The ng:click allows you to specify custom behavior when
|
||||
* The ng:click allows you to specify custom behavior when
|
||||
* element is clicked.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval upon click.
|
||||
*
|
||||
* @example
|
||||
<button ng:click="count = count + 1" ng:init="count=0">
|
||||
Increment
|
||||
</button>
|
||||
count: {{count}}
|
||||
* @scenario
|
||||
it('should check ng:click', function(){
|
||||
expect(binding('count')).toBe('0');
|
||||
element('.doc-example-live :button').click();
|
||||
expect(binding('count')).toBe('1');
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<button ng:click="count = count + 1" ng:init="count=0">
|
||||
Increment
|
||||
</button>
|
||||
count: {{count}}
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:click', function(){
|
||||
expect(binding('count')).toBe('0');
|
||||
element('.doc-example-live :button').click();
|
||||
expect(binding('count')).toBe('1');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
/*
|
||||
* A directive that allows creation of custom onclick handlers that are defined as angular
|
||||
|
|
@ -440,35 +464,37 @@ angularDirective("ng:click", function(expression, element){
|
|||
* @name angular.directive.ng:submit
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* @element form
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* <form ng:submit="list.push(text);text='';" ng:init="list=[]">
|
||||
* Enter text and hit enter:
|
||||
* <input type="text" name="text" value="hello"/>
|
||||
* </form>
|
||||
* <pre>list={{list}}</pre>
|
||||
* @scenario
|
||||
it('should check ng:submit', function(){
|
||||
expect(binding('list')).toBe('list=[]');
|
||||
element('.doc-example-live form input').click();
|
||||
this.addFutureAction('submit from', function($window, $document, done) {
|
||||
$window.angular.element(
|
||||
$document.elements('.doc-example-live form')).
|
||||
trigger('submit');
|
||||
done();
|
||||
});
|
||||
expect(binding('list')).toBe('list=["hello"]');
|
||||
});
|
||||
*/
|
||||
/**
|
||||
* Enables binding angular expressions to onsubmit events.
|
||||
*
|
||||
* Additionally it prevents the default action (which for form means sending the request to the
|
||||
* server and reloading the current page).
|
||||
*
|
||||
* @element form
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<form ng:submit="list.push(text);text='';" ng:init="list=[]">
|
||||
Enter text and hit enter:
|
||||
<input type="text" name="text" value="hello"/>
|
||||
</form>
|
||||
<pre>list={{list}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:submit', function(){
|
||||
expect(binding('list')).toBe('list=[]');
|
||||
element('.doc-example-live form input').click();
|
||||
this.addFutureAction('submit from', function($window, $document, done) {
|
||||
$window.angular.element(
|
||||
$document.elements('.doc-example-live form')).
|
||||
trigger('submit');
|
||||
done();
|
||||
});
|
||||
expect(binding('list')).toBe('list=["hello"]');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:submit", function(expression, element) {
|
||||
return injectUpdateView(function($updateView, element) {
|
||||
|
|
@ -488,26 +514,30 @@ angularDirective("ng:submit", function(expression, element) {
|
|||
* @name angular.directive.ng:watch
|
||||
*
|
||||
* @description
|
||||
* The `ng:watch` allows you watch a variable and then execute
|
||||
* The `ng:watch` allows you watch a variable and then execute
|
||||
* an evaluation on variable change.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @exampleDescription
|
||||
* Notice that the counter is incremented
|
||||
* every time you change the text.
|
||||
* @example
|
||||
<div ng:init="counter=0" ng:watch="name: counter = counter+1">
|
||||
<input type="text" name="name" value="hello"><br/>
|
||||
Change counter: {{counter}} Name: {{name}}
|
||||
</div>
|
||||
* @scenario
|
||||
it('should check ng:watch', function(){
|
||||
expect(using('.doc-example-live').binding('counter')).toBe('2');
|
||||
using('.doc-example-live').input('name').enter('abc');
|
||||
expect(using('.doc-example-live').binding('counter')).toBe('3');
|
||||
});
|
||||
* Notice that the counter is incremented
|
||||
* every time you change the text.
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="counter=0" ng:watch="name: counter = counter+1">
|
||||
<input type="text" name="name" value="hello"><br/>
|
||||
Change counter: {{counter}} Name: {{name}}
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:watch', function(){
|
||||
expect(using('.doc-example-live').binding('counter')).toBe('2');
|
||||
using('.doc-example-live').input('name').enter('abc');
|
||||
expect(using('.doc-example-live').binding('counter')).toBe('3');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
//TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular)
|
||||
angularDirective("ng:watch", function(expression, element){
|
||||
|
|
@ -544,34 +574,37 @@ function ngClass(selector) {
|
|||
* @name angular.directive.ng:class
|
||||
*
|
||||
* @description
|
||||
* The `ng:class` allows you to set CSS class on HTML element
|
||||
* The `ng:class` allows you to set CSS class on HTML element
|
||||
* conditionally.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
<input type="button" value="set" ng:click="myVar='ng-input-indicator-wait'">
|
||||
<input type="button" value="clear" ng:click="myVar=''">
|
||||
<br>
|
||||
<span ng:class="myVar">Sample Text </span>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:class', function(){
|
||||
expect(element('.doc-example-live span').attr('className')).not().
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<input type="button" value="set" ng:click="myVar='ng-input-indicator-wait'">
|
||||
<input type="button" value="clear" ng:click="myVar=''">
|
||||
<br>
|
||||
<span ng:class="myVar">Sample Text </span>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:class', function(){
|
||||
expect(element('.doc-example-live span').attr('className')).not().
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
|
||||
using('.doc-example-live').element(':button:first').click();
|
||||
using('.doc-example-live').element(':button:first').click();
|
||||
|
||||
expect(element('.doc-example-live span').attr('className')).
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
expect(element('.doc-example-live span').attr('className')).
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
|
||||
using('.doc-example-live').element(':button:last').click();
|
||||
|
||||
expect(element('.doc-example-live span').attr('className')).not().
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
});
|
||||
using('.doc-example-live').element(':button:last').click();
|
||||
|
||||
expect(element('.doc-example-live span').attr('className')).not().
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:class", ngClass(function(){return true;}));
|
||||
|
||||
|
|
@ -581,33 +614,35 @@ angularDirective("ng:class", ngClass(function(){return true;}));
|
|||
* @name angular.directive.ng:class-odd
|
||||
*
|
||||
* @description
|
||||
* The `ng:class-odd` and `ng:class-even` works exactly as
|
||||
* `ng:class`, except it works in conjunction with `ng:repeat`
|
||||
* The `ng:class-odd` and `ng:class-even` works exactly as
|
||||
* `ng:class`, except it works in conjunction with `ng:repeat`
|
||||
* and takes affect only on odd (even) rows.
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval. Must be inside
|
||||
* @param {expression} expression to eval. Must be inside
|
||||
* `ng:repeat`.
|
||||
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
<ol ng:init="names=['John', 'Mary', 'Cate', 'Suz']">
|
||||
<li ng:repeat="name in names">
|
||||
<span ng:class-odd="'ng-format-negative'"
|
||||
ng:class-even="'ng-input-indicator-wait'">
|
||||
{{name}}
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:class-odd and ng:class-even', function(){
|
||||
expect(element('.doc-example-live li:first span').attr('className')).
|
||||
toMatch(/ng-format-negative/);
|
||||
expect(element('.doc-example-live li:last span').attr('className')).
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<ol ng:init="names=['John', 'Mary', 'Cate', 'Suz']">
|
||||
<li ng:repeat="name in names">
|
||||
<span ng:class-odd="'ng-format-negative'"
|
||||
ng:class-even="'ng-input-indicator-wait'">
|
||||
{{name}}
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:class-odd and ng:class-even', function(){
|
||||
expect(element('.doc-example-live li:first span').attr('className')).
|
||||
toMatch(/ng-format-negative/);
|
||||
expect(element('.doc-example-live li:last span').attr('className')).
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;}));
|
||||
|
||||
|
|
@ -617,33 +652,35 @@ angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;}));
|
|||
* @name angular.directive.ng:class-even
|
||||
*
|
||||
* @description
|
||||
* The `ng:class-odd` and `ng:class-even` works exactly as
|
||||
* `ng:class`, except it works in conjunction with `ng:repeat`
|
||||
* The `ng:class-odd` and `ng:class-even` works exactly as
|
||||
* `ng:class`, except it works in conjunction with `ng:repeat`
|
||||
* and takes affect only on odd (even) rows.
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression to eval. Must be inside
|
||||
* @param {expression} expression to eval. Must be inside
|
||||
* `ng:repeat`.
|
||||
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
<ol ng:init="names=['John', 'Mary', 'Cate', 'Suz']">
|
||||
<li ng:repeat="name in names">
|
||||
<span ng:class-odd="'ng-format-negative'"
|
||||
ng:class-even="'ng-input-indicator-wait'">
|
||||
{{name}}
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:class-odd and ng:class-even', function(){
|
||||
expect(element('.doc-example-live li:first span').attr('className')).
|
||||
toMatch(/ng-format-negative/);
|
||||
expect(element('.doc-example-live li:last span').attr('className')).
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<ol ng:init="names=['John', 'Mary', 'Cate', 'Suz']">
|
||||
<li ng:repeat="name in names">
|
||||
<span ng:class-odd="'ng-format-negative'"
|
||||
ng:class-even="'ng-input-indicator-wait'">
|
||||
{{name}}
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:class-odd and ng:class-even', function(){
|
||||
expect(element('.doc-example-live li:first span').attr('className')).
|
||||
toMatch(/ng-format-negative/);
|
||||
expect(element('.doc-example-live li:last span').attr('className')).
|
||||
toMatch(/ng-input-indicator-wait/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;}));
|
||||
|
||||
|
|
@ -655,27 +692,30 @@ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;}));
|
|||
* @description
|
||||
* The `ng:show` and `ng:hide` allows you to show or hide a portion
|
||||
* of the HTML conditionally.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression if truthy then the element is
|
||||
* @param {expression} expression if truthy then the element is
|
||||
* shown or hidden respectively.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
Click me: <input type="checkbox" name="checked"><br/>
|
||||
Show: <span ng:show="checked">I show up when you checkbox is checked?</span> <br/>
|
||||
Hide: <span ng:hide="checked">I hide when you checkbox is checked?</span>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:show / ng:hide', function(){
|
||||
expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:visible').count()).toEqual(1);
|
||||
|
||||
input('checked').check();
|
||||
|
||||
expect(element('.doc-example-live span:first:visible').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Click me: <input type="checkbox" name="checked"><br/>
|
||||
Show: <span ng:show="checked">I show up when you checkbox is checked?</span> <br/>
|
||||
Hide: <span ng:hide="checked">I hide when you checkbox is checked?</span>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:show / ng:hide', function(){
|
||||
expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:visible').count()).toEqual(1);
|
||||
|
||||
input('checked').check();
|
||||
|
||||
expect(element('.doc-example-live span:first:visible').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:show", function(expression, element){
|
||||
return function(element){
|
||||
|
|
@ -693,27 +733,30 @@ angularDirective("ng:show", function(expression, element){
|
|||
* @description
|
||||
* The `ng:show` and `ng:hide` allows you to show or hide a portion
|
||||
* of the HTML conditionally.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression if truthy then the element is
|
||||
* @param {expression} expression if truthy then the element is
|
||||
* shown or hidden respectively.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
Click me: <input type="checkbox" name="checked"><br/>
|
||||
Show: <span ng:show="checked">I show up when you checkbox is checked?</span> <br/>
|
||||
Hide: <span ng:hide="checked">I hide when you checkbox is checked?</span>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:show / ng:hide', function(){
|
||||
expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:visible').count()).toEqual(1);
|
||||
|
||||
input('checked').check();
|
||||
|
||||
expect(element('.doc-example-live span:first:visible').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Click me: <input type="checkbox" name="checked"><br/>
|
||||
Show: <span ng:show="checked">I show up when you checkbox is checked?</span> <br/>
|
||||
Hide: <span ng:hide="checked">I hide when you checkbox is checked?</span>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:show / ng:hide', function(){
|
||||
expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:visible').count()).toEqual(1);
|
||||
|
||||
input('checked').check();
|
||||
|
||||
expect(element('.doc-example-live span:first:visible').count()).toEqual(1);
|
||||
expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:hide", function(expression, element){
|
||||
return function(element){
|
||||
|
|
@ -730,28 +773,31 @@ angularDirective("ng:hide", function(expression, element){
|
|||
*
|
||||
* @description
|
||||
* The ng:style allows you to set CSS style on an HTML element conditionally.
|
||||
*
|
||||
*
|
||||
* @element ANY
|
||||
* @param {expression} expression which evals to an object whes key's are
|
||||
* CSS style names and values are coresponding values for those
|
||||
* @param {expression} expression which evals to an object whes key's are
|
||||
* CSS style names and values are coresponding values for those
|
||||
* CSS keys.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
<input type="button" value="set" ng:click="myStyle={color:'red'}">
|
||||
<input type="button" value="clear" ng:click="myStyle={}">
|
||||
<br/>
|
||||
<span ng:style="myStyle">Sample Text</span>
|
||||
<pre>myStyle={{myStyle}}</pre>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:style', function(){
|
||||
expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');
|
||||
element('.doc-example-live :button[value=set]').click();
|
||||
expect(element('.doc-example-live span').css('color')).toBe('red');
|
||||
element('.doc-example-live :button[value=clear]').click();
|
||||
expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<input type="button" value="set" ng:click="myStyle={color:'red'}">
|
||||
<input type="button" value="clear" ng:click="myStyle={}">
|
||||
<br/>
|
||||
<span ng:style="myStyle">Sample Text</span>
|
||||
<pre>myStyle={{myStyle}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:style', function(){
|
||||
expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');
|
||||
element('.doc-example-live :button[value=set]').click();
|
||||
expect(element('.doc-example-live span').css('color')).toBe('red');
|
||||
element('.doc-example-live :button[value=clear]').click();
|
||||
expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularDirective("ng:style", function(expression, element){
|
||||
return function(element){
|
||||
|
|
|
|||
337
src/filters.js
337
src/filters.js
|
|
@ -14,19 +14,23 @@
|
|||
* When the value is negative, this css class is applied to the binding making it by default red.
|
||||
*
|
||||
* @example
|
||||
<input type="text" name="amount" value="1234.56"/> <br/>
|
||||
{{amount | currency}}
|
||||
*
|
||||
* @scenario
|
||||
it('should init with 1234.56', function(){
|
||||
expect(binding('amount | currency')).toBe('$1,234.56');
|
||||
});
|
||||
it('should update', function(){
|
||||
input('amount').enter('-1234');
|
||||
expect(binding('amount | currency')).toBe('$-1,234.00');
|
||||
expect(element('.doc-example-live .ng-binding').attr('className')).
|
||||
toMatch(/ng-format-negative/);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<input type="text" name="amount" value="1234.56"/> <br/>
|
||||
{{amount | currency}}
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should init with 1234.56', function(){
|
||||
expect(binding('amount | currency')).toBe('$1,234.56');
|
||||
});
|
||||
it('should update', function(){
|
||||
input('amount').enter('-1234');
|
||||
expect(binding('amount | currency')).toBe('$-1,234.00');
|
||||
expect(element('.doc-example-live .ng-binding').attr('className')).
|
||||
toMatch(/ng-format-negative/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFilter.currency = function(amount){
|
||||
this.$element.toggleClass('ng-format-negative', amount < 0);
|
||||
|
|
@ -49,24 +53,28 @@ angularFilter.currency = function(amount){
|
|||
* @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
|
||||
*
|
||||
* @example
|
||||
Enter number: <input name='val' value='1234.56789' /><br/>
|
||||
Default formatting: {{val | number}}<br/>
|
||||
No fractions: {{val | number:0}}<br/>
|
||||
Negative number: {{-val | number:4}}
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter number: <input name='val' value='1234.56789' /><br/>
|
||||
Default formatting: {{val | number}}<br/>
|
||||
No fractions: {{val | number:0}}<br/>
|
||||
Negative number: {{-val | number:4}}
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should format numbers', function(){
|
||||
expect(binding('val | number')).toBe('1,234.57');
|
||||
expect(binding('val | number:0')).toBe('1,235');
|
||||
expect(binding('-val | number:4')).toBe('-1,234.5679');
|
||||
});
|
||||
|
||||
* @scenario
|
||||
it('should format numbers', function(){
|
||||
expect(binding('val | number')).toBe('1,234.57');
|
||||
expect(binding('val | number:0')).toBe('1,235');
|
||||
expect(binding('-val | number:4')).toBe('-1,234.5679');
|
||||
});
|
||||
|
||||
it('should update', function(){
|
||||
input('val').enter('3374.333');
|
||||
expect(binding('val | number')).toBe('3,374.33');
|
||||
expect(binding('val | number:0')).toBe('3,374');
|
||||
expect(binding('-val | number:4')).toBe('-3,374.3330');
|
||||
});
|
||||
it('should update', function(){
|
||||
input('val').enter('3374.333');
|
||||
expect(binding('val | number')).toBe('3,374.33');
|
||||
expect(binding('val | number:0')).toBe('3,374');
|
||||
expect(binding('-val | number:4')).toBe('-3,374.3330');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFilter.number = function(number, fractionSize){
|
||||
if (isNaN(number) || !isFinite(number)) {
|
||||
|
|
@ -183,19 +191,22 @@ var NUMBER_STRING = /^\d+$/;
|
|||
* @returns {string} Formatted string or the input if input is not recognized as date/millis.
|
||||
*
|
||||
* @example
|
||||
<span ng:non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
|
||||
{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br/>
|
||||
<span ng:non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
|
||||
{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br/>
|
||||
*
|
||||
* @scenario
|
||||
it('should format date', function(){
|
||||
expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).
|
||||
toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/);
|
||||
expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
|
||||
toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(am|pm)/);
|
||||
});
|
||||
*
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<span ng:non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
|
||||
{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br/>
|
||||
<span ng:non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
|
||||
{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br/>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should format date', function(){
|
||||
expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).
|
||||
toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/);
|
||||
expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
|
||||
toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(am|pm)/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFilter.date = function(date, format) {
|
||||
if (isString(date)) {
|
||||
|
|
@ -255,19 +266,23 @@ angularFilter.date = function(date, format) {
|
|||
* @css ng-monospace Always applied to the encapsulating element.
|
||||
*
|
||||
* @example:
|
||||
<input type="text" name="objTxt" value="{a:1, b:[]}"
|
||||
ng:eval="obj = $eval(objTxt)"/>
|
||||
<pre>{{ obj | json }}</pre>
|
||||
*
|
||||
* @scenario
|
||||
it('should jsonify filtered objects', function() {
|
||||
expect(binding('obj | json')).toBe('{\n "a":1,\n "b":[]}');
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<input type="text" name="objTxt" value="{a:1, b:[]}"
|
||||
ng:eval="obj = $eval(objTxt)"/>
|
||||
<pre>{{ obj | json }}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should jsonify filtered objects', function() {
|
||||
expect(binding('obj | json')).toBe('{\n "a":1,\n "b":[]}');
|
||||
});
|
||||
|
||||
it('should update', function() {
|
||||
input('objTxt').enter('[1, 2, 3]');
|
||||
expect(binding('obj | json')).toBe('[1,2,3]');
|
||||
});
|
||||
it('should update', function() {
|
||||
input('objTxt').enter('[1, 2, 3]');
|
||||
expect(binding('obj | json')).toBe('[1,2,3]');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
angularFilter.json = function(object) {
|
||||
|
|
@ -324,63 +339,67 @@ angularFilter.uppercase = uppercase;
|
|||
* @returns {string} Sanitized or raw html.
|
||||
*
|
||||
* @example
|
||||
Snippet: <textarea name="snippet" cols="60" rows="3">
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Snippet: <textarea name="snippet" cols="60" rows="3">
|
||||
<p style="color:blue">an html
|
||||
<em onmouseover="this.textContent='PWN3D!'">click here</em>
|
||||
snippet</p></textarea>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Filter</td>
|
||||
<td>Source</td>
|
||||
<td>Rendered</td>
|
||||
</tr>
|
||||
<tr id="html-filter">
|
||||
<td>html filter</td>
|
||||
<td>
|
||||
<pre><div ng:bind="snippet | html"><br/></div></pre>
|
||||
</td>
|
||||
<td>
|
||||
<div ng:bind="snippet | html"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="escaped-html">
|
||||
<td>no filter</td>
|
||||
<td><pre><div ng:bind="snippet"><br/></div></pre></td>
|
||||
<td><div ng:bind="snippet"></div></td>
|
||||
</tr>
|
||||
<tr id="html-unsafe-filter">
|
||||
<td>unsafe html filter</td>
|
||||
<td><pre><div ng:bind="snippet | html:'unsafe'"><br/></div></pre></td>
|
||||
<td><div ng:bind="snippet | html:'unsafe'"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
*
|
||||
* @scenario
|
||||
it('should sanitize the html snippet ', function(){
|
||||
expect(using('#html-filter').binding('snippet | html')).
|
||||
toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
|
||||
});
|
||||
<table>
|
||||
<tr>
|
||||
<td>Filter</td>
|
||||
<td>Source</td>
|
||||
<td>Rendered</td>
|
||||
</tr>
|
||||
<tr id="html-filter">
|
||||
<td>html filter</td>
|
||||
<td>
|
||||
<pre><div ng:bind="snippet | html"><br/></div></pre>
|
||||
</td>
|
||||
<td>
|
||||
<div ng:bind="snippet | html"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="escaped-html">
|
||||
<td>no filter</td>
|
||||
<td><pre><div ng:bind="snippet"><br/></div></pre></td>
|
||||
<td><div ng:bind="snippet"></div></td>
|
||||
</tr>
|
||||
<tr id="html-unsafe-filter">
|
||||
<td>unsafe html filter</td>
|
||||
<td><pre><div ng:bind="snippet | html:'unsafe'"><br/></div></pre></td>
|
||||
<td><div ng:bind="snippet | html:'unsafe'"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should sanitize the html snippet ', function(){
|
||||
expect(using('#html-filter').binding('snippet | html')).
|
||||
toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
|
||||
});
|
||||
|
||||
it ('should escape snippet without any filter', function() {
|
||||
expect(using('#escaped-html').binding('snippet')).
|
||||
toBe("<p style=\"color:blue\">an html\n" +
|
||||
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
||||
"snippet</p>");
|
||||
});
|
||||
it('should escape snippet without any filter', function() {
|
||||
expect(using('#escaped-html').binding('snippet')).
|
||||
toBe("<p style=\"color:blue\">an html\n" +
|
||||
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
||||
"snippet</p>");
|
||||
});
|
||||
|
||||
it ('should inline raw snippet if filtered as unsafe', function() {
|
||||
expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).
|
||||
toBe("<p style=\"color:blue\">an html\n" +
|
||||
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
||||
"snippet</p>");
|
||||
});
|
||||
it('should inline raw snippet if filtered as unsafe', function() {
|
||||
expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).
|
||||
toBe("<p style=\"color:blue\">an html\n" +
|
||||
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
||||
"snippet</p>");
|
||||
});
|
||||
|
||||
it('should update', function(){
|
||||
input('snippet').enter('new <b>text</b>');
|
||||
expect(using('#html-filter').binding('snippet | html')).toBe('new <b>text</b>');
|
||||
expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>");
|
||||
expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new <b>text</b>');
|
||||
});
|
||||
it('should update', function(){
|
||||
input('snippet').enter('new <b>text</b>');
|
||||
expect(using('#html-filter').binding('snippet | html')).toBe('new <b>text</b>');
|
||||
expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>");
|
||||
expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new <b>text</b>');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFilter.html = function(html, option){
|
||||
return new HTML(html, option);
|
||||
|
|
@ -401,59 +420,63 @@ angularFilter.html = function(html, option){
|
|||
* @returns {string} Html-linkified text.
|
||||
*
|
||||
* @example
|
||||
Snippet: <textarea name="snippet" cols="60" rows="3">
|
||||
Pretty text with some links:
|
||||
http://angularjs.org/,
|
||||
mailto:us@somewhere.org,
|
||||
another@somewhere.org,
|
||||
and one more: ftp://127.0.0.1/.</textarea>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Filter</td>
|
||||
<td>Source</td>
|
||||
<td>Rendered</td>
|
||||
</tr>
|
||||
<tr id="linky-filter">
|
||||
<td>linky filter</td>
|
||||
<td>
|
||||
<pre><div ng:bind="snippet | linky"><br/></div></pre>
|
||||
</td>
|
||||
<td>
|
||||
<div ng:bind="snippet | linky"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="escaped-html">
|
||||
<td>no filter</td>
|
||||
<td><pre><div ng:bind="snippet"><br/></div></pre></td>
|
||||
<td><div ng:bind="snippet"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Snippet: <textarea name="snippet" cols="60" rows="3">
|
||||
Pretty text with some links:
|
||||
http://angularjs.org/,
|
||||
mailto:us@somewhere.org,
|
||||
another@somewhere.org,
|
||||
and one more: ftp://127.0.0.1/.</textarea>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Filter</td>
|
||||
<td>Source</td>
|
||||
<td>Rendered</td>
|
||||
</tr>
|
||||
<tr id="linky-filter">
|
||||
<td>linky filter</td>
|
||||
<td>
|
||||
<pre><div ng:bind="snippet | linky"><br/></div></pre>
|
||||
</td>
|
||||
<td>
|
||||
<div ng:bind="snippet | linky"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="escaped-html">
|
||||
<td>no filter</td>
|
||||
<td><pre><div ng:bind="snippet"><br/></div></pre></td>
|
||||
<td><div ng:bind="snippet"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should linkify the snippet with urls', function(){
|
||||
expect(using('#linky-filter').binding('snippet | linky')).
|
||||
toBe('Pretty text with some links:\n' +
|
||||
'<a href="http://angularjs.org/">http://angularjs.org/</a>,\n' +
|
||||
'<a href="mailto:us@somewhere.org">us@somewhere.org</a>,\n' +
|
||||
'<a href="mailto:another@somewhere.org">another@somewhere.org</a>,\n' +
|
||||
'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
|
||||
});
|
||||
|
||||
@scenario
|
||||
it('should linkify the snippet with urls', function(){
|
||||
expect(using('#linky-filter').binding('snippet | linky')).
|
||||
toBe('Pretty text with some links:\n' +
|
||||
'<a href="http://angularjs.org/">http://angularjs.org/</a>,\n' +
|
||||
'<a href="mailto:us@somewhere.org">us@somewhere.org</a>,\n' +
|
||||
'<a href="mailto:another@somewhere.org">another@somewhere.org</a>,\n' +
|
||||
'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
|
||||
});
|
||||
it ('should not linkify snippet without the linky filter', function() {
|
||||
expect(using('#escaped-html').binding('snippet')).
|
||||
toBe("Pretty text with some links:\n" +
|
||||
"http://angularjs.org/,\n" +
|
||||
"mailto:us@somewhere.org,\n" +
|
||||
"another@somewhere.org,\n" +
|
||||
"and one more: ftp://127.0.0.1/.");
|
||||
});
|
||||
|
||||
it ('should not linkify snippet without the linky filter', function() {
|
||||
expect(using('#escaped-html').binding('snippet')).
|
||||
toBe("Pretty text with some links:\n" +
|
||||
"http://angularjs.org/,\n" +
|
||||
"mailto:us@somewhere.org,\n" +
|
||||
"another@somewhere.org,\n" +
|
||||
"and one more: ftp://127.0.0.1/.");
|
||||
});
|
||||
|
||||
it('should update', function(){
|
||||
input('snippet').enter('new http://link.');
|
||||
expect(using('#linky-filter').binding('snippet | linky')).
|
||||
toBe('new <a href="http://link">http://link</a>.');
|
||||
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
|
||||
});
|
||||
it('should update', function(){
|
||||
input('snippet').enter('new http://link.');
|
||||
expect(using('#linky-filter').binding('snippet | linky')).
|
||||
toBe('new <a href="http://link">http://link</a>.');
|
||||
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
//TODO: externalize all regexps
|
||||
angularFilter.linky = function(text){
|
||||
|
|
|
|||
|
|
@ -18,17 +18,21 @@ angularFormatter.noop = formatter(identity, identity);
|
|||
* @returns {?string} A JSON string representation of the model.
|
||||
*
|
||||
* @example
|
||||
* <div ng:init="data={name:'misko', project:'angular'}">
|
||||
* <input type="text" size='50' name="data" ng:format="json"/>
|
||||
* <pre>data={{data}}</pre>
|
||||
* </div>
|
||||
*
|
||||
* @scenario
|
||||
* it('should format json', function(){
|
||||
* expect(binding('data')).toEqual('data={\n \"name\":\"misko\",\n \"project\":\"angular\"}');
|
||||
* input('data').enter('{}');
|
||||
* expect(binding('data')).toEqual('data={\n }');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="data={name:'misko', project:'angular'}">
|
||||
<input type="text" size='50' name="data" ng:format="json"/>
|
||||
<pre>data={{data}}</pre>
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should format json', function(){
|
||||
expect(binding('data')).toEqual('data={\n \"name\":\"misko\",\n \"project\":\"angular\"}');
|
||||
input('data').enter('{}');
|
||||
expect(binding('data')).toEqual('data={\n }');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFormatter.json = formatter(toJson, function(value){
|
||||
return fromJson(value || 'null');
|
||||
|
|
@ -45,17 +49,21 @@ angularFormatter.json = formatter(toJson, function(value){
|
|||
* @returns {boolean} Converts to `true` unless user enters (blank), `f`, `false`, `0`, `no`, `[]`.
|
||||
*
|
||||
* @example
|
||||
* Enter truthy text:
|
||||
* <input type="text" name="value" ng:format="boolean" value="no"/>
|
||||
* <input type="checkbox" name="value"/>
|
||||
* <pre>value={{value}}</pre>
|
||||
*
|
||||
* @scenario
|
||||
* it('should format boolean', function(){
|
||||
* expect(binding('value')).toEqual('value=false');
|
||||
* input('value').enter('truthy');
|
||||
* expect(binding('value')).toEqual('value=true');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter truthy text:
|
||||
<input type="text" name="value" ng:format="boolean" value="no"/>
|
||||
<input type="checkbox" name="value"/>
|
||||
<pre>value={{value}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should format boolean', function(){
|
||||
expect(binding('value')).toEqual('value=false');
|
||||
input('value').enter('truthy');
|
||||
expect(binding('value')).toEqual('value=true');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFormatter['boolean'] = formatter(toString, toBoolean);
|
||||
|
||||
|
|
@ -70,16 +78,20 @@ angularFormatter['boolean'] = formatter(toString, toBoolean);
|
|||
* @returns {number} Number from the parsed string.
|
||||
*
|
||||
* @example
|
||||
* Enter valid number:
|
||||
* <input type="text" name="value" ng:format="number" value="1234"/>
|
||||
* <pre>value={{value}}</pre>
|
||||
*
|
||||
* @scenario
|
||||
* it('should format numbers', function(){
|
||||
* expect(binding('value')).toEqual('value=1234');
|
||||
* input('value').enter('5678');
|
||||
* expect(binding('value')).toEqual('value=5678');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter valid number:
|
||||
<input type="text" name="value" ng:format="number" value="1234"/>
|
||||
<pre>value={{value}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should format numbers', function(){
|
||||
expect(binding('value')).toEqual('value=1234');
|
||||
input('value').enter('5678');
|
||||
expect(binding('value')).toEqual('value=5678');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFormatter.number = formatter(toString, function(obj){
|
||||
if (obj == _null || NUMBER.exec(obj)) {
|
||||
|
|
@ -100,20 +112,24 @@ angularFormatter.number = formatter(toString, function(obj){
|
|||
* @returns {Array} Array parsed from the entered string.
|
||||
*
|
||||
* @example
|
||||
* Enter a list of items:
|
||||
* <input type="text" name="value" ng:format="list" value=" chair ,, table"/>
|
||||
* <input type="text" name="value" ng:format="list"/>
|
||||
* <pre>value={{value}}</pre>
|
||||
*
|
||||
* @scenario
|
||||
* it('should format lists', function(){
|
||||
* expect(binding('value')).toEqual('value=["chair","table"]');
|
||||
* this.addFutureAction('change to XYZ', function($window, $document, done){
|
||||
* $document.elements('.doc-example :input:last').val(',,a,b,').trigger('change');
|
||||
* done();
|
||||
* });
|
||||
* expect(binding('value')).toEqual('value=["a","b"]');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter a list of items:
|
||||
<input type="text" name="value" ng:format="list" value=" chair ,, table"/>
|
||||
<input type="text" name="value" ng:format="list"/>
|
||||
<pre>value={{value}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should format lists', function(){
|
||||
expect(binding('value')).toEqual('value=["chair","table"]');
|
||||
this.addFutureAction('change to XYZ', function($window, $document, done){
|
||||
$document.elements('.doc-example :input:last').val(',,a,b,').trigger('change');
|
||||
done();
|
||||
});
|
||||
expect(binding('value')).toEqual('value=["a","b"]');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFormatter.list = formatter(
|
||||
function(obj) { return obj ? obj.join(", ") : obj; },
|
||||
|
|
@ -138,20 +154,24 @@ angularFormatter.list = formatter(
|
|||
* @returns {String} Trim excess leading and trailing space.
|
||||
*
|
||||
* @example
|
||||
* Enter text with leading/trailing spaces:
|
||||
* <input type="text" name="value" ng:format="trim" value=" book "/>
|
||||
* <input type="text" name="value" ng:format="trim"/>
|
||||
* <pre>value={{value|json}}</pre>
|
||||
*
|
||||
* @scenario
|
||||
* it('should format trim', function(){
|
||||
* expect(binding('value')).toEqual('value="book"');
|
||||
* this.addFutureAction('change to XYZ', function($window, $document, done){
|
||||
* $document.elements('.doc-example :input:last').val(' text ').trigger('change');
|
||||
* done();
|
||||
* });
|
||||
* expect(binding('value')).toEqual('value="text"');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter text with leading/trailing spaces:
|
||||
<input type="text" name="value" ng:format="trim" value=" book "/>
|
||||
<input type="text" name="value" ng:format="trim"/>
|
||||
<pre>value={{value|json}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should format trim', function(){
|
||||
expect(binding('value')).toEqual('value="book"');
|
||||
this.addFutureAction('change to XYZ', function($window, $document, done){
|
||||
$document.elements('.doc-example :input:last').val(' text ').trigger('change');
|
||||
done();
|
||||
});
|
||||
expect(binding('value')).toEqual('value="text"');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFormatter.trim = formatter(
|
||||
function(obj) { return obj ? trim("" + obj) : ""; }
|
||||
|
|
@ -176,33 +196,36 @@ angularFormatter.trim = formatter(
|
|||
* @returns {object} object which is located at the selected position.
|
||||
*
|
||||
* @example
|
||||
* <script>
|
||||
* function DemoCntl(){
|
||||
* this.users = [
|
||||
* {name:'guest', password:'guest'},
|
||||
* {name:'user', password:'123'},
|
||||
* {name:'admin', password:'abc'}
|
||||
* ];
|
||||
* }
|
||||
* </script>
|
||||
* <div ng:controller="DemoCntl">
|
||||
* User:
|
||||
* <select name="currentUser" ng:format="index:users">
|
||||
* <option ng:repeat="user in users" value="{{$index}}">{{user.name}}</option>
|
||||
* </select>
|
||||
* <select name="currentUser" ng:format="index:users">
|
||||
* <option ng:repeat="user in users" value="{{$index}}">{{user.name}}</option>
|
||||
* </select>
|
||||
* user={{currentUser.name}}<br/>
|
||||
* password={{currentUser.password}}<br/>
|
||||
* </div>
|
||||
*
|
||||
* @scenario
|
||||
* it('should retrieve object by index', function(){
|
||||
* expect(binding('currentUser.password')).toEqual('guest');
|
||||
* select('currentUser').option('2');
|
||||
* expect(binding('currentUser.password')).toEqual('abc');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
function DemoCntl(){
|
||||
this.users = [
|
||||
{name:'guest', password:'guest'},
|
||||
{name:'user', password:'123'},
|
||||
{name:'admin', password:'abc'}
|
||||
];
|
||||
}
|
||||
</script>
|
||||
<div ng:controller="DemoCntl">
|
||||
User:
|
||||
<select name="currentUser" ng:format="index:users">
|
||||
<option ng:repeat="user in users" value="{{$index}}">{{user.name}}</option>
|
||||
</select>
|
||||
<select name="currentUser" ng:format="index:users">
|
||||
<option ng:repeat="user in users" value="{{$index}}">{{user.name}}</option>
|
||||
</select>
|
||||
user={{currentUser.name}}<br/>
|
||||
password={{currentUser.password}}<br/>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should retrieve object by index', function(){
|
||||
expect(binding('currentUser.password')).toEqual('guest');
|
||||
select('currentUser').option('2');
|
||||
expect(binding('currentUser.password')).toEqual('abc');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularFormatter.index = formatter(
|
||||
function(object, array){
|
||||
|
|
|
|||
223
src/services.js
223
src/services.js
|
|
@ -22,8 +22,19 @@ function angularServiceInject(name, fn, inject, eager) {
|
|||
* suffer from window globality.
|
||||
*
|
||||
* @example
|
||||
<<<<<<< HEAD
|
||||
<input ng:init="$window = $service('$window'); greeting='Hello World!'" type="text" name="greeting" />
|
||||
<button ng:click="$window.alert(greeting)">ALERT</button>
|
||||
=======
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<input ng:init="greeting='Hello World!'" type="text" name="greeting" />
|
||||
<button ng:click="$window.alert(greeting)">ALERT</button>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
>>>>>>> changed the documentation @example to use <doc:example>
|
||||
*/
|
||||
angularServiceInject("$window", bind(window, identity, window), [], EAGER);
|
||||
|
||||
|
|
@ -63,10 +74,16 @@ angularServiceInject("$document", function(window){
|
|||
* Notice that using browser's forward/back buttons changes the $location.
|
||||
*
|
||||
* @example
|
||||
<a href="#">clear hash</a> |
|
||||
<a href="#myPath?name=misko">test hash</a><br/>
|
||||
<input type='text' name="$location.hash"/>
|
||||
<pre>$location = {{$location}}</pre>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<a href="#">clear hash</a> |
|
||||
<a href="#myPath?name=misko">test hash</a><br/>
|
||||
<input type='text' name="$location.hash"/>
|
||||
<pre>$location = {{$location}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularServiceInject("$location", function($browser) {
|
||||
var scope = this,
|
||||
|
|
@ -98,9 +115,15 @@ angularServiceInject("$location", function($browser) {
|
|||
* Browser is updated at the end of $eval()
|
||||
*
|
||||
* @example
|
||||
* scope.$location.update('http://www.angularjs.org/path#hash?search=x');
|
||||
* scope.$location.update({host: 'www.google.com', protocol: 'https'});
|
||||
* scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
scope.$location.update('http://www.angularjs.org/path#hash?search=x');
|
||||
scope.$location.update({host: 'www.google.com', protocol: 'https'});
|
||||
scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}});
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
* @param {(string|Object)} href Full href as a string or object with properties
|
||||
*/
|
||||
|
|
@ -133,14 +156,18 @@ angularServiceInject("$location", function($browser) {
|
|||
* @see update()
|
||||
*
|
||||
* @example
|
||||
* scope.$location.updateHash('/hp')
|
||||
* ==> update({hashPath: '/hp'})
|
||||
*
|
||||
* scope.$location.updateHash({a: true, b: 'val'})
|
||||
* ==> update({hashSearch: {a: true, b: 'val'}})
|
||||
*
|
||||
* scope.$location.updateHash('/hp', {a: true})
|
||||
* ==> update({hashPath: '/hp', hashSearch: {a: true}})
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
scope.$location.updateHash('/hp')
|
||||
==> update({hashPath: '/hp'})
|
||||
scope.$location.updateHash({a: true, b: 'val'})
|
||||
==> update({hashSearch: {a: true, b: 'val'}})
|
||||
scope.$location.updateHash('/hp', {a: true})
|
||||
==> update({hashPath: '/hp', hashSearch: {a: true}})
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
* @param {(string|Object)} path A hashPath or hashSearch object
|
||||
* @param {Object=} search A hashSearch object
|
||||
|
|
@ -176,7 +203,9 @@ angularServiceInject("$location", function($browser) {
|
|||
* - everything else
|
||||
*
|
||||
* @example
|
||||
* scope.$location.href = 'http://www.angularjs.org/path#a/b'
|
||||
* <pre>
|
||||
* scope.$location.href = 'http://www.angularjs.org/path#a/b'
|
||||
* </pre>
|
||||
* immediately after this call, other properties are still the old ones...
|
||||
*
|
||||
* This method checks the changes and update location to the consistent state
|
||||
|
|
@ -298,13 +327,19 @@ angularServiceInject("$location", function($browser) {
|
|||
* The main purpose of this service is to simplify debugging and troubleshooting.
|
||||
*
|
||||
* @example
|
||||
<p>Reload this page with open console, enter text and hit the log button...</p>
|
||||
Message:
|
||||
<input type="text" name="message" value="Hello World!"/>
|
||||
<button ng:click="$log.log(message)">log</button>
|
||||
<button ng:click="$log.warn(message)">warn</button>
|
||||
<button ng:click="$log.info(message)">info</button>
|
||||
<button ng:click="$log.error(message)">error</button>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<p>Reload this page with open console, enter text and hit the log button...</p>
|
||||
Message:
|
||||
<input type="text" name="message" value="Hello World!"/>
|
||||
<button ng:click="$log.log(message)">log</button>
|
||||
<button ng:click="$log.warn(message)">warn</button>
|
||||
<button ng:click="$log.info(message)">info</button>
|
||||
<button ng:click="$log.error(message)">error</button>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
var $logFactory; //reference to be used only in tests
|
||||
angularServiceInject("$log", $logFactory = function($window){
|
||||
|
|
@ -622,42 +657,46 @@ function switchRouteMatcher(on, when, dstName) {
|
|||
* widget.
|
||||
*
|
||||
* @example
|
||||
<p>
|
||||
This example shows how changing the URL hash causes the <tt>$route</tt>
|
||||
to match a route against the URL, and the <tt>[[ng:include]]</tt> pulls in the partial.
|
||||
Try changing the URL in the input box to see changes.
|
||||
</p>
|
||||
This example shows how changing the URL hash causes the <tt>$route</tt>
|
||||
to match a route against the URL, and the <tt>[[ng:include]]</tt> pulls in the partial.
|
||||
Try changing the URL in the input box to see changes.
|
||||
|
||||
<script>
|
||||
angular.service('myApp', function($route) {
|
||||
$route.when('/Book/:bookId', {template:'rsrc/book.html', controller:BookCntl});
|
||||
$route.when('/Book/:bookId/ch/:chapterId', {template:'rsrc/chapter.html', controller:ChapterCntl});
|
||||
$route.onChange(function() {
|
||||
$route.current.scope.params = $route.current.params;
|
||||
});
|
||||
}, {$inject: ['$route']});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
angular.service('myApp', function($route) {
|
||||
$route.when('/Book/:bookId', {template:'rsrc/book.html', controller:BookCntl});
|
||||
$route.when('/Book/:bookId/ch/:chapterId', {template:'rsrc/chapter.html', controller:ChapterCntl});
|
||||
$route.onChange(function() {
|
||||
$route.current.scope.params = $route.current.params;
|
||||
});
|
||||
}, {$inject: ['$route']});
|
||||
|
||||
function BookCntl() {
|
||||
this.name = "BookCntl";
|
||||
}
|
||||
function BookCntl() {
|
||||
this.name = "BookCntl";
|
||||
}
|
||||
|
||||
function ChapterCntl() {
|
||||
this.name = "ChapterCntl";
|
||||
}
|
||||
</script>
|
||||
function ChapterCntl() {
|
||||
this.name = "ChapterCntl";
|
||||
}
|
||||
</script>
|
||||
|
||||
Chose:
|
||||
<a href="#/Book/Moby">Moby</a> |
|
||||
<a href="#/Book/Moby/ch/1">Moby: Ch1</a> |
|
||||
<a href="#/Book/Gatsby">Gatsby</a> |
|
||||
<a href="#/Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a><br/>
|
||||
<input type="text" name="$location.hashPath" size="80" />
|
||||
<pre>$location={{$location}}</pre>
|
||||
<pre>$route.current.template={{$route.current.template}}</pre>
|
||||
<pre>$route.current.params={{$route.current.params}}</pre>
|
||||
<pre>$route.current.scope.name={{$route.current.scope.name}}</pre>
|
||||
<hr/>
|
||||
<ng:include src="$route.current.template" scope="$route.current.scope"/>
|
||||
Chose:
|
||||
<a href="#/Book/Moby">Moby</a> |
|
||||
<a href="#/Book/Moby/ch/1">Moby: Ch1</a> |
|
||||
<a href="#/Book/Gatsby">Gatsby</a> |
|
||||
<a href="#/Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a><br/>
|
||||
<input type="text" name="$location.hashPath" size="80" />
|
||||
<pre>$location={{$location}}</pre>
|
||||
<pre>$route.current.template={{$route.current.template}}</pre>
|
||||
<pre>$route.current.params={{$route.current.params}}</pre>
|
||||
<pre>$route.current.scope.name={{$route.current.scope.name}}</pre>
|
||||
<hr/>
|
||||
<ng:include src="$route.current.template" scope="$route.current.scope"/>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularServiceInject('$route', function(location) {
|
||||
var routes = {},
|
||||
|
|
@ -1122,43 +1161,49 @@ angularServiceInject('$xhr.cache', function($xhr, $defer, $log){
|
|||
* @returns {Object} A resource "class".
|
||||
*
|
||||
* @example
|
||||
<script>
|
||||
function BuzzController($resource) {
|
||||
this.Activity = $resource(
|
||||
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
|
||||
{alt:'json', callback:'JSON_CALLBACK'},
|
||||
{get:{method:'JSON', params:{visibility:'@self'}}, replies: {method:'JSON', params:{visibility:'@self', comments:'@comments'}}}
|
||||
);
|
||||
}
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
function BuzzController($resource) {
|
||||
this.Activity = $resource(
|
||||
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
|
||||
{alt:'json', callback:'JSON_CALLBACK'},
|
||||
{get:{method:'JSON', params:{visibility:'@self'}}, replies: {method:'JSON', params:{visibility:'@self', comments:'@comments'}}}
|
||||
);
|
||||
}
|
||||
|
||||
BuzzController.prototype = {
|
||||
fetch: function() {
|
||||
this.activities = this.Activity.get({userId:this.userId});
|
||||
},
|
||||
expandReplies: function(activity) {
|
||||
activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
|
||||
}
|
||||
};
|
||||
BuzzController.$inject = ['$resource'];
|
||||
</script>
|
||||
BuzzController.prototype = {
|
||||
fetch: function() {
|
||||
this.activities = this.Activity.get({userId:this.userId});
|
||||
},
|
||||
expandReplies: function(activity) {
|
||||
activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
|
||||
}
|
||||
};
|
||||
BuzzController.$inject = ['$resource'];
|
||||
</script>
|
||||
|
||||
<div ng:controller="BuzzController">
|
||||
<input name="userId" value="googlebuzz"/>
|
||||
<button ng:click="fetch()">fetch</button>
|
||||
<hr/>
|
||||
<div ng:repeat="item in activities.data.items">
|
||||
<h1 style="font-size: 15px;">
|
||||
<img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
|
||||
<a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
|
||||
<a href ng:click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
|
||||
</h1>
|
||||
{{item.object.content | html}}
|
||||
<div ng:repeat="reply in item.replies.data.items" style="margin-left: 20px;">
|
||||
<img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
|
||||
<a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
|
||||
<div ng:controller="BuzzController">
|
||||
<input name="userId" value="googlebuzz"/>
|
||||
<button ng:click="fetch()">fetch</button>
|
||||
<hr/>
|
||||
<div ng:repeat="item in activities.data.items">
|
||||
<h1 style="font-size: 15px;">
|
||||
<img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
|
||||
<a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
|
||||
<a href ng:click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
|
||||
</h1>
|
||||
{{item.object.content | html}}
|
||||
<div ng:repeat="reply in item.replies.data.items" style="margin-left: 20px;">
|
||||
<img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
|
||||
<a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularServiceInject('$resource', function($xhr){
|
||||
var resource = new ResourceFactory($xhr);
|
||||
|
|
|
|||
|
|
@ -14,24 +14,27 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* <script> function Cntl(){
|
||||
* this.ssnRegExp = /^\d\d\d-\d\d-\d\d\d\d$/;
|
||||
* }
|
||||
* </script>
|
||||
* Enter valid SSN:
|
||||
* <div ng:controller="Cntl">
|
||||
* <input name="ssn" value="123-45-6789" ng:validate="regexp:ssnRegExp" >
|
||||
* </div>
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate non ssn', function(){
|
||||
* var textBox = element('.doc-example :input');
|
||||
* expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* expect(textBox.val()).toEqual('123-45-6789');
|
||||
*
|
||||
* input('ssn').enter('123-45-67890');
|
||||
* expect(textBox.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script> function Cntl(){
|
||||
this.ssnRegExp = /^\d\d\d-\d\d-\d\d\d\d$/;
|
||||
}
|
||||
</script>
|
||||
Enter valid SSN:
|
||||
<div ng:controller="Cntl">
|
||||
<input name="ssn" value="123-45-6789" ng:validate="regexp:ssnRegExp" >
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate non ssn', function(){
|
||||
var textBox = element('.doc-example :input');
|
||||
expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
expect(textBox.val()).toEqual('123-45-6789');
|
||||
input('ssn').enter('123-45-67890');
|
||||
expect(textBox.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
'regexp': function(value, regexp, msg) {
|
||||
|
|
@ -57,28 +60,29 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter number: <input name="n1" ng:validate="number" > <br>
|
||||
* Enter number greater than 10: <input name="n2" ng:validate="number:10" > <br>
|
||||
* Enter number between 100 and 200: <input name="n3" ng:validate="number:100:200" > <br>
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate number', function(){
|
||||
* var n1 = element('.doc-example :input[name=n1]');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n1').enter('1.x');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n2 = element('.doc-example :input[name=n2]');
|
||||
* expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n2').enter('9');
|
||||
* expect(n2.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n3 = element('.doc-example :input[name=n3]');
|
||||
* expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n3').enter('201');
|
||||
* expect(n3.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter number: <input name="n1" ng:validate="number" > <br>
|
||||
Enter number greater than 10: <input name="n2" ng:validate="number:10" > <br>
|
||||
Enter number between 100 and 200: <input name="n3" ng:validate="number:100:200" > <br>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate number', function(){
|
||||
var n1 = element('.doc-example :input[name=n1]');
|
||||
expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('n1').enter('1.x');
|
||||
expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
var n2 = element('.doc-example :input[name=n2]');
|
||||
expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('n2').enter('9');
|
||||
expect(n2.attr('className')).toMatch(/ng-validation-error/);
|
||||
var n3 = element('.doc-example :input[name=n3]');
|
||||
expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('n3').enter('201');
|
||||
expect(n3.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
'number': function(value, min, max) {
|
||||
|
|
@ -110,28 +114,29 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter integer: <input name="n1" ng:validate="integer" > <br>
|
||||
* Enter integer equal or greater than 10: <input name="n2" ng:validate="integer:10" > <br>
|
||||
* Enter integer between 100 and 200 (inclusive): <input name="n3" ng:validate="integer:100:200" > <br>
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate integer', function(){
|
||||
* var n1 = element('.doc-example :input[name=n1]');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n1').enter('1.1');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n2 = element('.doc-example :input[name=n2]');
|
||||
* expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n2').enter('10.1');
|
||||
* expect(n2.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n3 = element('.doc-example :input[name=n3]');
|
||||
* expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n3').enter('100.1');
|
||||
* expect(n3.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter integer: <input name="n1" ng:validate="integer" > <br>
|
||||
Enter integer equal or greater than 10: <input name="n2" ng:validate="integer:10" > <br>
|
||||
Enter integer between 100 and 200 (inclusive): <input name="n3" ng:validate="integer:100:200" > <br>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate integer', function(){
|
||||
var n1 = element('.doc-example :input[name=n1]');
|
||||
expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('n1').enter('1.1');
|
||||
expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
var n2 = element('.doc-example :input[name=n2]');
|
||||
expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('n2').enter('10.1');
|
||||
expect(n2.attr('className')).toMatch(/ng-validation-error/);
|
||||
var n3 = element('.doc-example :input[name=n3]');
|
||||
expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('n3').enter('100.1');
|
||||
expect(n3.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
'integer': function(value, min, max) {
|
||||
var numberError = angularValidator['number'](value, min, max);
|
||||
|
|
@ -154,16 +159,20 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid date:
|
||||
* <input name="text" value="1/1/2009" ng:validate="date" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate date', function(){
|
||||
* var n1 = element('.doc-example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('123/123/123');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter valid date:
|
||||
<input name="text" value="1/1/2009" ng:validate="date" >
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate date', function(){
|
||||
var n1 = element('.doc-example :input');
|
||||
expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('text').enter('123/123/123');
|
||||
expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
'date': function(value) {
|
||||
|
|
@ -187,16 +196,20 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid email:
|
||||
* <input name="text" ng:validate="email" value="me@example.com">
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate email', function(){
|
||||
* var n1 = element('.doc-example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('a@b.c');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter valid email:
|
||||
<input name="text" ng:validate="email" value="me@example.com">
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate email', function(){
|
||||
var n1 = element('.doc-example :input');
|
||||
expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('text').enter('a@b.c');
|
||||
expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
'email': function(value) {
|
||||
|
|
@ -217,16 +230,20 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid phone number:
|
||||
* <input name="text" value="1(234)567-8901" ng:validate="phone" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate phone', function(){
|
||||
* var n1 = element('.doc-example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('+12345678');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter valid phone number:
|
||||
<input name="text" value="1(234)567-8901" ng:validate="phone" >
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate phone', function(){
|
||||
var n1 = element('.doc-example :input');
|
||||
expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('text').enter('+12345678');
|
||||
expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
'phone': function(value) {
|
||||
|
|
@ -250,16 +267,20 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid phone number:
|
||||
* <input name="text" value="http://example.com/abc.html" size="40" ng:validate="url" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate url', function(){
|
||||
* var n1 = element('.doc-example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('abc://server/path');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter valid phone number:
|
||||
<input name="text" value="http://example.com/abc.html" size="40" ng:validate="url" >
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate url', function(){
|
||||
var n1 = element('.doc-example :input');
|
||||
expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('text').enter('abc://server/path');
|
||||
expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
'url': function(value) {
|
||||
|
|
@ -280,17 +301,21 @@ extend(angularValidator, {
|
|||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* <textarea name="json" cols="60" rows="5" ng:validate="json">
|
||||
* {name:'abc'}
|
||||
* </textarea>
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate json', function(){
|
||||
* var n1 = element('.doc-example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('json').enter('{name}');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<textarea name="json" cols="60" rows="5" ng:validate="json">
|
||||
{name:'abc'}
|
||||
</textarea>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should invalidate json', function(){
|
||||
var n1 = element('.doc-example :input');
|
||||
expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('json').enter('{name}');
|
||||
expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
'json': function(value) {
|
||||
|
|
@ -338,35 +363,35 @@ extend(angularValidator, {
|
|||
* @css ng-input-indicator-wait, ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* <script>
|
||||
* function MyCntl(){
|
||||
* this.myValidator = function (inputToValidate, validationDone) {
|
||||
* setTimeout(function(){
|
||||
* validationDone(inputToValidate.length % 2);
|
||||
* }, 500);
|
||||
* }
|
||||
* }
|
||||
* </script>
|
||||
* This input is validated asynchronously:
|
||||
* <div ng:controller="MyCntl">
|
||||
* <input name="text" ng:validate="asynchronous:myValidator">
|
||||
* </div>
|
||||
*
|
||||
* @scenario
|
||||
* it('should change color in delayed way', function(){
|
||||
* var textBox = element('.doc-example :input');
|
||||
* expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
|
||||
* expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
*
|
||||
* input('text').enter('X');
|
||||
* expect(textBox.attr('className')).toMatch(/ng-input-indicator-wait/);
|
||||
*
|
||||
* pause(.6);
|
||||
*
|
||||
* expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
|
||||
* expect(textBox.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
function MyCntl(){
|
||||
this.myValidator = function (inputToValidate, validationDone) {
|
||||
setTimeout(function(){
|
||||
validationDone(inputToValidate.length % 2);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
This input is validated asynchronously:
|
||||
<div ng:controller="MyCntl">
|
||||
<input name="text" ng:validate="asynchronous:myValidator">
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should change color in delayed way', function(){
|
||||
var textBox = element('.doc-example :input');
|
||||
expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
|
||||
expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
input('text').enter('X');
|
||||
expect(textBox.attr('className')).toMatch(/ng-input-indicator-wait/);
|
||||
pause(.6);
|
||||
expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
|
||||
expect(textBox.attr('className')).toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*
|
||||
*/
|
||||
/*
|
||||
|
|
|
|||
554
src/widgets.js
554
src/widgets.js
|
|
@ -19,117 +19,122 @@
|
|||
* </select>
|
||||
*
|
||||
* @example
|
||||
<table style="font-size:.9em;">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Format</th>
|
||||
<th>HTML</th>
|
||||
<th>UI</th>
|
||||
<th ng:non-bindable>{{input#}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>text</th>
|
||||
<td>String</td>
|
||||
<td><tt><input type="text" name="input1"></tt></td>
|
||||
<td><input type="text" name="input1" size="4"></td>
|
||||
<td><tt>{{input1|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>textarea</th>
|
||||
<td>String</td>
|
||||
<td><tt><textarea name="input2"></textarea></tt></td>
|
||||
<td><textarea name="input2" cols='6'></textarea></td>
|
||||
<td><tt>{{input2|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>radio</th>
|
||||
<td>String</td>
|
||||
<td><tt>
|
||||
<input type="radio" name="input3" value="A"><br>
|
||||
<input type="radio" name="input3" value="B">
|
||||
</tt></td>
|
||||
<td>
|
||||
<input type="radio" name="input3" value="A">
|
||||
<input type="radio" name="input3" value="B">
|
||||
</td>
|
||||
<td><tt>{{input3|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>checkbox</th>
|
||||
<td>Boolean</td>
|
||||
<td><tt><input type="checkbox" name="input4" value="checked"></tt></td>
|
||||
<td><input type="checkbox" name="input4" value="checked"></td>
|
||||
<td><tt>{{input4|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pulldown</th>
|
||||
<td>String</td>
|
||||
<td><tt>
|
||||
<select name="input5"><br>
|
||||
<option value="c">C</option><br>
|
||||
<option value="d">D</option><br>
|
||||
</select><br>
|
||||
</tt></td>
|
||||
<td>
|
||||
<select name="input5">
|
||||
<option value="c">C</option>
|
||||
<option value="d">D</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><tt>{{input5|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>multiselect</th>
|
||||
<td>Array</td>
|
||||
<td><tt>
|
||||
<select name="input6" multiple size="4"><br>
|
||||
<option value="e">E</option><br>
|
||||
<option value="f">F</option><br>
|
||||
</select><br>
|
||||
</tt></td>
|
||||
<td>
|
||||
<select name="input6" multiple size="4">
|
||||
<option value="e">E</option>
|
||||
<option value="f">F</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><tt>{{input6|json}}</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<table style="font-size:.9em;">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Format</th>
|
||||
<th>HTML</th>
|
||||
<th>UI</th>
|
||||
<th ng:non-bindable>{{input#}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>text</th>
|
||||
<td>String</td>
|
||||
<td><tt><input type="text" name="input1"></tt></td>
|
||||
<td><input type="text" name="input1" size="4"></td>
|
||||
<td><tt>{{input1|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>textarea</th>
|
||||
<td>String</td>
|
||||
<td><tt><textarea name="input2"></textarea></tt></td>
|
||||
<td><textarea name="input2" cols='6'></textarea></td>
|
||||
<td><tt>{{input2|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>radio</th>
|
||||
<td>String</td>
|
||||
<td><tt>
|
||||
<input type="radio" name="input3" value="A"><br>
|
||||
<input type="radio" name="input3" value="B">
|
||||
</tt></td>
|
||||
<td>
|
||||
<input type="radio" name="input3" value="A">
|
||||
<input type="radio" name="input3" value="B">
|
||||
</td>
|
||||
<td><tt>{{input3|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>checkbox</th>
|
||||
<td>Boolean</td>
|
||||
<td><tt><input type="checkbox" name="input4" value="checked"></tt></td>
|
||||
<td><input type="checkbox" name="input4" value="checked"></td>
|
||||
<td><tt>{{input4|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pulldown</th>
|
||||
<td>String</td>
|
||||
<td><tt>
|
||||
<select name="input5"><br>
|
||||
<option value="c">C</option><br>
|
||||
<option value="d">D</option><br>
|
||||
</select><br>
|
||||
</tt></td>
|
||||
<td>
|
||||
<select name="input5">
|
||||
<option value="c">C</option>
|
||||
<option value="d">D</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><tt>{{input5|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>multiselect</th>
|
||||
<td>Array</td>
|
||||
<td><tt>
|
||||
<select name="input6" multiple size="4"><br>
|
||||
<option value="e">E</option><br>
|
||||
<option value="f">F</option><br>
|
||||
</select><br>
|
||||
</tt></td>
|
||||
<td>
|
||||
<select name="input6" multiple size="4">
|
||||
<option value="e">E</option>
|
||||
<option value="f">F</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><tt>{{input6|json}}</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
|
||||
* @scenario
|
||||
* it('should exercise text', function(){
|
||||
* input('input1').enter('Carlos');
|
||||
* expect(binding('input1')).toEqual('"Carlos"');
|
||||
* });
|
||||
* it('should exercise textarea', function(){
|
||||
* input('input2').enter('Carlos');
|
||||
* expect(binding('input2')).toEqual('"Carlos"');
|
||||
* });
|
||||
* it('should exercise radio', function(){
|
||||
* expect(binding('input3')).toEqual('null');
|
||||
* input('input3').select('A');
|
||||
* expect(binding('input3')).toEqual('"A"');
|
||||
* input('input3').select('B');
|
||||
* expect(binding('input3')).toEqual('"B"');
|
||||
* });
|
||||
* it('should exercise checkbox', function(){
|
||||
* expect(binding('input4')).toEqual('false');
|
||||
* input('input4').check();
|
||||
* expect(binding('input4')).toEqual('true');
|
||||
* });
|
||||
* it('should exercise pulldown', function(){
|
||||
* expect(binding('input5')).toEqual('"c"');
|
||||
* select('input5').option('d');
|
||||
* expect(binding('input5')).toEqual('"d"');
|
||||
* });
|
||||
* it('should exercise multiselect', function(){
|
||||
* expect(binding('input6')).toEqual('[]');
|
||||
* select('input6').options('e');
|
||||
* expect(binding('input6')).toEqual('["e"]');
|
||||
* select('input6').options('e', 'f');
|
||||
* expect(binding('input6')).toEqual('["e","f"]');
|
||||
* });
|
||||
it('should exercise text', function(){
|
||||
input('input1').enter('Carlos');
|
||||
expect(binding('input1')).toEqual('"Carlos"');
|
||||
});
|
||||
it('should exercise textarea', function(){
|
||||
input('input2').enter('Carlos');
|
||||
expect(binding('input2')).toEqual('"Carlos"');
|
||||
});
|
||||
it('should exercise radio', function(){
|
||||
expect(binding('input3')).toEqual('null');
|
||||
input('input3').select('A');
|
||||
expect(binding('input3')).toEqual('"A"');
|
||||
input('input3').select('B');
|
||||
expect(binding('input3')).toEqual('"B"');
|
||||
});
|
||||
it('should exercise checkbox', function(){
|
||||
expect(binding('input4')).toEqual('false');
|
||||
input('input4').check();
|
||||
expect(binding('input4')).toEqual('true');
|
||||
});
|
||||
it('should exercise pulldown', function(){
|
||||
expect(binding('input5')).toEqual('"c"');
|
||||
select('input5').option('d');
|
||||
expect(binding('input5')).toEqual('"d"');
|
||||
});
|
||||
it('should exercise multiselect', function(){
|
||||
expect(binding('input6')).toEqual('[]');
|
||||
select('input6').options('e');
|
||||
expect(binding('input6')).toEqual('["e"]');
|
||||
select('input6').options('e', 'f');
|
||||
expect(binding('input6')).toEqual('["e","f"]');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
|
||||
function modelAccessor(scope, element) {
|
||||
|
|
@ -193,26 +198,29 @@ function compileFormatter(expr) {
|
|||
* @element INPUT
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* This example shows how the input element becomes red when it contains invalid input. Correct
|
||||
* the input to make the error disappear.
|
||||
*
|
||||
* @example
|
||||
I don't validate:
|
||||
<input type="text" name="value" value="NotANumber"><br/>
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
I don't validate:
|
||||
<input type="text" name="value" value="NotANumber"><br/>
|
||||
|
||||
I need an integer or nothing:
|
||||
<input type="text" name="value" ng:validate="integer"><br/>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:validate', function(){
|
||||
expect(element('.doc-example-live :input:last').attr('className')).
|
||||
toMatch(/ng-validation-error/);
|
||||
I need an integer or nothing:
|
||||
<input type="text" name="value" ng:validate="integer"><br/>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:validate', function(){
|
||||
expect(element('.doc-example-live :input:last').attr('className')).
|
||||
toMatch(/ng-validation-error/);
|
||||
|
||||
input('value').enter('123');
|
||||
expect(element('.doc-example-live :input:last').attr('className')).
|
||||
not().toMatch(/ng-validation-error/);
|
||||
});
|
||||
input('value').enter('123');
|
||||
expect(element('.doc-example-live :input:last').attr('className')).
|
||||
not().toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
/**
|
||||
* @workInProgress
|
||||
|
|
@ -226,19 +234,22 @@ function compileFormatter(expr) {
|
|||
* @element INPUT
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* This example shows how the input element becomes red when it contains invalid input. Correct
|
||||
* the input to make the error disappear.
|
||||
*
|
||||
* @example
|
||||
I cannot be blank: <input type="text" name="value" ng:required><br/>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:required', function(){
|
||||
expect(element('.doc-example-live :input').attr('className')).toMatch(/ng-validation-error/);
|
||||
input('value').enter('123');
|
||||
expect(element('.doc-example-live :input').attr('className')).not().toMatch(/ng-validation-error/);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
I cannot be blank: <input type="text" name="value" ng:required><br/>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:required', function(){
|
||||
expect(element('.doc-example-live :input').attr('className')).toMatch(/ng-validation-error/);
|
||||
input('value').enter('123');
|
||||
expect(element('.doc-example-live :input').attr('className')).not().toMatch(/ng-validation-error/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
/**
|
||||
* @workInProgress
|
||||
|
|
@ -256,21 +267,24 @@ function compileFormatter(expr) {
|
|||
*
|
||||
* @element INPUT
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* This example shows how the user input is converted from a string and internally represented as an
|
||||
* array.
|
||||
*
|
||||
* @example
|
||||
Enter a comma separated list of items:
|
||||
<input type="text" name="list" ng:format="list" value="table, chairs, plate">
|
||||
<pre>list={{list}}</pre>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:format', function(){
|
||||
expect(binding('list')).toBe('list=["table","chairs","plate"]');
|
||||
input('list').enter(',,, a ,,,');
|
||||
expect(binding('list')).toBe('list=["a"]');
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Enter a comma separated list of items:
|
||||
<input type="text" name="list" ng:format="list" value="table, chairs, plate">
|
||||
<pre>list={{list}}</pre>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:format', function(){
|
||||
expect(binding('list')).toBe('list=["table","chairs","plate"]');
|
||||
input('list').enter(',,, a ,,,');
|
||||
expect(binding('list')).toBe('list=["a"]');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
function valueAccessor(scope, element) {
|
||||
var validatorName = element.attr('ng:validate') || NOOP,
|
||||
|
|
@ -453,28 +467,32 @@ function radioInit(model, view, element) {
|
|||
* @element INPUT
|
||||
* @param {expression} expression to execute.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
<div ng:init="checkboxCount=0; textCount=0"></div>
|
||||
<input type="text" name="text" ng:change="textCount = 1 + textCount">
|
||||
changeCount {{textCount}}<br/>
|
||||
<input type="checkbox" name="checkbox" ng:change="checkboxCount = 1 + checkboxCount">
|
||||
changeCount {{checkboxCount}}<br/>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:change', function(){
|
||||
expect(binding('textCount')).toBe('0');
|
||||
expect(binding('checkboxCount')).toBe('0');
|
||||
* @example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="checkboxCount=0; textCount=0"></div>
|
||||
<input type="text" name="text" ng:change="textCount = 1 + textCount">
|
||||
changeCount {{textCount}}<br/>
|
||||
<input type="checkbox" name="checkbox" ng:change="checkboxCount = 1 + checkboxCount">
|
||||
changeCount {{checkboxCount}}<br/>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:change', function(){
|
||||
expect(binding('textCount')).toBe('0');
|
||||
expect(binding('checkboxCount')).toBe('0');
|
||||
|
||||
using('.doc-example-live').input('text').enter('abc');
|
||||
expect(binding('textCount')).toBe('1');
|
||||
expect(binding('checkboxCount')).toBe('0');
|
||||
using('.doc-example-live').input('text').enter('abc');
|
||||
expect(binding('textCount')).toBe('1');
|
||||
expect(binding('checkboxCount')).toBe('0');
|
||||
|
||||
|
||||
using('.doc-example-live').input('checkbox').check();
|
||||
expect(binding('textCount')).toBe('1');
|
||||
expect(binding('checkboxCount')).toBe('1');
|
||||
});
|
||||
using('.doc-example-live').input('checkbox').check();
|
||||
expect(binding('textCount')).toBe('1');
|
||||
expect(binding('checkboxCount')).toBe('1');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
function inputWidget(events, modelAccessor, viewAccessor, initFn, textBox) {
|
||||
return injectService(['$updateView', '$defer'], function($updateView, $defer, element) {
|
||||
|
|
@ -594,27 +612,31 @@ angularWidget('option', function(){
|
|||
* @param {string=} onload Expression to evaluate when a new partial is loaded.
|
||||
*
|
||||
* @example
|
||||
* <select name="url">
|
||||
* <option value="angular.filter.date.html">date filter</option>
|
||||
* <option value="angular.filter.html.html">html filter</option>
|
||||
* <option value="">(blank)</option>
|
||||
* </select>
|
||||
* <tt>url = <a href="{{url}}">{{url}}</a></tt>
|
||||
* <hr/>
|
||||
* <ng:include src="url"></ng:include>
|
||||
*
|
||||
* @scenario
|
||||
* it('should load date filter', function(){
|
||||
* expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/);
|
||||
* });
|
||||
* it('should change to hmtl filter', function(){
|
||||
* select('url').option('angular.filter.html.html');
|
||||
* expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/);
|
||||
* });
|
||||
* it('should change to blank', function(){
|
||||
* select('url').option('(blank)');
|
||||
* expect(element('.doc-example ng\\:include').text()).toEqual('');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<select name="url">
|
||||
<option value="angular.filter.date.html">date filter</option>
|
||||
<option value="angular.filter.html.html">html filter</option>
|
||||
<option value="">(blank)</option>
|
||||
</select>
|
||||
<tt>url = <a href="{{url}}">{{url}}</a></tt>
|
||||
<hr/>
|
||||
<ng:include src="url"></ng:include>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should load date filter', function(){
|
||||
expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/);
|
||||
});
|
||||
it('should change to hmtl filter', function(){
|
||||
select('url').option('angular.filter.html.html');
|
||||
expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/);
|
||||
});
|
||||
it('should change to blank', function(){
|
||||
select('url').option('(blank)');
|
||||
expect(element('.doc-example ng\\:include').text()).toEqual('');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularWidget('ng:include', function(element){
|
||||
var compiler = this,
|
||||
|
|
@ -690,32 +712,36 @@ angularWidget('ng:include', function(element){
|
|||
* * `ng:switch-default`: the default case when no other casses match.
|
||||
*
|
||||
* @example
|
||||
<select name="switch">
|
||||
<option>settings</option>
|
||||
<option>home</option>
|
||||
<option>other</option>
|
||||
</select>
|
||||
<tt>switch={{switch}}</tt>
|
||||
</hr>
|
||||
<ng:switch on="switch" >
|
||||
<div ng:switch-when="settings">Settings Div</div>
|
||||
<span ng:switch-when="home">Home Span</span>
|
||||
<span ng:switch-default>default</span>
|
||||
</ng:switch>
|
||||
</code>
|
||||
*
|
||||
* @scenario
|
||||
* it('should start in settings', function(){
|
||||
* expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div');
|
||||
* });
|
||||
* it('should change to home', function(){
|
||||
* select('switch').option('home');
|
||||
* expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span');
|
||||
* });
|
||||
* it('should select deafault', function(){
|
||||
* select('switch').option('other');
|
||||
* expect(element('.doc-example ng\\:switch').text()).toEqual('default');
|
||||
* });
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<select name="switch">
|
||||
<option>settings</option>
|
||||
<option>home</option>
|
||||
<option>other</option>
|
||||
</select>
|
||||
<tt>switch={{switch}}</tt>
|
||||
</hr>
|
||||
<ng:switch on="switch" >
|
||||
<div ng:switch-when="settings">Settings Div</div>
|
||||
<span ng:switch-when="home">Home Span</span>
|
||||
<span ng:switch-default>default</span>
|
||||
</ng:switch>
|
||||
</code>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should start in settings', function(){
|
||||
expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div');
|
||||
});
|
||||
it('should change to home', function(){
|
||||
select('switch').option('home');
|
||||
expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span');
|
||||
});
|
||||
it('should select deafault', function(){
|
||||
select('switch').option('other');
|
||||
expect(element('.doc-example ng\\:switch').text()).toEqual('default');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
var ngSwitch = angularWidget('ng:switch', function (element){
|
||||
var compiler = this,
|
||||
|
|
@ -838,25 +864,29 @@ angularWidget('a', function() {
|
|||
*
|
||||
* For example: `(name, age) in {'adam':10, 'amalie':12}`.
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* This example initializes the scope to a list of names and
|
||||
* than uses `ng:repeat` to display every person.
|
||||
* @example
|
||||
<div ng:init="friends = [{name:'John', age:25}, {name:'Mary', age:28}]">
|
||||
I have {{friends.length}} friends. They are:
|
||||
<ul>
|
||||
<li ng:repeat="friend in friends">
|
||||
[{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
* @scenario
|
||||
it('should check ng:repeat', function(){
|
||||
var r = using('.doc-example-live').repeater('ul li');
|
||||
expect(r.count()).toBe(2);
|
||||
expect(r.row(0)).toEqual(["1","John","25"]);
|
||||
expect(r.row(1)).toEqual(["2","Mary","28"]);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div ng:init="friends = [{name:'John', age:25}, {name:'Mary', age:28}]">
|
||||
I have {{friends.length}} friends. They are:
|
||||
<ul>
|
||||
<li ng:repeat="friend in friends">
|
||||
[{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:repeat', function(){
|
||||
var r = using('.doc-example-live').repeater('ul li');
|
||||
expect(r.count()).toBe(2);
|
||||
expect(r.row(0)).toEqual(["1","John","25"]);
|
||||
expect(r.row(1)).toEqual(["2","Mary","28"]);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularWidget("@ng:repeat", function(expression, element){
|
||||
element.removeAttr('ng:repeat');
|
||||
|
|
@ -946,20 +976,24 @@ angularWidget("@ng:repeat", function(expression, element){
|
|||
*
|
||||
* @element ANY
|
||||
*
|
||||
* @exampleDescription
|
||||
* @example
|
||||
* In this example there are two location where a siple binding (`{{}}`) is present, but the one
|
||||
* wrapped in `ng:non-bindable` is left alone.
|
||||
*
|
||||
* @example
|
||||
<div>Normal: {{1 + 2}}</div>
|
||||
<div ng:non-bindable>Ignored: {{1 + 2}}</div>
|
||||
*
|
||||
* @scenario
|
||||
it('should check ng:non-bindable', function(){
|
||||
expect(using('.doc-example-live').binding('1 + 2')).toBe('3');
|
||||
expect(using('.doc-example-live').element('div:last').text()).
|
||||
toMatch(/1 \+ 2/);
|
||||
});
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<div>Normal: {{1 + 2}}</div>
|
||||
<div ng:non-bindable>Ignored: {{1 + 2}}</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should check ng:non-bindable', function(){
|
||||
expect(using('.doc-example-live').binding('1 + 2')).toBe('3');
|
||||
expect(using('.doc-example-live').element('div:last').text()).
|
||||
toMatch(/1 \+ 2/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularWidget("@ng:non-bindable", noop);
|
||||
|
||||
|
|
@ -989,26 +1023,30 @@ angularWidget("@ng:non-bindable", noop);
|
|||
* - doesn't require `$route` service to be available on the root scope
|
||||
*
|
||||
*
|
||||
* # Example
|
||||
* Because of the nature of this widget, we can't include the usual live example for it. Instead
|
||||
* following is a code snippet showing the typical usage:
|
||||
*
|
||||
<pre>
|
||||
<script>
|
||||
angular.service('routeConfig', function($route) {
|
||||
$route.when('/foo', {controller: MyCtrl, template: 'foo.html'});
|
||||
$route.when('/bar', {controller: MyCtrl, template: 'bar.html'});
|
||||
}, {$inject: ['$route'], $eager: true});
|
||||
* @example
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
function MyCtrl($route) {
|
||||
$route.when('/overview', {controller: OverviewCtrl, template: 'guide.overview.html'});
|
||||
$route.when('/bootstrap', {controller: BootstrapCtrl, template: 'guide.bootstrap.html'});
|
||||
console.log(window.$route = $route);
|
||||
};
|
||||
MyCtrl.$inject = ['$route'];
|
||||
|
||||
function MyCtrl() {};
|
||||
</script>
|
||||
<div>
|
||||
<a href="#/foo">foo</a> | <a href="#/bar">bar</a> | <a href="#/undefined">undefined</a><br/>
|
||||
The view is included below:
|
||||
<hr/>
|
||||
<ng:view></ng:view>
|
||||
</div>
|
||||
</pre>
|
||||
function BootstrapCtrl(){}
|
||||
function OverviewCtrl(){}
|
||||
</script>
|
||||
<div ng:controller="MyCtrl">
|
||||
<a href="#/overview">overview</a> | <a href="#/bootstrap">bootstrap</a> | <a href="#/undefined">undefined</a><br/>
|
||||
The view is included below:
|
||||
<hr/>
|
||||
<ng:view></ng:view>
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
*/
|
||||
angularWidget('ng:view', function(element) {
|
||||
var compiler = this;
|
||||
|
|
|
|||
Loading…
Reference in a new issue