=R&&(!b.match(/^(get|post|head|put|delete|options)$/i)||
76 | !Q.XMLHttpRequest))return new Q.ActiveXObject("Microsoft.XMLHTTP");if(Q.XMLHttpRequest)return new Q.XMLHttpRequest;throw x("$httpBackend")("noxhr");}function Vd(){this.$get=["$browser","$window","$document",function(b,a,c){return we(b,ve,b.defer,a.angular.callbacks,c[0])}]}function we(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),g=null;f.type="text/javascript";f.src=a;f.async=!0;g=function(a){Za(f,"load",g);Za(f,"error",g);e.body.removeChild(f);f=null;var k=-1,s="unknown";a&&("load"!==
77 | a.type||d[b].called||(a={type:"error"}),s=a.type,k="error"===a.type?404:200);c&&c(k,s)};rb(f,"load",g);rb(f,"error",g);8>=R&&(f.onreadystatechange=function(){z(f.readyState)&&/loaded|complete/.test(f.readyState)&&(f.onreadystatechange=null,g({type:"load"}))});e.body.appendChild(f);return g}var g=-1;return function(e,m,h,l,n,p,q,s){function L(){C=g;I&&I();w&&w.abort()}function v(a,d,e,f,g){K&&c.cancel(K);I=w=null;0===d&&(d=e?200:"file"==ua(m).protocol?404:0);a(1223===d?204:d,e,f,g||"");b.$$completeOutstandingRequest(y)}
78 | var C;b.$$incOutstandingRequestCount();m=m||b.url();if("jsonp"==N(e)){var O="_"+(d.counter++).toString(36);d[O]=function(a){d[O].data=a;d[O].called=!0};var I=f(m.replace("JSON_CALLBACK","angular.callbacks."+O),O,function(a,b){v(l,a,d[O].data,"",b);d[O]=y})}else{var w=a(e);w.open(e,m,!0);r(n,function(a,b){A(a)&&w.setRequestHeader(b,a)});w.onreadystatechange=function(){if(w&&4==w.readyState){var a=null,b=null,c="";C!==g&&(a=w.getAllResponseHeaders(),b="response"in w?w.response:w.responseText);C===g&&
79 | 10>R||(c=w.statusText);v(l,C||w.status,b,a,c)}};q&&(w.withCredentials=!0);if(s)try{w.responseType=s}catch(da){if("json"!==s)throw da;}w.send(h||null)}if(0=k&&(n.resolve(q),l(p.$$intervalId),delete e[p.$$intervalId]);s||b.$apply()},g);e[p.$$intervalId]=n;return p}var e={};d.cancel=
82 | function(b){return b&&b.$$intervalId in e?(e[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete e[b.$$intervalId],!0):!1};return d}]}function bd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),
83 | SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function Qb(b){b=b.split("/");for(var a=b.length;a--;)b[a]=
84 | jb(b[a]);return b.join("/")}function zc(b,a,c){b=ua(b,c);a.$$protocol=b.protocol;a.$$host=b.hostname;a.$$port=Z(b.port)||xe[b.protocol]||null}function Ac(b,a,c){var d="/"!==b.charAt(0);d&&(b="/"+b);b=ua(b,c);a.$$path=decodeURIComponent(d&&"/"===b.pathname.charAt(0)?b.pathname.substring(1):b.pathname);a.$$search=ec(b.search);a.$$hash=decodeURIComponent(b.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function qa(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function cb(b){var a=
85 | b.indexOf("#");return-1==a?b:b.substr(0,a)}function Rb(b){return b.substr(0,cb(b).lastIndexOf("/")+1)}function Bc(b,a){this.$$html5=!0;a=a||"";var c=Rb(b);zc(b,this,b);this.$$parse=function(a){var e=qa(c,a);if(!z(e))throw Sb("ipthprfx",a,c);Ac(e,this,b);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Cb(this.$$search),b=this.$$hash?"#"+jb(this.$$hash):"";this.$$url=Qb(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$rewrite=function(d){var e;
86 | if((e=qa(b,d))!==t)return d=e,(e=qa(a,e))!==t?c+(qa("/",e)||e):b+d;if((e=qa(c,d))!==t)return c+e;if(c==d+"/")return c}}function Tb(b,a){var c=Rb(b);zc(b,this,b);this.$$parse=function(d){var e=qa(b,d)||qa(c,d),e="#"==e.charAt(0)?qa(a,e):this.$$html5?e:"";if(!z(e))throw Sb("ihshprfx",d,a);Ac(e,this,b);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Cb(this.$$search),e=this.$$hash?
87 | "#"+jb(this.$$hash):"";this.$$url=Qb(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$rewrite=function(a){if(cb(b)==cb(a))return a}}function Ub(b,a){this.$$html5=!0;Tb.apply(this,arguments);var c=Rb(b);this.$$rewrite=function(d){var e;if(b==cb(d))return d;if(e=qa(c,d))return b+a+e;if(c===d+"/")return c};this.$$compose=function(){var c=Cb(this.$$search),e=this.$$hash?"#"+jb(this.$$hash):"";this.$$url=Qb(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function sb(b){return function(){return this[b]}}
88 | function Cc(b,a){return function(c){if(D(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Wd(){var b="",a=!1;this.hashPrefix=function(a){return A(a)?(b=a,this):b};this.html5Mode=function(b){return A(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,f){function g(a){c.$broadcast("$locationChangeSuccess",k.absUrl(),a)}var k,m,h=d.baseHref(),l=d.url(),n;a?(n=l.substring(0,l.indexOf("/",l.indexOf("//")+2))+(h||"/"),m=e.history?Bc:Ub):(n=
89 | cb(l),m=Tb);k=new m(n,"#"+b);k.$$parse(k.$$rewrite(l));var p=/^\s*(javascript|mailto):/i;f.on("click",function(a){if(!a.ctrlKey&&!a.metaKey&&2!=a.which){for(var e=u(a.target);"a"!==N(e[0].nodeName);)if(e[0]===f[0]||!(e=e.parent())[0])return;var g=e.prop("href");T(g)&&"[object SVGAnimatedString]"===g.toString()&&(g=ua(g.animVal).href);if(!p.test(g)){if(m===Ub){var h=e.attr("href")||e.attr("xlink:href");if(h&&0>h.indexOf("://"))if(g="#"+b,"/"==h[0])g=n+g+h;else if("#"==h[0])g=n+g+(k.path()||"/")+h;
90 | else{var l=k.path().split("/"),h=h.split("/");2!==l.length||l[1]||(l.length=1);for(var q=0;qe?Dc(d[0],d[1],d[2],d[3],d[4],c,a):function(b,f){var g=0,k;do k=Dc(d[g++],d[g++],d[g++],d[g++],d[g++],c,a)(b,f),f=t,b=k;while(ga)for(b in h++,e)e.hasOwnProperty(b)&&!d.hasOwnProperty(b)&&(r--,delete e[b])}else e!==d&&(e=d,h++);return h},function(){n?(n=!1,b(d,d,c)):b(d,g,c);if(k)if(T(d))if(fb(d)){g=Array(d.length);for(var a=0;at&&(u=4-t,W[u]||(W[u]=[]),J=P(d.exp)?"fn: "+(d.exp.name||d.exp.toString()):d.exp,
110 | J+="; newVal: "+ta(f)+"; oldVal: "+ta(g),W[u].push(J));else if(d===c){w=!1;break a}}catch(A){p.$$phase=null,e(A)}if(!(k=K.$$childHead||K!==this&&K.$$nextSibling))for(;K!==this&&!(k=K.$$nextSibling);)K=K.$parent}while(K=k);if((w||h.length)&&!t--)throw p.$$phase=null,a("infdig",b,ta(W));}while(w||h.length);for(p.$$phase=null;l.length;)try{l.shift()()}catch(x){e(x)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this!==p&&(r(this.$$listenerCount,
111 | Bb(null,l,this)),a.$$childHead==this&&(a.$$childHead=this.$$nextSibling),a.$$childTail==this&&(a.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=null,this.$$listeners={},this.$$watchers=this.$$asyncQueue=this.$$postDigestQueue=[],this.$destroy=this.$digest=this.$apply=y,this.$on=
112 | this.$watch=function(){return y})}},$eval:function(a,b){return f(a)(this,b)},$evalAsync:function(a){p.$$phase||p.$$asyncQueue.length||g.defer(function(){p.$$asyncQueue.length&&p.$digest()});this.$$asyncQueue.push({scope:this,expression:a})},$$postDigest:function(a){this.$$postDigestQueue.push(a)},$apply:function(a){try{return m("$apply"),this.$eval(a)}catch(b){e(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw e(c),c;}}},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=
113 | c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){c[Qa(c,b)]=null;l(e,1,a)}},$emit:function(a,b){var c=[],d,f=this,g=!1,k={name:a,targetScope:f,stopPropagation:function(){g=!0},preventDefault:function(){k.defaultPrevented=!0},defaultPrevented:!1},h=[k].concat(Aa.call(arguments,1)),m,l;do{d=f.$$listeners[a]||c;k.currentScope=f;m=0;for(l=d.length;mc.msieDocumentMode)throw wa("iequirks");var e=ga(fa);e.isEnabled=function(){return b};e.trustAs=d.trustAs;e.getTrusted=d.getTrusted;e.valueOf=d.valueOf;b||(e.trustAs=e.getTrusted=function(a,b){return b},
120 | e.valueOf=Ga);e.parseAs=function(b,c){var d=a(c);return d.literal&&d.constant?d:function(a,c){return e.getTrusted(b,d(a,c))}};var f=e.parseAs,g=e.getTrusted,k=e.trustAs;r(fa,function(a,b){var c=N(b);e[Ya("parse_as_"+c)]=function(b){return f(a,b)};e[Ya("get_trusted_"+c)]=function(b){return g(a,b)};e[Ya("trust_as_"+c)]=function(b){return k(a,b)}});return e}]}function ce(){this.$get=["$window","$document",function(b,a){var c={},d=Z((/android (\d+)/.exec(N((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||
121 | {}).userAgent),f=a[0]||{},g=f.documentMode,k,m=/^(Moz|webkit|O|ms)(?=[A-Z])/,h=f.body&&f.body.style,l=!1,n=!1;if(h){for(var p in h)if(l=m.exec(p)){k=l[0];k=k.substr(0,1).toUpperCase()+k.substr(1);break}k||(k="WebkitOpacity"in h&&"webkit");l=!!("transition"in h||k+"Transition"in h);n=!!("animation"in h||k+"Animation"in h);!d||l&&n||(l=z(f.body.style.webkitTransition),n=z(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hashchange:"onhashchange"in b&&(!g||7<
122 | g),hasEvent:function(a){if("input"==a&&9==R)return!1;if(D(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:Wa(),vendorPrefix:k,transitions:l,animations:n,android:d,msie:R,msieDocumentMode:g}}]}function ee(){this.$get=["$rootScope","$browser","$q","$exceptionHandler",function(b,a,c,d){function e(e,k,m){var h=c.defer(),l=h.promise,n=A(m)&&!m;k=a.defer(function(){try{h.resolve(e())}catch(a){h.reject(a),d(a)}finally{delete f[l.$$timeoutId]}n||b.$apply()},k);l.$$timeoutId=k;f[k]=h;
123 | return l}var f={};e.cancel=function(b){return b&&b.$$timeoutId in f?(f[b.$$timeoutId].reject("canceled"),delete f[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return e}]}function ua(b,a){var c=b;R&&(V.setAttribute("href",c),c=V.href);V.setAttribute("href",c);return{href:V.href,protocol:V.protocol?V.protocol.replace(/:$/,""):"",host:V.host,search:V.search?V.search.replace(/^\?/,""):"",hash:V.hash?V.hash.replace(/^#/,""):"",hostname:V.hostname,port:V.port,pathname:"/"===V.pathname.charAt(0)?V.pathname:
124 | "/"+V.pathname}}function Pb(b){b=z(b)?ua(b):b;return b.protocol===Hc.protocol&&b.host===Hc.host}function fe(){this.$get=$(Q)}function mc(b){function a(d,e){if(T(d)){var f={};r(d,function(b,c){f[c]=a(c,b)});return f}return b.factory(d+c,e)}var c="Filter";this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+c)}}];a("currency",Ic);a("date",Jc);a("filter",Ae);a("json",Be);a("limitTo",Ce);a("lowercase",De);a("number",Kc);a("orderBy",Lc);a("uppercase",Ee)}function Ae(){return function(b,
125 | a,c){if(!H(b))return b;var d=typeof c,e=[];e.check=function(a){for(var b=0;bb;b=Math.abs(b);var g=b+"",k="",m=[],h=!1;if(-1!==g.indexOf("e")){var l=g.match(/([\d\.]+)e(-?)(\d+)/);l&&"-"==l[2]&&
128 | l[3]>e+1?(g="0",b=0):(k=g,h=!0)}if(h)0b)&&(k=b.toFixed(e));else{g=(g.split(Nc)[1]||"").length;D(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);b=(""+b).split(Nc);g=b[0];b=b[1]||"";var l=0,n=a.lgSize,p=a.gSize;if(g.length>=n+p)for(l=g.length-n,h=0;hb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Xb(e,a,d)}}function ub(b,a){return function(c,d){var e=c["get"+b](),f=Ia(a?"SHORT"+b:b);return d[f][e]}}function Jc(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,k=b[8]?a.setUTCFullYear:
130 | a.setFullYear,m=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Z(b[9]+b[10]),g=Z(b[9]+b[11]));k.call(a,Z(b[1]),Z(b[2])-1,Z(b[3]));f=Z(b[4]||0)-f;g=Z(b[5]||0)-g;k=Z(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));m.call(a,f,g,k,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var f="",g=[],k,m;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;z(c)&&(c=Fe.test(c)?Z(c):a(c));Ab(c)&&(c=new Date(c));if(!sa(c))return c;
131 | for(;e;)(m=Ge.exec(e))?(g=g.concat(Aa.call(m,1)),e=g.pop()):(g.push(e),e=null);r(g,function(a){k=He[a];f+=k?k(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return f}}function Be(){return function(b){return ta(b,!0)}}function Ce(){return function(b,a){if(!H(b)&&!z(b))return b;a=Infinity===Math.abs(Number(a))?Number(a):Z(a);if(z(b))return a?0<=a?b.slice(0,a):b.slice(a,b.length):"";var c=[],d,e;a>b.length?a=b.length:a<-b.length&&(a=-b.length);0a||37<=a&&40>=a)||q()});if(e.hasEvent("paste"))a.on("paste cut",q)}a.on("change",n);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)};var s=c.ngPattern;s&&((e=s.match(/^\/(.*)\/([gim]*)$/))?(s=RegExp(e[1],e[2]),e=function(a){return ra(d,
138 | "pattern",d.$isEmpty(a)||s.test(a),a)}):e=function(c){var e=b.$eval(s);if(!e||!e.test)throw x("ngPattern")("noregexp",s,e,ha(a));return ra(d,"pattern",d.$isEmpty(c)||e.test(c),c)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var r=Z(c.ngMinlength);e=function(a){return ra(d,"minlength",d.$isEmpty(a)||a.length>=r,a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var v=Z(c.ngMaxlength);e=function(a){return ra(d,"maxlength",d.$isEmpty(a)||a.length<=v,a)};d.$parsers.push(e);
139 | d.$formatters.push(e)}}function Yb(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;dR?function(b){b=b.nodeName?b:b[0];return b.scopeName&&"HTML"!=b.scopeName?Ia(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName};var Wa=function(){if(A(Wa.isActive_))return Wa.isActive_;var b=!(!X.querySelector("[ng-csp]")&&!X.querySelector("[data-ng-csp]"));
143 | if(!b)try{new Function("")}catch(a){b=!0}return Wa.isActive_=b},Yc=/[A-Z]/g,ad={full:"1.2.23",major:1,minor:2,dot:23,codeName:"superficial-malady"};S.expando="ng339";var $a=S.cache={},ne=1,rb=Q.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},Za=Q.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)};S._data=function(b){return this.cache[b[this.expando]]||{}};var ie=/([\:\-\_]+(.))/g,
144 | je=/^moz([A-Z])/,Hb=x("jqLite"),ke=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Ib=/<|?\w+;/,le=/<([\w:]+)/,me=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ba={option:[1,'"],thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};ba.optgroup=ba.option;ba.tbody=ba.tfoot=ba.colgroup=ba.caption=ba.thead;ba.th=
145 | ba.td;var La=S.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===X.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),S(Q).on("load",a))},toString:function(){var b=[];r(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?u(this[b]):u(this[this.length+b])},length:0,push:Ke,sort:[].sort,splice:[].splice},ob={};r("multiple selected checked disabled readOnly required open".split(" "),function(b){ob[N(b)]=b});var rc={};r("input select option textarea button form details".split(" "),
146 | function(b){rc[Ia(b)]=!0});r({data:Mb,removeData:Lb},function(b,a){S[a]=b});r({data:Mb,inheritedData:nb,scope:function(b){return u.data(b,"$scope")||nb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return u.data(b,"$isolateScope")||u.data(b,"$isolateScopeNoTemplate")},controller:oc,injector:function(b){return nb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Nb,css:function(b,a,c){a=Ya(a);if(A(c))b.style[a]=c;else{var d;8>=R&&(d=b.currentStyle&&b.currentStyle[a],
147 | ""===d&&(d="auto"));d=d||b.style[a];8>=R&&(d=""===d?t:d);return d}},attr:function(b,a,c){var d=N(a);if(ob[d])if(A(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||y).specified?d:t;else if(A(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(A(c))b[a]=c;else return b[a]},text:function(){function b(b,d){var e=a[b.nodeType];if(D(d))return e?b[e]:"";b[e]=d}var a=[];9>R?(a[1]=
148 | "innerText",a[3]="nodeValue"):a[1]=a[3]="textContent";b.$dv="";return b}(),val:function(b,a){if(D(a)){if("SELECT"===Ma(b)&&b.multiple){var c=[];r(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(D(a))return b.innerHTML;for(var c=0,d=b.childNodes;c":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Pe={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},Wb=function(a){this.options=a};Wb.prototype=
161 | {constructor:Wb,lex:function(a){this.text=a;this.index=0;this.ch=t;this.lastCh=":";for(this.tokens=[];this.index=a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=A(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw ka("lexerr",a,c,this.text);
164 | },readNumber:function(){for(var a="",c=this.index;this.index","<=",">="))a=this.binaryFn(a,c.fn,this.relational());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.fn,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.fn,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(db.ZERO,a.fn,this.unary()):(a=this.expect("!"))?this.unaryFn(a.fn,this.unary()):
175 | this.primary()},fieldAccess:function(a){var c=this,d=this.expect().text,e=Ec(d,this.options,this.text);return B(function(c,d,k){return e(k||a(c,d))},{assign:function(e,g,k){(k=a(e,k))||a.assign(e,k={});return tb(k,d,g,c.text,c.options)}})},objectIndex:function(a){var c=this,d=this.expression();this.consume("]");return B(function(e,f){var g=a(e,f),k=d(e,f),m;ja(k,c.text);if(!g)return t;(g=Oa(g[k],c.text))&&(g.then&&c.options.unwrapPromises)&&(m=g,"$$v"in g||(m.$$v=t,m.then(function(a){m.$$v=a})),g=
176 | g.$$v);return g},{assign:function(e,f,g){var k=ja(d(e,g),c.text);(g=Oa(a(e,g),c.text))||a.assign(e,g={});return g[k]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());while(this.expect(","))}this.consume(")");var e=this;return function(f,g){for(var k=[],m=c?c(f,g):f,h=0;ha.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Xb(Math[0=R&&(c.href||c.name||c.$set("href",""),a.append(X.createComment("IE fix")));if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){var f="[object SVGAnimatedString]"===ya.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}),Fb={};r(ob,function(a,
181 | c){if("multiple"!=a){var d=na("ng-"+c);Fb[d]=function(){return{priority:100,link:function(a,f,g){a.$watch(g[d],function(a){g.$set(c,!!a)})}}}}});r(["src","srcset","href"],function(a){var c=na("ng-"+a);Fb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,k=a;"href"===a&&"[object SVGAnimatedString]"===ya.call(e.prop("href"))&&(k="xlinkHref",f.$attr[k]="xlink:href",g=null);f.$observe(c,function(c){c?(f.$set(k,c),R&&g&&e.prop(g,f[k])):"href"===a&&f.$set(k,null)})}}}});var xb={$addControl:y,
182 | $removeControl:y,$setValidity:y,$setDirty:y,$setPristine:y};Oc.$inject=["$element","$attrs","$scope","$animate"];var Rc=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Oc,compile:function(){return{pre:function(a,e,f,g){if(!f.action){var k=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};rb(e[0],"submit",k);e.on("$destroy",function(){c(function(){Za(e[0],"submit",k)},0,!1)})}var m=e.parent().controller("form"),h=f.name||f.ngForm;h&&tb(a,
183 | h,g,h);if(m)e.on("$destroy",function(){m.$removeControl(g);h&&tb(a,h,t,h);B(g,xb)})}}}}}]},ed=Rc(),rd=Rc(!0),Qe=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,Re=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,Se=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,Sc={text:zb,number:function(a,c,d,e,f,g){zb(a,c,d,e,f,g);e.$parsers.push(function(a){var c=e.$isEmpty(a);if(c||Se.test(a))return e.$setValidity("number",!0),""===
184 | a?null:c?a:parseFloat(a);e.$setValidity("number",!1);return t});Ie(e,"number",Te,null,e.$$validityState);e.$formatters.push(function(a){return e.$isEmpty(a)?"":""+a});d.min&&(a=function(a){var c=parseFloat(d.min);return ra(e,"min",e.$isEmpty(a)||a>=c,a)},e.$parsers.push(a),e.$formatters.push(a));d.max&&(a=function(a){var c=parseFloat(d.max);return ra(e,"max",e.$isEmpty(a)||a<=c,a)},e.$parsers.push(a),e.$formatters.push(a));e.$formatters.push(function(a){return ra(e,"number",e.$isEmpty(a)||Ab(a),a)})},
185 | url:function(a,c,d,e,f,g){zb(a,c,d,e,f,g);a=function(a){return ra(e,"url",e.$isEmpty(a)||Qe.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,f,g){zb(a,c,d,e,f,g);a=function(a){return ra(e,"email",e.$isEmpty(a)||Re.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){D(d.name)&&c.attr("name",gb());c.on("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",
186 | e.$render)},checkbox:function(a,c,d,e){var f=d.ngTrueValue,g=d.ngFalseValue;z(f)||(f=!0);z(g)||(g=!1);c.on("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return a!==f};e.$formatters.push(function(a){return a===f});e.$parsers.push(function(a){return a?f:g})},hidden:y,button:y,submit:y,reset:y,file:y},Te=["badInput"],jc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,
187 | e,f,g){g&&(Sc[N(f.type)]||Sc.text)(d,e,f,g,c,a)}}}],wb="ng-valid",vb="ng-invalid",Pa="ng-pristine",yb="ng-dirty",Ue=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate",function(a,c,d,e,f,g){function k(a,c){c=c?"-"+kb(c,"-"):"";g.removeClass(e,(a?vb:wb)+c);g.addClass(e,(a?wb:vb)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var m=f(d.ngModel),
188 | h=m.assign;if(!h)throw x("ngModel")("nonassign",d.ngModel,ha(e));this.$render=y;this.$isEmpty=function(a){return D(a)||""===a||null===a||a!==a};var l=e.inheritedData("$formController")||xb,n=0,p=this.$error={};e.addClass(Pa);k(!0);this.$setValidity=function(a,c){p[a]!==!c&&(c?(p[a]&&n--,n||(k(!0),this.$valid=!0,this.$invalid=!1)):(k(!1),this.$invalid=!0,this.$valid=!1,n++),p[a]=!c,k(c,a),l.$setValidity(a,c,this))};this.$setPristine=function(){this.$dirty=!1;this.$pristine=!0;g.removeClass(e,yb);g.addClass(e,
189 | Pa)};this.$setViewValue=function(d){this.$viewValue=d;this.$pristine&&(this.$dirty=!0,this.$pristine=!1,g.removeClass(e,Pa),g.addClass(e,yb),l.$setDirty());r(this.$parsers,function(a){d=a(d)});this.$modelValue!==d&&(this.$modelValue=d,h(a,d),r(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}}))};var q=this;a.$watch(function(){var c=m(a);if(q.$modelValue!==c){var d=q.$formatters,e=d.length;for(q.$modelValue=c;e--;)c=d[e](c);q.$viewValue!==c&&(q.$viewValue=c,q.$render())}return c})}],Gd=
190 | function(){return{require:["ngModel","^?form"],controller:Ue,link:function(a,c,d,e){var f=e[0],g=e[1]||xb;g.$addControl(f);a.$on("$destroy",function(){g.$removeControl(f)})}}},Id=$({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),kc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var f=function(a){if(d.required&&e.$isEmpty(a))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(f);
191 | e.$parsers.unshift(f);d.$observe("required",function(){f(e.$viewValue)})}}}},Hd=function(){return{require:"ngModel",link:function(a,c,d,e){var f=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){if(!D(a)){var c=[];a&&r(a.split(f),function(a){a&&c.push(aa(a))});return c}});e.$formatters.push(function(a){return H(a)?a.join(", "):t});e.$isEmpty=function(a){return!a||!a.length}}}},Ve=/^(true|false|\d+)$/,Jd=function(){return{priority:100,compile:function(a,c){return Ve.test(c.ngValue)?
192 | function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},jd=xa({compile:function(a){a.addClass("ng-binding");return function(a,d,e){d.data("$binding",e.ngBind);a.$watch(e.ngBind,function(a){d.text(a==t?"":a)})}}}),ld=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],kd=["$sce","$parse",function(a,c){return{compile:function(d){d.addClass("ng-binding");
193 | return function(d,f,g){f.data("$binding",g.ngBindHtml);var k=c(g.ngBindHtml);d.$watch(function(){return(k(d)||"").toString()},function(c){f.html(a.getTrustedHtml(k(d))||"")})}}}}],md=Yb("",!0),od=Yb("Odd",0),nd=Yb("Even",1),pd=xa({compile:function(a,c){c.$set("ngCloak",t);a.removeClass("ng-cloak")}}),qd=[function(){return{scope:!0,controller:"@",priority:500}}],lc={};r("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),
194 | function(a){var c=na("ng-"+a);lc[c]=["$parse",function(d){return{compile:function(e,f){var g=d(f[c]);return function(c,d){d.on(N(a),function(a){c.$apply(function(){g(c,{$event:a})})})}}}}]});var td=["$animate",function(a){return{transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var k,m,h;c.$watch(e.ngIf,function(f){Ta(f)?m||(m=c.$new(),g(m,function(c){c[c.length++]=X.createComment(" end ngIf: "+e.ngIf+" ");k={clone:c};a.enter(c,d.parent(),d)})):(h&&(h.remove(),
195 | h=null),m&&(m.$destroy(),m=null),k&&(h=Eb(k.clone),a.leave(h,function(){h=null}),k=null))})}}}],ud=["$http","$templateCache","$anchorScroll","$animate","$sce",function(a,c,d,e,f){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:Ua.noop,compile:function(g,k){var m=k.ngInclude||k.src,h=k.onload||"",l=k.autoscroll;return function(g,k,q,r,L){var v=0,t,u,I,w=function(){u&&(u.remove(),u=null);t&&(t.$destroy(),t=null);I&&(e.leave(I,function(){u=null}),u=I,I=null)};g.$watch(f.parseAsResourceUrl(m),
196 | function(f){var m=function(){!A(l)||l&&!g.$eval(l)||d()},q=++v;f?(a.get(f,{cache:c}).success(function(a){if(q===v){var c=g.$new();r.template=a;a=L(c,function(a){w();e.enter(a,null,k,m)});t=c;I=a;t.$emit("$includeContentLoaded");g.$eval(h)}}).error(function(){q===v&&w()}),g.$emit("$includeContentRequested")):(w(),r.template=null)})}}}}],Kd=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){d.html(f.template);a(d.contents())(c)}}}],vd=xa({priority:450,
197 | compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),wd=xa({terminal:!0,priority:1E3}),xd=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,f,g){var k=g.count,m=g.$attr.when&&f.attr(g.$attr.when),h=g.offset||0,l=e.$eval(m)||{},n={},p=c.startSymbol(),q=c.endSymbol(),s=/^when(Minus)?(.+)$/;r(g,function(a,c){s.test(c)&&(l[N(c.replace("when","").replace("Minus","-"))]=f.attr(g.$attr[c]))});r(l,function(a,e){n[e]=c(a.replace(d,p+k+"-"+h+q))});e.$watch(function(){var c=
198 | parseFloat(e.$eval(k));if(isNaN(c))return"";c in l||(c=a.pluralCat(c-h));return n[c](e,f,!0)},function(a){f.text(a)})}}}],yd=["$parse","$animate",function(a,c){var d=x("ngRepeat");return{transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,link:function(e,f,g,k,m){var h=g.ngRepeat,l=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),n,p,q,s,t,v,C={$id:Ka};if(!l)throw d("iexp",h);g=l[1];k=l[2];(l=l[3])?(n=a(l),p=function(a,c,d){v&&(C[v]=a);C[t]=c;C.$index=d;return n(e,
199 | C)}):(q=function(a,c){return Ka(c)},s=function(a){return a});l=g.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!l)throw d("iidexp",g);t=l[3]||l[1];v=l[2];var A={};e.$watchCollection(k,function(a){var g,k,l=f[0],n,C={},J,E,F,x,z,y,H=[];if(fb(a))z=a,n=p||q;else{n=p||s;z=[];for(F in a)a.hasOwnProperty(F)&&"$"!=F.charAt(0)&&z.push(F);z.sort()}J=z.length;k=H.length=z.length;for(g=0;gB;)t.pop().element.remove()}for(;z.length>M;)z.pop()[0].element.remove()}var h;if(!(h=s.match(d)))throw We("iexp",s,ha(f));var l=c(h[2]||h[1]),m=h[4]||h[6],n=h[5],p=c(h[3]||""),r=c(h[2]?h[1]:m),v=c(h[7]),u=h[8]?c(h[8]):null,z=[[{element:f,label:""}]];x&&(a(x)(e),x.removeClass("ng-scope"),x.remove());f.empty();f.on("change",function(){e.$apply(function(){var a,c=v(e)||[],d={},h,l,p,s,w,x,y;if(q)for(l=[],s=0,x=z.length;s<
211 | x;s++)for(a=z[s],p=1,w=a.length;p@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}.ng-hide-add-active,.ng-hide-remove{display:block!important;}');
215 | //# sourceMappingURL=angular.min.js.map
216 |
--------------------------------------------------------------------------------
/demo/custom_template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Notification demo (custom templates)
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Angular ui-notification demo (custom templates)
11 |
12 |
13 |
14 |
15 |
16 |
Custom templates
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
33 |
34 |
42 |
43 |
44 |
45 |
68 |
69 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Notification demo
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Angular ui-notification demo
11 |
12 |
13 |
14 |
15 |
Types of notifications
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
Notification with title
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Custom show delay
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
Using html tags within message and title
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
Change position notification
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
Custom template and scope
62 |
63 |
65 |
66 |
Clicks: {{nClicksLog.length}}
67 |
68 | - {{$index + 1}}. {{l}}
69 |
70 |
71 |
72 |
73 |
74 |
88 |
89 |
90 |
91 |
190 |
191 |
--------------------------------------------------------------------------------
/demo/max_count.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Notification demo
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Angular ui-notification demo
11 |
12 |
13 |
14 |
15 |
Max count of notifications
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
48 |
49 |
--------------------------------------------------------------------------------
/demo/notification_config.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Notification demo (custom configuration)
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Notification demo (custom configuration)
12 |
13 |
14 |
15 |
16 |
Types of notifications
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
101 |
102 |
--------------------------------------------------------------------------------
/demo/notification_kill.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Notification demo (kill message)
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Angular ui-notification demo (kill message)
11 |
12 |
13 |
14 |
15 |
16 |
Kill message
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
67 |
68 |
--------------------------------------------------------------------------------
/demo/notification_priority.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Notification demo (custom configuration)
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Notification demo (custom configuration)
12 |
13 |
14 |
15 |
16 |
Types of notifications
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
69 |
70 |
--------------------------------------------------------------------------------
/demo/notification_replace.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Notification demo (replace messages)
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Notification demo (replace messages)
12 |
13 |
14 |
15 |
16 |
Types of notifications
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
69 |
70 |
--------------------------------------------------------------------------------
/demo/onclose.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Notification demo
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Angular ui-notification demo
11 |
12 |
13 |
14 |
15 |
Types of notifications
16 |
17 |
18 |
19 |
20 |
21 |
{{hasElementClosed}}
22 |
23 |
24 |
25 |
26 |
27 |
55 |
56 |
--------------------------------------------------------------------------------
/dist/angular-ui-notification.css:
--------------------------------------------------------------------------------
1 | /**
2 | * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
3 | * @author Alex_Crack
4 | * @version v0.3.6
5 | * @link https://github.com/alexcrack/angular-ui-notification
6 | * @license MIT
7 | */
8 | .ui-notification
9 | {
10 | position: fixed;
11 | z-index: 9999;
12 |
13 | width: 300px;
14 |
15 | -webkit-transition: all ease .5s;
16 | -o-transition: all ease .5s;
17 | transition: all ease .5s;
18 |
19 | color: #fff;
20 | border-radius: 0;
21 | background: #337ab7;
22 | box-shadow: 5px 5px 10px rgba(0, 0, 0, .3);
23 | }
24 | .ui-notification.clickable
25 | {
26 | cursor: pointer;
27 | }
28 | .ui-notification.clickable:hover
29 | {
30 | opacity: .7;
31 | }
32 | .ui-notification.killed
33 | {
34 | -webkit-transition: opacity ease 1s;
35 | -o-transition: opacity ease 1s;
36 | transition: opacity ease 1s;
37 |
38 | opacity: 0;
39 | }
40 | .ui-notification > h3
41 | {
42 | font-size: 14px;
43 | font-weight: bold;
44 |
45 | display: block;
46 |
47 | margin: 10px 10px 0 10px;
48 | padding: 0 0 5px 0;
49 |
50 | text-align: left;
51 |
52 | border-bottom: 1px solid rgba(255, 255, 255, .3);
53 | }
54 | .ui-notification a
55 | {
56 | color: #fff;
57 | }
58 | .ui-notification a:hover
59 | {
60 | text-decoration: underline;
61 | }
62 | .ui-notification > .message
63 | {
64 | margin: 10px 10px 10px 10px;
65 | }
66 | .ui-notification.warning
67 | {
68 | color: #fff;
69 | background: #f0ad4e;
70 | }
71 | .ui-notification.error
72 | {
73 | color: #fff;
74 | background: #d9534f;
75 | }
76 | .ui-notification.success
77 | {
78 | color: #fff;
79 | background: #5cb85c;
80 | }
81 | .ui-notification.info
82 | {
83 | color: #fff;
84 | background: #5bc0de;
85 | }
86 |
--------------------------------------------------------------------------------
/dist/angular-ui-notification.js:
--------------------------------------------------------------------------------
1 | /**
2 | * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
3 | * @author Alex_Crack
4 | * @version v0.3.6
5 | * @link https://github.com/alexcrack/angular-ui-notification
6 | * @license MIT
7 | */
8 | angular.module('ui-notification', []);
9 |
10 | angular.module('ui-notification').provider('Notification', function () {
11 |
12 | this.options = {
13 | delay: 5000,
14 | startTop: 10,
15 | startRight: 10,
16 | verticalSpacing: 10,
17 | horizontalSpacing: 10,
18 | positionX: 'right',
19 | positionY: 'top',
20 | replaceMessage: false,
21 | templateUrl: 'angular-ui-notification.html',
22 | onClose: undefined,
23 | onClick: undefined,
24 | closeOnClick: true,
25 | maxCount: 0, // 0 - Infinite
26 | container: 'body',
27 | priority: 10
28 | };
29 |
30 | this.setOptions = function (options) {
31 | if (!angular.isObject(options)) throw new Error("Options should be an object!");
32 | this.options = angular.extend({}, this.options, options);
33 | };
34 |
35 | this.$get = ["$timeout", "$http", "$compile", "$templateCache", "$rootScope", "$injector", "$sce", "$q", "$window", function ($timeout, $http, $compile, $templateCache, $rootScope, $injector, $sce, $q, $window) {
36 | var options = this.options;
37 |
38 | var startTop = options.startTop;
39 | var startRight = options.startRight;
40 | var verticalSpacing = options.verticalSpacing;
41 | var horizontalSpacing = options.horizontalSpacing;
42 | var delay = options.delay;
43 |
44 | var messageElements = [];
45 | var isResizeBound = false;
46 |
47 | var notify = function (args, t) {
48 | var deferred = $q.defer();
49 |
50 | if (typeof args !== 'object' || args === null) {
51 | args = {message: args};
52 | }
53 |
54 | args.scope = args.scope ? args.scope : $rootScope;
55 | args.template = args.templateUrl ? args.templateUrl : options.templateUrl;
56 | args.delay = !angular.isUndefined(args.delay) ? args.delay : delay;
57 | args.type = t || args.type || options.type || '';
58 | args.positionY = args.positionY ? args.positionY : options.positionY;
59 | args.positionX = args.positionX ? args.positionX : options.positionX;
60 | args.replaceMessage = args.replaceMessage ? args.replaceMessage : options.replaceMessage;
61 | args.onClose = args.onClose ? args.onClose : options.onClose;
62 | args.onClick = args.onClick ? args.onClick : options.onClick;
63 | args.closeOnClick = (args.closeOnClick !== null && args.closeOnClick !== undefined) ? args.closeOnClick : options.closeOnClick;
64 | args.container = args.container ? args.container : options.container;
65 | args.priority = args.priority ? args.priority : options.priority;
66 |
67 | var template = $templateCache.get(args.template);
68 |
69 | if (template) {
70 | processNotificationTemplate(template);
71 | } else {
72 | // load it via $http only if it isn't default template and template isn't exist in template cache
73 | // cache:true means cache it for later access.
74 | $http.get(args.template, {cache: true})
75 | .then(function (response) {
76 | processNotificationTemplate(response.data);
77 | })
78 | .catch(function (data) {
79 | throw new Error('Template (' + args.template + ') could not be loaded. ' + data);
80 | });
81 | }
82 |
83 |
84 | function processNotificationTemplate(template) {
85 |
86 | var scope = args.scope.$new();
87 | scope.message = $sce.trustAsHtml(args.message);
88 | scope.title = $sce.trustAsHtml(args.title);
89 | scope.t = args.type.substr(0, 1);
90 | scope.delay = args.delay;
91 | scope.onClose = args.onClose;
92 | scope.onClick = args.onClick;
93 |
94 | var priorityCompareTop = function (a, b) {
95 | return a._priority - b._priority;
96 | };
97 |
98 | var priorityCompareBtm = function (a, b) {
99 | return b._priority - a._priority;
100 | };
101 |
102 | var reposite = function () {
103 | var j = 0;
104 | var k = 0;
105 | var lastTop = startTop;
106 | var lastRight = startRight;
107 | var lastPosition = [];
108 |
109 | if (args.positionY === 'top') {
110 | messageElements.sort(priorityCompareTop);
111 | } else if (args.positionY === 'bottom') {
112 | messageElements.sort(priorityCompareBtm);
113 | }
114 |
115 | for (var i = messageElements.length - 1; i >= 0; i--) {
116 | var element = messageElements[i];
117 | if (args.replaceMessage && i < messageElements.length - 1) {
118 | element.addClass('killed');
119 | continue;
120 | }
121 | var elHeight = parseInt(element[0].offsetHeight);
122 | var elWidth = parseInt(element[0].offsetWidth);
123 | var position = lastPosition[element._positionY + element._positionX];
124 |
125 | if ((top + elHeight) > window.innerHeight) {
126 | position = startTop;
127 | k++;
128 | j = 0;
129 | }
130 |
131 | var top = (lastTop = position ? (j === 0 ? position : position + verticalSpacing) : startTop);
132 | var right = lastRight + (k * (horizontalSpacing + elWidth));
133 |
134 | element.css(element._positionY, top + 'px');
135 | if (element._positionX === 'center') {
136 | element.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px');
137 | } else {
138 | element.css(element._positionX, right + 'px');
139 | }
140 |
141 | lastPosition[element._positionY + element._positionX] = top + elHeight;
142 |
143 | if (options.maxCount > 0 && messageElements.length > options.maxCount && i === 0) {
144 | element.scope().kill(true);
145 | }
146 |
147 | j++;
148 | }
149 | };
150 |
151 | var templateElement = $compile(template)(scope);
152 | templateElement._positionY = args.positionY;
153 | templateElement._positionX = args.positionX;
154 | templateElement._priority = args.priority;
155 | templateElement.addClass(args.type);
156 |
157 | var closeEvent = function (e) {
158 | e = e.originalEvent || e;
159 | if (e.type === 'click' || e.propertyName === 'opacity' && e.elapsedTime >= 1) {
160 |
161 | if (scope.onClose) {
162 | scope.$apply(scope.onClose(templateElement));
163 | }
164 |
165 | if (e.type === 'click')
166 | if (scope.onClick) {
167 | scope.$apply(scope.onClick(templateElement));
168 | }
169 |
170 | templateElement.remove();
171 | messageElements.splice(messageElements.indexOf(templateElement), 1);
172 | scope.$destroy();
173 | reposite();
174 | }
175 | };
176 |
177 | if (args.closeOnClick) {
178 | templateElement.addClass('clickable');
179 | templateElement.bind('click', closeEvent);
180 | }
181 |
182 | templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd', closeEvent);
183 |
184 | if (angular.isNumber(args.delay)) {
185 | $timeout(function () {
186 | templateElement.addClass('killed');
187 | }, args.delay);
188 | }
189 |
190 | setCssTransitions('none');
191 |
192 | angular.element(document.querySelector(args.container)).append(templateElement);
193 | var offset = -(parseInt(templateElement[0].offsetHeight) + 50);
194 | templateElement.css(templateElement._positionY, offset + "px");
195 | messageElements.push(templateElement);
196 |
197 | if (args.positionX == 'center') {
198 | var elWidth = parseInt(templateElement[0].offsetWidth);
199 | templateElement.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px');
200 | }
201 |
202 | $timeout(function () {
203 | setCssTransitions('');
204 | });
205 |
206 | function setCssTransitions(value) {
207 | ['-webkit-transition', '-o-transition', 'transition'].forEach(function (prefix) {
208 | templateElement.css(prefix, value);
209 | });
210 | }
211 |
212 | scope._templateElement = templateElement;
213 |
214 | scope.kill = function (isHard) {
215 | if (isHard) {
216 | if (scope.onClose) {
217 | scope.$apply(scope.onClose(scope._templateElement));
218 | }
219 |
220 | messageElements.splice(messageElements.indexOf(scope._templateElement), 1);
221 | scope._templateElement.remove();
222 | scope.$destroy();
223 | $timeout(reposite);
224 | } else {
225 | scope._templateElement.addClass('killed');
226 | }
227 | };
228 |
229 | $timeout(reposite);
230 |
231 | if (!isResizeBound) {
232 | angular.element($window).bind('resize', function (e) {
233 | $timeout(reposite);
234 | });
235 | isResizeBound = true;
236 | }
237 |
238 | deferred.resolve(scope);
239 |
240 | }
241 |
242 | return deferred.promise;
243 | };
244 |
245 | notify.primary = function (args) {
246 | return this(args, 'primary');
247 | };
248 | notify.error = function (args) {
249 | return this(args, 'error');
250 | };
251 | notify.success = function (args) {
252 | return this(args, 'success');
253 | };
254 | notify.info = function (args) {
255 | return this(args, 'info');
256 | };
257 | notify.warning = function (args) {
258 | return this(args, 'warning');
259 | };
260 |
261 | notify.clearAll = function () {
262 | angular.forEach(messageElements, function (element) {
263 | element.addClass('killed');
264 | });
265 | };
266 |
267 | return notify;
268 | }];
269 | });
270 |
271 | angular.module("ui-notification").run(["$templateCache", function($templateCache) {$templateCache.put("angular-ui-notification.html","");}]);
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var less = require('gulp-less');
3 | var minifyCSS = require('gulp-minify-css');
4 | var csscomb = require('gulp-csscomb');
5 | var ngAnnotate = require('gulp-ng-annotate');
6 | var uglify = require('gulp-uglify');
7 | var jshint = require('gulp-jshint');
8 | var rename = require('gulp-rename');
9 | var header = require('gulp-header');
10 | var templateCache = require('gulp-angular-templatecache');
11 | var minifyHtml = require("gulp-minify-html");
12 | var concat = require('gulp-concat');
13 | var addsrc = require('gulp-add-src');
14 | var order = require("gulp-order");
15 | var protractor = require("gulp-protractor").protractor;
16 |
17 | var pkg = require('./package.json');
18 | var banner = ['/**',
19 | ' * <%= pkg.name %> - <%= pkg.description %>',
20 | ' * @author <%= pkg.author %>',
21 | ' * @version v<%= pkg.version %>',
22 | ' * @link <%= pkg.homepage %>',
23 | ' * @license <%= pkg.license %>',
24 | ' */',
25 | ''].join('\n');
26 |
27 | // ==== Styles
28 | gulp.task('styles', function() {
29 | gulp.src('src/build.less')
30 | .pipe(less({
31 | strictMath: true
32 | }))
33 | .pipe(csscomb())
34 | .pipe(header(banner, { pkg : pkg }))
35 | .pipe(rename({
36 | basename: 'angular-ui-notification'
37 | }))
38 | .pipe(gulp.dest('dist'))
39 | .pipe(minifyCSS())
40 | .pipe(rename({
41 | suffix: '.min'
42 | }))
43 | .pipe(header(banner, { pkg : pkg }))
44 | .pipe(gulp.dest('dist'))
45 | .pipe(gulp.dest('demo'));
46 | });
47 |
48 | // ====== Templates
49 | gulp.task('templates', function() {
50 | gulp.src(['*.html'], {cwd: 'src'})
51 | .pipe(minifyHtml({
52 | empty: true,
53 | spare: true,
54 | quotes: true
55 | }))
56 | .pipe(templateCache({
57 | module: 'ui-notification'
58 | }))
59 | .pipe(rename('angular-ui-notification.templates.js'))
60 | .pipe(gulp.dest("build"));
61 | });
62 |
63 | gulp.task('service', function() {
64 | gulp.src(['src/*.js'])
65 | .pipe(jshint())
66 | .pipe(jshint.reporter('default'))
67 | .pipe(jshint.reporter('fail'))
68 | .pipe(ngAnnotate())
69 | .pipe(addsrc('build/*.js'))
70 | .pipe(order([
71 | 'src/*.js',
72 | 'build/angular-ui-notification.templates.js'
73 | ]))
74 | .pipe(concat('angular-ui-notification.js'))
75 |
76 | .pipe(header(banner, { pkg : pkg }))
77 | .pipe(gulp.dest('dist'))
78 |
79 | .pipe(uglify())
80 | .pipe(rename({
81 | suffix: '.min'
82 | }))
83 | .pipe(header(banner, { pkg : pkg }))
84 | .pipe(gulp.dest('dist'))
85 | .pipe(gulp.dest('demo'));
86 | });
87 |
88 | // ======
89 | gulp.task('e2eTest', function() {
90 | gulp.src(['./test/**/*_spec.js'])
91 | .pipe(protractor({
92 | configFile: "protractor_conf.js"
93 | }))
94 | .on('error', function(e) {throw e});
95 | });
96 |
97 | gulp.task('tests', ['e2eTest']);
98 | gulp.task('build', ['templates', 'service', 'styles']);
99 | gulp.task('deploy', ['build', 'tests']);
100 |
101 | gulp.task('default', ['deploy'], function() {});
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by alex_crack on 20.11.15.
3 | */
4 | require('./dist/angular-ui-notification.js');
5 | module.exports = 'ui-notification';
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-ui-notification",
3 | "version": "0.3.6",
4 | "description": "Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating",
5 | "main": "index.js",
6 | "scripts": {
7 | "update-chromedriver": "./node_modules/protractor/bin/webdriver-manager update",
8 | "test": "gulp tests"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/alexcrack/angular-ui-notification.git"
13 | },
14 | "keywords": [
15 | "angular",
16 | "notification",
17 | "notify",
18 | "bootstrap"
19 | ],
20 | "author": "Alex_Crack",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/alexcrack/angular-ui-notification/issues"
24 | },
25 | "homepage": "https://github.com/alexcrack/angular-ui-notification",
26 | "devDependencies": {
27 | "chromedriver": "^2.14.1",
28 | "gulp": "^3.8.11",
29 | "gulp-add-src": "^0.2.0",
30 | "gulp-angular-templatecache": "^1.5.0",
31 | "gulp-concat": "^2.5.2",
32 | "gulp-csscomb": "^3.0.3",
33 | "gulp-header": "^1.2.2",
34 | "gulp-jshint": "^1.9.2",
35 | "gulp-less": "^3.0.1",
36 | "gulp-minify-css": "^0.5.1",
37 | "gulp-minify-html": "^1.0.0",
38 | "gulp-ng-annotate": "^0.5.2",
39 | "gulp-order": "^1.1.1",
40 | "gulp-protractor": "0.0.12",
41 | "gulp-rename": "^1.2.0",
42 | "gulp-uglify": "^1.1.0",
43 | "protractor": "^1.8.0"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/protractor_conf.js:
--------------------------------------------------------------------------------
1 | // An example configuration file.
2 | exports.config = {
3 | allScriptsTimeout: 99999,
4 | // Do not start a Selenium Standalone sever - only run this using chrome.
5 | //directConnect: true,
6 | //chromeDriver: './node_modules/protractor/selenium/chromedriver',
7 |
8 | seleniumArgs: ['-browserTimeout=60'],
9 |
10 | // Capabilities to be passed to the webdriver instance.
11 | capabilities: {
12 | 'browserName': 'firefox'
13 | },
14 |
15 | // Spec patterns are relative to the current working directly when
16 | // protractor is called.
17 | specs: ['test/e2e/**/*.spec.js'],
18 |
19 | // Options to be passed to Jasmine-node.
20 | jasmineNodeOpts: {
21 | showColors: true,
22 | defaultTimeoutInterval: 30000,
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/src/angular-ui-notification.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/angular-ui-notification.js:
--------------------------------------------------------------------------------
1 | angular.module('ui-notification', []);
2 |
3 | angular.module('ui-notification').provider('Notification', function () {
4 |
5 | this.options = {
6 | delay: 5000,
7 | startTop: 10,
8 | startRight: 10,
9 | verticalSpacing: 10,
10 | horizontalSpacing: 10,
11 | positionX: 'right',
12 | positionY: 'top',
13 | replaceMessage: false,
14 | templateUrl: 'angular-ui-notification.html',
15 | onClose: undefined,
16 | onClick: undefined,
17 | closeOnClick: true,
18 | maxCount: 0, // 0 - Infinite
19 | container: 'body',
20 | priority: 10
21 | };
22 |
23 | this.setOptions = function (options) {
24 | if (!angular.isObject(options)) throw new Error("Options should be an object!");
25 | this.options = angular.extend({}, this.options, options);
26 | };
27 |
28 | this.$get = function ($timeout, $http, $compile, $templateCache, $rootScope, $injector, $sce, $q, $window) {
29 | var options = this.options;
30 |
31 | var startTop = options.startTop;
32 | var startRight = options.startRight;
33 | var verticalSpacing = options.verticalSpacing;
34 | var horizontalSpacing = options.horizontalSpacing;
35 | var delay = options.delay;
36 |
37 | var messageElements = [];
38 | var isResizeBound = false;
39 |
40 | var notify = function (args, t) {
41 | var deferred = $q.defer();
42 |
43 | if (typeof args !== 'object' || args === null) {
44 | args = {message: args};
45 | }
46 |
47 | args.scope = args.scope ? args.scope : $rootScope;
48 | args.template = args.templateUrl ? args.templateUrl : options.templateUrl;
49 | args.delay = !angular.isUndefined(args.delay) ? args.delay : delay;
50 | args.type = t || args.type || options.type || '';
51 | args.positionY = args.positionY ? args.positionY : options.positionY;
52 | args.positionX = args.positionX ? args.positionX : options.positionX;
53 | args.replaceMessage = args.replaceMessage ? args.replaceMessage : options.replaceMessage;
54 | args.onClose = args.onClose ? args.onClose : options.onClose;
55 | args.onClick = args.onClick ? args.onClick : options.onClick;
56 | args.closeOnClick = (args.closeOnClick !== null && args.closeOnClick !== undefined) ? args.closeOnClick : options.closeOnClick;
57 | args.container = args.container ? args.container : options.container;
58 | args.priority = args.priority ? args.priority : options.priority;
59 |
60 | var template = $templateCache.get(args.template);
61 |
62 | if (template) {
63 | processNotificationTemplate(template);
64 | } else {
65 | // load it via $http only if it isn't default template and template isn't exist in template cache
66 | // cache:true means cache it for later access.
67 | $http.get(args.template, {cache: true})
68 | .then(function (response) {
69 | processNotificationTemplate(response.data);
70 | })
71 | .catch(function (data) {
72 | throw new Error('Template (' + args.template + ') could not be loaded. ' + data);
73 | });
74 | }
75 |
76 |
77 | function processNotificationTemplate(template) {
78 |
79 | var scope = args.scope.$new();
80 | scope.message = $sce.trustAsHtml(args.message);
81 | scope.title = $sce.trustAsHtml(args.title);
82 | scope.t = args.type.substr(0, 1);
83 | scope.delay = args.delay;
84 | scope.onClose = args.onClose;
85 | scope.onClick = args.onClick;
86 |
87 | var priorityCompareTop = function (a, b) {
88 | return a._priority - b._priority;
89 | };
90 |
91 | var priorityCompareBtm = function (a, b) {
92 | return b._priority - a._priority;
93 | };
94 |
95 | var reposite = function () {
96 | var j = 0;
97 | var k = 0;
98 | var lastTop = startTop;
99 | var lastRight = startRight;
100 | var lastPosition = [];
101 |
102 | if (args.positionY === 'top') {
103 | messageElements.sort(priorityCompareTop);
104 | } else if (args.positionY === 'bottom') {
105 | messageElements.sort(priorityCompareBtm);
106 | }
107 |
108 | for (var i = messageElements.length - 1; i >= 0; i--) {
109 | var element = messageElements[i];
110 | if (args.replaceMessage && i < messageElements.length - 1) {
111 | element.addClass('killed');
112 | continue;
113 | }
114 | var elHeight = parseInt(element[0].offsetHeight);
115 | var elWidth = parseInt(element[0].offsetWidth);
116 | var position = lastPosition[element._positionY + element._positionX];
117 |
118 | if ((top + elHeight) > window.innerHeight) {
119 | position = startTop;
120 | k++;
121 | j = 0;
122 | }
123 |
124 | var top = (lastTop = position ? (j === 0 ? position : position + verticalSpacing) : startTop);
125 | var right = lastRight + (k * (horizontalSpacing + elWidth));
126 |
127 | element.css(element._positionY, top + 'px');
128 | if (element._positionX === 'center') {
129 | element.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px');
130 | } else {
131 | element.css(element._positionX, right + 'px');
132 | }
133 |
134 | lastPosition[element._positionY + element._positionX] = top + elHeight;
135 |
136 | if (options.maxCount > 0 && messageElements.length > options.maxCount && i === 0) {
137 | element.scope().kill(true);
138 | }
139 |
140 | j++;
141 | }
142 | };
143 |
144 | var templateElement = $compile(template)(scope);
145 | templateElement._positionY = args.positionY;
146 | templateElement._positionX = args.positionX;
147 | templateElement._priority = args.priority;
148 | templateElement.addClass(args.type);
149 |
150 | var closeEvent = function (e) {
151 | e = e.originalEvent || e;
152 | if (e.type === 'click' || e.propertyName === 'opacity' && e.elapsedTime >= 1) {
153 |
154 | if (scope.onClose) {
155 | scope.$apply(scope.onClose(templateElement));
156 | }
157 |
158 | if (e.type === 'click')
159 | if (scope.onClick) {
160 | scope.$apply(scope.onClick(templateElement));
161 | }
162 |
163 | templateElement.remove();
164 | messageElements.splice(messageElements.indexOf(templateElement), 1);
165 | scope.$destroy();
166 | reposite();
167 | }
168 | };
169 |
170 | if (args.closeOnClick) {
171 | templateElement.addClass('clickable');
172 | templateElement.bind('click', closeEvent);
173 | }
174 |
175 | templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd', closeEvent);
176 |
177 | if (angular.isNumber(args.delay)) {
178 | $timeout(function () {
179 | templateElement.addClass('killed');
180 | }, args.delay);
181 | }
182 |
183 | setCssTransitions('none');
184 |
185 | angular.element(document.querySelector(args.container)).append(templateElement);
186 | var offset = -(parseInt(templateElement[0].offsetHeight) + 50);
187 | templateElement.css(templateElement._positionY, offset + "px");
188 | messageElements.push(templateElement);
189 |
190 | if (args.positionX == 'center') {
191 | var elWidth = parseInt(templateElement[0].offsetWidth);
192 | templateElement.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px');
193 | }
194 |
195 | $timeout(function () {
196 | setCssTransitions('');
197 | });
198 |
199 | function setCssTransitions(value) {
200 | ['-webkit-transition', '-o-transition', 'transition'].forEach(function (prefix) {
201 | templateElement.css(prefix, value);
202 | });
203 | }
204 |
205 | scope._templateElement = templateElement;
206 |
207 | scope.kill = function (isHard) {
208 | if (isHard) {
209 | if (scope.onClose) {
210 | scope.$apply(scope.onClose(scope._templateElement));
211 | }
212 |
213 | messageElements.splice(messageElements.indexOf(scope._templateElement), 1);
214 | scope._templateElement.remove();
215 | scope.$destroy();
216 | $timeout(reposite);
217 | } else {
218 | scope._templateElement.addClass('killed');
219 | }
220 | };
221 |
222 | $timeout(reposite);
223 |
224 | if (!isResizeBound) {
225 | angular.element($window).bind('resize', function (e) {
226 | $timeout(reposite);
227 | });
228 | isResizeBound = true;
229 | }
230 |
231 | deferred.resolve(scope);
232 |
233 | }
234 |
235 | return deferred.promise;
236 | };
237 |
238 | notify.primary = function (args) {
239 | return this(args, 'primary');
240 | };
241 | notify.error = function (args) {
242 | return this(args, 'error');
243 | };
244 | notify.success = function (args) {
245 | return this(args, 'success');
246 | };
247 | notify.info = function (args) {
248 | return this(args, 'info');
249 | };
250 | notify.warning = function (args) {
251 | return this(args, 'warning');
252 | };
253 |
254 | notify.clearAll = function () {
255 | angular.forEach(messageElements, function (element) {
256 | element.addClass('killed');
257 | });
258 | };
259 |
260 | return notify;
261 | };
262 | });
263 |
--------------------------------------------------------------------------------
/src/angular-ui-notification.less:
--------------------------------------------------------------------------------
1 | @ui-notification-border-radius: 0px;
2 |
3 | .ui-notification {
4 | border-radius: @ui-notification-border-radius;
5 | position: fixed;
6 | z-index: 9999;
7 | box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3);
8 | width: 300px;
9 | color: @btn-primary-color;
10 | background: @brand-primary;
11 | .transition(all ease 0.5s);
12 | &.clickable {
13 | cursor: pointer;
14 |
15 | &:hover {
16 | opacity: 0.7;
17 | }
18 | }
19 | &.killed {
20 | opacity: 0;
21 | .transition(opacity ease 1s);
22 | }
23 | & > h3 {
24 | display: block;
25 | margin: 10px 10px 0 10px;
26 | padding: 0 0 5px 0;
27 | text-align: left;
28 | font-size: @font-size-base;
29 | font-weight: bold;
30 | border-bottom: 1px solid fadeout(@btn-primary-color, 70%);
31 | }
32 | & a {
33 | color: @btn-primary-color;
34 | &:hover {
35 | text-decoration: underline;
36 | }
37 | }
38 | & > .message {
39 | margin: 10px 10px 10px 10px;
40 | }
41 | &.warning {
42 | color: @btn-warning-color;
43 | background: @brand-warning;
44 | }
45 | &.error {
46 | color: @btn-danger-color;
47 | background: @brand-danger;
48 | }
49 | &.success {
50 | color: @btn-success-color;
51 | background: @brand-success;
52 | }
53 | &.info {
54 | color: @btn-info-color;
55 | background: @brand-info;
56 | }
57 | }
--------------------------------------------------------------------------------
/src/build.less:
--------------------------------------------------------------------------------
1 | @import "../bower_components/bootstrap/less/variables.less";
2 | @import "../bower_components/bootstrap/less/mixins.less";
3 | @import "angular-ui-notification.less";
4 |
--------------------------------------------------------------------------------
/test/e2e/main.spec.js:
--------------------------------------------------------------------------------
1 | describe('E2E: main page', function() {
2 | beforeEach(function() {
3 | browser.ignoreSynchronization = true;
4 | browser.driver.get('http://localhost:8080/index.html');
5 | });
6 |
7 | describe('Buttons exists', function() {
8 | it('should be 15', function() {
9 | expect(element.all(by.css('button.btn')).count()).toBe(17);
10 | });
11 | });
12 |
13 | describe('Show notifications', function() {
14 | it('should be shown notifications', function() {
15 | var buttons = element.all(by.css('button.btn'));
16 | buttons.each(function(button) {
17 | button.click();
18 | });
19 |
20 | var notifications = element.all(by.css('.ui-notification'));
21 | expect(notifications.count()).toBe(buttons.count());
22 | });
23 |
24 | });
25 |
26 | describe('Custom template and scope', function() {
27 | beforeEach(function() {
28 | var notifications = element.all(by.css('.ui-notification'));
29 | notifications.each(function(notification) {
30 | notification.addClass('killed');
31 | });
32 | });
33 |
34 | it('should be the message with custom template', function() {
35 | element(by.css('button.show-custom')).click();
36 | expect(element.all(by.css('div.custom-template')).count()).toBe(1);
37 | });
38 |
39 | it('should trigger click callback in current scope from notification', function(done) {
40 | element(by.css('button.show-custom')).click();
41 |
42 | setTimeout(function() {
43 | element(by.css('a.close-notification')).click();
44 |
45 | setTimeout(function() {
46 | var clicksLog = element.all(by.css('.elements-count li'));
47 | expect(clicksLog.count()).toBe(1);
48 | done();
49 | }, 1000);
50 |
51 | }, 1000);
52 | });
53 | });
54 |
55 | });
56 |
57 | describe("E2E: notification with configuration", function() {
58 | beforeEach(function() {
59 | browser.ignoreSynchronization = true;
60 | browser.driver.get('http://localhost:8080/notification_config.html');
61 | });
62 |
63 | describe('Show notifications', function() {
64 | it('should be shown notifications', function() {
65 | var buttons = element.all(by.css('button.btn'));
66 | buttons.each(function(button) {
67 | button.click();
68 | });
69 |
70 | var notifications = element.all(by.css('.ui-notification'));
71 | expect(notifications.count()).toBe(buttons.count());
72 | });
73 |
74 | });
75 | });
76 |
77 | describe("E2E: replace notifications", function() {
78 | beforeEach(function() {
79 | browser.ignoreSynchronization = true;
80 | browser.driver.get('http://localhost:8080/notification_replace.html');
81 | });
82 |
83 | describe('show all notifications', function() {
84 | it('should leave only one last message', function(done) {
85 | var buttons = element.all(by.css('button.btn'));
86 | buttons.each(function(button) {
87 | button.click();
88 | });
89 |
90 | setTimeout(function() {
91 | var notifications = element.all(by.css('.ui-notification'));
92 | expect(notifications.count()).toEqual(1);
93 | done();
94 | }, 4000);
95 | });
96 | });
97 | });
98 |
99 | describe("E2E: kill notification", function() {
100 | beforeEach(function() {
101 | browser.ignoreSynchronization = true;
102 | browser.driver.get('http://localhost:8080/notification_kill.html');
103 | });
104 |
105 | describe('Show and kill notification', function() {
106 |
107 | it('should kill notification with fadeout', function(done) {
108 | element(by.css('button.btn.kill-soft')).click();
109 |
110 | setTimeout(function() {
111 | var notifications = element.all(by.css('.ui-notification'));
112 | expect(notifications.count()).toEqual(3);
113 | done();
114 | }, 6000);
115 | });
116 |
117 | it('should hard kill notification', function(done) {
118 | element(by.css('button.btn.kill-hard')).click();
119 |
120 | setTimeout(function() {
121 | var notifications = element.all(by.css('.ui-notification'));
122 | expect(notifications.count()).toEqual(3);
123 | done();
124 | }, 6000);
125 | });
126 |
127 | });
128 | });
129 |
130 | describe("E2E: custom templates", function() {
131 | beforeEach(function() {
132 | browser.ignoreSynchronization = true;
133 | browser.driver.get('http://localhost:8080/custom_template.html');
134 | });
135 |
136 | describe('Show custom templated notifications', function() {
137 |
138 | it('should show 4 notifications (2 types of every template)', function() {
139 | var buttons = element.all(by.css('button.btn'));
140 | buttons.each(function(button) {
141 | button.click();
142 | button.click();
143 | });
144 |
145 | expect(element.all(by.css('div.custom-template')).count()).toBe(2);
146 | expect(element.all(by.css('div.custom-template-overriden')).count()).toBe(2);
147 | });
148 |
149 | });
150 | });
151 |
152 |
153 | ddescribe("E2E: call onClose callback", function() {
154 | beforeEach(function() {
155 | browser.ignoreSynchronization = true;
156 | browser.driver.get('http://localhost:8080/onclose.html');
157 | });
158 |
159 | // TODO: Fix this test.
160 | // describe('Change scope variable when notification hs closed', function() {
161 | //
162 | // it('should open and close one notification', function(done) {
163 | // element(by.css('button.btn-primary')).click();
164 | // expect(element.all(by.css('.ui-notification')).count()).toBe(1);
165 | //
166 | // setTimeout(function() {
167 | // expect(element(by.css('#is-closed')).evaluate('hasElementClosed')).toEqual(true);
168 | // done();
169 | // }, 10000);
170 | // });
171 | //
172 | // });
173 |
174 | describe('Do not close on click', function() {
175 |
176 | it('should leave message after clicking', function() {
177 | element(by.css('button.btn-danger')).click();
178 | expect(element.all(by.css('.ui-notification.error')).count()).toBe(1);
179 |
180 | element(by.css('.ui-notification.error')).click();
181 | expect(element.all(by.css('.ui-notification.error')).count()).toBe(1);
182 | });
183 |
184 | });
185 | });
186 |
187 | describe("E2E: Max count", function() {
188 | beforeEach(function() {
189 | browser.ignoreSynchronization = true;
190 | browser.driver.get('http://localhost:8080/max_count.html');
191 | });
192 |
193 | describe('Click many times but messages less than max count', function() {
194 |
195 | it('should click 20 times but messages should be less than 5', function() {
196 | for (var i = 0; i < 20; i++) {
197 | // Click 20 times
198 | element(by.css('button.btn-primary')).click();
199 | }
200 |
201 | expect(element.all(by.css('.ui-notification')).count()).toBe(5);
202 | });
203 |
204 | });
205 | });
--------------------------------------------------------------------------------