Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit - angular skeleton app

  • Loading branch information...
commit 8389180edb696e1949dcc5a8043e78d486d89c71 0 parents
Vojta Jina authored
Showing with 32,560 additions and 0 deletions.
  1. +7 −0 .gitignore
  2. +147 −0 README.md
  3. +30 −0 app/css/app.css
  4. +22 −0 app/index.html
  5. +10 −0 app/js/controllers.js
  6. +1 −0  app/js/filters.js
  7. +23 −0 app/js/services.js
  8. +1 −0  app/js/widgets.js
  9. +32 −0 app/lib/angular/angular-ie-compat.js
  10. +10,021 −0 app/lib/angular/angular.js
  11. +112 −0 app/lib/angular/angular.min.js
  12. +1 −0  app/lib/angular/version.txt
  13. +1 −0  app/partials/partial1.html
  14. +1 −0  app/partials/partial2.html
  15. +12 −0 config/jsTestDriver.conf
  16. +2 −0  logs/.gitignore
  17. +10 −0 scripts/test-server.sh
  18. +10 −0 scripts/test.sh
  19. +19 −0 scripts/watchr.rb
  20. +243 −0 scripts/web-server.js
  21. +10 −0 test/e2e/runner.html
  22. +41 −0 test/e2e/scenarios.js
  23. +392 −0 test/lib/angular/angular-mocks.js
  24. +18,221 −0 test/lib/angular/angular-scenario.js
  25. +1 −0  test/lib/angular/version.txt
  26. +179 −0 test/lib/jasmine-jstd-adapter/JasmineAdapter.js
  27. +1 −0  test/lib/jasmine-jstd-adapter/version.txt
  28. +20 −0 test/lib/jasmine/MIT.LICENSE
  29. +180 −0 test/lib/jasmine/index.js
  30. +188 −0 test/lib/jasmine/jasmine-html.js
  31. +166 −0 test/lib/jasmine/jasmine.css
  32. +2,421 −0 test/lib/jasmine/jasmine.js
  33. +2 −0  test/lib/jasmine/version.txt
  34. BIN  test/lib/jstestdriver/JsTestDriver.jar
  35. +1 −0  test/lib/jstestdriver/version.txt
  36. +29 −0 test/unit/controllersSpec.js
  37. +1 −0  test/unit/filtersSpec.js
  38. +1 −0  test/unit/servicesSpec.js
  39. +1 −0  test/unit/widgetsSpec.js
7 .gitignore
@@ -0,0 +1,7 @@
+**/.DS_Store
+nbproject
+manifest.mf
+build.xml
+
+.project
+.settings
147 README.md
@@ -0,0 +1,147 @@
+# angular-seed — the seed for <angular/> apps
+
+This project is an application skeleton for a typical [angular](http://angularjs.org/) web app. You
+can use it to quickly bootstrap your angular webapp projects and dev environment for these projects.
+
+The seed contains angular libraries, test libraries and a bunch of scripts all preconfigured for
+instant web development gratification. Just clone the repo (or download the zip/tarball), start up
+our (or yours) webserver and you are ready to develop and test your application.
+
+The seed app doesn't do much, just shows how to wire two controllers and views together. You can
+check it out by opening app/index.html in your browser (might not work file `file://` scheme in
+certain browsers, see note below).
+
+_Note: While angular is client-side-only technology and it's possible to create angular webapps that
+don't require a backend server at all, we recommend hosting the project files using a local
+webserver during development to avoid issues with security restrictions (sandbox) in browsers. The
+sandbox implementation varies between browsers, but quite often prevents things like cookies, xhr,
+etc to function properly when an html page is opened via `file://` scheme instead of `http://`._
+
+
+## How to use angular-seed
+
+Clone the angular-seed repository and start hacking...
+
+
+### Running the app during development
+
+You can pick one of these options:
+
+* serve this repository with your webserver
+* install node.js and run `scripts/web-server.js`
+
+Then navigate your browser to `http://localhost:<port>/app/index.html` to see the app running in
+your browser.
+
+
+### Running the app in production
+
+This really depends on how complex is your app and the overall infrastructure of your system, but
+the general rule is that all you need in production are all the files under the `app/` directory.
+Everything else should be omitted.
+
+angular apps are really just a bunch of static html, css and js files that just need to be hosted
+somewhere, where they can be accessed by browsers.
+
+If your angular app is talking to the backend server via xhr or other means, you need to figure
+out what is the best way to host the static files to comply with the same origin policy if
+applicable. Usually this is done by hosting the files by the backend server or through
+reverse-proxying the backend server(s) and a webserver(s).
+
+
+### Running unit tests
+
+We recommend using [jasmine](http://pivotal.github.com/jasmine/) and
+[JsTestDriver](http://code.google.com/p/js-test-driver/) for your unit tests/specs, but you are free
+to use whatever works for you.
+
+Requires java and a local or remote browser.
+
+* start `scripts/test-server.sh`
+* navigate your browser to `http://localhost:9876/`
+* click on one of the capture links (preferably the "strict" one)
+* run `scripts/test.sh`
+
+
+### Continuous unit testing
+
+Requires ruby and [watchr](https://github.com/mynyml/watchr) gem.
+
+* start JSTD server and capture a browser as described above
+* start watchr as `watchr scripts/watchr.rb`
+* in a different window/tab/editor `tail -f logs/jstd.log`
+* edit files in `app/` or `src/` and save them
+* watch the log to see updates
+
+There are many other ways to achieve the same effect. Feel free to use them if you prefer them over
+watchr.
+
+
+### End to end testing
+
+angular ships with a baked-in end-to-end test runner that understands angular, your app and allows
+you to write your tests with jasmine-like BDD syntax.
+
+Requires a webserver, node.js or your backend server that hosts the angular static files.
+
+* create your end-to-end tests in `test/e2e/scenarios.js`
+* serve your project directory with your http/backend server or node.js + `scripts/web-server.js`
+* open `http://localhost:port/test/e2e/runner.html` in your browser
+
+
+### Receiving updates from upstream
+
+When we upgrade angular-seed's repo with newer angular or testing library code, you can just
+fetch the changes and merge them into your project with git.
+
+
+## Directory Layout
+
+ app/ --> all of the files to be used in production
+ css/ --> css files
+ app.css --> default stylesheet
+ img/ --> image files
+ index.html --> app layout file (the main html template file of the app)
+ js/ --> javascript files
+ controllers.js --> application controllers
+ filters.js --> custom angular filters
+ services.js --> custom angular services
+ widgets.js --> custom angular widgets
+ lib/ --> angular and 3rd party javascript libraries
+ angular/
+ angular.js --> the latest angular js
+ angular.min.js --> the latest minified angular js
+ angular-ie-compat.js --> angular patch for IE 6&7 compatibility
+ version.txt --> version number
+ partials/ --> angular view partials (partial html templates)
+ partial1.html
+ partial2.html
+
+ config/jsTestDriver.conf --> config file for JsTestDriver
+
+ logs/ --> JSTD and other logs go here (git-ignored)
+
+ scripts/ --> handy shell/js/ruby scripts
+ test-server.sh --> starts JSTD server
+ test.sh --> runs all unit tests
+ watchr.rb --> config script for continuous testing with watchr
+ web-server.js --> simple development webserver based on node.js
+
+ test/ --> test source files and libraries
+ e2e/ -->
+ runner.html --> end-to-end test runner (open in your browser to run)
+ scenarios.js --> end-to-end specs
+ lib/
+ angular/ --> angular testing libraries
+ angular-mocks.js --> mocks that replace certain angular services in tests
+ angular-scenario.js --> angular's scenario (end-to-end) test runner library
+ version.txt --> version file
+ jasmine/ --> Pivotal's Jasmine - an elegant BDD-style testing framework
+ jasmine-jstd-adapter/ --> bridge between JSTD and Jasmine
+ jstestdriver/ --> JSTD - JavaScript test runner
+ unit/ --> unit level specs/tests
+ controllersSpec.js --> specs for controllers
+
+## Contact
+
+For more information on angular please check out http://angularjs.org/
30 app/css/app.css
@@ -0,0 +1,30 @@
+/* app css stylesheet */
+
+.menu {
+ list-style: none;
+ border-bottom: 0.1em solid black;
+ margin-bottom: 2em;
+ padding: 0 0 0.5em;
+}
+
+.menu:before {
+ content: "[";
+}
+
+.menu:after {
+ content: "]";
+}
+
+.menu > li {
+ display: inline;
+}
+
+.menu > li:before {
+ content: "|";
+ padding-right: 0.3em;
+}
+
+.menu > li:nth-child(1):before {
+ content: "";
+ padding: 0;
+}
22 app/index.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html xmlns:ng="http://angularjs.org/">
+<head>
+ <meta charset="utf-8">
+ <title>my angular app</title>
+ <link rel="stylesheet" href="css/app.css"/>
+</head>
+<body>
+ <ul class="menu">
+ <li><a href="#/view1">view1</a></li>
+ <li><a href="#/view2">view2</a></li>
+ </ul>
+
+ <ng:view></ng:view>
+
+ <script src="lib/angular/angular.js" ng:autobind></script>
+ <script src="js/services.js"></script>
+ <script src="js/controllers.js"></script>
+ <script src="js/filters.js"></script>
+ <script src="js/widgets.js"></script>
+</body>
+</html>
10 app/js/controllers.js
@@ -0,0 +1,10 @@
+/* App Controllers */
+
+
+function MyCtrl1() {}
+MyCtrl1.$inject = [];
+
+
+function MyCtrl2() {
+}
+MyCtrl2.$inject = [];
1  app/js/filters.js
@@ -0,0 +1 @@
+/* http://docs.angularjs.org/#!angular.filter */
23 app/js/services.js
@@ -0,0 +1,23 @@
+/* http://docs.angularjs.org/#!angular.service */
+
+/**
+ * App service which is responsible for the main configuration of the app.
+ */
+angular.service('myAngularApp', function($route, $location, $window) {
+
+ $route.when('/view1', {template: 'partials/partial1.html', controller: MyCtrl1});
+ $route.when('/view2', {template: 'partials/partial2.html', controller: MyCtrl2});
+
+ var self = this;
+
+ $route.onChange(function() {
+ if ($location.hash === '') {
+ $location.updateHash('/view1');
+ self.$eval();
+ } else {
+ $route.current.scope.params = $route.current.params;
+ $window.scrollTo(0,0);
+ }
+ });
+
+}, {$inject:['$route', '$location', '$window'], $eager: true});
1  app/js/widgets.js
@@ -0,0 +1 @@
+/* http://docs.angularjs.org/#!angular.widget */
32 app/lib/angular/angular-ie-compat.js
@@ -0,0 +1,32 @@
+/*
+Content-Type: multipart/related; boundary="_"
+
+--_
+Content-Location:img0
+Content-Transfer-Encoding:base64
+
+R0lGODlhCwAXAKIAAMzMzO/v7/f39////////wAAAAAAAAAAACH5BAUUAAQALAAAAAALABcAAAMrSLoc/AG8FeUUIN+sGebWAnbKSJodqqlsOxJtqYooU9vvk+vcJIcTkg+QAAA7
+--_
+Content-Location:img1
+Content-Transfer-Encoding:base64
+
+R0lGODlhCwAXAKIAAMzMzO/v7/f39////////wAAAAAAAAAAACH5BAUUAAQALAAAAAALABcAAAMrCLTcoM29yN6k9socs91e5X3EyJloipYrO4ohTMqA0Fn2XVNswJe+H+SXAAA7
+--_
+Content-Location:img2
+Content-Transfer-Encoding:base64
+
+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
+--_--
+*/
+(function(){
+ var jsUri = document.location.href.replace(/\/[^/]+(#.*)?$/, '/') + document.getElementById('ng-ie-compat').src;
+ var css = '#ng-callout .ng-arrow-left{*background-image:url("mhtml:' + jsUri + '!img0")}#ng-callout .ng-arrow-right{*background-image:url("mhtml:' + jsUri + '!img1")}.ng-input-indicator-wait {*background-image:url("mhtml:' + jsUri + '!img2")}'
+ var s = document.createElement('style');
+ s.setAttribute('type', 'text/css');
+ if (s.styleSheet) {
+ s.styleSheet.cssText = css;
+ } else {
+ s.appendChild(document.createTextNode(css));
+ }
+ document.getElementsByTagName('head')[0].appendChild(s);
+})();
10,021 app/lib/angular/angular.js
10,021 additions, 0 deletions not shown
112 app/lib/angular/angular.min.js
@@ -0,0 +1,112 @@
+(function(s,L,E){function k(a,b,c){var d;if(a)if(m(a))for(d in a)d!="prototype"&&d!=Wb&&d!=Xb&&a.hasOwnProperty(d)&&b.call(c,a[d],d);else if(a.forEach&&a.forEach!==k)a.forEach(b,c);else if(I(a)&&ma(a.length))for(d=0;d<a.length;d++)b.call(c,a[d],d);else for(d in a)b.call(c,a[d],d);return a}function Ga(a,b,c){var d=[],e;for(e in a)d.push(e);d.sort();for(e=0;e<d.length;e++)b.call(c,a[d[e]],d[e]);return d}function Ha(a){if(a instanceof K)a.stack?a=a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+
+a.line);return a}function n(a){k(arguments,function(b){b!==a&&k(b,function(b,d){a[d]=b})});return a}function Yb(a,b){return n(new (n(function(){},{prototype:a})),b)}function q(){}function Z(a){return a}function ua(a){return function(){return a}}function P(a,b,c){var d;return a[b]||(d=a[b]=function(a,b,g){a=(c||Z)(a);x(b)&&(d[a]=n(b,g||{}));return d[a]})}function z(a){return typeof a==$}function x(a){return typeof a!=$}function I(a){return a!=null&&typeof a==gb}function w(a){return typeof a==Zb}function ma(a){return typeof a==
+$b}function Q(a){return a instanceof Array}function m(a){return typeof a==R}function ia(a){return w(a)?a.replace(/^\s*/,"").replace(/\s*$/,""):a}function Ia(a,b){this.html=a;this.get=D(b)=="unsafe"?ua(a):function(){var b=[];hb(a,ib(b));return b.join("")}}function ac(a,b,c){var d=[];k(a,function(a,f,g){d.push(b.call(c,a,f,g))});return d}function jb(a,b){var c=0,d;if(Q(a)||w(a))return a.length;else if(I(a))for(d in a)(!b||a.hasOwnProperty(d))&&c++;return c}function kb(a,b){for(var c=0;c<a.length;c++)if(b===
+a[c])return!0;return!1}function na(a,b){for(var c=0;c<a.length;c++)if(b===a[c])return c;return-1}function bc(a){if(a)switch(a.nodeName){case "OPTION":case "PRE":case "TITLE":return!0}return!1}function A(a,b){if(b)if(Q(a)){for(;b.length;)b.pop();for(var c=0;c<a.length;c++)b.push(A(a[c]))}else for(c in k(b,function(a,c){delete b[c]}),a)b[c]=A(a[c]);else(b=a)&&(Q(a)?b=A(a,[]):a instanceof Date?b=new Date(a.getTime()):I(a)&&(b=A(a,{})));return b}function oa(a,b){if(a==b)return!0;if(a===null||b===null)return!1;
+var c=typeof a,d;if(c==typeof b&&c=="object")if(a instanceof Array){if((c=a.length)==b.length){for(d=0;d<c;d++)if(!oa(a[d],b[d]))return!1;return!0}}else{c={};for(d in a){if(d.charAt(0)!=="$"&&!m(a[d])&&!oa(a[d],b[d]))return!1;c[d]=!0}for(d in b)if(!c[d]&&d.charAt(0)!=="$"&&!m(b[d]))return!1;return!0}return!1}function cc(a){return(a=a&&a[0]&&a[0].nodeName)&&a.charAt(0)!="#"&&!kb(["TR","COL","COLGROUP","TBODY","THEAD","TFOOT"],a)}function aa(a,b,c){for(var d;!cc(a);)if(d=a.parent(),d.length)a=a.parent();
+else return;if(a[0].$NG_ERROR!==c)(a[0].$NG_ERROR=c)?(a.addClass(b),a.attr(b,c.message||c)):(a.removeClass(b),a.removeAttr(b))}function F(a,b){var c=arguments.length>2?ba.call(arguments,2,arguments.length):[];return typeof b==R&&!(b instanceof RegExp)?c.length?function(){return arguments.length?b.apply(a,c.concat(ba.call(arguments,0,arguments.length))):b.apply(a,c)}:function(){return arguments.length?b.apply(a,arguments):b.call(a)}:b}function ja(a){a&&a.length!==0?(a=D(""+a),a=!(a=="f"||a=="0"||a==
+"false"||a=="no"||a=="n"||a=="[]")):a=!1;return a}function lb(a){return(new mb(Ja,nb,B,J)).compile(a)}function Ka(a){var b={},c,d;k((a||"").split("&"),function(a){a&&(c=a.split("="),d=unescape(c[0]),b[d]=x(c[1])?unescape(c[1]):!0)});return b}function ob(a){var b=[];k(a,function(a,d){b.push(escape(d)+(a===!0?"":"="+escape(a)))});return b.length?b.join("&"):""}function La(a,b){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(b?null:
+/%20/g,"+")}function dc(a,b){pb();var c=a.getElementsByTagName("script"),d;b=n({ie_compat_id:"ng-ie-compat"},b);for(var e=0;e<c.length;e++)if(d=(c[e].src||"").match(ec))b.base_url=d[1],b.ie_compat=d[1]+"angular-ie-compat"+(d[2]||"")+".js",n(b,Ka(d[6])),va(o(c[e]),function(a,c){/^ng:/.exec(c)&&(c=c.substring(3).replace(/-/g,"_"),b[c]=a||!0)});return b}function pb(){(Ma=s.jQuery)?(o=Ma,n(Ma.fn,{scope:qb.scope})):o=Na;u.element=o}function rb(a,b,c){if(!a)throw a=new K("Argument '"+(b||"?")+"' is "+(c||
+"required")),s.console&&s.console.log(a.stack),a;}function M(a,b){var c=[];Oa(c,a,b?"\n ":null,[]);return c.join("")}function ca(a,b){function c(a){if(w(a)&&a.length===sb)return Pa.toDate(a);else(Q(a)||I(a))&&k(a,function(b,d){a[d]=c(b)});return a}if(!w(a))return a;var d,e,f;try{if(b&&s.JSON&&s.JSON.parse)return d=JSON.parse(a),c(d);e=da(a,!0);f=e.primary();e.assertAllConsumed();return f()}catch(g){throw fc("fromJson error: ",a,g),g;}}function Oa(a,b,c,d){if(I(b)){if(b===s){a.push("WINDOW");return}if(b===
+L){a.push("DOCUMENT");return}if(kb(d,b)){a.push("RECURSION");return}d.push(b)}if(b===null)a.push(wa);else if(b instanceof RegExp)a.push(u.String.quoteUnicode(b.toString()));else if(m(b))return;else if(typeof b==gc)a.push(""+b);else if(ma(b))isNaN(b)?a.push(wa):a.push(""+b);else if(w(b))return a.push(u.String.quoteUnicode(b));else if(I(b))if(Q(b)){a.push("[");for(var e=b.length,f=!1,g=0;g<e;g++){var h=b[g];f&&a.push(",");!(h instanceof RegExp)&&(m(h)||z(h))?a.push(wa):Oa(a,h,c,d);f=!0}a.push("]")}else if(b instanceof
+Date)a.push(u.String.quoteUnicode(u.Date.toString(b)));else{a.push("{");c&&a.push(c);e=!1;f=c?c+" ":!1;g=[];for(h in b)b[h]!==E&&g.push(h);g.sort();for(h=0;h<g.length;h++){var i=g[h],j=b[i];typeof j!=R&&(e&&(a.push(","),c&&a.push(c)),a.push(u.String.quote(i)),a.push(":"),Oa(a,j,f,d),e=!0)}a.push("}")}I(b)&&d.pop()}function Qa(a){this.paths=[];this.children=[];this.inits=[];this.priority=a;this.newScope=!1}function mb(a,b,c,d){this.markup=a;this.attrMarkup=b;this.directives=c;this.widgets=d}function tb(a,
+b){var c,d=a[0].childNodes||[],e;for(c=0;c<d.length;c++){var f=e=d[c];pa(f)=="#text"||b(o(e),c)}}function va(a,b){var c,d=a[0].attributes||[],e,f,g={};for(c=0;c<d.length;c++)e=d[c],f=e.name,e=e.value,S&&f=="href"&&(e=decodeURIComponent(a[0].getAttribute(f,2))),g[f]=e;Ga(g,b)}function qa(a,b,c){if(!b)return a;for(var d=b.split("."),e,f=a,g=d.length,h=0;h<g;h++){e=d[h];if(!e.match(/^[\$\w][\$\w\d]*$/))throw"Expression '"+b+"' is not a valid expression for accesing variables.";a&&(f=a,a=a[e]);if(z(a)&&
+e.charAt(0)=="$"){var i=u.Global.typeOf(f);if(e=(i=u[i.charAt(0).toUpperCase()+i.substring(1)])?i[[e.substring(1)]]:E)return a=F(f,e,f)}}if(!c&&m(a))return F(f,a);return a}function Ra(a,b,c){b=b.split(".");for(var d=0;b.length>1;d++){var e=b.shift(),f=a[e];f||(f={},a[e]=f);a=f}return a[b.shift()]=c}function ub(a){var b=vb[a];if(b)return b;var c="var l, fn, t;\n";k(a.split("."),function(a){a=wb[a]?'["'+a+'"]':"."+a;c+="if(!s) return s;\nl=s;\ns=s"+a+';\nif(typeof s=="function" && !(s instanceof RegExp)) s = function(){ return l'+
+a+".apply(l, arguments); };\n";a.charAt(1)=="$"&&(a=a.substr(2),c+='if(!s) {\n t = angular.Global.typeOf(l);\n fn = (angular[t.charAt(0).toUpperCase() + t.substring(1)]||{})["'+a+'"];\n if (fn) s = function(){ return fn.apply(l, [l].concat(Array.prototype.slice.call(arguments, 0, arguments.length))); };\n}\n')});c+="return s;";b=Function("s",c);b.toString=function(){return c};return vb[a]=b}function ea(a){if(typeof a===R)return a;var b=xb[a];if(!b){b=da(a);var c=b.statements();b.assertAllConsumed();
+b=xb[a]=n(function(){return c(this)},{fnSelf:c})}return b}function T(a,b,c){function d(){}a=d.prototype=a||{};var e=new d,f={sorted:[]},g,h;n(e,{"this":e,$id:hc++,$parent:a,$bind:F(e,F,e),$get:F(e,qa,e),$set:F(e,Ra,e),$eval:function(a){var b=typeof a,c,d,g;if(b==$){a=0;for(b=f.sorted.length;a<b;a++){g=f.sorted[a];d=g.length;for(c=0;c<d;c++)e.$tryEval(g[c].fn,g[c].handler)}}else if(b===R)return a.call(e);else if(b==="string")return ea(a).call(e)},$tryEval:function(a,b){var c=typeof a;try{if(c==R)return a.call(e);
+else if(c=="string")return ea(a).call(e)}catch(d){g&&g.error(d),m(b)?b(d):b?aa(b,xa,x(d)?Ha(d):d):m(h)&&h(d)}},$watch:function(a,b,c,d){function g(a){var d=f.call(e),i=h;if(a||i!==d)h=d,e.$tryEval(function(){return b.call(e,d,i)},c)}var f=ea(a),h=f.call(e);b=ea(b);e.$onEval(yb,g);z(d)&&(d=!0);d&&g(!0)},$onEval:function(a,b,c){ma(a)||(c=b,b=a,a=0);var d=f[a];if(!d)d=f[a]=[],d.priority=a,f.sorted.push(d),f.sorted.sort(function(a,b){return a.priority-b.priority});d.push({fn:ea(b),handler:c})},$become:function(a){if(m(a))e.constructor=
+a,k(a.prototype,function(a,b){e[b]=F(e,a)}),e.$service.apply(e,[a,e].concat(ba.call(arguments,1,arguments.length))),m(a.prototype.init)&&e.init()},$new:function(a){var b=T(e);b.$become.apply(e,[a].concat(ba.call(arguments,1,arguments.length)));e.$onEval(b.$eval);return b}});if(!a.$root)e.$root=e,e.$parent=e,(e.$service=zb(e,b,c))();g=e.$service("$log");h=e.$service("$exceptionHandler");return e}function zb(a,b,c){b=b||Ta;c=c||{};a=a||{};return function e(f,g){var h,i;if(w(f)){if(!(f in c)){i=b[f];
+if(!i)throw"Unknown provider for '"+f+"'.";c[f]=e(i,a)}h=c[f]}else Q(f)?(h=[],k(f,function(a){h.push(e(a))})):m(f)?(h=e(ic(f)),h=f.apply(g,h.concat(ba.call(arguments,2,arguments.length)))):I(f)?k(b,function(a,b){a.$eager&&e(b);if(a.$creation)throw new K("Failed to register service '"+b+"': $creation property is unsupported. Use $eager:true or see release notes.");}):h=e(a);return h}}function C(a,b,c,d){Ta(a,b,{$inject:c,$eager:d})}function ic(a){rb(m(a,void 0,"not a function"));if(!a.$inject){var b=
+a.$inject=[],c=a.toString().replace(jc,"").match(kc);k(c[1].split(lc),function(a){a.replace(mc,function(a,c,d,h,i){rb(b,c,"after non-injectable arg");h||i?b.push(d):b=null})})}return a.$inject}function nc(a,b){function c(a){return a.indexOf(t)!=-1}function d(){return l+1<a.length?a.charAt(l+1):!1}function e(a){return"0"<=a&&a<="9"}function f(a){return"a"<=a&&a<="z"||"A"<=a&&a<="Z"||"_"==a||a=="$"}function g(a){return a=="-"||a=="+"||e(a)}function h(b,c,d){d=d||l;throw K("Lexer Error: "+b+" at column"+
+(x(c)?"s "+c+"-"+l+" ["+a.substring(c,d)+"]":" "+d)+" in expression ["+a+"].");}function i(){for(var b="",c=l;l<a.length;){var f=D(a.charAt(l));if(f=="."||e(f))b+=f;else{var i=d();if(f=="e"&&g(i))b+=f;else if(g(f)&&i&&e(i)&&b.charAt(b.length-1)=="e")b+=f;else if(g(f)&&(!i||!e(i))&&b.charAt(b.length-1)=="e")h("Invalid exponent");else break}l++}b*=1;r.push({index:c,text:b,json:!0,fn:function(){return b}})}function j(){for(var b="",c=l,d;l<a.length;){d=a.charAt(l);if(d=="."||f(d)||e(d))b+=d;else break;
+l++}d=Ua[b];r.push({index:c,text:b,json:d,fn:d||n(ub(b),{assign:function(a,c){return Ra(a,b,c)}})})}function v(b){var c=l;l++;for(var d="",e=b,f=!1;l<a.length;){var g=a.charAt(l);e+=g;if(f)g=="u"?(g=a.substring(l+1,l+5),g.match(/[\da-f]{4}/i)||h("Invalid unicode escape [\\u"+g+"]"),l+=4,d+=String.fromCharCode(parseInt(g,16))):(f=oc[g],d+=f?f:g),f=!1;else if(g=="\\")f=!0;else if(g==b){l++;r.push({index:c,text:e,string:d,json:!0,fn:function(){return d.length==p?u.String.toDate(d):d}});return}else d+=
+g;l++}h("Unterminated quote",c)}for(var p=b?sb:-1,r=[],y,l=0,k=[],t,U=":";l<a.length;){t=a.charAt(l);if(c("\"'"))v(t);else if(e(t)||c(".")&&e(d()))i();else if(f(t)){if(j(),"{,".indexOf(U)!=-1&&k[0]=="{"&&(y=r[r.length-1]))y.json=y.text.indexOf(".")==-1}else if(c("(){}[].,;:"))r.push({index:l,text:t,json:":[,".indexOf(U)!=-1&&c("{[")||c("}]:,")}),c("{[")&&k.unshift(t),c("}]")&&k.shift(),l++;else if(t==" "||t=="\r"||t=="\t"||t=="\n"||t=="\u000b"||t=="\u00a0"){l++;continue}else{var ka=t+d(),o=Ua[t],
+q=Ua[ka];q?(r.push({index:l,text:ka,fn:q}),l+=2):o?(r.push({index:l,text:t,fn:o,json:"[,:".indexOf(U)!=-1&&c("+-")}),l+=1):h("Unexpected next character ",l,l+1)}U=t}return r}function da(a,b){function c(b,c){throw K("Parse Error: Token '"+c.text+"' "+b+" at column "+(c.index+1)+" of expression ["+a+"] starting at ["+a.substring(c.index)+"].");}function d(){if(s.length===0)throw K("Unexpected end of expression: "+a);return s[0]}function e(a,b,c,d){if(s.length>0){var e=s[0],g=e.text;if(g==a||g==b||g==
+c||g==d||!a&&!b&&!c&&!d)return e}return!1}function f(a,d,g,f){if(a=e(a,d,g,f)){if(b&&!a.json)index=a.index,c("is not valid json",a);s.shift();return this.currentToken=a}return!1}function g(a){f(a)||c("is unexpected, expecting ["+a+"]",e())}function h(a,b){return function(c){return a(c,b(c))}}function i(a,b,c){return function(d){return b(d,a(d),c(d))}}function j(){s.length!==0&&c("is extra token not part of expression",s[0])}function v(){for(var a=[];;)if(s.length>0&&!e("}",")",";","]")&&a.push(A()),
+!f(";"))return function(b){for(var c,d=0;d<a.length;d++){var e=a[d];e&&(c=e(b))}return c}}function p(){return G(N)}function r(){for(var a=y(),b;;)if(b=f("||"))a=i(a,b.fn,y());else return a}function y(){var a=l(),b;if(b=f("&&"))a=i(a,b.fn,y());return a}function l(){var a=k(),b;if(b=f("==","!="))a=i(a,b.fn,l());return a}function k(){var a;a=t();for(var b;b=f("+","-");)a=i(a,b.fn,t());if(b=f("<",">","<=",">="))a=i(a,b.fn,k());return a}function t(){for(var a=U(),b;b=f("*","/","%");)a=i(a,b.fn,U());return a}
+function U(){var a;return f("+")?ka():(a=f("-"))?i(x,a.fn,U()):(a=f("!"))?h(a.fn,U()):ka()}function ka(){var a;if(f("("))a=A(),g(")");else if(f("["))a=o();else if(f("{"))a=u();else{var b=f();(a=b.fn)||c("not a primary expression",b)}for(;b=f("(","[",".");)b.text==="("?a=B(a):b.text==="["?a=D(a):b.text==="."?a=C(a):c("IMPOSSIBLE");return a}function o(){var a=[];if(d().text!="]"){do a.push(m());while(f(","))}g("]");return function(b){for(var c=[],d=0;d<a.length;d++)c.push(a[d](b));return c}}function u(){var a=
+[];if(d().text!="}"){do{var b=f();b=b.string||b.text;g(":");var c=m();a.push({key:b,value:c})}while(f(","))}g("}");return function(b){for(var c={},d=0;d<a.length;d++){var e=a[d],g=e.value(b);c[e.key]=g}return c}}function w(){var a=f().text;g(":");var b;d().text=="{"?(g("{"),b=v(),g("}")):b=m();return function(){return{name:a,fn:b}}}var x=ua(0),s=nc(a,b),m=function(){var b=r(),d,e;return(e=f("="))?(b.assign||c("implies assignment but ["+a.substring(0,e.index)+"] can not be assigned to",e),d=r(),function(a){return b.assign(a,
+d(a))}):b},z=r,B=function(a){var b=[];if(d().text!=")"){do b.push(m());while(f(","))}g(")");return function(c){for(var d=[],e=0;e<b.length;e++)d.push(b[e](c));e=a(c)||q;return e.apply?e.apply(c,d):e(d[0],d[1],d[2],d[3],d[4])}},C=function(a){var b=f().text,c=ub(b);return n(function(b){return c(a(b))},{assign:function(c,d){return Ra(a(c),b,d)}})},D=function(a){var b=m();g("]");return n(function(c){var d=a(c);c=b(c);return d?d[c]:E},{assign:function(c,d){return a(c)[b(c)]=d}})},A=function(){for(var a=
+m(),b;;)if(b=f("|"))a=i(a,b.fn,p());else return a},F=function(a){for(var b=f(),d=b.text.split("."),e,g=0;g<d.length;g++)e=d[g],a&&(a=a[e]);typeof a!=R&&c("should be a function",b);return a},G=function(a){for(var b=F(a),c=[];;)if(f(":"))c.push(m());else{var d=function(a,d){for(var e=[d],g=0;g<c.length;g++)e.push(c[g](a));return b.apply(a,e)};return function(){return d}}};b&&(m=r,B=C=D=z=A=F=G=function(){c("is not valid json",{text:a,index:0})});return{assertAllConsumed:j,assignable:z,primary:ka,statements:v,
+validator:function(){return G(Va)},formatter:function(){function a(b){return function(a,c){for(var d=[c],g=0;g<e.length;g++)d.push(e[g](a));return b.apply(a,d)}}var b=f(),d=Y[b.text],e=[];for(d||c("is not a valid formatter.",b);;)if(b=f(":"))e.push(m());else return ua({format:a(d.format),parse:a(d.parse)})},filter:p,watch:function(){for(var a=[];s.length>0;)a.push(w()),f(";")||j();j();return function(b){for(var c=0;c<a.length;c++){var d=a[c](b);b.addListener(d.name,d.fn)}}}}}function Ab(a,b){this.template=
+a+="#";this.defaults=b||{};var c=this.urlParams={};k(a.split(/\W/),function(b){b&&a.match(RegExp(":"+b+"\\W"))&&(c[b]=!0)})}function ya(a){this.xhr=a}function qc(a,b,c,d,e){function f(a){try{a.apply(null,ba.call(arguments,1))}finally{if(v--,v===0)for(;p.length;)try{p.pop()()}catch(b){e.error(b)}}}var g=this,h=a.location,i=a.setTimeout;g.isMock=!1;var j=0,v=0,p=[];g.xhr=function(b,e,g,i,h){v++;if(D(b)=="json"){var p=("angular_"+Math.random()+"_"+j++).replace(/\d\./,""),r=o("<script>").attr({type:"text/javascript",
+src:e.replace("JSON_CALLBACK",p)});a[p]=function(b){a[p]=E;r.remove();f(i,200,b)};c.append(r)}else{var l=new d;l.open(b,e,!0);k(n(rc,h||{}),function(a,b){a&&l.setRequestHeader(b,a)});l.onreadystatechange=function(){l.readyState==4&&f(i,l.status||200,l.responseText)};l.send(g||"")}};g.notifyWhenNoOutstandingRequests=function(a){v===0?a():p.push(a)};var r=[];g.poll=function(){k(r,function(a){a()})};g.addPollFn=function(a){r.push(a);return a};g.startPoller=function(a,b){(function pc(){g.poll();b(pc,
+a)})()};g.setUrl=function(a){h.href.match(/#/);a.match(/#/)||(a+="#");h.href=a};g.getUrl=function(){return h.href};g.onHashChange=function(b){if("onhashchange"in a)o(a).bind("hashchange",b);else{var c=g.getUrl();g.addPollFn(function(){c!=g.getUrl()&&(b(),c=g.getUrl())})}return b};var y=b[0],l={},Sa="";g.cookies=function(a,b){var c,d,g,f;if(a)if(b===E)y.cookie=escape(a)+"=;expires=Thu, 01 Jan 1970 00:00:00 GMT";else{if(w(b))y.cookie=escape(a)+"="+escape(b),c=a.length+b.length+1,c>4096&&e.warn("Cookie '"+
+a+"' possibly not set or overflowed because it was too large ("+c+" > 4096 bytes)!"),l.length>20&&e.warn("Cookie '"+a+"' possibly not set or overflowed because too many cookies were already set ("+l.length+" > 20 )")}else{if(y.cookie!==Sa){Sa=y.cookie;c=Sa.split("; ");l={};for(g=0;g<c.length;g++)d=c[g],f=d.indexOf("="),f>0&&(l[unescape(d.substring(0,f))]=unescape(d.substring(f+1)))}return l}};g.defer=function(a,b){v++;i(function(){f(a)},b||0)};var t=q;g.hover=function(a){t=a};g.bind=function(){b.bind("mouseover",
+function(a){t(o(S?a.srcElement:a.target),!0);return!0});b.bind("mouseleave mouseout click dblclick keypress keyup",function(a){t(o(a.target),!1);return!0})};g.addCss=function(a){var b=o(y.createElement("link"));b.attr("rel","stylesheet");b.attr("type","text/css");b.attr("href",a);c.append(b)};g.addJs=function(a,b){var d=o(y.createElement("script"));d.attr("type","text/javascript");d.attr("src",a);b&&d.attr("id",b);c.append(d)}}function hb(a,b){function c(a,c,e,f){c=D(c);if(Bb[c])for(;g.last()&&Cb[g.last()];)d("",
+g.last());Db[c]&&g.last()==c&&d("",c);(f=Eb[c]||!!f)||g.push(c);var h={};e.replace(sc,function(a,b,c,d,e){h[b]=Wa(c||d||e||"")});b.start&&b.start(c,h,f)}function d(a,c){var d=0,e;if(c=D(c))for(d=g.length-1;d>=0;d--)if(g[d]==c)break;if(d>=0){for(e=g.length-1;e>=d;e--)b.end&&b.end(g[e]);g.length=d}}var e,f,g=[],h=a;for(g.last=function(){return g[g.length-1]};a;){f=!0;if(!g.last()||!Fb[g.last()]){if(a.indexOf("<\!--")===0)e=a.indexOf("--\>"),e>=0&&(b.comment&&b.comment(a.substring(4,e)),a=a.substring(e+
+3),f=!1);else if(tc.test(a)){if(e=a.match(Gb))a=a.substring(e[0].length),e[0].replace(Gb,d),f=!1}else if(uc.test(a)&&(e=a.match(Hb)))a=a.substring(e[0].length),e[0].replace(Hb,c),f=!1;f&&(e=a.indexOf("<"),f=e<0?a:a.substring(0,e),a=e<0?"":a.substring(e),b.chars&&b.chars(Wa(f)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+g.last()+"[^>]*>","i"),function(a,c){c=c.replace(vc,"$1").replace(wc,"$1");b.chars&&b.chars(Wa(c));return""}),d("",g.last());if(a==h)throw"Parse Error: "+a;h=a}d()}function fa(a){var b=
+{};a=a.split(",");var c;for(c=0;c<a.length;c++)b[a[c]]=!0;return b}function Wa(a){Xa.innerHTML=a.replace(/</g,"&lt;");return Xa.innerText||Xa.textContent||""}function Ib(a){return a.replace(/&/g,"&amp;").replace(xc,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function ib(a){var b=!1,c=F(a,a.push);return{start:function(a,e,f){a=D(a);!b&&Fb[a]&&(b=a);!b&&Jb[a]==!0&&(c("<"),c(a),k(e,function(a,b){var d=D(b);if(yc[d]==!0&&(Kb[d]!==!0||a.match(zc)))c(" "),c(b),
+c('="'),c(Ib(a)),c('"')}),c(f?"/>":">"))},end:function(a){a=D(a);!b&&Jb[a]==!0&&(c("</"),c(a),c(">"));a==b&&(b=!1)},chars:function(a){b||c(Ib(a))}}}function Ac(a){var b={};a=a[0].style;var c,d;if(typeof a.length=="number")for(c=0;c<a.length;c++)d=a[c],b[d]=a[d];else for(d in a)c=a[d],1*d!=d&&d!="cssText"&&c&&typeof c=="string"&&c!="false"&&(b[d]=c);return b}function Na(a){if(w(a)&&a.charAt(0)!="<")throw new K("selectors not implemented");return new V(a)}function V(a){if(a instanceof V)return a;else if(w(a)){var b=
+L.createElement("div");b.innerHTML="<div>&nbsp;</div>"+a;b.removeChild(b.firstChild);Ya(this,b.childNodes);this.remove()}else Ya(this,a)}function ra(a){Lb(a);var b=0;for(a=a.childNodes||[];b<a.length;b++)ra(a[b])}function Lb(a){var b=a[za],c=Aa[b];c&&(k(c.bind||{},function(b,c){Bc(a,c,b)}),delete Aa[b],a[za]=E)}function Za(a,b,c){var d=a[za];d=Aa[d||-1];if(x(c))d||(a[za]=d=Cc++,d=Aa[d]={}),d[b]=c;else return d?d[b]:null}function $a(a,b){var c;return(" "+a.className+" ").replace(/[\n\t]/g," ").indexOf(" "+
+b+" ")>-1}function Mb(a,b){a.className=ia((" "+a.className+" ").replace(/[\n\t]/g," ").replace(" "+b+" ",""))}function Nb(a,b){if(!$a(a,b))a.className=ia(a.className+" "+b)}function Ya(a,b){if(b){b=!b.nodeName&&x(b.length)&&(!b||!b.document||!b.location||!b.alert||!b.setInterval)?b:[b];for(var c=0;c<b.length;c++)a.push(b[c])}}function ga(a,b){u[a]=u[a]||{};k(b,function(b){n(u[a],b)})}function O(a,b,c){var d="";a<0&&(d="-",a=-a);for(a=""+a;a.length<b;)a="0"+a;c&&(a=a.substr(a.length-b));return d+a}
+function G(a,b,c,d){return function(e){e=e["get"+a]();if(c>0||e>-c)e+=c;e===0&&c==-12&&(e=12);return O(e,b,d)}}function ha(a,b){return{format:a,parse:b||a}}function Ob(a){return x(a)&&a!==null?""+a:a}function ab(a){function b(){d=!1;c.$eval()}var c=this,d;return a.isMock?b:function(){d||(d=!0,a.defer(b,ab.delay))}}function Pb(a){var b=Qb[a];if(!b){var c=[];k(Ba(a),function(a){var b=Ca(a);c.push(b?function(a){var c,d=this.$tryEval(b,function(a){c=M(a)});aa(a,xa,c);return c?c:d}:function(){return a})});
+Qb[a]=b=function(a,b){var f=[],g=this.hasOwnProperty(Rb)?this.$element:E;this.$element=a;for(var h=0;h<c.length;h++){var i=c[h].call(this,a);i&&(i.nodeName||i.bind&&i.find)?i="":I(i)&&(i=M(i,b));f.push(i)}this.$element=g;return f.join("")}}return b}function bb(a){return function(b,c){var d=c[0].className+" ";return function(c){this.$onEval(function(){if(a(this.$index)){var f=this.$eval(b);Q(f)&&(f=f.join(" "));c[0].className=ia(d+f)}},c)}}}function Ba(a){for(var b=[],c=0,d;(d=a.indexOf("{{",c))>-1;)c<
+d&&b.push(a.substr(c,d-c)),c=d,d=a.indexOf("}}",d),d=d<0?a.length:d+2,b.push(a.substr(c,d-c)),c=d;c!=a.length&&b.push(a.substr(c,a.length-c));return b.length===0?[a]:b}function Ca(a){return(a=a.replace(/\n/gm," ").match(/^\{\{(.*)\}\}$/))?a[1]:null}function sa(a,b){var c=b.attr("name"),d;if(c){d=da(c).assignable().assign;if(!d)throw new K("Expression '"+c+"' is not assignable.");return{get:function(){return a.$eval(c)},set:function(c){if(c!==E)return a.$tryEval(function(){d(a,c)},b)}}}}function cb(a,
+b){var c=sa(a,b),d=b.attr("ng:format")||Da,e=da(d).formatter()();if(c)return{get:function(){return e.format(a,c.get())},set:function(b){return c.set(e.parse(a,b))}}}function db(a,b){function c(){var c=ia(b.val());if(b[0].disabled||b[0].readOnly)aa(b,ta,null),p.markValid(b);else{var d=Yb(a,{$element:b});c=v&&!c?"Required":c?e(d,c):null;aa(b,ta,c);(j=c)?p.markInvalid(b):p.markValid(b)}}var d=b.attr("ng:validate")||Da,e=da(d).validator()(),f=b.attr("ng:required"),g=b.attr("ng:format")||Da;g=da(g).formatter()();
+var h,i,j,v,p=a.$service("$invalidWidgets")||{markValid:q,markInvalid:q};if(!e)throw"Validator named '"+d+"' not found.";h=g.format;i=g.parse;f?a.$watch(f,function(a){v=a;c()}):v=f==="";b.data(eb,c);return{get:function(){j&&aa(b,ta,null);try{var d=i(a,b.val());c();return d}catch(e){j=e,aa(b,ta,e)}},set:function(d){var e=b.val();d=h(a,d);e!=d&&b.val(d||"");c()}}}function Sb(a,b){var c=b.attr("ng:format")||Da,d=da(c).formatter()();return{get:function(){var c=[];k(b[0].options,function(b){b.selected&&
+c.push(d.parse(a,b.value))});return c},set:function(c){var f={};k(c,function(b){f[d.format(a,b)]=!0});k(b[0].options,function(a){a.selected=f[a.value]})}}}function Tb(){return{get:q,set:q}}function Ea(a){return function(b,c){var d=c.get();!d&&x(a)&&(d=A(a));z(b.get())&&x(d)&&b.set(d)}}function la(a,b,c,d,e){return n(function(f,g,h){var i=this,j=b(i,h),v=c(i,h),p=h.attr("ng:change")||"",r;j&&(d.call(i,j,v,h),this.$eval(h.attr("ng:init")||""),h.bind(a,function(a){function b(){var a=v.get();if(!e||a!=
+r)j.set(a),r=j.get(),i.$tryEval(p,h),f()}a.type=="keydown"?g(b):b()}),i.$watch(j.get,function(a){r!==a&&v.set(r=a)}))},{$inject:["$updateView","$defer"]})}function Fa(a){this.directives(!0);this.descend(!0);return Dc[D(a[0].type)]||q}if(typeof L.getAttribute==$)L.getAttribute=function(){};var D=function(a){return w(a)?a.toLowerCase():a},fb=function(a){return w(a)?a.toUpperCase():a},Rb="$element",eb="$validate",gc="boolean",R="function",Wb="length",Xb="name",wa="null",$b="number",gb="object",Zb="string",
+$="undefined",xa="ng-exception",ta="ng-validation-error",Da="noop",yb=-1E3,Ec={FIRST:-99999,LAST:99999,WATCH:yb},K=s.Error,S=parseInt((/msie (\d+)/.exec(D(navigator.userAgent))||[])[1],10),o,Ma,ba=[].slice,H=[].push,fc=s.console?F(s.console,s.console.error||q):q,u=s.angular||(s.angular={}),Ja=P(u,"markup"),nb=P(u,"attrMarkup"),B=P(u,"directive"),J=P(u,"widget",D),Va=P(u,"validator"),N=P(u,"filter"),Y=P(u,"formatter"),Ta=P(u,"service");P(u,"callbacks");var pa,ec=/^(|.*\/)angular(-.*?)?(\.min)?.js(\?[^#]*)?(#(.*))?$/,
+sb=24;pa=S<9?function(a){a=a.nodeName?a:a[0];return a.scopeName&&a.scopeName!="HTML"?fb(a.scopeName+":"+a.nodeName):a.nodeName}:function(a){return a.nodeName?a.nodeName:a[0].nodeName};u.toJson=M;u.fromJson=ca;Qa.prototype={attach:function(a,b){var c={};this.collectInits(a,c,b);Ga(c,function(a){k(a,function(a){a()})})},collectInits:function(a,b,c){var d=b[this.priority],e=c;d||(b[this.priority]=d=[]);this.newScope&&(e=T(c),c.$onEval(e.$eval),a.data("$scope",e));k(this.inits,function(b){d.push(function(){e.$tryEval(function(){return e.$service(b,
+e,a)},a)})});var f=a[0].childNodes,g=this.children,h=this.paths,i=h.length;for(c=0;c<i;c++)g[c].collectInits(o(f[h[c]]),b,e)},addInit:function(a){a&&this.inits.push(a)},addChild:function(a,b){b&&(this.paths.push(a),this.children.push(b))},empty:function(){return this.inits.length===0&&this.paths.length===0}};mb.prototype={compile:function(a){a=o(a);var b=0,c,d=a.parent();if(d&&d[0]){d=d[0];for(var e=0;e<d.childNodes.length;e++)d.childNodes[e]==a[0]&&(b=e)}c=this.templatize(a,b,0)||new Qa;return function(b,
+d){var e=d?qb.clone.call(a):a;b=b||T();e.data("$scope",b);b.$element=e;(d||q)(e,b);c.attach(e,b);b.$eval();return b}},templatize:function(a,b,c){var d=this,e,f,g=d.directives,h=!0,i=!0,j=pa(a),v=j.indexOf(":")>0?D(j).replace(":","-"):"",p,r={compile:F(d,d.compile),descend:function(a){x(a)&&(h=a);return h},directives:function(a){x(a)&&(i=a);return i},scope:function(a){if(x(a))p.newScope=p.newScope||a;return p.newScope}};try{c=a.attr("ng:eval-order")||c||0}catch(y){c=c||0}a.addClass(v);w(c)&&(c=Ec[fb(c)]||
+parseInt(c,10));p=new Qa(c);va(a,function(b,c){if(!e&&(e=d.widgets("@"+c)))a.addClass("ng-attr-widget"),e=F(r,e,b,a)});if(!e&&(e=d.widgets(j)))v&&a.addClass("ng-widget"),e=F(r,e,a);e&&(i=h=!1,j=a.parent(),p.addInit(e.call(r,a)),j&&j[0]&&(a=o(j[0].childNodes[b])));if(h)for(var l=0,n=a[0].childNodes;l<n.length;l++)pa(n[l])=="#text"&&k(d.markup,function(b){if(l<n.length){var c=o(n[l]);b.call(r,c.text(),c,a)}});i&&(va(a,function(b,c){k(d.attrMarkup,function(d){d.call(r,b,c,a)})}),va(a,function(b,c){if(f=
+g[c])a.addClass("ng-directive"),p.addInit(g[c].call(r,b,a))}));h&&tb(a,function(a,b){p.addChild(b,d.templatize(a,b,c))});return p.empty()?null:p}};var hc=0,vb={},xb={},wb={};k("abstract,boolean,break,byte,case,catch,char,class,const,continue,debugger,default,delete,do,double,else,enum,export,extends,false,final,finally,float,for,function,goto,if,implements,import,ininstanceof,intinterface,long,native,new,null,package,private,protected,public,return,short,static,super,switch,synchronized,this,throw,throws,transient,true,try,typeof,var,volatile,void,undefined,while,with".split(/,/),
+function(a){wb[a]=!0});var kc=/^function\s*[^\(]*\(([^\)]*)\)/,lc=/,/,mc=/^\s*(((\$?).+?)(_?))\s*$/,jc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ua={"null":function(){return null},"true":function(){return!0},"false":function(){return!1},$undefined:q,"+":function(a,b,c){return(x(b)?b:0)+(x(c)?c:0)},"-":function(a,b,c){return(x(b)?b:0)-(x(c)?c:0)},"*":function(a,b,c){return b*c},"/":function(a,b,c){return b/c},"%":function(a,b,c){return b%c},"^":function(a,b,c){return b^c},"=":q,"==":function(a,b,c){return b==
+c},"!=":function(a,b,c){return b!=c},"<":function(a,b,c){return b<c},">":function(a,b,c){return b>c},"<=":function(a,b,c){return b<=c},">=":function(a,b,c){return b>=c},"&&":function(a,b,c){return b&&c},"||":function(a,b,c){return b||c},"&":function(a,b,c){return b&c},"|":function(a,b,c){return c(a,b)},"!":function(a,b){return!b}},oc={n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'};Ab.prototype={url:function(a){var b=this,c=this.template,d;a=a||{};k(this.urlParams,function(e,g){d=La(a[g]||
+b.defaults[g]||"",!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+");c=c.replace(RegExp(":"+g+"(\\W)"),d+"$1")});c=c.replace(/\/?#$/,"");var e=[];Ga(a,function(a,c){b.urlParams[c]||e.push(La(c)+"="+La(a))});c=c.replace(/\/*$/,"");return c+(e.length?"?"+e.join("&"):"")}};ya.DEFAULT_ACTIONS={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}};ya.prototype={route:function(a,b,c){function d(a){var c={};k(b||{},function(b,
+d){c[d]=b.charAt&&b.charAt(0)=="@"?qa(a,b.substr(1)):b});return c}function e(a){A(a||{},this)}var f=this,g=new Ab(a);c=n({},ya.DEFAULT_ACTIONS,c);k(c,function(h,i){var j=h.method=="POST"||h.method=="PUT";e[i]=function(a,b,c){var i={},l,o=q;switch(arguments.length){case 3:o=c;case 2:if(m(b))o=b;else{i=a;l=b;break}case 1:m(a)?o=a:j?l=a:i=a;break;case 0:break;default:throw"Expected between 0-3 arguments [params, data, callback], got "+arguments.length+" arguments.";}var t=this instanceof e?this:h.isArray?
+[]:new e(l);f.xhr(h.method,g.url(n({},h.params||{},d(l),i)),l,function(a,b){if(200<=a&&a<300){if(b)h.isArray?(t.length=0,k(b,function(a){t.push(new e(a))})):A(b,t);(o||q)(t)}else throw{status:a,response:b,message:a+": "+b};},h.verifyCache);return t};e.bind=function(d){return f.route(a,n({},b,d),c)};e.prototype["$"+i]=function(a,b){var c=d(this),g=q;switch(arguments.length){case 2:c=a,g=b;case 1:typeof a==R?g=a:c=a;case 0:break;default:throw"Expected between 1-2 arguments [params, callback], got "+
+arguments.length+" arguments.";}e[i].call(this,c,j?this:E,g)}});return e}};var Fc=s.XMLHttpRequest||function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(b){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(c){}throw new K("This browser does not support XMLHttpRequest.");},rc={"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json, text/plain, */*","X-Requested-With":"XMLHttpRequest"},Hb=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
+Gb=/^<\s*\/\s*([\w:-]+)[^>]*>/,sc=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,uc=/^</,tc=/^<\s*\//,vc=/<\!--(.*?)--\>/g,wc=/<!\[CDATA\[(.*?)]]\>/g,zc=/^((ftp|https?):\/\/|mailto:|#)/,xc=/([^\#-~| |!])/g,Eb=fa("area,br,col,hr,img"),Bb=fa("address,blockquote,center,dd,del,dir,div,dl,dt,hr,ins,li,map,menu,ol,p,pre,script,table,tbody,td,tfoot,th,thead,tr,ul"),Cb=fa("a,abbr,acronym,b,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,q,s,samp,small,span,strike,strong,sub,sup,tt,u,var"),
+Db=fa("colgroup,dd,dt,li,p,td,tfoot,th,thead,tr"),Fb=fa("script,style"),Jb=n({},Eb,Bb,Cb,Db),Kb=fa("background,href,longdesc,src,usemap"),yc=n({},Kb,fa("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),Xa=L.createElement("pre"),Aa={},za="ng-"+(new Date).getTime(),
+Cc=1,Gc=s.document.addEventListener?function(a,b,c){a.addEventListener(b,c,!1)}:function(a,b,c){a.attachEvent("on"+b,c)},Bc=s.document.removeEventListener?function(a,b,c){a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent("on"+b,c)};S&&n(V.prototype,{text:function(a){var b=this[0];if(b.nodeType==3){if(x(a))b.nodeValue=a;return b.nodeValue}else{if(x(a))b.innerText=a;return b.innerText}}});var qb=V.prototype={ready:function(a){function b(){c||(c=!0,a())}var c=!1;this.bind("DOMContentLoaded",
+b);Na(s).bind("load",b)},toString:function(){var a=[];k(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},length:0,push:H,sort:[].sort,splice:[].splice};k({data:Za,scope:function(a){for(var b;a&&!(b=o(a).data("$scope"));)a=a.parentNode;return b},removeAttr:function(a,b){a.removeAttribute(b)},hasClass:$a,css:function(a,b,c){if(x(c))a.style[b]=c;else return a.style[b]},attr:function(a,b,c){if(x(c))a.setAttribute(b,c);else if(a.getAttribute)return a.getAttribute(b,2)},text:n(S<9?function(a,
+b){if(a.nodeType==3){if(z(b))return a.nodeValue;a.nodeValue=b}else{if(z(b))return a.innerText;a.innerText=b}}:function(a,b){if(z(b))return a.textContent;a.textContent=b},{$dv:""}),val:function(a,b){if(z(b))return a.value;a.value=b},html:function(a,b){if(z(b))return a.innerHTML;for(var c=0,d=a.childNodes;c<d.length;c++)ra(d[c]);a.innerHTML=b}},function(a,b){V.prototype[b]=function(b,d){var e,f;if((a.length==2?b:d)===E)if(I(b)){for(e=0;e<this.length;e++)for(f in b)a(this[e],f,b[f]);return this}else{if(this.length)return a(this[0],
+b,d)}else{for(e=0;e<this.length;e++)a(this[e],b,d);return this}return a.$dv}});k({removeData:Lb,dealoc:ra,bind:function(a,b,c){var d=Za(a,"bind"),e;d||Za(a,"bind",d={});k(b.split(" "),function(b){e=d[b];if(!e)d[b]=e=function(b){if(!b.preventDefault)b.preventDefault=function(){b.returnValue=!1};if(!b.stopPropagation)b.stopPropagation=function(){b.cancelBubble=!0};k(e.fns,function(c){c.call(a,b)})},e.fns=[],Gc(a,b,e);e.fns.push(c)})},replaceWith:function(a,b){var c,d=a.parentNode;ra(a);k(new V(b),function(b){c?
+d.insertBefore(b,c.nextSibling):d.replaceChild(b,a);c=b})},children:function(a){var b=[];k(a.childNodes,function(a){a.nodeName!="#text"&&b.push(a)});return b},append:function(a,b){k(new V(b),function(b){a.nodeType===1&&a.appendChild(b)})},remove:function(a){ra(a);var b=a.parentNode;b&&b.removeChild(a)},after:function(a,b){var c=a,d=a.parentNode;k(new V(b),function(a){d.insertBefore(a,c.nextSibling);c=a})},addClass:Nb,removeClass:Mb,toggleClass:function(a,b,c){z(c)&&(c=!$a(a,b));(c?Nb:Mb)(a,b)},parent:function(a){return(a=
+a.parentNode)&&a.nodeType!==11?a:null},next:function(a){return a.nextSibling},find:function(a,b){return a.getElementsByTagName(b)},clone:function(a){return a.cloneNode(!0)}},function(a,b){V.prototype[b]=function(b,d){for(var e,f=0;f<this.length;f++)e==E?(e=a(this[f],b,d),e!==E&&(e=o(e))):Ya(e,a(this[f],b,d));return e==E?this:e}});H={typeOf:function(a){if(a===null)return wa;var b=typeof a;if(b==gb){if(a instanceof Array)return"array";if(a instanceof Date)return"date";if(a.nodeType==1)return"element"}return b}};
+var W={copy:A,size:jb,equals:oa},Hc={extend:n},Ic={indexOf:na,sum:function(a,b){for(var c=u.Function.compile(b),d=0,e=0;e<a.length;e++){var f=1*c(a[e]);isNaN(f)||(d+=f)}return d},remove:function(a,b){var c=na(a,b);c>=0&&a.splice(c,1);return b},filter:function(a,b){var c=[];c.check=function(a){for(var b=0;b<c.length;b++)if(!c[b](a))return!1;return!0};var d=function(a,b){if(b.charAt(0)==="!")return!d(a,b.substr(1));switch(typeof a){case "boolean":case "number":case "string":return(""+a).toLowerCase().indexOf(b)>
+-1;case "object":for(var c in a)if(c.charAt(0)!=="$"&&d(a[c],b))return!0;return!1;case "array":for(c=0;c<a.length;c++)if(d(a[c],b))return!0;return!1;default:return!1}};switch(typeof b){case "boolean":case "number":case "string":b={$:b};case "object":for(var e in b)e=="$"?function(){var a=(""+b[e]).toLowerCase();a&&c.push(function(b){return d(b,a)})}():function(){var a=e,g=(""+b[e]).toLowerCase();g&&c.push(function(b){return d(qa(b,a),g)})}();break;case R:c.push(b);break;default:return a}for(var f=
+[],g=0;g<a.length;g++){var h=a[g];c.check(h)&&f.push(h)}return f},add:function(a,b){a.push(z(b)?{}:b);return a},count:function(a,b){if(!b)return a.length;var c=u.Function.compile(b),d=0;k(a,function(a){c(a)&&d++});return d},orderBy:function(a,b,c){function d(a,b){return ja(b)?function(b,c){return a(c,b)}:a}function e(a,b){var c=typeof a,d=typeof b;if(c==d){c=="string"&&(a=a.toLowerCase());c=="string"&&(b=b.toLowerCase());if(a===b)return 0;return a<b?-1:1}else return c<d?-1:1}b=Q(b)?b:[b];b=ac(b,function(a){var b=
+!1,c=a||Z;if(w(a)){if(a.charAt(0)=="+"||a.charAt(0)=="-")b=a.charAt(0)=="-",a=a.substring(1);c=ea(a).fnSelf}return d(function(a,b){return e(c(a),c(b))},b)});for(var f=[],g=0;g<a.length;g++)f.push(a[g]);return f.sort(d(function(a,c){for(var d=0;d<b.length;d++){var e=b[d](a,c);if(e!==0)return e}return 0},c))},limitTo:function(a,b){b=parseInt(b,10);var c=[],d,e;b>0?(d=0,e=b):(d=a.length+b,e=a.length);for(;d<e;d++)c.push(a[d]);return c}},Jc=/^(\d{4})-(\d\d)-(\d\d)(?:T(\d\d)(?:\:(\d\d)(?:\:(\d\d)(?:\.(\d{3}))?)?)?Z)?$/,
+Pa={quote:function(a){return'"'+a.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\f/g,"\\f").replace(/\r/g,"\\r").replace(/\t/g,"\\t").replace(/\v/g,"\\v")+'"'},quoteUnicode:function(a){a=u.String.quote(a);for(var b=[],c=0;c<a.length;c++){var d=a.charCodeAt(c);d<128?b.push(a.charAt(c)):(d="000"+d.toString(16),b.push("\\u"+d.substring(d.length-4)))}return b.join("")},toDate:function(a){var b;if(w(a)&&(b=a.match(Jc)))a=new Date(0),a.setUTCFullYear(b[1],b[2]-1,b[3]),a.setUTCHours(b[4]||
+0,b[5]||0,b[6]||0,b[7]||0);return a}},Ub={toString:function(a){return!a?a:a.toISOString?a.toISOString():O(a.getUTCFullYear(),4)+"-"+O(a.getUTCMonth()+1,2)+"-"+O(a.getUTCDate(),2)+"T"+O(a.getUTCHours(),2)+":"+O(a.getUTCMinutes(),2)+":"+O(a.getUTCSeconds(),2)+"."+O(a.getUTCMilliseconds(),3)+"Z"}};ga("Global",[H]);ga("Collection",[H,W]);ga("Array",[H,W,Ic]);ga("Object",[H,W,Hc]);ga("String",[H,Pa]);ga("Date",[H,Ub]);u.Date.toString=Ub.toString;ga("Function",[H,W,{compile:function(a){return m(a)?a:a?
+ea(a).fnSelf:Z}}]);N.currency=function(a){this.$element.toggleClass("ng-format-negative",a<0);return"$"+N.number.apply(this,[a,2])};N.number=function(a,b){if(isNaN(a)||!isFinite(a))return"";b=typeof b==$?2:b;var c=a<0;a=Math.abs(a);var d=""+Math.round(a*Math.pow(10,b)),e=d.substring(0,d.length-b);e=e||"0";var f=d.substring(d.length-b);d=c?"-":"";for(c=0;c<e.length;c++)(e.length-c)%3===0&&c!==0&&(d+=","),d+=e.charAt(c);if(b>0){for(e=f.length;e<b;e++)f+="0";d+="."+f.substring(0,b)}return d};var Kc=
+{yyyy:G("FullYear",4),yy:G("FullYear",2,0,!0),MM:G("Month",2,1),M:G("Month",1,1),dd:G("Date",2),d:G("Date",1),HH:G("Hours",2),H:G("Hours",1),hh:G("Hours",2,-12),h:G("Hours",1,-12),mm:G("Minutes",2),m:G("Minutes",1),ss:G("Seconds",2),s:G("Seconds",1),a:function(a){return a.getHours()<12?"am":"pm"},Z:function(a){a=a.getTimezoneOffset();return O(a/60,2)+O(Math.abs(a%60),2)}},Lc=/([^yMdHhmsaZ]*)(y+|M+|d+|H+|h+|m+|s+|a|Z)(.*)/,Mc=/^\d+$/;N.date=function(a,b){w(a)&&(a=Mc.test(a)?parseInt(a,10):Pa.toDate(a));
+ma(a)&&(a=new Date(a));if(!(a instanceof Date))return a;var c=a.toLocaleDateString(),d;if(b&&w(b)){c="";for(var e=[],f;b;)(f=Lc.exec(b))?(e=e.concat(ba.call(f,1,f.length)),b=e.pop()):(e.push(b),b=null);k(e,function(b){d=Kc[b];c+=d?d(a):b})}return c};N.json=function(a){this.$element.addClass("ng-monospace");return M(a,!0)};N.lowercase=D;N.uppercase=fb;N.html=function(a,b){return new Ia(a,b)};N.linky=function(a){if(!a)return a;for(var b=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
+c=a,d=[],e=ib(d),f,g;a=c.match(b);)f=a[0],a[2]==a[3]&&(f="mailto:"+f),g=a.index,e.chars(c.substr(0,g)),e.start("a",{href:f}),e.chars(a[0].replace(/^mailto:/,"")),e.end("a"),c=c.substring(g+a[0].length);e.chars(c);return new Ia(d.join(""))};var Nc=/^\s*[-+]?\d*(\.\d*)?\s*$/;Y.noop=ha(Z,Z);Y.json=ha(M,function(a){return ca(a||"null")});Y["boolean"]=ha(Ob,ja);Y.number=ha(Ob,function(a){if(a==null||Nc.exec(a))return a===null||a===""?null:1*a;else throw"Not a number";});Y.list=ha(function(a){return a?
+a.join(", "):a},function(a){var b=[];k((a||"").split(","),function(a){(a=ia(a))&&b.push(a)});return b});Y.trim=ha(function(a){return a?ia(""+a):""});Y.index=ha(function(a,b){return""+na(b||[],a)},function(a,b){return(b||[])[a]});n(Va,{noop:function(){return null},regexp:function(a,b,c){return a.match(b)?null:c||"Value does not match expected format "+b+"."},number:function(a,b,c){var d=1*a;if(d==a){if(typeof b!=$&&d<b)return"Value can not be less than "+b+".";if(typeof b!=$&&d>c)return"Value can not be greater than "+
+c+".";return null}else return"Not a number"},integer:function(a,b,c){if(b=Va.number(a,b,c))return b;if(!(""+a).match(/^\s*[\d+]*\s*$/)||a!=Math.round(a))return"Not a whole number";return null},date:function(a){var b=(a=/^(\d\d?)\/(\d\d?)\/(\d\d\d\d)$/.exec(a))?new Date(a[3],a[1]-1,a[2]):0;return b&&b.getFullYear()==a[3]&&b.getMonth()==a[1]-1&&b.getDate()==a[2]?null:"Value is not a date. (Expecting format: 12/31/2009)."},email:function(a){if(a.match(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/))return null;
+return"Email needs to be in username@host.com format."},phone:function(a){if(a.match(/^1\(\d\d\d\)\d\d\d-\d\d\d\d$/))return null;if(a.match(/^\+\d{2,3} (\(\d{1,5}\))?[\d ]+\d$/))return null;return"Phone number needs to be in 1(987)654-3210 format in North America or +999 (123) 45678 906 internationaly."},url:function(a){if(a.match(/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/))return null;return"URL needs to be in http://server[:port]/path format."},json:function(a){try{return ca(a),
+null}catch(b){return b.toString()}},asynchronous:function(a,b,c){if(a){var d=this,e=d.$element,f=e.data("$asyncValidator");f||e.data("$asyncValidator",f={inputs:{}});f.current=a;var g=f.inputs[a],h=d.$service("$invalidWidgets");g?g.inFlight?h.markInvalid(d.$element):(c||q)(g.response):(f.inputs[a]=g={inFlight:!0},h.markInvalid(d.$element),e.addClass("ng-input-indicator-wait"),b(a,function(b,c){g.response=c;g.error=b;g.inFlight=!1;f.current==a&&(e.removeClass("ng-input-indicator-wait"),h.markValid(e));
+e.data(eb)();d.$service("$updateView")()}));return g.error}}});C("$cookieStore",function(a){return{get:function(b){return ca(a[b])},put:function(b,c){a[b]=M(c)},remove:function(b){delete a[b]}}},["$cookies"]);C("$cookies",function(a){var b=this,c={},d={},e,f=!1;a.addPollFn(function(){var g=a.cookies();e!=g&&(e=g,A(g,d),A(g,c),f&&b.$eval())})();f=!0;this.$onEval(99999,function(){var b,e,f;for(b in d)z(c[b])&&a.cookies(b,E);for(b in c)e=c[b],w(e)?e!==d[b]&&(a.cookies(b,e),f=!0):x(d[b])?c[b]=d[b]:delete c[b];
+if(f)for(b in e=a.cookies(),c)c[b]!==e[b]&&(z(e[b])?delete c[b]:c[b]=e[b])});return c},["$browser"]);C("$defer",function(a,b,c){return function(d,e){a.defer(function(){try{d()}catch(a){b(a)}finally{c()}},e)}},["$browser","$exceptionHandler","$updateView"]);C("$document",function(a){return o(a.document)},["$window"]);C("$exceptionHandler",function(a){return function(b){a.error(b)}},["$log"]);C("$hover",function(a,b){var c,d,e=o(b[0].body);a.hover(function(a,b){if(b&&(d=a.attr(xa)||a.attr(ta))){c||
+(c={callout:o('<div id="ng-callout"></div>'),arrow:o("<div></div>"),title:o('<div class="ng-title"></div>'),content:o('<div class="ng-content"></div>')},c.callout.append(c.arrow),c.callout.append(c.title),c.callout.append(c.content),e.append(c.callout));var h=e[0].getBoundingClientRect(),i=a[0].getBoundingClientRect();h=h.right-i.right-10;c.title.text(a.hasClass("ng-exception")?"EXCEPTION:":"Validation error...");c.content.text(d);h<300?(c.arrow.addClass("ng-arrow-right"),c.arrow.css({left:"301px"}),
+c.callout.css({position:"fixed",left:i.left-10-300-4+"px",top:i.top-3+"px",width:"300px"})):(c.arrow.addClass("ng-arrow-left"),c.callout.css({position:"fixed",left:i.right+10+"px",top:i.top-3+"px",width:"300px"}))}else c&&(c.callout.remove(),c=null)})},["$browser","$document"],!0);C("$invalidWidgets",function(){function a(b){if(b==s.document)return!1;b=b.parentNode;return!b||a(b)}var b=[];b.markValid=function(a){a=na(b,a);a!=-1&&b.splice(a,1)};b.markInvalid=function(a){na(b,a)===-1&&b.push(a)};b.visible=
+function(){var a=0;k(b,function(b){var e=a;b=b[0].getBoundingClientRect();var f=b.height||b.bottom||0-b.top||0;a=e+((b.width||b.right||0-b.left||0)>0&&f>0?1:0)});return a};this.$onEval(99999,function(){for(var c=0;c<b.length;){var d=b[c];a(d[0])?(b.splice(c,1),d.dealoc&&d.dealoc()):c++}});return b});var Oc=/^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,Pc=/^([^\?]*)?(\?([^\?]*))?$/,Vb={http:80,https:443,ftp:21};C("$location",function(a){function b(a){if(w(a)){var b=
+n,c=i,d={},h=Oc.exec(a);if(h)d.href=a.replace(/#$/,""),d.protocol=h[1],d.host=h[3]||"",d.port=h[5]||Vb[d.protocol]||null,d.path=h[6]||"",d.search=Ka(h[8]),d.hash=h[10]||"",n(d,g(d.hash));b(c,d)}else{x(a.hash)&&n(a,w(a.hash)?g(a.hash):a.hash);n(i,a);if(x(a.hashPath||a.hashSearch))i.hash=f(i);i.href=e(i)}}function c(a,c){var d={};w(a)?(d.hashPath=a,d.hashSearch=c||{}):d.hashSearch=a;d.hash=f(d);b({hash:d})}function d(){if(!oa(i,j)){if(i.href==j.href)if(i.hash!=j.hash){var a=g(i.hash);c(a.hashPath,a.hashSearch)}else i.hash=
+f(i),i.href=e(i);b(i.href)}}function e(a){var b=ob(a.search),c=a.port==Vb[a.protocol]?null:a.port;return a.protocol+"://"+a.host+(c?":"+c:"")+a.path+(b?"?"+b:"")+(a.hash?"#"+a.hash:"")}function f(a){var b=ob(a.hashSearch);return escape(a.hashPath).replace(/%21/gi,"!").replace(/%3A/gi,":").replace(/%24/gi,"$")+(b?"?"+b:"")}function g(a){var b={},c=Pc.exec(a);if(c)b.hash=a,b.hashPath=unescape(c[1]||""),b.hashSearch=Ka(c[3]);return b}var h=this,i={update:b,updateHash:c},j={};a.onHashChange(function(){b(a.getUrl());
+A(i,j);h.$eval()})();this.$onEval(-99999,d);this.$onEval(99999,function(){d();a.getUrl()!=i.href&&(a.setUrl(i.href),A(i,j))});return i},["$browser"]);C("$log",function(a){function b(b){var d=a.console||{},e=d[b]||d.log||q;return e.apply?function(){var a=[];k(arguments,function(b){a.push(Ha(b))});return e.apply(d,a)}:e}return{log:b("log"),warn:b("warn"),info:b("info"),error:b("error")}},["$window"]);C("$resource",function(a){a=new ya(a);return F(a,a.route)},["$xhr.cache"]);C("$route",function(a,b){var c=
+{},d=[],e=function(a,b,c){var d="^"+b.replace(/[\.\\\(\)\^\$]/g,"$1")+"$",e=[],g={};k(b.split(/\W/),function(a){if(a){var b=RegExp(":"+a+"([\\W])");d.match(b)&&(d=d.replace(b,"([^/]*)$1"),e.push(a))}});var f=a.match(RegExp(d));f&&(k(e,function(a,b){g[a]=f[b+1]}),c&&this.$set(c,g));return f?g:null},f=this,g=0,h={routes:c,onChange:function(a){d.push(a);return a},parent:function(a){a&&(f=a)},when:function(a,b){if(z(a))return c;var d=c[a];d||(d=c[a]={});b&&n(d,b);g++;return d},otherwise:function(a){h.when(null,
+a)},reload:function(){g++}};this.$watch(function(){return g+a.hash},function(){var g,j,v,p,r,y;h.current=null;k(c,function(b,c){if(!v&&(v=e(a.hashPath,c)))j=b});if(j=j||c[null]){if(j.redirectTo){w(j.redirectTo)?(y={hashPath:"",hashSearch:n({},a.hashSearch,v)},k(j.redirectTo.split(":"),function(b,c){c==0?y.hashPath+=b:(p=b.match(/(\w+)(.*)/),r=p[1],y.hashPath+=v[r]||a.hashSearch[r],y.hashPath+=p[2]||"",delete y.hashSearch[r])})):y={hash:j.redirectTo(v,a.hash,a.hashPath,a.hashSearch)};a.update(y);b();
+return}g=T(f);h.current=n({},j,{scope:g,params:n({},a.hashSearch,v)})}k(d,f.$tryEval);g&&g.$become(h.current.controller)});return h},["$location","$updateView"]);ab.delay=25;C("$updateView",ab,["$browser"]);C("$window",F(s,Z,s));C("$xhr.bulk",function(a,b,c){function d(b,c,e,i){m(e)&&(i=e,e=null);var j;k(d.urls,function(a){if(m(a.match)?a.match(c):a.match.exec(c))j=a});if(j){if(!j.requests)j.requests=[];j.requests.push({method:b,url:c,data:e,callback:i})}else a(b,c,e,i)}var e=this;d.urls={};d.flush=
+function(f){k(d.urls,function(d,h){var i=d.requests;if(i&&i.length)d.requests=[],d.callbacks=[],a("POST",h,{requests:i},function(a,d){k(d,function(a,d){try{a.status==200?(i[d].callback||q)(a.status,a.response):b(i[d],a)}catch(e){c.error(e)}});(f||q)()}),e.$eval()})};this.$onEval(99999,d.flush);return d},["$xhr","$xhr.error","$log"]);C("$xhr.cache",function(a,b,c){function d(a,g,h,i,j,v){m(h)&&(i=h,h=null);if(a=="GET"){var p;if(p=d.data[g])if(v?i(200,A(p.value)):b(function(){i(200,A(p.value))}),!j)return;
+(j=e[g])?j.callbacks.push(i):(e[g]={callbacks:[i]},d.delegate(a,g,h,function(a,b){a==200&&(d.data[g]={value:b});var f=e[g].callbacks;delete e[g];k(f,function(d){try{(d||q)(a,A(b))}catch(e){c.error(e)}})}))}else d.data={},d.delegate(a,g,h,i)}var e={};d.data={};d.delegate=a;return d},["$xhr.bulk","$defer","$log"]);C("$xhr.error",function(a){return function(b,c){a.error("ERROR: XHR: "+b.url,b,c)}},["$log"]);C("$xhr",function(a,b,c,d){return function(e,f,g,h){m(g)&&(h=g,g=null);g&&I(g)&&(g=M(g));a.xhr(e,
+f,g,function(a,j){try{w(j)&&(j.match(/^\)\]\}',\n/)&&(j=j.substr(6)),/^\s*[\[\{]/.exec(j)&&/[\}\]]\s*$/.exec(j)&&(j=ca(j,!0))),200<=a&&a<300?h(a,j):b({method:e,url:f,data:g,callback:h},{status:a,body:j})}catch(k){c.error(k)}finally{d()}},{"X-XSRF-TOKEN":a.cookies()["XSRF-TOKEN"]})}},["$browser","$xhr.error","$log","$updateView"]);B("ng:init",function(a){return function(b){this.$tryEval(a,b)}});B("ng:controller",function(a){this.scope(!0);return function(){var b=qa(s,a,!0)||qa(this,a,!0);if(!b)throw"Can not find '"+
+a+"' controller.";if(!m(b))throw"Reference '"+a+"' is not a class.";this.$become(b)}});B("ng:eval",function(a){return function(b){this.$onEval(a,b)}});B("ng:bind",function(a,b){b.addClass("ng-binding");return function(b){var d=q,e=q;this.$onEval(function(){var f,g,h,i,j;i=this.hasOwnProperty(Rb)?this.$element:E;this.$element=b;g=this.$tryEval(a,function(a){f=Ha(a)});this.$element=i;if(i=g instanceof Ia)g=(h=g).html;if(!(d===g&&e==f)&&(j=g&&(g.nodeName||g.bind&&g.find),!i&&!j&&I(g)&&(g=M(g,!0)),g!=
+d||f!=e))d=g,e=f,aa(b,xa,f),f&&(g=f),i?b.html(h.get()):j?(b.html(""),b.append(g)):b.text(g==E?"":g)},b)}});var Qb={};B("ng:bind-template",function(a,b){b.addClass("ng-binding");var c=Pb(a);return function(a){var b;this.$onEval(function(){var f=c.call(this,a,!0);f!=b&&(a.text(f),b=f)},a)}});var Qc={disabled:"disabled",readonly:"readOnly",checked:"checked",selected:"selected"};B("ng:bind-attr",function(a){return function(b){var c={},d=b.data("$update")||q;this.$onEval(function(){var e=this.$eval(a),
+f=q,g;for(g in e){var h=Pb(e[g]).call(this,b),i=Qc[D(g)];c[g]!==h&&(c[g]=h,i?(ja(h)?(b.attr(i,i),b.attr("ng-"+i,h)):(b.removeAttr(i),b.removeAttr("ng-"+i)),(b.data(eb)||q)()):b.attr(g,h),f=d)}f()},b)}});B("ng:click",function(a){return n(function(b,c){var d=this;c.bind("click",function(e){d.$tryEval(a,c);b();e.stopPropagation()})},{$inject:["$updateView"]})});B("ng:submit",function(a){return n(function(b,c){var d=this;c.bind("submit",function(e){d.$tryEval(a,c);b();e.preventDefault()})},{$inject:["$updateView"]})});
+B("ng:class",bb(function(){return!0}));B("ng:class-odd",bb(function(a){return a%2===0}));B("ng:class-even",bb(function(a){return a%2===1}));B("ng:show",function(a){return function(b){this.$onEval(function(){b.css("display",ja(this.$eval(a))?"":"none")},b)}});B("ng:hide",function(a){return function(b){this.$onEval(function(){b.css("display",ja(this.$eval(a))?"none":"")},b)}});B("ng:style",function(a){return function(b){var c=Ac(b);this.$onEval(function(){var d=this.$eval(a)||{},e,f={};for(e in d)c[e]===
+E&&(c[e]=""),f[e]=d[e];for(e in c)f[e]=f[e]||c[e];b.css(f)},b)}});Ja("{{}}",function(a,b,c){var d=Ba(a);if(d.length>1||Ca(d[0])!==null)if(bc(c[0]))c.attr("ng:bind-template",a);else{var e=b,f;k(Ba(a),function(a){var b=Ca(a);b?(f=o("<span>"),f.attr("ng:bind",b)):f=o(L.createTextNode(a));S&&a.charAt(0)==" "&&(f=o("<span>&nbsp;</span>"),b=f.html(),f.text(a.substr(1)),f.html(b+f.html()));e.after(f);e=f});b.remove()}});Ja("option",function(a,b,c){D(pa(c))=="option"&&(S<=7?hb(c[0].outerHTML,{start:function(b,
+e){z(e.value)&&c.attr("value",a)}}):c[0].getAttribute("value")==null&&c.attr("value",a))});var Rc={"ng:src":"src","ng:href":"href"};nb("{{}}",function(a,b,c){if(!B(b)&&!B("@"+b)){S&&b=="src"&&(a=decodeURI(a));var d=Ba(a);if(d.length>1||Ca(d[0])!==null)c.removeAttr(b),d=ca(c.attr("ng:bind-attr")||"{}"),d[Rc[b]||b]=a,c.attr("ng:bind-attr",M(d))}});H=la("keydown change",sa,db,Ea(),!0);W=la("click",Tb,Tb,q);var Dc={text:H,textarea:H,hidden:H,password:H,button:W,submit:W,reset:W,image:W,checkbox:la("click",
+cb,function(a,b){var c=b[0];return{get:function(){return!!c.checked},set:function(a){c.checked=ja(a)}}},Ea(!1)),radio:la("click",cb,function(a,b){var c=b[0];return{get:function(){return c.checked?c.value:null},set:function(a){c.checked=a==c.value}}},function(a,b,c){var d=a.get(),e=b.get();c=c[0];c.checked=!1;c.name=this.$id+"@"+c.name;z(d)&&a.set(d=null);d==null&&e!==null&&a.set(e);b.set(d)}),"select-one":la("change",sa,db,Ea(null)),"select-multiple":la("change",sa,Sb,Ea([]))};J("input",Fa);J("textarea",
+Fa);J("button",Fa);J("select",function(a){this.descend(!0);return Fa.call(this,a)});J("option",function(){this.descend(!0);this.directives(!0);return function(a){var b=a.parent(),c=b[0].type=="select-multiple",d=b.scope(),e=sa(d,b);if(e){var f=cb(d,b),g=c?Sb(d,b):db(d,b),h=a.attr("value"),i=a.attr("ng-selected");a.data("$update",c?function(){g.set(e.get())}:function(){var b=a.attr("value"),c=a.attr("ng-selected"),d=e.get();if(i!=c||h!=b)i=c,h=b,(c||!d==null||d==E)&&f.set(b),b==d&&g.set(h)})}}});J("ng:include",
+function(a){var b=this,c=a.attr("src"),d=a.attr("scope")||"",e=a[0].getAttribute("onload")||"";if(a[0]["ng:compiled"])this.descend(!0),this.directives(!0);else return a[0]["ng:compiled"]=!0,n(function(a,g){function h(){k++}var i=this,j,k=0,p=!1;this.$watch(c,h);this.$watch(d,h);i.$onEval(function(){if(j&&!p){p=!0;try{j.$eval()}finally{p=!1}}});this.$watch(function(){return k},function(){var h=this.$eval(c),k=this.$eval(d);h?a("GET",h,null,function(a,c){g.html(c);j=k||T(i);b.compile(g)(j);i.$eval(e)},
+!1,!0):(j=null,g.html(""))})},{$inject:["$xhr.cache"]})});var Sc=J("ng:switch",function(a){var b=this,c=a.attr("on"),d=a.attr("using")||"equals",e=d.split(":"),f=Sc[e.shift()],g=a.attr("change")||"",h=[];if(!f)throw"Using expression '"+d+"' unknown.";if(!c)throw"Missing 'on' attribute.";tb(a,function(a){var c=a.attr("ng:switch-when"),d={change:g,element:a,template:b.compile(a)};if(w(c))d.when=function(a,b){var d=[b,c];k(e,function(a){d.push(a)});return f.apply(a,d)},h.unshift(d);else if(w(a.attr("ng:switch-default")))d.when=
+ua(!0),h.push(d)});k(h,function(a){a.element.remove()});a.html("");return function(a){var b=this,d;this.$watch(c,function(c){var e=!1;a.html("");d=T(b);k(h,function(b){!e&&b.when(d,c)&&(e=!0,d.$tryEval(b.change,a),b.template(d,function(b){a.append(b)}))})});b.$onEval(function(){d&&d.$eval()})}},{equals:function(a,b){return""+a==b}});J("a",function(){this.descend(!0);this.directives(!0);return function(a){a.attr("href")===""&&a.bind("click",function(a){a.preventDefault()})}});J("@ng:repeat",function(a,
+b){b.removeAttr("ng:repeat");b.replaceWith(o("<\!-- ng:repeat: "+a+" --!>"));var c=this.compile(b);return function(d){var e=a.match(/^\s*(.+)\s+in\s+(.*)\s*$/),f,g,h,i;if(!e)throw K("Expected ng:repeat in form of 'item in collection' but got '"+a+"'.");f=e[1];g=e[2];e=f.match(/^([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\)$/);if(!e)throw K("'item' in 'item in collection' should be identifier or (key, value) but got '"+keyValue+"'.");h=e[3]||e[1];i=e[2];var j=[],k=this;this.$onEval(function(){var a=0,e=
+j.length,f=d,l=this.$tryEval(g,d),n=jb(l,!0),t=b[0].nodeName!="OPTION"?L.createDocumentFragment():null,s,m,q;for(q in l)if(l.hasOwnProperty(q))a<e?(m=j[a],m[h]=l[q],i&&(m[i]=q),f=m.$element,m.$eval()):(m=T(k),m[h]=l[q],i&&(m[i]=q),m.$index=a,m.$position=a==0?"first":a==n-1?"last":"middle",j.push(m),c(m,function(b){b.attr("ng:repeat-index",a);t?(t.appendChild(b[0]),s=!0):(f.after(b),f=b)})),a++;for(s&&f.after(o(t));j.length>a;)j.pop().$element.remove()},d)}});J("@ng:non-bindable",q);J("ng:view",function(a){var b=
+this;if(a[0]["ng:compiled"])this.descend(!0),this.directives(!0);else return a[0]["ng:compiled"]=!0,n(function(a,d,e){var f;d.onChange(function(){var g;if(d.current)g=d.current.template,f=d.current.scope;g?a("GET",g,function(a,c){e.html(c);b.compile(e)(f)}):e.html("")})();this.$onEval(function(){f&&f.$eval()})},{$inject:["$xhr.cache","$route"]})});var X;Ta("$browser",function(a){if(!X){X=new qc(s,o(s.document),o(s.document.body),Fc,a);var b=X.addPollFn;X.addPollFn=function(){X.addPollFn=b;X.startPoller(100,
+function(a,b){setTimeout(a,b)});return b.apply(X,arguments)};X.bind()}return X},{$inject:["$log"]});n(u,{element:o,compile:lb,scope:T,copy:A,extend:n,equals:oa,forEach:k,injector:zb,noop:q,bind:F,toJson:M,fromJson:ca,identity:Z,isUndefined:z,isDefined:x,isString:w,isFunction:m,isObject:I,isNumber:ma,isArray:Q});pb();Na(L).ready(function(){var a=dc(L),b=L,c=a.autobind;c&&(b=w(c)?b.getElementById(c):b,b=lb(b)(T({$config:a})).$service("$browser"),a.css?b.addCss(a.base_url+a.css):S<8&&b.addJs(a.base_url+
+a.ie_compat,a.ie_compat_id))})})(window,document);angular.element(document).find("head").append('<style type="text/css">@charset "UTF-8";.ng-format-negative{color:red;}.ng-exception{border:2px solid #FF0000;font-family:"Courier New",Courier,monospace;font-size:smaller;white-space:pre;}.ng-validation-error{border:2px solid #FF0000;}#ng-callout{margin:0;padding:0;border:0;outline:0;font-size:13px;font-weight:normal;font-family:Verdana,Arial,Helvetica,sans-serif;vertical-align:baseline;background:transparent;text-decoration:none;}#ng-callout .ng-arrow-left{background-image:url("data:image/gif;base64,R0lGODlhCwAXAKIAAMzMzO/v7/f39////////wAAAAAAAAAAACH5BAUUAAQALAAAAAALABcAAAMrSLoc/AG8FeUUIN+sGebWAnbKSJodqqlsOxJtqYooU9vvk+vcJIcTkg+QAAA7");background-repeat:no-repeat;background-position:left top;position:absolute;z-index:101;left:-12px;height:23px;width:10px;top:-3px;}#ng-callout .ng-arrow-right{background-image:url("data:image/gif;base64,R0lGODlhCwAXAKIAAMzMzO/v7/f39////////wAAAAAAAAAAACH5BAUUAAQALAAAAAALABcAAAMrCLTcoM29yN6k9socs91e5X3EyJloipYrO4ohTMqA0Fn2XVNswJe+H+SXAAA7");background-repeat:no-repeat;background-position:left top;position:absolute;z-index:101;height:23px;width:11px;top:-2px;}#ng-callout{position:absolute;z-index:100;border:2px solid #CCCCCC;background-color:#fff;}#ng-callout .ng-content{padding:10px 10px 10px 10px;color:#333333;}#ng-callout .ng-title{background-color:#CCCCCC;text-align:left;padding-left:8px;padding-bottom:5px;padding-top:2px;font-weight:bold;}.ng-input-indicator-wait{background-image:url("data:image/png;base64,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");background-position:right;background-repeat:no-repeat;}</style>');
1  app/lib/angular/version.txt
@@ -0,0 +1 @@
+0.9.15
1  app/partials/partial1.html
@@ -0,0 +1 @@
+<p>This is the partial for view 1.</p>
1  app/partials/partial2.html
@@ -0,0 +1 @@
+<p>This is the partial for view 2.</p>
12 config/jsTestDriver.conf
@@ -0,0 +1,12 @@
+server: http://localhost:9876
+
+load:
+ - test/lib/jasmine/jasmine.js
+ - test/lib/jasmine-jstd-adapter/JasmineAdapter.js
+ - app/lib/angular/angular.js
+ - test/lib/angular/angular-mocks.js
+ - app/js/*.js
+ - test/unit/*.js
+
+exclude:
+
2  logs/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
10 scripts/test-server.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+base_dir=`dirname $0`
+port=9876
+
+echo "Starting JsTestDriver Server (http://code.google.com/p/js-test-driver/)"
+echo "Please open the following url and capture one or more browsers:"
+echo "http://localhost:$port"
+
+java -jar "$base_dir/../test/lib/jstestdriver/JsTestDriver.jar" --port $port --browserTimeout 20000 --config "$base_dir/../config/jsTestDriver.conf" --basePath "$base_dir/.."
10 scripts/test.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+base_dir=`dirname $0`
+
+tests=$1
+if [[ $tests = "" ]]; then
+ tests="all"
+fi
+
+java -jar "$base_dir/../test/lib/jstestdriver/JsTestDriver.jar" --config "$base_dir/../config/jsTestDriver.conf" --basePath "$base_dir/.." --tests "$tests"
19 scripts/watchr.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env watchr
+
+# config file for watchr http://github.com/mynyml/watchr
+# install: gem install watchr
+# run: watch watchr.rb
+# note: make sure that you have jstd server running (server.sh) and a browser captured
+
+log_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')
+
+`cd ..`
+`touch #{log_file}`
+
+puts "String watchr... log file: #{log_file}"
+
+watch( '(app/js|test/unit)' ) do
+ `echo "\n\ntest run started @ \`date\`" > #{log_file}`
+ `scripts/test.sh &> #{log_file}`
+end
+
243 scripts/web-server.js
@@ -0,0 +1,243 @@
+#!/usr/bin/env node
+
+var sys = require('sys'),
+ http = require('http'),
+ fs = require('fs'),
+ url = require('url'),
+ events = require('events');
+
+var DEFAULT_PORT = 8000;
+
+function main(argv) {
+ new HttpServer({
+ 'GET': createServlet(StaticServlet),
+ 'HEAD': createServlet(StaticServlet)
+ }).start(Number(argv[2]) || DEFAULT_PORT);
+}
+
+function escapeHtml(value) {
+ return value.toString().
+ replace('<', '&lt;').
+ replace('>', '&gt').
+ replace('"', '&quot;');
+}
+
+function createServlet(Class) {
+ var servlet = new Class();
+ return servlet.handleRequest.bind(servlet);
+}
+
+/**
+ * An Http server implementation that uses a map of methods to decide
+ * action routing.
+ *
+ * @param {Object} Map of method => Handler function
+ */
+function HttpServer(handlers) {
+ this.handlers = handlers;
+ this.server = http.createServer(this.handleRequest_.bind(this));
+}
+
+HttpServer.prototype.start = function(port) {
+ this.port = port;
+ this.server.listen(port);
+ sys.puts('Http Server running at http://localhost:' + port + '/');
+};
+
+HttpServer.prototype.parseUrl_ = function(urlString) {
+ var parsed = url.parse(urlString);
+ parsed.pathname = url.resolve('/', parsed.pathname);
+ return url.parse(url.format(parsed), true);
+};
+
+HttpServer.prototype.handleRequest_ = function(req, res) {
+ var logEntry = req.method + ' ' + req.url;
+ if (req.headers['user-agent']) {
+ logEntry += ' ' + req.headers['user-agent'];
+ }
+ sys.puts(logEntry);
+ req.url = this.parseUrl_(req.url);
+ var handler = this.handlers[req.method];
+ if (!handler) {
+ res.writeHead(501);
+ res.end();
+ } else {
+ handler.call(this, req, res);
+ }
+};
+
+/**
+ * Handles static content.
+ */
+function StaticServlet() {}
+
+StaticServlet.MimeMap = {
+ 'txt': 'text/plain',
+ 'html': 'text/html',
+ 'css': 'text/css',
+ 'xml': 'application/xml',
+ 'json': 'application/json',
+ 'js': 'application/javascript',
+ 'jpg': 'image/jpeg',
+ 'jpeg': 'image/jpeg',
+ 'gif': 'image/gif',
+ 'png': 'image/png'
+};
+
+StaticServlet.prototype.handleRequest = function(req, res) {
+ var self = this;
+ var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/, function(match, hex){
+ return String.fromCharCode(parseInt(hex, 16));
+ });
+ var parts = path.split('/');
+ if (parts[parts.length-1].charAt(0) === '.')
+ return self.sendForbidden_(req, res, path);
+ fs.stat(path, function(err, stat) {
+ if (err)
+ return self.sendMissing_(req, res, path);
+ if (stat.isDirectory())
+ return self.sendDirectory_(req, res, path);
+ return self.sendFile_(req, res, path);
+ });
+}
+
+StaticServlet.prototype.sendError_ = function(req, res, error) {
+ res.writeHead(500, {
+ 'Content-Type': 'text/html'
+ });
+ res.write('<!doctype html>\n');
+ res.write('<title>Internal Server Error</title>\n');
+ res.write('<h1>Internal Server Error</h1>');
+ res.write('<pre>' + escapeHtml(sys.inspect(error)) + '</pre>');
+ sys.puts('500 Internal Server Error');
+ sys.puts(sys.inspect(error));
+};
+
+StaticServlet.prototype.sendMissing_ = function(req, res, path) {
+ path = path.substring(1);
+ res.writeHead(404, {
+ 'Content-Type': 'text/html'
+ });
+ res.write('<!doctype html>\n');
+ res.write('<title>404 Not Found</title>\n');
+ res.write('<h1>Not Found</h1>');
+ res.write(
+ '<p>The requested URL ' +
+ escapeHtml(path) +
+ ' was not found on this server.</p>'
+ );
+ res.end();
+ sys.puts('404 Not Found: ' + path);
+};
+
+StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
+ path = path.substring(1);
+ res.writeHead(403, {
+ 'Content-Type': 'text/html'
+ });
+ res.write('<!doctype html>\n');
+ res.write('<title>403 Forbidden</title>\n');
+ res.write('<h1>Forbidden</h1>');
+ res.write(
+ '<p>You do not have permission to access ' +
+ escapeHtml(path) + ' on this server.</p>'
+ );
+ res.end();
+ sys.puts('403 Forbidden: ' + path);
+};
+
+StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
+ res.writeHead(301, {
+ 'Content-Type': 'text/html',
+ 'Location': redirectUrl
+ });
+ res.write('<!doctype html>\n');
+ res.write('<title>301 Moved Permanently</title>\n');
+ res.write('<h1>Moved Permanently</h1>');
+ res.write(
+ '<p>The document has moved <a href="' +
+ redirectUrl +
+ '">here</a>.</p>'
+ );
+ res.end();
+ sys.puts('401 Moved Permanently: ' + redirectUrl);
+};
+
+StaticServlet.prototype.sendFile_ = function(req, res, path) {
+ var self = this;
+ var file = fs.createReadStream(path);
+ res.writeHead(200, {
+ 'Content-Type': StaticServlet.
+ MimeMap[path.split('.').pop()] || 'text/plain'
+ });
+ if (req.method === 'HEAD') {
+ res.end();
+ } else {
+ file.on('data', res.write.bind(res));
+ file.on('close', function() {
+ res.end();
+ });
+ file.on('error', function(error) {
+ self.sendError_(req, res, error);
+ });
+ }
+};
+
+StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
+ var self = this;
+ if (path.match(/[^\/]$/)) {
+ req.url.pathname += '/';
+ var redirectUrl = url.format(url.parse(url.format(req.url)));
+ return self.sendRedirect_(req, res, redirectUrl);
+ }
+ fs.readdir(path, function(err, files) {
+ if (err)
+ return self.sendError_(req, res, error);
+
+ if (!files.length)
+ return self.writeDirectoryIndex_(req, res, path, []);
+
+ var remaining = files.length;
+ files.forEach(function(fileName, index) {
+ fs.stat(path + '/' + fileName, function(err, stat) {
+ if (err)
+ return self.sendError_(req, res, err);
+ if (stat.isDirectory()) {
+ files[index] = fileName + '/';
+ }
+ if (!(--remaining))
+ return self.writeDirectoryIndex_(req, res, path, files);
+ });
+ });
+ });
+};
+
+StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
+ path = path.substring(1);
+ res.writeHead(200, {
+ 'Content-Type': 'text/html'
+ });
+ if (req.method === 'HEAD') {
+ res.end();
+ return;
+ }
+ res.write('<!doctype html>\n');
+ res.write('<title>' + escapeHtml(path) + '</title>\n');
+ res.write('<style>\n');
+ res.write(' ol { list-style-type: none; font-size: 1.2em; }\n');
+ res.write('</style>\n');
+ res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');
+ res.write('<ol>');
+ files.forEach(function(fileName) {
+ if (fileName.charAt(0) !== '.') {
+ res.write('<li><a href="' +
+ escapeHtml(fileName) + '">' +
+ escapeHtml(fileName) + '</a></li>');
+ }
+ });
+ res.write('</ol>');
+ res.end();
+};
+
+// Must be last,
+main(process.argv);
10 test/e2e/runner.html
@@ -0,0 +1,10 @@
+<!doctype html">
+<html lang="en">
+ <head>
+ <title>End2end Test Runner</title>
+ <script src="../lib/angular/angular-scenario.js"></script>
+ <script src="scenarios.js"></script>
+ </head>
+ <body>
+ </body>
+</html>
41 test/e2e/scenarios.js
@@ -0,0 +1,41 @@
+describe('my app', function() {
+
+ beforeEach(function() {
+ browser().navigateTo('../../app/index.html');
+ });
+
+
+ it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
+ expect(browser().location().hash()).toBe("/view1");
+ });
+
+
+ describe('view1', function() {
+
+ beforeEach(function() {
+ browser().navigateTo('#/view1');
+ });
+
+
+ it('should render view1 when user navigates to /view1', function() {
+ expect(element('ng\\:view p:first').text()).
+ toMatch(/partial for view 1/)
+ });
+
+ });
+
+
+ describe('view2', function() {
+
+ beforeEach(function() {
+ browser().navigateTo('#/view2');
+ });
+
+
+ it('should render view1 when user navigates to /view2', function() {
+ expect(element('ng\\:view p:first').text()).
+ toMatch(/partial for view 2/)
+ });
+
+ });
+});
392 test/lib/angular/angular-mocks.js
@@ -0,0 +1,392 @@
+/**
+ * The MIT License
+ *
+ * Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+/*
+
+ NUGGGGGH MUST TONGUE WANGS
+ \
+ .....
+ C C /
+ /< /
+ ___ __________/_#__=o
+ /(- /(\_\________ \
+ \ ) \ )_ \o \
+ /|\ /|\ |' |
+ | _|
+ /o __\
+ / ' |
+ / / |
+ /_/\______|
+ ( _( <
+ \ \ \
+ \ \ |
+ \____\____\
+ ____\_\__\_\
+ /` /` o\
+ |___ |_______|.. . b'ger
+
+
+ IN THE FINAL BUILD THIS FILE DOESN'T HAVE DIRECT ACCESS TO GLOBAL FUNCTIONS
+ DEFINED IN Angular.js YOU *MUST* REFER TO THEM VIA angular OBJECT
+ (e.g. angular.forEach(...)) AND MAKE SURE THAT THE GIVEN FUNCTION IS EXPORTED
+ TO THE angular NAMESPACE in AngularPublic.js
+
+ */
+
+
+/**
+ * @ngdoc overview
+ * @name angular.mock
+ * @namespace Namespace for all built-in angular mocks.
+ *
+ * @description
+ * `angular.mock` is a namespace for all built-in mocks that ship with angular and automatically
+ * replace real services if `angular-mocks.js` file is loaded after `angular.js` and before any
+ * tests.
+ */
+angular.mock = {};
+
+
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.mock.service.$browser
+ */
+function MockBrowser() {
+ var self = this,
+ expectations = {},
+ requests = [];
+
+ this.isMock = true;
+ self.url = "http://server";
+ self.lastUrl = self.url; // used by url polling fn
+ self.pollFns = [];
+
+
+ // register url polling fn
+
+ self.onHashChange = function(listener) {
+ self.pollFns.push(
+ function() {
+ if (self.lastUrl != self.url) {
+ self.lastUrl = self.url;
+ listener();
+ }
+ }
+ );
+
+ return listener;
+ };
+
+
+ self.xhr = function(method, url, data, callback, headers) {
+ headers = headers || {};
+ if (data && angular.isObject(data)) data = angular.toJson(data);
+ if (data && angular.isString(data)) url += "|" + data;
+ var expect = expectations[method] || {};
+ var expectation = expect[url];
+ if (!expectation) {
+ throw new Error("Unexpected request for method '" + method + "' and url '" + url + "'.");
+ }
+ requests.push(function(){
+ angular.forEach(expectation.headers, function(value, key){
+ if (headers[key] !== value) {
+ throw new Error("Missing HTTP request header: " + key + ": " + value);
+ }
+ });
+ callback(expectation.code, expectation.response);
+ });
+ };
+ self.xhr.expectations = expectations;
+ self.xhr.requests = requests;
+ self.xhr.expect = function(method, url, data, headers) {
+ if (data && angular.isObject(data)) data = angular.toJson(data);
+ if (data && angular.isString(data)) url += "|" + data;
+ var expect = expectations[method] || (expectations[method] = {});
+ return {
+ respond: function(code, response) {
+ if (!angular.isNumber(code)) {
+ response = code;
+ code = 200;
+ }
+ expect[url] = {code:code, response:response, headers: headers || {}};
+ }
+ };
+ };
+ self.xhr.expectGET = angular.bind(self, self.xhr.expect, 'GET');
+ self.xhr.expectPOST = angular.bind(self, self.xhr.expect, 'POST');
+ self.xhr.expectDELETE = angular.bind(self, self.xhr.expect, 'DELETE');
+ self.xhr.expectPUT = angular.bind(self, self.xhr.expect, 'PUT');
+ self.xhr.expectJSON = angular.bind(self, self.xhr.expect, 'JSON');
+ self.xhr.flush = function() {
+ if (requests.length == 0) {
+ throw new Error("No xhr requests to be flushed!");
+ }
+
+ while(requests.length) {
+ requests.pop()();
+ }
+ };
+
+ self.cookieHash = {};
+ self.lastCookieHash = {};
+ self.deferredFns = [];
+
+ self.defer = function(fn) {
+ self.deferredFns.push(fn);
+ };
+
+ self.defer.flush = function() {
+ while (self.deferredFns.length) self.deferredFns.shift()();
+ };
+}
+MockBrowser.prototype = {
+
+ poll: function poll(){
+ angular.forEach(this.pollFns, function(pollFn){
+ pollFn();
+ });
+ },
+
+ addPollFn: function(pollFn) {
+ this.pollFns.push(pollFn);
+ return pollFn;
+ },
+
+ hover: function(onHover) {
+ },
+
+ getUrl: function(){
+ return this.url;
+ },
+
+ setUrl: function(url){
+ this.url = url;
+ },
+
+ cookies: function(name, value) {
+ if (name) {
+ if (value == undefined) {
+ delete this.cookieHash[name];
+ } else {
+ if (angular.isString(value) && //strings only
+ value.length <= 4096) { //strict cookie storage limits
+ this.cookieHash[name] = value;
+ }
+ }
+ } else {
+ if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
+ this.lastCookieHash = angular.copy(this.cookieHash);
+ this.cookieHash = angular.copy(this.cookieHash);
+ }
+ return this.cookieHash;
+ }
+ }
+};
+
+angular.service('$browser', function(){
+ return new MockBrowser();
+});
+
+
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.mock.service.$exceptionHandler
+ *
+ * @description
+ * Mock implementation of {@link angular.service.$exceptionHandler} that rethrows any error passed
+ * into `$exceptionHandler`. If any errors are are passed into the handler in tests, it typically
+ * means that there is a bug in the application or test, so this mock will make these tests fail.
+ *
+ * See {@link angular.mock} for more info on angular mocks.
+ */
+angular.service('$exceptionHandler', function(e) {
+ return function(e) {throw e;};
+});
+
+
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.mock.service.$log
+ *
+ * @description
+ * Mock implementation of {@link angular.service.$log} that gathers all logged messages in arrays
+ * (one array per logging level). These arrays are exposed as `logs` property of each of the
+ * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
+ *
+ * See {@link angular.mock} for more info on angular mocks.
+ */
+angular.service('$log', MockLogFactory);
+
+function MockLogFactory() {
+ var $log = {
+ log: function(){ $log.log.logs.push(arguments); },
+ warn: function(){ $log.warn.logs.push(arguments); },
+ info: function(){ $log.info.logs.push(arguments); },
+ error: function(){ $log.error.logs.push(arguments); }
+ };
+
+ $log.log.logs = [];
+ $log.warn.logs = [];
+ $log.info.logs = [];
+ $log.error.logs = [];
+
+ return $log;
+}
+
+
+/**
+ * Mock of the Date type which has its timezone specified via constroctor arg.
+ *
+ * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
+ * offset, so that we can test code that depends on local timezone settings without dependency on
+ * the time zone settings of the machine where the code is running.
+ *
+ * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
+ * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
+ *
+ * @example
+ * !!!! 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.
+ *
+ * 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)) {
+ var tsStr = timestamp;
+
+ this.origDate = angular.String.toDate(timestamp);
+
+ timestamp = this.origDate.getTime();
+ if (isNaN(timestamp))
+ throw {
+ name: "Illegal Argument",
+ message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
+ };
+ } else {
+ this.origDate = new Date(timestamp);
+ }
+
+ var localOffset = new Date(timestamp).getTimezoneOffset();
+ this.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
+ this.date = new Date(timestamp + this.offsetDiff);
+
+ this.getTime = function() {
+ return this.date.getTime() - this.offsetDiff;
+ };
+
+ this.toLocaleDateString = function() {
+ return this.date.toLocaleDateString();
+ };
+
+ this.getFullYear = function() {
+ return this.date.getFullYear();
+ };
+
+ this.getMonth = function() {
+ return this.date.getMonth();
+ };
+
+ this.getDate = function() {
+ return this.date.getDate();
+ };
+
+ this.getHours = function() {
+ return this.date.getHours();
+ };
+
+ this.getMinutes = function() {
+ return this.date.getMinutes();
+ };
+
+ this.getSeconds = function() {
+ return this.date.getSeconds();
+ };
+
+ this.getTimezoneOffset = function() {
+ return offset * 60;
+ };
+
+ this.getUTCFullYear = function() {
+ return this.origDate.getUTCFullYear();
+ };
+
+ this.getUTCMonth = function() {
+ return this.origDate.getUTCMonth();
+ };
+
+ this.getUTCDate = function() {
+ return this.origDate.getUTCDate();
+ };
+
+ this.getUTCHours = function() {
+ return this.origDate.getUTCHours();
+ };
+
+ this.getUTCMinutes = function() {
+ return this.origDate.getUTCMinutes();
+ };
+
+ this.getUTCSeconds = function() {
+ return this.origDate.getUTCSeconds();
+ };
+
+
+ //hide all methods not implemented in this mock that the Date prototype exposes
+ var unimplementedMethods = ['getDay', 'getMilliseconds', 'getTime', 'getUTCDay',
+ 'getUTCMilliseconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
+ 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
+ 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
+ 'setYear', 'toDateString', 'toJSON', 'toGMTString', 'toLocaleFormat', 'toLocaleString',
+ 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
+
+ angular.forEach(unimplementedMethods, function(methodName) {
+ this[methodName] = function() {
+ throw {
+ name: "MethodNotImplemented",
+ message: "Method '" + methodName + "' is not implemented in the TzDate mock"
+ };
+ };
+ });
+}
+
+//make "tzDateInstance instanceof Date" return true
+TzDate.prototype = Date.prototype;
18,221 test/lib/angular/angular-scenario.js
18,221 additions, 0 deletions not shown
1  test/lib/angular/version.txt
@@ -0,0 +1 @@
+0.9.15
179 test/lib/jasmine-jstd-adapter/JasmineAdapter.js
@@ -0,0 +1,179 @@
+/**
+ * @fileoverview Jasmine JsTestDriver Adapter.
+ * @author misko@hevery.com (Misko Hevery)
+ */
+(function(window) {
+ var rootDescribes = new Describes(window);
+ var describePath = [];
+ rootDescribes.collectMode();
+
+ var jasmineTest = TestCase('Jasmine Adapter Tests', null, 'jasmine test case');
+
+ var jasminePlugin = {
+ name:'jasmine',
+ runTestConfiguration: function(testRunConfiguration, onTestDone, onTestRunConfigurationComplete){
+ if (testRunConfiguration.testCaseInfo_.template_ !== jasmineTest) return;
+
+ var jasmineEnv = jasmine.currentEnv_ = new jasmine.Env();
+ rootDescribes.playback();
+ var specLog = jstestdriver.console.log_ = [];
+ var start;
+ jasmineEnv.specFilter = function(spec) {
+ return rootDescribes.isExclusive(spec);
+ };
+ jasmineEnv.reporter = {
+ log: function(str){
+ specLog.push(str);
+ },
+
+ reportRunnerStarting: function(runner) { },
+
+ reportSpecStarting: function(spec) {
+ specLog = jstestdriver.console.log_ = [];
+ start = new Date().getTime();
+ },
+
+ reportSpecResults: function(spec) {
+ var suite = spec.suite;
+ var results = spec.results();
+ if (results.skipped) return;
+ var end = new Date().getTime();
+ var messages = [];
+ var resultItems = results.getItems();
+ var state = 'passed';
+ for ( var i = 0; i < resultItems.length; i++) {
+ if (!resultItems[i].passed()) {
+ state = resultItems[i].message.match(/AssertionError:/) ? 'error' : 'failed';
+ messages.push({
+ message: resultItems[i].toString(),
+ name: resultItems[i].trace.name,
+ stack: formatStack(resultItems[i].trace.stack)
+ });
+ }
+ }
+ onTestDone(
+ new jstestdriver.TestResult(
+ suite.getFullName(),
+ spec.description,
+ state,
+ jstestdriver.angular.toJson(messages),
+ specLog.join('\n'),
+ end - start));
+ },
+
+ reportSuiteResults: function(suite) {},
+
+ reportRunnerResults: function(runner) {
+ onTestRunConfigurationComplete();
+ }
+ };
+ jasmineEnv.execute();
+ return true;
+ },
+ onTestsFinish: function(){
+ jasmine.currentEnv_ = null;
+ rootDescribes.collectMode();
+ }
+ };
+ jstestdriver.pluginRegistrar.register(jasminePlugin);
+
+ function formatStack(stack) {
+ var lines = (stack||'').split(/\r?\n/);
+ var frames = [];
+ for (i = 0; i < lines.length; i++) {
+ if (!lines[i].match(/\/jasmine[\.-]/)) {
+ frames.push(lines[i].replace(/https?:\/\/\w+(:\d+)?\/test\//, '').replace(/^\s*/, ' '));
+ }
+ }
+ return frames.join('\n');
+ }
+
+ function noop(){}
+ function Describes(window){
+ var describes = {};
+ var beforeEachs = {};
+ var afterEachs = {};
+ var exclusive;
+ var collectMode = true;
+ intercept('describe', describes);
+ intercept('xdescribe', describes);
+ intercept('beforeEach', beforeEachs);
+ intercept('afterEach', afterEachs);
+
+ function intercept(functionName, collection){
+ window[functionName] = function(desc, fn){
+ if (collectMode) {
+ collection[desc] = function(){
+ jasmine.getEnv()[functionName](desc, fn);
+ };
+ } else {
+ jasmine.getEnv()[functionName](desc, fn);
+ }
+ };
+ }
+ window.ddescribe = function(name, fn){
+ exclusive = true;
+ console.log('ddescribe', name);
+ window.describe(name, function(){
+ var oldIt = window.it;
+ window.it = window.iit;
+ try {
+ fn.call(this);
+ } finally {
+ window.it = oldIt;
+ };
+ });
+ };
+ window.iit = function(name, fn){
+ exclusive = fn.exclusive = true;
+ console.log(fn);
+ jasmine.getEnv().it(name, fn);
+ };
+
+
+ this.collectMode = function() {
+ collectMode = true;
+ exclusive = false;
+ };
+ this.playback = function(){
+ collectMode = false;
+ playback(beforeEachs);
+ playback(afterEachs);
+ playback(describes);
+
+ function playback(set) {
+ for ( var name in set) {
+ set[name]();
+ }
+ }
+ };
+
+ this.isExclusive = function(spec) {
+ if (exclusive) {
+ var blocks = spec.queue.blocks;
+ for ( var i = 0; i < blocks.length; i++) {
+ if (blocks[i].func.exclusive) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+ };
+ }
+
+})(window);
+
+// Patch Jasmine for proper stack traces
+jasmine.Spec.prototype.fail = function (e) {
+ var expectationResult = new jasmine.ExpectationResult({
+ passed: false,
+ message: e ? jasmine.util.formatException(e) : 'Exception'
+ });
+ // PATCH
+ if (e) {
+ expectationResult.trace = e;
+ }
+ this.results_.addResult(expectationResult);
+};
+
1  test/lib/jasmine-jstd-adapter/version.txt
@@ -0,0 +1 @@
+1ade1ad7cad4caadb3a3 @ 2011-03-07
20 test/lib/jasmine/MIT.LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008-2010 Pivotal Labs
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
180 test/lib/jasmine/index.js
@@ -0,0 +1,180 @@
+var fs = require('fs');
+var sys = require('sys');
+var path = require('path');
+
+var filename = __dirname + '/jasmine.js';
+global.window = {
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
+ setInterval: setInterval,
+ clearInterval: clearInterval
+};
+var src = fs.readFileSync(filename);
+var jasmine = process.compile(src + '\njasmine;', filename);
+delete global.window;
+
+function noop(){}
+
+jasmine.executeSpecsInFolder = function(folder, done, isVerbose, showColors, matcher){
+ var log = [];
+ var columnCounter = 0;
+ var start = 0;
+ var elapsed = 0;
+ var verbose = isVerbose || false;
+ var fileMatcher = new RegExp(matcher || "\.js$");
+ var colors = showColors || false;
+ var specs = jasmine.getAllSpecFiles(folder, fileMatcher);
+
+ var ansi = {
+ green: '\033[32m',
+ red: '\033[31m',
+ yellow: '\033[33m',
+ none: '\033[0m'
+ };
+
+ for (var i = 0, len = specs.length; i < len; ++i){
+ var filename = specs[i];
+ require(filename.replace(/\.*$/, ""));
+ }
+
+ var jasmineEnv = jasmine.getEnv();
+ jasmineEnv.reporter = {
+ log: function(str){
+ },
+
+ reportSpecStarting: function(runner) {
+ },
+
+ reportRunnerStarting: function(runner) {
+ sys.puts('Started');
+ start = Number(new Date);
+ },
+
+ reportSuiteResults: function(suite) {
+ var specResults = suite.results();
+ var path = [];
+ while(suite) {
+ path.unshift(suite.description);
+ suite = suite.parentSuite;
+ }
+ var description = path.join(' ');
+
+ if (verbose)
+ log.push('Spec ' + description);
+
+ specResults.items_.forEach(function(spec){
+ if (spec.failedCount > 0 && spec.description) {
+ if (!verbose)
+ log.push(description);
+ log.push(' it ' + spec.description);
+ spec.items_.forEach(function(result){
+ log.push(' ' + result.trace.stack + '\n');
+ });
+ }
+ });
+ },
+
+ reportSpecResults: function(spec) {
+ var result = spec.results();
+ var msg = '';
+ if (result.passed())
+ {
+ msg = (colors) ? (ansi.green + '.' + ansi.none) : '.';
+// } else if (result.skipped) { TODO: Research why "result.skipped" returns false when "xit" is called on a spec?
+// msg = (colors) ? (ansi.yellow + '*' + ansi.none) : '*';
+ } else {
+ msg = (colors) ? (ansi.red + 'F' + ansi.none) : 'F';
+ }
+ sys.print(msg);
+ if (columnCounter++ < 50) return;
+ columnCounter = 0;
+ sys.print('\n');
+ },
+
+
+ reportRunnerResults: function(runner) {
+ elapsed = (Number(new Date) - start) / 1000;
+ sys.puts('\n');
+ log.forEach(function(log){
+ sys.puts(log);
+ });
+ sys.puts('Finished in ' + elapsed + ' seconds');
+
+ var summary = jasmine.printRunnerResults(runner);
+ if(colors)
+ {
+ if(runner.results().failedCount === 0 )
+ sys.puts(ansi.green + summary + ansi.none);
+ else
+ sys.puts(ansi.red + summary + ansi.none);
+ } else {
+ sys.puts(summary);
+ }
+ (done||noop)(runner, log);
+ }
+ };
+ jasmineEnv.execute();
+};
+
+jasmine.getAllSpecFiles = function(dir, matcher){
+ var specs = [];
+
+ if (fs.statSync(dir).isFile() && dir.match(matcher)) {
+ specs.push(dir);
+ } else {
+ var files = fs.readdirSync(dir);
+ for (var i = 0, len = files.length; i < len; ++i){
+ var filename = dir + '/' + files[i];
+ if (fs.statSync(filename).isFile() && filename.match(matcher)){
+ specs.push(filename);
+ }else if (fs.statSync(filename).isDirectory()){
+ var subfiles = this.getAllSpecFiles(filename, matcher);
+ subfiles.forEach(function(result){
+ specs.push(result);
+ });
+ }
+ }
+ }
+
+ return specs;
+};
+
+jasmine.printRunnerResults = function(runner){
+ var results = runner.results();
+ var suites = runner.suites();
+ var msg = '';
+ msg += suites.length + ' test' + ((suites.length === 1) ? '' : 's') + ', ';
+ msg += results.totalCount + ' assertion' + ((results.totalCount === 1) ? '' : 's') + ', ';
+ msg += results.failedCount + ' failure' + ((results.failedCount === 1) ? '' : 's') + '\n';
+ return msg;
+};
+
+function now(){
+ return new Date().getTime();
+}
+
+jasmine.asyncSpecWait = function(){
+ var wait = jasmine.asyncSpecWait;
+ wait.start = now();
+ wait.done = false;
+ (function innerWait(){
+ waits(10);
+ runs(function() {
+ if (wait.start + wait.timeout < now()) {
+ expect('timeout waiting for spec').toBeNull();
+ } else if (wait.done) {
+ wait.done = false;
+ } else {
+ innerWait();
+ }
+ });
+ })();
+};
+jasmine.asyncSpecWait.timeout = 4 * 1000;
+jasmine.asyncSpecDone = function(){
+ jasmine.asyncSpecWait.done = true;
+};
+
+for ( var key in jasmine) {
+ exports[key] = jasmine[key];
+}
188 test/lib/jasmine/jasmine-html.js
@@ -0,0 +1,188 @@
+jasmine.TrivialReporter = function(doc) {
+ this.document = doc || document;
+ this.suiteDivs = {};
+ this.logRunningSpecs = false;
+};
+
+jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
+ var el = document.createElement(type);
+
+ for (var i = 2; i < arguments.length; i++) {
+ var child = arguments[i];
+
+ if (typeof child === 'string') {
+ el.appendChild(document.createTextNode(child));
+ } else {
+ if (child) { el.appendChild(child); }
+ }
+ }
+
+ for (var attr in attrs) {
+ if (attr == "className") {
+ el[attr] = attrs[attr];
+ } else {
+ el.setAttribute(attr, attrs[attr]);
+ }
+ }
+
+ return el;
+};
+
+jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
+ var showPassed, showSkipped;
+
+ this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
+ this.createDom('div', { className: 'banner' },
+ this.createDom('div', { className: 'logo' },
+ this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
+ this.createDom('span', { className: 'version' }, runner.env.versionString())),
+ this.createDom('div', { className: 'options' },
+ "Show ",
+ showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
+ showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
+ )
+ ),
+
+ this.runnerDiv = this.createDom('div', { className: 'runner running' },
+ this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
+ this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
+ this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
+ );
+
+ this.document.body.appendChild(this.outerDiv);
+
+ var suites = runner.suites();
+ for (var i = 0; i < suites.length; i++) {
+ var suite = suites[i];
+ var suiteDiv = this.createDom('div', { className: 'suite' },
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
+ this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
+ this.suiteDivs[suite.id] = suiteDiv;
+ var parentDiv = this.outerDiv;
+ if (suite.parentSuite) {
+ parentDiv = this.suiteDivs[suite.parentSuite.id];
+ }
+ parentDiv.appendChild(suiteDiv);
+ }
+
+ this.startedAt = new Date();
+
+ var self = this;
+ showPassed.onclick = function(evt) {
+ if (showPassed.checked) {
+ self.outerDiv.className += ' show-passed';
+ } else {
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
+ }
+ };
+
+ showSkipped.onclick = function(evt) {
+ if (showSkipped.checked) {
+ self.outerDiv.className += ' show-skipped';
+ } else {
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
+ }
+ };
+};
+
+jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
+ var results = runner.results();
+ var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
+ this.runnerDiv.setAttribute("class", className);
+ //do it twice for IE
+ this.runnerDiv.setAttribute("className", className);
+ var specs = runner.specs();
+ var specCount = 0;
+ for (var i = 0; i < specs.length; i++) {
+ if (this.specFilter(specs[i])) {
+ specCount++;
+ }
+ }
+ var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
+ message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
+ this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
+
+ this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
+};
+
+jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
+ var results = suite.results();
+ var status = results.passed() ? 'passed' : 'failed';
+ if (results.totalCount == 0) { // todo: change this to check results.skipped
+ status = 'skipped';
+ }
+ this.suiteDivs[suite.id].className += " " + status;
+};
+
+jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
+ if (this.logRunningSpecs) {
+ this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
+ }
+};
+
+jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
+ var results = spec.results();
+ var status = results.passed() ? 'passed' : 'failed';
+ if (results.skipped) {
+ status = 'skipped';
+ }
+ var specDiv = this.createDom('div', { className: 'spec ' + status },
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
+ this.createDom('a', {
+ className: 'description',
+ href: '?spec=' + encodeURIComponent(spec.getFullName()),
+ title: spec.getFullName()
+ }, spec.description));
+
+
+ var resultItems = results.getItems();
+ var messagesDiv = this.createDom('div', { className: 'messages' });
+ for (var i = 0; i < resultItems.length; i++) {
+ var result = resultItems[i];
+
+ if (result.type == 'log') {
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
+ } else if (result.type == 'expect' && result.passed && !result.passed()) {
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
+
+ if (result.trace.stack) {
+ messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
+ }