';R.jb='Sorry, you do not have permission for this!
';R.prototype={bind:J(),Na:function(a){this.D.push(a);this.D.length==1&&
+this.Ba("/user_session/new.mini?return_url="+encodeURIComponent(this.ab()))},Xb:function(a){this.D.push(a);this.D.length==1&&this.Ba("/user_session/do_destroy.mini")},ab:function(){return this.window.location.href.split("#")[0]},Ba:function(a){var b=this,c=(new Date).getTime(),d=this.ab();d+="#$iframe_notify="+c;var e=k('');this.document.append(e);e.Aa({height:363,width:500,wd:false,
+Zb:true,title:'Authentication: <angular/>'});callbacks["_iframe_notify_"+c]=function(){e.Aa("destroy");e.remove();o(b.D,function(f){f()});b.D=[]}},Qa:function(){if(!this.Da){this.Da=k(R.jb);this.Da.Aa({Vc:true,height:70,Zb:true})}}};T.kb=U(J(),{all:function(){return[]},query:function(){return[]},load:function(){return{}},title:undefined});T.prototype={Q:function(a){if(!a instanceof E)throw"Parameter must be an instance of Entity! "+w(a);var b=
+a.N+"/"+a.w,c=this.z[b];if(c)E.ea(a,c);else c=this.z[b]=a;return c},load:function(a,b,c,d){if(b&&b!=="*"){var e=this;this.A(["GET",a.N+"/"+b],function(f){a.O(f);a.fb();f=a.Gc(a);e.Q(f);(c||n)(a)},d)}return a},ja:function(a,b,c){var d=this,e=[],f=0;o(b,function(g){e.push(d.load(a(),g,function(){f++;if(f==b.length)(c||n)(e)}))});return e},Ja:function(a,b,c){return this.load(a,b,c,function(d){if(d.ba==404){a.w=b;(c||n)(a)}else throw d;})},Ia:function(a,b){var c=this,d=[];d.ra=function(e){return e.N==
+a.title};this.z.M.push(d);this.A(["GET",a.title],function(e){for(var f=0;fg.title?1:-1});a&&a(b)});return b},Fb:function(){var a={};this.post([["GET","$users"]],function(b,c){o(c[0],function(d,
+e){a[e]=d})});return a},yc:function(a){var b={};this.post([["GET","$users/"+a]],function(c,d){o(d[0],function(e,f){b[f]=e})});return b},C:function(a,b){if(!a)return T.kb;var c=this,d=U(function(e){return new E(d,e)},{title:a,$$factory:true,datastore:this,defaults:b||{},load:function(e,f){return c.load(d(),e,f)},loadMany:function(e,f){return c.ja(d,e,f)},loadOrCreate:function(e,f){return c.Ja(d(),e,f)},all:function(e){return c.Ia(d,e)},query:function(e,f,g){return c.Ua(d,e,f,g)},properties:function(e){c.A(["GET",
+a+"/$properties"],e)}});return d},join:function(a){function b(){throw"Joined entities can not be instantiated into a document.";}var c=_(a).Wc().map(function(d,e){return e}).sortBy(function(d){var e=[];do{if(_(e).include(d))throw"Infinite loop in join: "+e.join(" -> ");e.push(d);if(!a[d])throw _("Named entity '<%=name%>' is undefined.").template({name:d});d=a[d].W?a[d].W.substring(0,a[d].W.indexOf(".")):undefined}while(d);return e.length}).value();if(_(c).select(function(d){return a[d].W}).length!=
+c.length-1)throw"Exactly one entity needs to be primary.";b.query=function(d,e){var f=[],g=d?d.substring(0,d.indexOf(".")):undefined;if(g!=c[0])throw _("Named entity '<%=name%>' is not a primary entity.").template({name:g});var h=1;a[g].join.query(d.substring(d.indexOf(".")+1),e,function(i){var j=c[h++],l=a[j],p=l.W,B={};_(i).each(function(s){var t={};f.push(t);t[g]=s;s=v.J(t,p);B[s]=s});l.join.ja(_.toArray(B),function(s){var t={};_(s).each(function(z){t[z.w]=z});_(f).each(function(z){var I=v.J(z,
+p);z[j]=t[I]})})});return f};return b}};r.g=function(a){if(a)for(var b in a)this[b]=a[b]};r.g.get=function(a,b){b=b||"text";switch(typeof a){case "string":return b=="text"?a:undefined;case "object":if(a&&typeof a[b]!=="undefined")return a[b];return;default:return a}};var u;o({currency:function(a){k(this.element).toggleClass("ng-format-negative",a<0);return"$"+r.number.apply(this,[a,2])},number:function(a,b){if(isNaN(a)||!isFinite(a))return"";b=typeof b=="undefined"?2:b;var c=a<0;a=Math.abs(a);var d=
+Math.pow(10,b);a=""+Math.round(a*d);var e=a.substring(0,a.length-b);e=e||"0";d=a.substring(a.length-b);a=c?"-":"";for(c=0;c0){for(c=d.length;c'+g+"",Ad:b});_.breakLoop()}});e&&_.breakLoop()});return e?e:b?c||new r.g({text:b+" is not recognized"}):null}}(),link:function(a,b){b=b||r.g.get(a);var c=r.g.get(a,"url")||r.g.get(a);if(c){if(m.L.ld(c)===null)c="mailto:"+c;a=''+b+"";return new r.g({text:b,url:c,html:a})}return a},bytes:function(){var a=["bytes","KB","MB","GB","TB","PB"];return function(b){if(b===null)return"";for(var c=0;b>1E3;){b/=1024;c++}b=""+b;var d=b.indexOf(".");if(d>-1&&d+2"})}return null},lowercase:function(a){return(a=r.g.get(a))?(""+a).toLowerCase():a},uppercase:function(a){return(a=r.g.get(a))?(""+a).toUpperCase():a},linecount:function(a){a=r.g.get(a);if(a===""||!a)return 1;return a.split(/\n|\f/).length},"if":function(a,b){return b?a:undefined},unless:function(a,
+b){return b?undefined:a},googleChartApi:U(function(a,b,c,d){b=b||{};a={xb:a,Xc:u.yb(b,"color"),cd:u.title(b),Zc:u.yb(b,"label"),Yc:u.values(b),$c:"bg,s,FFFFFF00"};if(_.isArray(b.Ec)){a.ed="x";a.dd="0:|"+b.Ec.join("|")}return u.encode(a,c,d)},{values:function(a){var b=[];o(a.uc||[],function(c){var d=[];o(c.values||[],function(e){d.push(e)});b.push(d.join(","))});a=b.join("|");return a===""?null:"t:"+a},title:function(a){var b=[];a=a.title||[];o(_.isArray(a)?a:[a],function(c){b.push(encodeURIComponent(c))});
+return b.join("|")},collect:function(a,b){var c=[],d=0;o(a.uc||[],function(e){var f=[];e=e[b]||[];o(_.isArray(e)?e:[e],function(g){f.push(encodeURIComponent(g));d++});c.push(f.join("|"))});return d?c.join(","):null},encode:function(a,b,c){b=b||200;c=c||b;var d="http://chart.apis.google.com/chart?",e=[];a.bd=b+"x"+c;o(a,function(f,g){f&&e.push(g+"="+f)});e.sort();d+=e.join("&");return new r.g({url:d,html:'
'})}}),qrcode:function(a,b,c){return u.encode({xb:"qr",
+ad:encodeURIComponent(a)},b,c)},chart:{td:function(a,b,c){return u("p",a,b,c)},ud:function(a,b,c){return u("p3",a,b,c)},vd:function(a,b,c){return u("pc",a,b,c)},Sc:function(a,b,c){return u("bhs",a,b,c)},Rc:function(a,b,c){return u("bhg",a,b,c)},Uc:function(a,b,c){return u("bvs",a,b,c)},Tc:function(a,b,c){return u("bvg",a,b,c)},qd:function(a,b,c){return u("lc",a,b,c)},yd:function(a,b,c){return u("ls",a,b,c)},xd:function(a,b,c){return u("s",a,b,c)}},html:function(a){return new r.g({html:a})},linky:function(a){if(!a)return a;
+for(var b=/(ftp|http|https|mailto):\/\/([^\(\)|\s]+)/,c,d=a,e=[];c=d.match(b);){c=c[0].replace(/[\.\;\,\(\)\{\}\<\>]$/,"");var f=d.indexOf(c);e.push(C(d.substr(0,f)));e.push('');e.push(c);e.push("");d=d.substring(f+c.length)}e.push(C(d));return new r.g({text:a,html:e.join("")})}},function(a,b){r[b]=a});u=r.googleChartApi;array=[].constructor;m.toJson=w;m.fromJson=P;E.ea=function(a,b){if(!(a===b||!a||!b)){var c=function(e,f,g){return g.substring(0,2)!=="$$"&&typeof e[g]!=="function"&&
+typeof f[g]!=="function"};for(var d in b)c(a,b,d)&&delete b[d];for(d in a)if(c(a,b,d))b[d]=a[d]}};E.prototype={$migrate:function(){Z(this.$$entity.kd,this);return this},$save:function(a){this.$$entity.Cb.save(this,a===true?undefined:a);a===true&&this.$$entity.Cb.ga();return this},$loadFrom:function(a){E.ea(a,this);return this},$saveTo:function(a){E.ea(this,a);return this}};F.ua={"null":N(null),"true":N(true),"false":N(false),"+":function(a,b,c){return(b||0)+(c||0)},"-":function(a,b,c){return(b||0)-
+(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},"=":function(a,b,c){return a.scope.h(b,c)},"==":function(a,b,c){return b==c},"!=":function(a,b,c){return b!=c},"<":function(a,b,c){return b":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}};F.ib={n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'};F.prototype={F:function(){return this.index+10){e=e[0];var f=e.text;if(f==a||f==b||f==c||f==d||!a&&!b&&!c&&!d)return e}return false},a:function(a,b,c,d){if(a=this.F(a,b,c,d)){this.i.shift();return this.fd=a}return false},j:function(a){if(!this.a(a)){var b=this.F();throw"Expecting '"+
+a+"' at column '"+(b.index+1)+"' in '"+this.text+"' got '"+this.text.substring(b.index)+"'.";}},mb:function(a,b){return function(c){return a(c,b(c))}},q:function(a,b,c){return function(d){return b(d,a(d),c(d))}},Ea:function(){return this.i.length>0},G:function(){if(this.i.length!==0)throw"Did not understand '"+this.text.substring(this.i[0].index)+"' while evaluating '"+this.text+"'.";},pa:function(){for(var a=[];;){this.i.length>0&&!this.F("}",")",";","]")&&a.push(this.Ca());if(!this.a(";"))return function(b){for(var c,
+d=0;d","<=",">="))a=this.q(a,b.b,this.xa());else return a},xa:function(){for(var a=this.la(),b;b=this.a("+","-");)a=this.q(a,b.b,this.la());return a},la:function(){for(var a=this.Za(),b;b=this.a("*","/","%");)a=this.q(a,b.b,this.Za());return a},Za:function(){var a;return this.a("+")?
+this.Z():(a=this.a("-"))?this.q(D.lb,a.b,this.la()):this.Z()},Pb:function(a){var b=this.a(),c=b.text.split(".");a=a;for(var d,e=0;e1;d++){var e=a.shift(),f=c[e];if(!f){f={};c[e]=f}c=f}return c[a.shift()]=b},l:function(a,b){this.eval(a+"="+w(b))},eval:function(a,b){var c=v.S[a];if(!c){var d=new D(a);c=d.pa();d.G();v.S[a]=c}b=b||{};b.scope=this;return c(b)},k:function(a,b,c,d,e){try{var f=this.eval(b,c);if(a.u){a.u=false;k(a.view).removeClass("ng-exception").removeAttr("ng-error")}d&&d.apply(a,[f]);return true}catch(g){W("Eval Widget Error:",g);b=w(g,true);a.u=true;k(a.view).addClass("ng-exception").attr("ng-error",
+b);e&&e.apply(a,[g,b]);return false}},Ac:function(a,b){var c=v.S[a];if(!c){c=(new D(a)).L();v.S[a]=c}a={scope:this};return c(a)(a,b)},C:function(a){return(new D(a)).Jb()({scope:this})},Yb:function(a){this.p.Ic.push(a)},watch:function(a){var b=this;(new D(a)).watch()({scope:this,pb:function(c,d){b.qb(c,function(e,f){try{return d({scope:b},e,f)}catch(g){alert(g)}})}})},qb:function(a,b){var c=this.qa[a];if(!c){c={Ha:[],m:a};this.qa[a]=c}c.Ha.push(b)},Nb:function(){var a=this,b=false;o(this.qa,function(c){var d=
+a.eval(c.m);if(d!==c.c){o(c.Ha,function(e){e(d,c.c);b=true});c.c=d}});return b}};ka.prototype={ub:function(a){return ba.Gb(a)},K:function(a,b,c,d){var e=this.zc+this.$b++;ca[e]=function(h){delete m[e];d(200,h)};a={Bd:b,rd:a,sd:c};a=this.ub(w(a));b=Math.ceil(a.length/this.ka);c=this.url+"/$/"+e+"/"+b+"/";for(var f=0;fc)return"Value can not be greater than "+c+".";return null}else return"Value is not a number."},integer:function(a,b,c){b=Ba.number(a,b,c);if(b===null&&a!=Math.round(a))return"Value is not a whole number.";return b},date:function(a){if(a.match(/^\d\d?\/\d\d?\/\d\d\d\d$/))return null;return"Value is not a date. (Expecting format: 12/31/2009)."},ssn:function(a){if(a.match(/^\d\d\d-\d\d-\d\d\d\d$/))return null;
+return"SSN needs to be in 999-99-9999 format."},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{P(a);return null}catch(b){return b.toString()}}},function(a,b){Ba[b]=a});ja.prototype={Ab:function(a,b){var c,d=a.attr("type").toLowerCase(),e=a.attr("name");if(e)e=e.split(":").pop();var f="change",g=true;if(d=="button"||d=="submit"||d=="reset"||d=="image"){c=new La(a[0],e);f="click";g=false}else if(d=="text"||d=="textarea"||d=="hidden"||d=="password"){c=new na(a[0],e);f="keyup change"}else if(d=="checkbox"){c=new oa(a[0],
+e);f="click"}else if(d=="radio"){c=new ra(a[0],e);f="click"}else if(d=="select-one")c=new pa(a[0],e);else if(d=="select-multiple")c=new qa(a[0],e);else if(d=="file")c=this.Bb(a,e);else throw"Unknown type: "+d;a.data("controller",c);var h=b.get("$updateView");k(c.view,":input").bind(f,function(){if(c.e(b)){var i=k(c.view).attr("ng-action")||"";b.k(c,i)&&h(b)}return g});return c},Bb:function(a){var b="__uploadWidget_"+this.ac++,c=L.template(b);a.after(c);b=this.za({data:this.aa+"/admin/ServerAPI.swf",
+width:"95",height:"20",align:"top",Ed:"transparent"},{pd:"uploadWidgetId="+b,Oc:"always"},b);a.remove();a=new L(c,a[0].name,b,this.aa+"/data/"+this.fa);k(b).data("controller",a);return a}};L.dispatchEvent=function(a,b,c){a=y.getElementById(a);a=k(a).data("controller");L.prototype["_on_"+b].apply(a,c)};L.template=function(a){return k('')};L.prototype={e:function(a){var b=this.view.find("input").attr("checked")?
+this.value:null;if(this.c===b)return false;else{a.h(this.Xa,b);return true}},d:function(a){if((a=a.get(this.Xa))&&this.value!==a){this.value=a;this.view.find("a").attr("href",this.value.url).text(this.value.text);this.view.find("span").text(m.filter.bytes(this.value.size))}this.view.find("input").attr("checked",!!a)}};Q.prototype={e:N(true),d:n};Q.Rb=new Q;var La=Q;na.prototype={e:function(a){var b=this.view.value;if(this.c===b)return false;else{a.l(this.exp,b);this.c=b;return true}},d:function(a){var b=
+this.view,c=a.get(this.exp);if(typeof c==="undefined"){c=this.o;a.l(this.exp,c)}c=c?c:"";if(this.c!=c)this.c=b.value=c;var d=false;b.removeAttribute("ng-error");if(this.rc)d=!(c&&c.length>0);var e=d?"Required Value":null;if(!d&&this.L&&c){e=a.Ac(this.L,c);d=!!e}if(this.Ga!==e){this.Ga=d;if(e!==null){b.setAttribute("ng-error",e);a.Yb(this)}k(b).toggleClass("ng-validation-error",d)}}};oa.prototype={e:function(a){var b=this.view;b=b.checked?b.value:"";if(this.c===b)return false;else{a.l(this.exp,b);
+this.c=b;return true}},d:function(a){var b=this.view,c=a.eval(this.exp);if(typeof c==="undefined"){c=this.o;a.l(this.exp,c)}b.checked=b.value==""+c}};pa.prototype={e:function(a){if(this.view.selectedIndex<0)a.l(this.exp,null);else{var b=this.view.value;if(this.c===b)return false;else{a.l(this.exp,b);this.c=b;return true}}},d:function(a){var b=this.view,c=a.get(this.exp);if(typeof c==="undefined"){c=this.o;a.l(this.exp,c)}if(c!==this.c){b.value=c?c:"";this.c=c}}};qa.prototype={selected:function(){for(var a=
+[],b=this.view.options,c=0;cd;--b){var p=this.children.pop().element[0];p.parentNode.removeChild(p)}if(h&&h.element[0].nodeName==="OPTION")if(d=k(h.element[0].parentNode).data("controller")){d.c=
+undefined;d.d(a)}})}};A.va="mouseleave mouseout click dblclick keypress keyup";A.lc=function(){A.ma();var a=k(this);a.bind(A.va,A.ma);var b=a.position(),c=y.documentElement,d=(self.innerWidth||c&&c.clientWidth||y.body.clientWidth)-b.left;c=a.hasClass("ng-exception")?"EXCEPTION:":"Validation error...";a=a.attr("ng-error");d=d>375?"left":"right";c=k("");k("body").append(c);
+if(d==="left")a=b.left+this.offsetWidth+11;else{a=b.left-315;c.find(".ng-arrow-right").css({left:301})}c.css({left:a+"px",top:b.top-3+"px"});return true};A.ma=function(){k("#ng-callout").unbind(A.va,A.ma).remove();return true};A.prototype={bind:function(){this.B.find(".ng-validation-error,.ng-exception").live("mouseover",A.lc)}};S.hb='loading....
';S.prototype={vb:function(){this.$===0&&this.Ka.show();this.$++},Hb:function(){this.$--;this.$===0&&
+this.Ka.hide("fold")}}})(window,document);
diff --git a/angular.js b/angular.js
index 9609929c..adfa3611 100644
--- a/angular.js
+++ b/angular.js
@@ -299,16 +299,6 @@ function bind(_this, _function) {
};
}
-function shiftBind(_this, _function) {
- return function() {
- var args = [ this ];
- for ( var i = 0; i < arguments.length; i++) {
- args.push(arguments[i]);
- }
- return _function.apply(_this, args);
- };
-}
-
function outerHTML(node) {
var temp = document.createElement('div');
temp.appendChild(node);
@@ -342,159 +332,9 @@ function merge(src, dst) {
}
// ////////////////////////////
-// Angular
+// UrlWatcher
// ////////////////////////////
-function Angular(document, head, config) {
- this.document = jQuery(document);
- this.head = jQuery(head);
- this.config = config;
- this.location = window.location;
-}
-
-Angular.prototype = {
- load: function() {
- this.configureLogging();
- log("Server: " + this.config.server);
- this.configureJQueryPlugins();
- this.computeConfiguration();
- this.bindHtml();
- },
-
- configureJQueryPlugins: function() {
- log('Angular.configureJQueryPlugins()');
- jQuery['fn']['scope'] = function() {
- var element = this;
- while (element && element.get(0)) {
- var scope = element.data("scope");
- if (scope)
- return scope;
- element = element.parent();
- }
- return null;
- };
- jQuery['fn']['controller'] = function() {
- return this.data('controller') || NullController.instance;
- };
- },
-
- uid: function() {
- return "" + new Date().getTime();
- },
-
- computeConfiguration: function() {
- var config = this.config;
- if (!config.database) {
- var match = config.server.match(/https?:\/\/([\w]*)/);
- config.database = match ? match[1] : "$MEMORY";
- }
- },
-
- bindHtml: function() {
- log('Angular.bindHtml()');
- var watcher = this.watcher = new UrlWatcher(this.location);
- var document = this.document;
- var widgetFactory = new WidgetFactory(this.config.server, this.config.database);
- var binder = new Binder(document[0], widgetFactory, watcher, this.config);
- widgetFactory.onChangeListener = shiftBind(binder, binder.updateModel);
- var controlBar = new ControlBar(document.find('body'), this.config.server);
- var onUpdate = function(){binder.updateView();};
- var server = this.config.database=="$MEMORY" ?
- new FrameServer(this.window) :
- new Server(this.config.server, jQuery.getScript);
- server = new VisualServer(server, new Status(jQuery(document.body)), onUpdate);
- var users = new Users(server, controlBar);
- var databasePath = '/data/' + this.config.database;
- var post = function(request, callback){
- server.request("POST", databasePath, request, callback);
- };
- var datastore = new DataStore(post, users, binder.anchor);
- binder.updateListeners.push(function(){datastore.flush();});
- var scope = new Scope( {
- '$anchor' : binder.anchor,
- '$binder' : binder,
- '$config' : this.config,
- '$console' : window.console,
- '$datastore' : datastore,
- '$save' : function(callback) {
- datastore.saveScope(scope.state, callback, binder.anchor);
- },
- '$window' : window,
- '$uid' : this.uid,
- '$users' : users
- }, "ROOT");
-
- document.data('scope', scope);
- log('$binder.entity()');
- binder.entity(scope);
-
- log('$binder.compile()');
- binder.compile();
-
- log('ControlBar.bind()');
- controlBar.bind();
-
- log('$users.fetchCurrentUser()');
- function fetchCurrentUser() {
- users.fetchCurrentUser(function(u) {
- if (!u && document.find("[ng-auth=eager]").length) {
- users.login();
- }
- });
- }
- fetchCurrentUser();
-
- log('PopUp.bind()');
- new PopUp(document).bind();
-
- log('$binder.parseAnchor()');
- binder.parseAnchor();
-
- document.find("body").show();
- log('ready()');
- },
-
- visualPost: function(delegate) {
- var status = new Status(jQuery(document.body));
- return function(request, delegateCallback) {
- status.beginRequest(request);
- var callback = function() {
- status.endRequest();
- try {
- delegateCallback.apply(this, arguments);
- } catch (e) {
- alert(toJson(e));
- }
- };
- delegate(request, callback);
- };
- },
-
- configureLogging: function() {
- var url = window.location.href + '#';
- url = url.split('#')[1];
- var config = {
- debug : null
- };
- var configs = url.split('&');
- for ( var i = 0; i < configs.length; i++) {
- var part = (configs[i] + '=').split('=');
- config[part[0]] = part[1];
- }
- if (config.debug == 'console') {
- consoleNode = document.createElement("div");
- consoleNode.id = 'ng-console';
- document.getElementsByTagName('body')[0].appendChild(consoleNode);
- log = function() {
- consoleLog('ng-console-info', arguments);
- };
- console.error = function() {
- consoleLog('ng-console-error', arguments);
- };
- }
- }
-};
-
function UrlWatcher(location) {
this.location = location;
this.delay = 25;
@@ -508,6 +348,9 @@ function UrlWatcher(location) {
}
UrlWatcher.prototype = {
+ listen: function(fn){
+ this.listener = fn;
+ },
watch: function() {
var self = this;
var pull = function() {
@@ -534,50 +377,151 @@ UrlWatcher.prototype = {
self.setTimeout(pull, self.delay);
};
pull();
+ return this;
},
- setUrl: function(url) {
- //TODO: conditionaly?
- var existingURL = window.location.href;
+ set: function(url) {
+ var existingURL = this.location.href;
if (!existingURL.match(/#/))
existingURL += '#';
if (existingURL != url)
- window.location.href = url;
+ this.location.href = url;
this.existingURL = url;
},
- getUrl: function() {
+ get: function() {
return window.location.href;
}
};
-
-angular['compile'] = function(root, config) {
- config = config || {};
- var defaults = {
- 'server': "",
- 'addUrlChangeListener': noop
- };
- //todo: don't start watcher
- var angular = new Angular(root, jQuery("head"), _(defaults).extend(config));
- //todo: don't load stylesheet by default
- // loader.loadCss('/stylesheets/jquery-ui/smoothness/jquery-ui-1.7.1.css');
- // loader.loadCss('/stylesheets/css');
- angular.load();
- var scope = jQuery(root).scope();
- //TODO: cleanup
- return {
- 'updateView':function(){return scope.updateView();},
- 'set':function(){return scope.set.apply(scope, arguments);},
- 'get':function(){return scope.get.apply(scope, arguments);},
- 'init':function(){scope.get('$binder.executeInit')(); scope.updateView();},
- 'watchUrl':function(){
- var binder = scope.get('$binder');
- var watcher = angular.watcher;
- watcher.listener = bind(binder, binder.onUrlChange, watcher);
- watcher.onUpdate = function(){alert("update");};
- watcher.watch();
+
+/////////////////////////////////////////////////
+function configureJQueryPlugins() {
+ log('Angular.configureJQueryPlugins()');
+ var fn = jQuery['fn'];
+ fn['scope'] = function() {
+ var element = this;
+ while (element && element.get(0)) {
+ var scope = element.data("scope");
+ if (scope)
+ return scope;
+ element = element.parent();
}
+ return null;
+ };
+ fn['controller'] = function() {
+ return this.data('controller') || NullController.instance;
+ };
+}
+
+function configureLogging(config) {
+ if (config.debug == 'console' && !consoleNode) {
+ consoleNode = document.createElement("div");
+ consoleNode.id = 'ng-console';
+ document.getElementsByTagName('body')[0].appendChild(consoleNode);
+ log = function() {
+ consoleLog('ng-console-info', arguments);
+ };
+ console.error = function() {
+ consoleLog('ng-console-error', arguments);
+ };
+ }
+}
+
+function exposeMethods(obj, methods){
+ var bound = {};
+ foreach(methods, function(fn, name){
+ bound[name] = _(fn).bind(obj);
+ });
+ return bound;
+}
+
+function wireAngular(element, config) {
+ var widgetFactory = new WidgetFactory(config['server'], config['database']);
+ var binder = new Binder(element[0], widgetFactory, config['location'], config);
+ var controlBar = new ControlBar(element.find('body'), config.server);
+ var onUpdate = function(){binder.updateView();};
+ var server = config.database=="$MEMORY" ?
+ new FrameServer(this.window) :
+ new Server(config.server, jQuery.getScript);
+ server = new VisualServer(server, new Status(jQuery(element.body)), onUpdate);
+ var users = new Users(server, controlBar);
+ var databasePath = '/data/' + config.database;
+ var post = function(request, callback){
+ server.request("POST", databasePath, request, callback);
};
+ var datastore = new DataStore(post, users, binder.anchor);
+ binder.updateListeners.push(function(){datastore.flush();});
+ var scope = new Scope({
+ '$anchor' : binder.anchor,
+ '$updateView': _(binder.updateView).bind(binder),
+ '$config' : config,
+ '$console' : window.console,
+ '$datastore' : exposeMethods(datastore, {
+ 'load': datastore.load,
+ 'loadMany': datastore.loadMany,
+ 'loadOrCreate': datastore.loadOrCreate,
+ 'loadAll': datastore.loadAll,
+ 'save': datastore.save,
+ 'remove': datastore.remove,
+ 'flush': datastore.flush,
+ 'query': datastore.query,
+ 'entity': datastore.entity,
+ 'entities': datastore.entities,
+ 'documentCountsByUser': datastore.documentCountsByUser,
+ 'userDocumentIdsByEntity': datastore.userDocumentIdsByEntity,
+ 'join': datastore.join
+ }),
+ '$save' : function(callback) {
+ datastore.saveScope(scope.state, callback, binder.anchor);
+ },
+ '$window' : window,
+ '$uid' : function() {
+ return "" + new Date().getTime();
+ },
+ '$users' : users
+ }, "ROOT");
+
+ element.data('scope', scope);
+ binder.entity(scope);
+ binder.compile();
+ controlBar.bind();
+
+ //TODO: remove this code
+ new PopUp(element).bind();
+
+ var self = _(exposeMethods(scope, {
+ 'updateView': scope.updateView,
+ 'set': scope.set,
+ 'get': scope.get,
+ 'eval': scope.eval
+ })).extend({
+ 'init':function(){
+ config['location']['listen'](_(binder.onUrlChange).bind(binder));
+ binder.parseAnchor();
+ binder.executeInit();
+ scope.updateView();
+ return self;
+ },
+ 'element':element[0],
+ 'config':config
+ });
+ return self;
+}
+
+angular['startUrlWatcher'] = function(){
+ return new UrlWatcher(window['location']).watch();
+};
+
+angular['compile'] = function(element, config) {
+ config = _({
+ 'server': "",
+ 'location': {'get':noop, 'set':noop, 'listen':noop}
+ }).extend(config||{});
+
+ configureLogging(config);
+ configureJQueryPlugins();
+
+ return wireAngular(jQuery(element), config);
};var angularGlobal = {
'typeOf':function(obj){
if (obj === null) return "null";
@@ -901,9 +845,9 @@ defineApi('String', [angularGlobal, angularString], []);
defineApi('Date', [angularGlobal, angularDate], []);
defineApi('Function', [angularGlobal, angularCollection, angularFunction],
['bind', 'bindAll', 'delay', 'defer', 'wrap', 'compose']);
-function Binder(doc, widgetFactory, urlWatcher, config) {
+function Binder(doc, widgetFactory, location, config) {
this.doc = doc;
- this.urlWatcher = urlWatcher;
+ this.location = location;
this.anchor = {};
this.widgetFactory = widgetFactory;
this.config = config || {};
@@ -951,9 +895,8 @@ Binder.prototype = {
return params;
},
- parseAnchor: function(url) {
- var self = this;
- url = url || this.urlWatcher.getUrl();
+ parseAnchor: function() {
+ var self = this, url = this.location.get() || "";
var anchorIndex = url.indexOf('#');
if (anchorIndex < 0) return;
@@ -968,13 +911,13 @@ Binder.prototype = {
});
},
- onUrlChange: function (url) {
- this.parseAnchor(url);
+ onUrlChange: function() {
+ this.parseAnchor();
this.updateView();
},
updateAnchor: function() {
- var url = this.urlWatcher.getUrl();
+ var url = this.location.get();
var anchorIndex = url.indexOf('#');
if (anchorIndex > -1)
url = url.substring(0, anchorIndex);
@@ -991,7 +934,7 @@ Binder.prototype = {
sep = '&';
}
}
- this.urlWatcher.setUrl(url);
+ this.location.set(url);
return url;
},
@@ -1057,7 +1000,7 @@ Binder.prototype = {
jNode.addClass("ng-exception");
jNode.attr('ng-error', toJson(e, true));
}
- scope.eval('$binder.updateView()');
+ scope.get('$updateView')();
return false;
});
},
@@ -1980,7 +1923,7 @@ array = [].constructor;
function toJson(obj, pretty){
var buf = [];
- toJsonArray(buf, obj, pretty ? "\n " : null);
+ toJsonArray(buf, obj, pretty ? "\n " : null, _([]));
return buf.join('');
};
@@ -2003,7 +1946,14 @@ function fromJson(json) {
angular['toJson'] = toJson;
angular['fromJson'] = fromJson;
-function toJsonArray(buf, obj, pretty){
+function toJsonArray(buf, obj, pretty, stack){
+ if (typeof obj == "object") {
+ if (stack.include(obj)) {
+ buf.push("RECURSION");
+ return;
+ }
+ stack.push(obj);
+ }
var type = typeof obj;
if (obj === null) {
buf.push("null");
@@ -2030,7 +1980,7 @@ function toJsonArray(buf, obj, pretty){
if (typeof item == 'function' || typeof item == 'undefined') {
buf.push("null");
} else {
- toJsonArray(buf, item, pretty);
+ toJsonArray(buf, item, pretty, stack);
}
sep = true;
}
@@ -2060,7 +2010,7 @@ function toJsonArray(buf, obj, pretty){
}
buf.push(angular['String']['quote'](key));
buf.push(":");
- toJsonArray(buf, value, childPretty);
+ toJsonArray(buf, value, childPretty, stack);
comma = true;
}
} catch (e) {
@@ -2069,6 +2019,9 @@ function toJsonArray(buf, obj, pretty){
buf.push("}");
}
}
+ if (typeof obj == "object") {
+ stack.pop();
+ }
};
// Single $ is special and does not get searched
// Double $$ is special an is client only (does not get sent to server)
@@ -3153,7 +3106,7 @@ Users.prototype = {
'fetchCurrentUser':function(callback) {
var self = this;
this.server.request("GET", "/account.json", {}, function(code, response){
- self.current = response.user;
+ self['current'] = response['user'];
callback(response.user);
});
},
@@ -3161,7 +3114,7 @@ Users.prototype = {
'logout': function(callback) {
var self = this;
this.controlBar.logout(function(){
- delete self.current;
+ delete self['current'];
(callback||noop)();
});
},
@@ -3270,7 +3223,6 @@ function WidgetFactory(serverUrl, database) {
alert("ERROR: swfobject not loaded!");
};
}
- this.onChangeListener = function(){};
};
WidgetFactory.prototype = {
@@ -3304,12 +3256,12 @@ WidgetFactory.prototype = {
throw 'Unknown type: ' + type;
}
input.data('controller', controller);
- var binder = scope.get('$binder');
+ var updateView = scope.get('$updateView');
var action = function() {
if (controller.updateModel(scope)) {
var action = jQuery(controller.view).attr('ng-action') || "";
if (scope.evalWidget(controller, action)) {
- binder.updateView(scope);
+ updateView(scope);
}
}
return bubbleEvent;
@@ -3335,12 +3287,6 @@ WidgetFactory.prototype = {
var cntl = new FileController(view, fileInput[0].name, swfNode, this.serverUrl + "/data/" + this.database);
jQuery(swfNode).data('controller', cntl);
return cntl;
- },
-
- createTextWidget: function(textInput) {
- var controller = new TextController(textInput);
- controller.onChange(this.onChangeListener);
- return controller;
}
};
/////////////////////
diff --git a/example/tweeter/tweeterclient.js b/example/tweeter/tweeterclient.js
index 2fb60b0a..8c68fac0 100644
--- a/example/tweeter/tweeterclient.js
+++ b/example/tweeter/tweeterclient.js
@@ -1,6 +1,8 @@
function noop(){}
$(document).ready(function(){
- var scope = window.scope = angular.compile(document);
+ var scope = window.scope = angular.compile(document, {
+ location:angular.startUrlWatcher()
+ });
scope.getJSON = function(url, callback) {
var list = [];
var self = this;
@@ -32,6 +34,5 @@ $(document).ready(function(){
notes:'Author of & Ruby guru see: http://www.angularjs.org.',
profile_image_url:'http://media.linkedin.com/mpr/mpr/shrink_80_80/p/2/000/005/0a8/044278d.jpg'}
]);
- scope.watchUrl();
scope.init();
});
diff --git a/jsTestDriver.conf b/jsTestDriver.conf
index 1fbe05a7..28958ee4 100644
--- a/jsTestDriver.conf
+++ b/jsTestDriver.conf
@@ -1,6 +1,8 @@
server: http://localhost:9876
load:
+ - lib/jasmine/jasmine-0.10.0.js
+ - lib/jasmine-jstd-adapter/JasmineAdapter.js
- lib/webtoolkit/webtoolkit.base64.js
- lib/jquery/jquery-1.3.2.js
- lib/jquery/jquery-ui-1.7.1.custom.min.js
diff --git a/src/Angular.js b/src/Angular.js
index 3dc72ff7..51fca458 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -134,16 +134,6 @@ function bind(_this, _function) {
};
}
-function shiftBind(_this, _function) {
- return function() {
- var args = [ this ];
- for ( var i = 0; i < arguments.length; i++) {
- args.push(arguments[i]);
- }
- return _function.apply(_this, args);
- };
-}
-
function outerHTML(node) {
var temp = document.createElement('div');
temp.appendChild(node);
@@ -177,159 +167,9 @@ function merge(src, dst) {
}
// ////////////////////////////
-// Angular
+// UrlWatcher
// ////////////////////////////
-function Angular(document, head, config) {
- this.document = jQuery(document);
- this.head = jQuery(head);
- this.config = config;
- this.location = window.location;
-}
-
-Angular.prototype = {
- load: function() {
- this.configureLogging();
- log("Server: " + this.config.server);
- this.configureJQueryPlugins();
- this.computeConfiguration();
- this.bindHtml();
- },
-
- configureJQueryPlugins: function() {
- log('Angular.configureJQueryPlugins()');
- jQuery['fn']['scope'] = function() {
- var element = this;
- while (element && element.get(0)) {
- var scope = element.data("scope");
- if (scope)
- return scope;
- element = element.parent();
- }
- return null;
- };
- jQuery['fn']['controller'] = function() {
- return this.data('controller') || NullController.instance;
- };
- },
-
- uid: function() {
- return "" + new Date().getTime();
- },
-
- computeConfiguration: function() {
- var config = this.config;
- if (!config.database) {
- var match = config.server.match(/https?:\/\/([\w]*)/);
- config.database = match ? match[1] : "$MEMORY";
- }
- },
-
- bindHtml: function() {
- log('Angular.bindHtml()');
- var watcher = this.watcher = new UrlWatcher(this.location);
- var document = this.document;
- var widgetFactory = new WidgetFactory(this.config.server, this.config.database);
- var binder = new Binder(document[0], widgetFactory, watcher, this.config);
- widgetFactory.onChangeListener = shiftBind(binder, binder.updateModel);
- var controlBar = new ControlBar(document.find('body'), this.config.server);
- var onUpdate = function(){binder.updateView();};
- var server = this.config.database=="$MEMORY" ?
- new FrameServer(this.window) :
- new Server(this.config.server, jQuery.getScript);
- server = new VisualServer(server, new Status(jQuery(document.body)), onUpdate);
- var users = new Users(server, controlBar);
- var databasePath = '/data/' + this.config.database;
- var post = function(request, callback){
- server.request("POST", databasePath, request, callback);
- };
- var datastore = new DataStore(post, users, binder.anchor);
- binder.updateListeners.push(function(){datastore.flush();});
- var scope = new Scope( {
- '$anchor' : binder.anchor,
- '$binder' : binder,
- '$config' : this.config,
- '$console' : window.console,
- '$datastore' : datastore,
- '$save' : function(callback) {
- datastore.saveScope(scope.state, callback, binder.anchor);
- },
- '$window' : window,
- '$uid' : this.uid,
- '$users' : users
- }, "ROOT");
-
- document.data('scope', scope);
- log('$binder.entity()');
- binder.entity(scope);
-
- log('$binder.compile()');
- binder.compile();
-
- log('ControlBar.bind()');
- controlBar.bind();
-
- log('$users.fetchCurrentUser()');
- function fetchCurrentUser() {
- users.fetchCurrentUser(function(u) {
- if (!u && document.find("[ng-auth=eager]").length) {
- users.login();
- }
- });
- }
- fetchCurrentUser();
-
- log('PopUp.bind()');
- new PopUp(document).bind();
-
- log('$binder.parseAnchor()');
- binder.parseAnchor();
-
- document.find("body").show();
- log('ready()');
- },
-
- visualPost: function(delegate) {
- var status = new Status(jQuery(document.body));
- return function(request, delegateCallback) {
- status.beginRequest(request);
- var callback = function() {
- status.endRequest();
- try {
- delegateCallback.apply(this, arguments);
- } catch (e) {
- alert(toJson(e));
- }
- };
- delegate(request, callback);
- };
- },
-
- configureLogging: function() {
- var url = window.location.href + '#';
- url = url.split('#')[1];
- var config = {
- debug : null
- };
- var configs = url.split('&');
- for ( var i = 0; i < configs.length; i++) {
- var part = (configs[i] + '=').split('=');
- config[part[0]] = part[1];
- }
- if (config.debug == 'console') {
- consoleNode = document.createElement("div");
- consoleNode.id = 'ng-console';
- document.getElementsByTagName('body')[0].appendChild(consoleNode);
- log = function() {
- consoleLog('ng-console-info', arguments);
- };
- console.error = function() {
- consoleLog('ng-console-error', arguments);
- };
- }
- }
-};
-
function UrlWatcher(location) {
this.location = location;
this.delay = 25;
@@ -343,6 +183,9 @@ function UrlWatcher(location) {
}
UrlWatcher.prototype = {
+ listen: function(fn){
+ this.listener = fn;
+ },
watch: function() {
var self = this;
var pull = function() {
@@ -369,48 +212,149 @@ UrlWatcher.prototype = {
self.setTimeout(pull, self.delay);
};
pull();
+ return this;
},
- setUrl: function(url) {
- //TODO: conditionaly?
- var existingURL = window.location.href;
+ set: function(url) {
+ var existingURL = this.location.href;
if (!existingURL.match(/#/))
existingURL += '#';
if (existingURL != url)
- window.location.href = url;
+ this.location.href = url;
this.existingURL = url;
},
- getUrl: function() {
+ get: function() {
return window.location.href;
}
};
-
-angular['compile'] = function(root, config) {
- config = config || {};
- var defaults = {
- 'server': "",
- 'addUrlChangeListener': noop
- };
- //todo: don't start watcher
- var angular = new Angular(root, jQuery("head"), _(defaults).extend(config));
- //todo: don't load stylesheet by default
- // loader.loadCss('/stylesheets/jquery-ui/smoothness/jquery-ui-1.7.1.css');
- // loader.loadCss('/stylesheets/css');
- angular.load();
- var scope = jQuery(root).scope();
- //TODO: cleanup
- return {
- 'updateView':function(){return scope.updateView();},
- 'set':function(){return scope.set.apply(scope, arguments);},
- 'get':function(){return scope.get.apply(scope, arguments);},
- 'init':function(){scope.get('$binder.executeInit')(); scope.updateView();},
- 'watchUrl':function(){
- var binder = scope.get('$binder');
- var watcher = angular.watcher;
- watcher.listener = bind(binder, binder.onUrlChange, watcher);
- watcher.onUpdate = function(){alert("update");};
- watcher.watch();
+
+/////////////////////////////////////////////////
+function configureJQueryPlugins() {
+ log('Angular.configureJQueryPlugins()');
+ var fn = jQuery['fn'];
+ fn['scope'] = function() {
+ var element = this;
+ while (element && element.get(0)) {
+ var scope = element.data("scope");
+ if (scope)
+ return scope;
+ element = element.parent();
}
+ return null;
+ };
+ fn['controller'] = function() {
+ return this.data('controller') || NullController.instance;
};
+}
+
+function configureLogging(config) {
+ if (config.debug == 'console' && !consoleNode) {
+ consoleNode = document.createElement("div");
+ consoleNode.id = 'ng-console';
+ document.getElementsByTagName('body')[0].appendChild(consoleNode);
+ log = function() {
+ consoleLog('ng-console-info', arguments);
+ };
+ console.error = function() {
+ consoleLog('ng-console-error', arguments);
+ };
+ }
+}
+
+function exposeMethods(obj, methods){
+ var bound = {};
+ foreach(methods, function(fn, name){
+ bound[name] = _(fn).bind(obj);
+ });
+ return bound;
+}
+
+function wireAngular(element, config) {
+ var widgetFactory = new WidgetFactory(config['server'], config['database']);
+ var binder = new Binder(element[0], widgetFactory, config['location'], config);
+ var controlBar = new ControlBar(element.find('body'), config.server);
+ var onUpdate = function(){binder.updateView();};
+ var server = config.database=="$MEMORY" ?
+ new FrameServer(this.window) :
+ new Server(config.server, jQuery.getScript);
+ server = new VisualServer(server, new Status(jQuery(element.body)), onUpdate);
+ var users = new Users(server, controlBar);
+ var databasePath = '/data/' + config.database;
+ var post = function(request, callback){
+ server.request("POST", databasePath, request, callback);
+ };
+ var datastore = new DataStore(post, users, binder.anchor);
+ binder.updateListeners.push(function(){datastore.flush();});
+ var scope = new Scope({
+ '$anchor' : binder.anchor,
+ '$updateView': _(binder.updateView).bind(binder),
+ '$config' : config,
+ '$console' : window.console,
+ '$datastore' : exposeMethods(datastore, {
+ 'load': datastore.load,
+ 'loadMany': datastore.loadMany,
+ 'loadOrCreate': datastore.loadOrCreate,
+ 'loadAll': datastore.loadAll,
+ 'save': datastore.save,
+ 'remove': datastore.remove,
+ 'flush': datastore.flush,
+ 'query': datastore.query,
+ 'entity': datastore.entity,
+ 'entities': datastore.entities,
+ 'documentCountsByUser': datastore.documentCountsByUser,
+ 'userDocumentIdsByEntity': datastore.userDocumentIdsByEntity,
+ 'join': datastore.join
+ }),
+ '$save' : function(callback) {
+ datastore.saveScope(scope.state, callback, binder.anchor);
+ },
+ '$window' : window,
+ '$uid' : function() {
+ return "" + new Date().getTime();
+ },
+ '$users' : users
+ }, "ROOT");
+
+ element.data('scope', scope);
+ binder.entity(scope);
+ binder.compile();
+ controlBar.bind();
+
+ //TODO: remove this code
+ new PopUp(element).bind();
+
+ var self = _(exposeMethods(scope, {
+ 'updateView': scope.updateView,
+ 'set': scope.set,
+ 'get': scope.get,
+ 'eval': scope.eval
+ })).extend({
+ 'init':function(){
+ config['location']['listen'](_(binder.onUrlChange).bind(binder));
+ binder.parseAnchor();
+ binder.executeInit();
+ scope.updateView();
+ return self;
+ },
+ 'element':element[0],
+ 'config':config
+ });
+ return self;
+}
+
+angular['startUrlWatcher'] = function(){
+ return new UrlWatcher(window['location']).watch();
+};
+
+angular['compile'] = function(element, config) {
+ config = _({
+ 'server': "",
+ 'location': {'get':noop, 'set':noop, 'listen':noop}
+ }).extend(config||{});
+
+ configureLogging(config);
+ configureJQueryPlugins();
+
+ return wireAngular(jQuery(element), config);
};
\ No newline at end of file
diff --git a/src/Binder.js b/src/Binder.js
index b687fb77..3fc45a20 100644
--- a/src/Binder.js
+++ b/src/Binder.js
@@ -1,6 +1,6 @@
-function Binder(doc, widgetFactory, urlWatcher, config) {
+function Binder(doc, widgetFactory, location, config) {
this.doc = doc;
- this.urlWatcher = urlWatcher;
+ this.location = location;
this.anchor = {};
this.widgetFactory = widgetFactory;
this.config = config || {};
@@ -48,9 +48,8 @@ Binder.prototype = {
return params;
},
- parseAnchor: function(url) {
- var self = this;
- url = url || this.urlWatcher.getUrl();
+ parseAnchor: function() {
+ var self = this, url = this.location.get() || "";
var anchorIndex = url.indexOf('#');
if (anchorIndex < 0) return;
@@ -65,13 +64,13 @@ Binder.prototype = {
});
},
- onUrlChange: function (url) {
- this.parseAnchor(url);
+ onUrlChange: function() {
+ this.parseAnchor();
this.updateView();
},
updateAnchor: function() {
- var url = this.urlWatcher.getUrl();
+ var url = this.location.get();
var anchorIndex = url.indexOf('#');
if (anchorIndex > -1)
url = url.substring(0, anchorIndex);
@@ -88,7 +87,7 @@ Binder.prototype = {
sep = '&';
}
}
- this.urlWatcher.setUrl(url);
+ this.location.set(url);
return url;
},
@@ -154,7 +153,7 @@ Binder.prototype = {
jNode.addClass("ng-exception");
jNode.attr('ng-error', toJson(e, true));
}
- scope.eval('$binder.updateView()');
+ scope.get('$updateView')();
return false;
});
},
diff --git a/src/JSON.js b/src/JSON.js
index 0c842865..98dfddd2 100644
--- a/src/JSON.js
+++ b/src/JSON.js
@@ -2,7 +2,7 @@ array = [].constructor;
function toJson(obj, pretty){
var buf = [];
- toJsonArray(buf, obj, pretty ? "\n " : null);
+ toJsonArray(buf, obj, pretty ? "\n " : null, _([]));
return buf.join('');
};
@@ -25,7 +25,14 @@ function fromJson(json) {
angular['toJson'] = toJson;
angular['fromJson'] = fromJson;
-function toJsonArray(buf, obj, pretty){
+function toJsonArray(buf, obj, pretty, stack){
+ if (typeof obj == "object") {
+ if (stack.include(obj)) {
+ buf.push("RECURSION");
+ return;
+ }
+ stack.push(obj);
+ }
var type = typeof obj;
if (obj === null) {
buf.push("null");
@@ -52,7 +59,7 @@ function toJsonArray(buf, obj, pretty){
if (typeof item == 'function' || typeof item == 'undefined') {
buf.push("null");
} else {
- toJsonArray(buf, item, pretty);
+ toJsonArray(buf, item, pretty, stack);
}
sep = true;
}
@@ -82,7 +89,7 @@ function toJsonArray(buf, obj, pretty){
}
buf.push(angular['String']['quote'](key));
buf.push(":");
- toJsonArray(buf, value, childPretty);
+ toJsonArray(buf, value, childPretty, stack);
comma = true;
}
} catch (e) {
@@ -91,4 +98,7 @@ function toJsonArray(buf, obj, pretty){
buf.push("}");
}
}
+ if (typeof obj == "object") {
+ stack.pop();
+ }
};
diff --git a/src/Users.js b/src/Users.js
index 47da4f73..79ed3129 100644
--- a/src/Users.js
+++ b/src/Users.js
@@ -7,7 +7,7 @@ Users.prototype = {
'fetchCurrentUser':function(callback) {
var self = this;
this.server.request("GET", "/account.json", {}, function(code, response){
- self.current = response.user;
+ self['current'] = response['user'];
callback(response.user);
});
},
@@ -15,7 +15,7 @@ Users.prototype = {
'logout': function(callback) {
var self = this;
this.controlBar.logout(function(){
- delete self.current;
+ delete self['current'];
(callback||noop)();
});
},
diff --git a/src/Widgets.js b/src/Widgets.js
index f93f2476..a012adf3 100644
--- a/src/Widgets.js
+++ b/src/Widgets.js
@@ -9,7 +9,6 @@ function WidgetFactory(serverUrl, database) {
alert("ERROR: swfobject not loaded!");
};
}
- this.onChangeListener = function(){};
};
WidgetFactory.prototype = {
@@ -43,12 +42,12 @@ WidgetFactory.prototype = {
throw 'Unknown type: ' + type;
}
input.data('controller', controller);
- var binder = scope.get('$binder');
+ var updateView = scope.get('$updateView');
var action = function() {
if (controller.updateModel(scope)) {
var action = jQuery(controller.view).attr('ng-action') || "";
if (scope.evalWidget(controller, action)) {
- binder.updateView(scope);
+ updateView(scope);
}
}
return bubbleEvent;
@@ -74,12 +73,6 @@ WidgetFactory.prototype = {
var cntl = new FileController(view, fileInput[0].name, swfNode, this.serverUrl + "/data/" + this.database);
jQuery(swfNode).data('controller', cntl);
return cntl;
- },
-
- createTextWidget: function(textInput) {
- var controller = new TextController(textInput);
- controller.onChange(this.onChangeListener);
- return controller;
}
};
/////////////////////
diff --git a/test/AngularTest.js b/test/AngularTest.js
index 9610ef76..a9146adf 100644
--- a/test/AngularTest.js
+++ b/test/AngularTest.js
@@ -1,20 +1,5 @@
AngularTest = TestCase('AngularTest');
-AngularTest.prototype.testDefaultDatabasePathFromSubdomain = function() {
- var loader = new Angular(null, null, {server:"http://account.getangular.com", database:"database"});
- loader.computeConfiguration();
- assertEquals("database", loader.config.database);
-
- loader = new Angular(null, null, {server:"http://account.getangular.com"});
- loader.computeConfiguration();
- assertEquals("account", loader.config.database);
-
- loader = new Angular(null, null, {server:"https://account.getangular.com"});
- loader.computeConfiguration();
- assertEquals("account", loader.config.database);
-};
-
-
UrlWatcherTest = TestCase('UrlWatcherTest');
diff --git a/test/BinderTest.js b/test/BinderTest.js
index 0ffd2120..bbb3eb8f 100644
--- a/test/BinderTest.js
+++ b/test/BinderTest.js
@@ -5,10 +5,10 @@ function compile(content, initialScope, config) {
config = config || {autoSubmit:true};
var scope = new Scope(initialScope, "ROOT");
h.data('scope', scope);
- var binder = new Binder(h[0], new WidgetFactory(), new MockUrlWatcher(), config);
+ var binder = new Binder(h[0], new WidgetFactory(), new MockLocation(), config);
var datastore = new DataStore();
scope.set("$datastore", datastore);
- scope.set("$binder", binder);
+ scope.set("$updateView", _(binder.updateView).bind(binder));
scope.set("$anchor", binder.anchor);
binder.entity(scope);
binder.compile();
@@ -120,7 +120,7 @@ BinderTest.prototype.testChangingTextareaUpdatesModel = function(){
var form = html('');
var scope = new Scope({model:{}});
form.data('scope', scope);
- var binder = new Binder(form.get(0), new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(form.get(0), new WidgetFactory(), new MockLocation());
binder.compile();
binder.updateView();
assertEquals(scope.get('model').note, 'abc');
@@ -131,7 +131,7 @@ BinderTest.prototype.testChangingRadioUpdatesModel = function(){
'');
var scope = new Scope({model:{}});
form.data('scope', scope);
- var binder = new Binder(form.get(0), new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(form.get(0), new WidgetFactory(), new MockLocation());
binder.compile();
binder.updateView();
assertEquals(scope.get('model').price, 'A');
@@ -141,7 +141,7 @@ BinderTest.prototype.testChangingCheckboxUpdatesModel = function(){
var form = html('');
var scope = new Scope({model:{}});
form.data('scope', scope);
- var binder = new Binder(form.get(0), new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(form.get(0), new WidgetFactory(), new MockLocation());
binder.compile();
binder.updateView();
assertEquals('A', scope.get('model').price);
@@ -157,7 +157,7 @@ BinderTest.prototype.testChangingSelectNonSelectedUpdatesModel = function(){
var form = html('');
var scope = new Scope({model:{}});
form.data('scope', scope);
- var binder = new Binder(form.get(0), new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(form.get(0), new WidgetFactory(), new MockLocation());
binder.compile();
binder.updateView();
assertEquals('A', scope.get('model').price);
@@ -171,7 +171,7 @@ BinderTest.prototype.testChangingMultiselectUpdatesModel = function(){
'');
var scope = new Scope({Invoice:{}});
form.data('scope', scope);
- var binder = new Binder(form.get(0), new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(form.get(0), new WidgetFactory(), new MockLocation());
binder.compile();
binder.updateView();
assertJsonEquals(["A", "B"], scope.get('Invoice').options);
@@ -181,7 +181,7 @@ BinderTest.prototype.testChangingSelectSelectedUpdatesModel = function(){
var form = html('');
var scope = new Scope({model:{}});
form.data('scope', scope);
- var binder = new Binder(form.get(0), new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(form.get(0), new WidgetFactory(), new MockLocation());
binder.compile();
binder.updateView();
assertEquals(scope.get('model').price, 'b');
@@ -210,7 +210,7 @@ BinderTest.prototype.testApplyTextBindings = function(){
var form = html('x
');
var scope = new Scope({model:{a:123}});
form.data('scope', scope);
- var binder = new Binder(form.get(0), null, new MockUrlWatcher());
+ var binder = new Binder(form.get(0), null, new MockLocation());
binder.compile();
binder.updateView();
assertEquals('123', form.text());
@@ -287,7 +287,7 @@ BinderTest.prototype.testExistingAttrbindingIsAppended = function() {
BinderTest.prototype.testAttributesAreEvaluated = function(){
var form = html('');
form.data('scope', new Scope({a:1, b:2}));
- var binder = new Binder(form.get(0), null, new MockUrlWatcher());
+ var binder = new Binder(form.get(0), null, new MockLocation());
binder.compile();
binder.updateView();
var a = form.find("a");
@@ -304,7 +304,7 @@ BinderTest.prototype.testInputsAreUpdated = function(){
'' +
'' +
'');
- var binder = new Binder(form.get(0), new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(form.get(0), new WidgetFactory(), new MockLocation());
form.data('scope', new Scope({A:{text:"t1", textarea:"t2", radio:"r", checkbox:"c", select:"S"}}));
binder.compile();
binder.updateView();
@@ -348,21 +348,27 @@ BinderTest.prototype.testButtonElementActionExecutesInScope = function(){
};
BinderTest.prototype.testParseEmptyAnchor = function(){
- var binder = new Binder(null, null, new MockUrlWatcher());
+ var location = new MockLocation();
+ var binder = new Binder(null, null, location);
var anchor = binder.anchor;
- binder.parseAnchor("a#x=1");
+ location.url = "a#x=1";
+ binder.parseAnchor();
assertEquals(1, binder.anchor.x);
- binder.parseAnchor("a#");
+ location.url = "a#";
+ binder.parseAnchor();
assertTrue("old values did not get removed", !binder.anchor.x);
assertTrue("anchor gor replaced", anchor === binder.anchor);
assertEquals('undefined', typeof (anchor[""]));
};
BinderTest.prototype.testParseAnchor = function(){
- var binder = new Binder(null, null, new MockUrlWatcher());
- binder.parseAnchor("a#x=1");
+ var location = new MockLocation();
+ var binder = new Binder(null, null, location);
+ location.url = "a#x=1";
+ binder.parseAnchor();
assertEquals(binder.anchor.x, "1");
- binder.parseAnchor("a#a=b&c=%20&d");
+ location.url = "a#a=b&c=%20&d";
+ binder.parseAnchor();
assertEquals(binder.anchor.a, 'b');
assertEquals(binder.anchor.c, ' ');
assertTrue(binder.anchor.d !== null);
@@ -370,27 +376,27 @@ BinderTest.prototype.testParseAnchor = function(){
};
BinderTest.prototype.testWriteAnchor = function(){
- var binder = new Binder(null, null, new MockUrlWatcher());
- binder.urlWatcher.setUrl('a');
+ var binder = new Binder(null, null, new MockLocation());
+ binder.location.set('a');
binder.anchor.a = 'b';
binder.anchor.c = ' ';
binder.anchor.d = true;
binder.updateAnchor();
- assertEquals(binder.urlWatcher.getUrl(), "a#a=b&c=%20&d");
+ assertEquals(binder.location.get(), "a#a=b&c=%20&d");
};
BinderTest.prototype.testWriteAnchorAsPartOfTheUpdateView = function(){
- var binder = new Binder(html("")[0], null, new MockUrlWatcher());
- binder.urlWatcher.setUrl('a');
+ var binder = new Binder(html("")[0], null, new MockLocation());
+ binder.location.set('a');
$(binder.doc).data('scope', new Scope());
binder.anchor.a = 'b';
binder.updateView();
- assertEquals(binder.urlWatcher.getUrl(), "a#a=b");
+ assertEquals(binder.location.get(), "a#a=b");
};
BinderTest.prototype.testRepeaterUpdateBindings = function(){
var form = html('');
- var binder = new Binder(form.get(0), null, new MockUrlWatcher());
+ var binder = new Binder(form.get(0), null, new MockLocation());
var items = [{a:"A"}, {a:"B"}];
form.data('scope', new Scope({model:{items:items}}));
binder.compile();
@@ -423,7 +429,7 @@ BinderTest.prototype.testRepeaterUpdateBindings = function(){
BinderTest.prototype.testRepeaterContentDoesNotBind = function(){
var form = html('');
form.data('scope', new Scope({model:{items:[{a:"A"}]}}));
- var binder = new Binder(form.get(0), null, new MockUrlWatcher());
+ var binder = new Binder(form.get(0), null, new MockLocation());
binder.compile();
binder.updateView();
assertEquals('' +
@@ -449,7 +455,7 @@ BinderTest.prototype.testRepeaterInputContentDoesNotBind = function(){
var form =
html('');
- var binder = new Binder(form.get(0), null, new MockUrlWatcher());
+ var binder = new Binder(form.get(0), null, new MockLocation());
var items = [{a:"A"}];
form.data('scope', new Scope({model:{items:items}}));
@@ -493,7 +499,7 @@ BinderTest.prototype.testReplaceFileUploadWithSwf = function(){
var form = jQuery("body").append('');
form.data('scope', new Scope());
var factory = {};
- var binder = new Binder(form.get(0), factory, new MockUrlWatcher());
+ var binder = new Binder(form.get(0), factory, new MockLocation());
factory.createController = function(node){
assertEquals(node.attr('type'), 'file');
return {updateModel:function(){}};
@@ -504,7 +510,7 @@ BinderTest.prototype.testReplaceFileUploadWithSwf = function(){
BinderTest.prototype.testRepeaterAdd = function(){
var doc = $('');
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
doc.data('scope', new Scope({items:[{x:'a'}, {x:'b'}], $binder:binder}));
binder.compile();
binder.updateView();
@@ -521,7 +527,7 @@ BinderTest.prototype.testIfTextBindingThrowsErrorDecorateTheSpan = function(){
var doc = $('{{error.throw()}}
');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('error.throw', function(){throw "ErrorMsg1";});
@@ -549,7 +555,7 @@ BinderTest.prototype.testIfAttrBindingThrowsErrorDecorateTheSpan = function(){
var doc = $('');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('error.throw', function(){throw "ErrorMsg";});
@@ -571,7 +577,7 @@ BinderTest.prototype.testNestedRepeater = function() {
'');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('model', [{name:'a', item:['a1', 'a2']}, {name:'b', item:['b1', 'b2']}]);
@@ -595,7 +601,7 @@ BinderTest.prototype.testRadioButtonGetsPrefixed = function () {
var doc = html('');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('model', ['a1', 'a2']);
@@ -612,7 +618,7 @@ BinderTest.prototype.testHideBindingExpression = function() {
var doc = html('');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('hidden', 3);
@@ -630,7 +636,7 @@ BinderTest.prototype.testHideBinding = function() {
var doc = html('');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('hidden', 'true');
@@ -653,7 +659,7 @@ BinderTest.prototype.testShowBinding = function() {
var doc = html('');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('show', 'true');
@@ -685,7 +691,7 @@ BinderTest.prototype.testBindClass = function() {
var doc = html('');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.set('class', 'testClass');
@@ -714,7 +720,7 @@ BinderTest.prototype.testBindStyle = function() {
var doc = html('');
var scope = new Scope();
doc.data('scope', scope);
- var binder = new Binder(doc[0], new WidgetFactory(), new MockUrlWatcher());
+ var binder = new Binder(doc[0], new WidgetFactory(), new MockLocation());
binder.compile();
scope.eval('style={color:"red"}');
@@ -797,7 +803,7 @@ BinderTest.prototype.testDissableAutoSubmit = function() {
BinderTest.prototype.testSettingAnchorToNullOrUndefinedRemovesTheAnchorFromURL = function() {
var c = compile('');
- c.binder.urlWatcher.setUrl("http://server/#a=1&b=2");
+ c.binder.location.set("http://server/#a=1&b=2");
c.binder.parseAnchor();
assertEquals('1', c.binder.anchor.a);
assertEquals('2', c.binder.anchor.b);
@@ -805,7 +811,7 @@ BinderTest.prototype.testSettingAnchorToNullOrUndefinedRemovesTheAnchorFromURL =
c.binder.anchor.a = null;
c.binder.anchor.b = null;
c.binder.updateAnchor();
- assertEquals('http://server/#', c.binder.urlWatcher.getUrl());
+ assertEquals('http://server/#', c.binder.location.get());
};
BinderTest.prototype.testFillInOptionValueWhenMissing = function() {
@@ -875,15 +881,24 @@ BinderTest.prototype.testItShouldCallListenersWhenAnchorChanges = function() {
log += oldValue + "->" + newValue + ";";
});
assertEquals(0, c.scope.get("count"));
- c.binder.onUrlChange("#counter=1");
+ c.binder.location.url = "#counter=1";
+ c.binder.onUrlChange();
assertEquals(1, c.scope.get("count"));
- c.binder.onUrlChange("#counter=1");
+
+ c.binder.location.url = "#counter=1";
+ c.binder.onUrlChange();
assertEquals(1, c.scope.get("count"));
- c.binder.onUrlChange("#counter=2");
+
+ c.binder.location.url = "#counter=2";
+ c.binder.onUrlChange();
assertEquals(2, c.scope.get("count"));
- c.binder.onUrlChange("#counter=2");
+
+ c.binder.location.url = "#counter=2";
+ c.binder.onUrlChange();
assertEquals(2, c.scope.get("count"));
- c.binder.onUrlChange("#");
+
+ c.binder.location.url = "#";
+ c.binder.onUrlChange();
assertEquals("undefined->1;1->2;2->undefined;", log);
assertEquals(3, c.scope.get("count"));
};
@@ -904,7 +919,7 @@ BinderTest.prototype.testParseQueryString = function(){
BinderTest.prototype.testSetBinderAnchorTriggersListeners = function(){
expectAsserts(2);
var doc = html("")[0];
- var binder = new Binder(doc, null, new MockUrlWatcher());
+ var binder = new Binder(doc, null, new MockLocation());
var scope = new Scope({$binder:binder, $anchor:binder.anchor});
jQuery(doc).data('scope', scope);
diff --git a/test/ControlBarTest.js b/test/ControlBarTest.js
deleted file mode 100644
index c914c8ff..00000000
--- a/test/ControlBarTest.js
+++ /dev/null
@@ -1,2 +0,0 @@
-ControlBarTest = TestCase("ControlBarTest");
-
diff --git a/test/ExternalApiTest.js b/test/ExternalApiTest.js
deleted file mode 100644
index cc102ae0..00000000
--- a/test/ExternalApiTest.js
+++ /dev/null
@@ -1,15 +0,0 @@
-ExternalApiTest = TestCase("ExternalApiTest");
-
-ExternalApiTest.prototype = {
- testItShouldExposefactory:function(){
- var node = $('{{b=a+1}}
')[0];
- var scope = angular.compile(node);
- scope.init();
- assertEquals(1, scope.get('a'));
- assertEquals(2, scope.get('b'));
- },
-
- testItShouldRegisterAnchorListener: function (){
-
- }
-};
diff --git a/test/JsonTest.js b/test/JsonTest.js
index cf49bec3..9b275248 100644
--- a/test/JsonTest.js
+++ b/test/JsonTest.js
@@ -67,3 +67,14 @@ JsonTest.prototype.testItShouldUTCDates = function() {
assertEquals(date.getTime(),
fromJson('"2009-10-09T01:02:03Z"').getTime());
};
+
+JsonTest.prototype.testItShouldPreventRecursion = function () {
+ var obj = {a:'b'};
+ obj.recursion = obj;
+ assertEquals('{"a":"b","recursion":RECURSION}', angular.toJson(obj));
+};
+
+JsonTest.prototype.testItShouldSerializeSameObjectsMultipleTimes = function () {
+ var obj = {a:'b'};
+ assertEquals('{"A":{"a":"b"},"B":{"a":"b"}}', angular.toJson({A:obj, B:obj}));
+};
diff --git a/test/ScenarioSpec.js b/test/ScenarioSpec.js
new file mode 100644
index 00000000..c3c29f02
--- /dev/null
+++ b/test/ScenarioSpec.js
@@ -0,0 +1,66 @@
+describe("ScenarioSpec: Compilation", function(){
+ it("should compile dom node and return scope", function(){
+ var node = $('{{b=a+1}}
')[0];
+ var scope = angular.compile(node);
+ scope.init();
+ expect(scope.get('a')).toEqual(1);
+ expect(scope.get('b')).toEqual(2);
+ });
+
+ it("should compile jQuery node and return scope", function(){
+ var scope = angular.compile($('{{a=123}}
')).init();
+ expect($(scope.element).text()).toEqual('123');
+ });
+
+ it("should compile text node and return scope", function(){
+ var scope = angular.compile('{{a=123}}
').init();
+ expect($(scope.element).text()).toEqual('123');
+ });
+});
+
+describe("ScenarioSpec: Scope", function(){
+ it("should have set, get, eval, init, updateView methods", function(){
+ var scope = angular.compile('{{a}}
').init();
+ expect(scope.set("a", 2)).toEqual(2);
+ expect(scope.get("a")).toEqual(2);
+ expect(scope.eval("a=3")).toEqual(3);
+ scope.updateView();
+ expect($(scope.element).text()).toEqual('3');
+ });
+
+ it("should have config", function(){
+ expect(angular.compile('', {a:'b'}).config.a).toEqual('b');
+ });
+
+ it("should have $ objects", function(){
+ var scope = angular.compile('', {a:"b"});
+ expect(scope.get('$anchor')).toBeDefined();
+ expect(scope.get('$updateView')).toBeDefined();
+ expect(scope.get('$config')).toBeDefined();
+ expect(scope.get('$config.a')).toEqual("b");
+ expect(scope.get('$datastore')).toBeDefined();
+ });
+});
+
+describe("ScenarioSpec: configuration", function(){
+ it("should take location object", function(){
+ var url = "http://server/#book=moby";
+ var onUrlChange;
+ var location = {
+ listen:function(fn){onUrlChange=fn;},
+ set:function(u){url = u;},
+ get:function(){return url;}
+ };
+ var scope = angular.compile("{{$anchor}}
", {location:location});
+ var $anchor = scope.get('$anchor');
+ expect($anchor.book).toBeUndefined();
+ expect(onUrlChange).toBeUndefined();
+ scope.init();
+ expect($anchor.book).toEqual('moby');
+ expect(onUrlChange).toBeDefined();
+
+ url = "http://server/#book=none";
+ onUrlChange();
+ expect($anchor.book).toEqual('none');
+ });
+});
diff --git a/test/ScopeTest.js b/test/ScopeTest.js
index e1c5c8ce..b066f0cb 100644
--- a/test/ScopeTest.js
+++ b/test/ScopeTest.js
@@ -38,7 +38,7 @@ ScopeTest.prototype.testScopeFromPrototype = function(){
ScopeTest.prototype.testSetScopeGet = function(){
var scope = new Scope();
- scope.set('a', 987);
+ assertEquals(987, scope.set('a', 987));
assertEquals(scope.get('a'), 987);
assertEquals(scope.eval('a'), 987);
};
diff --git a/test/formsTest.js b/test/formsTest.js
deleted file mode 100644
index ccade915..00000000
--- a/test/formsTest.js
+++ /dev/null
@@ -1,18 +0,0 @@
-nglrTest = TestCase('nglrTest');
-
-nglrTest.prototype.testShiftBind = function(){
- expectAsserts(3);
- shiftBind('this', function(target, arg) {
- assertEquals(this, 'this');
- assertEquals(target, 'target');
- assertEquals(arg, 'arg');
- }).apply('target', ['arg']);
-};
-
-nglrTest.prototype.testBind = function(){
- expectAsserts(2);
- bind('this', function(arg) {
- assertEquals(this, 'this');
- assertEquals(arg, 'arg');
- }).apply('XXX', ['arg']);
-};
diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js
index 78ffd380..8fac7598 100644
--- a/test/testabilityPatch.js
+++ b/test/testabilityPatch.js
@@ -35,13 +35,13 @@ function report(reportTest){
});
}
-MockUrlWatcher = function() {
+MockLocation = function() {
this.url = "http://server";
};
-MockUrlWatcher.prototype.getUrl = function(){
+MockLocation.prototype.get = function(){
return this.url;
};
-MockUrlWatcher.prototype.setUrl = function(url){
+MockLocation.prototype.set = function(url){
this.url = url;
};
@@ -96,7 +96,7 @@ function decode64(base64){
return fromJson(Base64.decode(base64));
}
-Angular.prototype.configureJQueryPlugins();
+configureJQueryPlugins();
function assertHidden(node) {
var display = node.css('display');
--
cgit v1.2.3