diff --git a/.externalToolBuilders/JSTD_Tests.launch b/.externalToolBuilders/JSTD_Tests.launch new file mode 100644 index 00000000..503cbaff --- /dev/null +++ b/.externalToolBuilders/JSTD_Tests.launch @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..90a1eea4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +angular-minified.map +externs.js diff --git a/.project b/.project new file mode 100644 index 00000000..0fb4c323 --- /dev/null +++ b/.project @@ -0,0 +1,27 @@ + + + angular.js + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/JSTD_Tests.launch + + + + + + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope new file mode 100644 index 00000000..fcd57436 --- /dev/null +++ b/.settings/.jsdtscope @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 00000000..49c8cd4f --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.JRE_CONTAINER \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 00000000..11006e2a --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Global \ No newline at end of file diff --git a/Rakefile b/Rakefile index 9fb7f173..56f7a9c4 100644 --- a/Rakefile +++ b/Rakefile @@ -1,11 +1,40 @@ include FileUtils +desc 'Generate Externs' +task :compileexterns do + out = File.new("externs.js", "w") + + out.write("function _(){};\n") + file = File.new("lib/underscore/underscore.js", "r") + while (line = file.gets) + if line =~ /^\s*_\.(\w+)\s*=.*$/ + out.write("_.#{$1}=function(){};\n") + end + end + file.close + + out.write("function jQuery(){};\n") + file = File.new("lib/jquery/jquery-1.3.2.js", "r") + while (line = file.gets) + if line =~ /^\s*(\w+)\s*:\s*function.*$/ + out.write("jQuery.#{$1}=function(){};\n") + end + end + file.close + out.write("jQuery.scope=function(){};\n") + out.write("jQuery.controller=function(){};\n") + + out.close +end + desc 'Compile JavaScript' task :compile do - compiled = %x(java -jar lib/shrinksafe/shrinksafe.jar \ + Rake::Task['compileexterns'].execute + + concat = %x(cat \ + src/angular.prefix \ lib/webtoolkit/webtoolkit.base64.js \ - lib/underscore/underscore.js \ - src/Loader.js \ + src/Angular.js \ src/API.js \ src/Binder.js \ src/ControlBar.js \ @@ -19,35 +48,18 @@ task :compile do src/Users.js \ src/Validators.js \ src/Widgets.js \ - src/angular-bootstrap.js \ + src/angular.suffix \ ) f = File.new("angular.js", 'w') - f.write(compiled) + f.write(concat) f.close -end -desc 'Compile JavaScript with Google Closure Compiler' -task :compileclosure do %x(java -jar lib/compiler-closure/compiler.jar \ --compilation_level ADVANCED_OPTIMIZATIONS \ - --js lib/webtoolkit/webtoolkit.base64.js \ - --js lib/underscore/underscore.js \ - --js src/Loader.js \ - --js src/API.js \ - --js src/Binder.js \ - --js src/ControlBar.js \ - --js src/DataStore.js \ - --js src/Filters.js \ - --js src/JSON.js \ - --js src/Model.js \ - --js src/Parser.js \ - --js src/Scope.js \ - --js src/Server.js \ - --js src/Users.js \ - --js src/Validators.js \ - --js src/Widgets.js \ - --js src/angular-bootstrap.js \ - --js_output_file angular.js) + --js angular.js \ + --externs externs.js \ + --create_source_map ./angular-minified.map \ + --js_output_file angular-minified.js) end namespace :server do diff --git a/TODO.text b/TODO.text new file mode 100644 index 00000000..d4d013a5 --- /dev/null +++ b/TODO.text @@ -0,0 +1,6 @@ +* move angular-bootstrap.js out of anugular.js. +* 'angular' is the official namespace for public API + - angular.defaults = {} + - var scope = angular.compile(element, options); +* angular.js is not self boot straping by default. +* Remove SWFObject diff --git a/angular-minified.js b/angular-minified.js new file mode 100644 index 00000000..64ce47d8 --- /dev/null +++ b/angular-minified.js @@ -0,0 +1,99 @@ +function J(){return function(){}}function M(q){return function(){return q}} +(function(q,y){function n(){}function N(a,b,c){var d=q.console;switch(arguments.length){case 1:d.log(a);break;case 2:d.log(a,b);break;default:d.log(a,b,c);break}}function W(a,b,c){var d=q.console;switch(arguments.length){case 1:d.error(a);break;case 2:d.error(a,b);break;default:d.error(a,b,c);break}}function da(a,b){var c=y.createElement("div");c.className=a;for(var d=a="",e=0;e/g,">")}function Ca(a){if(!a||!a.replace)return a;return a.replace(//g,">").replace(/\"/g,""")}function Da(a,b){if(!a)throw"Missing this";if(!_.isFunction(b))throw"Missing function";return function(){return b.apply(a,arguments)}}function ga(a){var b=y.createElement("div"); +b.appendChild(a);var c=b.innerHTML;b.removeChild(a);return c}function Y(a){var b=(""+a).toLowerCase();if(b=="f"||b=="0"||b=="false"||b=="no")a=false;return!!a}function Z(a,b){for(var c in a){var d=b[c],e=typeof d;if(e=="undefined")b[c]=P(w(a[c]));else e=="object"&&d.constructor!=array&&c.substring(0,1)!="$"&&Z(a[c],d)}}function ha(a){this.location=a;this.delay=25;this.setTimeout=function(b,c){q.setTimeout(b,c)};this.Wb=function(b){return b};this.I=a.href}function Ea(){var a=k.fn;a.scope=function(){for(var b= +this;b&&b.get(0);){var c=b.data("scope");if(c)return c;b=b.parent()}return null};a.controller=function(){return this.data("controller")||Q.Rb}}function Fa(a){if(a.hd=="console"&&!O){O=y.createElement("div");O.id="ng-console";y.getElementsByTagName("body")[0].appendChild(O);N=function(){da("ng-console-info",arguments)};console.error=function(){da("ng-console-error",arguments)}}}function ia(a,b){var c={};o(b,function(d,e){c[e]=_(d).bind(a)});return c}function Ga(a,b){var c=new ja(b.server,b.database), +d=new x(a[0],c,b.location,b);c=new R(a.find("body"),b.oa);var e=b.fa=="$MEMORY"?new $(this.window):new ka(b.oa,k.getScript);e=new la(e,new S(k(a.body)),function(){d.d()});var f=new ma(e,c),g="/data/"+b.fa,h=new T(function(l,p){e.K("POST",g,l,p)},f,d.anchor);d.$a.push(function(){h.ga()});var i=new v({$anchor:d.anchor,$updateView:_(d.d).bind(d),$config:b,$console:q.console,$datastore:ia(h,{load:h.load,loadMany:h.ja,loadOrCreate:h.Ja,loadAll:h.Ia,save:h.save,remove:h.remove,flush:h.ga,query:h.Ua,entity:h.C, +entities:h.entities,documentCountsByUser:h.Fb,userDocumentIdsByEntity:h.yc,join:h.join}),$save:function(l){h.sc(i.p,l,d.anchor)},$window:q,$uid:function(){return""+(new Date).getTime()},$users:f},"ROOT");a.data("scope",i);d.C(i);d.compile();c.bind();(new A(a)).bind();var j=_(ia(i,{updateView:i.d,set:i.h,get:i.get,eval:i.eval})).extend({init:function(){b.location.listen(_(d.mc).bind(d));d.Ra();d.Lb();d.d();return j},element:a[0],config:b});return j}function G(a,b,c){var d=_.last(b);o(c,function(e){d[e]= +_[e]});m[a]=m[a]||{};o(b,function(e){U(m[a],e)})}function x(a,b,c,d){this.B=a;this.location=c;this.anchor={};this.Dc=b;this.zb=d||{};this.$a=[]}function R(a,b){this.document=a;this.aa=b;this.window=q;this.D=[]}function T(a,b,c){this.post=a;this.bb=b;this.z={M:[]};this.anchor=c;this.P=[]}function w(a,b){var c=[];aa(c,a,b?"\n ":null,_([]));return c.join("")}function P(a){try{var b=new D(a,true),c=b.Z();b.G();return c()}catch(d){W("fromJson error: ",a,d);throw d;}}function aa(a,b,c,d){if(typeof b== +"object"){if(d.include(b)){a.push("RECURSION");return}d.push(b)}var e=typeof b;if(b===null)a.push("null");else if(e==="function")return;else if(e==="boolean")a.push(""+b);else if(e==="number")isNaN(b)?a.push("null"):a.push(""+b);else if(e==="string")return a.push(m.String.quoteUnicode(b));else if(e==="object")if(b instanceof Array){a.push("[");var f=b.length;e=false;for(var g=0;g>2;c=(c&3)<<4|d>>4;g=(d&15)<<2|e>>6;h=e&63;if(isNaN(d))g=h=64;else if(isNaN(e))h=64;b=b+this.s.charAt(f)+this.s.charAt(c)+this.s.charAt(g)+this.s.charAt(h)}return b}, +jd:function(a){var b="",c,d,e,f,g,h=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");h>4;d=(d&15)<<4|f>>2;e=(f&3)<<6|g;b+=String.fromCharCode(c);if(f!=64)b+=String.fromCharCode(d);if(g!=64)b+=String.fromCharCode(e)}return b=ba.nb(b)},ob:function(a){a=a.replace(/\r\n/g,"\n");for(var b="",c=0;c127&&d<2048)b+=String.fromCharCode(d>>6|192);else{b+=String.fromCharCode(d>>12|224);b+=String.fromCharCode(d>>6&63|128)}b+=String.fromCharCode(d&63|128)}}return b},nb:function(a){for(var b="",c=0,d=c1=c2=0;c191&&d<224){c2=a.charCodeAt(c+1);b+=String.fromCharCode((d&31)<<6|c2&63);c+=2}else{c2=a.charCodeAt(c+1);c3=a.charCodeAt(c+2);b+=String.fromCharCode((d&15)<<12|(c2&63)<<6|c3&63);c+=3}}return b}};if(typeof y.getAttribute== +"undefined")y.getAttribute=J();if(typeof Node=="undefined")Node={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12};q.console||(q.console={log:n,error:n});var O,o=_.each,U=_.extend,k=q.jQuery,X=k.browser.msie,m=q.angular||(q.angular={}),Ba=m.validator||(m.validator={}),r=m.filter||(m.filter={}),ca=m.callbacks||(m.callbacks= +{});m.alert||(m.alert=function(){N(arguments);q.alert.apply(q,arguments)});ha.prototype={watch:function(){var a=this;function b(){if(a.I!==a.location.href){var c=a.location.hash.match(/^#\$iframe_notify=(.*)$/);if(c){a.I.match(/#/)||(a.I+="#");a.location.href=a.I;c="_iframe_notify_"+c[1];var d=ca[c];delete ca[c];try{(d||n)()}catch(e){alert(e)}}else{a.Wb(a.location.href);a.I=a.location.href}}a.setTimeout(b,a.delay)}b();return this},h:function(a){var b=this.location.href;b.match(/#/)||(b+="#");if(b!= +a)this.location.href=a;this.md=a},get:function(){return q.location.href}};m.startUrlWatcher=function(){return(new ha(q.location)).watch()};m.compile=function(a,b){b=_({server:"",location:{get:n,set:n,listen:n}}).extend(b||{});Fa(b);Ea();return Ga(k(a),b)};var H={typeOf:function(a){if(a===null)return"null";var b=typeof a;if(b=="object"){if(a instanceof Array)return"array";if(a instanceof Date)return"date";if(a.nodeType==1)return"element"}return b}},V={},Ha={includeIf:function(a,b,c){var d=_.indexOf(a, +b);if(c)d==-1&&a.push(b);else a.splice(d,1);return a},sum:function(a,b){b=m.Function.compile(b);for(var c=0,d=0;d=0&&a.splice(c,1);return b},find:function(a,b,c){if(b){var d=m.Function.compile(b);_.detect(a,function(e){if(d(e)){c=e;return true}});return c}},findById:function(a,b){return m.Lc.find(a,function(c){return c.w==b},null)},filter:function(a,b){var c=[];c.wb=function(j){for(var l=0;l-1;case "object":for(var p in j)if(p.charAt(0)!=="$"&&e(j[p],l))return true;return false;case "array":for(p=0;p=0&&a.splice(d,1);a.unshift((c?"-":"+")+b);return a},orderByDirection:function(a,b,c,d){c=c||"ng-ascend";d=d||"ng-descend";a=a[0]||"";var e=true;if(a.charAt(0)=="-"){a=a.substring(1);e=false}else if(a.charAt(0)=="+")a=a.substring(1);return a==b?e?c:d:""},merge:function(a, +b,c){var d=a[b];if(!d){d={};a[b]=d}Z(c,d);return a}},Ia={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=m.String.quote(a);for(var b=[],c=0;c-1;){c1||x.H(a[0])!==null};x.H=function(a){return(a=a.replace(/\n/gm," ").match(/^\{\{(.*)\}\}$/))?a[1]:null};x.prototype={nc:function(a){var b={};a.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(c,d, +e){if(d)b[decodeURIComponent(d)]=decodeURIComponent(e)});return b},Ra:function(){var a=this,b=this.location.get()||"",c=b.indexOf("#");if(!(c<0)){b=this.nc(b.substring(c+1));o(a.anchor,function(d,e){delete a.anchor[e]});o(b,function(d,e){a.anchor[e]=d})}},mc:function(){this.Ra();this.d()},xc:function(){var a=this.location.get()||"",b=a.indexOf("#");if(b>-1)a=a.substring(0,b);a+="#";b="";for(var c in this.anchor){var d=this.anchor[c];if(typeof d==="undefined"||d===null)delete this.anchor[c];else{a+= +b+encodeURIComponent(c);if(d!==true)a+="="+encodeURIComponent(d);b="&"}}this.location.h(a);return a},d:function(){(new Date).getTime();var a=k(this.B).scope();a.h("$invalidWidgets",[]);a.d();(new Date).getTime();this.xc();_.each(this.$a,function(b){b()})},R:function(a){var b=k(this.B),c=b.find(a);if(b.is(a))c=c.andSelf();return c},Lb:function(){this.R("[ng-init]").each(function(){var a=k(this),b=a.scope();try{b.eval(a.attr("ng-init"))}catch(c){alert("EVAL ERROR:\n"+a.attr("ng-init")+"\n"+w(c,true))}})}, +C:function(a){this.R("[ng-entity]").attr("ng-watch",function(){try{var b=k(this);return a.C(b.attr("ng-entity"))+(b.attr("ng-watch")||"")}catch(c){alert(c)}})},compile:function(){var a=k(this.B);if(this.zb.Qc){var b=this.R(":submit").not("[ng-action]");b.attr("ng-action","$save()");b.not(":disabled").not("ng-bind-attr").attr("ng-bind-attr",'{disabled:"{{$invalidWidgets}}"}')}this.Sa(this.B)(this.B,a.scope(),"");this.R("a[ng-action]").live("click",function(){var c=k(this),d=c.scope();try{d.eval(c.attr("ng-action")); +c.removeAttr("ng-error");c.removeClass("ng-exception")}catch(e){c.addClass("ng-exception");c.attr("ng-error",w(e,true))}d.get("$updateView")();return false})},wc:function(a,b,c){b=b.concat();var d=b.pop(),e=x.X(a.nodeValue);if(e.length>1||x.H(e[0])){var f=a.parentNode;if(ea(f)){f.setAttribute("ng-bind-template",a.nodeValue);c.push({path:b,b:function(l){return new L(l,l.getAttribute("ng-bind-template"))}})}else for(var g=0;g2&&a.setAttribute("ng-bind-attr",d)}a.getAttribute||N(a);var j=a.getAttribute("ng-repeat");if(j){a.removeAttribute("ng-repeat");var l=this.Sa(a);d=y.createComment("ng-repeat: "+ +j);e=a.parentNode;e.insertBefore(d,a);e.removeChild(a);function p(s,t,z){var I=k(a).clone();I.css("display","");I.attr("ng-repeat-index",""+z);I.data("scope",s);l(I[0],s,t+z+":");return I}c.push({path:b,b:function(s,t,z){return new Aa(k(s),j,p,z)}})}else{a.getAttribute("ng-eval")&&c.push({path:b,b:this.fc});a.getAttribute("ng-bind")&&c.push({path:b,b:this.Pa});a.getAttribute("ng-bind-attr")&&c.push({path:b,b:this.bc});a.getAttribute("ng-hide")&&c.push({path:b,b:this.gc});a.getAttribute("ng-show")&& +c.push({path:b,b:this.hc});a.getAttribute("ng-class")&&c.push({path:b,b:this.cc});a.getAttribute("ng-class-odd")&&c.push({path:b,b:this.ec});a.getAttribute("ng-class-even")&&c.push({path:b,b:this.dc});a.getAttribute("ng-style")&&c.push({path:b,b:this.ic});a.getAttribute("ng-watch")&&c.push({path:b,b:this.jc});d=a.nodeName;if(d=="INPUT"||d=="TEXTAREA"||d=="SELECT"||d=="BUTTON"){var B=this;c.push({path:b,b:function(s,t,z){s.name=z+s.name.split(":").pop();return B.Dc.Ab(k(s),t)}})}if(d=="OPTION")if(!k("')};K.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:M(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("
"+c+"
"+a+"
");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 0c19175d..2a8d6008 100644 --- a/angular.js +++ b/angular.js @@ -1,128 +1,4009 @@ -function r(){return function(a){return a}}function v(){return function(){}}function x(a){return function(b){this[a]=b}}function z(a){return function(){return a}}var A; -function aa(a){var b="",c,e,d,f,i,j,n=0;a=a;a=a.replace(/\r\n/g,"\n");e="";for(d=0;d127&&f<2048)e+=String.fromCharCode(f>>6|192);else{e+=String.fromCharCode(f>>12|224);e+=String.fromCharCode(f>>6&63|128)}e+=String.fromCharCode(f&63|128)}}for(a=e;n>2;c=(c&3)<<4|e>>4;i=(e&15)<<2|d>>6;j=d&63;if(isNaN(e))i=j=64;else if(isNaN(d))j=64;b=b+this.eb.charAt(f)+ -this.eb.charAt(c)+this.eb.charAt(i)+this.eb.charAt(j)}return b};(function(){var a=this,b=a.cb;function c(g){this.da=g}var e=typeof StopIteration!=="undefined"?StopIteration:"__break__",d=a.cb=function(g){return new c(g)};if(typeof exports!=="undefined")exports.cb=d;var f=Array.prototype.slice,i=Array.prototype.unshift,j=Object.prototype.toString,n=Object.prototype.hasOwnProperty,m=Object.prototype.propertyIsEnumerable;d.oe="0.5.1";d.a=function(g,h,k){try{if(g.forEach)g.forEach(h,k);else if(d.z(g)||d.dc(g))for(var l=0,p=g.length;l=l.ga&&(l={value:p,ga:s})});return l.value};d.min=function(g,h,k){if(!h&&d.z(g))return Math.min.apply(Math,g);var l={ga:Infinity};d.a(g,function(p,s,u){s=h?h.call(k,p,s,u):p;sp?1:0}),"value")};d.yf=function(g,h,k){k=k||d.ka;for(var l=0,p=g.length;l>1;k(g[s])=0})})};d.Pf=function(){for(var g=d.D(arguments),h=d.max(d.vb(g,"length")),k=new Array(h),l=0;l0?p-h:h-p)>=0)return l;l[s++]=p}};d.u=function(g,h){var k=d.Q(arguments,2);return function(){return g.apply(h||a,k.concat(d.D(arguments)))}};d.we=function(g){var h= -d.Q(arguments);if(h.length==0)h=d.nb(g);d.a(h,function(k){g[k]=d.u(g[k],g)});return g};d.lb=function(g,h){var k=d.Q(arguments,2);return setTimeout(function(){return g.apply(g,k)},h)};d.defer=function(g){return d.lb.apply(d,[g,1].concat(d.Q(arguments)))};d.Of=function(g,h){return function(){var k=[g].concat(d.D(arguments));return h.apply(h,k)}};d.Ie=function(){var g=d.D(arguments);return function(){for(var h=d.D(arguments),k=g.length-1;k>=0;k--)h=[g[k].apply(this,h)];return h[0]}};d.la=function(g){if(d.z(g))return d.Md(0, -g.length);var h=[];for(var k in g)n.call(g,k)&&h.push(k);return h};d.Ab=function(g){return d.map(g,d.ka)};d.nb=function(g){return d.select(d.la(g),function(h){return d.P(g[h])}).sort()};d.extend=function(g,h){for(var k in h)g[k]=h[k];return g};d.fa=function(g){if(d.z(g))return g.slice(0);return d.extend({},g)};d.isEqual=function(g,h){if(g===h)return true;var k=typeof g;if(k!=typeof h)return false;if(g==h)return true;if(!g&&h||g&&!h)return false;if(g.isEqual)return g.isEqual(h);if(d.pd(g)&&d.pd(h))return g.getTime()=== -h.getTime();if(d.fc(g)&&d.fc(h))return true;if(d.qd(g)&&d.qd(h))return g.source===h.source&&g.global===h.global&&g.ignoreCase===h.ignoreCase&&g.multiline===h.multiline;if(k!=="object")return false;if(g.length&&g.length!==h.length)return false;k=d.la(g);var l=d.la(h);if(k.length!=l.length)return false;for(var p in g)if(!d.isEqual(g[p],h[p]))return false;return true};d.bf=function(g){return d.la(g).length==0};d.af=function(g){return!!(g&&g.nodeType==1)};d.dc=function(g){return g&&"0"<=g.length&&g.length<= -"9"&&!d.z(g)&&!m.call(g,"length")};d.fc=function(g){return"0"<=g&&g<="9"&&isNaN(g)};d.cf=function(g){return g===null};d.K=function(g){return typeof g=="undefined"};for(var o=["Array","Date","Function","Number","RegExp","String"],q=0,w=o.length;q)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');");return h?g(h):g};d.forEach=d.a;d.Se=d.We=d.reduce;d.Te=d.reduceRight;d.filter=d.select;d.every=d.all;d.some=d.Uc;d.ac=d.jd;d.Cf=d.Q;d.hf=d.nb;function y(g,h){return h?d(g).Ob():g}d.a(d.nb(d),function(g){var h= -d[g];c.prototype[g]=function(){i.call(arguments,this.da);return y(h.apply(d,arguments),this.db)}});d.a(["pop","push","reverse","shift","sort","splice","unshift"],function(g){var h=Array.prototype[g];c.prototype[g]=function(){h.apply(this.da,arguments);return y(this.da,this.db)}});d.a(["concat","join","slice"],function(g){var h=Array.prototype[g];c.prototype[g]=function(){return y(h.apply(this.da,arguments),this.db)}});c.prototype.Ob=function(){this.db=true;return this};c.prototype.value=function(){return this.da}})();if(typeof document.getAttribute=="undefined")document.getAttribute=v();if(typeof Node=="undefined")Node={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12};if(_.K(window.jf))nglr={};if(_.K(window.Lb))angular={};if(_.K(angular.k))angular.k={};if(_.K(angular.filter))angular.filter={}; -if(_.K(window.console))window.console={log:v(),error:v()};if(_.K(nglr.alert))nglr.alert=function(){console.log(arguments);window.alert.apply(window,arguments)};nglr.Qb=function(a,b){var c=document.createElement("div");c.className=a;for(var e=a="",d=0;d/g,">")};nglr.hd=function(a){if(!a||!a.replace)return a;return a.replace(//g,">").replace(/\"/g,""")}; -nglr.u=function(a,b){if(!a)throw"Missing this";if(!_.P(b))throw"Missing function";return function(){return b.apply(a,arguments)}};nglr.Qd=function(a,b){return function(){for(var c=[this],e=0;e=0&&a.splice(c,1);return b},find:function(a,b,c){if(b){var e=angular.$.compile(b);_.Ub(a,function(d){if(e(d)){c=d;return true}});return c}},Pe:function(a,b){return angular.La.find(a,function(c){return c.R==b},null)},filter:function(a,b){var c= -[];c.Zc=function(m){for(var o=0;o-1;case "object":for(var q in m)if(q.charAt(0)!=="$"&&d(m[q],o))return true;return false;case "array":for(q=0;q=0&&a.splice(e,1);a.unshift((c?"-":"+")+b);return a},mf:function(a,b,c,e){c=c||"ng-ascend";e=e||"ng-descend";a=a[0]||"";var d=true;if(a.charAt(0)=="-"){a=a.substring(1);d=false}else if(a.charAt(0)=="+")a=a.substring(1);return a==b?d?c: -e:""},Ea:function(a,b,c){var e=a[b];if(!e){e={};a[b]=e}nglr.Ea(c,e);return a}}; -angular.U={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")+'"'},tc:function(a){a=angular.U.quote(a);for(var b=[],c=0;c-1;){c1||nglr.g.ea(a[0])!==null};nglr.g.ea=function(a){return(a=a.replace(/\n/gm," ").match(/^\{\{(.*)\}\}$/))?a[1]:null}; -function ga(a,b){var c={};b.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(e,d,f){if(d)c[decodeURIComponent(d)]=decodeURIComponent(f)});return c}function D(a,b){b=b||window.location.href;var c=b.indexOf("#");if(!(c<0)){b=b.substring(c+1);b=ga(a,b);jQuery.a(a.anchor,function(e){delete a.anchor[e]});jQuery.a(b,function(e,d){a.anchor[e]=d})}}nglr.g.prototype.Ld=function(a){console.log("URL change detected",a);D(this,a);this.c()}; -function ha(a){var b=window.location.href,c=b.indexOf("#");if(c>-1)b=b.substring(0,c);b+="#";c="";for(var e in a.anchor){var d=a.anchor[e];if(typeof d==="undefined"||d===null)delete a.anchor[e];else{b+=c+encodeURIComponent(e);if(d!==true)b+="="+encodeURIComponent(d);c="&"}}a=b;e=window.location.href;e.match(/#/)||(e+="#");if(e!=a)window.location.href=a;self.Oe=a;return b} -nglr.g.prototype.c=function(){(new Date).getTime();var a=jQuery(this.F).scope();E(a,"$invalidWidgets",[]);a.c();(new Date).getTime();ha(this);_.a(this.Cc,function(b){b()})};function fa(a){jQuery("[ng-init]",a.F).a(function(){var b=jQuery(this),c=b.scope();try{c.eval(b.e("ng-init"))}catch(e){nglr.alert("EVAL ERROR:\n"+b.e("ng-init")+"\n"+nglr.m(e,true))}})} -nglr.g.prototype.ha=function(a){jQuery("[ng-entity]",this.F).e("ng-watch",function(){try{var b=jQuery(this);return a.ha(b.e("ng-entity"))+(b.e("ng-watch")||"")}catch(c){nglr.alert(c)}})}; -nglr.g.prototype.compile=function(){var a=jQuery(this.F),b=this;if(this.w.Xc){var c=jQuery(":submit",this.F).rc("[ng-action]");c.e("ng-action","$save()");c.rc(":disabled").rc("ng-bind-attr").e("ng-bind-attr",'{disabled:"{{$invalidWidgets}}"}')}F(this,this.F)(this.F,a.scope(),"");jQuery("a[ng-action]",this.F).vd("click",function(){var e=jQuery(this);try{e.scope().eval(e.e("ng-action"));e.vc("ng-error");e.wc("ng-exception")}catch(d){e.fb("ng-exception");e.e("ng-error",nglr.m(d,true))}b.c();return false})}; -function ia(a,b,c,e){a=c.concat();c=a.pop();var d=nglr.g.Ha(b.nodeValue);if(d.length>1||nglr.g.ea(d[0])){var f=b.parentNode;if(nglr.ec(f)){f.setAttribute("ng-bind-template",b.nodeValue);e.push({path:a,b:function(o){return new nglr.S(o,o.getAttribute("ng-bind-template"))}})}else for(var i=0;i2&&b.setAttribute("ng-bind-attr",d)}b.getAttribute|| -console.log(b);var o=b.getAttribute("ng-repeat");if(o){b.removeAttribute("ng-repeat");var q=F(a,b);d=document.createComment("ng-repeat: "+o);f=b.parentNode;f.insertBefore(d,b);f.removeChild(b);var w=function(t,y,g){var h=jQuery(b).fa();h.kb("display","");h.e("ng-repeat-index",""+g);h.data("scope",t);q(h[0],t,y+g+":");return h};e.push({path:c,b:function(t,y,g){return new nglr.Xa(jQuery(t),o,w,g)}})}else{b.getAttribute("ng-eval")&&e.push({path:c,b:a.Dd});b.getAttribute("ng-bind")&&e.push({path:c,b:a.qc}); -b.getAttribute("ng-bind-attr")&&e.push({path:c,b:a.zd});b.getAttribute("ng-hide")&&e.push({path:c,b:a.Ed});b.getAttribute("ng-show")&&e.push({path:c,b:a.Fd});b.getAttribute("ng-class")&&e.push({path:c,b:a.Ad});b.getAttribute("ng-class-odd")&&e.push({path:c,b:a.Cd});b.getAttribute("ng-class-even")&&e.push({path:c,b:a.Bd});b.getAttribute("ng-style")&&e.push({path:c,b:a.Gd});b.getAttribute("ng-watch")&&e.push({path:c,b:a.Hd});d=b.nodeName;if(d=="INPUT"||d=="TEXTAREA"||d=="SELECT"||d=="BUTTON")e.push({path:c, -b:function(t,y,g){t.name=g+t.name.split(":").pop();return ja(a.$d,jQuery(t),y)}});if(d=="OPTION")if(!jQuery("')};nglr.T.prototype.j=function(a){var b=this.view.find("input").e("checked")?this.value:null;if(this.d===b)return false;else{E(a,this.xc,b);return true}}; -nglr.T.prototype.c=function(a){if((a=a.i(this.xc))&&this.value!==a){this.value=a;this.view.find("a").e("href",this.value.url).text(this.value.text);this.view.find("span").text(angular.filter.gb(this.value.size))}this.view.find("input").e("checked",!!a)};nglr.ba=x("view");nglr.ba.prototype.j=z(true);nglr.ba.prototype.c=v();nglr.ba.od=new nglr.ba;nglr.Na=x("view");nglr.Na.prototype.j=z(true);nglr.Na.prototype.c=v(); -nglr.bb=function(a,b){this.view=a;this.exp=b;this.k=a.getAttribute("ng-validate");this.Nd=typeof a.attributes["ng-required"]!="undefined";this.hc=null;this.d=undefined;this.H=a.value;a.getAttribute("ng-widget")==="datepicker"&&jQuery(a).Ne()};nglr.bb.prototype.j=function(a){var b=this.view.value;if(this.d===b)return false;else{$(a,this.exp,b);this.d=b;return true}}; -nglr.bb.prototype.c=function(a){var b=this.view,c=a.i(this.exp);if(typeof c==="undefined"){c=this.H;$(a,this.exp,c)}c=c?c:"";if(this.d!=c)this.d=b.value=c;var e=false;b.removeAttribute("ng-error");if(this.Nd)e=!(c&&c.length>0);var d=e?"Required Value":null;if(!e&&this.k&&c){e=this.k;c=c;d=nglr.h.ya[e];if(!d){d=(new nglr.q(e)).k();nglr.h.ya[e]=d}e={scope:a};d=d(e)(e,c);e=!!d}if(this.hc!==d){this.hc=e;if(d!==null){b.setAttribute("ng-error",d);a.I.he.push(this)}jQuery(b).zb("ng-validation-error",e)}}; -nglr.Oa=function(a,b){this.view=a;this.exp=b;this.d=undefined;this.H=a.checked?a.value:""};nglr.Oa.prototype.j=function(a){var b=this.view;b=b.checked?b.value:"";if(this.d===b)return false;else{$(a,this.exp,b);this.d=b;return true}};nglr.Oa.prototype.c=function(a){var b=this.view,c=a.eval(this.exp);if(typeof c==="undefined"){c=this.H;$(a,this.exp,c)}b.checked=b.value==""+c};nglr.Ya=function(a,b){this.view=a;this.exp=b;this.d=undefined;this.H=a.value}; -nglr.Ya.prototype.j=function(a){if(this.view.selectedIndex<0)$(a,this.exp,null);else{var b=this.view.value;if(this.d===b)return false;else{$(a,this.exp,b);this.d=b;return true}}};nglr.Ya.prototype.c=function(a){var b=this.view,c=a.i(this.exp);if(typeof c==="undefined"){c=this.H;$(a,this.exp,c)}if(c!==this.d){b.value=c?c:"";this.d=c}};nglr.ua=function(a,b){this.view=a;this.exp=b;this.d=undefined;this.H=this.selected()}; -nglr.ua.prototype.selected=function(){for(var a=[],b=this.view.options,c=0;ce;--b)this.xa.pop().element.removeNode();if(j&&j.element[0].nodeName==="OPTION")if(e=jQuery(j.element[0].parentNode).data("controller")){e.d=undefined;e.c(a)}})};nglr.A=x("F");nglr.A.Fb="mouseleave mouseout click dblclick keypress keyup";nglr.A.prototype.u=function(){this.F.find(".ng-validation-error,.ng-exception").vd("mouseover",nglr.A.Kd)}; -nglr.A.Kd=function(){nglr.A.ub();var a=jQuery(this);a.u(nglr.A.Fb,nglr.A.ub);var b=a.position(),c=document.documentElement,e=(self.innerWidth||c&&c.clientWidth||document.body.clientWidth)-b.left;c=a.Ue("ng-exception")?"EXCEPTION:":"Validation error...";a=a.e("ng-error");e=e>375?"left":"right";c=jQuery("
"+c+"
"+a+"
");jQuery("body").append(c);if(e==="left")a=b.left+this.offsetWidth+ -11;else{a=b.left-315;c.find(".ng-arrow-right").kb({left:301})}c.kb({left:a+"px",top:b.top-3+"px"});return true};nglr.A.ub=function(){jQuery("#ng-callout").Gf(nglr.A.Fb,nglr.A.ub).remove();return true};nglr.$a=function(a){this.lc=a.append(nglr.$a.Ic).find("#ng-loading");this.Ia=0};nglr.$a.Ic='
loading....
';function Da(a){a.Ia===0&&a.lc.wb();a.Ia++};(function(a){for(var b=/(.*)\/angular-(.*).js(#(.*))?/,c=document.getElementsByTagName("script"),e={Xc:true,Wc:true,Nb:false},d=0;d<\/script>')}if(e.Nb){m("/javascripts/webtoolkit.base64.js");m("/javascripts/swfobject.js");m("/javascripts/jQuery/jquery-1.3.2.js");m("/javascripts/jQuery/jquery-ui-1.7.1.custom.min.js");m("/javascripts/underscore/underscore.js");m("/javascripts/nglr/Loader.js");m("/javascripts/nglr/API.js");m("/javascripts/nglr/Binder.js");m("/javascripts/nglr/ControlBar.js");m("/javascripts/nglr/DataStore.js");m("/javascripts/nglr/Filters.js");m("/javascripts/nglr/JSON.js");m("/javascripts/nglr/Model.js"); -m("/javascripts/nglr/Parser.js");m("/javascripts/nglr/Scope.js");m("/javascripts/nglr/Server.js");m("/javascripts/nglr/Users.js");m("/javascripts/nglr/Validators.js");m("/javascripts/nglr/Widgets.js")}else{m("/ajax/libs/swfobject/2.2/swfobject.js","http://ajax.googleapis.com");m("/ajax/libs/jquery/1.3.2/jquery.min.js","http://ajax.googleapis.com");m("/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js","http://ajax.googleapis.com")}window.onload=function(){window.Lb.nd=function(h,k){var l=_.fa(e||{});_.extend(l, -k);(new nglr.Va(h,jQuery("head"),l)).load()};var o=window.document;if(e.Yc){o=null;for(var q=e.Yc.split("|"),w=0;w1)if(!window.document.getElementById(t[1]))continue;o=window.document.getElementById(y)}}e.Wc&&o&&window.Lb.nd(o);if(typeof a==="function")try{a.apply(this,arguments)}catch(g){}}})(window.onload); +/** + * 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. + */ +(function(window, document){ +/** +* +* Base64 encode / decode +* http://www.webtoolkit.info/ +* +**/ + +var Base64 = { + + // private property + _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=", + + // public method for encoding + encode : function (input) { + var output = ""; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 0; + + input = Base64._utf8_encode(input); + + while (i < input.length) { + + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); + + } + + return output; + }, + + // public method for decoding + decode : function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + while (i < input.length) { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + + } + + output = Base64._utf8_decode(output); + + return output; + + }, + + // private method for UTF-8 encoding + _utf8_encode : function (string) { + string = string.replace(/\r\n/g,"\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; + }, + + // private method for UTF-8 decoding + _utf8_decode : function (utftext) { + var string = ""; + var i = 0; + var c = c1 = c2 = 0; + + while ( i < utftext.length ) { + + c = utftext.charCodeAt(i); + + if (c < 128) { + string += String.fromCharCode(c); + i++; + } + else if((c > 191) && (c < 224)) { + c2 = utftext.charCodeAt(i+1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } + else { + c2 = utftext.charCodeAt(i+1); + c3 = utftext.charCodeAt(i+2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + + } + + return string; + } + +};if (typeof document.getAttribute == 'undefined') + document.getAttribute = function() {}; +if (typeof Node == 'undefined') { + Node = { + ELEMENT_NODE : 1, + ATTRIBUTE_NODE : 2, + TEXT_NODE : 3, + CDATA_SECTION_NODE : 4, + ENTITY_REFERENCE_NODE : 5, + ENTITY_NODE : 6, + PROCESSING_INSTRUCTION_NODE : 7, + COMMENT_NODE : 8, + DOCUMENT_NODE : 9, + DOCUMENT_TYPE_NODE : 10, + DOCUMENT_FRAGMENT_NODE : 11, + NOTATION_NODE : 12 + }; +} + +function noop() {} +if (!window['console']) window['console']={'log':noop, 'error':noop}; + +var consoleNode, + foreach = _.each, + extend = _.extend, + jQuery = window['jQuery'], + msie = jQuery['browser']['msie'], + angular = window['angular'] || (window['angular'] = {}), + angularValidator = angular['validator'] || (angular['validator'] = {}), + angularFilter = angular['filter'] || (angular['filter'] = {}), + angularCallbacks = angular['callbacks'] || (angular['callbacks'] = {}), + angularAlert = angular['alert'] || (angular['alert'] = function(){ + log(arguments); window.alert.apply(window, arguments); + }); + +function log(a, b, c){ + var console = window['console']; + switch(arguments.length) { + case 1: + console['log'](a); + break; + case 2: + console['log'](a, b); + break; + default: + console['log'](a, b, c); + break; + } +} + +function error(a, b, c){ + var console = window['console']; + switch(arguments.length) { + case 1: + console['error'](a); + break; + case 2: + console['error'](a, b); + break; + default: + console['error'](a, b, c); + break; + } +} + +function consoleLog(level, objs) { + var log = document.createElement("div"); + log.className = level; + var msg = ""; + var sep = ""; + for ( var i = 0; i < objs.length; i++) { + var obj = objs[i]; + msg += sep + (typeof obj == 'string' ? obj : toJson(obj)); + sep = " "; + } + log.appendChild(document.createTextNode(msg)); + consoleNode.appendChild(log); +} + +function isNode(inp) { + return inp && + inp.tagName && + inp.nodeName && + inp.ownerDocument && + inp.removeAttribute; +} + +function isLeafNode (node) { + switch (node.nodeName) { + case "OPTION": + case "PRE": + case "TITLE": + return true; + default: + return false; + } +} + +function setHtml(node, html) { + if (isLeafNode(node)) { + if (msie) { + node.innerText = html; + } else { + node.textContent = html; + } + } else { + node.innerHTML = html; + } +} + +function escapeHtml(html) { + if (!html || !html.replace) + return html; + return html. + replace(/&/g, '&'). + replace(//g, '>'); +} + +function escapeAttr(html) { + if (!html || !html.replace) + return html; + return html.replace(//g, '>').replace(/\"/g, + '"'); +} + +function bind(_this, _function) { + if (!_this) + throw "Missing this"; + if (!_.isFunction(_function)) + throw "Missing function"; + return function() { + return _function.apply(_this, arguments); + }; +} + +function outerHTML(node) { + var temp = document.createElement('div'); + temp.appendChild(node); + var outerHTML = temp.innerHTML; + temp.removeChild(node); + return outerHTML; +} + +function trim(str) { + return str.replace(/^ */, '').replace(/ *$/, ''); +} + +function toBoolean(value) { + var v = ("" + value).toLowerCase(); + if (v == 'f' || v == '0' || v == 'false' || v == 'no') + value = false; + return !!value; +} + +function merge(src, dst) { + for ( var key in src) { + var value = dst[key]; + var type = typeof value; + if (type == 'undefined') { + dst[key] = fromJson(toJson(src[key])); + } else if (type == 'object' && value.constructor != array && + key.substring(0, 1) != "$") { + merge(src[key], value); + } + } +} + +// //////////////////////////// +// UrlWatcher +// //////////////////////////// + +function UrlWatcher(location) { + this.location = location; + this.delay = 25; + this.setTimeout = function(fn, delay) { + window.setTimeout(fn, delay); + }; + this.listener = function(url) { + return url; + }; + this.expectedUrl = location.href; +} + +UrlWatcher.prototype = { + listen: function(fn){ + this.listener = fn; + }, + watch: function() { + var self = this; + var pull = function() { + if (self.expectedUrl !== self.location.href) { + var notify = self.location.hash.match(/^#\$iframe_notify=(.*)$/); + if (notify) { + if (!self.expectedUrl.match(/#/)) { + self.expectedUrl += "#"; + } + self.location.href = self.expectedUrl; + var id = '_iframe_notify_' + notify[1]; + var notifyFn = angularCallbacks[id]; + delete angularCallbacks[id]; + try { + (notifyFn||noop)(); + } catch (e) { + alert(e); + } + } else { + self.listener(self.location.href); + self.expectedUrl = self.location.href; + } + } + self.setTimeout(pull, self.delay); + }; + pull(); + return this; + }, + + set: function(url) { + var existingURL = this.location.href; + if (!existingURL.match(/#/)) + existingURL += '#'; + if (existingURL != url) + this.location.href = url; + this.existingURL = url; + }, + + get: function() { + return window.location.href; + } +}; + +///////////////////////////////////////////////// +function 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(); + binder.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"; + var type = typeof obj; + if (type == "object") { + if (obj instanceof Array) return "array"; + if (obj instanceof Date) return "date"; + if (obj.nodeType == 1) return "element"; + } + return type; + } +}; + +var angularCollection = {}; +var angularObject = {}; +var angularArray = { + 'includeIf':function(array, value, condition) { + var index = _.indexOf(array, value); + if (condition) { + if (index == -1) + array.push(value); + } else { + array.splice(index, 1); + } + return array; + }, + 'sum':function(array, expression) { + var fn = angular['Function']['compile'](expression); + var sum = 0; + for (var i = 0; i < array.length; i++) { + var value = 1 * fn(array[i]); + if (!isNaN(value)){ + sum += value; + } + } + return sum; + }, + 'remove':function(array, value) { + var index = _.indexOf(array, value); + if (index >=0) + array.splice(index, 1); + return value; + }, + 'find':function(array, condition, defaultValue) { + if (!condition) return undefined; + var fn = angular['Function']['compile'](condition); + _.detect(array, function($){ + if (fn($)){ + defaultValue = $; + return true; + } + }); + return defaultValue; + }, + 'findById':function(array, id) { + return angular.Array.find(array, function($){return $.$id == id;}, null); + }, + 'filter':function(array, expression) { + var predicates = []; + predicates.check = function(value) { + for (var j = 0; j < predicates.length; j++) { + if(!predicates[j](value)) { + return false; + } + } + return true; + }; + var getter = Scope.getter; + var search = function(obj, text){ + if (text.charAt(0) === '!') { + return !search(obj, text.substr(1)); + } + switch (typeof obj) { + case "boolean": + case "number": + case "string": + return ('' + obj).toLowerCase().indexOf(text) > -1; + case "object": + for ( var objKey in obj) { + if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { + return true; + } + } + return false; + case "array": + for ( var i = 0; i < obj.length; i++) { + if (search(obj[i], text)) { + return true; + } + } + return false; + default: + return false; + } + }; + switch (typeof expression) { + case "boolean": + case "number": + case "string": + expression = {$:expression}; + case "object": + for (var key in expression) { + if (key == '$') { + (function(){ + var text = (''+expression[key]).toLowerCase(); + if (!text) return; + predicates.push(function(value) { + return search(value, text); + }); + })(); + } else { + (function(){ + var path = key; + var text = (''+expression[key]).toLowerCase(); + if (!text) return; + predicates.push(function(value) { + return search(getter(value, path), text); + }); + })(); + } + } + break; + case "function": + predicates.push(expression); + break; + default: + return array; + } + var filtered = []; + for ( var j = 0; j < array.length; j++) { + var value = array[j]; + if (predicates.check(value)) { + filtered.push(value); + } + } + return filtered; + }, + 'add':function(array, value) { + array.push(_.isUndefined(value)? {} : value); + return array; + }, + 'count':function(array, condition) { + if (!condition) return array.length; + var fn = angular['Function']['compile'](condition); + return _.reduce(array, 0, function(count, $){return count + (fn($)?1:0);}); + }, + 'orderBy':function(array, expression, descend) { + function reverse(comp, descending) { + return toBoolean(descending) ? + function(a,b){return comp(b,a);} : comp; + } + function compare(v1, v2){ + var t1 = typeof v1; + var t2 = typeof v2; + if (t1 == t2) { + if (t1 == "string") v1 = v1.toLowerCase(); + if (t1 == "string") v2 = v2.toLowerCase(); + if (v1 === v2) return 0; + return v1 < v2 ? -1 : 1; + } else { + return t1 < t2 ? -1 : 1; + } + } + expression = _.isArray(expression) ? expression: [expression]; + expression = _.map(expression, function($){ + var descending = false; + if (typeof $ == "string" && ($.charAt(0) == '+' || $.charAt(0) == '-')) { + descending = $.charAt(0) == '-'; + $ = $.substring(1); + } + var get = $ ? angular['Function']['compile']($) : _.identity; + return reverse(function(a,b){ + return compare(get(a),get(b)); + }, descending); + }); + var comparator = function(o1, o2){ + for ( var i = 0; i < expression.length; i++) { + var comp = expression[i](o1, o2); + if (comp !== 0) return comp; + } + return 0; + }; + return _.clone(array).sort(reverse(comparator, descend)); + }, + 'orderByToggle':function(predicate, attribute) { + var STRIP = /^([+|-])?(.*)/; + var ascending = false; + var index = -1; + _.detect(predicate, function($, i){ + if ($ == attribute) { + ascending = true; + index = i; + return true; + } + if (($.charAt(0)=='+'||$.charAt(0)=='-') && $.substring(1) == attribute) { + ascending = $.charAt(0) == '+'; + index = i; + return true; + } + }); + if (index >= 0) { + predicate.splice(index, 1); + } + predicate.unshift((ascending ? "-" : "+") + attribute); + return predicate; + }, + 'orderByDirection':function(predicate, attribute, ascend, descend) { + ascend = ascend || 'ng-ascend'; + descend = descend || 'ng-descend'; + var att = predicate[0] || ''; + var direction = true; + if (att.charAt(0) == '-') { + att = att.substring(1); + direction = false; + } else if(att.charAt(0) == '+') { + att = att.substring(1); + } + return att == attribute ? (direction ? ascend : descend) : ""; + }, + 'merge':function(array, index, mergeValue) { + var value = array[index]; + if (!value) { + value = {}; + array[index] = value; + } + merge(mergeValue, value); + return array; + } +}; + +var angularString = { + 'quote':function(string) { + return '"' + string.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(string) { + var str = angular['String']['quote'](string); + var chars = []; + for ( var i = 0; i < str.length; i++) { + var ch = str.charCodeAt(i); + if (ch < 128) { + chars.push(str.charAt(i)); + } else { + var encode = "000" + ch.toString(16); + chars.push("\\u" + encode.substring(encode.length - 4)); + } + } + return chars.join(''); + }, + 'toDate':function(string){ + var match; + if (typeof string == 'string' && + (match = string.match(/^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z$/))){ + var date = new Date(0); + date.setUTCFullYear(match[1], match[2] - 1, match[3]); + date.setUTCHours(match[4], match[5], match[6], 0); + return date; + } + return string; + } +}; + +var angularDate = { + 'toString':function(date){ + function pad(n) { return n < 10 ? "0" + n : n; } + return (date.getUTCFullYear()) + '-' + + pad(date.getUTCMonth() + 1) + '-' + + pad(date.getUTCDate()) + 'T' + + pad(date.getUTCHours()) + ':' + + pad(date.getUTCMinutes()) + ':' + + pad(date.getUTCSeconds()) + 'Z'; + } + }; + +var angularFunction = { + 'compile':function(expression) { + if (_.isFunction(expression)){ + return expression; + } else if (expression){ + var scope = new Scope(); + return function($) { + scope.state = $; + return scope.eval(expression); + }; + } else { + return function($){return $;}; + } + } +}; + +function defineApi(dst, chain, underscoreNames){ + var lastChain = _.last(chain); + foreach(underscoreNames, function(name){ + lastChain[name] = _[name]; + }); + angular[dst] = angular[dst] || {}; + foreach(chain, function(parent){ + extend(angular[dst], parent); + }); +} +defineApi('Global', [angularGlobal], + ['extend', 'clone','isEqual', + 'isElement', 'isArray', 'isFunction', 'isUndefined']); +defineApi('Collection', [angularGlobal, angularCollection], + ['each', 'map', 'reduce', 'reduceRight', 'detect', + 'select', 'reject', 'all', 'any', 'include', + 'invoke', 'pluck', 'max', 'min', 'sortBy', + 'sortedIndex', 'toArray', 'size']); +defineApi('Array', [angularGlobal, angularCollection, angularArray], + ['first', 'last', 'compact', 'flatten', 'without', + 'uniq', 'intersect', 'zip', 'indexOf', 'lastIndexOf']); +defineApi('Object', [angularGlobal, angularCollection, angularObject], + ['keys', 'values']); +defineApi('String', [angularGlobal, angularString], []); +defineApi('Date', [angularGlobal, angularDate], []); +defineApi('Function', [angularGlobal, angularCollection, angularFunction], + ['bind', 'bindAll', 'delay', 'defer', 'wrap', 'compose']); +function Binder(doc, widgetFactory, location, config) { + this.doc = doc; + this.location = location; + this.anchor = {}; + this.widgetFactory = widgetFactory; + this.config = config || {}; + this.updateListeners = []; +} + +Binder.parseBindings = function(string) { + var results = []; + var lastIndex = 0; + var index; + while((index = string.indexOf('{{', lastIndex)) > -1) { + if (lastIndex < index) + results.push(string.substr(lastIndex, index - lastIndex)); + lastIndex = index; + + index = string.indexOf('}}', index); + index = index < 0 ? string.length : index + 2; + + results.push(string.substr(lastIndex, index - lastIndex)); + lastIndex = index; + } + if (lastIndex != string.length) + results.push(string.substr(lastIndex, string.length - lastIndex)); + return results.length === 0 ? [ string ] : results; +}; + +Binder.hasBinding = function(string) { + var bindings = Binder.parseBindings(string); + return bindings.length > 1 || Binder.binding(bindings[0]) !== null; +}; + +Binder.binding = function(string) { + var binding = string.replace(/\n/gm, ' ').match(/^\{\{(.*)\}\}$/); + return binding ? binding[1] : null; +}; + + +Binder.prototype = { + parseQueryString: function(query) { + var params = {}; + query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, + function (match, left, right) { + if (left) params[decodeURIComponent(left)] = decodeURIComponent(right); + }); + return params; + }, + + parseAnchor: function() { + var self = this, url = this.location.get() || ""; + + var anchorIndex = url.indexOf('#'); + if (anchorIndex < 0) return; + var anchor = url.substring(anchorIndex + 1); + + var anchorQuery = this.parseQueryString(anchor); + foreach(self.anchor, function(newValue, key) { + delete self.anchor[key]; + }); + foreach(anchorQuery, function(newValue, key) { + self.anchor[key] = newValue; + }); + }, + + onUrlChange: function() { + this.parseAnchor(); + this.updateView(); + }, + + updateAnchor: function() { + var url = this.location.get() || ""; + var anchorIndex = url.indexOf('#'); + if (anchorIndex > -1) + url = url.substring(0, anchorIndex); + url += "#"; + var sep = ''; + for (var key in this.anchor) { + var value = this.anchor[key]; + if (typeof value === 'undefined' || value === null) { + delete this.anchor[key]; + } else { + url += sep + encodeURIComponent(key); + if (value !== true) + url += "=" + encodeURIComponent(value); + sep = '&'; + } + } + this.location.set(url); + return url; + }, + + updateView: function() { + var start = new Date().getTime(); + var scope = jQuery(this.doc).scope(); + scope.set("$invalidWidgets", []); + scope.updateView(); + var end = new Date().getTime(); + this.updateAnchor(); + _.each(this.updateListeners, function(fn) {fn();}); + }, + + docFindWithSelf: function(exp){ + var doc = jQuery(this.doc); + var selection = doc.find(exp); + if (doc.is(exp)){ + selection = selection.andSelf(); + } + return selection; + }, + + executeInit: function() { + this.docFindWithSelf("[ng-init]").each(function() { + var jThis = jQuery(this); + var scope = jThis.scope(); + try { + scope.eval(jThis.attr('ng-init')); + } catch (e) { + alert("EVAL ERROR:\n" + jThis.attr('ng-init') + '\n' + toJson(e, true)); + } + }); + }, + + entity: function (scope) { + this.docFindWithSelf("[ng-entity]").attr("ng-watch", function() { + try { + var jNode = jQuery(this); + var decl = scope.entity(jNode.attr("ng-entity")); + return decl + (jNode.attr('ng-watch') || ""); + } catch (e) { + alert(e); + } + }); + }, + + compile: function() { + var jNode = jQuery(this.doc); + if (this.config.autoSubmit) { + var submits = this.docFindWithSelf(":submit").not("[ng-action]"); + submits.attr("ng-action", "$save()"); + submits.not(":disabled").not("ng-bind-attr").attr("ng-bind-attr", '{disabled:"{{$invalidWidgets}}"}'); + } + this.precompile(this.doc)(this.doc, jNode.scope(), ""); + this.docFindWithSelf("a[ng-action]").live('click', function (event) { + var jNode = jQuery(this); + var scope = jNode.scope(); + try { + scope.eval(jNode.attr('ng-action')); + jNode.removeAttr('ng-error'); + jNode.removeClass("ng-exception"); + } catch (e) { + jNode.addClass("ng-exception"); + jNode.attr('ng-error', toJson(e, true)); + } + scope.get('$updateView')(); + return false; + }); + }, + + translateBinding: function(node, parentPath, factories) { + var path = parentPath.concat(); + var offset = path.pop(); + var parts = Binder.parseBindings(node.nodeValue); + if (parts.length > 1 || Binder.binding(parts[0])) { + var parent = node.parentNode; + if (isLeafNode(parent)) { + parent.setAttribute('ng-bind-template', node.nodeValue); + factories.push({path:path, fn:function(node, scope, prefix) { + return new BindUpdater(node, node.getAttribute('ng-bind-template')); + }}); + } else { + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + var binding = Binder.binding(part); + var newNode; + if (binding) { + newNode = document.createElement("span"); + var jNewNode = jQuery(newNode); + jNewNode.attr("ng-bind", binding); + if (i === 0) { + factories.push({path:path.concat(offset + i), fn:this.ng_bind}); + } + } else if (msie && part.charAt(0) == ' ') { + newNode = document.createElement("span"); + newNode.innerHTML = ' ' + part.substring(1); + } else { + newNode = document.createTextNode(part); + } + parent.insertBefore(newNode, node); + } + } + parent.removeChild(node); + } + }, + + precompile: function(root) { + var factories = []; + this.precompileNode(root, [], factories); + return function (template, scope, prefix) { + var len = factories.length; + for (var i = 0; i < len; i++) { + var factory = factories[i]; + var node = template; + var path = factory.path; + for (var j = 0; j < path.length; j++) { + node = node.childNodes[path[j]]; + } + try { + scope.addWidget(factory.fn(node, scope, prefix)); + } catch (e) { + alert(e); + } + } + }; + }, + + precompileNode: function(node, path, factories) { + var nodeType = node.nodeType; + if (nodeType == Node.TEXT_NODE) { + this.translateBinding(node, path, factories); + return; + } else if (nodeType != Node.ELEMENT_NODE && nodeType != Node.DOCUMENT_NODE) { + return; + } + + if (!node.getAttribute) return; + var nonBindable = node.getAttribute('ng-non-bindable'); + if (nonBindable || nonBindable === "") return; + + var attributes = node.attributes; + if (attributes) { + var bindings = node.getAttribute('ng-bind-attr'); + node.removeAttribute('ng-bind-attr'); + bindings = bindings ? fromJson(bindings) : {}; + var attrLen = attributes.length; + for (var i = 0; i < attrLen; i++) { + var attr = attributes[i]; + var attrName = attr.name; + // http://www.glennjones.net/Post/809/getAttributehrefbug.htm + var attrValue = msie && attrName == 'href' ? + decodeURI(node.getAttribute(attrName, 2)) : attr.value; + if (Binder.hasBinding(attrValue)) { + bindings[attrName] = attrValue; + } + } + var json = toJson(bindings); + if (json.length > 2) { + node.setAttribute("ng-bind-attr", json); + } + } + + if (!node.getAttribute) log(node); + var repeaterExpression = node.getAttribute('ng-repeat'); + if (repeaterExpression) { + node.removeAttribute('ng-repeat'); + var precompiled = this.precompile(node); + var view = document.createComment("ng-repeat: " + repeaterExpression); + var parentNode = node.parentNode; + parentNode.insertBefore(view, node); + parentNode.removeChild(node); + function template(childScope, prefix, i) { + var clone = jQuery(node).clone(); + clone.css('display', ''); + clone.attr('ng-repeat-index', "" + i); + clone.data('scope', childScope); + precompiled(clone[0], childScope, prefix + i + ":"); + return clone; + } + factories.push({path:path, fn:function(node, scope, prefix) { + return new RepeaterUpdater(jQuery(node), repeaterExpression, template, prefix); + }}); + return; + } + + if (node.getAttribute('ng-eval')) factories.push({path:path, fn:this.ng_eval}); + if (node.getAttribute('ng-bind')) factories.push({path:path, fn:this.ng_bind}); + if (node.getAttribute('ng-bind-attr')) factories.push({path:path, fn:this.ng_bind_attr}); + if (node.getAttribute('ng-hide')) factories.push({path:path, fn:this.ng_hide}); + if (node.getAttribute('ng-show')) factories.push({path:path, fn:this.ng_show}); + if (node.getAttribute('ng-class')) factories.push({path:path, fn:this.ng_class}); + if (node.getAttribute('ng-class-odd')) factories.push({path:path, fn:this.ng_class_odd}); + if (node.getAttribute('ng-class-even')) factories.push({path:path, fn:this.ng_class_even}); + if (node.getAttribute('ng-style')) factories.push({path:path, fn:this.ng_style}); + if (node.getAttribute('ng-watch')) factories.push({path:path, fn:this.ng_watch}); + var nodeName = node.nodeName; + if ((nodeName == 'INPUT' ) || + nodeName == 'TEXTAREA' || + nodeName == 'SELECT' || + nodeName == 'BUTTON') { + var self = this; + factories.push({path:path, fn:function(node, scope, prefix) { + node.name = prefix + node.name.split(":").pop(); + return self.widgetFactory.createController(jQuery(node), scope); + }}); + } + if (nodeName == 'OPTION') { + var html = jQuery('' + + '' + + '' + + '' + + ''); +}; + +FileController.prototype = { + '_on_cancel': noop, + '_on_complete': noop, + '_on_httpStatus': function(status) { + alert("httpStatus:" + this.scopeName + " status:" + status); + }, + '_on_ioError': function() { + alert("ioError:" + this.scopeName); + }, + '_on_open': function() { + alert("open:" + this.scopeName); + }, + '_on_progress':noop, + '_on_securityError': function() { + alert("securityError:" + this.scopeName); + }, + '_on_uploadCompleteData': function(data) { + var value = fromJson(data); + value.url = this.attachmentsPath + '/' + value.id + '/' + value.text; + this.view.find("input").attr('checked', true); + var scope = this.view.scope(); + this.value = value; + this.updateModel(scope); + this.value = null; + scope.get('$binder').updateView(); + }, + '_on_select': function(name, size, type) { + this.name = name; + this.view.find("a").text(name).attr('href', name); + this.view.find("span").text(angular['filter']['bytes'](size)); + this.upload(); + }, + + updateModel: function(scope) { + var isChecked = this.view.find("input").attr('checked'); + var value = isChecked ? this.value : null; + if (this.lastValue === value) { + return false; + } else { + scope.set(this.scopeName, value); + return true; + } + }, + + updateView: function(scope) { + var modelValue = scope.get(this.scopeName); + if (modelValue && this.value !== modelValue) { + this.value = modelValue; + this.view.find("a"). + attr("href", this.value.url). + text(this.value.text); + this.view.find("span").text(angular['filter']['bytes'](this.value.size)); + } + this.view.find("input").attr('checked', !!modelValue); + }, + + upload: function() { + if (this.name) { + this.uploader.uploadFile(this.attachmentsPath); + } + } +}; + +/////////////////////// +// NullController +/////////////////////// +function NullController(view) {this.view = view;}; +NullController.prototype = { + updateModel: function() { return true; }, + updateView: noop +}; +NullController.instance = new NullController(); + + +/////////////////////// +// ButtonController +/////////////////////// +var ButtonController = NullController; + +/////////////////////// +// TextController +/////////////////////// +function TextController(view, exp) { + this.view = view; + this.exp = exp; + this.validator = view.getAttribute('ng-validate'); + this.required = typeof view.attributes['ng-required'] != "undefined"; + this.lastErrorText = null; + this.lastValue = undefined; + this.initialValue = view.value; + var widget = view.getAttribute('ng-widget'); + if (widget === 'datepicker') { + jQuery(view).datepicker(); + } +}; + +TextController.prototype = { + updateModel: function(scope) { + var value = this.view.value; + if (this.lastValue === value) { + return false; + } else { + scope.setEval(this.exp, value); + this.lastValue = value; + return true; + } + }, + + updateView: function(scope) { + var view = this.view; + var value = scope.get(this.exp); + if (typeof value === "undefined") { + value = this.initialValue; + scope.setEval(this.exp, value); + } + value = value ? value : ''; + if (this.lastValue != value) { + view.value = value; + this.lastValue = value; + } + var isValidationError = false; + view.removeAttribute('ng-error'); + if (this.required) { + isValidationError = !(value && value.length > 0); + } + var errorText = isValidationError ? "Required Value" : null; + if (!isValidationError && this.validator && value) { + errorText = scope.validate(this.validator, value); + isValidationError = !!errorText; + } + if (this.lastErrorText !== errorText) { + this.lastErrorText = isValidationError; + if (errorText !== null) { + view.setAttribute('ng-error', errorText); + scope.markInvalid(this); + } + jQuery(view).toggleClass('ng-validation-error', isValidationError); + } + } +}; + +/////////////////////// +// CheckboxController +/////////////////////// +function CheckboxController(view, exp) { + this.view = view; + this.exp = exp; + this.lastValue = undefined; + this.initialValue = view.checked ? view.value : ""; +}; + +CheckboxController.prototype = { + updateModel: function(scope) { + var input = this.view; + var value = input.checked ? input.value : ''; + if (this.lastValue === value) { + return false; + } else { + scope.setEval(this.exp, value); + this.lastValue = value; + return true; + } + }, + + updateView: function(scope) { + var input = this.view; + var value = scope.eval(this.exp); + if (typeof value === "undefined") { + value = this.initialValue; + scope.setEval(this.exp, value); + } + input.checked = input.value == (''+value); + } +}; + +/////////////////////// +// SelectController +/////////////////////// +function SelectController(view, exp) { + this.view = view; + this.exp = exp; + this.lastValue = undefined; + this.initialValue = view.value; +}; + +SelectController.prototype = { + updateModel: function(scope) { + var input = this.view; + if (input.selectedIndex < 0) { + scope.setEval(this.exp, null); + } else { + var value = this.view.value; + if (this.lastValue === value) { + return false; + } else { + scope.setEval(this.exp, value); + this.lastValue = value; + return true; + } + } + }, + + updateView: function(scope) { + var input = this.view; + var value = scope.get(this.exp); + if (typeof value === 'undefined') { + value = this.initialValue; + scope.setEval(this.exp, value); + } + if (value !== this.lastValue) { + input.value = value ? value : ""; + this.lastValue = value; + } + } +}; + +/////////////////////// +// MultiSelectController +/////////////////////// +function MultiSelectController(view, exp) { + this.view = view; + this.exp = exp; + this.lastValue = undefined; + this.initialValue = this.selected(); +}; + +MultiSelectController.prototype = { + selected: function () { + var value = []; + var options = this.view.options; + for ( var i = 0; i < options.length; i++) { + var option = options[i]; + if (option.selected) { + value.push(option.value); + } + } + return value; + }, + + updateModel: function(scope) { + var value = this.selected(); + // TODO: This is wrong! no caching going on here as we are always comparing arrays + if (this.lastValue === value) { + return false; + } else { + scope.setEval(this.exp, value); + this.lastValue = value; + return true; + } + }, + + updateView: function(scope) { + var input = this.view; + var selected = scope.get(this.exp); + if (typeof selected === "undefined") { + selected = this.initialValue; + scope.setEval(this.exp, selected); + } + if (selected !== this.lastValue) { + var options = input.options; + for ( var i = 0; i < options.length; i++) { + var option = options[i]; + option.selected = _.include(selected, option.value); + } + this.lastValue = selected; + } + } +}; + +/////////////////////// +// RadioController +/////////////////////// +function RadioController(view, exp) { + this.view = view; + this.exp = exp; + this.lastChecked = undefined; + this.lastValue = undefined; + this.inputValue = view.value; + this.initialValue = view.checked ? view.value : null; +}; + +RadioController.prototype = { + updateModel: function(scope) { + var input = this.view; + if (this.lastChecked) { + return false; + } else { + input.checked = true; + this.lastValue = scope.setEval(this.exp, this.inputValue); + this.lastChecked = true; + return true; + } + }, + + updateView: function(scope) { + var input = this.view; + var value = scope.get(this.exp); + if (this.initialValue && typeof value === "undefined") { + value = this.initialValue; + scope.setEval(this.exp, value); + } + if (this.lastValue != value) { + this.lastChecked = input.checked = this.inputValue == (''+value); + this.lastValue = value; + } + } +}; + +/////////////////////// +//ElementController +/////////////////////// +function BindUpdater(view, exp) { + this.view = view; + this.exp = Binder.parseBindings(exp); + this.hasError = false; + this.scopeSelf = {element:view}; +}; + +BindUpdater.toText = function(obj) { + var e = escapeHtml; + switch(typeof obj) { + case "string": + case "boolean": + case "number": + return e(obj); + case "function": + return BindUpdater.toText(obj()); + case "object": + if (isNode(obj)) { + return outerHTML(obj); + } else if (obj instanceof angular.filter.Meta) { + switch(typeof obj.html) { + case "string": + case "number": + return obj.html; + case "function": + return obj.html(); + case "object": + if (isNode(obj.html)) + return outerHTML(obj.html); + default: + break; + } + switch(typeof obj.text) { + case "string": + case "number": + return e(obj.text); + case "function": + return e(obj.text()); + default: + break; + } + } + if (obj === null) + return ""; + return e(toJson(obj, true)); + default: + return ""; + } +}; + +BindUpdater.prototype = { + updateModel: noop, + updateView: function(scope) { + var html = []; + var parts = this.exp; + var length = parts.length; + for(var i=0; i iteratorLength; --r) { + var unneeded = this.children.pop().element[0]; + unneeded.parentNode.removeChild(unneeded); + } + // Special case for option in select + if (child && child.element[0].nodeName === "OPTION") { + var select = jQuery(child.element[0].parentNode); + var cntl = select.data('controller'); + if (cntl) { + cntl.lastValue = undefined; + cntl.updateView(scope); + } + } + }); + } +}; + +////////////////////////////////// +// PopUp +////////////////////////////////// + +function PopUp(doc) { + this.doc = doc; +}; + +PopUp.OUT_EVENT = "mouseleave mouseout click dblclick keypress keyup"; + +PopUp.onOver = function(e) { + PopUp.onOut(); + var jNode = jQuery(this); + jNode.bind(PopUp.OUT_EVENT, PopUp.onOut); + var position = jNode.position(); + var de = document.documentElement; + var w = self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth; + var hasArea = w - position.left; + var width = 300; + var title = jNode.hasClass("ng-exception") ? "EXCEPTION:" : "Validation error..."; + var msg = jNode.attr("ng-error"); + + var x; + var arrowPos = hasArea>(width+75) ? "left" : "right"; + var tip = jQuery( + "
" + + "
" + + "
"+title+"
" + + "
"+msg+"
" + + "
"); + jQuery("body").append(tip); + if(arrowPos === 'left'){ + x = position.left + this.offsetWidth + 11; + }else{ + x = position.left - (width + 15); + tip.find('.ng-arrow-right').css({left:width+1}); + } + + tip.css({left: x+"px", top: (position.top - 3)+"px"}); + return true; +}; + +PopUp.onOut = function() { + jQuery('#ng-callout'). + unbind(PopUp.OUT_EVENT, PopUp.onOut). + remove(); + return true; +}; + +PopUp.prototype = { + bind: function () { + var self = this; + this.doc.find('.ng-validation-error,.ng-exception'). + live("mouseover", PopUp.onOver); + } +}; + +////////////////////////////////// +// Status +////////////////////////////////// + + +function Status(body) { + this.loader = body.append(Status.DOM).find("#ng-loading"); + this.requestCount = 0; +}; + +Status.DOM ='
loading....
'; + +Status.prototype = { + beginRequest: function () { + if (this.requestCount === 0) { + this.loader.show(); + } + this.requestCount++; + }, + + endRequest: function () { + this.requestCount--; + if (this.requestCount === 0) { + this.loader.hide("fold"); + } + } +}; +})(window, document); \ No newline at end of file diff --git a/css/angular-scenario.css b/css/angular-scenario.css new file mode 100644 index 00000000..ad263d21 --- /dev/null +++ b/css/angular-scenario.css @@ -0,0 +1,62 @@ +@charset "UTF-8"; +/* CSS Document */ + +#runner { + position: absolute; + top:5px; + left:10px; + right:10px; + height: 200px; +} + +#testView { + position: absolute; + bottom:10px; + top:210px; + left:10px; + right:10px; +} + +#testView iframe { + width: 100%; + height: 100%; +} + +.console { + display: block; + overflow: scroll; + height: 200px; + border: 1px solid black; +} + +.collapsed .log { + display: none; +} + +.run, .info, .error { + display: block; + padding: 0 1em; + font-family: monospace; + white-space: pre; +} + +.run { + background-color: lightgrey; + padding: 0 .2em; +} + +.run.pass { + background-color: lightgreen; +} + +.run.fail { + background-color: lightred; +} + +.name, .time, .state { + padding-right: 2em; +} + +error { + color: red; +} \ No newline at end of file diff --git a/css/angular.css b/css/angular.css new file mode 100644 index 00000000..f90c5d07 --- /dev/null +++ b/css/angular.css @@ -0,0 +1,172 @@ +@charset "UTF-8"; +/* CSS Document */ + +#ng-console { + border: thin solid black; + font-family: 'courier'; + font-size: x-small; +} + +#ng-console .ng-console-error { + color: red; +} + +#ng-console .ng-console-info { + color: blue; +} + +.ng-upload-widget object { + align:center; +} + +.ng-upload-widget a { + margin-right: .3em; +} + +.ng-upload-widget span { + color: #999999; + font-size: smaller; +} + +.ng-format-negative { + color: red; +} + +.ng-exception { + border: 2px solid #FF0000; + font-family: "Courier New", Courier, monospace; + font-size: smaller; +} + +.ng-validation-error { + border: 2px solid #FF0000; +} + +.ng-hidden { + display:none; +} + +/***************** + * DatePicker + *****************/ + +div.ui-widget { + font-size: 11px; + } + +/***************** + * OrderBy + *****************/ +.ng-ascend, +.ng-descend { + padding-right: 20px; + background-repeat: no-repeat; + background-position: right; +} +.ng-ascend { background-image: url(angular_images/arrow_ascend.png); } +.ng-descend { background-image: url(angular_images/arrow_descend.png); } + +/***************** + * TIP + *****************/ +#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(angular_images/arrow_left.gif); + 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(angular_images/arrow_right.gif); + 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-spacer { + height: 1.2em; +} + +#ng-loading { + position: fixed; + bottom: 0; + height: 1.2em; + width: 100%; + text-align: center; +} + +/***************** + * Login + *****************/ + +#ng-login { + z-index: 2000; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding-top: 100px; +} + +#ng-login .ng-login-container { + width: 500px; + height: 380px; + margin: auto; + border-top: 5px solid #FFF; + border-left: 5px solid #DDD; + border-right: 5px solid #777; + border-bottom: 5px solid #555; + padding: 0 3px 3px 0; +} + +#ng-login .ng-login-container iframe { + width: 100%; + height: 100%; + border: 2px solid black; +} diff --git a/css/angular_images/arrow_ascend.png b/css/angular_images/arrow_ascend.png new file mode 100644 index 00000000..dd27b92b Binary files /dev/null and b/css/angular_images/arrow_ascend.png differ diff --git a/css/angular_images/arrow_descend.png b/css/angular_images/arrow_descend.png new file mode 100644 index 00000000..ec1cb5df Binary files /dev/null and b/css/angular_images/arrow_descend.png differ diff --git a/css/angular_images/arrow_left.gif b/css/angular_images/arrow_left.gif new file mode 100644 index 00000000..4c9e5c66 Binary files /dev/null and b/css/angular_images/arrow_left.gif differ diff --git a/css/angular_images/arrow_right.gif b/css/angular_images/arrow_right.gif new file mode 100644 index 00000000..3252c359 Binary files /dev/null and b/css/angular_images/arrow_right.gif differ diff --git a/css/angular_images/loader-bar.gif b/css/angular_images/loader-bar.gif new file mode 100644 index 00000000..47adbf03 Binary files /dev/null and b/css/angular_images/loader-bar.gif differ diff --git a/example/calculator-auto_init.html b/example/calculator-auto_init.html new file mode 100644 index 00000000..fa965042 --- /dev/null +++ b/example/calculator-auto_init.html @@ -0,0 +1,12 @@ + + + + + + + Quantity: + * + Cost: + = {{a * b | currency}} + + diff --git a/example/calculator-manual_init.html b/example/calculator-manual_init.html new file mode 100644 index 00000000..43d013fc --- /dev/null +++ b/example/calculator-manual_init.html @@ -0,0 +1,21 @@ + + + + + + + + + + Quantity: + * + Cost: + = {{a * b | currency}} + + diff --git a/example/calculator-minified_init.html b/example/calculator-minified_init.html new file mode 100644 index 00000000..4f113f87 --- /dev/null +++ b/example/calculator-minified_init.html @@ -0,0 +1,21 @@ + + + + + + + + + + Quantity: + * + Cost: + = {{a * b | currency}} + + diff --git a/example/index.html b/example/index.html new file mode 100644 index 00000000..aaaf8c80 --- /dev/null +++ b/example/index.html @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/example/tweeter/style.css b/example/tweeter/style.css new file mode 100644 index 00000000..e8468b6b --- /dev/null +++ b/example/tweeter/style.css @@ -0,0 +1,98 @@ +.loading {display: none;} +.fetching .loading {display: block;} + +a { + color: blue; +} + +h1 { + background-color: black; + margin: 0; + padding: .25em; + color: white; + border-bottom: 5px solid gray; +} + +.box { + border: 2px solid gray; +} + +.tweeter { + margin-right: 360px; +} + +ul { + list-style: none; + margin: 0; + padding: 0; +} + +li { + margin: .25em; + padding: 2px; +} + +li img { + float: left; + margin: 2px; + margin-right: .5em; + max-height: 48px; + min-height: 48px; +} + +li.even { + background-color: lightgray; +} + + +.addressbook { + float: right; + width: 350px; +} + +.addressbook li { + font-size: .9em; +} + +.clrleft { + clear: left; +} + +.notes { + font-size: .8em; + color: gray; +} + +.username, .nickname { + font-weight: bold; +} + +.editor { + padding: 4px; +} + +label { + color: gray; + display: inline-block; + width: 75px; + text-align: right; + padding: 2px; + margin-top: 10px; +} + +.editor input[type=text], +.editor textarea { + width: 230px; + vertical-align: text-top; +} + +.editor TEXTAREA { + height: 50px; +} + +.debug{ + font-size: .7em; + white-space: pre; + padding: 0; + margin: 0; +} \ No newline at end of file diff --git a/example/tweeter/tweeter_addressbook.html b/example/tweeter/tweeter_addressbook.html new file mode 100644 index 00000000..64a3f95e --- /dev/null +++ b/example/tweeter/tweeter_addressbook.html @@ -0,0 +1,80 @@ + + + + + + + + + + + +
+

Address Book

+ [ Filter: ] + +
+
+
+ + + + + + + + + + +
+
+
+
+mute={{mute|json}} + +userFilter={{userFilter|json}} + +tweetFilter={{tweetFilter|json}} + +$anchor={{$anchor}} + +users={{users}} + +tweets={{tweets}} +
+
+
+

Tweets: {{$anchor.user}}

+ [ Filter: + | << All + ] +
Loading...
+ +
+ + diff --git a/example/tweeter/tweeterclient.js b/example/tweeter/tweeterclient.js new file mode 100644 index 00000000..8c68fac0 --- /dev/null +++ b/example/tweeter/tweeterclient.js @@ -0,0 +1,38 @@ +function noop(){} +$(document).ready(function(){ + var scope = window.scope = angular.compile(document, { + location:angular.startUrlWatcher() + }); + scope.getJSON = function(url, callback) { + var list = []; + var self = this; + self.set('status', 'fetching'); + $.getJSON(url, function(response, code){ + _(response).forEach(function(v,k){ + list[k] = v; + }); + (callback||noop)(response); + self.set('status', ''); + self.updateView(); + }); + return list; + }; + + function fetchTweets(username){ + return scope.getJSON( + username ? + "http://twitter.com/statuses/user_timeline/"+username+".json" : + "http://twitter.com/statuses/home_timeline.json"); + } + + scope.set('fetchTweets', fetchTweets); + scope.set('users', [ + {screen_name:'mhevery', name:'Mi\u0161ko Hevery', + notes:'Author of http://www.getangular.com.', + profile_image_url:'http://a3.twimg.com/profile_images/54360179/Me_-_Small_Banner_normal.jpg'}, + {screen_name:'abrons', name:'Adam Abrons', + 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.init(); +}); diff --git a/jsTestDriver.conf b/jsTestDriver.conf index 77a5f0bf..6c2cf0bb 100644 --- a/jsTestDriver.conf +++ b/jsTestDriver.conf @@ -1,16 +1,20 @@ server: http://localhost:9876 load: - - lib/swfobject/swfobject.js + - 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-1.4.0.js - lib/jquery/jquery-ui-1.7.1.custom.min.js - lib/underscore/underscore.js - - src/Loader.js + - src/Angular.js - src/*.js - src/test/_namespace.js - src/test/*.js - test/testabilityPatch.js - test/test/*.js - test/*.js - \ No newline at end of file + +exclude: + - src/angular.prefix + - src/angular.suffix diff --git a/lib/jasmine-jstd-adapter/JasmineAdapter.js b/lib/jasmine-jstd-adapter/JasmineAdapter.js new file mode 100644 index 00000000..83a1deed --- /dev/null +++ b/lib/jasmine-jstd-adapter/JasmineAdapter.js @@ -0,0 +1,96 @@ +/** + * @fileoverview Jasmine JsTestDriver Adapter. + * @author ibolmo@gmail.com (Olmo Maldonado) + */ + +(function() { + +// Suite/TestCase before and after function stacks. +var before = []; +var after = []; + +jasmine.Env.prototype.describe = (function(describe){ + + // TODO(ibolmo): Support nested describes. + return function(description, specDefinitions){ + this.currentTestCase = TestCase(description); + return describe.call(this, description, specDefinitions); + }; + +})(jasmine.Env.prototype.describe); + + +jasmine.Env.prototype.it = (function(it){ + + return function(desc, func){ + var spec = it.call(this, desc, func); + this.currentTestCase.prototype['test that it ' + desc] = func; + return spec; + }; + +})(jasmine.Env.prototype.it); + + +jasmine.Env.prototype.beforeEach = (function(beforeEach){ + + // TODO(ibolmo): Support beforeEach TestCase. + return function(beforeEachFunction) { + beforeEach.call(this, beforeEachFunction); + if (this.currentTestCase) { + this.currentTestCase.prototype.setUp = beforeEachFunction; + } else { + before.push(beforeEachFunction); + } + }; + +})(jasmine.Env.prototype.beforeEach); + + +jasmine.Env.prototype.afterEach = (function(afterEach){ + + // TODO(ibolmo): Support afterEach TestCase. + return function(afterEachFunction) { + afterEach.call(this, afterEachFunction); + if (this.currentTestCase) { + this.currentTestCase.prototype.tearDown = afterEachFunction; + } else { + after.push(afterEachFunction); + } + }; + +})(jasmine.Env.prototype.afterEach); + + +jasmine.NestedResults.prototype.addResult = (function(addResult){ + + return function(result) { + addResult.call(this, result); + if (result.type != 'MessageResult' && !result.passed()) fail(result.message); + }; + +})(jasmine.NestedResults.prototype.addResult); + + +jstestdriver.plugins.TestRunnerPlugin.prototype.runTestConfiguration = (function(runTestConfiguration){ + + return function(testRunConfiguration, onTestDone, onTestRunConfigurationComplete){ + for (var i = 0, l = before.length; i < l; i++) before[i](); + onTestRunConfigurationComplete = (function(configurationComplete){ + + return function() { + for (var i = 0, l = after.length; i < l; i++) after[i](); + configurationComplete(); + }; + + })(onTestRunConfigurationComplete); + runTestConfiguration.call(this, testRunConfiguration, onTestDone, onTestRunConfigurationComplete); + }; + +})(jstestdriver.plugins.TestRunnerPlugin.prototype.runTestConfiguration); + + +// Reset environment with overriden methods. +jasmine.currentEnv_ = null; +jasmine.getEnv(); + +})(); diff --git a/lib/jasmine/jasmine-0.10.0.js b/lib/jasmine/jasmine-0.10.0.js new file mode 100644 index 00000000..bb7547e8 --- /dev/null +++ b/lib/jasmine/jasmine-0.10.0.js @@ -0,0 +1,2261 @@ +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; + +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).wasCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following mehtod: wasCalled, callCount, mostRecentCall, and argsForCall (see docs) + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).wasCalled(); + * expect(foo.not).wasCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +jasmine.log = function(message) { + jasmine.getEnv().currentSpec.log(message); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @returns a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; + +/** + * Waits for a timeout before moving to the next runs()-defined block. + * @param {Number} timeout + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next runs()-defined block. + * + * @param {Number} timeout + * @param {Function} latchFunction + * @param {String} message + */ +var waitsFor = function(timeout, latchFunction, message) { + jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message); +}; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + try { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + } catch(e) { + } + try { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + } catch(e) { + } + try { + return new ActiveXObject("Msxml2.XMLHTTP"); + } catch(e) { + } + try { + return new ActiveXObject("Microsoft.XMLHTTP"); + } catch(e) { + } + throw new Error("This browser does not support XMLHttpRequest."); +} : XMLHttpRequest; + +/** + * Adds suite files to an HTML document so that they are executed, thus adding them to the current + * Jasmine environment. + * + * @param {String} url path to the file to include + * @param {Boolean} opt_global + */ +jasmine.include = function(url, opt_global) { + if (opt_global) { + document.write(''); - }; - - if (scriptConfig.autoLoadDependencies) { - addScript("/javascripts/webtoolkit.base64.js"); - addScript("/javascripts/swfobject.js"); - addScript("/javascripts/jQuery/jquery-1.3.2.js"); - addScript("/javascripts/jQuery/jquery-ui-1.7.1.custom.min.js"); - addScript("/javascripts/underscore/underscore.js"); - addScript("/javascripts/nglr/Loader.js"); - addScript("/javascripts/nglr/API.js"); - addScript("/javascripts/nglr/Binder.js"); - addScript("/javascripts/nglr/ControlBar.js"); - addScript("/javascripts/nglr/DataStore.js"); - addScript("/javascripts/nglr/Filters.js"); - addScript("/javascripts/nglr/JSON.js"); - addScript("/javascripts/nglr/Model.js"); - addScript("/javascripts/nglr/Parser.js"); - addScript("/javascripts/nglr/Scope.js"); - addScript("/javascripts/nglr/Server.js"); - addScript("/javascripts/nglr/Users.js"); - addScript("/javascripts/nglr/Validators.js"); - addScript("/javascripts/nglr/Widgets.js"); - } else { - addScript("/ajax/libs/swfobject/2.2/swfobject.js", "http://ajax.googleapis.com"); - addScript("/ajax/libs/jquery/1.3.2/jquery.min.js", "http://ajax.googleapis.com"); - addScript("/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js", "http://ajax.googleapis.com"); - } - - window.onload = function() { - window.angular.init = function(root, config){ - var cnfgMerged = _.clone(scriptConfig||{}); - _.extend(cnfgMerged, config); - new nglr.Loader(root, jQuery("head"), cnfgMerged).load(); - }; - - var doc = window.document; - if (scriptConfig.bindRootId) { - doc = null; - var ids = scriptConfig.bindRootId.split('|'); - for ( var i = 0; i < ids.length && !doc; i++) { - var idCond = ids[i].split('?'); - var id = idCond[0]; - if (idCond.length > 1) { - if (!window.document.getElementById(idCond[1])) { - continue; - } - } - doc = window.document.getElementById(id); - } - } - if (scriptConfig.autoBind && doc) { - window.angular.init(doc); - } - if (typeof previousOnLoad === 'function') { - try { - previousOnLoad.apply(this, arguments); - } catch (e) {} - } - }; -})(window.onload); - - diff --git a/src/angular.prefix b/src/angular.prefix new file mode 100644 index 00000000..26a8429f --- /dev/null +++ b/src/angular.prefix @@ -0,0 +1,24 @@ +/** + * 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. + */ +(function(window, document){ diff --git a/src/angular.suffix b/src/angular.suffix new file mode 100644 index 00000000..4b3cc37b --- /dev/null +++ b/src/angular.suffix @@ -0,0 +1 @@ +})(window, document); \ No newline at end of file diff --git a/src/test/Runner.js b/src/test/Runner.js index 478ef73e..c6684951 100644 --- a/src/test/Runner.js +++ b/src/test/Runner.js @@ -1,9 +1,11 @@ -nglr.test.ScenarioRunner = function(scenarios, body) { +if (typeof test == 'undefined') test = {}; + +test.ScenarioRunner = function(scenarios, body) { this.scenarios = scenarios; this.body = body; }; -nglr.test.ScenarioRunner.prototype = { +test.ScenarioRunner.prototype = { run:function(){ this.setUpUI(); this.runScenarios(); @@ -23,22 +25,22 @@ nglr.test.ScenarioRunner.prototype = { }); }, runScenarios:function(){ - var runner = new nglr.test.Runner(this.console, this.testFrame); + var runner = new test.Runner(this.console, this.testFrame); _.stepper(this.scenarios, function(next, scenario, name){ - new nglr.test.Scenario(name, scenario).run(runner, next); + new test.Scenario(name, scenario).run(runner, next); }, function(){ } ); } }; -nglr.test.Runner = function(console, frame){ +test.Runner = function(console, frame){ this.console = console; this.current = null; this.tests = []; this.frame = frame; }; -nglr.test.Runner.prototype = { +test.Runner.prototype = { start:function(name){ var current = this.current = { name:name, @@ -46,10 +48,10 @@ nglr.test.Runner.prototype = { scenario:jQuery('
') }; current.run = current.scenario.append( - '
' + - '.' + - '.' + - '.' + + '
' + + '.' + + '.' + + '.' + '').find(".run"); current.log = current.scenario.append('
').find(".log"); current.run.find(".name").text(name); @@ -73,22 +75,22 @@ nglr.test.Runner.prototype = { var buf = []; for ( var i = 1; i < arguments.length; i++) { var arg = arguments[i]; - buf.push(typeof arg == "string" ?arg:nglr.toJson(arg)); + buf.push(typeof arg == "string" ?arg:toJson(arg)); } var log = jQuery('
'); log.text(buf.join(" ")); this.current.log.append(log); this.console.scrollTop(this.console[0].scrollHeight); - if (level == "error") + if (level == "error") this.current.error = buf.join(" "); } }; -nglr.test.Scenario = function(name, scenario){ +test.Scenario = function(name, scenario){ this.name = name; this.scenario = scenario; }; -nglr.test.Scenario.prototype = { +test.Scenario.prototype = { run:function(runner, callback) { var self = this; _.stepper(this.scenario, function(next, steps, name){ @@ -108,22 +110,22 @@ nglr.test.Scenario.prototype = { }, verb:function(step){ var fn = null; - if (!step) fn = function (){ throw "Step is null!"; } + if (!step) fn = function (){ throw "Step is null!"; }; else if (step.Given) fn = angular.test.GIVEN[step.Given]; else if (step.When) fn = angular.test.WHEN[step.When]; else if (step.Then) fn = angular.test.THEN[step.Then]; return fn || function (){ - throw "ERROR: Need Given/When/Then got: " + nglr.toJson(step); - }; + throw "ERROR: Need Given/When/Then got: " + toJson(step); + }; }, context: function(runner) { var frame = runner.frame; var window = frame[0].contentWindow; var document; - if (window.jQuery) + if (window.jQuery) document = window.jQuery(window.document); var context = { - frame:frame, + frame:frame, window:window, log:_.bind(runner.log, runner, "info"), document:document, @@ -147,14 +149,14 @@ nglr.test.Scenario.prototype = { callback(); return; } - runner.log("info", nglr.toJson(step)); + runner.log("info", toJson(step)); var fn = this.verb(step); var context = this.context(runner); _.extend(context, step); try { (fn.call(context)||function(c){c();})(callback); } catch (e) { - runner.log("error", "ERROR: " + nglr.toJson(e)); + runner.log("error", "ERROR: " + toJson(e)); } } }; diff --git a/src/test/Steps.js b/src/test/Steps.js index af4b84d6..cc9ff549 100644 --- a/src/test/Steps.js +++ b/src/test/Steps.js @@ -14,7 +14,7 @@ angular.test.GIVEN = { }; }, dataset:function(){ - this.frame.name="$DATASET:" + nglr.toJson({dataset:this.dataset}); + this.frame.name="$DATASET:" + toJson({dataset:this.dataset}); } }; angular.test.WHEN = { diff --git a/src/test/_namespace.js b/src/test/_namespace.js index 78f430f1..e29ae72a 100644 --- a/src/test/_namespace.js +++ b/src/test/_namespace.js @@ -1,5 +1,5 @@ -if (!angular) angular = {}; -if (!angular.test) angular.test = {}; -if (!angular.test.GIVEN) angular.test.GIVEN = {}; -if (!angular.test.WHEN) angular.test.WHEN = {}; -if (!angular.test.THEN) angular.test.THEN = {}; +if (!angular) var angular = window['angular'] = {}; +if (!angular['test']) var angularTest = angular['test'] = {}; +if (!angular['test']['GIVEN']) angularTest['GIVEN'] = {}; +if (!angular['test']['WHEN']) angularTest['WHEN'] = {}; +if (!angular['test']['THEN']) angularTest['THEN'] = {}; diff --git a/test.sh b/test.sh new file mode 100755 index 00000000..c0d1e7ac --- /dev/null +++ b/test.sh @@ -0,0 +1,2 @@ +java -jar lib/jstestdriver/JsTestDriver.jar --tests all | grep -v lib/jasmine + diff --git a/test/AngularTest.js b/test/AngularTest.js new file mode 100644 index 00000000..a9146adf --- /dev/null +++ b/test/AngularTest.js @@ -0,0 +1,45 @@ +AngularTest = TestCase('AngularTest'); + + +UrlWatcherTest = TestCase('UrlWatcherTest'); + +UrlWatcherTest.prototype.testUrlWatcher = function () { + expectAsserts(2); + var location = {href:"http://server", hash:""}; + var watcher = new UrlWatcher(location); + watcher.delay = 1; + watcher.listener = function(url){ + assertEquals('http://getangular.test', url); + }; + watcher.setTimeout = function(fn, delay){ + assertEquals(1, delay); + location.href = "http://getangular.test"; + watcher.setTimeout = function(fn, delay) { + }; + fn(); + }; + watcher.watch(); +}; + +UrlWatcherTest.prototype.testItShouldFireOnUpdateEventWhenSpecialURLSet = function(){ + expectAsserts(2); + var location = {href:"http://server", hash:"#$iframe_notify=1234"}; + var watcher = new UrlWatcher(location); + angular.callbacks._iframe_notify_1234 = function () { + assertEquals("undefined", typeof angularCallbacks._iframe_notify_1234); + assertEquals("http://server2#", location.href); + }; + watcher.delay = 1; + watcher.expectedUrl = "http://server2"; + watcher.setTimeout = function(fn, delay){ + watcher.setTimeout = function(fn, delay) {}; + fn(); + }; + watcher.watch(); +}; + +FunctionTest = TestCase("FunctionTest"); + +FunctionTest.prototype.testEscapeHtml = function () { + assertEquals("<div>&amp;</div>", escapeHtml('
&
')); +}; \ No newline at end of file diff --git a/test/BinderTest.js b/test/BinderTest.js index d033996d..6ef46fae 100644 --- a/test/BinderTest.js +++ b/test/BinderTest.js @@ -3,96 +3,94 @@ BinderTest = TestCase('BinderTest'); function compile(content, initialScope, config) { var h = html(content); config = config || {autoSubmit:true}; - var scope = new nglr.Scope(initialScope, "ROOT"); + var scope = new Scope(initialScope, "ROOT"); h.data('scope', scope); - var binder = new nglr.Binder(h[0], new nglr.WidgetFactory(), new MockUrlWatcher(), config); - var datastore = new nglr.DataStore(); - scope.set("$datastore", datastore); - scope.set("$binder", binder); + var datastore = new DataStore(); + var binder = new Binder(h[0], new WidgetFactory(), datastore, new MockLocation(), config); + scope.set("$updateView", _(binder.updateView).bind(binder)); scope.set("$anchor", binder.anchor); binder.entity(scope); binder.compile(); - return {node:h, binder:binder, scope:scope}; + return {node:h, binder:binder, scope:scope, datastore:datastore}; } function compileToHtml(content) { return compile(content).node.sortedHtml(); } - BinderTest.prototype.testParseTextWithNoBindings = function(){ - var parts = nglr.Binder.parseBindings("a"); + var parts = Binder.parseBindings("a"); assertEquals(parts.length, 1); assertEquals(parts[0], "a"); - assertTrue(!nglr.Binder.binding(parts[0])); + assertTrue(!Binder.binding(parts[0])); }; BinderTest.prototype.testParseEmptyText = function(){ - var parts = nglr.Binder.parseBindings(""); + var parts = Binder.parseBindings(""); assertEquals(parts.length, 1); assertEquals(parts[0], ""); - assertTrue(!nglr.Binder.binding(parts[0])); + assertTrue(!Binder.binding(parts[0])); }; BinderTest.prototype.testParseInnerBinding = function(){ - var parts = nglr.Binder.parseBindings("a{{b}}c"); + var parts = Binder.parseBindings("a{{b}}c"); assertEquals(parts.length, 3); assertEquals(parts[0], "a"); - assertTrue(!nglr.Binder.binding(parts[0])); + assertTrue(!Binder.binding(parts[0])); assertEquals(parts[1], "{{b}}"); - assertEquals(nglr.Binder.binding(parts[1]), "b"); + assertEquals(Binder.binding(parts[1]), "b"); assertEquals(parts[2], "c"); - assertTrue(!nglr.Binder.binding(parts[2])); + assertTrue(!Binder.binding(parts[2])); }; BinderTest.prototype.testParseEndingBinding = function(){ - var parts = nglr.Binder.parseBindings("a{{b}}"); + var parts = Binder.parseBindings("a{{b}}"); assertEquals(parts.length, 2); assertEquals(parts[0], "a"); - assertTrue(!nglr.Binder.binding(parts[0])); + assertTrue(!Binder.binding(parts[0])); assertEquals(parts[1], "{{b}}"); - assertEquals(nglr.Binder.binding(parts[1]), "b"); + assertEquals(Binder.binding(parts[1]), "b"); }; BinderTest.prototype.testParseBeggingBinding = function(){ - var parts = nglr.Binder.parseBindings("{{b}}c"); + var parts = Binder.parseBindings("{{b}}c"); assertEquals(parts.length, 2); assertEquals(parts[0], "{{b}}"); - assertEquals(nglr.Binder.binding(parts[0]), "b"); + assertEquals(Binder.binding(parts[0]), "b"); assertEquals(parts[1], "c"); - assertTrue(!nglr.Binder.binding(parts[1])); + assertTrue(!Binder.binding(parts[1])); }; BinderTest.prototype.testParseLoanBinding = function(){ - var parts = nglr.Binder.parseBindings("{{b}}"); + var parts = Binder.parseBindings("{{b}}"); assertEquals(parts.length, 1); assertEquals(parts[0], "{{b}}"); - assertEquals(nglr.Binder.binding(parts[0]), "b"); + assertEquals(Binder.binding(parts[0]), "b"); }; BinderTest.prototype.testParseTwoBindings = function(){ - var parts = nglr.Binder.parseBindings("{{b}}{{c}}"); + var parts = Binder.parseBindings("{{b}}{{c}}"); assertEquals(parts.length, 2); assertEquals(parts[0], "{{b}}"); - assertEquals(nglr.Binder.binding(parts[0]), "b"); + assertEquals(Binder.binding(parts[0]), "b"); assertEquals(parts[1], "{{c}}"); - assertEquals(nglr.Binder.binding(parts[1]), "c"); + assertEquals(Binder.binding(parts[1]), "c"); }; BinderTest.prototype.testParseTwoBindingsWithTextInMiddle = function(){ - var parts = nglr.Binder.parseBindings("{{b}}x{{c}}"); + var parts = Binder.parseBindings("{{b}}x{{c}}"); assertEquals(parts.length, 3); assertEquals(parts[0], "{{b}}"); - assertEquals(nglr.Binder.binding(parts[0]), "b"); + assertEquals(Binder.binding(parts[0]), "b"); assertEquals(parts[1], "x"); - assertTrue(!nglr.Binder.binding(parts[1])); + assertTrue(!Binder.binding(parts[1])); assertEquals(parts[2], "{{c}}"); - assertEquals(nglr.Binder.binding(parts[2]), "c"); + assertEquals(Binder.binding(parts[2]), "c"); }; BinderTest.prototype.testParseMultiline = function(){ - var parts = nglr.Binder.parseBindings('"X\nY{{A\nB}}C\nD"'); - assertTrue(!!nglr.Binder.binding('{{A\nB}}')); + var parts = Binder.parseBindings('"X\nY{{A\nB}}C\nD"'); + assertTrue(!!Binder.binding('{{A\nB}}')); assertEquals(parts.length, 3); assertEquals(parts[0], '"X\nY'); assertEquals(parts[1], '{{A\nB}}'); @@ -100,9 +98,9 @@ BinderTest.prototype.testParseMultiline = function(){ }; BinderTest.prototype.testHasBinding = function(){ - assertTrue(nglr.Binder.hasBinding("{{a}}")); - assertTrue(!nglr.Binder.hasBinding("a")); - assertTrue(nglr.Binder.hasBinding("{{b}}x{{c}}")); + assertTrue(Binder.hasBinding("{{a}}")); + assertTrue(!Binder.hasBinding("a")); + assertTrue(Binder.hasBinding("{{b}}x{{c}}")); }; @@ -118,34 +116,23 @@ BinderTest.prototype.testChangingTextfieldUpdatesModel = function(){ }; BinderTest.prototype.testChangingTextareaUpdatesModel = function(){ - var form = html(''); - var scope = new nglr.Scope({model:{}}); - form.data('scope', scope); - var binder = new nglr.Binder(form.get(0), new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - binder.updateView(); - assertEquals(scope.get('model').note, 'abc'); + var c = compile(''); + c.binder.updateView(); + assertEquals(c.scope.get('model').note, 'abc'); }; BinderTest.prototype.testChangingRadioUpdatesModel = function(){ - var form = html('' + + var c = compile('' + ''); - var scope = new nglr.Scope({model:{}}); - form.data('scope', scope); - var binder = new nglr.Binder(form.get(0), new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - binder.updateView(); - assertEquals(scope.get('model').price, 'A'); + c.binder.updateView(); + assertEquals(c.scope.get('model').price, 'A'); }; BinderTest.prototype.testChangingCheckboxUpdatesModel = function(){ - var form = html(''); - var scope = new nglr.Scope({model:{}}); - form.data('scope', scope); - var binder = new nglr.Binder(form.get(0), new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - binder.updateView(); - assertEquals('A', scope.get('model').price); + var form = compile(''); + form.scope.set('model', {}); + form.binder.updateView(); + assertEquals('A', form.scope.get('model').price); }; BinderTest.prototype.testBindUpdate = function() { @@ -155,66 +142,55 @@ BinderTest.prototype.testBindUpdate = function() { }; BinderTest.prototype.testChangingSelectNonSelectedUpdatesModel = function(){ - var form = html(''); - var scope = new nglr.Scope({model:{}}); - form.data('scope', scope); - var binder = new nglr.Binder(form.get(0), new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - binder.updateView(); - assertEquals('A', scope.get('model').price); + var form = compile(''); + form.scope.set('model', {}); + form.binder.updateView(); + assertEquals('A', form.scope.get('model').price); }; BinderTest.prototype.testChangingMultiselectUpdatesModel = function(){ - var form = html('' + '' + '' + '' + ''); - var scope = new nglr.Scope({Invoice:{}}); - form.data('scope', scope); - var binder = new nglr.Binder(form.get(0), new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - binder.updateView(); - assertJsonEquals(["A", "B"], scope.get('Invoice').options); + form.scope.set("Invoice", {}); + form.binder.updateView(); + assertJsonEquals(["A", "B"], form.scope.get('Invoice').options); }; BinderTest.prototype.testChangingSelectSelectedUpdatesModel = function(){ - var form = html(''); - var scope = new nglr.Scope({model:{}}); - form.data('scope', scope); - var binder = new nglr.Binder(form.get(0), new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - binder.updateView(); - assertEquals(scope.get('model').price, 'b'); + var form = compile(''); + form.scope.set('model', {}); + form.binder.updateView(); + assertEquals(form.scope.get('model').price, 'b'); }; BinderTest.prototype.testExecuteInitialization = function() { var form = html('
'); - var scope = new nglr.Scope(); + var scope = new Scope(); form.data('scope', scope); - var binder = new nglr.Binder(form.get(0)); + var binder = new Binder(form.get(0)); binder.executeInit(); assertEquals(scope.get('a'), 123); }; BinderTest.prototype.testExecuteInitializationStatements = function() { var form = html('
'); - var scope = new nglr.Scope(); + var scope = new Scope(); form.data('scope', scope); - var binder = new nglr.Binder(form.get(0)); + var binder = new Binder(form.get(0)); binder.executeInit(); assertEquals(scope.get('a'), 123); assertEquals(scope.get('b'), 345); }; BinderTest.prototype.testApplyTextBindings = function(){ - var form = html('
x
'); - var scope = new nglr.Scope({model:{a:123}}); - form.data('scope', scope); - var binder = new nglr.Binder(form.get(0), null, new MockUrlWatcher()); - binder.compile(); - binder.updateView(); - assertEquals('123', form.text()); + var form = compile('
x
'); + form.scope.set('model', {a:123}); + form.binder.compile(); + form.binder.updateView(); + assertEquals('123', form.node.text()); }; BinderTest.prototype.testReplaceBindingInTextWithSpan = function() { @@ -224,15 +200,15 @@ BinderTest.prototype.testReplaceBindingInTextWithSpan = function() { BinderTest.prototype.testReplaceBindingCreatesCorrectNumberOfWidgets = function() { var h = html("space{{a}}{{a}}a{{a}}{{a}}"); - h.data('scope', new nglr.Scope()); - var binder = new nglr.Binder(h.get(0), new nglr.WidgetFactory()); + h.data('scope', new Scope()); + var binder = new Binder(h.get(0), new WidgetFactory()); binder.compile(); assertEquals(4, h.scope().widgets.length); }; BinderTest.prototype.testBindingSpaceConfusesIE = function() { - if (!nglr.msie) return; + if (!msie) return; var span = document.createElement("span"); span.innerHTML = ' '; var nbsp = span.firstChild.nodeValue; @@ -246,30 +222,30 @@ BinderTest.prototype.testBindingSpaceConfusesIE = function() { BinderTest.prototype.testBindingOfAttributes = function() { var form = html(""); - form.data('scope', new nglr.Scope()); - var binder = new nglr.Binder(form.get(0)); + form.data('scope', new Scope()); + var binder = new Binder(form.get(0)); binder.compile(); var attrbinding = form.find("a").attr("ng-bind-attr"); - var bindings = nglr.fromJson(attrbinding); + var bindings = fromJson(attrbinding); assertEquals("http://s/a{{b}}c", decodeURI(bindings.href)); assertTrue(!bindings.foo); }; BinderTest.prototype.testMarkMultipleAttributes = function() { var form = html(""); - form.data('scope', new nglr.Scope()); - var binder = new nglr.Binder(form.get(0)); + form.data('scope', new Scope()); + var binder = new Binder(form.get(0)); binder.compile(); var attrbinding = form.find("a").attr("ng-bind-attr"); - var bindings = nglr.fromJson(attrbinding); + var bindings = fromJson(attrbinding); assertEquals(decodeURI(bindings.href), "http://s/a{{b}}c"); assertEquals(bindings.foo, "{{d}}"); }; BinderTest.prototype.testAttributesNoneBound = function() { var form = html(""); - form.data('scope', new nglr.Scope()); - var binder = new nglr.Binder(form.get(0)); + form.data('scope', new Scope()); + var binder = new Binder(form.get(0)); binder.compile(); var a = form.find("a"); assertEquals(a.get(0).nodeName, "A"); @@ -278,18 +254,17 @@ BinderTest.prototype.testAttributesNoneBound = function() { BinderTest.prototype.testExistingAttrbindingIsAppended = function() { var form = html(""); - form.data('scope', new nglr.Scope()); - var binder = new nglr.Binder(form.get(0)); + form.data('scope', new Scope()); + var binder = new Binder(form.get(0)); binder.compile(); var a = form.find("a"); assertEquals('{"b":"{{def}}","href":"http://s/{{abc}}"}', a.attr('ng-bind-attr')); }; BinderTest.prototype.testAttributesAreEvaluated = function(){ - var form = html(''); - form.data('scope', new nglr.Scope({a:1, b:2})); - var binder = new nglr.Binder(form.get(0), null, new MockUrlWatcher()); - binder.compile(); + var c = compile(''); + var binder = c.binder, form = c.node; + c.scope.eval('a=1;b=2'); binder.updateView(); var a = form.find("a"); assertEquals(a.attr('a'), 'a'); @@ -297,16 +272,16 @@ BinderTest.prototype.testAttributesAreEvaluated = function(){ }; BinderTest.prototype.testInputsAreUpdated = function(){ - var form = - html('' + - '' + + '' + + '' + + '' + + '' + + ''); + var binder = a.binder, form = a.node; + a.scope.set('A', {text:"t1", textarea:"t2", radio:"r", checkbox:"c", select:"S"}); binder.compile(); binder.updateView(); assertEquals(form.find("input[type=text]").attr('value'), 't1'); @@ -349,21 +324,27 @@ BinderTest.prototype.testButtonElementActionExecutesInScope = function(){ }; BinderTest.prototype.testParseEmptyAnchor = function(){ - var binder = new nglr.Binder(null, null, new MockUrlWatcher()); + var binder = compile("
").binder; + var location = binder.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 nglr.Binder(null, null, new MockUrlWatcher()); - binder.parseAnchor("a#x=1"); + var binder = compile("
").binder; + var location = binder.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); @@ -371,32 +352,30 @@ BinderTest.prototype.testParseAnchor = function(){ }; BinderTest.prototype.testWriteAnchor = function(){ - var binder = new nglr.Binder(null, null, new MockUrlWatcher()); - binder.urlWatcher.setUrl('a'); + var binder = compile("
").binder; + 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 nglr.Binder(html("
")[0], null, new MockUrlWatcher()); - binder.urlWatcher.setUrl('a'); - $(binder.doc).data('scope', new nglr.Scope()); + var binder = compile("
").binder; + binder.location.set('a'); 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 nglr.Binder(form.get(0), null, new MockUrlWatcher()); + var a = compile('
'); + var form = a.node; var items = [{a:"A"}, {a:"B"}]; - form.data('scope', new nglr.Scope({model:{items:items}})); - binder.compile(); + a.scope.set('model', {items:items}); - binder.updateView(); + a.binder.updateView(); assertEquals('
    ' + '<#comment>' + '
  • A
  • ' + @@ -404,7 +383,7 @@ BinderTest.prototype.testRepeaterUpdateBindings = function(){ '
', form.sortedHtml()); items.unshift({a:'C'}); - binder.updateView(); + a.binder.updateView(); assertEquals('
    ' + '<#comment>' + '
  • C
  • ' + @@ -413,7 +392,7 @@ BinderTest.prototype.testRepeaterUpdateBindings = function(){ '
', form.sortedHtml()); items.shift(); - binder.updateView(); + a.binder.updateView(); assertEquals('
    ' + '<#comment>' + '
  • A
  • ' + @@ -422,15 +401,13 @@ BinderTest.prototype.testRepeaterUpdateBindings = function(){ }; BinderTest.prototype.testRepeaterContentDoesNotBind = function(){ - var form = html('
    '); - form.data('scope', new nglr.Scope({model:{items:[{a:"A"}]}})); - var binder = new nglr.Binder(form.get(0), null, new MockUrlWatcher()); - binder.compile(); - binder.updateView(); + var a = compile('
    '); + a.scope.set('model', {items:[{a:"A"}]}); + a.binder.updateView(); assertEquals('
      ' + '<#comment>' + '
    • A
    • ' + - '
    ', form.sortedHtml()); + '
', a.node.sortedHtml()); }; BinderTest.prototype.testShouldBindActionsOnRepeaterClone = function(){ @@ -450,9 +427,9 @@ BinderTest.prototype.testRepeaterInputContentDoesNotBind = function(){ var form = html('
  • ' + '
'); - var binder = new nglr.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 nglr.Scope({model:{items:items}})); + form.data('scope', new Scope({model:{items:items}})); assertEquals(form.find(":input").attr("value"), "OLD"); }; @@ -492,9 +469,9 @@ BinderTest.prototype.testDoNotOverwriteCustomAction = function(){ BinderTest.prototype.testReplaceFileUploadWithSwf = function(){ expectAsserts(1); var form = jQuery("body").append('
'); - form.data('scope', new nglr.Scope()); + form.data('scope', new Scope()); var factory = {}; - var binder = new nglr.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,11 +481,11 @@ BinderTest.prototype.testReplaceFileUploadWithSwf = function(){ }; BinderTest.prototype.testRepeaterAdd = function(){ - var doc = $('
'); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - doc.data('scope', new nglr.Scope({items:[{x:'a'}, {x:'b'}], $binder:binder})); - binder.compile(); - binder.updateView(); + var c = compile('
'); + var doc = c.node; + c.scope.set('items', [{x:'a'}, {x:'b'}]); + c.binder.compile(); + c.binder.updateView(); assertEquals('a', doc.find(':input')[0].value); assertEquals('b', doc.find(':input')[1].value); @@ -519,64 +496,55 @@ BinderTest.prototype.testRepeaterAdd = function(){ }; BinderTest.prototype.testIfTextBindingThrowsErrorDecorateTheSpan = function(){ - var doc = $('
{{error.throw()}}
'); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); + var a = compile('
{{error.throw()}}
'); + var doc = a.node.find('div'); - scope.set('error.throw', function(){throw "ErrorMsg1";}); - binder.updateView(); + a.scope.set('error.throw', function(){throw "ErrorMsg1";}); + a.binder.updateView(); var span = doc.find('span'); assertTrue(span.hasClass('ng-exception')); - assertEquals('ErrorMsg1', nglr.fromJson(span.text())); + assertEquals('ErrorMsg1', fromJson(span.text())); assertEquals('"ErrorMsg1"', span.attr('ng-error')); - scope.set('error.throw', function(){throw "MyError";}); - binder.updateView(); + a.scope.set('error.throw', function(){throw "MyError";}); + a.binder.updateView(); span = doc.find('span'); assertTrue(span.hasClass('ng-exception')); assertTrue(span.text(), span.text().match('MyError') !== null); assertEquals('"MyError"', span.attr('ng-error')); - scope.set('error.throw', function(){return "ok";}); - binder.updateView(); + a.scope.set('error.throw', function(){return "ok";}); + a.binder.updateView(); assertFalse(span.hasClass('ng-exception')); assertEquals('ok', span.text()); assertEquals(null, span.attr('ng-error')); }; BinderTest.prototype.testIfAttrBindingThrowsErrorDecorateTheSpan = function(){ - var doc = $('
'); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); + var a = compile('
'); + var doc = a.node.find("div"); - scope.set('error.throw', function(){throw "ErrorMsg";}); - binder.updateView(); + a.scope.set('error.throw', function(){throw "ErrorMsg";}); + a.binder.updateView(); assertTrue('ng-exception', doc.hasClass('ng-exception')); assertEquals('before ["ErrorMsg"] after', doc.attr('attr')); assertEquals('"ErrorMsg"', doc.attr('ng-error')); - scope.set('error.throw', function(){ return 'X';}); - binder.updateView(); + a.scope.set('error.throw', function(){ return 'X';}); + a.binder.updateView(); assertFalse('!ng-exception', doc.hasClass('ng-exception')); assertEquals('before X after', doc.attr('attr')); assertEquals(null, doc.attr('ng-error')); + }; BinderTest.prototype.testNestedRepeater = function() { - var doc = html('
' + + var a = compile('
' + '
    ' + '
    '); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - scope.set('model', [{name:'a', item:['a1', 'a2']}, {name:'b', item:['b1', 'b2']}]); - binder.updateView(); + a.scope.set('model', [{name:'a', item:['a1', 'a2']}, {name:'b', item:['b1', 'b2']}]); + a.binder.updateView(); assertEquals( //'<#comment>'+ @@ -589,88 +557,71 @@ BinderTest.prototype.testNestedRepeater = function() { '<#comment>'+ '
      '+ '
        '+ - '
        ', doc.sortedHtml()); + '
        ', a.node.sortedHtml()); }; BinderTest.prototype.testRadioButtonGetsPrefixed = function () { - var doc = html(''); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); - - scope.set('model', ['a1', 'a2']); - binder.updateView(); + var a = compile(''); + a.scope.set('model', ['a1', 'a2']); + a.binder.updateView(); assertEquals( //'<#comment>'+ ''+ '', - doc.sortedHtml()); + a.node.sortedHtml()); }; BinderTest.prototype.testHideBindingExpression = function() { - var doc = html('
        '); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); + var a = compile('
        '); - scope.set('hidden', 3); - binder.updateView(); + a.scope.set('hidden', 3); + a.binder.updateView(); - assertHidden(doc.children()); + assertHidden(a.node.children()); - scope.set('hidden', 2); - binder.updateView(); + a.scope.set('hidden', 2); + a.binder.updateView(); - assertVisible(doc.children()); + assertVisible(a.node.children()); }; BinderTest.prototype.testHideBinding = function() { - var doc = html('
        '); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); + var c = compile('
        '); - scope.set('hidden', 'true'); - binder.updateView(); + c.scope.set('hidden', 'true'); + c.binder.updateView(); - assertHidden(doc.children()); + assertHidden(c.node.children()); - scope.set('hidden', 'false'); - binder.updateView(); + c.scope.set('hidden', 'false'); + c.binder.updateView(); - assertVisible(doc.children()); + assertVisible(c.node.children()); - scope.set('hidden', ''); - binder.updateView(); + c.scope.set('hidden', ''); + c.binder.updateView(); - assertVisible(doc.children()); + assertVisible(c.node.children()); }; BinderTest.prototype.testShowBinding = function() { - var doc = html('
        '); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); + var c = compile('
        '); - scope.set('show', 'true'); - binder.updateView(); + c.scope.set('show', 'true'); + c.binder.updateView(); - assertVisible(doc.children()); + assertVisible(c.node.children()); - scope.set('show', 'false'); - binder.updateView(); + c.scope.set('show', 'false'); + c.binder.updateView(); - assertHidden(doc.children()); + assertHidden(c.node.children()); - scope.set('show', ''); - binder.updateView(); + c.scope.set('show', ''); + c.binder.updateView(); - assertHidden(doc.children()); + assertHidden(c.node.children()); }; BinderTest.prototype.testBindClassUndefined = function() { @@ -683,22 +634,18 @@ BinderTest.prototype.testBindClassUndefined = function() { }; BinderTest.prototype.testBindClass = function() { - var doc = html('
        '); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); + var c = compile('
        '); - scope.set('class', 'testClass'); - binder.updateView(); + c.scope.set('class', 'testClass'); + c.binder.updateView(); - assertEquals(doc.sortedHtml(), + assertEquals(c.node.sortedHtml(), '
        '); - scope.set('class', ['a', 'b']); - binder.updateView(); + c.scope.set('class', ['a', 'b']); + c.binder.updateView(); - assertEquals(doc.sortedHtml(), + assertEquals(c.node.sortedHtml(), '
        '); }; @@ -712,21 +659,17 @@ BinderTest.prototype.testBindClassEvenOdd = function() { }; BinderTest.prototype.testBindStyle = function() { - var doc = html('
        '); - var scope = new nglr.Scope(); - doc.data('scope', scope); - var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher()); - binder.compile(); + var c = compile('
        '); - scope.eval('style={color:"red"}'); - binder.updateView(); + c.scope.eval('style={color:"red"}'); + c.binder.updateView(); - assertEquals("red", doc.find('div').css('color')); + assertEquals("red", c.node.find('div').css('color')); - scope.eval('style={}'); - binder.updateView(); + c.scope.eval('style={}'); + c.binder.updateView(); - assertEquals(doc.sortedHtml(), '
        '); + assertEquals(c.node.sortedHtml(), '
        '); }; BinderTest.prototype.testActionOnAHrefThrowsError = function(){ @@ -734,7 +677,7 @@ BinderTest.prototype.testActionOnAHrefThrowsError = function(){ var state = compile('Add Phone', model); var input = state.node.find('a'); input.click(); - assertEquals('abc', nglr.fromJson(input.attr('ng-error')).a); + assertEquals('abc', fromJson(input.attr('ng-error')).a); assertNotNull(input.data('qtip')); assertTrue("should have an error class", input.hasClass('ng-exception')); @@ -798,7 +741,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); @@ -806,7 +749,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() { @@ -876,21 +819,30 @@ 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")); }; BinderTest.prototype.testParseQueryString = function(){ - var binder = new nglr.Binder(); + var binder = new Binder(); assertJsonEquals({"a":"1"}, binder.parseQueryString("a=1")); assertJsonEquals({"a":"1", "b":"two"}, binder.parseQueryString("a=1&b=two")); assertJsonEquals({}, binder.parseQueryString("")); @@ -905,8 +857,8 @@ BinderTest.prototype.testParseQueryString = function(){ BinderTest.prototype.testSetBinderAnchorTriggersListeners = function(){ expectAsserts(2); var doc = html("
        ")[0]; - var binder = new nglr.Binder(doc, null, new MockUrlWatcher()); - var scope = new nglr.Scope({$binder:binder, $anchor:binder.anchor}); + var binder = new Binder(doc, null, null, new MockLocation()); + var scope = new Scope({$binder:binder, $anchor:binder.anchor}); jQuery(doc).data('scope', scope); scope.addWatchListener("$anchor.name", function(newVal, oldVal) { diff --git a/test/ConsoleTest.js b/test/ConsoleTest.js index 56e223bd..f659752f 100644 --- a/test/ConsoleTest.js +++ b/test/ConsoleTest.js @@ -1,13 +1,12 @@ ConsoleTest = TestCase('ConsoleTest'); ConsoleTest.prototype.testConsoleWrite = function(){ - var consoleNode = $("
        ")[0]; - nglr.consoleNode = consoleNode; - nglr.consoleLog("error", ["Hello", "world"]); + consoleNode = $("
        ")[0]; + consoleLog("error", ["Hello", "world"]); assertEquals($(consoleNode)[0].nodeName, 'DIV'); assertEquals($(consoleNode).text(), 'Hello world'); assertEquals($('div', consoleNode)[0].className, 'error'); - nglr.consoleLog("error",["Bye"]); + consoleLog("error",["Bye"]); assertEquals($(consoleNode).text(), 'Hello worldBye'); - nglr.consoleNode = null; + consoleNode = null; }; \ No newline at end of file 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/DataStoreTest.js b/test/DataStoreTest.js index 9fe6c3df..87c5be2e 100644 --- a/test/DataStoreTest.js +++ b/test/DataStoreTest.js @@ -11,15 +11,14 @@ DataStoreTest.prototype.testSavePostsToServer = function(){ assertEquals("123", posted.$id); assertEquals("1", posted.$version); assertFalse('function' == typeof posted.save); - response = nglr.fromJson(nglr.toJson(posted)); + response = fromJson(toJson(posted)); response.$entity = "abc"; response.$id = "123"; response.$version = "2"; callback(200, [response]); }; - var model; - var datastore = new nglr.DataStore(post); - model = datastore.entity('abc', {name: "value"})(); + var datastore = new DataStore(post); + var model = datastore.entity('abc', {name: "value"})(); model.$id = "123"; model.$version = "1"; @@ -44,7 +43,7 @@ DataStoreTest.prototype.testLoadGetsFromServer = function(){ response = [{$entity:'abc', $id:'1', $version:'2', key:"value"}]; callback(200, response); }; - var datastore = new nglr.DataStore(post); + var datastore = new DataStore(post); var model = datastore.entity("abc", {merge:true})(); assertEquals(datastore.load(model, '1', function(obj){ @@ -72,14 +71,14 @@ DataStoreTest.prototype.testRemove = function(){ assertEquals("123", posted.$id); assertEquals("1", posted.$version); assertFalse('function' == typeof posted.save); - response = nglr.fromJson(nglr.toJson(posted)); + response = fromJson(toJson(posted)); response.$entity = "abc"; response.$id = "123"; response.$version = "2"; callback(200, [response]); }; var model; - var datastore = new nglr.DataStore(post); + var datastore = new DataStore(post); model = datastore.entity('abc', {name: "value"})(); model.$id = "123"; model.$version = "1"; @@ -101,7 +100,7 @@ DataStoreTest.prototype.test401ResponseDoesNotCallCallback = function(){ callback(200, {$status_code: 401}); }; - var datastore = new nglr.DataStore(post, {login:function(){ + var datastore = new DataStore(post, {login:function(){ assertTrue(true); }}); @@ -119,7 +118,7 @@ DataStoreTest.prototype.test403ResponseDoesNotCallCallback = function(){ callback(200, [{$status_code: 403}]); }; - var datastore = new nglr.DataStore(post, {notAuthorized:function(){ + var datastore = new DataStore(post, {notAuthorized:function(){ assertTrue(true); }}); @@ -136,14 +135,14 @@ DataStoreTest.prototype.testLoadCalledWithoutIdShouldBeNoop = function(){ var post = function(url, callback){ assertTrue(false); }; - var datastore = new nglr.DataStore(post); + var datastore = new DataStore(post); var model = datastore.entity("abc")(); assertEquals(datastore.load(model, undefined), model); assertEquals(model.$entity, "abc"); }; DataStoreTest.prototype.testEntityFactory = function(){ - var ds = new nglr.DataStore(); + var ds = new DataStore(); var Recipe = ds.entity("Recipe", {a:1, b:2}); assertEquals(Recipe.title, "Recipe"); assertEquals(Recipe.defaults.a, 1); @@ -161,7 +160,7 @@ DataStoreTest.prototype.testEntityFactory = function(){ }; DataStoreTest.prototype.testEntityFactoryNoDefaults = function(){ - var ds = new nglr.DataStore(); + var ds = new DataStore(); var Recipe = ds.entity("Recipe"); assertEquals(Recipe.title, "Recipe"); @@ -170,7 +169,7 @@ DataStoreTest.prototype.testEntityFactoryNoDefaults = function(){ }; DataStoreTest.prototype.testEntityFactoryWithInitialValues = function(){ - var ds = new nglr.DataStore(); + var ds = new DataStore(); var Recipe = ds.entity("Recipe"); var recipe = Recipe({name: "name"}); @@ -178,7 +177,7 @@ DataStoreTest.prototype.testEntityFactoryWithInitialValues = function(){ }; DataStoreTest.prototype.testEntityLoad = function(){ - var ds = new nglr.DataStore(); + var ds = new DataStore(); var Recipe = ds.entity("Recipe", {a:1, b:2}); ds.load = function(instance, id, callback){ callback.apply(instance); @@ -192,7 +191,7 @@ DataStoreTest.prototype.testEntityLoad = function(){ }; DataStoreTest.prototype.testSaveScope = function(){ - var ds = new nglr.DataStore(); + var ds = new DataStore(); var log = ""; var Person = ds.entity("Person"); var person1 = Person({name:"A", $entity:"Person", $id:"1", $version:"1"}, ds); @@ -215,7 +214,7 @@ DataStoreTest.prototype.testSaveScope = function(){ }; DataStoreTest.prototype.testEntityLoadAllRows = function(){ - var ds = new nglr.DataStore(); + var ds = new DataStore(); var Recipe = ds.entity("Recipe"); var list = []; ds.loadAll = function(entity, callback){ @@ -236,7 +235,7 @@ DataStoreTest.prototype.testLoadAll = function(){ assertEquals("A", data[0][1]); callback(200, [[{$entity:'A', $id:'1'},{$entity:'A', $id:'2'}]]); }; - var datastore = new nglr.DataStore(post); + var datastore = new DataStore(post); var list = datastore.entity("A").all(function(){ assertTrue(true); }); @@ -256,7 +255,7 @@ DataStoreTest.prototype.testQuery = function(){ callback(200, [[{$entity:"Employee", $id: "456", managerId: "123ABC"}]]); }; - var datastore = new nglr.DataStore(post); + var datastore = new DataStore(post); var Employee = datastore.entity("Employee"); var list = Employee.query('managerId', "123abc", function(){ assertTrue(true); @@ -269,7 +268,7 @@ DataStoreTest.prototype.testQuery = function(){ DataStoreTest.prototype.testLoadingDocumentRefreshesExistingArrays = function() { expectAsserts(12); var post; - var datastore = new nglr.DataStore(function(r, c){post(r,c);}); + var datastore = new DataStore(function(r, c){post(r,c);}); var Book = datastore.entity('Book'); post = function(req, callback) { callback(200, [[{$id:1, $entity:"Book", name:"Moby"}, @@ -285,7 +284,7 @@ DataStoreTest.prototype.testLoadingDocumentRefreshesExistingArrays = function() assertEquals("Dick", queryBooks[1].name); post = function(req, callback) { - assertEquals('[["GET","Book/1"]]', nglr.toJson(req)); + assertEquals('[["GET","Book/1"]]', toJson(req)); callback(200, [{$id:1, $entity:"Book", name:"Moby Dick"}]); }; var book = Book.load(1); @@ -307,7 +306,7 @@ DataStoreTest.prototype.testLoadingDocumentRefreshesExistingArrays = function() DataStoreTest.prototype.testEntityProperties = function() { expectAsserts(2); - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var callback = {}; datastore._jsonRequest = function(request, callbackFn) { @@ -322,11 +321,11 @@ DataStoreTest.prototype.testEntityProperties = function() { DataStoreTest.prototype.testLoadInstanceIsNotFromCache = function() { var post; - var datastore = new nglr.DataStore(function(r, c){post(r,c);}); + var datastore = new DataStore(function(r, c){post(r,c);}); var Book = datastore.entity('Book'); post = function(req, callback) { - assertEquals('[["GET","Book/1"]]', nglr.toJson(req)); + assertEquals('[["GET","Book/1"]]', toJson(req)); callback(200, [{$id:1, $entity:"Book", name:"Moby Dick"}]); }; var book = Book.load(1); @@ -336,14 +335,14 @@ DataStoreTest.prototype.testLoadInstanceIsNotFromCache = function() { }; DataStoreTest.prototype.testLoadStarsIsNewDocument = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Book = datastore.entity('Book'); var book = Book.load('*'); assertEquals('Book', book.$entity); }; DataStoreTest.prototype.testUndefinedEntityReturnsNullValueObject = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Entity = datastore.entity(undefined); var all = Entity.all(); assertEquals(0, all.length); @@ -355,7 +354,7 @@ DataStoreTest.prototype.testFetchEntities = function(){ assertJsonEquals(["GET", "$entities"], data[0]); callback(200, [{A:0, B:0}]); }; - var datastore = new nglr.DataStore(post); + var datastore = new DataStore(post); var entities = datastore.entities(function(){ assertTrue(true); }); @@ -367,20 +366,20 @@ DataStoreTest.prototype.testFetchEntities = function(){ }; DataStoreTest.prototype.testItShouldMigrateSchema = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Entity = datastore.entity("Entity", {a:[], user:{name:"Misko", email:""}}); var doc = Entity().$loadFrom({b:'abc', user:{email:"misko@hevery.com"}}); assertFalse( - nglr.toJson({a:[], b:'abc', user:{name:"Misko", email:"misko@hevery.com"}}) == - nglr.toJson(doc)); + toJson({a:[], b:'abc', user:{name:"Misko", email:"misko@hevery.com"}}) == + toJson(doc)); doc.$migrate(); assertEquals( - nglr.toJson({a:[], b:'abc', user:{name:"Misko", email:"misko@hevery.com"}}), - nglr.toJson(doc)); + toJson({a:[], b:'abc', user:{name:"Misko", email:"misko@hevery.com"}}), + toJson(doc)); }; DataStoreTest.prototype.testItShouldCollectRequestsForBulk = function() { - var ds = new nglr.DataStore(); + var ds = new DataStore(); var Book = ds.entity("Book"); var Library = ds.entity("Library"); Book.all(); @@ -391,7 +390,7 @@ DataStoreTest.prototype.testItShouldCollectRequestsForBulk = function() { }; DataStoreTest.prototype.testEmptyFlushShouldDoNothing = function () { - var ds = new nglr.DataStore(function(){ + var ds = new DataStore(function(){ fail("expecting noop"); }); ds.flush(); @@ -400,17 +399,17 @@ DataStoreTest.prototype.testEmptyFlushShouldDoNothing = function () { DataStoreTest.prototype.testFlushShouldCallAllCallbacks = function() { var log = ""; function post(request, callback){ - log += 'BulkRequest:' + nglr.toJson(request) + ';'; + log += 'BulkRequest:' + toJson(request) + ';'; callback(200, [[{$id:'ABC'}], {$id:'XYZ'}]); } - var ds = new nglr.DataStore(post); + var ds = new DataStore(post); var Book = ds.entity("Book"); var Library = ds.entity("Library"); Book.all(function(instance){ - log += nglr.toJson(instance) + ';'; + log += toJson(instance) + ';'; }); Library.load("123", function(instance){ - log += nglr.toJson(instance) + ';'; + log += toJson(instance) + ';'; }); assertEquals("", log); ds.flush(); @@ -421,7 +420,7 @@ DataStoreTest.prototype.testFlushShouldCallAllCallbacks = function() { DataStoreTest.prototype.testSaveOnNotLoggedInRetriesAfterLoggin = function(){ var log = ""; var book; - var ds = new nglr.DataStore(null, {login:function(c){c();}}); + var ds = new DataStore(null, {login:function(c){c();}}); ds.post = function (request, callback){ assertJsonEquals([["POST", "", book]], request); ds.post = function(request, callback){ @@ -439,7 +438,7 @@ DataStoreTest.prototype.testSaveOnNotLoggedInRetriesAfterLoggin = function(){ DataStoreTest.prototype.testItShouldRemoveItemFromCollectionWhenDeleted = function() { expectAsserts(6); - var ds = new nglr.DataStore(); + var ds = new DataStore(); ds.post = function(request, callback){ assertJsonEquals([["GET", "Book"]], request); callback(200, [[{name:"Moby Dick", $id:123, $entity:'Book'}]]); @@ -462,7 +461,7 @@ DataStoreTest.prototype.testItShouldRemoveItemFromCollectionWhenDeleted = functi DataStoreTest.prototype.testItShouldAddToAll = function() { expectAsserts(8); - var ds = new nglr.DataStore(); + var ds = new DataStore(); ds.post = function(request, callback){ assertJsonEquals([["GET", "Book"]], request); callback(200, [[]]); @@ -490,7 +489,7 @@ DataStoreTest.prototype.testItShouldAddToAll = function() { DataStoreTest.prototype.testItShouldReturnCreatedDocumentCountByUser = function(){ expectAsserts(2); - var datastore = new nglr.DataStore( + var datastore = new DataStore( function(request, callback){ assertJsonEquals([["GET", "$users"]], request); callback(200, [{misko:1, adam:1}]); @@ -502,7 +501,7 @@ DataStoreTest.prototype.testItShouldReturnCreatedDocumentCountByUser = function( DataStoreTest.prototype.testItShouldReturnDocumentIdsForUeserByEntity = function(){ expectAsserts(2); - var datastore = new nglr.DataStore( + var datastore = new DataStore( function(request, callback){ assertJsonEquals([["GET", "$users/misko@hevery.com"]], request); callback(200, [{Book:["1"], Library:["2"]}]); @@ -514,7 +513,7 @@ DataStoreTest.prototype.testItShouldReturnDocumentIdsForUeserByEntity = function DataStoreTest.prototype.testItShouldReturnNewInstanceOn404 = function(){ expectAsserts(7); var log = ""; - var datastore = new nglr.DataStore( + var datastore = new DataStore( function(request, callback){ assertJsonEquals([["GET", "User/misko"]], request); callback(200, [{$status_code:404}]); @@ -532,13 +531,13 @@ DataStoreTest.prototype.testItShouldReturnNewInstanceOn404 = function(){ DataStoreTest.prototype.testItShouldReturnNewInstanceOn404 = function(){ var log = ""; - var datastore = new nglr.DataStore( + var datastore = new DataStore( function(request, callback){ assertJsonEquals([["GET", "User/misko"],["GET", "User/adam"]], request); callback(200, [{$id:'misko'},{$id:'adam'}]); }); var User = datastore.entity("User"); - var users = User.loadMany(['misko', 'adam'], function(i){log+="cb "+nglr.toJson(i)+";";}); + var users = User.loadMany(['misko', 'adam'], function(i){log+="cb "+toJson(i)+";";}); datastore.flush(); assertEquals("misko", users[0].$id); assertEquals("adam", users[1].$id); @@ -546,7 +545,7 @@ DataStoreTest.prototype.testItShouldReturnNewInstanceOn404 = function(){ }; DataStoreTest.prototype.testItShouldCreateJoinAndQuery = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Invoice = datastore.entity("Invoice"); var Customer = datastore.entity("Customer"); var InvoiceWithCustomer = datastore.join({ @@ -568,7 +567,7 @@ DataStoreTest.prototype.testItShouldCreateJoinAndQuery = function() { }; DataStoreTest.prototype.testItShouldThrowIfMoreThanOneEntityIsPrimary = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Invoice = datastore.entity("Invoice"); var Customer = datastore.entity("Customer"); assertThrows("Exactly one entity needs to be primary.", function(){ @@ -580,7 +579,7 @@ DataStoreTest.prototype.testItShouldThrowIfMoreThanOneEntityIsPrimary = function }; DataStoreTest.prototype.testItShouldThrowIfLoopInReferences = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Invoice = datastore.entity("Invoice"); var Customer = datastore.entity("Customer"); assertThrows("Infinite loop in join: invoice -> customer", function(){ @@ -592,7 +591,7 @@ DataStoreTest.prototype.testItShouldThrowIfLoopInReferences = function() { }; DataStoreTest.prototype.testItShouldThrowIfReferenceToNonExistantJoin = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Invoice = datastore.entity("Invoice"); var Customer = datastore.entity("Customer"); assertThrows("Named entity 'x' is undefined.", function(){ @@ -604,7 +603,7 @@ DataStoreTest.prototype.testItShouldThrowIfReferenceToNonExistantJoin = function }; DataStoreTest.prototype.testItShouldThrowIfQueryOnNonPrimary = function() { - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var Invoice = datastore.entity("Invoice"); var Customer = datastore.entity("Customer"); var InvoiceWithCustomer = datastore.join({ diff --git a/test/EntityDeclarationTest.js b/test/EntityDeclarationTest.js index 5cab90f4..28986ea8 100644 --- a/test/EntityDeclarationTest.js +++ b/test/EntityDeclarationTest.js @@ -2,31 +2,34 @@ EntityDeclarationTest = TestCase('EntityDeclarationTest'); EntityDeclarationTest.prototype.testEntityTypeOnly = function(){ expectAsserts(2); - var scope = new nglr.Scope({$datastore:{entity:function(name){ + var datastore = {entity:function(name){ assertEquals("Person", name); - }}}); - var init = scope.entity("Person"); + }}; + var scope = new Scope(); + var init = scope.entity("Person", datastore); assertEquals("", init); }; EntityDeclarationTest.prototype.testWithDefaults = function(){ expectAsserts(4); - var scope = new nglr.Scope({$datastore:{entity:function(name, init){ + var datastore = {entity:function(name, init){ assertEquals("Person", name); assertEquals("=a:", init.a); assertEquals(0, init.b.length); - }}}); - var init = scope.entity('Person:{a:"=a:", b:[]}'); + }}; + var scope = new Scope(); + var init = scope.entity('Person:{a:"=a:", b:[]}', datastore); assertEquals("", init); }; EntityDeclarationTest.prototype.testWithName = function(){ expectAsserts(2); - var scope = new nglr.Scope({$datastore:{entity:function(name, init){ + var datastore = {entity:function(name, init){ assertEquals("Person", name); return function (){ return {}; }; - }}}); - var init = scope.entity('friend=Person'); + }}; + var scope = new Scope(); + var init = scope.entity('friend=Person', datastore); assertEquals("$anchor.friend:{friend=Person.load($anchor.friend);friend.$$anchor=\"friend\";};", init); }; @@ -34,12 +37,13 @@ EntityDeclarationTest.prototype.testMultipleEntities = function(){ expectAsserts(3); var expect = ['Person', 'Book']; var i=0; - var scope = new nglr.Scope({$datastore:{entity:function(name, init){ + var datastore = {entity:function(name, init){ assertEquals(expect[i], name); i++; return function (){ return {}; }; - }}}); - var init = scope.entity('friend=Person;book=Book;'); + }}; + var scope = new Scope(); + var init = scope.entity('friend=Person;book=Book;', datastore); assertEquals("$anchor.friend:{friend=Person.load($anchor.friend);friend.$$anchor=\"friend\";};" + "$anchor.book:{book=Book.load($anchor.book);book.$$anchor=\"book\";};", init); diff --git a/test/FileControllerTest.js b/test/FileControllerTest.js index ca5925e4..454e7624 100644 --- a/test/FileControllerTest.js +++ b/test/FileControllerTest.js @@ -3,24 +3,24 @@ FileControllerTest = TestCase('FileControllerTest'); FileControllerTest.prototype.testOnSelectUpdateView = function(){ var view = jQuery(''); var swf = {}; - var controller = new nglr.FileController(view, null, swf); + var controller = new FileController(view, null, swf); swf.uploadFile = function(path){}; - controller._on_select('A', 9, '9 bytes'); + controller.select('A', 9, '9 bytes'); assertEquals(view.find('a').text(), "A"); assertEquals(view.find('span').text(), "9 bytes"); }; FileControllerTest.prototype.testUpdateModelView = function(){ - var view = nglr.FileController.template(''); + var view = FileController.template(''); var input = $(''); var controller; - var scope = new nglr.Scope({value:{}, $binder:{updateView:function(){ + var scope = new Scope({value:{}, $binder:{updateView:function(){ controller.updateView(scope); }}}); view.data('scope', scope); - controller = new nglr.FileController(view, 'value.input', null, "http://server_base"); + controller = new FileController(view, 'value.input', null, "http://server_base"); var value = '{"text":"A", "size":123, "id":"890"}'; - controller._on_uploadCompleteData(value); + controller.uploadCompleteData(value); controller.updateView(scope); assertEquals(scope.get('value.input.text'), 'A'); assertEquals(scope.get('value.input.size'), 123); @@ -34,7 +34,7 @@ FileControllerTest.prototype.testUpdateModelView = function(){ FileControllerTest.prototype.testFileUpload = function(){ expectAsserts(1); var swf = {}; - var controller = new nglr.FileController(null, null, swf, "http://server_base"); + var controller = new FileController(null, null, swf, "http://server_base"); swf.uploadFile = function(path){ assertEquals("http://server_base/_attachments", path); }; @@ -47,16 +47,16 @@ FileControllerTest.prototype.testFileUploadNoFileIsNoop = function(){ var swf = {uploadFile:function(path){ fail(); }}; - var controller = new nglr.FileController(null, swf); + var controller = new FileController(null, swf); controller.upload("basePath", null); }; FileControllerTest.prototype.testRemoveAttachment = function(){ - var doc = nglr.FileController.template(); + var doc = FileController.template(); var input = $(''); - var scope = new nglr.Scope(); + var scope = new Scope(); input.data('scope', scope); - var controller = new nglr.FileController(doc, 'file', null, null); + var controller = new FileController(doc, 'file', null, null); controller.updateView(scope); assertEquals(false, doc.find('input').attr('checked')); @@ -75,10 +75,10 @@ FileControllerTest.prototype.testRemoveAttachment = function(){ }; FileControllerTest.prototype.testShouldEmptyOutOnUndefined = function () { - var view = nglr.FileController.template('hello'); - var controller = new nglr.FileController(view, 'abc', null, null); + var view = FileController.template('hello'); + var controller = new FileController(view, 'abc', null, null); - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('abc', {text: 'myname', url: 'myurl', size: 1234}); controller.updateView(scope); diff --git a/test/FiltersTest.js b/test/FiltersTest.js index 8943fdd4..5ca63ca7 100644 --- a/test/FiltersTest.js +++ b/test/FiltersTest.js @@ -3,7 +3,7 @@ FiltersTest = TestCase('FiltersTest'); FiltersTest.prototype.testCurrency = function(){ var html = $(''); var context = {element:html[0]}; - var currency = nglr.bind(context, angular.filter.currency); + var currency = bind(context, angular.filter.currency); assertEquals(currency(0), '$0.00'); assertEquals(html.hasClass('ng-format-negative'), false); @@ -15,8 +15,8 @@ FiltersTest.prototype.testCurrency = function(){ FiltersTest.prototype.testFilterThisIsContext = function(){ expectAsserts(2); - var scope = new nglr.Scope(); - nglr.Scope.expressionCache = {}; + var scope = new Scope(); + Scope.expressionCache = {}; var context = {element:123}; angular.filter.testFn = function () { assertEquals('Context not equal', this, context); @@ -28,7 +28,7 @@ FiltersTest.prototype.testFilterThisIsContext = function(){ FiltersTest.prototype.testNumberFormat = function(){ var context = {jqElement:$('')}; - var number = nglr.bind(context, angular.filter.number); + var number = bind(context, angular.filter.number); assertEquals('0', number(0, 0)); assertEquals('0.00', number(0)); @@ -40,7 +40,7 @@ FiltersTest.prototype.testNumberFormat = function(){ }; FiltersTest.prototype.testJson = function () { - assertEquals(nglr.toJson({a:"b"}, true), angular.filter.json({a:"b"})); + assertEquals(toJson({a:"b"}, true), angular.filter.json({a:"b"})); }; FiltersTest.prototype.testPackageTracking = function () { @@ -48,9 +48,9 @@ FiltersTest.prototype.testPackageTracking = function () { var val = angular.filter.trackPackage(trackingNo, title); assertNotNull("Did Not Match: " + trackingNo, val); assertEquals(angular.filter.Meta.TAG, val.TAG); - assertEquals(title + ": " + nglr.trim(trackingNo), val.text); + assertEquals(title + ": " + trim(trackingNo), val.text); assertNotNull(val.url); - assertEquals(nglr.trim(trackingNo), val.trackingNo); + assertEquals(trim(trackingNo), val.trackingNo); assertEquals('' + val.text + '', val.html); }; assert('UPS', ' 1Z 999 999 99 9999 999 9 '); @@ -83,7 +83,7 @@ FiltersTest.prototype.testLink = function() { }; FiltersTest.prototype.testBytes = function(){ - var controller = new nglr.FileController(); + var controller = new FileController(); assertEquals(angular.filter.bytes(123), '123 bytes'); assertEquals(angular.filter.bytes(1234), '1.2 KB'); assertEquals(angular.filter.bytes(1234567), '1.1 MB'); @@ -151,3 +151,17 @@ FiltersTest.prototype.testHtml = function() { angular.filter.html("acd").html); assertTrue(angular.filter.html("acd") instanceof angular.filter.Meta); }; + +FiltersTest.prototype.testLinky = function() { + var linky = angular.filter.linky; + assertEquals( + 'http://ab ' + + '(http://a) ' + + '<http://a> \n ' + + 'http://1.2/v:~-123. c', + linky("http://ab (http://a) \n http://1.2/v:~-123. c").html); + assertTrue(linky("a") instanceof angular.filter.Meta); + assertEquals(undefined, linky(undefined)); +}; + + diff --git a/test/JsonTest.js b/test/JsonTest.js index 5c3644f5..9b275248 100644 --- a/test/JsonTest.js +++ b/test/JsonTest.js @@ -1,69 +1,80 @@ JsonTest = TestCase("JsonTest"); JsonTest.prototype.testPrimitives = function () { - assertEquals("null", nglr.toJson(0/0)); - assertEquals("null", nglr.toJson(null)); - assertEquals("true", nglr.toJson(true)); - assertEquals("false", nglr.toJson(false)); - assertEquals("123.45", nglr.toJson(123.45)); - assertEquals('"abc"', nglr.toJson("abc")); - assertEquals('"a \\t \\n \\r b \\\\"', nglr.toJson("a \t \n \r b \\")); + assertEquals("null", toJson(0/0)); + assertEquals("null", toJson(null)); + assertEquals("true", toJson(true)); + assertEquals("false", toJson(false)); + assertEquals("123.45", toJson(123.45)); + assertEquals('"abc"', toJson("abc")); + assertEquals('"a \\t \\n \\r b \\\\"', toJson("a \t \n \r b \\")); }; JsonTest.prototype.testEscaping = function () { - assertEquals("\"7\\\\\\\"7\"", nglr.toJson("7\\\"7")); + assertEquals("\"7\\\\\\\"7\"", toJson("7\\\"7")); }; JsonTest.prototype.testObjects = function () { - assertEquals('{"a":1,"b":2}', nglr.toJson({a:1,b:2})); - assertEquals('{"a":{"b":2}}', nglr.toJson({a:{b:2}})); - assertEquals('{"a":{"b":{"c":0}}}', nglr.toJson({a:{b:{c:0}}})); - assertEquals('{"a":{"b":null}}', nglr.toJson({a:{b:0/0}})); + assertEquals('{"a":1,"b":2}', toJson({a:1,b:2})); + assertEquals('{"a":{"b":2}}', toJson({a:{b:2}})); + assertEquals('{"a":{"b":{"c":0}}}', toJson({a:{b:{c:0}}})); + assertEquals('{"a":{"b":null}}', toJson({a:{b:0/0}})); }; JsonTest.prototype.testObjectPretty = function () { - assertEquals('{\n "a":1,\n "b":2}', nglr.toJson({a:1,b:2}, true)); - assertEquals('{\n "a":{\n "b":2}}', nglr.toJson({a:{b:2}}, true)); + assertEquals('{\n "a":1,\n "b":2}', toJson({a:1,b:2}, true)); + assertEquals('{\n "a":{\n "b":2}}', toJson({a:{b:2}}, true)); }; JsonTest.prototype.testArray = function () { - assertEquals('[]', nglr.toJson([])); - assertEquals('[1,"b"]', nglr.toJson([1,"b"])); + assertEquals('[]', toJson([])); + assertEquals('[1,"b"]', toJson([1,"b"])); }; JsonTest.prototype.testIgnoreFunctions = function () { - assertEquals('[null,1]', nglr.toJson([function(){},1])); - assertEquals('{}', nglr.toJson({a:function(){}})); + assertEquals('[null,1]', toJson([function(){},1])); + assertEquals('{}', toJson({a:function(){}})); }; JsonTest.prototype.testParseNull = function () { - assertNull(nglr.fromJson("null")); + assertNull(fromJson("null")); }; JsonTest.prototype.testParseBoolean = function () { - assertTrue(nglr.fromJson("true")); - assertFalse(nglr.fromJson("false")); + assertTrue(fromJson("true")); + assertFalse(fromJson("false")); }; JsonTest.prototype.test$$isIgnored = function () { - assertEquals("{}", nglr.toJson({$$:0})); + assertEquals("{}", toJson({$$:0})); }; JsonTest.prototype.testArrayWithEmptyItems = function () { var a = []; a[1] = "X"; - assertEquals('[null,"X"]', nglr.toJson(a)); + assertEquals('[null,"X"]', toJson(a)); }; JsonTest.prototype.testItShouldEscapeUnicode = function () { assertEquals(1, "\u00a0".length); - assertEquals(8, nglr.toJson("\u00a0").length); - assertEquals(1, nglr.fromJson(nglr.toJson("\u00a0")).length); + assertEquals(8, toJson("\u00a0").length); + assertEquals(1, fromJson(toJson("\u00a0")).length); }; JsonTest.prototype.testItShouldUTCDates = function() { var date = angular.String.toDate("2009-10-09T01:02:03Z"); - assertEquals('"2009-10-09T01:02:03Z"', nglr.toJson(date)); + assertEquals('"2009-10-09T01:02:03Z"', toJson(date)); assertEquals(date.getTime(), - nglr.fromJson('"2009-10-09T01:02:03Z"').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/LoaderTest.js b/test/LoaderTest.js deleted file mode 100644 index 91a804a5..00000000 --- a/test/LoaderTest.js +++ /dev/null @@ -1,70 +0,0 @@ -LoaderTest = TestCase('LoaderTest'); - -LoaderTest.prototype.testLoadCss = function(){ - if ($.browser.safari) return; - var head = jQuery('')[0]; - var loader = new nglr.Loader(document, head, {}); - var log = ''; - loader.config.server = 'http://'; - loader.loadCss('x'); - assertEquals($(head).find('link').attr('href'), 'http://x'); -}; - -LoaderTest.prototype.testDefaultDatabasePathFromSubdomain = function() { - var loader = new nglr.Loader(null, null, {server:"http://account.getangular.com", database:"database"}); - loader.computeConfiguration(); - assertEquals("database", loader.config.database); - - loader = new nglr.Loader(null, null, {server:"http://account.getangular.com"}); - loader.computeConfiguration(); - assertEquals("account", loader.config.database); - - loader = new nglr.Loader(null, null, {server:"https://account.getangular.com"}); - loader.computeConfiguration(); - assertEquals("account", loader.config.database); -}; - - - -UrlWatcherTest = TestCase('UrlWatcherTest'); - -UrlWatcherTest.prototype.testUrlWatcher = function () { - expectAsserts(2); - var location = {href:"http://server", hash:""}; - var watcher = new nglr.UrlWatcher(location); - watcher.delay = 1; - watcher.listener = function(url){ - assertEquals('http://getangular.test', url); - }; - watcher.setTimeout = function(fn, delay){ - assertEquals(1, delay); - location.href = "http://getangular.test"; - watcher.setTimeout = function(fn, delay) { - }; - fn(); - }; - watcher.watch(); -}; - -UrlWatcherTest.prototype.testItShouldFireOnUpdateEventWhenSpecialURLSet = function(){ - expectAsserts(2); - var location = {href:"http://server", hash:"#$iframe_notify=1234"}; - var watcher = new nglr.UrlWatcher(location); - nglr._iframe_notify_1234 = function () { - assertEquals("undefined", typeof nglr._iframe_notify_1234); - assertEquals("http://server2#", location.href); - }; - watcher.delay = 1; - watcher.expectedUrl = "http://server2"; - watcher.setTimeout = function(fn, delay){ - watcher.setTimeout = function(fn, delay) {}; - fn(); - }; - watcher.watch(); -}; - -FunctionTest = TestCase("FunctionTest"); - -FunctionTest.prototype.testEscapeHtml = function () { - assertEquals("<div>&amp;</div>", nglr.escapeHtml('
        &
        ')); -}; \ No newline at end of file diff --git a/test/ModelTest.js b/test/ModelTest.js index 5d9119a1..dbd97778 100644 --- a/test/ModelTest.js +++ b/test/ModelTest.js @@ -1,7 +1,7 @@ ModelTest = TestCase('ModelTest'); ModelTest.prototype.testLoadSaveOperations = function(){ - var m1 = new nglr.DataStore().entity('A')(); + var m1 = new DataStore().entity('A')(); m1.a = 1; var m2 = {b:1}; @@ -13,7 +13,7 @@ ModelTest.prototype.testLoadSaveOperations = function(){ }; ModelTest.prototype.testLoadfromDoesNotClobberFunctions = function(){ - var m1 = new nglr.DataStore().entity('A')(); + var m1 = new DataStore().entity('A')(); m1.id = function(){return 'OK';}; m1.$loadFrom({id:null}); assertEquals(m1.id(), 'OK'); @@ -24,7 +24,7 @@ ModelTest.prototype.testLoadfromDoesNotClobberFunctions = function(){ }; ModelTest.prototype.testDataStoreDoesNotGetClobbered = function(){ - var ds = new nglr.DataStore(); + var ds = new DataStore(); var m = ds.entity('A')(); assertTrue(m.$$entity.datastore === ds); m.$loadFrom({}); @@ -33,7 +33,7 @@ ModelTest.prototype.testDataStoreDoesNotGetClobbered = function(){ ModelTest.prototype.testManagedModelDelegatesMethodsToDataStore = function(){ expectAsserts(7); - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var model = datastore.entity("A", {a:1})(); var fn = {}; datastore.save = function(instance, callback) { @@ -56,7 +56,7 @@ ModelTest.prototype.testManagedModelDelegatesMethodsToDataStore = function(){ ModelTest.prototype.testManagedModelCanBeForcedToFlush = function(){ expectAsserts(6); - var datastore = new nglr.DataStore(); + var datastore = new DataStore(); var model = datastore.entity("A", {a:1})(); datastore.save = function(instance, callback) { @@ -77,7 +77,7 @@ ModelTest.prototype.testManagedModelCanBeForcedToFlush = function(){ ModelTest.prototype.testItShouldMakeDeepCopyOfInitialValues = function (){ var initial = {a:[]}; - var entity = new nglr.DataStore().entity("A", initial); + var entity = new DataStore().entity("A", initial); var model = entity(); model.a.push(1); assertEquals(0, entity().a.length); diff --git a/test/ParserTest.js b/test/ParserTest.js index 7fe8e6a4..2fcbc7fe 100644 --- a/test/ParserTest.js +++ b/test/ParserTest.js @@ -1,7 +1,7 @@ LexerTest = TestCase('LexerTest'); LexerTest.prototype.testTokenizeAString = function(){ - var lexer = new nglr.Lexer("a.bc[22]+1.3|f:'a\\\'c':\"d\\\"e\""); + var lexer = new Lexer("a.bc[22]+1.3|f:'a\\\'c':\"d\\\"e\""); var tokens = lexer.parse(); var i = 0; assertEquals(tokens[i].index, 0); @@ -54,7 +54,7 @@ LexerTest.prototype.testTokenizeAString = function(){ LexerTest.prototype.testTokenizeRegExp = function(){ - var lexer = new nglr.Lexer("/r 1/"); + var lexer = new Lexer("/r 1/"); var tokens = lexer.parse(); var i = 0; assertEquals(tokens[i].index, 0); @@ -64,7 +64,7 @@ LexerTest.prototype.testTokenizeRegExp = function(){ LexerTest.prototype.testQuotedString = function(){ var str = "['\\'', \"\\\"\"]"; - var lexer = new nglr.Lexer(str); + var lexer = new Lexer(str); var tokens = lexer.parse(); assertEquals(1, tokens[1].index); @@ -77,21 +77,21 @@ LexerTest.prototype.testQuotedString = function(){ LexerTest.prototype.testQuotedStringEscape = function(){ var str = '"\\"\\n\\f\\r\\t\\v\\u00A0"'; - var lexer = new nglr.Lexer(str); + var lexer = new Lexer(str); var tokens = lexer.parse(); assertEquals('"\n\f\r\t\v\u00A0', tokens[0].text); }; LexerTest.prototype.testTokenizeUnicode = function(){ - var lexer = new nglr.Lexer('"\\u00A0"'); + var lexer = new Lexer('"\\u00A0"'); var tokens = lexer.parse(); assertEquals(1, tokens.length); assertEquals('\u00a0', tokens[0].text); }; LexerTest.prototype.testTokenizeRegExpWithOptions = function(){ - var lexer = new nglr.Lexer("/r/g"); + var lexer = new Lexer("/r/g"); var tokens = lexer.parse(); var i = 0; assertEquals(tokens[i].index, 0); @@ -101,7 +101,7 @@ LexerTest.prototype.testTokenizeRegExpWithOptions = function(){ }; LexerTest.prototype.testTokenizeRegExpWithEscape = function(){ - var lexer = new nglr.Lexer("/\\/\\d/"); + var lexer = new Lexer("/\\/\\d/"); var tokens = lexer.parse(); var i = 0; assertEquals(tokens[i].index, 0); @@ -110,14 +110,14 @@ LexerTest.prototype.testTokenizeRegExpWithEscape = function(){ }; LexerTest.prototype.testIgnoreWhitespace = function(){ - var lexer = new nglr.Lexer("a \t \n \r b"); + var lexer = new Lexer("a \t \n \r b"); var tokens = lexer.parse(); assertEquals(tokens[0].text, 'a'); assertEquals(tokens[1].text, 'b'); }; LexerTest.prototype.testRelation = function(){ - var lexer = new nglr.Lexer("! == != < > <= >="); + var lexer = new Lexer("! == != < > <= >="); var tokens = lexer.parse(); assertEquals(tokens[0].text, '!'); assertEquals(tokens[1].text, '=='); @@ -129,7 +129,7 @@ LexerTest.prototype.testRelation = function(){ }; LexerTest.prototype.testStatements = function(){ - var lexer = new nglr.Lexer("a;b;"); + var lexer = new Lexer("a;b;"); var tokens = lexer.parse(); assertEquals(tokens[0].text, 'a'); assertEquals(tokens[1].text, ';'); @@ -140,7 +140,7 @@ LexerTest.prototype.testStatements = function(){ ParserTest = TestCase('ParserTest'); ParserTest.prototype.testExpressions = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("-1"), -1); assertEquals(scope.eval("1 + 2.5"), 3.5); assertEquals(scope.eval("1 + -2.5"), -1.5); @@ -151,7 +151,7 @@ ParserTest.prototype.testExpressions = function(){ }; ParserTest.prototype.testComparison = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("false"), false); assertEquals(scope.eval("!true"), false); assertEquals(scope.eval("1==1"), true); @@ -163,14 +163,14 @@ ParserTest.prototype.testComparison = function(){ }; ParserTest.prototype.testLogical = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("0&&2"), 0&&2); assertEquals(scope.eval("0||2"), 0||2); assertEquals(scope.eval("0||1&&2"), 0||1&&2); }; ParserTest.prototype.testString = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("'a' + 'b c'"), "ab c"); }; @@ -182,7 +182,7 @@ ParserTest.prototype.testFilters = function(){ angular.filter.upper = {_case:function(input) { return input.toUpperCase(); }}; - var scope = new nglr.Scope(); + var scope = new Scope(); try { scope.eval("1|nonExistant"); fail(); @@ -196,7 +196,7 @@ ParserTest.prototype.testFilters = function(){ }; ParserTest.prototype.testScopeAccess = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('a', 123); scope.set('b.c', 456); assertEquals(scope.eval("a", scope), 123); @@ -205,16 +205,16 @@ ParserTest.prototype.testScopeAccess = function(){ }; ParserTest.prototype.testGrouping = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("(1+2)*3"), (1+2)*3); }; ParserTest.prototype.testAssignments = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("a=12"), 12); assertEquals(scope.get("a"), 12); - scope = new nglr.Scope(); + scope = new Scope(); assertEquals(scope.eval("x.y.z=123;"), 123); assertEquals(scope.get("x.y.z"), 123); @@ -224,13 +224,13 @@ ParserTest.prototype.testAssignments = function(){ }; ParserTest.prototype.testFunctionCallsNoArgs = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('const', function(a,b){return 123;}); assertEquals(scope.eval("const()"), 123); }; ParserTest.prototype.testFunctionCalls = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('add', function(a,b){ return a+b; }); @@ -238,7 +238,7 @@ ParserTest.prototype.testFunctionCalls = function(){ }; ParserTest.prototype.testCalculationBug = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('taxRate', 8); scope.set('subTotal', 100); assertEquals(scope.eval("taxRate / 100 * subTotal"), 8); @@ -246,7 +246,7 @@ ParserTest.prototype.testCalculationBug = function(){ }; ParserTest.prototype.testArray = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("[]").length, 0); assertEquals(scope.eval("[1, 2]").length, 2); assertEquals(scope.eval("[1, 2]")[0], 1); @@ -254,7 +254,7 @@ ParserTest.prototype.testArray = function(){ }; ParserTest.prototype.testArrayAccess = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("[1][0]"), 1); assertEquals(scope.eval("[[1]][0][0]"), 1); assertEquals(scope.eval("[].length"), 0); @@ -262,33 +262,33 @@ ParserTest.prototype.testArrayAccess = function(){ }; ParserTest.prototype.testObject = function(){ - var scope = new nglr.Scope(); - assertEquals(nglr.toJson(scope.eval("{}")), "{}"); - assertEquals(nglr.toJson(scope.eval("{a:'b'}")), '{"a":"b"}'); - assertEquals(nglr.toJson(scope.eval("{'a':'b'}")), '{"a":"b"}'); - assertEquals(nglr.toJson(scope.eval("{\"a\":'b'}")), '{"a":"b"}'); + var scope = new Scope(); + assertEquals(toJson(scope.eval("{}")), "{}"); + assertEquals(toJson(scope.eval("{a:'b'}")), '{"a":"b"}'); + assertEquals(toJson(scope.eval("{'a':'b'}")), '{"a":"b"}'); + assertEquals(toJson(scope.eval("{\"a\":'b'}")), '{"a":"b"}'); }; ParserTest.prototype.testObjectAccess = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals("WC", scope.eval("{false:'WC', true:'CC'}[false]")); }; ParserTest.prototype.testJSON = function(){ - var scope = new nglr.Scope(); - assertEquals(nglr.toJson(scope.eval("[{}]")), "[{}]"); - assertEquals(nglr.toJson(scope.eval("[{a:[]}, {b:1}]")), '[{"a":[]},{"b":1}]'); + var scope = new Scope(); + assertEquals(toJson(scope.eval("[{}]")), "[{}]"); + assertEquals(toJson(scope.eval("[{a:[]}, {b:1}]")), '[{"a":[]},{"b":1}]'); }; ParserTest.prototype.testMultippleStatements = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(scope.eval("a=1;b=3;a+b"), 4); assertEquals(scope.eval(";;1;;"), 1); }; ParserTest.prototype.testParseThrow = function(){ expectAsserts(1); - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('e', 'abc'); try { scope.eval("throw e"); @@ -298,7 +298,7 @@ ParserTest.prototype.testParseThrow = function(){ }; ParserTest.prototype.testMethodsGetDispatchedWithCorrectThis = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); var C = function (){ this.a=123; }; @@ -310,7 +310,7 @@ ParserTest.prototype.testMethodsGetDispatchedWithCorrectThis = function(){ assertEquals(123, scope.eval("obj.getA()")); }; ParserTest.prototype.testMethodsArgumentsGetCorrectThis = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); var C = function (){ this.a=123; }; @@ -326,13 +326,13 @@ ParserTest.prototype.testMethodsArgumentsGetCorrectThis = function(){ }; ParserTest.prototype.testObjectPointsToScopeValue = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('a', "abc"); assertEquals("abc", scope.eval("{a:a}").a); }; ParserTest.prototype.testFieldAccess = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); var fn = function(){ return {name:'misko'}; }; @@ -341,14 +341,14 @@ ParserTest.prototype.testFieldAccess = function(){ }; ParserTest.prototype.testArrayIndexBug = function () { - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('items', [{}, {name:'misko'}]); assertEquals("misko", scope.eval('items[1].name')); }; ParserTest.prototype.testArrayAssignment = function () { - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('items', []); assertEquals("abc", scope.eval('items[1] = "abc"')); @@ -359,30 +359,30 @@ ParserTest.prototype.testArrayAssignment = function () { }; ParserTest.prototype.testFiltersCanBeGrouped = function () { - var scope = new nglr.Scope({name:'MISKO'}); + var scope = new Scope({name:'MISKO'}); assertEquals('misko', scope.eval('n = (name|lowercase)')); assertEquals('misko', scope.eval('n')); }; ParserTest.prototype.testFiltersCanBeGrouped = function () { - var scope = new nglr.Scope({name:'MISKO'}); + var scope = new Scope({name:'MISKO'}); assertEquals('misko', scope.eval('n = (name|lowercase)')); assertEquals('misko', scope.eval('n')); }; ParserTest.prototype.testRemainder = function () { - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(1, scope.eval('1%2')); }; ParserTest.prototype.testSumOfUndefinedIsNotUndefined = function () { - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(1, scope.eval('1+undefined')); assertEquals(1, scope.eval('undefined+1')); }; ParserTest.prototype.testMissingThrowsError = function() { - var scope = new nglr.Scope(); + var scope = new Scope(); try { scope.eval('[].count('); fail(); @@ -392,7 +392,7 @@ ParserTest.prototype.testMissingThrowsError = function() { }; ParserTest.prototype.testItShouldParseOnChangeIntoHashSet = function () { - var scope = new nglr.Scope({count:0}); + var scope = new Scope({count:0}); scope.watch("$anchor.a:count=count+1;$anchor.a:count=count+20;b:count=count+300"); scope.watchListeners["$anchor.a"].listeners[0](); @@ -403,7 +403,7 @@ ParserTest.prototype.testItShouldParseOnChangeIntoHashSet = function () { assertEquals(321, scope.get("count")); }; ParserTest.prototype.testItShouldParseOnChangeBlockIntoHashSet = function () { - var scope = new nglr.Scope({count:0}); + var scope = new Scope({count:0}); var listeners = {a:[], b:[]}; scope.watch("a:{count=count+1;count=count+20;};b:count=count+300", function(n, fn){listeners[n].push(fn);}); @@ -417,12 +417,12 @@ ParserTest.prototype.testItShouldParseOnChangeBlockIntoHashSet = function () { }; ParserTest.prototype.testItShouldParseEmptyOnChangeAsNoop = function () { - var scope = new nglr.Scope(); + var scope = new Scope(); scope.watch("", function(){fail();}); }; ParserTest.prototype.testItShouldCreateClosureFunctionWithNoArguments = function () { - var scope = new nglr.Scope(); + var scope = new Scope(); var fn = scope.eval("{:value}"); scope.set("value", 1); assertEquals(1, fn()); @@ -433,7 +433,7 @@ ParserTest.prototype.testItShouldCreateClosureFunctionWithNoArguments = function }; ParserTest.prototype.testItShouldCreateClosureFunctionWithArguments = function () { - var scope = new nglr.Scope(); + var scope = new Scope(); var fn = scope.eval("{(a):value+a}"); scope.set("value", 1); assertEquals(11, fn(10)); @@ -444,15 +444,14 @@ ParserTest.prototype.testItShouldCreateClosureFunctionWithArguments = function ( }; ParserTest.prototype.testItShouldHaveDefaultArugument = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); var fn = scope.eval("{:$*2}"); assertEquals(4, fn(2)); }; ParserTest.prototype.testReturnFunctionsAreNotBound = function(){ - var scope = new nglr.Scope(); - scope.set("$datastore", new nglr.DataStore()); - scope.entity("Group"); + var scope = new Scope(); + scope.entity("Group", new DataStore()); var Group = scope.get("Group"); assertEquals("eval Group", "function", typeof scope.eval("Group")); assertEquals("direct Group", "function", typeof Group); @@ -460,3 +459,11 @@ ParserTest.prototype.testReturnFunctionsAreNotBound = function(){ assertEquals("direct Group.all", "function", typeof Group.query); }; +ParserTest.prototype.testDoubleNegationBug = function (){ + var scope = new Scope(); + assertEquals(true, scope.eval('true')); + assertEquals(false, scope.eval('!true')); + assertEquals(true, scope.eval('!!true')); + assertEquals('a', scope.eval('{true:"a", false:"b"}[!!true]')); +}; + diff --git a/test/ScenarioSpec.js b/test/ScenarioSpec.js new file mode 100644 index 00000000..2ca1de2f --- /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 c66a2329..b066f0cb 100644 --- a/test/ScopeTest.js +++ b/test/ScopeTest.js @@ -23,13 +23,13 @@ ScopeTest.prototype.testNoScopeDoesNotCauseInfiniteRecursion = function(){ }; ScopeTest.prototype.testScopeEval = function(){ - var scope = new nglr.Scope({b:345}); + var scope = new Scope({b:345}); assertEquals(scope.eval('b = 123'), 123); assertEquals(scope.get('b'), 123); }; ScopeTest.prototype.testScopeFromPrototype = function(){ - var scope = new nglr.Scope({b:123}); + var scope = new Scope({b:123}); scope.eval('a = b'); scope.eval('b = 456'); assertEquals(scope.get('a'), 123); @@ -37,32 +37,32 @@ ScopeTest.prototype.testScopeFromPrototype = function(){ }; ScopeTest.prototype.testSetScopeGet = function(){ - var scope = new nglr.Scope(); - scope.set('a', 987); + var scope = new Scope(); + assertEquals(987, scope.set('a', 987)); assertEquals(scope.get('a'), 987); assertEquals(scope.eval('a'), 987); }; ScopeTest.prototype.testGetChain = function(){ - var scope = new nglr.Scope({a:{b:987}}); + var scope = new Scope({a:{b:987}}); assertEquals(scope.get('a.b'), 987); assertEquals(scope.eval('a.b'), 987); }; ScopeTest.prototype.testGetUndefinedChain = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); assertEquals(typeof scope.get('a.b'), 'undefined'); }; ScopeTest.prototype.testSetChain = function(){ - var scope = new nglr.Scope({a:{}}); + var scope = new Scope({a:{}}); scope.set('a.b', 987); assertEquals(scope.get('a.b'), 987); assertEquals(scope.eval('a.b'), 987); }; ScopeTest.prototype.testSetGetOnChain = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('a.b', 987); assertEquals(scope.get('a.b'), 987); assertEquals(scope.eval('a.b'), 987); @@ -70,7 +70,7 @@ ScopeTest.prototype.testSetGetOnChain = function(){ ScopeTest.prototype.testGlobalFunctionAccess =function(){ window['scopeAddTest'] = function (a, b) {return a+b;}; - var scope = new nglr.Scope({window:window}); + var scope = new Scope({window:window}); assertEquals(scope.eval('window.scopeAddTest(1,2)'), 3); scope.set('add', function (a, b) {return a+b;}); @@ -82,7 +82,7 @@ ScopeTest.prototype.testGlobalFunctionAccess =function(){ ScopeTest.prototype.testValidationEval = function(){ expectAsserts(4); - var scope = new nglr.Scope(); + var scope = new Scope(); angular.validator.testValidator = function(value, expect){ assertEquals(scope, this.scope); return value == expect ? null : "Error text"; @@ -96,7 +96,7 @@ ScopeTest.prototype.testValidationEval = function(){ ScopeTest.prototype.testCallingNonExistantMethodShouldProduceFriendlyException = function() { expectAsserts(1); - var scope = new nglr.Scope({obj:{}}); + var scope = new Scope({obj:{}}); try { scope.eval("obj.iDontExist()"); fail(); @@ -106,7 +106,7 @@ ScopeTest.prototype.testCallingNonExistantMethodShouldProduceFriendlyException = }; ScopeTest.prototype.testAccessingWithInvalidPathShouldThrowError = function() { - var scope = new nglr.Scope(); + var scope = new Scope(); try { scope.get('a.{{b}}'); fail(); @@ -116,25 +116,25 @@ ScopeTest.prototype.testAccessingWithInvalidPathShouldThrowError = function() { }; ScopeTest.prototype.testItShouldHave$parent = function() { - var parent = new nglr.Scope({}, "ROOT"); - var child = new nglr.Scope(parent.state); + var parent = new Scope({}, "ROOT"); + var child = new Scope(parent.state); assertSame("parent", child.state.$parent, parent.state); assertSame("root", child.state.$root, parent.state); }; ScopeTest.prototype.testItShouldHave$root = function() { - var scope = new nglr.Scope({}, "ROOT"); + var scope = new Scope({}, "ROOT"); assertSame(scope.state.$root, scope.state); }; ScopeTest.prototype.testItShouldBuildPathOnUndefined = function(){ - var scope = new nglr.Scope({}, "ROOT"); + var scope = new Scope({}, "ROOT"); scope.setEval("a.$b.c", 1); assertJsonEquals({$b:{c:1}}, scope.get("a")); }; ScopeTest.prototype.testItShouldMapUnderscoreFunctions = function(){ - var scope = new nglr.Scope({}, "ROOT"); + var scope = new Scope({}, "ROOT"); scope.set("a", [1,2,3]); assertEquals('function', typeof scope.get("a.$size")); scope.eval("a.$includeIf(4,true)"); diff --git a/test/ServerTest.js b/test/ServerTest.js index d1f662f9..02fab84c 100644 --- a/test/ServerTest.js +++ b/test/ServerTest.js @@ -1,7 +1,7 @@ ServerTest = TestCase("ServerTest"); ServerTest.prototype.testBreakLargeRequestIntoPackets = function() { var log = ""; - var server = new nglr.Server("http://server", function(url){ + var server = new Server("http://server", function(url){ log += "|" + url; }); server.maxSize = 30; @@ -10,7 +10,7 @@ ServerTest.prototype.testBreakLargeRequestIntoPackets = function() { assertEquals(200, code); assertEquals("response", r); }); - nglr.uuid0("response"); + angularCallbacks.uuid0("response"); assertEquals( "|http://server/$/uuid0/2/1?h=eyJtIjoiUE9TVCIsInAiOnt9LCJ1Ij" + "|http://server/$/uuid0/2/2?h=oiL2RhdGEvZGF0YWJhc2UifQ==", @@ -18,7 +18,7 @@ ServerTest.prototype.testBreakLargeRequestIntoPackets = function() { }; ServerTest.prototype.testItShouldEncodeUsingUrlRules = function() { - var server = new nglr.Server("http://server"); + var server = new Server("http://server"); assertEquals("fn5-fn5-", server.base64url("~~~~~~")); assertEquals("fn5_fn5_", server.base64url("~~\u007f~~\u007f")); }; @@ -28,14 +28,14 @@ FrameServerTest = TestCase("FrameServerTest"); FrameServerTest.prototype = { testRead:function(){ var window = {name:'$DATASET:"MyData"'}; - var server = new nglr.FrameServer(window); + var server = new FrameServer(window); server.read(); assertEquals("MyData", server.data); }, testWrite:function(){ var window = {}; - var server = new nglr.FrameServer(window); - server.data = "TestData" + var server = new FrameServer(window); + server.data = "TestData"; server.write(); assertEquals('$DATASET:"TestData"', window.name); } diff --git a/test/UsersTest.js b/test/UsersTest.js index c808885c..f0ff545a 100644 --- a/test/UsersTest.js +++ b/test/UsersTest.js @@ -10,10 +10,10 @@ UsersTest.prototype = { testItShouldFetchCurrentUser:function(){ expectAsserts(5); var user; - var users = new nglr.Users({request:function(method, url, request, callback){ + var users = new Users({request:function(method, url, request, callback){ assertEquals("GET", method); assertEquals("/account.json", url); - assertEquals("{}", nglr.toJson(request)); + assertEquals("{}", toJson(request)); callback(200, {$status_code:200, user:{name:'misko'}}); }}); users.fetchCurrentUser(function(u){ diff --git a/test/WidgetsTest.js b/test/WidgetsTest.js index a245abda..c0a2d082 100644 --- a/test/WidgetsTest.js +++ b/test/WidgetsTest.js @@ -2,8 +2,8 @@ WidgetTest = TestCase('WidgetTest'); WidgetTest.prototype.testRequired = function () { var view = $(''); - var scope = new nglr.Scope({$invalidWidgets:[]}); - var cntl = new nglr.TextController(view[0], 'a'); + var scope = new Scope({$invalidWidgets:[]}); + var cntl = new TextController(view[0], 'a'); cntl.updateView(scope); assertTrue(view.hasClass('ng-validation-error')); assertEquals("Required Value", view.attr('ng-error')); @@ -15,8 +15,8 @@ WidgetTest.prototype.testRequired = function () { WidgetTest.prototype.testValidator = function () { var view = $(''); - var scope = new nglr.Scope({$invalidWidgets:[]}); - var cntl = new nglr.TextController(view[0], 'a'); + var scope = new Scope({$invalidWidgets:[]}); + var cntl = new TextController(view[0], 'a'); angular.validator.testValidator = function(value, expect){ return value == expect ? null : "Error text"; }; @@ -43,8 +43,8 @@ WidgetTest.prototype.testValidator = function () { WidgetTest.prototype.testRequiredValidator = function () { var view = $(''); - var scope = new nglr.Scope({$invalidWidgets:[]}); - var cntl = new nglr.TextController(view[0], 'a'); + var scope = new Scope({$invalidWidgets:[]}); + var cntl = new TextController(view[0], 'a'); angular.validator.testValidator = function(value, expect){ return value == expect ? null : "Error text"; }; @@ -67,29 +67,29 @@ WidgetTest.prototype.testRequiredValidator = function () { delete angular.validator['testValidator']; }; -TextController = TestCase("TextController"); +TextControllerTest = TestCase("TextControllerTest"); -TextController.prototype.testDatePicker = function() { +TextControllerTest.prototype.testDatePicker = function() { var input = $(''); - input.data('scope', new nglr.Scope()); + input.data('scope', new Scope()); var body = $(document.body); body.append(input); - var binder = new nglr.Binder(input[0], new nglr.WidgetFactory()); + var binder = new Binder(input[0], new WidgetFactory()); assertTrue('before', input.data('datepicker') === undefined); binder.compile(); assertTrue('after', input.data('datepicker') !== null); assertTrue(body.html(), input.hasClass('hasDatepicker')); }; -RepeaterUpdater = TestCase("RepeaterUpdater"); +RepeaterUpdaterTest = TestCase("RepeaterUpdaterTest"); -RepeaterUpdater.prototype.testRemoveThenAdd = function() { +RepeaterUpdaterTest.prototype.testRemoveThenAdd = function() { var view = $("
        "); var template = function () { return $("
      • "); }; - var repeater = new nglr.RepeaterUpdater(view.find("span"), "a in b", template, ""); - var scope = new nglr.Scope(); + var repeater = new RepeaterUpdater(view.find("span"), "a in b", template, ""); + var scope = new Scope(); scope.set('b', [1,2]); repeater.updateView(scope); @@ -102,14 +102,14 @@ RepeaterUpdater.prototype.testRemoveThenAdd = function() { assertEquals(1, view.find("li").size()); }; -RepeaterUpdater.prototype.testShouldBindWidgetOnRepeaterClone = function(){ +RepeaterUpdaterTest.prototype.testShouldBindWidgetOnRepeaterClone = function(){ //fail(); }; -RepeaterUpdater.prototype.testShouldThrowInformativeSyntaxError= function(){ +RepeaterUpdaterTest.prototype.testShouldThrowInformativeSyntaxError= function(){ expectAsserts(1); try { - var repeater = new nglr.RepeaterUpdater(null, "a=b"); + var repeater = new RepeaterUpdater(null, "a=b"); } catch (e) { assertEquals("Expected ng-repeat in form of 'item in collection' but got 'a=b'.", e); } @@ -118,17 +118,17 @@ RepeaterUpdater.prototype.testShouldThrowInformativeSyntaxError= function(){ SelectControllerTest = TestCase("SelectControllerTest"); SelectControllerTest.prototype.testShouldUpdateModelNullOnNothingSelected = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); var view = {selectedIndex:-1, options:[]}; - var cntl = new nglr.SelectController(view, 'abc'); + var cntl = new SelectController(view, 'abc'); cntl.updateModel(scope); assertNull(scope.get('abc')); }; SelectControllerTest.prototype.testShouldUpdateModelWhenNothingSelected = function(){ - var scope = new nglr.Scope(); + var scope = new Scope(); var view = {value:'123'}; - var cntl = new nglr.SelectController(view, 'abc'); + var cntl = new SelectController(view, 'abc'); cntl.updateView(scope); assertEquals("123", scope.get('abc')); }; @@ -137,8 +137,8 @@ BindUpdaterTest = TestCase("BindUpdaterTest"); BindUpdaterTest.prototype.testShouldDisplayNothingForUndefined = function () { var view = $(''); - var controller = new nglr.BindUpdater(view[0], "{{a}}"); - var scope = new nglr.Scope(); + var controller = new BindUpdater(view[0], "{{a}}"); + var scope = new Scope(); scope.set('a', undefined); controller.updateView(scope); @@ -151,20 +151,20 @@ BindUpdaterTest.prototype.testShouldDisplayNothingForUndefined = function () { BindUpdaterTest.prototype.testShouldDisplayJsonForNonStrings = function () { var view = $(''); - var controller = new nglr.BindUpdater(view[0], "{{obj}}"); + var controller = new BindUpdater(view[0], "{{obj}}"); - controller.updateView(new nglr.Scope({obj:[]})); + controller.updateView(new Scope({obj:[]})); assertEquals("[]", view.text()); - controller.updateView(new nglr.Scope({obj:{text:'abc'}})); - assertEquals('abc', nglr.fromJson(view.text()).text); + controller.updateView(new Scope({obj:{text:'abc'}})); + assertEquals('abc', fromJson(view.text()).text); }; BindUpdaterTest.prototype.testShouldInsertHtmlNode = function () { var view = $(''); - var controller = new nglr.BindUpdater(view[0], "&{{obj}}"); - var scope = new nglr.Scope(); + var controller = new BindUpdater(view[0], "&{{obj}}"); + var scope = new Scope(); scope.set("obj", $('
        myDiv
        ')[0]); controller.updateView(scope); @@ -174,8 +174,8 @@ BindUpdaterTest.prototype.testShouldInsertHtmlNode = function () { BindUpdaterTest.prototype.testShouldDisplayTextMethod = function () { var view = $('
        '); - var controller = new nglr.BindUpdater(view[0], "{{obj}}"); - var scope = new nglr.Scope(); + var controller = new BindUpdater(view[0], "{{obj}}"); + var scope = new Scope(); scope.set("obj", new angular.filter.Meta({text:function(){return "abc";}})); controller.updateView(scope); @@ -187,13 +187,13 @@ BindUpdaterTest.prototype.testShouldDisplayTextMethod = function () { scope.set("obj", {text:"123"}); controller.updateView(scope); - assertEquals("123", nglr.fromJson(view.text()).text); + assertEquals("123", fromJson(view.text()).text); }; BindUpdaterTest.prototype.testShouldDisplayHtmlMethod = function () { var view = $('
        '); - var controller = new nglr.BindUpdater(view[0], "{{obj}}"); - var scope = new nglr.Scope(); + var controller = new BindUpdater(view[0], "{{obj}}"); + var scope = new Scope(); scope.set("obj", new angular.filter.Meta({html:function(){return "a
        b
        c";}})); controller.updateView(scope); @@ -205,13 +205,13 @@ BindUpdaterTest.prototype.testShouldDisplayHtmlMethod = function () { scope.set("obj", {html:"123"}); controller.updateView(scope); - assertEquals("123", nglr.fromJson(view.text()).html); + assertEquals("123", fromJson(view.text()).html); }; BindUpdaterTest.prototype.testUdateBoolean = function() { var view = $('
        '); - var controller = new nglr.BindUpdater(view[0], "{{true}}, {{false}}"); - controller.updateView(new nglr.Scope()); + var controller = new BindUpdater(view[0], "{{true}}, {{false}}"); + controller.updateView(new Scope()); assertEquals('true, false', view.text()); }; @@ -219,26 +219,25 @@ BindAttrUpdaterTest = TestCase("BindAttrUpdaterTest"); BindAttrUpdaterTest.prototype.testShouldLoadBlankImageWhenBindingIsUndefined = function () { var view = $(''); - var controller = new nglr.BindAttrUpdater(view[0], {src: '{{imageUrl}}'}); + var controller = new BindAttrUpdater(view[0], {src: '{{imageUrl}}'}); - var scope = new nglr.Scope(); + var scope = new Scope(); scope.set('imageUrl', undefined); - scope.set('config.server', 'http://server'); + scope.set('$config.blankImage', 'http://server/blank.gif'); controller.updateView(scope); - assertEquals("http://server/images/blank.gif", view.attr('src')); + assertEquals("http://server/blank.gif", view.attr('src')); }; -RepeaterUpdaterTest = TestCase("RepeaterUpdaterTest"); RepeaterUpdaterTest.prototype.testShouldNotDieWhenRepeatExpressionIsNull = function() { - var rep = new nglr.RepeaterUpdater(null, "$item in items", null, null); - var scope = new nglr.Scope(); + var rep = new RepeaterUpdater(null, "$item in items", null, null); + var scope = new Scope(); scope.set('items', undefined); rep.updateView(scope); }; RepeaterUpdaterTest.prototype.testShouldIterateOverKeys = function() { - var rep = new nglr.RepeaterUpdater(null, "($k,_v) in items", null, null); + var rep = new RepeaterUpdater(null, "($k,_v) in items", null, null); assertEquals("items", rep.iteratorExp); assertEquals("_v", rep.valueExp); assertEquals("$k", rep.keyExp); @@ -247,14 +246,14 @@ RepeaterUpdaterTest.prototype.testShouldIterateOverKeys = function() { EvalUpdaterTest = TestCase("EvalUpdaterTest"); EvalUpdaterTest.prototype.testEvalThrowsException = function(){ var view = $('
        '); - var eval = new nglr.EvalUpdater(view[0], 'undefined()'); + var eval = new EvalUpdater(view[0], 'undefined()'); - eval.updateView(new nglr.Scope()); + eval.updateView(new Scope()); assertTrue(!!view.attr('ng-error')); assertTrue(view.hasClass('ng-exception')); eval.exp = "1"; - eval.updateView(new nglr.Scope()); + eval.updateView(new Scope()); assertFalse(!!view.attr('ng-error')); assertFalse(view.hasClass('ng-exception')); }; @@ -262,8 +261,8 @@ EvalUpdaterTest.prototype.testEvalThrowsException = function(){ RadioControllerTest = TestCase("RadioController"); RadioControllerTest.prototype.testItShouldTreatTrueStringAsBoolean = function () { var view = $(''); - var radio = new nglr.RadioController(view[0], 'select'); - var scope = new nglr.Scope({select:true}); + var radio = new RadioController(view[0], 'select'); + var scope = new Scope({select:true}); radio.updateView(scope); assertTrue(view[0].checked); }; diff --git a/test/XSitePostTest.js b/test/XSitePostTest.js deleted file mode 100644 index 8a3e4d6f..00000000 --- a/test/XSitePostTest.js +++ /dev/null @@ -1,47 +0,0 @@ -XSitePost = TestCase("XSitePost"); - -var e = function(text){ return Base64.encode(text); }; - -XSitePost.prototype.testMessageReceived = function () { - expectAsserts(4); - var xPost = new nglr.XSitePost(); - xPost.baseUrl = "http://getangular.test"; - xPost.post = function(url, request, callback){ - assertEquals('http://getangular.test/url', url); - assertEquals('abc', request.a); - assertEquals('xyz', request.x); - }; - xPost.incomingFragment('#id;0;1;'+e('/url')+':a:'+e('abc')+':x:'+e('xyz')); - assertEquals('{}', nglr.toJson(xPost.inQueue)); -}; - -XSitePost.prototype.testMessageReceivedInParts = function () { - expectAsserts(5); - var xPost = new nglr.XSitePost(); - xPost.baseUrl = "http://getangular.test"; - xPost.post = function(url, request, callback){ - assertEquals('http://getangular.test/url', url); - assertEquals('abc', request.a); - assertEquals('xyz', request.x); - }; - xPost.incomingFragment('#id;1;2;:x:'+e('xyz')); - assertNotSame('{}', nglr.toJson(xPost.inQueue)); - xPost.incomingFragment('#id;0;2;'+e('/url')+':a:'+e('abc')); - assertEquals('{}', nglr.toJson(xPost.inQueue)); -}; - -XSitePost.prototype.testPostResponsIsEnqueued = function () { - var xPost = new nglr.XSitePost(); - xPost.maxMsgSize = 11; - xPost.response("id", "response", "status"); - - assertEquals('["id:0:2:cmVzcG9uc2U","id:1:2:="]', - nglr.toJson(xPost.outQueue)); -}; - -XSitePost.prototype.testPush = function () { - var window = {}; - var xPost = new nglr.XSitePost(window); - xPost.response("id", "response", "status"); - assertEquals('id:0:1:cmVzcG9uc2U=', xPost.outQueue[0]); -}; diff --git a/test/formsTest.js b/test/formsTest.js deleted file mode 100644 index e834e938..00000000 --- a/test/formsTest.js +++ /dev/null @@ -1,22 +0,0 @@ -nglrTest = TestCase('nglrTest'); - -nglrTest.prototype.testShiftBind = function(){ - expectAsserts(3); - nglr.shiftBind('this', function(target, arg) { - assertEquals(this, 'this'); - assertEquals(target, 'target'); - assertEquals(arg, 'arg'); - }).apply('target', ['arg']); -}; - -nglrTest.prototype.testBind = function(){ - expectAsserts(2); - nglr.bind('this', function(arg) { - assertEquals(this, 'this'); - assertEquals(arg, 'arg'); - }).apply('XXX', ['arg']); -}; - - - - diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js index 5fca3524..8fac7598 100644 --- a/test/testabilityPatch.js +++ b/test/testabilityPatch.js @@ -6,13 +6,19 @@ HIDDEN = jQuery.browser.msie ? ' style="display: none; "' : ' style="display: none;"'; -nglr.msie = jQuery.browser.msie; -nglr.alert = function(msg) {jstestdriver.console.log("ALERT: " + msg);}; +msie = jQuery.browser.msie; +alert = function(msg) {jstestdriver.console.log("ALERT: " + msg);}; function noop(){} jstd = jstestdriver; +swfobject = { + createSwf:function(){ + fail("must mock out swfobject.createSwf in test."); + } +}; + function html(content) { return jQuery("
        ").html(content); } @@ -29,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; }; @@ -44,7 +50,7 @@ jQuery.fn.sortedHtml = function() { var toString = function(index, node) { node = node || this; if (node.nodeName == "#text") { - html += nglr.escapeHtml(node.nodeValue); + html += escapeHtml(node.nodeValue); } else { html += '<' + node.nodeName.toLowerCase(); var attributes = node.attributes || []; @@ -83,14 +89,14 @@ jQuery.fn.sortedHtml = function() { }; function encode64(obj){ - return Base64.encode(nglr.toJson(obj)); + return Base64.encode(toJson(obj)); } function decode64(base64){ - return nglr.fromJson(Base64.decode(base64)); + return fromJson(Base64.decode(base64)); } -nglr.Loader.prototype.configureJQueryPlugins(); +configureJQueryPlugins(); function assertHidden(node) { var display = node.css('display'); @@ -104,7 +110,7 @@ function assertVisible(node) { } function assertJsonEquals(expected, actual) { - assertEquals(nglr.toJson(expected), nglr.toJson(actual)); + assertEquals(toJson(expected), toJson(actual)); } function assertUndefined(value) { @@ -112,7 +118,7 @@ function assertUndefined(value) { } function assertDefined(value) { - assertTrue(nglr.toJson(value), !!value); + assertTrue(toJson(value), !!value); } function assertThrows(error, fn){ @@ -126,4 +132,4 @@ function assertThrows(error, fn){ fail("Expecting exception, none thrown"); } assertEquals(error, exception); -} \ No newline at end of file +}