aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--example/temp.html86
-rw-r--r--scenario/location.html15
-rw-r--r--src/Angular.js6
-rw-r--r--src/angular-bootstrap.js6
-rw-r--r--src/formatters.js1
-rw-r--r--src/jqLite.js2
-rw-r--r--src/services.js95
-rw-r--r--test/servicesSpec.js19
8 files changed, 165 insertions, 65 deletions
diff --git a/example/temp.html b/example/temp.html
index f21d3f5c..b238c185 100644
--- a/example/temp.html
+++ b/example/temp.html
@@ -1,15 +1,85 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
+<html xmlns:ng="http://angularjs.org">
<head>
- <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript"
src="../src/angular-bootstrap.js#autobind"></script>
</head>
<body ng:init="$window.$root = this">
- <div ng:click="$window.alert('outter')">
- outter
- <div ng:click="$window.alert('inner')">inner</div>
- <a href="#ERROR" ng:click="$window.alert('link')">link</a>
- </div>
+
+<script>
+function TicTacToeCntl(){
+ this.cellStyle= {
+ 'height': '20px',
+ 'width': '20px',
+ 'border': '1px solid black',
+ 'text-align': 'center',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer'
+ };
+ this.reset();
+ this.$watch('$location.hashPath', this.setMemento);
+ this.$onEval(function(){
+ this.$location.hashPath = this.getMemento();
+ });
+}
+TicTacToeCntl.prototype = {
+ dropPiece: function(row, col) {
+ if (!this.winner && !this.board[row][col]) {
+ this.board[row][col] = this.nextMove;
+ this.nextMove = this.nextMove == 'X' ? 'O' : 'X';
+ this.grade();
+ }
+ },
+ reset: function(){
+ this.board = [
+ ['', '', ''],
+ ['', '', ''],
+ ['', '', '']
+ ];
+ this.nextMove = 'X';
+ this.winner = '';
+ },
+ grade: function(){
+ var b = this.board;
+ this.winner =
+ row(0) || row(1) || row(2) ||
+ col(0) || col(1) || col(2) ||
+ diagonal(-1) || diagonal(1);
+ function row(r) { return same(b[r][0], b[r][1], b[r][2]);}
+ function col(c) { return same(b[0][c], b[1][c], b[2][c]);}
+ function diagonal(i) { return same(b[0][1-i], b[1][1], b[2][1+i]);}
+ function same(a, b, c) { return (a==b && b==c) ? a : '';};
+ },
+ getMemento: function(){
+ var rows = [];
+ angular.foreach(this.board, function(row){
+ rows.push(row.join(','));
+ });
+ return rows.join(';') + '/' + this.nextMove;
+ },
+ setMemento: function(value) {
+ if (value) {
+ value = value.split('/');
+ this.nextMove = value[1];
+ angular.foreach(value[0].split(';'), function(row, i){
+ this.board[i] = row.split(',');
+ }, this);
+ } else {
+ this.reset();
+ }
+ }
+};
+</script>
+<h3>Tic-Tac-Toe</h3>
+Next Player: {{nextMove}}
+<div ng:show="winner">Player {{winner}} has won!</div>
+<table ng:controller="TicTacToeCntl">
+ <tr ng:repeat="row in board" style="height:15px;">
+ <td ng:repeat="cell in row" ng:style="cellStyle"
+ ng:click="dropPiece($parent.$index, $index)">{{cell}}</td>
+ </tr>
+</table>
+<button ng:click="reset()">reset board</button>
+
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/scenario/location.html b/scenario/location.html
new file mode 100644
index 00000000..a162636b
--- /dev/null
+++ b/scenario/location.html
@@ -0,0 +1,15 @@
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <link rel="stylesheet" type="text/css" href="style.css"/>
+ <script type="text/javascript" src="../src/angular-bootstrap.js#autobind"></script>
+ </head>
+ <body ng:init="$window.$scope = this">
+ <pre>$location={{$location}}</pre>
+ <hr/>
+ href: <input type="text" name="$location.href" size="120"/> <br/>
+ hash: <input type="text" name="$location.hash" size="120"/> <br/>
+ hashPath: <input type="text" name="$location.hashPath" size="120"/> <br/>
+ hashSearch: <input type="text" name="$location.hashSearch" size="120" ng:format="json"/> <br/>
+ </body>
+ </html>
diff --git a/src/Angular.js b/src/Angular.js
index 32e3ccf7..80acddf0 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -300,10 +300,10 @@ function bind(_this, _function) {
} :
function() {
return _function.apply(_this, curryArgs.concat(slice.call(arguments, 0, arguments.length)));
- }
+ };
} else {
- // in IE, native methonds ore not functions and so they can not be bound (but they don't need to be)
- return function(a, b, c, d, e){ return _function(a, b, c, d, e); };
+ // in IE, native methods ore not functions and so they can not be bound (but they don't need to be)
+ return _function;
}
}
diff --git a/src/angular-bootstrap.js b/src/angular-bootstrap.js
index 90e1104e..e055371a 100644
--- a/src/angular-bootstrap.js
+++ b/src/angular-bootstrap.js
@@ -22,16 +22,14 @@
* THE SOFTWARE.
*/
(function(previousOnLoad){
- var filename = /(.*)\/angular-(.*).js(#(.*))?/,
+ var filename = /(.*)\/angular-(.*).js(#.*)?/,
scripts = document.getElementsByTagName("SCRIPT"),
serverPath,
- config,
match;
for(var j = 0; j < scripts.length; j++) {
match = (scripts[j].src || "").match(filename);
if (match) {
serverPath = match[1];
- config = match[4];
}
}
@@ -63,7 +61,7 @@
try {
if (previousOnLoad) previousOnLoad();
} catch(e) {}
- angularInit(parseKeyValue(config));
+ angularInit(parseKeyValue(angularJsConfig(document)));
};
})(window.onload);
diff --git a/src/formatters.js b/src/formatters.js
index 40462cf3..ca1ce83e 100644
--- a/src/formatters.js
+++ b/src/formatters.js
@@ -5,6 +5,7 @@ var NUMBER = /^\s*[-+]?\d*(\.\d*)?\s*$/;
extend(angularFormatter, {
'noop':formatter(identity, identity),
+ 'json':formatter(toJson, fromJson),
'boolean':formatter(toString, toBoolean),
'number':formatter(toString,
function(obj){
diff --git a/src/jqLite.js b/src/jqLite.js
index 04682754..22b3c070 100644
--- a/src/jqLite.js
+++ b/src/jqLite.js
@@ -107,7 +107,7 @@ JQLite.prototype = {
if (!event.preventDefault) {
event.preventDefault = function(){
event.returnValue = false;
- }
+ };
}
foreach(eventHandler.fns, function(fn){
fn.call(self, event);
diff --git a/src/services.js b/src/services.js
index 106f8954..3dd7df09 100644
--- a/src/services.js
+++ b/src/services.js
@@ -7,61 +7,78 @@ var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+)
var HASH_MATCH = /^([^\?]*)?(\?([^\?]*))?$/;
var DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21};
angularService("$location", function(browser){
- var scope = this, location = {parse:parseUrl, toString:toString};
- var lastHash, lastUrl;
+ var scope = this,
+ location = {parse:parseUrl, toString:toString, update:update},
+ lastLocation = {};
+
+ browser.watchUrl(function(url){
+ update(url);
+ scope.$root.$eval();
+ });
+ this.$onEval(PRIORITY_FIRST, update);
+ this.$onEval(PRIORITY_LAST, update);
+ update(browser.getUrl());
+ return location;
+
+ function update(href){
+ if (href) {
+ parseUrl(href);
+ } else {
+ href = check('href') || check('protocol', '://', 'host', ':', 'port', '', 'path', '?', 'search');
+ var hash = check('hash');
+ if (isUndefined(hash)) hash = check('hashPath', '?', 'hashSearch');
+ if (isDefined(hash)) {
+ href = (href || location.href).split('#')[0];
+ href+= '#' + hash;
+ }
+ if (isDefined(href)) {
+ parseUrl(href);
+ browser.setUrl(href);
+ }
+ }
+ }
+
+ function check() {
+ var i = -1,
+ length=arguments.length,
+ name, seperator, parts = [],
+ value, same = true;
+ for(; i<length; i = i+2) {
+ parts.push(seperator = (arguments[i] || ''));
+ name = arguments[i + 1];
+ value=location[name];
+ parts.push(typeof value == 'object' ? toKeyValue(value) : value);
+ same = same && equals(lastLocation[name], value);
+ }
+ return same ? undefined : parts.join('');
+ }
+
function parseUrl(url){
if (isDefined(url)) {
var match = URL_MATCH.exec(url);
if (match) {
- location.href = url;
+ location.href = url.replace('#$', '');
location.protocol = match[1];
location.host = match[3] || '';
- location.port = match[5] || DEFAULT_PORTS[location.href] || null;
+ location.port = match[5] || DEFAULT_PORTS[location.protocol] || null;
location.path = match[6];
location.search = parseKeyValue(match[8]);
location.hash = match[9] || '';
if (location.hash)
location.hash = location.hash.substr(1);
- parseHash(location.hash);
+ match = HASH_MATCH.exec(location.hash);
+ location.hashPath = match[1] || '';
+ location.hashSearch = parseKeyValue(match[3]);
+
+ copy(location, lastLocation);
}
}
}
- function parseHash(hash) {
- var match = HASH_MATCH.exec(hash);
- location.hashPath = match[1] || '';
- location.hashSearch = parseKeyValue(match[3]);
- lastHash = hash;
- }
+
function toString() {
- if (lastHash === location.hash) {
- var hashKeyValue = toKeyValue(location.hashSearch),
- hash = (location.hashPath ? location.hashPath : '') + (hashKeyValue ? '?' + hashKeyValue : ''),
- url = location.href.split('#')[0] + '#' + (hash ? hash : '');
- if (url !== location.href) parseUrl(url);
- return url;
- } else {
- parseUrl(location.href.split('#')[0] + '#' + location.hash);
- return toString();
- }
+ update();
+ return location.href;
}
- browser.watchUrl(function(url){
- parseUrl(url);
- scope.$root.$eval();
- });
- parseUrl(browser.getUrl());
- this.$onEval(PRIORITY_FIRST, function(){
- if (location.hash != lastHash) {
- parseHash(location.hash);
- }
- });
- this.$onEval(PRIORITY_LAST, function(){
- var url = toString();
- if (lastUrl != url) {
- browser.setUrl(url);
- lastUrl = url;
- }
- });
- return location;
}, {inject: ['$browser']});
angularService("$log", function($window){
diff --git a/test/servicesSpec.js b/test/servicesSpec.js
index 91538703..cb5c9b30 100644
--- a/test/servicesSpec.js
+++ b/test/servicesSpec.js
@@ -106,7 +106,7 @@ describe("service", function(){
expect(scope.$location.hashPath).toEqual('');
expect(scope.$location.hashSearch).toEqual({});
- expect(scope.$location.toString()).toEqual('file:///Users/Shared/misko/work/angular.js/scenario/widgets.html#');
+ expect(scope.$location.toString()).toEqual('file:///Users/Shared/misko/work/angular.js/scenario/widgets.html');
});
it('should update url on hash change', function(){
@@ -123,6 +123,14 @@ describe("service", function(){
expect(scope.$location.hash).toEqual('?a=b');
});
+ it("should parse url which contains - in host", function(){
+ scope.$location.parse('http://a-b1.c-d.09/path');
+ expect(scope.$location.href).toEqual('http://a-b1.c-d.09/path');
+ expect(scope.$location.protocol).toEqual('http');
+ expect(scope.$location.host).toEqual('a-b1.c-d.09');
+ expect(scope.$location.path).toEqual('/path');
+ });
+
it('should update hash before any processing', function(){
var scope = compile('<div>');
var log = '';
@@ -136,15 +144,6 @@ describe("service", function(){
scope.$eval();
expect(log).toEqual('/abc;');
});
-
- it("should parse url which contains - in host", function(){
- scope.$location.parse('http://a-b1.c-d.09/path');
- expect(scope.$location.href).toEqual('http://a-b1.c-d.09/path');
- expect(scope.$location.protocol).toEqual('http');
- expect(scope.$location.host).toEqual('a-b1.c-d.09');
- expect(scope.$location.path).toEqual('/path');
- });
-
});
describe("$invalidWidgets", function(){