/* Minification failed. Returning unminified contents.
(779,166-173): run-time error JS1019: Can't have 'break' outside of loop: break a
 */
/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */
!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=r.isArray(d)))?(e?(e=!1,f=c&&r.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e);return!1}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}return!1}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):C.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\x20\t\r\n\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,M,e),g(f,c,N,e)):(f++,j.call(a,g(f,c,M,e),g(f,c,N,e),g(f,c,M,c.notifyWith))):(d!==M&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),
a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},T=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function U(){this.expando=r.expando+U.uid++}U.uid=1,U.prototype={cache:function(a){var b=a[this.expando];return b||(b={},T(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){r.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(K)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var V=new U,W=new U,X=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Y=/[A-Z]/g;function Z(a){return"true"===a||"false"!==a&&("null"===a?null:a===+a+""?+a:X.test(a)?JSON.parse(a):a)}function $(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Y,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c=Z(c)}catch(e){}W.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return W.hasData(a)||V.hasData(a)},data:function(a,b,c){return W.access(a,b,c)},removeData:function(a,b){W.remove(a,b)},_data:function(a,b,c){return V.access(a,b,c)},_removeData:function(a,b){V.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=W.get(f),1===f.nodeType&&!V.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),$(f,d,e[d])));V.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){W.set(this,a)}):S(this,function(b){var c;if(f&&void 0===b){if(c=W.get(f,a),void 0!==c)return c;if(c=$(f,a),void 0!==c)return c}else this.each(function(){W.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=V.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var _=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,aa=new RegExp("^(?:([+-])=|)("+_+")([a-z%]*)$","i"),ba=["Top","Right","Bottom","Left"],ca=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},da=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function ea(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&aa.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var fa={};function ga(a){var b,c=a.ownerDocument,d=a.nodeName,e=fa[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),fa[d]=e,e)}function ha(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=V.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&ca(d)&&(e[f]=ga(d))):"none"!==c&&(e[f]="none",V.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ha(this,!0)},hide:function(){return ha(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){ca(this)?r(this).show():r(this).hide()})}});var ia=/^(?:checkbox|radio)$/i,ja=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,ka=/^$|\/(?:java|ecma)script/i,la={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};la.optgroup=la.option,la.tbody=la.tfoot=la.colgroup=la.caption=la.thead,la.th=la.td;function ma(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function na(a,b){for(var c=0,d=a.length;c<d;c++)V.set(a[c],"globalEval",!b||V.get(b[c],"globalEval"))}var oa=/<|&#?\w+;/;function pa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(oa.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ja.exec(f)||["",""])[1].toLowerCase(),i=la[h]||la._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=ma(l.appendChild(f),"script"),j&&na(g),c){k=0;while(f=g[k++])ka.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var qa=d.documentElement,ra=/^key/,sa=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ta=/^([^.]*)(?:\.(.+)|)/;function ua(){return!0}function va(){return!1}function wa(){try{return d.activeElement}catch(a){}}function xa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)xa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=va;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(qa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g,h=[],i=b.delegateCount,j=a.target;if(i&&j.nodeType&&!("click"===a.type&&a.button>=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c<i;c++)d=b[c],e=d.selector+" ",void 0===g[e]&&(g[e]=d.needsContext?r(e,this).index(j)>-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i<b.length&&h.push({elem:j,handlers:b.slice(i)}),h},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==wa()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===wa()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&r.nodeName(this,"input"))return this.click(),!1},_default:function(a){return r.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ua:va,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:va,isPropagationStopped:va,isImmediatePropagationStopped:va,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ua,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ua,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ua,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&ra.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&sa.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return xa(this,a,b,c,d)},one:function(a,b,c,d){return xa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=va),this.each(function(){r.event.remove(this,a,c,b)})}});var ya=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,za=/<script|<style|<link/i,Aa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ba=/^true\/(.*)/,Ca=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Da(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Ea(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Fa(a){var b=Ba.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ga(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event.add(b,e,j[e][c])}W.hasData(a)&&(h=W.access(a),i=r.extend({},h),W.set(b,i))}}function Ha(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ia.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ia(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&Aa.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ia(f,b,c,d)});if(m&&(e=pa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(ma(e,"script"),Ea),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,ma(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Fa),l=0;l<i;l++)j=h[l],ka.test(j.type||"")&&!V.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Ca,""),k))}return a}function Ja(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(ma(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&na(ma(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(ya,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=ma(h),f=ma(a),d=0,e=f.length;d<e;d++)Ha(f[d],g[d]);if(b)if(c)for(f=f||ma(a),g=g||ma(h),d=0,e=f.length;d<e;d++)Ga(f[d],g[d]);else Ga(a,h);return g=ma(h,"script"),g.length>0&&na(g,!i&&ma(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ja(this,a,!0)},remove:function(a){return Ja(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.appendChild(a)}})},prepend:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(ma(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!za.test(a)&&!la[(ja.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(ma(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ia(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(ma(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var Ka=/^margin/,La=new RegExp("^("+_+")(?!px)[a-z%]+$","i"),Ma=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",qa.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,qa.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Na(a,b,c){var d,e,f,g,h=a.style;return c=c||Ma(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&La.test(g)&&Ka.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Oa(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Pa=/^(none|table(?!-c[ea]).+)/,Qa={position:"absolute",visibility:"hidden",display:"block"},Ra={letterSpacing:"0",fontWeight:"400"},Sa=["Webkit","Moz","ms"],Ta=d.createElement("div").style;function Ua(a){if(a in Ta)return a;var b=a[0].toUpperCase()+a.slice(1),c=Sa.length;while(c--)if(a=Sa[c]+b,a in Ta)return a}function Va(a,b,c){var d=aa.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Wa(a,b,c,d,e){var f,g=0;for(f=c===(d?"border":"content")?4:"width"===b?1:0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+ba[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+ba[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+ba[f]+"Width",!0,e))):(g+=r.css(a,"padding"+ba[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+ba[f]+"Width",!0,e)));return g}function Xa(a,b,c){var d,e=!0,f=Ma(a),g="border-box"===r.css(a,"boxSizing",!1,f);if(a.getClientRects().length&&(d=a.getBoundingClientRect()[b]),d<=0||null==d){if(d=Na(a,b,f),(d<0||null==d)&&(d=a.style[b]),La.test(d))return d;e=g&&(o.boxSizingReliable()||d===a.style[b]),d=parseFloat(d)||0}return d+Wa(a,b,c||(g?"border":"content"),e,f)+"px"}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Na(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=a.style;return b=r.cssProps[h]||(r.cssProps[h]=Ua(h)||h),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=aa.exec(c))&&e[1]&&(c=ea(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b);return b=r.cssProps[h]||(r.cssProps[h]=Ua(h)||h),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Na(a,b,d)),"normal"===e&&b in Ra&&(e=Ra[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Pa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?Xa(a,b,d):da(a,Qa,function(){return Xa(a,b,d)})},set:function(a,c,d){var e,f=d&&Ma(a),g=d&&Wa(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=aa.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Va(a,c,g)}}}),r.cssHooks.marginLeft=Oa(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Na(a,"marginLeft"))||a.getBoundingClientRect().left-da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+ba[d]+b]=f[d]||f[d-2]||f[0];return e}},Ka.test(a)||(r.cssHooks[a+b].set=Va)}),r.fn.extend({css:function(a,b){return S(this,function(a,b,c){var d,e,f={},g=0;if(r.isArray(b)){for(d=Ma(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function Ya(a,b,c,d,e){return new Ya.prototype.init(a,b,c,d,e)}r.Tween=Ya,Ya.prototype={constructor:Ya,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Ya.propHooks[this.prop];return a&&a.get?a.get(this):Ya.propHooks._default.get(this)},run:function(a){var b,c=Ya.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ya.propHooks._default.set(this),this}},Ya.prototype.init.prototype=Ya.prototype,Ya.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Ya.propHooks.scrollTop=Ya.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Ya.prototype.init,r.fx.step={};var Za,$a,_a=/^(?:toggle|show|hide)$/,ab=/queueHooks$/;function bb(){$a&&(a.requestAnimationFrame(bb),r.fx.tick())}function cb(){return a.setTimeout(function(){Za=void 0}),Za=r.now()}function db(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ba[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function eb(a,b,c){for(var d,e=(hb.tweeners[b]||[]).concat(hb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function fb(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&ca(a),q=V.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],_a.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=V.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ha([a],!0),j=a.style.display||j,k=r.css(a,"display"),ha([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=V.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ha([a],!0),m.done(function(){p||ha([a]),V.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=eb(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function gb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],r.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function hb(a,b,c){var d,e,f=0,g=hb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Za||cb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:Za||cb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(gb(k,j.opts.specialEasing);f<g;f++)if(d=hb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,eb,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}r.Animation=r.extend(hb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return ea(c.elem,a,aa.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(K);for(var c,d=0,e=a.length;d<e;d++)c=a[d],hb.tweeners[c]=hb.tweeners[c]||[],hb.tweeners[c].unshift(b)},prefilters:[fb],prefilter:function(a,b){b?hb.prefilters.unshift(a):hb.prefilters.push(a)}}),r.speed=function(a,b,c){var e=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off||d.hidden?e.duration=0:"number"!=typeof e.duration&&(e.duration in r.fx.speeds?e.duration=r.fx.speeds[e.duration]:e.duration=r.fx.speeds._default),null!=e.queue&&e.queue!==!0||(e.queue="fx"),e.old=e.complete,e.complete=function(){r.isFunction(e.old)&&e.old.call(this),e.queue&&r.dequeue(this,e.queue)},e},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(ca).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=hb(this,r.extend({},a),f);(e||V.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=V.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&ab.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=V.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(db(b,!0),a,d,e)}}),r.each({slideDown:db("show"),slideUp:db("hide"),slideToggle:db("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(Za=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),Za=void 0},r.fx.timer=function(a){r.timers.push(a),a()?r.fx.start():r.timers.pop()},r.fx.interval=13,r.fx.start=function(){$a||($a=a.requestAnimationFrame?a.requestAnimationFrame(bb):a.setInterval(r.fx.tick,r.fx.interval))},r.fx.stop=function(){a.cancelAnimationFrame?a.cancelAnimationFrame($a):a.clearInterval($a),$a=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var ib,jb=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return S(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?ib:void 0)),
void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),ib={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=jb[b]||r.find.attr;jb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=jb[g],jb[g]=e,e=null!=c(a,b,d)?g:null,jb[g]=f),e}});var kb=/^(?:input|select|textarea|button)$/i,lb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):kb.test(a.nodeName)||lb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function mb(a){var b=a.match(K)||[];return b.join(" ")}function nb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,nb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,nb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,nb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=nb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(nb(c))+" ").indexOf(b)>-1)return!0;return!1}});var ob=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(ob,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:mb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d<i;d++)if(c=e[d],(c.selected||d===f)&&!c.disabled&&(!c.parentNode.disabled||!r.nodeName(c.parentNode,"optgroup"))){if(b=r(c).val(),g)return b;h.push(b)}return h},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ia.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,"$1"),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Qb=[],Rb=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Qb.pop()||r.expando+"_"+rb++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Rb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Rb.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Rb,"$1"+e):b.jsonp!==!1&&(b.url+=(sb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Qb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=B.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=pa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=mb(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length};function Sb(a){return r.isWindow(a)?a:9===a.nodeType&&a.defaultView}r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),d.width||d.height?(e=f.ownerDocument,c=Sb(e),b=e.documentElement,{top:d.top+c.pageYOffset-b.clientTop,left:d.left+c.pageXOffset-b.clientLeft}):d):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),r.nodeName(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||qa})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return S(this,function(a,d,e){var f=Sb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Oa(o.pixelPosition,function(a,c){if(c)return c=Na(a,b),La.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return S(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.parseJSON=JSON.parse,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Tb=a.jQuery,Ub=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Ub),b&&a.jQuery===r&&(a.jQuery=Tb),r},b||(a.jQuery=a.$=r),r});
;
(function LTPPolyfills() {
    //polyfill for startsWith
    if (!String.prototype.startsWith) {
        String.prototype.startsWith = function (searchString, position) {
            return this.substr(position || 0, searchString.length) === searchString;
        };
    }

    function imgError(image) {
        image.onerror = "";
        image.src = "//d5ia2wpngn16p.cloudfront.net/assets/ripple.gif";
        return true;
    }

})();;
/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under the MIT license
 */
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){document===a.target||this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);if(this.$element.trigger(g),!g.isDefaultPrevented())return f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=window.SVGElement&&c instanceof window.SVGElement,g=d?{top:0,left:0}:f?null:b.offset(),h={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},i=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,h,i,g)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){
this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);;
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
 * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
 *  */

!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);;
/*
 AngularJS v1.5.8
 (c) 2010-2016 Google, Inc. http://angularjs.org
 License: MIT
*/
(function (C) {
    'use strict'; function N(a) { return function () { var b = arguments[0], d; d = "[" + (a ? a + ":" : "") + b + "] http://errors.angularjs.org/1.5.8/" + (a ? a + "/" : "") + b; for (b = 1; b < arguments.length; b++) { d = d + (1 == b ? "?" : "&") + "p" + (b - 1) + "="; var c = encodeURIComponent, e; e = arguments[b]; e = "function" == typeof e ? e.toString().replace(/ \{[\s\S]*$/, "") : "undefined" == typeof e ? "undefined" : "string" != typeof e ? JSON.stringify(e) : e; d += c(e) } return Error(d) } } function ta(a) {
        if (null == a || Va(a)) return !1; if (L(a) || G(a) || F && a instanceof F) return !0;
        var b = "length" in Object(a) && a.length; return T(b) && (0 <= b && (b - 1 in a || a instanceof Array) || "function" == typeof a.item)
    } function q(a, b, d) {
        var c, e; if (a) if (z(a)) for (c in a) "prototype" == c || "length" == c || "name" == c || a.hasOwnProperty && !a.hasOwnProperty(c) || b.call(d, a[c], c, a); else if (L(a) || ta(a)) { var f = "object" !== typeof a; c = 0; for (e = a.length; c < e; c++) (f || c in a) && b.call(d, a[c], c, a) } else if (a.forEach && a.forEach !== q) a.forEach(b, d, a); else if (sc(a)) for (c in a) b.call(d, a[c], c, a); else if ("function" === typeof a.hasOwnProperty) for (c in a) a.hasOwnProperty(c) &&
        b.call(d, a[c], c, a); else for (c in a) ua.call(a, c) && b.call(d, a[c], c, a); return a
    } function tc(a, b, d) { for (var c = Object.keys(a).sort(), e = 0; e < c.length; e++) b.call(d, a[c[e]], c[e]); return c } function uc(a) { return function (b, d) { a(d, b) } } function Yd() { return ++pb } function Pb(a, b, d) {
        for (var c = a.$$hashKey, e = 0, f = b.length; e < f; ++e) {
            var g = b[e]; if (D(g) || z(g)) for (var h = Object.keys(g), k = 0, l = h.length; k < l; k++) {
                var m = h[k], n = g[m]; d && D(n) ? da(n) ? a[m] = new Date(n.valueOf()) : Wa(n) ? a[m] = new RegExp(n) : n.nodeName ? a[m] = n.cloneNode(!0) :
                Qb(n) ? a[m] = n.clone() : (D(a[m]) || (a[m] = L(n) ? [] : {}), Pb(a[m], [n], !0)) : a[m] = n
            }
        } c ? a.$$hashKey = c : delete a.$$hashKey; return a
    } function S(a) { return Pb(a, va.call(arguments, 1), !1) } function Zd(a) { return Pb(a, va.call(arguments, 1), !0) } function Z(a) { return parseInt(a, 10) } function Rb(a, b) { return S(Object.create(a), b) } function A() { } function Xa(a) { return a } function ha(a) { return function () { return a } } function vc(a) { return z(a.toString) && a.toString !== ma } function y(a) { return "undefined" === typeof a } function w(a) {
        return "undefined" !==
        typeof a
    } function D(a) { return null !== a && "object" === typeof a } function sc(a) { return null !== a && "object" === typeof a && !wc(a) } function G(a) { return "string" === typeof a } function T(a) { return "number" === typeof a } function da(a) { return "[object Date]" === ma.call(a) } function z(a) { return "function" === typeof a } function Wa(a) { return "[object RegExp]" === ma.call(a) } function Va(a) { return a && a.window === a } function Ya(a) { return a && a.$evalAsync && a.$watch } function Ga(a) { return "boolean" === typeof a } function $d(a) {
        return a && T(a.length) &&
        ae.test(ma.call(a))
    } function Qb(a) { return !(!a || !(a.nodeName || a.prop && a.attr && a.find)) } function be(a) { var b = {}; a = a.split(","); var d; for (d = 0; d < a.length; d++) b[a[d]] = !0; return b } function wa(a) { return Q(a.nodeName || a[0] && a[0].nodeName) } function Za(a, b) { var d = a.indexOf(b); 0 <= d && a.splice(d, 1); return d } function pa(a, b) {
        function d(a, b) {
            var d = b.$$hashKey, e; if (L(a)) { e = 0; for (var f = a.length; e < f; e++) b.push(c(a[e])) } else if (sc(a)) for (e in a) b[e] = c(a[e]); else if (a && "function" === typeof a.hasOwnProperty) for (e in a) a.hasOwnProperty(e) &&
            (b[e] = c(a[e])); else for (e in a) ua.call(a, e) && (b[e] = c(a[e])); d ? b.$$hashKey = d : delete b.$$hashKey; return b
        } function c(a) { if (!D(a)) return a; var b = f.indexOf(a); if (-1 !== b) return g[b]; if (Va(a) || Ya(a)) throw xa("cpws"); var b = !1, c = e(a); void 0 === c && (c = L(a) ? [] : Object.create(wc(a)), b = !0); f.push(a); g.push(c); return b ? d(a, c) : c } function e(a) {
            switch (ma.call(a)) {
                case "[object Int8Array]": case "[object Int16Array]": case "[object Int32Array]": case "[object Float32Array]": case "[object Float64Array]": case "[object Uint8Array]": case "[object Uint8ClampedArray]": case "[object Uint16Array]": case "[object Uint32Array]": return new a.constructor(c(a.buffer),
                a.byteOffset, a.length); case "[object ArrayBuffer]": if (!a.slice) { var b = new ArrayBuffer(a.byteLength); (new Uint8Array(b)).set(new Uint8Array(a)); return b } return a.slice(0); case "[object Boolean]": case "[object Number]": case "[object String]": case "[object Date]": return new a.constructor(a.valueOf()); case "[object RegExp]": return b = new RegExp(a.source, a.toString().match(/[^\/]*$/)[0]), b.lastIndex = a.lastIndex, b; case "[object Blob]": return new a.constructor([a], { type: a.type })
            } if (z(a.cloneNode)) return a.cloneNode(!0)
        }
        var f = [], g = []; if (b) { if ($d(b) || "[object ArrayBuffer]" === ma.call(b)) throw xa("cpta"); if (a === b) throw xa("cpi"); L(b) ? b.length = 0 : q(b, function (a, d) { "$$hashKey" !== d && delete b[d] }); f.push(a); g.push(b); return d(a, b) } return c(a)
    } function na(a, b) {
        if (a === b) return !0; if (null === a || null === b) return !1; if (a !== a && b !== b) return !0; var d = typeof a, c; if (d == typeof b && "object" == d) if (L(a)) { if (!L(b)) return !1; if ((d = a.length) == b.length) { for (c = 0; c < d; c++) if (!na(a[c], b[c])) return !1; return !0 } } else {
            if (da(a)) return da(b) ? na(a.getTime(),
            b.getTime()) : !1; if (Wa(a)) return Wa(b) ? a.toString() == b.toString() : !1; if (Ya(a) || Ya(b) || Va(a) || Va(b) || L(b) || da(b) || Wa(b)) return !1; d = U(); for (c in a) if ("$" !== c.charAt(0) && !z(a[c])) { if (!na(a[c], b[c])) return !1; d[c] = !0 } for (c in b) if (!(c in d) && "$" !== c.charAt(0) && w(b[c]) && !z(b[c])) return !1; return !0
        } return !1
    } function $a(a, b, d) { return a.concat(va.call(b, d)) } function ab(a, b) {
        var d = 2 < arguments.length ? va.call(arguments, 2) : []; return !z(b) || b instanceof RegExp ? b : d.length ? function () {
            return arguments.length ? b.apply(a,
            $a(d, arguments, 0)) : b.apply(a, d)
        } : function () { return arguments.length ? b.apply(a, arguments) : b.call(a) }
    } function ce(a, b) { var d = b; "string" === typeof a && "$" === a.charAt(0) && "$" === a.charAt(1) ? d = void 0 : Va(b) ? d = "$WINDOW" : b && C.document === b ? d = "$DOCUMENT" : Ya(b) && (d = "$SCOPE"); return d } function bb(a, b) { if (!y(a)) return T(b) || (b = b ? 2 : null), JSON.stringify(a, ce, b) } function xc(a) { return G(a) ? JSON.parse(a) : a } function yc(a, b) { a = a.replace(de, ""); var d = Date.parse("Jan 01, 1970 00:00:00 " + a) / 6E4; return isNaN(d) ? b : d } function Sb(a,
    b, d) { d = d ? -1 : 1; var c = a.getTimezoneOffset(); b = yc(b, c); d *= b - c; a = new Date(a.getTime()); a.setMinutes(a.getMinutes() + d); return a } function ya(a) { a = F(a).clone(); try { a.empty() } catch (b) { } var d = F("<div>").append(a).html(); try { return a[0].nodeType === Ma ? Q(d) : d.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/, function (a, b) { return "<" + Q(b) }) } catch (c) { return Q(d) } } function zc(a) { try { return decodeURIComponent(a) } catch (b) { } } function Ac(a) {
        var b = {}; q((a || "").split("&"), function (a) {
            var c, e, f; a && (e = a = a.replace(/\+/g, "%20"),
            c = a.indexOf("="), -1 !== c && (e = a.substring(0, c), f = a.substring(c + 1)), e = zc(e), w(e) && (f = w(f) ? zc(f) : !0, ua.call(b, e) ? L(b[e]) ? b[e].push(f) : b[e] = [b[e], f] : b[e] = f))
        }); return b
    } function Tb(a) { var b = []; q(a, function (a, c) { L(a) ? q(a, function (a) { b.push(ea(c, !0) + (!0 === a ? "" : "=" + ea(a, !0))) }) : b.push(ea(c, !0) + (!0 === a ? "" : "=" + ea(a, !0))) }); return b.length ? b.join("&") : "" } function qb(a) { return ea(a, !0).replace(/%26/gi, "&").replace(/%3D/gi, "=").replace(/%2B/gi, "+") } function ea(a, b) {
        return encodeURIComponent(a).replace(/%40/gi,
        "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%3B/gi, ";").replace(/%20/g, b ? "%20" : "+")
    } function ee(a, b) { var d, c, e = Na.length; for (c = 0; c < e; ++c) if (d = Na[c] + b, G(d = a.getAttribute(d))) return d; return null } function fe(a, b) {
        var d, c, e = {}; q(Na, function (b) { b += "app"; !d && a.hasAttribute && a.hasAttribute(b) && (d = a, c = a.getAttribute(b)) }); q(Na, function (b) { b += "app"; var e; !d && (e = a.querySelector("[" + b.replace(":", "\\:") + "]")) && (d = e, c = e.getAttribute(b)) }); d && (e.strictDi = null !== ee(d, "strict-di"),
        b(d, c ? [c] : [], e))
    } function Bc(a, b, d) {
        D(d) || (d = {}); d = S({ strictDi: !1 }, d); var c = function () {
            a = F(a); if (a.injector()) { var c = a[0] === C.document ? "document" : ya(a); throw xa("btstrpd", c.replace(/</, "&lt;").replace(/>/, "&gt;")); } b = b || []; b.unshift(["$provide", function (b) { b.value("$rootElement", a) }]); d.debugInfoEnabled && b.push(["$compileProvider", function (a) { a.debugInfoEnabled(!0) }]); b.unshift("ng"); c = cb(b, d.strictDi); c.invoke(["$rootScope", "$rootElement", "$compile", "$injector", function (a, b, c, d) {
                a.$apply(function () {
                    b.data("$injector",
                    d); c(b)(a)
                })
            }]); return c
        }, e = /^NG_ENABLE_DEBUG_INFO!/, f = /^NG_DEFER_BOOTSTRAP!/; C && e.test(C.name) && (d.debugInfoEnabled = !0, C.name = C.name.replace(e, "")); if (C && !f.test(C.name)) return c(); C.name = C.name.replace(f, ""); ca.resumeBootstrap = function (a) { q(a, function (a) { b.push(a) }); return c() }; z(ca.resumeDeferredBootstrap) && ca.resumeDeferredBootstrap()
    } function ge() { C.name = "NG_ENABLE_DEBUG_INFO!" + C.name; C.location.reload() } function he(a) { a = ca.element(a).injector(); if (!a) throw xa("test"); return a.get("$$testability") }
    function Cc(a, b) { b = b || "_"; return a.replace(ie, function (a, c) { return (c ? b : "") + a.toLowerCase() }) } function je() { var a; if (!Dc) { var b = rb(); (qa = y(b) ? C.jQuery : b ? C[b] : void 0) && qa.fn.on ? (F = qa, S(qa.fn, { scope: Oa.scope, isolateScope: Oa.isolateScope, controller: Oa.controller, injector: Oa.injector, inheritedData: Oa.inheritedData }), a = qa.cleanData, qa.cleanData = function (b) { for (var c, e = 0, f; null != (f = b[e]) ; e++) (c = qa._data(f, "events")) && c.$destroy && qa(f).triggerHandler("$destroy"); a(b) }) : F = O; ca.element = F; Dc = !0 } } function sb(a,
    b, d) { if (!a) throw xa("areq", b || "?", d || "required"); return a } function Pa(a, b, d) { d && L(a) && (a = a[a.length - 1]); sb(z(a), b, "not a function, got " + (a && "object" === typeof a ? a.constructor.name || "Object" : typeof a)); return a } function Qa(a, b) { if ("hasOwnProperty" === a) throw xa("badname", b); } function Ec(a, b, d) { if (!b) return a; b = b.split("."); for (var c, e = a, f = b.length, g = 0; g < f; g++) c = b[g], a && (a = (e = a)[c]); return !d && z(a) ? ab(e, a) : a } function tb(a) {
        for (var b = a[0], d = a[a.length - 1], c, e = 1; b !== d && (b = b.nextSibling) ; e++) if (c || a[e] !==
        b) c || (c = F(va.call(a, 0, e))), c.push(b); return c || a
    } function U() { return Object.create(null) } function ke(a) {
        function b(a, b, c) { return a[b] || (a[b] = c()) } var d = N("$injector"), c = N("ng"); a = b(a, "angular", Object); a.$$minErr = a.$$minErr || N; return b(a, "module", function () {
            var a = {}; return function (f, g, h) {
                if ("hasOwnProperty" === f) throw c("badname", "module"); g && a.hasOwnProperty(f) && (a[f] = null); return b(a, f, function () {
                    function a(b, d, e, f) { f || (f = c); return function () { f[e || "push"]([b, d, arguments]); return R } } function b(a,
                    d) { return function (b, e) { e && z(e) && (e.$$moduleName = f); c.push([a, d, arguments]); return R } } if (!g) throw d("nomod", f); var c = [], e = [], p = [], u = a("$injector", "invoke", "push", e), R = {
                        _invokeQueue: c, _configBlocks: e, _runBlocks: p, requires: g, name: f, provider: b("$provide", "provider"), factory: b("$provide", "factory"), service: b("$provide", "service"), value: a("$provide", "value"), constant: a("$provide", "constant", "unshift"), decorator: b("$provide", "decorator"), animation: b("$animateProvider", "register"), filter: b("$filterProvider",
                        "register"), controller: b("$controllerProvider", "register"), directive: b("$compileProvider", "directive"), component: b("$compileProvider", "component"), config: u, run: function (a) { p.push(a); return this }
                    }; h && u(h); return R
                })
            }
        })
    } function ia(a, b) { if (L(a)) { b = b || []; for (var d = 0, c = a.length; d < c; d++) b[d] = a[d] } else if (D(a)) for (d in b = b || {}, a) if ("$" !== d.charAt(0) || "$" !== d.charAt(1)) b[d] = a[d]; return b || a } function le(a) {
        S(a, {
            bootstrap: Bc, copy: pa, extend: S, merge: Zd, equals: na, element: F, forEach: q, injector: cb, noop: A, bind: ab,
            toJson: bb, fromJson: xc, identity: Xa, isUndefined: y, isDefined: w, isString: G, isFunction: z, isObject: D, isNumber: T, isElement: Qb, isArray: L, version: me, isDate: da, lowercase: Q, uppercase: ub, callbacks: { $$counter: 0 }, getTestability: he, $$minErr: N, $$csp: Ba, reloadWithDebugInfo: ge
        }); Ub = ke(C); Ub("ng", ["ngLocale"], ["$provide", function (a) {
            a.provider({ $$sanitizeUri: ne }); a.provider("$compile", Fc).directive({
                a: oe, input: Gc, textarea: Gc, form: pe, script: qe, select: re, style: se, option: te, ngBind: ue, ngBindHtml: ve, ngBindTemplate: we, ngClass: xe,
                ngClassEven: ye, ngClassOdd: ze, ngCloak: Ae, ngController: Be, ngForm: Ce, ngHide: De, ngIf: Ee, ngInclude: Fe, ngInit: Ge, ngNonBindable: He, ngPluralize: Ie, ngRepeat: Je, ngShow: Ke, ngStyle: Le, ngSwitch: Me, ngSwitchWhen: Ne, ngSwitchDefault: Oe, ngOptions: Pe, ngTransclude: Qe, ngModel: Re, ngList: Se, ngChange: Te, pattern: Hc, ngPattern: Hc, required: Ic, ngRequired: Ic, minlength: Jc, ngMinlength: Jc, maxlength: Kc, ngMaxlength: Kc, ngValue: Ue, ngModelOptions: Ve
            }).directive({ ngInclude: We }).directive(vb).directive(Lc); a.provider({
                $anchorScroll: Xe,
                $animate: Ye, $animateCss: Ze, $$animateJs: $e, $$animateQueue: af, $$AnimateRunner: bf, $$animateAsyncRun: cf, $browser: df, $cacheFactory: ef, $controller: ff, $document: gf, $exceptionHandler: hf, $filter: Mc, $$forceReflow: jf, $interpolate: kf, $interval: lf, $http: mf, $httpParamSerializer: nf, $httpParamSerializerJQLike: of, $httpBackend: pf, $xhrFactory: qf, $jsonpCallbacks: rf, $location: sf, $log: tf, $parse: uf, $rootScope: vf, $q: wf, $$q: xf, $sce: yf, $sceDelegate: zf, $sniffer: Af, $templateCache: Bf, $templateRequest: Cf, $$testability: Df, $timeout: Ef,
                $window: Ff, $$rAF: Gf, $$jqLite: Hf, $$HashMap: If, $$cookieReader: Jf
            })
        }])
    } function db(a) { return a.replace(Kf, function (a, d, c, e) { return e ? c.toUpperCase() : c }).replace(Lf, "Moz$1") } function Nc(a) { a = a.nodeType; return 1 === a || !a || 9 === a } function Oc(a, b) {
        var d, c, e = b.createDocumentFragment(), f = []; if (Vb.test(a)) {
            d = e.appendChild(b.createElement("div")); c = (Mf.exec(a) || ["", ""])[1].toLowerCase(); c = ja[c] || ja._default; d.innerHTML = c[1] + a.replace(Nf, "<$1></$2>") + c[2]; for (c = c[0]; c--;) d = d.lastChild; f = $a(f, d.childNodes); d = e.firstChild;
            d.textContent = ""
        } else f.push(b.createTextNode(a)); e.textContent = ""; e.innerHTML = ""; q(f, function (a) { e.appendChild(a) }); return e
    } function Pc(a, b) { var d = a.parentNode; d && d.replaceChild(b, a); b.appendChild(a) } function O(a) { if (a instanceof O) return a; var b; G(a) && (a = W(a), b = !0); if (!(this instanceof O)) { if (b && "<" != a.charAt(0)) throw Wb("nosel"); return new O(a) } if (b) { b = C.document; var d; a = (d = Of.exec(a)) ? [b.createElement(d[1])] : (d = Oc(a, b)) ? d.childNodes : [] } Qc(this, a) } function Xb(a) { return a.cloneNode(!0) } function wb(a,
    b) { b || eb(a); if (a.querySelectorAll) for (var d = a.querySelectorAll("*"), c = 0, e = d.length; c < e; c++) eb(d[c]) } function Rc(a, b, d, c) { if (w(c)) throw Wb("offargs"); var e = (c = xb(a)) && c.events, f = c && c.handle; if (f) if (b) { var g = function (b) { var c = e[b]; w(d) && Za(c || [], d); w(d) && c && 0 < c.length || (a.removeEventListener(b, f, !1), delete e[b]) }; q(b.split(" "), function (a) { g(a); yb[a] && g(yb[a]) }) } else for (b in e) "$destroy" !== b && a.removeEventListener(b, f, !1), delete e[b] } function eb(a, b) {
        var d = a.ng339, c = d && fb[d]; c && (b ? delete c.data[b] :
        (c.handle && (c.events.$destroy && c.handle({}, "$destroy"), Rc(a)), delete fb[d], a.ng339 = void 0))
    } function xb(a, b) { var d = a.ng339, d = d && fb[d]; b && !d && (a.ng339 = d = ++Pf, d = fb[d] = { events: {}, data: {}, handle: void 0 }); return d } function Yb(a, b, d) { if (Nc(a)) { var c = w(d), e = !c && b && !D(b), f = !b; a = (a = xb(a, !e)) && a.data; if (c) a[b] = d; else { if (f) return a; if (e) return a && a[b]; S(a, b) } } } function zb(a, b) { return a.getAttribute ? -1 < (" " + (a.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " ").indexOf(" " + b + " ") : !1 } function Ab(a, b) {
        b && a.setAttribute &&
        q(b.split(" "), function (b) { a.setAttribute("class", W((" " + (a.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " ").replace(" " + W(b) + " ", " "))) })
    } function Bb(a, b) { if (b && a.setAttribute) { var d = (" " + (a.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " "); q(b.split(" "), function (a) { a = W(a); -1 === d.indexOf(" " + a + " ") && (d += a + " ") }); a.setAttribute("class", W(d)) } } function Qc(a, b) {
        if (b) if (b.nodeType) a[a.length++] = b; else {
            var d = b.length; if ("number" === typeof d && b.window !== b) {
                if (d) for (var c = 0; c < d; c++) a[a.length++] =
                b[c]
            } else a[a.length++] = b
        }
    } function Sc(a, b) { return Cb(a, "$" + (b || "ngController") + "Controller") } function Cb(a, b, d) { 9 == a.nodeType && (a = a.documentElement); for (b = L(b) ? b : [b]; a;) { for (var c = 0, e = b.length; c < e; c++) if (w(d = F.data(a, b[c]))) return d; a = a.parentNode || 11 === a.nodeType && a.host } } function Tc(a) { for (wb(a, !0) ; a.firstChild;) a.removeChild(a.firstChild) } function Db(a, b) { b || wb(a); var d = a.parentNode; d && d.removeChild(a) } function Qf(a, b) {
        b = b || C; if ("complete" === b.document.readyState) b.setTimeout(a); else F(b).on("load",
        a)
    } function Uc(a, b) { var d = Eb[b.toLowerCase()]; return d && Vc[wa(a)] && d } function Rf(a, b) {
        var d = function (c, d) {
            c.isDefaultPrevented = function () { return c.defaultPrevented }; var f = b[d || c.type], g = f ? f.length : 0; if (g) {
                if (y(c.immediatePropagationStopped)) { var h = c.stopImmediatePropagation; c.stopImmediatePropagation = function () { c.immediatePropagationStopped = !0; c.stopPropagation && c.stopPropagation(); h && h.call(c) } } c.isImmediatePropagationStopped = function () { return !0 === c.immediatePropagationStopped }; var k = f.specialHandlerWrapper ||
                Sf; 1 < g && (f = ia(f)); for (var l = 0; l < g; l++) c.isImmediatePropagationStopped() || k(a, c, f[l])
            }
        }; d.elem = a; return d
    } function Sf(a, b, d) { d.call(a, b) } function Tf(a, b, d) { var c = b.relatedTarget; c && (c === a || Uf.call(a, c)) || d.call(a, b) } function Hf() { this.$get = function () { return S(O, { hasClass: function (a, b) { a.attr && (a = a[0]); return zb(a, b) }, addClass: function (a, b) { a.attr && (a = a[0]); return Bb(a, b) }, removeClass: function (a, b) { a.attr && (a = a[0]); return Ab(a, b) } }) } } function Ca(a, b) {
        var d = a && a.$$hashKey; if (d) return "function" === typeof d &&
        (d = a.$$hashKey()), d; d = typeof a; return d = "function" == d || "object" == d && null !== a ? a.$$hashKey = d + ":" + (b || Yd)() : d + ":" + a
    } function Ra(a, b) { if (b) { var d = 0; this.nextUid = function () { return ++d } } q(a, this.put, this) } function Wc(a) { a = (Function.prototype.toString.call(a) + " ").replace(Vf, ""); return a.match(Wf) || a.match(Xf) } function Yf(a) { return (a = Wc(a)) ? "function(" + (a[1] || "").replace(/[\s\r\n]+/, " ") + ")" : "fn" } function cb(a, b) {
        function d(a) { return function (b, c) { if (D(b)) q(b, uc(a)); else return a(b, c) } } function c(a, b) {
            Qa(a,
            "service"); if (z(b) || L(b)) b = p.instantiate(b); if (!b.$get) throw Ha("pget", a); return n[a + "Provider"] = b
        } function e(a, b) { return function () { var c = B.invoke(b, this); if (y(c)) throw Ha("undef", a); return c } } function f(a, b, d) { return c(a, { $get: !1 !== d ? e(a, b) : b }) } function g(a) {
            sb(y(a) || L(a), "modulesToLoad", "not an array"); var b = [], c; q(a, function (a) {
                function d(a) { var b, c; b = 0; for (c = a.length; b < c; b++) { var e = a[b], f = p.get(e[0]); f[e[1]].apply(f, e[2]) } } if (!m.get(a)) {
                    m.put(a, !0); try {
                        G(a) ? (c = Ub(a), b = b.concat(g(c.requires)).concat(c._runBlocks),
                        d(c._invokeQueue), d(c._configBlocks)) : z(a) ? b.push(p.invoke(a)) : L(a) ? b.push(p.invoke(a)) : Pa(a, "module")
                    } catch (e) { throw L(a) && (a = a[a.length - 1]), e.message && e.stack && -1 == e.stack.indexOf(e.message) && (e = e.message + "\n" + e.stack), Ha("modulerr", a, e.stack || e.message || e); }
                }
            }); return b
        } function h(a, c) {
            function d(b, e) { if (a.hasOwnProperty(b)) { if (a[b] === k) throw Ha("cdep", b + " <- " + l.join(" <- ")); return a[b] } try { return l.unshift(b), a[b] = k, a[b] = c(b, e) } catch (f) { throw a[b] === k && delete a[b], f; } finally { l.shift() } } function e(a,
            c, f) { var g = []; a = cb.$$annotate(a, b, f); for (var h = 0, k = a.length; h < k; h++) { var l = a[h]; if ("string" !== typeof l) throw Ha("itkn", l); g.push(c && c.hasOwnProperty(l) ? c[l] : d(l, f)) } return g } return {
                invoke: function (a, b, c, d) { "string" === typeof c && (d = c, c = null); c = e(a, c, d); L(a) && (a = a[a.length - 1]); d = 11 >= Ea ? !1 : "function" === typeof a && /^(?:class\b|constructor\()/.test(Function.prototype.toString.call(a) + " "); return d ? (c.unshift(null), new (Function.prototype.bind.apply(a, c))) : a.apply(b, c) }, instantiate: function (a, b, c) {
                    var d =
                    L(a) ? a[a.length - 1] : a; a = e(a, b, c); a.unshift(null); return new (Function.prototype.bind.apply(d, a))
                }, get: d, annotate: cb.$$annotate, has: function (b) { return n.hasOwnProperty(b + "Provider") || a.hasOwnProperty(b) }
            }
        } b = !0 === b; var k = {}, l = [], m = new Ra([], !0), n = {
            $provide: {
                provider: d(c), factory: d(f), service: d(function (a, b) { return f(a, ["$injector", function (a) { return a.instantiate(b) }]) }), value: d(function (a, b) { return f(a, ha(b), !1) }), constant: d(function (a, b) { Qa(a, "constant"); n[a] = b; u[a] = b }), decorator: function (a, b) {
                    var c =
                    p.get(a + "Provider"), d = c.$get; c.$get = function () { var a = B.invoke(d, c); return B.invoke(b, null, { $delegate: a }) }
                }
            }
        }, p = n.$injector = h(n, function (a, b) { ca.isString(b) && l.push(b); throw Ha("unpr", l.join(" <- ")); }), u = {}, R = h(u, function (a, b) { var c = p.get(a + "Provider", b); return B.invoke(c.$get, c, void 0, a) }), B = R; n.$injectorProvider = { $get: ha(R) }; var r = g(a), B = R.get("$injector"); B.strictDi = b; q(r, function (a) { a && B.invoke(a) }); return B
    } function Xe() {
        var a = !0; this.disableAutoScrolling = function () { a = !1 }; this.$get = ["$window",
        "$location", "$rootScope", function (b, d, c) {
            function e(a) { var b = null; Array.prototype.some.call(a, function (a) { if ("a" === wa(a)) return b = a, !0 }); return b } function f(a) { if (a) { a.scrollIntoView(); var c; c = g.yOffset; z(c) ? c = c() : Qb(c) ? (c = c[0], c = "fixed" !== b.getComputedStyle(c).position ? 0 : c.getBoundingClientRect().bottom) : T(c) || (c = 0); c && (a = a.getBoundingClientRect().top, b.scrollBy(0, a - c)) } else b.scrollTo(0, 0) } function g(a) {
                a = G(a) ? a : d.hash(); var b; a ? (b = h.getElementById(a)) ? f(b) : (b = e(h.getElementsByName(a))) ? f(b) : "top" ===
                a && f(null) : f(null)
            } var h = b.document; a && c.$watch(function () { return d.hash() }, function (a, b) { a === b && "" === a || Qf(function () { c.$evalAsync(g) }) }); return g
        }]
    } function gb(a, b) { if (!a && !b) return ""; if (!a) return b; if (!b) return a; L(a) && (a = a.join(" ")); L(b) && (b = b.join(" ")); return a + " " + b } function Zf(a) { G(a) && (a = a.split(" ")); var b = U(); q(a, function (a) { a.length && (b[a] = !0) }); return b } function Ia(a) { return D(a) ? a : {} } function $f(a, b, d, c) {
        function e(a) { try { a.apply(null, va.call(arguments, 1)) } finally { if (R--, 0 === R) for (; B.length;) try { B.pop()() } catch (b) { d.error(b) } } }
        function f() { t = null; g(); h() } function g() { r = K(); r = y(r) ? null : r; na(r, E) && (r = E); E = r } function h() { if (v !== k.url() || J !== r) v = k.url(), J = r, q(M, function (a) { a(k.url(), r) }) } var k = this, l = a.location, m = a.history, n = a.setTimeout, p = a.clearTimeout, u = {}; k.isMock = !1; var R = 0, B = []; k.$$completeOutstandingRequest = e; k.$$incOutstandingRequestCount = function () { R++ }; k.notifyWhenNoOutstandingRequests = function (a) { 0 === R ? a() : B.push(a) }; var r, J, v = l.href, fa = b.find("base"), t = null, K = c.history ? function () { try { return m.state } catch (a) { } } :
        A; g(); J = r; k.url = function (b, d, e) { y(e) && (e = null); l !== a.location && (l = a.location); m !== a.history && (m = a.history); if (b) { var f = J === e; if (v === b && (!c.history || f)) return k; var h = v && Ja(v) === Ja(b); v = b; J = e; !c.history || h && f ? (h || (t = b), d ? l.replace(b) : h ? (d = l, e = b.indexOf("#"), e = -1 === e ? "" : b.substr(e), d.hash = e) : l.href = b, l.href !== b && (t = b)) : (m[d ? "replaceState" : "pushState"](e, "", b), g(), J = r); t && (t = b); return k } return t || l.href.replace(/%27/g, "'") }; k.state = function () { return r }; var M = [], H = !1, E = null; k.onUrlChange = function (b) {
            if (!H) {
                if (c.history) F(a).on("popstate",
                f); F(a).on("hashchange", f); H = !0
            } M.push(b); return b
        }; k.$$applicationDestroyed = function () { F(a).off("hashchange popstate", f) }; k.$$checkUrlChange = h; k.baseHref = function () { var a = fa.attr("href"); return a ? a.replace(/^(https?\:)?\/\/[^\/]*/, "") : "" }; k.defer = function (a, b) { var c; R++; c = n(function () { delete u[c]; e(a) }, b || 0); u[c] = !0; return c }; k.defer.cancel = function (a) { return u[a] ? (delete u[a], p(a), e(A), !0) : !1 }
    } function df() {
        this.$get = ["$window", "$log", "$sniffer", "$document", function (a, b, d, c) {
            return new $f(a, c, b,
            d)
        }]
    } function ef() {
        this.$get = function () {
            function a(a, c) {
                function e(a) { a != n && (p ? p == a && (p = a.n) : p = a, f(a.n, a.p), f(a, n), n = a, n.n = null) } function f(a, b) { a != b && (a && (a.p = b), b && (b.n = a)) } if (a in b) throw N("$cacheFactory")("iid", a); var g = 0, h = S({}, c, { id: a }), k = U(), l = c && c.capacity || Number.MAX_VALUE, m = U(), n = null, p = null; return b[a] = {
                    put: function (a, b) { if (!y(b)) { if (l < Number.MAX_VALUE) { var c = m[a] || (m[a] = { key: a }); e(c) } a in k || g++; k[a] = b; g > l && this.remove(p.key); return b } }, get: function (a) {
                        if (l < Number.MAX_VALUE) {
                            var b = m[a];
                            if (!b) return; e(b)
                        } return k[a]
                    }, remove: function (a) { if (l < Number.MAX_VALUE) { var b = m[a]; if (!b) return; b == n && (n = b.p); b == p && (p = b.n); f(b.n, b.p); delete m[a] } a in k && (delete k[a], g--) }, removeAll: function () { k = U(); g = 0; m = U(); n = p = null }, destroy: function () { m = h = k = null; delete b[a] }, info: function () { return S({}, h, { size: g }) }
                }
            } var b = {}; a.info = function () { var a = {}; q(b, function (b, e) { a[e] = b.info() }); return a }; a.get = function (a) { return b[a] }; return a
        }
    } function Bf() { this.$get = ["$cacheFactory", function (a) { return a("templates") }] }
    function Fc(a, b) {
        function d(a, b, c) { var d = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/, e = U(); q(a, function (a, f) { if (a in n) e[f] = n[a]; else { var g = a.match(d); if (!g) throw ga("iscp", b, f, a, c ? "controller bindings definition" : "isolate scope definition"); e[f] = { mode: g[1][0], collection: "*" === g[2], optional: "?" === g[3], attrName: g[4] || f }; g[4] && (n[a] = e[f]) } }); return e } function c(a) { var b = a.charAt(0); if (!b || b !== Q(b)) throw ga("baddir", a); if (a !== a.trim()) throw ga("baddir", a); } function e(a) {
            var b = a.require || a.controller && a.name;
            !L(b) && D(b) && q(b, function (a, c) { var d = a.match(l); a.substring(d[0].length) || (b[c] = d[0] + c) }); return b
        } var f = {}, g = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, h = /(([\w\-]+)(?:\:([^;]+))?;?)/, k = be("ngSrc,ngSrcset,src,srcset"), l = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/, m = /^(on[a-z]+|formaction)$/, n = U(); this.directive = function B(b, d) {
            Qa(b, "directive"); G(b) ? (c(b), sb(d, "directiveFactory"), f.hasOwnProperty(b) || (f[b] = [], a.factory(b + "Directive", ["$injector", "$exceptionHandler", function (a, c) {
                var d = []; q(f[b], function (f, g) {
                    try {
                        var h =
                        a.invoke(f); z(h) ? h = { compile: ha(h) } : !h.compile && h.link && (h.compile = ha(h.link)); h.priority = h.priority || 0; h.index = g; h.name = h.name || b; h.require = e(h); h.restrict = h.restrict || "EA"; h.$$moduleName = f.$$moduleName; d.push(h)
                    } catch (k) { c(k) }
                }); return d
            }])), f[b].push(d)) : q(b, uc(B)); return this
        }; this.component = function (a, b) {
            function c(a) {
                function e(b) { return z(b) || L(b) ? function (c, d) { return a.invoke(b, this, { $element: c, $attrs: d }) } : b } var f = b.template || b.templateUrl ? b.template : "", g = {
                    controller: d, controllerAs: Xc(b.controller) ||
                    b.controllerAs || "$ctrl", template: e(f), templateUrl: e(b.templateUrl), transclude: b.transclude, scope: {}, bindToController: b.bindings || {}, restrict: "E", require: b.require
                }; q(b, function (a, b) { "$" === b.charAt(0) && (g[b] = a) }); return g
            } var d = b.controller || function () { }; q(b, function (a, b) { "$" === b.charAt(0) && (c[b] = a, z(d) && (d[b] = a)) }); c.$inject = ["$injector"]; return this.directive(a, c)
        }; this.aHrefSanitizationWhitelist = function (a) { return w(a) ? (b.aHrefSanitizationWhitelist(a), this) : b.aHrefSanitizationWhitelist() }; this.imgSrcSanitizationWhitelist =
        function (a) { return w(a) ? (b.imgSrcSanitizationWhitelist(a), this) : b.imgSrcSanitizationWhitelist() }; var p = !0; this.debugInfoEnabled = function (a) { return w(a) ? (p = a, this) : p }; var u = 10; this.onChangesTtl = function (a) { return arguments.length ? (u = a, this) : u }; this.$get = ["$injector", "$interpolate", "$exceptionHandler", "$templateRequest", "$parse", "$controller", "$rootScope", "$sce", "$animate", "$$sanitizeUri", function (a, b, c, e, n, t, K, M, H, E) {
            function I() {
                try {
                    if (!--qa) throw Y = void 0, ga("infchng", u); K.$apply(function () {
                        for (var a =
                        [], b = 0, c = Y.length; b < c; ++b) try { Y[b]() } catch (d) { a.push(d) } Y = void 0; if (a.length) throw a;
                    })
                } finally { qa++ }
            } function Da(a, b) { if (b) { var c = Object.keys(b), d, e, f; d = 0; for (e = c.length; d < e; d++) f = c[d], this[f] = b[f] } else this.$attr = {}; this.$$element = a } function P(a, b, c) { pa.innerHTML = "<span " + b + ">"; b = pa.firstChild.attributes; var d = b[0]; b.removeNamedItem(d.name); d.value = c; a.attributes.setNamedItem(d) } function x(a, b) { try { a.addClass(b) } catch (c) { } } function aa(a, b, c, d, e) {
                a instanceof F || (a = F(a)); for (var f = /\S+/, g = 0, h = a.length; g <
                h; g++) { var k = a[g]; k.nodeType === Ma && k.nodeValue.match(f) && Pc(k, a[g] = C.document.createElement("span")) } var l = s(a, b, a, c, d, e); aa.$$addScopeClass(a); var m = null; return function (b, c, d) {
                    sb(b, "scope"); e && e.needsNewScope && (b = b.$parent.$new()); d = d || {}; var f = d.parentBoundTranscludeFn, g = d.transcludeControllers; d = d.futureParentElement; f && f.$$boundTransclude && (f = f.$$boundTransclude); m || (m = (d = d && d[0]) ? "foreignobject" !== wa(d) && ma.call(d).match(/SVG/) ? "svg" : "html" : "html"); d = "html" !== m ? F(da(m, F("<div>").append(a).html())) :
                    c ? Oa.clone.call(a) : a; if (g) for (var h in g) d.data("$" + h + "Controller", g[h].instance); aa.$$addScopeInfo(d, b); c && c(d, b); l && l(b, d, d, f); return d
                }
            } function s(a, b, c, d, e, f) {
                function g(a, c, d, e) {
                    var f, k, l, m, p, r, v; if (n) for (v = Array(c.length), m = 0; m < h.length; m += 3) f = h[m], v[f] = c[f]; else v = c; m = 0; for (p = h.length; m < p;) k = v[h[m++]], c = h[m++], f = h[m++], c ? (c.scope ? (l = a.$new(), aa.$$addScopeInfo(F(k), l)) : l = a, r = c.transcludeOnThisElement ? za(a, c.transclude, e) : !c.templateOnThisElement && e ? e : !e && b ? za(a, b) : null, c(f, l, k, d, r)) : f && f(a,
                    k.childNodes, void 0, e)
                } for (var h = [], k, l, m, p, n, r = 0; r < a.length; r++) { k = new Da; l = $b(a[r], [], k, 0 === r ? d : void 0, e); (f = l.length ? oa(l, a[r], k, b, c, null, [], [], f) : null) && f.scope && aa.$$addScopeClass(k.$$element); k = f && f.terminal || !(m = a[r].childNodes) || !m.length ? null : s(m, f ? (f.transcludeOnThisElement || !f.templateOnThisElement) && f.transclude : b); if (f || k) h.push(r, f, k), p = !0, n = n || f; f = null } return p ? g : null
            } function za(a, b, c) {
                function d(e, f, g, h, k) {
                    e || (e = a.$new(!1, k), e.$$transcluded = !0); return b(e, f, {
                        parentBoundTranscludeFn: c,
                        transcludeControllers: g, futureParentElement: h
                    })
                } var e = d.$$slots = U(), f; for (f in b.$$slots) e[f] = b.$$slots[f] ? za(a, b.$$slots[f], c) : null; return d
            } function $b(a, b, c, d, e) {
                var f = c.$attr; switch (a.nodeType) {
                    case 1: O(b, Aa(wa(a)), "E", d, e); for (var g, k, l, m, p = a.attributes, n = 0, r = p && p.length; n < r; n++) {
                        var v = !1, u = !1; g = p[n]; k = g.name; l = W(g.value); g = Aa(k); if (m = Ba.test(g)) k = k.replace(Yc, "").substr(8).replace(/_(.)/g, function (a, b) { return b.toUpperCase() }); (g = g.match(Ca)) && V(g[1]) && (v = k, u = k.substr(0, k.length - 5) + "end", k =
                        k.substr(0, k.length - 6)); g = Aa(k.toLowerCase()); f[g] = k; if (m || !c.hasOwnProperty(g)) c[g] = l, Uc(a, g) && (c[g] = !0); ia(a, b, l, g, m); O(b, g, "A", d, e, v, u)
                    } f = a.className; D(f) && (f = f.animVal); if (G(f) && "" !== f) for (; a = h.exec(f) ;) g = Aa(a[2]), O(b, g, "C", d, e) && (c[g] = W(a[3])), f = f.substr(a.index + a[0].length); break; case Ma: if (11 === Ea) for (; a.parentNode && a.nextSibling && a.nextSibling.nodeType === Ma;) a.nodeValue += a.nextSibling.nodeValue, a.parentNode.removeChild(a.nextSibling); ca(b, a.nodeValue); break; case 8: hb(a, b, c, d, e)
                } b.sort(Z);
                return b
            } function hb(a, b, c, d, e) { try { var f = g.exec(a.nodeValue); if (f) { var h = Aa(f[1]); O(b, h, "M", d, e) && (c[h] = W(f[2])) } } catch (k) { } } function N(a, b, c) { var d = [], e = 0; if (b && a.hasAttribute && a.hasAttribute(b)) { do { if (!a) throw ga("uterdir", b, c); 1 == a.nodeType && (a.hasAttribute(b) && e++, a.hasAttribute(c) && e--); d.push(a); a = a.nextSibling } while (0 < e) } else d.push(a); return F(d) } function Zc(a, b, c) { return function (d, e, f, g, h) { e = N(e[0], b, c); return a(d, e, f, g, h) } } function ac(a, b, c, d, e, f) {
                var g; return a ? aa(b, c, d, e, f) : function () {
                    g ||
                    (g = aa(b, c, d, e, f), b = c = f = null); return g.apply(this, arguments)
                }
            } function oa(a, b, d, e, f, g, h, k, l) {
                function m(a, b, c, d) { if (a) { c && (a = Zc(a, c, d)); a.require = x.require; a.directiveName = I; if (u === x || x.$$isolateScope) a = ja(a, { isolateScope: !0 }); h.push(a) } if (b) { c && (b = Zc(b, c, d)); b.require = x.require; b.directiveName = I; if (u === x || x.$$isolateScope) b = ja(b, { isolateScope: !0 }); k.push(b) } } function p(a, e, f, g, l) {
                    function m(a, b, c, d) {
                        var e; Ya(a) || (d = c, c = b, b = a, a = void 0); fa && (e = t); c || (c = fa ? I.parent() : I); if (d) {
                            var f = l.$$slots[d]; if (f) return f(a,
                            b, e, c, s); if (y(f)) throw ga("noslot", d, ya(I));
                        } else return l(a, b, e, c, s)
                    } var n, E, x, M, B, t, P, I; b === f ? (g = d, I = d.$$element) : (I = F(f), g = new Da(I, d)); B = e; u ? M = e.$new(!0) : r && (B = e.$parent); l && (P = m, P.$$boundTransclude = l, P.isSlotFilled = function (a) { return !!l.$$slots[a] }); v && (t = ag(I, g, P, v, M, e, u)); u && (aa.$$addScopeInfo(I, M, !0, !(H && (H === u || H === u.$$originalDirective))), aa.$$addScopeClass(I, !0), M.$$isolateBindings = u.$$isolateBindings, E = ka(e, g, M, M.$$isolateBindings, u), E.removeWatches && M.$on("$destroy", E.removeWatches));
                    for (n in t) { E = v[n]; x = t[n]; var Zb = E.$$bindings.bindToController; x.bindingInfo = x.identifier && Zb ? ka(B, g, x.instance, Zb, E) : {}; var K = x(); K !== x.instance && (x.instance = K, I.data("$" + E.name + "Controller", K), x.bindingInfo.removeWatches && x.bindingInfo.removeWatches(), x.bindingInfo = ka(B, g, x.instance, Zb, E)) } q(v, function (a, b) { var c = a.require; a.bindToController && !L(c) && D(c) && S(t[b].instance, ib(b, c, I, t)) }); q(t, function (a) {
                        var b = a.instance; if (z(b.$onChanges)) try { b.$onChanges(a.bindingInfo.initialChanges) } catch (d) { c(d) } if (z(b.$onInit)) try { b.$onInit() } catch (e) { c(e) } z(b.$doCheck) &&
                        (B.$watch(function () { b.$doCheck() }), b.$doCheck()); z(b.$onDestroy) && B.$on("$destroy", function () { b.$onDestroy() })
                    }); n = 0; for (E = h.length; n < E; n++) x = h[n], la(x, x.isolateScope ? M : e, I, g, x.require && ib(x.directiveName, x.require, I, t), P); var s = e; u && (u.template || null === u.templateUrl) && (s = M); a && a(s, f.childNodes, void 0, l); for (n = k.length - 1; 0 <= n; n--) x = k[n], la(x, x.isolateScope ? M : e, I, g, x.require && ib(x.directiveName, x.require, I, t), P); q(t, function (a) { a = a.instance; z(a.$postLink) && a.$postLink() })
                } l = l || {}; for (var n = -Number.MAX_VALUE,
                r = l.newScopeDirective, v = l.controllerDirectives, u = l.newIsolateScopeDirective, H = l.templateDirective, E = l.nonTlbTranscludeDirective, M = !1, B = !1, fa = l.hasElementTranscludeDirective, t = d.$$element = F(b), x, I, P, K = e, s, Fa = !1, za = !1, w, A = 0, C = a.length; A < C; A++) {
                    x = a[A]; var G = x.$$start, hb = x.$$end; G && (t = N(b, G, hb)); P = void 0; if (n > x.priority) break; if (w = x.scope) x.templateUrl || (D(w) ? (X("new/isolated scope", u || r, x, t), u = x) : X("new/isolated scope", u, x, t)), r = r || x; I = x.name; if (!Fa && (x.replace && (x.templateUrl || x.template) || x.transclude &&
                    !x.$$tlb)) { for (w = A + 1; Fa = a[w++];) if (Fa.transclude && !Fa.$$tlb || Fa.replace && (Fa.templateUrl || Fa.template)) { za = !0; break } Fa = !0 } !x.templateUrl && x.controller && (w = x.controller, v = v || U(), X("'" + I + "' controller", v[I], x, t), v[I] = x); if (w = x.transclude) if (M = !0, x.$$tlb || (X("transclusion", E, x, t), E = x), "element" == w) fa = !0, n = x.priority, P = t, t = d.$$element = F(aa.$$createComment(I, d[I])), b = t[0], ea(f, va.call(P, 0), b), P[0].$$parentNode = P[0].parentNode, K = ac(za, P, e, n, g && g.name, { nonTlbTranscludeDirective: E }); else {
                        var oa = U(); P = F(Xb(b)).contents();
                        if (D(w)) { P = []; var Q = U(), O = U(); q(w, function (a, b) { var c = "?" === a.charAt(0); a = c ? a.substring(1) : a; Q[a] = b; oa[b] = null; O[b] = c }); q(t.contents(), function (a) { var b = Q[Aa(wa(a))]; b ? (O[b] = !0, oa[b] = oa[b] || [], oa[b].push(a)) : P.push(a) }); q(O, function (a, b) { if (!a) throw ga("reqslot", b); }); for (var V in oa) oa[V] && (oa[V] = ac(za, oa[V], e)) } t.empty(); K = ac(za, P, e, void 0, void 0, { needsNewScope: x.$$isolateScope || x.$$newScope }); K.$$slots = oa
                    } if (x.template) if (B = !0, X("template", H, x, t), H = x, w = z(x.template) ? x.template(t, d) : x.template,
                    w = xa(w), x.replace) { g = x; P = Vb.test(w) ? $c(da(x.templateNamespace, W(w))) : []; b = P[0]; if (1 != P.length || 1 !== b.nodeType) throw ga("tplrt", I, ""); ea(f, t, b); C = { $attr: {} }; w = $b(b, [], C); var Z = a.splice(A + 1, a.length - (A + 1)); (u || r) && T(w, u, r); a = a.concat(w).concat(Z); $(d, C); C = a.length } else t.html(w); if (x.templateUrl) B = !0, X("template", H, x, t), H = x, x.replace && (g = x), p = ba(a.splice(A, a.length - A), t, d, f, M && K, h, k, { controllerDirectives: v, newScopeDirective: r !== x && r, newIsolateScopeDirective: u, templateDirective: H, nonTlbTranscludeDirective: E }),
                    C = a.length; else if (x.compile) try { s = x.compile(t, d, K); var Y = x.$$originalDirective || x; z(s) ? m(null, ab(Y, s), G, hb) : s && m(ab(Y, s.pre), ab(Y, s.post), G, hb) } catch (ca) { c(ca, ya(t)) } x.terminal && (p.terminal = !0, n = Math.max(n, x.priority))
                } p.scope = r && !0 === r.scope; p.transcludeOnThisElement = M; p.templateOnThisElement = B; p.transclude = K; l.hasElementTranscludeDirective = fa; return p
            } function ib(a, b, c, d) {
                var e; if (G(b)) {
                    var f = b.match(l); b = b.substring(f[0].length); var g = f[1] || f[3], f = "?" === f[2]; "^^" === g ? c = c.parent() : e = (e = d && d[b]) &&
                    e.instance; if (!e) { var h = "$" + b + "Controller"; e = g ? c.inheritedData(h) : c.data(h) } if (!e && !f) throw ga("ctreq", b, a);
                } else if (L(b)) for (e = [], g = 0, f = b.length; g < f; g++) e[g] = ib(a, b[g], c, d); else D(b) && (e = {}, q(b, function (b, f) { e[f] = ib(a, b, c, d) })); return e || null
            } function ag(a, b, c, d, e, f, g) { var h = U(), k; for (k in d) { var l = d[k], m = { $scope: l === g || l.$$isolateScope ? e : f, $element: a, $attrs: b, $transclude: c }, p = l.controller; "@" == p && (p = b[l.name]); m = t(p, m, !0, l.controllerAs); h[l.name] = m; a.data("$" + l.name + "Controller", m.instance) } return h }
            function T(a, b, c) { for (var d = 0, e = a.length; d < e; d++) a[d] = Rb(a[d], { $$isolateScope: b, $$newScope: c }) } function O(b, e, g, h, k, l, m) {
                if (e === k) return null; k = null; if (f.hasOwnProperty(e)) {
                    var p; e = a.get(e + "Directive"); for (var n = 0, r = e.length; n < r; n++) try {
                        if (p = e[n], (y(h) || h > p.priority) && -1 != p.restrict.indexOf(g)) {
                            l && (p = Rb(p, { $$start: l, $$end: m })); if (!p.$$bindings) {
                                var u = p, v = p, x = p.name, H = { isolateScope: null, bindToController: null }; D(v.scope) && (!0 === v.bindToController ? (H.bindToController = d(v.scope, x, !0), H.isolateScope = {}) :
                                H.isolateScope = d(v.scope, x, !1)); D(v.bindToController) && (H.bindToController = d(v.bindToController, x, !0)); if (D(H.bindToController)) { var E = v.controller, M = v.controllerAs; if (!E) throw ga("noctrl", x); if (!Xc(E, M)) throw ga("noident", x); } var t = u.$$bindings = H; D(t.isolateScope) && (p.$$isolateBindings = t.isolateScope)
                            } b.push(p); k = p
                        }
                    } catch (I) { c(I) }
                } return k
            } function V(b) { if (f.hasOwnProperty(b)) for (var c = a.get(b + "Directive"), d = 0, e = c.length; d < e; d++) if (b = c[d], b.multiElement) return !0; return !1 } function $(a, b) {
                var c = b.$attr,
                d = a.$attr; q(a, function (d, e) { "$" != e.charAt(0) && (b[e] && b[e] !== d && (d += ("style" === e ? ";" : " ") + b[e]), a.$set(e, d, !0, c[e])) }); q(b, function (b, e) { a.hasOwnProperty(e) || "$" === e.charAt(0) || (a[e] = b, "class" !== e && "style" !== e && (d[e] = c[e])) })
            } function ba(a, b, c, d, f, g, h, k) {
                var l = [], m, p, n = b[0], r = a.shift(), u = Rb(r, { templateUrl: null, transclude: null, replace: null, $$originalDirective: r }), H = z(r.templateUrl) ? r.templateUrl(b, c) : r.templateUrl, E = r.templateNamespace; b.empty(); e(H).then(function (e) {
                    var v, M; e = xa(e); if (r.replace) {
                        e =
                        Vb.test(e) ? $c(da(E, W(e))) : []; v = e[0]; if (1 != e.length || 1 !== v.nodeType) throw ga("tplrt", r.name, H); e = { $attr: {} }; ea(d, b, v); var B = $b(v, [], e); D(r.scope) && T(B, !0); a = B.concat(a); $(c, e)
                    } else v = n, b.html(e); a.unshift(u); m = oa(a, v, c, f, b, r, g, h, k); q(d, function (a, c) { a == v && (d[c] = b[0]) }); for (p = s(b[0].childNodes, f) ; l.length;) {
                        e = l.shift(); M = l.shift(); var t = l.shift(), I = l.shift(), B = b[0]; if (!e.$$destroyed) {
                            if (M !== n) { var P = M.className; k.hasElementTranscludeDirective && r.replace || (B = Xb(v)); ea(t, F(M), B); x(F(B), P) } M = m.transcludeOnThisElement ?
                            za(e, m.transclude, I) : I; m(p, e, B, d, M)
                        }
                    } l = null
                }); return function (a, b, c, d, e) { a = e; b.$$destroyed || (l ? l.push(b, c, d, a) : (m.transcludeOnThisElement && (a = za(b, m.transclude, e)), m(p, b, c, d, a))) }
            } function Z(a, b) { var c = b.priority - a.priority; return 0 !== c ? c : a.name !== b.name ? a.name < b.name ? -1 : 1 : a.index - b.index } function X(a, b, c, d) { function e(a) { return a ? " (module: " + a + ")" : "" } if (b) throw ga("multidir", b.name, e(b.$$moduleName), c.name, e(c.$$moduleName), a, ya(d)); } function ca(a, c) {
                var d = b(c, !0); d && a.push({
                    priority: 0, compile: function (a) {
                        a =
                        a.parent(); var b = !!a.length; b && aa.$$addBindingClass(a); return function (a, c) { var e = c.parent(); b || aa.$$addBindingClass(e); aa.$$addBindingInfo(e, d.expressions); a.$watch(d, function (a) { c[0].nodeValue = a }) }
                    }
                })
            } function da(a, b) { a = Q(a || "html"); switch (a) { case "svg": case "math": var c = C.document.createElement("div"); c.innerHTML = "<" + a + ">" + b + "</" + a + ">"; return c.childNodes[0].childNodes; default: return b } } function ha(a, b) {
                if ("srcdoc" == b) return M.HTML; var c = wa(a); if ("xlinkHref" == b || "form" == c && "action" == b || "img" !=
                c && ("src" == b || "ngSrc" == b)) return M.RESOURCE_URL
            } function ia(a, c, d, e, f) {
                var g = ha(a, e); f = k[e] || f; var h = b(d, !0, g, f); if (h) {
                    if ("multiple" === e && "select" === wa(a)) throw ga("selmulti", ya(a)); c.push({
                        priority: 100, compile: function () {
                            return {
                                pre: function (a, c, k) {
                                    c = k.$$observers || (k.$$observers = U()); if (m.test(e)) throw ga("nodomevents"); var l = k[e]; l !== d && (h = l && b(l, !0, g, f), d = l); h && (k[e] = h(a), (c[e] || (c[e] = [])).$$inter = !0, (k.$$observers && k.$$observers[e].$$scope || a).$watch(h, function (a, b) {
                                        "class" === e && a != b ? k.$updateClass(a,
                                        b) : k.$set(e, a)
                                    }))
                                }
                            }
                        }
                    })
                }
            } function ea(a, b, c) { var d = b[0], e = b.length, f = d.parentNode, g, h; if (a) for (g = 0, h = a.length; g < h; g++) if (a[g] == d) { a[g++] = c; h = g + e - 1; for (var k = a.length; g < k; g++, h++) h < k ? a[g] = a[h] : delete a[g]; a.length -= e - 1; a.context === d && (a.context = c); break } f && f.replaceChild(c, d); a = C.document.createDocumentFragment(); for (g = 0; g < e; g++) a.appendChild(b[g]); F.hasData(d) && (F.data(c, F.data(d)), F(d).off("$destroy")); F.cleanData(a.querySelectorAll("*")); for (g = 1; g < e; g++) delete b[g]; b[0] = c; b.length = 1 } function ja(a,
            b) { return S(function () { return a.apply(null, arguments) }, a, b) } function la(a, b, d, e, f, g) { try { a(b, d, e, f, g) } catch (h) { c(h, ya(d)) } } function ka(a, c, d, e, f) {
                function g(b, c, e) { z(d.$onChanges) && c !== e && (Y || (a.$$postDigest(I), Y = []), m || (m = {}, Y.push(h)), m[b] && (e = m[b].previousValue), m[b] = new Fb(e, c)) } function h() { d.$onChanges(m); m = void 0 } var k = [], l = {}, m; q(e, function (e, h) {
                    var m = e.attrName, p = e.optional, v, u, x, H; switch (e.mode) {
                        case "@": p || ua.call(c, m) || (d[h] = c[m] = void 0); c.$observe(m, function (a) {
                            if (G(a) || Ga(a)) g(h, a, d[h]),
                            d[h] = a
                        }); c.$$observers[m].$$scope = a; v = c[m]; G(v) ? d[h] = b(v)(a) : Ga(v) && (d[h] = v); l[h] = new Fb(bc, d[h]); break; case "=": if (!ua.call(c, m)) { if (p) break; c[m] = void 0 } if (p && !c[m]) break; u = n(c[m]); H = u.literal ? na : function (a, b) { return a === b || a !== a && b !== b }; x = u.assign || function () { v = d[h] = u(a); throw ga("nonassign", c[m], m, f.name); }; v = d[h] = u(a); p = function (b) { H(b, d[h]) || (H(b, v) ? x(a, b = d[h]) : d[h] = b); return v = b }; p.$stateful = !0; p = e.collection ? a.$watchCollection(c[m], p) : a.$watch(n(c[m], p), null, u.literal); k.push(p); break; case "<": if (!ua.call(c,
                        m)) { if (p) break; c[m] = void 0 } if (p && !c[m]) break; u = n(c[m]); var E = d[h] = u(a); l[h] = new Fb(bc, d[h]); p = a.$watch(u, function (a, b) { if (b === a) { if (b === E) return; b = E } g(h, a, b); d[h] = a }, u.literal); k.push(p); break; case "&": u = c.hasOwnProperty(m) ? n(c[m]) : A; if (u === A && p) break; d[h] = function (b) { return u(a, b) }
                    }
                }); return { initialChanges: l, removeWatches: k.length && function () { for (var a = 0, b = k.length; a < b; ++a) k[a]() } }
            } var ta = /^\w/, pa = C.document.createElement("div"), qa = u, Y; Da.prototype = {
                $normalize: Aa, $addClass: function (a) {
                    a && 0 < a.length &&
                    H.addClass(this.$$element, a)
                }, $removeClass: function (a) { a && 0 < a.length && H.removeClass(this.$$element, a) }, $updateClass: function (a, b) { var c = ad(a, b); c && c.length && H.addClass(this.$$element, c); (c = ad(b, a)) && c.length && H.removeClass(this.$$element, c) }, $set: function (a, b, d, e) {
                    var f = Uc(this.$$element[0], a), g = bd[a], h = a; f ? (this.$$element.prop(a, b), e = f) : g && (this[g] = b, h = g); this[a] = b; e ? this.$attr[a] = e : (e = this.$attr[a]) || (this.$attr[a] = e = Cc(a, "-")); f = wa(this.$$element); if ("a" === f && ("href" === a || "xlinkHref" === a) || "img" ===
                    f && "src" === a) this[a] = b = E(b, "src" === a); else if ("img" === f && "srcset" === a && w(b)) { for (var f = "", g = W(b), k = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/, k = /\s/.test(g) ? k : /(,)/, g = g.split(k), k = Math.floor(g.length / 2), l = 0; l < k; l++) var m = 2 * l, f = f + E(W(g[m]), !0), f = f + (" " + W(g[m + 1])); g = W(g[2 * l]).split(/\s/); f += E(W(g[0]), !0); 2 === g.length && (f += " " + W(g[1])); this[a] = b = f } !1 !== d && (null === b || y(b) ? this.$$element.removeAttr(e) : ta.test(e) ? this.$$element.attr(e, b) : P(this.$$element[0], e, b)); (a = this.$$observers) && q(a[h], function (a) { try { a(b) } catch (d) { c(d) } })
                },
                $observe: function (a, b) { var c = this, d = c.$$observers || (c.$$observers = U()), e = d[a] || (d[a] = []); e.push(b); K.$evalAsync(function () { e.$$inter || !c.hasOwnProperty(a) || y(c[a]) || b(c[a]) }); return function () { Za(e, b) } }
            }; var ra = b.startSymbol(), sa = b.endSymbol(), xa = "{{" == ra && "}}" == sa ? Xa : function (a) { return a.replace(/\{\{/g, ra).replace(/}}/g, sa) }, Ba = /^ngAttr[A-Z]/, Ca = /^(.+)Start$/; aa.$$addBindingInfo = p ? function (a, b) { var c = a.data("$binding") || []; L(b) ? c = c.concat(b) : c.push(b); a.data("$binding", c) } : A; aa.$$addBindingClass =
            p ? function (a) { x(a, "ng-binding") } : A; aa.$$addScopeInfo = p ? function (a, b, c, d) { a.data(c ? d ? "$isolateScopeNoTemplate" : "$isolateScope" : "$scope", b) } : A; aa.$$addScopeClass = p ? function (a, b) { x(a, b ? "ng-isolate-scope" : "ng-scope") } : A; aa.$$createComment = function (a, b) { var c = ""; p && (c = " " + (a || "") + ": ", b && (c += b + " ")); return C.document.createComment(c) }; return aa
        }]
    } function Fb(a, b) { this.previousValue = a; this.currentValue = b } function Aa(a) { return db(a.replace(Yc, "")) } function ad(a, b) {
        var d = "", c = a.split(/\s+/), e = b.split(/\s+/),
        f = 0; a: for (; f < c.length; f++) { for (var g = c[f], h = 0; h < e.length; h++) if (g == e[h]) continue a; d += (0 < d.length ? " " : "") + g } return d
    } function $c(a) { a = F(a); var b = a.length; if (1 >= b) return a; for (; b--;) 8 === a[b].nodeType && bg.call(a, b, 1); return a } function Xc(a, b) { if (b && G(b)) return b; if (G(a)) { var d = cd.exec(a); if (d) return d[3] } } function ff() {
        var a = {}, b = !1; this.has = function (b) { return a.hasOwnProperty(b) }; this.register = function (b, c) { Qa(b, "controller"); D(b) ? S(a, b) : a[b] = c }; this.allowGlobals = function () { b = !0 }; this.$get = ["$injector",
        "$window", function (d, c) {
            function e(a, b, c, d) { if (!a || !D(a.$scope)) throw N("$controller")("noscp", d, b); a.$scope[b] = c } return function (f, g, h, k) {
                var l, m, n; h = !0 === h; k && G(k) && (n = k); if (G(f)) { k = f.match(cd); if (!k) throw cg("ctrlfmt", f); m = k[1]; n = n || k[3]; f = a.hasOwnProperty(m) ? a[m] : Ec(g.$scope, m, !0) || (b ? Ec(c, m, !0) : void 0); Pa(f, m, !0) } if (h) return h = (L(f) ? f[f.length - 1] : f).prototype, l = Object.create(h || null), n && e(g, n, l, m || f.name), S(function () { var a = d.invoke(f, l, g, m); a !== l && (D(a) || z(a)) && (l = a, n && e(g, n, l, m || f.name)); return l },
                { instance: l, identifier: n }); l = d.instantiate(f, g, m); n && e(g, n, l, m || f.name); return l
            }
        }]
    } function gf() { this.$get = ["$window", function (a) { return F(a.document) }] } function hf() { this.$get = ["$log", function (a) { return function (b, d) { a.error.apply(a, arguments) } }] } function cc(a) { return D(a) ? da(a) ? a.toISOString() : bb(a) : a } function nf() {
        this.$get = function () {
            return function (a) {
                if (!a) return ""; var b = []; tc(a, function (a, c) { null === a || y(a) || (L(a) ? q(a, function (a) { b.push(ea(c) + "=" + ea(cc(a))) }) : b.push(ea(c) + "=" + ea(cc(a)))) });
                return b.join("&")
            }
        }
    } function of() { this.$get = function () { return function (a) { function b(a, e, f) { null === a || y(a) || (L(a) ? q(a, function (a, c) { b(a, e + "[" + (D(a) ? c : "") + "]") }) : D(a) && !da(a) ? tc(a, function (a, c) { b(a, e + (f ? "" : "[") + c + (f ? "" : "]")) }) : d.push(ea(e) + "=" + ea(cc(a)))) } if (!a) return ""; var d = []; b(a, "", !0); return d.join("&") } } } function dc(a, b) { if (G(a)) { var d = a.replace(dg, "").trim(); if (d) { var c = b("Content-Type"); (c = c && 0 === c.indexOf(dd)) || (c = (c = d.match(eg)) && fg[c[0]].test(d)); c && (a = xc(d)) } } return a } function ed(a) {
        var b =
        U(), d; G(a) ? q(a.split("\n"), function (a) { d = a.indexOf(":"); var e = Q(W(a.substr(0, d))); a = W(a.substr(d + 1)); e && (b[e] = b[e] ? b[e] + ", " + a : a) }) : D(a) && q(a, function (a, d) { var f = Q(d), g = W(a); f && (b[f] = b[f] ? b[f] + ", " + g : g) }); return b
    } function fd(a) { var b; return function (d) { b || (b = ed(a)); return d ? (d = b[Q(d)], void 0 === d && (d = null), d) : b } } function gd(a, b, d, c) { if (z(c)) return c(a, b, d); q(c, function (c) { a = c(a, b, d) }); return a } function mf() {
        var a = this.defaults = {
            transformResponse: [dc], transformRequest: [function (a) {
                return D(a) && "[object File]" !==
                ma.call(a) && "[object Blob]" !== ma.call(a) && "[object FormData]" !== ma.call(a) ? bb(a) : a
            }], headers: { common: { Accept: "application/json, text/plain, */*" }, post: ia(ec), put: ia(ec), patch: ia(ec) }, xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", paramSerializer: "$httpParamSerializer"
        }, b = !1; this.useApplyAsync = function (a) { return w(a) ? (b = !!a, this) : b }; var d = !0; this.useLegacyPromiseExtensions = function (a) { return w(a) ? (d = !!a, this) : d }; var c = this.interceptors = []; this.$get = ["$httpBackend", "$$cookieReader", "$cacheFactory",
        "$rootScope", "$q", "$injector", function (e, f, g, h, k, l) {
            function m(b) {
                function c(a, b) { for (var d = 0, e = b.length; d < e;) { var f = b[d++], g = b[d++]; a = a.then(f, g) } b.length = 0; return a } function e(a, b) { var c, d = {}; q(a, function (a, e) { z(a) ? (c = a(b), null != c && (d[e] = c)) : d[e] = a }); return d } function f(a) { var b = S({}, a); b.data = gd(a.data, a.headers, a.status, g.transformResponse); a = a.status; return 200 <= a && 300 > a ? b : k.reject(b) } if (!D(b)) throw N("$http")("badreq", b); if (!G(b.url)) throw N("$http")("badreq", b.url); var g = S({
                    method: "get", transformRequest: a.transformRequest,
                    transformResponse: a.transformResponse, paramSerializer: a.paramSerializer
                }, b); g.headers = function (b) { var c = a.headers, d = S({}, b.headers), f, g, h, c = S({}, c.common, c[Q(b.method)]); a: for (f in c) { g = Q(f); for (h in d) if (Q(h) === g) continue a; d[f] = c[f] } return e(d, ia(b)) }(b); g.method = ub(g.method); g.paramSerializer = G(g.paramSerializer) ? l.get(g.paramSerializer) : g.paramSerializer; var h = [], m = [], p = k.when(g); q(R, function (a) {
                    (a.request || a.requestError) && h.unshift(a.request, a.requestError); (a.response || a.responseError) && m.push(a.response,
                    a.responseError)
                }); p = c(p, h); p = p.then(function (b) { var c = b.headers, d = gd(b.data, fd(c), void 0, b.transformRequest); y(d) && q(c, function (a, b) { "content-type" === Q(b) && delete c[b] }); y(b.withCredentials) && !y(a.withCredentials) && (b.withCredentials = a.withCredentials); return n(b, d).then(f, f) }); p = c(p, m); d ? (p.success = function (a) { Pa(a, "fn"); p.then(function (b) { a(b.data, b.status, b.headers, g) }); return p }, p.error = function (a) { Pa(a, "fn"); p.then(null, function (b) { a(b.data, b.status, b.headers, g) }); return p }) : (p.success = hd("success"),
                p.error = hd("error")); return p
            } function n(c, d) {
                function g(a) { if (a) { var c = {}; q(a, function (a, d) { c[d] = function (c) { function d() { a(c) } b ? h.$applyAsync(d) : h.$$phase ? d() : h.$apply(d) } }); return c } } function l(a, c, d, e) { function f() { n(c, a, d, e) } E && (200 <= a && 300 > a ? E.put(P, [a, c, ed(d), e]) : E.remove(P)); b ? h.$applyAsync(f) : (f(), h.$$phase || h.$apply()) } function n(a, b, d, e) { b = -1 <= b ? b : 0; (200 <= b && 300 > b ? M.resolve : M.reject)({ data: a, status: b, headers: fd(d), config: c, statusText: e }) } function t(a) {
                    n(a.data, a.status, ia(a.headers()),
                    a.statusText)
                } function R() { var a = m.pendingRequests.indexOf(c); -1 !== a && m.pendingRequests.splice(a, 1) } var M = k.defer(), H = M.promise, E, I, Da = c.headers, P = p(c.url, c.paramSerializer(c.params)); m.pendingRequests.push(c); H.then(R, R); !c.cache && !a.cache || !1 === c.cache || "GET" !== c.method && "JSONP" !== c.method || (E = D(c.cache) ? c.cache : D(a.cache) ? a.cache : u); E && (I = E.get(P), w(I) ? I && z(I.then) ? I.then(t, t) : L(I) ? n(I[1], I[0], ia(I[2]), I[3]) : n(I, 200, {}, "OK") : E.put(P, H)); y(I) && ((I = id(c.url) ? f()[c.xsrfCookieName || a.xsrfCookieName] :
                void 0) && (Da[c.xsrfHeaderName || a.xsrfHeaderName] = I), e(c.method, P, d, l, Da, c.timeout, c.withCredentials, c.responseType, g(c.eventHandlers), g(c.uploadEventHandlers))); return H
            } function p(a, b) { 0 < b.length && (a += (-1 == a.indexOf("?") ? "?" : "&") + b); return a } var u = g("$http"); a.paramSerializer = G(a.paramSerializer) ? l.get(a.paramSerializer) : a.paramSerializer; var R = []; q(c, function (a) { R.unshift(G(a) ? l.get(a) : l.invoke(a)) }); m.pendingRequests = []; (function (a) {
                q(arguments, function (a) {
                    m[a] = function (b, c) {
                        return m(S({}, c || {},
                        { method: a, url: b }))
                    }
                })
            })("get", "delete", "head", "jsonp"); (function (a) { q(arguments, function (a) { m[a] = function (b, c, d) { return m(S({}, d || {}, { method: a, url: b, data: c })) } }) })("post", "put", "patch"); m.defaults = a; return m
        }]
    } function qf() { this.$get = function () { return function () { return new C.XMLHttpRequest } } } function pf() { this.$get = ["$browser", "$jsonpCallbacks", "$document", "$xhrFactory", function (a, b, d, c) { return gg(a, c, a.defer, b, d[0]) }] } function gg(a, b, d, c, e) {
        function f(a, b, d) {
            a = a.replace("JSON_CALLBACK", b); var f =
            e.createElement("script"), m = null; f.type = "text/javascript"; f.src = a; f.async = !0; m = function (a) { f.removeEventListener("load", m, !1); f.removeEventListener("error", m, !1); e.body.removeChild(f); f = null; var g = -1, u = "unknown"; a && ("load" !== a.type || c.wasCalled(b) || (a = { type: "error" }), u = a.type, g = "error" === a.type ? 404 : 200); d && d(g, u) }; f.addEventListener("load", m, !1); f.addEventListener("error", m, !1); e.body.appendChild(f); return m
        } return function (e, h, k, l, m, n, p, u, R, B) {
            function r() { fa && fa(); t && t.abort() } function J(b, c, e,
            f, g) { w(M) && d.cancel(M); fa = t = null; b(c, e, f, g); a.$$completeOutstandingRequest(A) } a.$$incOutstandingRequestCount(); h = h || a.url(); if ("jsonp" === Q(e)) var v = c.createCallback(h), fa = f(h, v, function (a, b) { var d = 200 === a && c.getResponse(v); J(l, a, d, "", b); c.removeCallback(v) }); else {
                var t = b(e, h); t.open(e, h, !0); q(m, function (a, b) { w(a) && t.setRequestHeader(b, a) }); t.onload = function () {
                    var a = t.statusText || "", b = "response" in t ? t.response : t.responseText, c = 1223 === t.status ? 204 : t.status; 0 === c && (c = b ? 200 : "file" == Y(h).protocol ? 404 :
                    0); J(l, c, b, t.getAllResponseHeaders(), a)
                }; e = function () { J(l, -1, null, null, "") }; t.onerror = e; t.onabort = e; q(R, function (a, b) { t.addEventListener(b, a) }); q(B, function (a, b) { t.upload.addEventListener(b, a) }); p && (t.withCredentials = !0); if (u) try { t.responseType = u } catch (K) { if ("json" !== u) throw K; } t.send(y(k) ? null : k)
            } if (0 < n) var M = d(r, n); else n && z(n.then) && n.then(r)
        }
    } function kf() {
        var a = "{{", b = "}}"; this.startSymbol = function (b) { return b ? (a = b, this) : a }; this.endSymbol = function (a) { return a ? (b = a, this) : b }; this.$get = ["$parse",
        "$exceptionHandler", "$sce", function (d, c, e) {
            function f(a) { return "\\\\\\" + a } function g(c) { return c.replace(n, a).replace(p, b) } function h(a, b, c, d) { var e; return e = a.$watch(function (a) { e(); return d(a) }, b, c) } function k(f, k, p, n) {
                function J(a) { try { var b = a; a = p ? e.getTrusted(p, b) : e.valueOf(b); var d; if (n && !w(a)) d = a; else if (null == a) d = ""; else { switch (typeof a) { case "string": break; case "number": a = "" + a; break; default: a = bb(a) } d = a } return d } catch (g) { c(Ka.interr(f, g)) } } if (!f.length || -1 === f.indexOf(a)) {
                    var v; k || (k = g(f),
                    v = ha(k), v.exp = f, v.expressions = [], v.$$watchDelegate = h); return v
                } n = !!n; var q, t, K = 0, M = [], H = []; v = f.length; for (var E = [], I = []; K < v;) if (-1 != (q = f.indexOf(a, K)) && -1 != (t = f.indexOf(b, q + l))) K !== q && E.push(g(f.substring(K, q))), K = f.substring(q + l, t), M.push(K), H.push(d(K, J)), K = t + m, I.push(E.length), E.push(""); else { K !== v && E.push(g(f.substring(K))); break } p && 1 < E.length && Ka.throwNoconcat(f); if (!k || M.length) {
                    var Da = function (a) { for (var b = 0, c = M.length; b < c; b++) { if (n && y(a[b])) return; E[I[b]] = a[b] } return E.join("") }; return S(function (a) {
                        var b =
                        0, d = M.length, e = Array(d); try { for (; b < d; b++) e[b] = H[b](a); return Da(e) } catch (g) { c(Ka.interr(f, g)) }
                    }, { exp: f, expressions: M, $$watchDelegate: function (a, b) { var c; return a.$watchGroup(H, function (d, e) { var f = Da(d); z(b) && b.call(this, f, d !== e ? c : f, a); c = f }) } })
                }
            } var l = a.length, m = b.length, n = new RegExp(a.replace(/./g, f), "g"), p = new RegExp(b.replace(/./g, f), "g"); k.startSymbol = function () { return a }; k.endSymbol = function () { return b }; return k
        }]
    } function lf() {
        this.$get = ["$rootScope", "$window", "$q", "$$q", "$browser", function (a,
        b, d, c, e) {
            function f(f, k, l, m) { function n() { p ? f.apply(null, u) : f(r) } var p = 4 < arguments.length, u = p ? va.call(arguments, 4) : [], R = b.setInterval, q = b.clearInterval, r = 0, J = w(m) && !m, v = (J ? c : d).defer(), fa = v.promise; l = w(l) ? l : 0; fa.$$intervalId = R(function () { J ? e.defer(n) : a.$evalAsync(n); v.notify(r++); 0 < l && r >= l && (v.resolve(r), q(fa.$$intervalId), delete g[fa.$$intervalId]); J || a.$apply() }, k); g[fa.$$intervalId] = v; return fa } var g = {}; f.cancel = function (a) {
                return a && a.$$intervalId in g ? (g[a.$$intervalId].reject("canceled"), b.clearInterval(a.$$intervalId),
                delete g[a.$$intervalId], !0) : !1
            }; return f
        }]
    } function fc(a) { a = a.split("/"); for (var b = a.length; b--;) a[b] = qb(a[b]); return a.join("/") } function jd(a, b) { var d = Y(a); b.$$protocol = d.protocol; b.$$host = d.hostname; b.$$port = Z(d.port) || hg[d.protocol] || null } function kd(a, b) {
        var d = "/" !== a.charAt(0); d && (a = "/" + a); var c = Y(a); b.$$path = decodeURIComponent(d && "/" === c.pathname.charAt(0) ? c.pathname.substring(1) : c.pathname); b.$$search = Ac(c.search); b.$$hash = decodeURIComponent(c.hash); b.$$path && "/" != b.$$path.charAt(0) && (b.$$path =
        "/" + b.$$path)
    } function ka(a, b) { if (0 === b.lastIndexOf(a, 0)) return b.substr(a.length) } function Ja(a) { var b = a.indexOf("#"); return -1 == b ? a : a.substr(0, b) } function jb(a) { return a.replace(/(#.+)|#$/, "$1") } function gc(a, b, d) {
        this.$$html5 = !0; d = d || ""; jd(a, this); this.$$parse = function (a) { var d = ka(b, a); if (!G(d)) throw Gb("ipthprfx", a, b); kd(d, this); this.$$path || (this.$$path = "/"); this.$$compose() }; this.$$compose = function () {
            var a = Tb(this.$$search), d = this.$$hash ? "#" + qb(this.$$hash) : ""; this.$$url = fc(this.$$path) + (a ? "?" +
                a : "") + d; this.$$absUrl = b + this.$$url.substr(1)
        }; this.$$parseLinkUrl = function (c, e) { if (e && "#" === e[0]) return this.hash(e.slice(1)), !0; var f, g; w(f = ka(a, c)) ? (g = f, g = w(f = ka(d, f)) ? b + (ka("/", f) || f) : a + g) : w(f = ka(b, c)) ? g = b + f : b == c + "/" && (g = b); g && this.$$parse(g); return !!g }
    } function hc(a, b, d) {
        jd(a, this); this.$$parse = function (c) {
            var e = ka(a, c) || ka(b, c), f; y(e) || "#" !== e.charAt(0) ? this.$$html5 ? f = e : (f = "", y(e) && (a = c, this.replace())) : (f = ka(d, e), y(f) && (f = e)); kd(f, this); c = this.$$path; var e = a, g = /^\/[A-Z]:(\/.*)/; 0 === f.lastIndexOf(e,
            0) && (f = f.replace(e, "")); g.exec(f) || (c = (f = g.exec(c)) ? f[1] : c); this.$$path = c; this.$$compose()
        }; this.$$compose = function () { var b = Tb(this.$$search), e = this.$$hash ? "#" + qb(this.$$hash) : ""; this.$$url = fc(this.$$path) + (b ? "?" + b : "") + e; this.$$absUrl = a + (this.$$url ? d + this.$$url : "") }; this.$$parseLinkUrl = function (b, d) { return Ja(a) == Ja(b) ? (this.$$parse(b), !0) : !1 }
    } function ld(a, b, d) {
        this.$$html5 = !0; hc.apply(this, arguments); this.$$parseLinkUrl = function (c, e) {
            if (e && "#" === e[0]) return this.hash(e.slice(1)), !0; var f, g; a == Ja(c) ?
            f = c : (g = ka(b, c)) ? f = a + d + g : b === c + "/" && (f = b); f && this.$$parse(f); return !!f
        }; this.$$compose = function () { var b = Tb(this.$$search), e = this.$$hash ? "#" + qb(this.$$hash) : ""; this.$$url = fc(this.$$path) + (b ? "?" + b : "") + e; this.$$absUrl = a + d + this.$$url }
    } function Hb(a) { return function () { return this[a] } } function md(a, b) { return function (d) { if (y(d)) return this[a]; this[a] = b(d); this.$$compose(); return this } } function sf() {
        var a = "", b = { enabled: !1, requireBase: !0, rewriteLinks: !0 }; this.hashPrefix = function (b) {
            return w(b) ? (a = b, this) :
            a
        }; this.html5Mode = function (a) { return Ga(a) ? (b.enabled = a, this) : D(a) ? (Ga(a.enabled) && (b.enabled = a.enabled), Ga(a.requireBase) && (b.requireBase = a.requireBase), Ga(a.rewriteLinks) && (b.rewriteLinks = a.rewriteLinks), this) : b }; this.$get = ["$rootScope", "$browser", "$sniffer", "$rootElement", "$window", function (d, c, e, f, g) {
            function h(a, b, d) { var e = l.url(), f = l.$$state; try { c.url(a, b, d), l.$$state = c.state() } catch (g) { throw l.url(e), l.$$state = f, g; } } function k(a, b) {
                d.$broadcast("$locationChangeSuccess", l.absUrl(), a, l.$$state,
                b)
            } var l, m; m = c.baseHref(); var n = c.url(), p; if (b.enabled) { if (!m && b.requireBase) throw Gb("nobase"); p = n.substring(0, n.indexOf("/", n.indexOf("//") + 2)) + (m || "/"); m = e.history ? gc : ld } else p = Ja(n), m = hc; var u = p.substr(0, Ja(p).lastIndexOf("/") + 1); l = new m(p, u, "#" + a); l.$$parseLinkUrl(n, n); l.$$state = c.state(); var R = /^\s*(javascript|mailto):/i; f.on("click", function (a) {
                if (b.rewriteLinks && !a.ctrlKey && !a.metaKey && !a.shiftKey && 2 != a.which && 2 != a.button) {
                    for (var e = F(a.target) ; "a" !== wa(e[0]) ;) if (e[0] === f[0] || !(e = e.parent())[0]) return;
                    var h = e.prop("href"), k = e.attr("href") || e.attr("xlink:href"); D(h) && "[object SVGAnimatedString]" === h.toString() && (h = Y(h.animVal).href); R.test(h) || !h || e.attr("target") || a.isDefaultPrevented() || !l.$$parseLinkUrl(h, k) || (a.preventDefault(), l.absUrl() != c.url() && (d.$apply(), g.angular["ff-684208-preventDefault"] = !0))
                }
            }); jb(l.absUrl()) != jb(n) && c.url(l.absUrl(), !0); var q = !0; c.onUrlChange(function (a, b) {
                y(ka(u, a)) ? g.location.href = a : (d.$evalAsync(function () {
                    var c = l.absUrl(), e = l.$$state, f; a = jb(a); l.$$parse(a); l.$$state =
                    b; f = d.$broadcast("$locationChangeStart", a, c, b, e).defaultPrevented; l.absUrl() === a && (f ? (l.$$parse(c), l.$$state = e, h(c, !1, e)) : (q = !1, k(c, e)))
                }), d.$$phase || d.$digest())
            }); d.$watch(function () {
                var a = jb(c.url()), b = jb(l.absUrl()), f = c.state(), g = l.$$replace, m = a !== b || l.$$html5 && e.history && f !== l.$$state; if (q || m) q = !1, d.$evalAsync(function () {
                    var b = l.absUrl(), c = d.$broadcast("$locationChangeStart", b, a, l.$$state, f).defaultPrevented; l.absUrl() === b && (c ? (l.$$parse(a), l.$$state = f) : (m && h(b, g, f === l.$$state ? null : l.$$state),
                    k(a, f)))
                }); l.$$replace = !1
            }); return l
        }]
    } function tf() {
        var a = !0, b = this; this.debugEnabled = function (b) { return w(b) ? (a = b, this) : a }; this.$get = ["$window", function (d) {
            function c(a) { a instanceof Error && (a.stack ? a = a.message && -1 === a.stack.indexOf(a.message) ? "Error: " + a.message + "\n" + a.stack : a.stack : a.sourceURL && (a = a.message + "\n" + a.sourceURL + ":" + a.line)); return a } function e(a) {
                var b = d.console || {}, e = b[a] || b.log || A; a = !1; try { a = !!e.apply } catch (k) { } return a ? function () {
                    var a = []; q(arguments, function (b) { a.push(c(b)) });
                    return e.apply(b, a)
                } : function (a, b) { e(a, null == b ? "" : b) }
            } return { log: e("log"), info: e("info"), warn: e("warn"), error: e("error"), debug: function () { var c = e("debug"); return function () { a && c.apply(b, arguments) } }() }
        }]
    } function Sa(a, b) { if ("__defineGetter__" === a || "__defineSetter__" === a || "__lookupGetter__" === a || "__lookupSetter__" === a || "__proto__" === a) throw X("isecfld", b); return a } function ig(a) { return a + "" } function ra(a, b) {
        if (a) {
            if (a.constructor === a) throw X("isecfn", b); if (a.window === a) throw X("isecwindow", b); if (a.children &&
            (a.nodeName || a.prop && a.attr && a.find)) throw X("isecdom", b); if (a === Object) throw X("isecobj", b);
        } return a
    } function nd(a, b) { if (a) { if (a.constructor === a) throw X("isecfn", b); if (a === jg || a === kg || a === lg) throw X("isecff", b); } } function Ib(a, b) { if (a && (a === (0).constructor || a === (!1).constructor || a === "".constructor || a === {}.constructor || a === [].constructor || a === Function.constructor)) throw X("isecaf", b); } function mg(a, b) { return "undefined" !== typeof a ? a : b } function od(a, b) {
        return "undefined" === typeof a ? b : "undefined" ===
        typeof b ? a : a + b
    } function V(a, b) {
        var d, c; switch (a.type) {
            case s.Program: d = !0; q(a.body, function (a) { V(a.expression, b); d = d && a.expression.constant }); a.constant = d; break; case s.Literal: a.constant = !0; a.toWatch = []; break; case s.UnaryExpression: V(a.argument, b); a.constant = a.argument.constant; a.toWatch = a.argument.toWatch; break; case s.BinaryExpression: V(a.left, b); V(a.right, b); a.constant = a.left.constant && a.right.constant; a.toWatch = a.left.toWatch.concat(a.right.toWatch); break; case s.LogicalExpression: V(a.left, b); V(a.right,
            b); a.constant = a.left.constant && a.right.constant; a.toWatch = a.constant ? [] : [a]; break; case s.ConditionalExpression: V(a.test, b); V(a.alternate, b); V(a.consequent, b); a.constant = a.test.constant && a.alternate.constant && a.consequent.constant; a.toWatch = a.constant ? [] : [a]; break; case s.Identifier: a.constant = !1; a.toWatch = [a]; break; case s.MemberExpression: V(a.object, b); a.computed && V(a.property, b); a.constant = a.object.constant && (!a.computed || a.property.constant); a.toWatch = [a]; break; case s.CallExpression: d = a.filter ? !b(a.callee.name).$stateful :
            !1; c = []; q(a.arguments, function (a) { V(a, b); d = d && a.constant; a.constant || c.push.apply(c, a.toWatch) }); a.constant = d; a.toWatch = a.filter && !b(a.callee.name).$stateful ? c : [a]; break; case s.AssignmentExpression: V(a.left, b); V(a.right, b); a.constant = a.left.constant && a.right.constant; a.toWatch = [a]; break; case s.ArrayExpression: d = !0; c = []; q(a.elements, function (a) { V(a, b); d = d && a.constant; a.constant || c.push.apply(c, a.toWatch) }); a.constant = d; a.toWatch = c; break; case s.ObjectExpression: d = !0; c = []; q(a.properties, function (a) {
                V(a.value,
                b); d = d && a.value.constant && !a.computed; a.value.constant || c.push.apply(c, a.value.toWatch)
            }); a.constant = d; a.toWatch = c; break; case s.ThisExpression: a.constant = !1; a.toWatch = []; break; case s.LocalsExpression: a.constant = !1, a.toWatch = []
        }
    } function pd(a) { if (1 == a.length) { a = a[0].expression; var b = a.toWatch; return 1 !== b.length ? b : b[0] !== a ? b : void 0 } } function qd(a) { return a.type === s.Identifier || a.type === s.MemberExpression } function rd(a) {
        if (1 === a.body.length && qd(a.body[0].expression)) return {
            type: s.AssignmentExpression,
            left: a.body[0].expression, right: { type: s.NGValueParameter }, operator: "="
        }
    } function sd(a) { return 0 === a.body.length || 1 === a.body.length && (a.body[0].expression.type === s.Literal || a.body[0].expression.type === s.ArrayExpression || a.body[0].expression.type === s.ObjectExpression) } function td(a, b) { this.astBuilder = a; this.$filter = b } function ud(a, b) { this.astBuilder = a; this.$filter = b } function Jb(a) { return "constructor" == a } function ic(a) { return z(a.valueOf) ? a.valueOf() : ng.call(a) } function uf() {
        var a = U(), b = U(), d = {
            "true": !0,
            "false": !1, "null": null, undefined: void 0
        }, c, e; this.addLiteral = function (a, b) { d[a] = b }; this.setIdentifierFns = function (a, b) { c = a; e = b; return this }; this.$get = ["$filter", function (f) {
            function g(c, d, e) {
                var g, k, H; e = e || J; switch (typeof c) {
                    case "string": H = c = c.trim(); var E = e ? b : a; g = E[H]; if (!g) {
                        ":" === c.charAt(0) && ":" === c.charAt(1) && (k = !0, c = c.substring(2)); g = e ? r : B; var q = new jc(g); g = (new kc(q, f, g)).parse(c); g.constant ? g.$$watchDelegate = p : k ? g.$$watchDelegate = g.literal ? n : m : g.inputs && (g.$$watchDelegate = l); e && (g = h(g)); E[H] =
                        g
                    } return u(g, d); case "function": return u(c, d); default: return u(A, d)
                }
            } function h(a) { function b(c, d, e, f) { var g = J; J = !0; try { return a(c, d, e, f) } finally { J = g } } if (!a) return a; b.$$watchDelegate = a.$$watchDelegate; b.assign = h(a.assign); b.constant = a.constant; b.literal = a.literal; for (var c = 0; a.inputs && c < a.inputs.length; ++c) a.inputs[c] = h(a.inputs[c]); b.inputs = a.inputs; return b } function k(a, b) { return null == a || null == b ? a === b : "object" === typeof a && (a = ic(a), "object" === typeof a) ? !1 : a === b || a !== a && b !== b } function l(a, b, c, d,
            e) { var f = d.inputs, g; if (1 === f.length) { var h = k, f = f[0]; return a.$watch(function (a) { var b = f(a); k(b, h) || (g = d(a, void 0, void 0, [b]), h = b && ic(b)); return g }, b, c, e) } for (var l = [], m = [], p = 0, n = f.length; p < n; p++) l[p] = k, m[p] = null; return a.$watch(function (a) { for (var b = !1, c = 0, e = f.length; c < e; c++) { var h = f[c](a); if (b || (b = !k(h, l[c]))) m[c] = h, l[c] = h && ic(h) } b && (g = d(a, void 0, void 0, m)); return g }, b, c, e) } function m(a, b, c, d) {
                var e, f; return e = a.$watch(function (a) { return d(a) }, function (a, c, d) {
                    f = a; z(b) && b.apply(this, arguments); w(a) &&
                    d.$$postDigest(function () { w(f) && e() })
                }, c)
            } function n(a, b, c, d) { function e(a) { var b = !0; q(a, function (a) { w(a) || (b = !1) }); return b } var f, g; return f = a.$watch(function (a) { return d(a) }, function (a, c, d) { g = a; z(b) && b.call(this, a, c, d); e(a) && d.$$postDigest(function () { e(g) && f() }) }, c) } function p(a, b, c, d) { var e; return e = a.$watch(function (a) { e(); return d(a) }, b, c) } function u(a, b) {
                if (!b) return a; var c = a.$$watchDelegate, d = !1, c = c !== n && c !== m ? function (c, e, f, g) { f = d && g ? g[0] : a(c, e, f, g); return b(f, c, e) } : function (c, d, e, f) {
                    e = a(c,
                    d, e, f); c = b(e, c, d); return w(e) ? c : e
                }; a.$$watchDelegate && a.$$watchDelegate !== l ? c.$$watchDelegate = a.$$watchDelegate : b.$stateful || (c.$$watchDelegate = l, d = !a.inputs, c.inputs = a.inputs ? a.inputs : [a]); return c
            } var R = Ba().noUnsafeEval, B = { csp: R, expensiveChecks: !1, literals: pa(d), isIdentifierStart: z(c) && c, isIdentifierContinue: z(e) && e }, r = { csp: R, expensiveChecks: !0, literals: pa(d), isIdentifierStart: z(c) && c, isIdentifierContinue: z(e) && e }, J = !1; g.$$runningExpensiveChecks = function () { return J }; return g
        }]
    } function wf() {
        this.$get =
        ["$rootScope", "$exceptionHandler", function (a, b) { return vd(function (b) { a.$evalAsync(b) }, b) }]
    } function xf() { this.$get = ["$browser", "$exceptionHandler", function (a, b) { return vd(function (b) { a.defer(b) }, b) }] } function vd(a, b) {
        function d() { this.$$state = { status: 0 } } function c(a, b) { return function (c) { b.call(a, c) } } function e(c) {
            !c.processScheduled && c.pending && (c.processScheduled = !0, a(function () {
                var a, d, e; e = c.pending; c.processScheduled = !1; c.pending = void 0; for (var f = 0, g = e.length; f < g; ++f) {
                    d = e[f][0]; a = e[f][c.status];
                    try { z(a) ? d.resolve(a(c.value)) : 1 === c.status ? d.resolve(c.value) : d.reject(c.value) } catch (h) { d.reject(h), b(h) }
                }
            }))
        } function f() { this.promise = new d } var g = N("$q", TypeError), h = function () { var a = new f; a.resolve = c(a, a.resolve); a.reject = c(a, a.reject); a.notify = c(a, a.notify); return a }; S(d.prototype, {
            then: function (a, b, c) { if (y(a) && y(b) && y(c)) return this; var d = new f; this.$$state.pending = this.$$state.pending || []; this.$$state.pending.push([d, a, b, c]); 0 < this.$$state.status && e(this.$$state); return d.promise }, "catch": function (a) {
                return this.then(null,
                a)
            }, "finally": function (a, b) { return this.then(function (b) { return l(b, !0, a) }, function (b) { return l(b, !1, a) }, b) }
        }); S(f.prototype, {
            resolve: function (a) { this.promise.$$state.status || (a === this.promise ? this.$$reject(g("qcycle", a)) : this.$$resolve(a)) }, $$resolve: function (a) {
                function d(a) { k || (k = !0, h.$$resolve(a)) } function f(a) { k || (k = !0, h.$$reject(a)) } var g, h = this, k = !1; try {
                    if (D(a) || z(a)) g = a && a.then; z(g) ? (this.promise.$$state.status = -1, g.call(a, d, f, c(this, this.notify))) : (this.promise.$$state.value = a, this.promise.$$state.status =
                    1, e(this.promise.$$state))
                } catch (l) { f(l), b(l) }
            }, reject: function (a) { this.promise.$$state.status || this.$$reject(a) }, $$reject: function (a) { this.promise.$$state.value = a; this.promise.$$state.status = 2; e(this.promise.$$state) }, notify: function (c) { var d = this.promise.$$state.pending; 0 >= this.promise.$$state.status && d && d.length && a(function () { for (var a, e, f = 0, g = d.length; f < g; f++) { e = d[f][0]; a = d[f][3]; try { e.notify(z(a) ? a(c) : c) } catch (h) { b(h) } } }) }
        }); var k = function (a, b) { var c = new f; b ? c.resolve(a) : c.reject(a); return c.promise },
        l = function (a, b, c) { var d = null; try { z(c) && (d = c()) } catch (e) { return k(e, !1) } return d && z(d.then) ? d.then(function () { return k(a, b) }, function (a) { return k(a, !1) }) : k(a, b) }, m = function (a, b, c, d) { var e = new f; e.resolve(a); return e.promise.then(b, c, d) }, n = function (a) { if (!z(a)) throw g("norslvr", a); var b = new f; a(function (a) { b.resolve(a) }, function (a) { b.reject(a) }); return b.promise }; n.prototype = d.prototype; n.defer = h; n.reject = function (a) { var b = new f; b.reject(a); return b.promise }; n.when = m; n.resolve = m; n.all = function (a) {
            var b =
            new f, c = 0, d = L(a) ? [] : {}; q(a, function (a, e) { c++; m(a).then(function (a) { d.hasOwnProperty(e) || (d[e] = a, --c || b.resolve(d)) }, function (a) { d.hasOwnProperty(e) || b.reject(a) }) }); 0 === c && b.resolve(d); return b.promise
        }; n.race = function (a) { var b = h(); q(a, function (a) { m(a).then(b.resolve, b.reject) }); return b.promise }; return n
    } function Gf() {
        this.$get = ["$window", "$timeout", function (a, b) {
            var d = a.requestAnimationFrame || a.webkitRequestAnimationFrame, c = a.cancelAnimationFrame || a.webkitCancelAnimationFrame || a.webkitCancelRequestAnimationFrame,
            e = !!d, f = e ? function (a) { var b = d(a); return function () { c(b) } } : function (a) { var c = b(a, 16.66, !1); return function () { b.cancel(c) } }; f.supported = e; return f
        }]
    } function vf() {
        function a(a) { function b() { this.$$watchers = this.$$nextSibling = this.$$childHead = this.$$childTail = null; this.$$listeners = {}; this.$$listenerCount = {}; this.$$watchersCount = 0; this.$id = ++pb; this.$$ChildScope = null } b.prototype = a; return b } var b = 10, d = N("$rootScope"), c = null, e = null; this.digestTtl = function (a) { arguments.length && (b = a); return b }; this.$get =
        ["$exceptionHandler", "$parse", "$browser", function (f, g, h) {
            function k(a) { a.currentScope.$$destroyed = !0 } function l(a) { 9 === Ea && (a.$$childHead && l(a.$$childHead), a.$$nextSibling && l(a.$$nextSibling)); a.$parent = a.$$nextSibling = a.$$prevSibling = a.$$childHead = a.$$childTail = a.$root = a.$$watchers = null } function m() {
                this.$id = ++pb; this.$$phase = this.$parent = this.$$watchers = this.$$nextSibling = this.$$prevSibling = this.$$childHead = this.$$childTail = null; this.$root = this; this.$$destroyed = !1; this.$$listeners = {}; this.$$listenerCount =
                {}; this.$$watchersCount = 0; this.$$isolateBindings = null
            } function n(a) { if (J.$$phase) throw d("inprog", J.$$phase); J.$$phase = a } function p(a, b) { do a.$$watchersCount += b; while (a = a.$parent) } function u(a, b, c) { do a.$$listenerCount[c] -= b, 0 === a.$$listenerCount[c] && delete a.$$listenerCount[c]; while (a = a.$parent) } function s() { } function B() { for (; t.length;) try { t.shift()() } catch (a) { f(a) } e = null } function r() { null === e && (e = h.defer(function () { J.$apply(B) })) } m.prototype = {
                constructor: m, $new: function (b, c) {
                    var d; c = c || this; b ?
                    (d = new m, d.$root = this.$root) : (this.$$ChildScope || (this.$$ChildScope = a(this)), d = new this.$$ChildScope); d.$parent = c; d.$$prevSibling = c.$$childTail; c.$$childHead ? (c.$$childTail.$$nextSibling = d, c.$$childTail = d) : c.$$childHead = c.$$childTail = d; (b || c != this) && d.$on("$destroy", k); return d
                }, $watch: function (a, b, d, e) {
                    var f = g(a); if (f.$$watchDelegate) return f.$$watchDelegate(this, b, d, f, a); var h = this, k = h.$$watchers, l = { fn: b, last: s, get: f, exp: e || a, eq: !!d }; c = null; z(b) || (l.fn = A); k || (k = h.$$watchers = []); k.unshift(l); p(this,
                    1); return function () { 0 <= Za(k, l) && p(h, -1); c = null }
                }, $watchGroup: function (a, b) { function c() { h = !1; k ? (k = !1, b(e, e, g)) : b(e, d, g) } var d = Array(a.length), e = Array(a.length), f = [], g = this, h = !1, k = !0; if (!a.length) { var l = !0; g.$evalAsync(function () { l && b(e, e, g) }); return function () { l = !1 } } if (1 === a.length) return this.$watch(a[0], function (a, c, f) { e[0] = a; d[0] = c; b(e, a === c ? e : d, f) }); q(a, function (a, b) { var k = g.$watch(a, function (a, f) { e[b] = a; d[b] = f; h || (h = !0, g.$evalAsync(c)) }); f.push(k) }); return function () { for (; f.length;) f.shift()() } },
                $watchCollection: function (a, b) {
                    function c(a) { e = a; var b, d, g, h; if (!y(e)) { if (D(e)) if (ta(e)) for (f !== n && (f = n, u = f.length = 0, l++), a = e.length, u !== a && (l++, f.length = u = a), b = 0; b < a; b++) h = f[b], g = e[b], d = h !== h && g !== g, d || h === g || (l++, f[b] = g); else { f !== p && (f = p = {}, u = 0, l++); a = 0; for (b in e) ua.call(e, b) && (a++, g = e[b], h = f[b], b in f ? (d = h !== h && g !== g, d || h === g || (l++, f[b] = g)) : (u++, f[b] = g, l++)); if (u > a) for (b in l++, f) ua.call(e, b) || (u--, delete f[b]) } else f !== e && (f = e, l++); return l } } c.$stateful = !0; var d = this, e, f, h, k = 1 < b.length, l = 0, m =
                    g(a, c), n = [], p = {}, r = !0, u = 0; return this.$watch(m, function () { r ? (r = !1, b(e, e, d)) : b(e, h, d); if (k) if (D(e)) if (ta(e)) { h = Array(e.length); for (var a = 0; a < e.length; a++) h[a] = e[a] } else for (a in h = {}, e) ua.call(e, a) && (h[a] = e[a]); else h = e })
                }, $digest: function () {
                    var a, g, k, l, m, p, u, r, q = b, t, y = [], A, C; n("$digest"); h.$$checkUrlChange(); this === J && null !== e && (h.defer.cancel(e), B()); c = null; do {
                        r = !1; t = this; for (p = 0; p < v.length; p++) { try { C = v[p], C.scope.$eval(C.expression, C.locals) } catch (F) { f(F) } c = null } v.length = 0; a: do {
                            if (p = t.$$watchers) for (u =
                            p.length; u--;) try { if (a = p[u]) if (m = a.get, (g = m(t)) !== (k = a.last) && !(a.eq ? na(g, k) : "number" === typeof g && "number" === typeof k && isNaN(g) && isNaN(k))) r = !0, c = a, a.last = a.eq ? pa(g, null) : g, l = a.fn, l(g, k === s ? g : k, t), 5 > q && (A = 4 - q, y[A] || (y[A] = []), y[A].push({ msg: z(a.exp) ? "fn: " + (a.exp.name || a.exp.toString()) : a.exp, newVal: g, oldVal: k })); else if (a === c) { r = !1; break a } } catch (G) { f(G) } if (!(p = t.$$watchersCount && t.$$childHead || t !== this && t.$$nextSibling)) for (; t !== this && !(p = t.$$nextSibling) ;) t = t.$parent
                        } while (t = p); if ((r || v.length) &&
                        !q--) throw J.$$phase = null, d("infdig", b, y);
                    } while (r || v.length); for (J.$$phase = null; K < w.length;) try { w[K++]() } catch (D) { f(D) } w.length = K = 0
                }, $destroy: function () {
                    if (!this.$$destroyed) {
                        var a = this.$parent; this.$broadcast("$destroy"); this.$$destroyed = !0; this === J && h.$$applicationDestroyed(); p(this, -this.$$watchersCount); for (var b in this.$$listenerCount) u(this, this.$$listenerCount[b], b); a && a.$$childHead == this && (a.$$childHead = this.$$nextSibling); a && a.$$childTail == this && (a.$$childTail = this.$$prevSibling); this.$$prevSibling &&
                        (this.$$prevSibling.$$nextSibling = this.$$nextSibling); this.$$nextSibling && (this.$$nextSibling.$$prevSibling = this.$$prevSibling); this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = A; this.$on = this.$watch = this.$watchGroup = function () { return A }; this.$$listeners = {}; this.$$nextSibling = null; l(this)
                    }
                }, $eval: function (a, b) { return g(a)(this, b) }, $evalAsync: function (a, b) { J.$$phase || v.length || h.defer(function () { v.length && J.$digest() }); v.push({ scope: this, expression: g(a), locals: b }) }, $$postDigest: function (a) { w.push(a) },
                $apply: function (a) { try { n("$apply"); try { return this.$eval(a) } finally { J.$$phase = null } } catch (b) { f(b) } finally { try { J.$digest() } catch (c) { throw f(c), c; } } }, $applyAsync: function (a) { function b() { c.$eval(a) } var c = this; a && t.push(b); a = g(a); r() }, $on: function (a, b) { var c = this.$$listeners[a]; c || (this.$$listeners[a] = 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 () { var d = c.indexOf(b); -1 !== d && (c[d] = null, u(e, 1, a)) } }, $emit: function (a,
                b) { var c = [], d, e = this, g = !1, h = { name: a, targetScope: e, stopPropagation: function () { g = !0 }, preventDefault: function () { h.defaultPrevented = !0 }, defaultPrevented: !1 }, k = $a([h], arguments, 1), l, m; do { d = e.$$listeners[a] || c; h.currentScope = e; l = 0; for (m = d.length; l < m; l++) if (d[l]) try { d[l].apply(null, k) } catch (n) { f(n) } else d.splice(l, 1), l--, m--; if (g) return h.currentScope = null, h; e = e.$parent } while (e); h.currentScope = null; return h }, $broadcast: function (a, b) {
                    var c = this, d = this, e = {
                        name: a, targetScope: this, preventDefault: function () {
                            e.defaultPrevented =
                            !0
                        }, defaultPrevented: !1
                    }; if (!this.$$listenerCount[a]) return e; for (var g = $a([e], arguments, 1), h, k; c = d;) { e.currentScope = c; d = c.$$listeners[a] || []; h = 0; for (k = d.length; h < k; h++) if (d[h]) try { d[h].apply(null, g) } catch (l) { f(l) } else d.splice(h, 1), h--, k--; if (!(d = c.$$listenerCount[a] && c.$$childHead || c !== this && c.$$nextSibling)) for (; c !== this && !(d = c.$$nextSibling) ;) c = c.$parent } e.currentScope = null; return e
                }
            }; var J = new m, v = J.$$asyncQueue = [], w = J.$$postDigestQueue = [], t = J.$$applyAsyncQueue = [], K = 0; return J
        }]
    } function ne() {
        var a =
        /^\s*(https?|ftp|mailto|tel|file):/, b = /^\s*((https?|ftp|file|blob):|data:image\/)/; this.aHrefSanitizationWhitelist = function (b) { return w(b) ? (a = b, this) : a }; this.imgSrcSanitizationWhitelist = function (a) { return w(a) ? (b = a, this) : b }; this.$get = function () { return function (d, c) { var e = c ? b : a, f; f = Y(d).href; return "" === f || f.match(e) ? d : "unsafe:" + f } }
    } function og(a) {
        if ("self" === a) return a; if (G(a)) {
            if (-1 < a.indexOf("***")) throw sa("iwcard", a); a = wd(a).replace("\\*\\*", ".*").replace("\\*", "[^:/.?&;]*"); return new RegExp("^" +
            a + "$")
        } if (Wa(a)) return new RegExp("^" + a.source + "$"); throw sa("imatcher");
    } function xd(a) { var b = []; w(a) && q(a, function (a) { b.push(og(a)) }); return b } function zf() {
        this.SCE_CONTEXTS = la; var a = ["self"], b = []; this.resourceUrlWhitelist = function (b) { arguments.length && (a = xd(b)); return a }; this.resourceUrlBlacklist = function (a) { arguments.length && (b = xd(a)); return b }; this.$get = ["$injector", function (d) {
            function c(a, b) { return "self" === a ? id(b) : !!a.exec(b.href) } function e(a) {
                var b = function (a) {
                    this.$$unwrapTrustedValue =
                    function () { return a }
                }; a && (b.prototype = new a); b.prototype.valueOf = function () { return this.$$unwrapTrustedValue() }; b.prototype.toString = function () { return this.$$unwrapTrustedValue().toString() }; return b
            } var f = function (a) { throw sa("unsafe"); }; d.has("$sanitize") && (f = d.get("$sanitize")); var g = e(), h = {}; h[la.HTML] = e(g); h[la.CSS] = e(g); h[la.URL] = e(g); h[la.JS] = e(g); h[la.RESOURCE_URL] = e(h[la.URL]); return {
                trustAs: function (a, b) {
                    var c = h.hasOwnProperty(a) ? h[a] : null; if (!c) throw sa("icontext", a, b); if (null === b || y(b) ||
                    "" === b) return b; if ("string" !== typeof b) throw sa("itype", a); return new c(b)
                }, getTrusted: function (d, e) { if (null === e || y(e) || "" === e) return e; var g = h.hasOwnProperty(d) ? h[d] : null; if (g && e instanceof g) return e.$$unwrapTrustedValue(); if (d === la.RESOURCE_URL) { var g = Y(e.toString()), n, p, u = !1; n = 0; for (p = a.length; n < p; n++) if (c(a[n], g)) { u = !0; break } if (u) for (n = 0, p = b.length; n < p; n++) if (c(b[n], g)) { u = !1; break } if (u) return e; throw sa("insecurl", e.toString()); } if (d === la.HTML) return f(e); throw sa("unsafe"); }, valueOf: function (a) {
                    return a instanceof
                    g ? a.$$unwrapTrustedValue() : a
                }
            }
        }]
    } function yf() {
        var a = !0; this.enabled = function (b) { arguments.length && (a = !!b); return a }; this.$get = ["$parse", "$sceDelegate", function (b, d) {
            if (a && 8 > Ea) throw sa("iequirks"); var c = ia(la); c.isEnabled = function () { return a }; c.trustAs = d.trustAs; c.getTrusted = d.getTrusted; c.valueOf = d.valueOf; a || (c.trustAs = c.getTrusted = function (a, b) { return b }, c.valueOf = Xa); c.parseAs = function (a, d) { var e = b(d); return e.literal && e.constant ? e : b(d, function (b) { return c.getTrusted(a, b) }) }; var e = c.parseAs,
            f = c.getTrusted, g = c.trustAs; q(la, function (a, b) { var d = Q(b); c[db("parse_as_" + d)] = function (b) { return e(a, b) }; c[db("get_trusted_" + d)] = function (b) { return f(a, b) }; c[db("trust_as_" + d)] = function (b) { return g(a, b) } }); return c
        }]
    } function Af() {
        this.$get = ["$window", "$document", function (a, b) {
            var d = {}, c = !(a.chrome && a.chrome.app && a.chrome.app.runtime) && a.history && a.history.pushState, e = Z((/android (\d+)/.exec(Q((a.navigator || {}).userAgent)) || [])[1]), f = /Boxee/i.test((a.navigator || {}).userAgent), g = b[0] || {}, h, k = /^(Moz|webkit|ms)(?=[A-Z])/,
            l = g.body && g.body.style, m = !1, n = !1; if (l) { for (var p in l) if (m = k.exec(p)) { h = m[0]; h = h[0].toUpperCase() + h.substr(1); break } h || (h = "WebkitOpacity" in l && "webkit"); m = !!("transition" in l || h + "Transition" in l); n = !!("animation" in l || h + "Animation" in l); !e || m && n || (m = G(l.webkitTransition), n = G(l.webkitAnimation)) } return { history: !(!c || 4 > e || f), hasEvent: function (a) { if ("input" === a && 11 >= Ea) return !1; if (y(d[a])) { var b = g.createElement("div"); d[a] = "on" + a in b } return d[a] }, csp: Ba(), vendorPrefix: h, transitions: m, animations: n, android: e }
        }]
    }
    function Cf() {
        var a; this.httpOptions = function (b) { return b ? (a = b, this) : a }; this.$get = ["$templateCache", "$http", "$q", "$sce", function (b, d, c, e) {
            function f(g, h) {
                f.totalPendingRequests++; if (!G(g) || y(b.get(g))) g = e.getTrustedResourceUrl(g); var k = d.defaults && d.defaults.transformResponse; L(k) ? k = k.filter(function (a) { return a !== dc }) : k === dc && (k = null); return d.get(g, S({ cache: b, transformResponse: k }, a))["finally"](function () { f.totalPendingRequests-- }).then(function (a) { b.put(g, a.data); return a.data }, function (a) {
                    if (!h) throw pg("tpload",
                    g, a.status, a.statusText); return c.reject(a)
                })
            } f.totalPendingRequests = 0; return f
        }]
    } function Df() {
        this.$get = ["$rootScope", "$browser", "$location", function (a, b, d) {
            return {
                findBindings: function (a, b, d) { a = a.getElementsByClassName("ng-binding"); var g = []; q(a, function (a) { var c = ca.element(a).data("$binding"); c && q(c, function (c) { d ? (new RegExp("(^|\\s)" + wd(b) + "(\\s|\\||$)")).test(c) && g.push(a) : -1 != c.indexOf(b) && g.push(a) }) }); return g }, findModels: function (a, b, d) {
                    for (var g = ["ng-", "data-ng-", "ng\\:"], h = 0; h < g.length; ++h) {
                        var k =
                        a.querySelectorAll("[" + g[h] + "model" + (d ? "=" : "*=") + '"' + b + '"]'); if (k.length) return k
                    }
                }, getLocation: function () { return d.url() }, setLocation: function (b) { b !== d.url() && (d.url(b), a.$digest()) }, whenStable: function (a) { b.notifyWhenNoOutstandingRequests(a) }
            }
        }]
    } function Ef() {
        this.$get = ["$rootScope", "$browser", "$q", "$$q", "$exceptionHandler", function (a, b, d, c, e) {
            function f(f, k, l) {
                z(f) || (l = k, k = f, f = A); var m = va.call(arguments, 3), n = w(l) && !l, p = (n ? c : d).defer(), u = p.promise, q; q = b.defer(function () {
                    try {
                        p.resolve(f.apply(null,
                        m))
                    } catch (b) { p.reject(b), e(b) } finally { delete g[u.$$timeoutId] } n || a.$apply()
                }, k); u.$$timeoutId = q; g[q] = p; return u
            } var g = {}; f.cancel = function (a) { return a && a.$$timeoutId in g ? (g[a.$$timeoutId].reject("canceled"), delete g[a.$$timeoutId], b.defer.cancel(a.$$timeoutId)) : !1 }; return f
        }]
    } function Y(a) {
        Ea && ($.setAttribute("href", a), a = $.href); $.setAttribute("href", a); return {
            href: $.href, protocol: $.protocol ? $.protocol.replace(/:$/, "") : "", host: $.host, search: $.search ? $.search.replace(/^\?/, "") : "", hash: $.hash ? $.hash.replace(/^#/,
            "") : "", hostname: $.hostname, port: $.port, pathname: "/" === $.pathname.charAt(0) ? $.pathname : "/" + $.pathname
        }
    } function id(a) { a = G(a) ? Y(a) : a; return a.protocol === yd.protocol && a.host === yd.host } function Ff() { this.$get = ha(C) } function zd(a) {
        function b(a) { try { return decodeURIComponent(a) } catch (b) { return a } } var d = a[0] || {}, c = {}, e = ""; return function () {
            var a, g, h, k, l; a = d.cookie || ""; if (a !== e) for (e = a, a = e.split("; "), c = {}, h = 0; h < a.length; h++) g = a[h], k = g.indexOf("="), 0 < k && (l = b(g.substring(0, k)), y(c[l]) && (c[l] = b(g.substring(k +
            1)))); return c
        }
    } function Jf() { this.$get = zd } function Mc(a) { function b(d, c) { if (D(d)) { var e = {}; q(d, function (a, c) { e[c] = b(c, a) }); return e } return a.factory(d + "Filter", c) } this.register = b; this.$get = ["$injector", function (a) { return function (b) { return a.get(b + "Filter") } }]; b("currency", Ad); b("date", Bd); b("filter", qg); b("json", rg); b("limitTo", sg); b("lowercase", tg); b("number", Cd); b("orderBy", Dd); b("uppercase", ug) } function qg() {
        return function (a, b, d, c) {
            if (!ta(a)) {
                if (null == a) return a; throw N("filter")("notarray",
                a);
            } c = c || "$"; var e; switch (lc(b)) { case "function": break; case "boolean": case "null": case "number": case "string": e = !0; case "object": b = vg(b, d, c, e); break; default: return a } return Array.prototype.filter.call(a, b)
        }
    } function vg(a, b, d, c) { var e = D(a) && d in a; !0 === b ? b = na : z(b) || (b = function (a, b) { if (y(a)) return !1; if (null === a || null === b) return a === b; if (D(b) || D(a) && !vc(a)) return !1; a = Q("" + a); b = Q("" + b); return -1 !== a.indexOf(b) }); return function (f) { return e && !D(f) ? La(f, a[d], b, d, !1) : La(f, a, b, d, c) } } function La(a, b, d, c, e,
    f) { var g = lc(a), h = lc(b); if ("string" === h && "!" === b.charAt(0)) return !La(a, b.substring(1), d, c, e); if (L(a)) return a.some(function (a) { return La(a, b, d, c, e) }); switch (g) { case "object": var k; if (e) { for (k in a) if ("$" !== k.charAt(0) && La(a[k], b, d, c, !0)) return !0; return f ? !1 : La(a, b, d, c, !1) } if ("object" === h) { for (k in b) if (f = b[k], !z(f) && !y(f) && (g = k === c, !La(g ? a : a[k], f, d, c, g, g))) return !1; return !0 } return d(a, b); case "function": return !1; default: return d(a, b) } } function lc(a) { return null === a ? "null" : typeof a } function Ad(a) {
        var b =
        a.NUMBER_FORMATS; return function (a, c, e) { y(c) && (c = b.CURRENCY_SYM); y(e) && (e = b.PATTERNS[1].maxFrac); return null == a ? a : Ed(a, b.PATTERNS[1], b.GROUP_SEP, b.DECIMAL_SEP, e).replace(/\u00A4/g, c) }
    } function Cd(a) { var b = a.NUMBER_FORMATS; return function (a, c) { return null == a ? a : Ed(a, b.PATTERNS[0], b.GROUP_SEP, b.DECIMAL_SEP, c) } } function wg(a) {
        var b = 0, d, c, e, f, g; -1 < (c = a.indexOf(Fd)) && (a = a.replace(Fd, "")); 0 < (e = a.search(/e/i)) ? (0 > c && (c = e), c += +a.slice(e + 1), a = a.substring(0, e)) : 0 > c && (c = a.length); for (e = 0; a.charAt(e) == mc; e++);
        if (e == (g = a.length)) d = [0], c = 1; else { for (g--; a.charAt(g) == mc;) g--; c -= e; d = []; for (f = 0; e <= g; e++, f++) d[f] = +a.charAt(e) } c > Gd && (d = d.splice(0, Gd - 1), b = c - 1, c = 1); return { d: d, e: b, i: c }
    } function xg(a, b, d, c) {
        var e = a.d, f = e.length - a.i; b = y(b) ? Math.min(Math.max(d, f), c) : +b; d = b + a.i; c = e[d]; if (0 < d) { e.splice(Math.max(a.i, d)); for (var g = d; g < e.length; g++) e[g] = 0 } else for (f = Math.max(0, f), a.i = 1, e.length = Math.max(1, d = b + 1), e[0] = 0, g = 1; g < d; g++) e[g] = 0; if (5 <= c) if (0 > d - 1) { for (c = 0; c > d; c--) e.unshift(0), a.i++; e.unshift(1); a.i++ } else e[d - 1]++;
        for (; f < Math.max(0, b) ; f++) e.push(0); if (b = e.reduceRight(function (a, b, c, d) { b += a; d[c] = b % 10; return Math.floor(b / 10) }, 0)) e.unshift(b), a.i++
    } function Ed(a, b, d, c, e) {
        if (!G(a) && !T(a) || isNaN(a)) return ""; var f = !isFinite(a), g = !1, h = Math.abs(a) + "", k = ""; if (f) k = "\u221e"; else {
            g = wg(h); xg(g, e, b.minFrac, b.maxFrac); k = g.d; h = g.i; e = g.e; f = []; for (g = k.reduce(function (a, b) { return a && !b }, !0) ; 0 > h;) k.unshift(0), h++; 0 < h ? f = k.splice(h, k.length) : (f = k, k = [0]); h = []; for (k.length >= b.lgSize && h.unshift(k.splice(-b.lgSize, k.length).join("")) ; k.length >
            b.gSize;) h.unshift(k.splice(-b.gSize, k.length).join("")); k.length && h.unshift(k.join("")); k = h.join(d); f.length && (k += c + f.join("")); e && (k += "e+" + e)
        } return 0 > a && !g ? b.negPre + k + b.negSuf : b.posPre + k + b.posSuf
    } function Kb(a, b, d, c) { var e = ""; if (0 > a || c && 0 >= a) c ? a = -a + 1 : (a = -a, e = "-"); for (a = "" + a; a.length < b;) a = mc + a; d && (a = a.substr(a.length - b)); return e + a } function ba(a, b, d, c, e) { d = d || 0; return function (f) { f = f["get" + a](); if (0 < d || f > -d) f += d; 0 === f && -12 == d && (f = 12); return Kb(f, b, c, e) } } function kb(a, b, d) {
        return function (c, e) {
            var f =
            c["get" + a](), g = ub((d ? "STANDALONE" : "") + (b ? "SHORT" : "") + a); return e[g][f]
        }
    } function Hd(a) { var b = (new Date(a, 0, 1)).getDay(); return new Date(a, 0, (4 >= b ? 5 : 12) - b) } function Id(a) { return function (b) { var d = Hd(b.getFullYear()); b = +new Date(b.getFullYear(), b.getMonth(), b.getDate() + (4 - b.getDay())) - +d; b = 1 + Math.round(b / 6048E5); return Kb(b, a) } } function nc(a, b) { return 0 >= a.getFullYear() ? b.ERAS[0] : b.ERAS[1] } function Bd(a) {
        function b(a) {
            var b; if (b = a.match(d)) {
                a = new Date(0); var f = 0, g = 0, h = b[8] ? a.setUTCFullYear : a.setFullYear,
                k = b[8] ? a.setUTCHours : a.setHours; b[9] && (f = Z(b[9] + b[10]), g = Z(b[9] + b[11])); h.call(a, Z(b[1]), Z(b[2]) - 1, Z(b[3])); f = Z(b[4] || 0) - f; g = Z(b[5] || 0) - g; h = Z(b[6] || 0); b = Math.round(1E3 * parseFloat("0." + (b[7] || 0))); k.call(a, f, g, h, b)
            } return a
        } var d = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; return function (c, d, f) {
            var g = "", h = [], k, l; d = d || "mediumDate"; d = a.DATETIME_FORMATS[d] || d; G(c) && (c = yg.test(c) ? Z(c) : b(c)); T(c) && (c = new Date(c)); if (!da(c) || !isFinite(c.getTime())) return c;
            for (; d;) (l = zg.exec(d)) ? (h = $a(h, l, 1), d = h.pop()) : (h.push(d), d = null); var m = c.getTimezoneOffset(); f && (m = yc(f, m), c = Sb(c, f, !0)); q(h, function (b) { k = Ag[b]; g += k ? k(c, a.DATETIME_FORMATS, m) : "''" === b ? "'" : b.replace(/(^'|'$)/g, "").replace(/''/g, "'") }); return g
        }
    } function rg() { return function (a, b) { y(b) && (b = 2); return bb(a, b) } } function sg() {
        return function (a, b, d) {
            b = Infinity === Math.abs(Number(b)) ? Number(b) : Z(b); if (isNaN(b)) return a; T(a) && (a = a.toString()); if (!ta(a)) return a; d = !d || isNaN(d) ? 0 : Z(d); d = 0 > d ? Math.max(0, a.length +
            d) : d; return 0 <= b ? oc(a, d, d + b) : 0 === d ? oc(a, b, a.length) : oc(a, Math.max(0, d + b), d)
        }
    } function oc(a, b, d) { return G(a) ? a.slice(b, d) : va.call(a, b, d) } function Dd(a) {
        function b(b) { return b.map(function (b) { var c = 1, d = Xa; if (z(b)) d = b; else if (G(b)) { if ("+" == b.charAt(0) || "-" == b.charAt(0)) c = "-" == b.charAt(0) ? -1 : 1, b = b.substring(1); if ("" !== b && (d = a(b), d.constant)) var e = d(), d = function (a) { return a[e] } } return { get: d, descending: c } }) } function d(a) { switch (typeof a) { case "number": case "boolean": case "string": return !0; default: return !1 } }
        function c(a, b) { var c = 0, d = a.type, k = b.type; if (d === k) { var k = a.value, l = b.value; "string" === d ? (k = k.toLowerCase(), l = l.toLowerCase()) : "object" === d && (D(k) && (k = a.index), D(l) && (l = b.index)); k !== l && (c = k < l ? -1 : 1) } else c = d < k ? -1 : 1; return c } return function (a, f, g, h) {
            if (null == a) return a; if (!ta(a)) throw N("orderBy")("notarray", a); L(f) || (f = [f]); 0 === f.length && (f = ["+"]); var k = b(f), l = g ? -1 : 1, m = z(h) ? h : c; a = Array.prototype.map.call(a, function (a, b) {
                return {
                    value: a, tieBreaker: { value: b, type: "number", index: b }, predicateValues: k.map(function (c) {
                        var e =
                        c.get(a); c = typeof e; if (null === e) c = "string", e = "null"; else if ("object" === c) a: { if (z(e.valueOf) && (e = e.valueOf(), d(e))) break a; vc(e) && (e = e.toString(), d(e)) } return { value: e, type: c, index: b }
                    })
                }
            }); a.sort(function (a, b) { for (var c = 0, d = k.length; c < d; c++) { var e = m(a.predicateValues[c], b.predicateValues[c]); if (e) return e * k[c].descending * l } return m(a.tieBreaker, b.tieBreaker) * l }); return a = a.map(function (a) { return a.value })
        }
    } function Ta(a) { z(a) && (a = { link: a }); a.restrict = a.restrict || "AC"; return ha(a) } function Jd(a, b, d,
    c, e) {
        var f = this, g = []; f.$error = {}; f.$$success = {}; f.$pending = void 0; f.$name = e(b.name || b.ngForm || "")(d); f.$dirty = !1; f.$pristine = !0; f.$valid = !0; f.$invalid = !1; f.$submitted = !1; f.$$parentForm = Lb; f.$rollbackViewValue = function () { q(g, function (a) { a.$rollbackViewValue() }) }; f.$commitViewValue = function () { q(g, function (a) { a.$commitViewValue() }) }; f.$addControl = function (a) { Qa(a.$name, "input"); g.push(a); a.$name && (f[a.$name] = a); a.$$parentForm = f }; f.$$renameControl = function (a, b) {
            var c = a.$name; f[c] === a && delete f[c]; f[b] =
            a; a.$name = b
        }; f.$removeControl = function (a) { a.$name && f[a.$name] === a && delete f[a.$name]; q(f.$pending, function (b, c) { f.$setValidity(c, null, a) }); q(f.$error, function (b, c) { f.$setValidity(c, null, a) }); q(f.$$success, function (b, c) { f.$setValidity(c, null, a) }); Za(g, a); a.$$parentForm = Lb }; Kd({ ctrl: this, $element: a, set: function (a, b, c) { var d = a[b]; d ? -1 === d.indexOf(c) && d.push(c) : a[b] = [c] }, unset: function (a, b, c) { var d = a[b]; d && (Za(d, c), 0 === d.length && delete a[b]) }, $animate: c }); f.$setDirty = function () {
            c.removeClass(a, Ua); c.addClass(a,
            Mb); f.$dirty = !0; f.$pristine = !1; f.$$parentForm.$setDirty()
        }; f.$setPristine = function () { c.setClass(a, Ua, Mb + " ng-submitted"); f.$dirty = !1; f.$pristine = !0; f.$submitted = !1; q(g, function (a) { a.$setPristine() }) }; f.$setUntouched = function () { q(g, function (a) { a.$setUntouched() }) }; f.$setSubmitted = function () { c.addClass(a, "ng-submitted"); f.$submitted = !0; f.$$parentForm.$setSubmitted() }
    } function pc(a) { a.$formatters.push(function (b) { return a.$isEmpty(b) ? b : b.toString() }) } function lb(a, b, d, c, e, f) {
        var g = Q(b[0].type); if (!e.android) {
            var h =
            !1; b.on("compositionstart", function () { h = !0 }); b.on("compositionend", function () { h = !1; l() })
        } var k, l = function (a) { k && (f.defer.cancel(k), k = null); if (!h) { var e = b.val(); a = a && a.type; "password" === g || d.ngTrim && "false" === d.ngTrim || (e = W(e)); (c.$viewValue !== e || "" === e && c.$$hasNativeValidators) && c.$setViewValue(e, a) } }; if (e.hasEvent("input")) b.on("input", l); else {
            var m = function (a, b, c) { k || (k = f.defer(function () { k = null; b && b.value === c || l(a) })) }; b.on("keydown", function (a) {
                var b = a.keyCode; 91 === b || 15 < b && 19 > b || 37 <= b && 40 >= b ||
                m(a, this, this.value)
            }); if (e.hasEvent("paste")) b.on("paste cut", m)
        } b.on("change", l); if (Ld[g] && c.$$hasNativeValidators && g === d.type) b.on("keydown wheel mousedown", function (a) { if (!k) { var b = this.validity, c = b.badInput, d = b.typeMismatch; k = f.defer(function () { k = null; b.badInput === c && b.typeMismatch === d || l(a) }) } }); c.$render = function () { var a = c.$isEmpty(c.$viewValue) ? "" : c.$viewValue; b.val() !== a && b.val(a) }
    } function Nb(a, b) {
        return function (d, c) {
            var e, f; if (da(d)) return d; if (G(d)) {
                '"' == d.charAt(0) && '"' == d.charAt(d.length -
                1) && (d = d.substring(1, d.length - 1)); if (Bg.test(d)) return new Date(d); a.lastIndex = 0; if (e = a.exec(d)) return e.shift(), f = c ? { yyyy: c.getFullYear(), MM: c.getMonth() + 1, dd: c.getDate(), HH: c.getHours(), mm: c.getMinutes(), ss: c.getSeconds(), sss: c.getMilliseconds() / 1E3 } : { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }, q(e, function (a, c) { c < b.length && (f[b[c]] = +a) }), new Date(f.yyyy, f.MM - 1, f.dd, f.HH, f.mm, f.ss || 0, 1E3 * f.sss || 0)
            } return NaN
        }
    } function mb(a, b, d, c) {
        return function (e, f, g, h, k, l, m) {
            function n(a) {
                return a && !(a.getTime &&
                a.getTime() !== a.getTime())
            } function p(a) { return w(a) && !da(a) ? d(a) || void 0 : a } Md(e, f, g, h); lb(e, f, g, h, k, l); var u = h && h.$options && h.$options.timezone, q; h.$$parserName = a; h.$parsers.push(function (a) { if (h.$isEmpty(a)) return null; if (b.test(a)) return a = d(a, q), u && (a = Sb(a, u)), a }); h.$formatters.push(function (a) { if (a && !da(a)) throw nb("datefmt", a); if (n(a)) return (q = a) && u && (q = Sb(q, u, !0)), m("date")(a, c, u); q = null; return "" }); if (w(g.min) || g.ngMin) {
                var s; h.$validators.min = function (a) { return !n(a) || y(s) || d(a) >= s }; g.$observe("min",
                function (a) { s = p(a); h.$validate() })
            } if (w(g.max) || g.ngMax) { var r; h.$validators.max = function (a) { return !n(a) || y(r) || d(a) <= r }; g.$observe("max", function (a) { r = p(a); h.$validate() }) }
        }
    } function Md(a, b, d, c) { (c.$$hasNativeValidators = D(b[0].validity)) && c.$parsers.push(function (a) { var c = b.prop("validity") || {}; return c.badInput || c.typeMismatch ? void 0 : a }) } function Nd(a, b, d, c, e) { if (w(c)) { a = a(c); if (!a.constant) throw nb("constexpr", d, c); return a(b) } return e } function qc(a, b) {
        a = "ngClass" + a; return ["$animate", function (d) {
            function c(a,
            b) { var c = [], d = 0; a: for (; d < a.length; d++) { for (var e = a[d], m = 0; m < b.length; m++) if (e == b[m]) continue a; c.push(e) } return c } function e(a) { var b = []; return L(a) ? (q(a, function (a) { b = b.concat(e(a)) }), b) : G(a) ? a.split(" ") : D(a) ? (q(a, function (a, c) { a && (b = b.concat(c.split(" "))) }), b) : a } return {
                restrict: "AC", link: function (f, g, h) {
                    function k(a) { a = l(a, 1); h.$addClass(a) } function l(a, b) { var c = g.data("$classCounts") || U(), d = []; q(a, function (a) { if (0 < b || c[a]) c[a] = (c[a] || 0) + b, c[a] === +(0 < b) && d.push(a) }); g.data("$classCounts", c); return d.join(" ") }
                    function m(a, b) { var e = c(b, a), f = c(a, b), e = l(e, 1), f = l(f, -1); e && e.length && d.addClass(g, e); f && f.length && d.removeClass(g, f) } function n(a) { if (!0 === b || (f.$index & 1) === b) { var c = e(a || []); if (!p) k(c); else if (!na(a, p)) { var d = e(p); m(d, c) } } p = L(a) ? a.map(function (a) { return ia(a) }) : ia(a) } var p; f.$watch(h[a], n, !0); h.$observe("class", function (b) { n(f.$eval(h[a])) }); "ngClass" !== a && f.$watch("$index", function (c, d) { var g = c & 1; if (g !== (d & 1)) { var m = e(f.$eval(h[a])); g === b ? k(m) : (g = l(m, -1), h.$removeClass(g)) } })
                }
            }
        }]
    } function Kd(a) {
        function b(a,
        b) { b && !f[a] ? (k.addClass(e, a), f[a] = !0) : !b && f[a] && (k.removeClass(e, a), f[a] = !1) } function d(a, c) { a = a ? "-" + Cc(a, "-") : ""; b(ob + a, !0 === c); b(Od + a, !1 === c) } var c = a.ctrl, e = a.$element, f = {}, g = a.set, h = a.unset, k = a.$animate; f[Od] = !(f[ob] = e.hasClass(ob)); c.$setValidity = function (a, e, f) {
            y(e) ? (c.$pending || (c.$pending = {}), g(c.$pending, a, f)) : (c.$pending && h(c.$pending, a, f), Pd(c.$pending) && (c.$pending = void 0)); Ga(e) ? e ? (h(c.$error, a, f), g(c.$$success, a, f)) : (g(c.$error, a, f), h(c.$$success, a, f)) : (h(c.$error, a, f), h(c.$$success,
            a, f)); c.$pending ? (b(Qd, !0), c.$valid = c.$invalid = void 0, d("", null)) : (b(Qd, !1), c.$valid = Pd(c.$error), c.$invalid = !c.$valid, d("", c.$valid)); e = c.$pending && c.$pending[a] ? void 0 : c.$error[a] ? !1 : c.$$success[a] ? !0 : null; d(a, e); c.$$parentForm.$setValidity(a, e, c)
        }
    } function Pd(a) { if (a) for (var b in a) if (a.hasOwnProperty(b)) return !1; return !0 } var Cg = /^\/(.+)\/([a-z]*)$/, ua = Object.prototype.hasOwnProperty, Q = function (a) { return G(a) ? a.toLowerCase() : a }, ub = function (a) { return G(a) ? a.toUpperCase() : a }, Ea, F, qa, va = [].slice,
    bg = [].splice, Dg = [].push, ma = Object.prototype.toString, wc = Object.getPrototypeOf, xa = N("ng"), ca = C.angular || (C.angular = {}), Ub, pb = 0; Ea = C.document.documentMode; A.$inject = []; Xa.$inject = []; var L = Array.isArray, ae = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/, W = function (a) { return G(a) ? a.trim() : a }, wd = function (a) { return a.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, "\\$1").replace(/\x08/g, "\\x08") }, Ba = function () {
        if (!w(Ba.rules)) {
            var a = C.document.querySelector("[ng-csp]") ||
            C.document.querySelector("[data-ng-csp]"); if (a) { var b = a.getAttribute("ng-csp") || a.getAttribute("data-ng-csp"); Ba.rules = { noUnsafeEval: !b || -1 !== b.indexOf("no-unsafe-eval"), noInlineStyle: !b || -1 !== b.indexOf("no-inline-style") } } else { a = Ba; try { new Function(""), b = !1 } catch (d) { b = !0 } a.rules = { noUnsafeEval: b, noInlineStyle: !1 } }
        } return Ba.rules
    }, rb = function () {
        if (w(rb.name_)) return rb.name_; var a, b, d = Na.length, c, e; for (b = 0; b < d; ++b) if (c = Na[b], a = C.document.querySelector("[" + c.replace(":", "\\:") + "jq]")) {
            e = a.getAttribute(c +
            "jq"); break
        } return rb.name_ = e
    }, de = /:/g, Na = ["ng-", "data-ng-", "ng:", "x-ng-"], ie = /[A-Z]/g, Dc = !1, Ma = 3, me = { full: "1.5.8", major: 1, minor: 5, dot: 8, codeName: "arbitrary-fallbacks" }; O.expando = "ng339"; var fb = O.cache = {}, Pf = 1; O._data = function (a) { return this.cache[a[this.expando]] || {} }; var Kf = /([\:\-\_]+(.))/g, Lf = /^moz([A-Z])/, yb = { mouseleave: "mouseout", mouseenter: "mouseover" }, Wb = N("jqLite"), Of = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/, Vb = /<|&#?\w+;/, Mf = /<([\w:-]+)/, Nf = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
    ja = { option: [1, '<select multiple="multiple">', "</select>"], thead: [1, "<table>", "</table>"], col: [2, "<table><colgroup>", "</colgroup></table>"], tr: [2, "<table><tbody>", "</tbody></table>"], td: [3, "<table><tbody><tr>", "</tr></tbody></table>"], _default: [0, "", ""] }; ja.optgroup = ja.option; ja.tbody = ja.tfoot = ja.colgroup = ja.caption = ja.thead; ja.th = ja.td; var Uf = C.Node.prototype.contains || function (a) { return !!(this.compareDocumentPosition(a) & 16) }, Oa = O.prototype = {
        ready: function (a) {
            function b() { d || (d = !0, a()) } var d = !1; "complete" ===
            C.document.readyState ? C.setTimeout(b) : (this.on("DOMContentLoaded", b), O(C).on("load", b))
        }, toString: function () { var a = []; q(this, function (b) { a.push("" + b) }); return "[" + a.join(", ") + "]" }, eq: function (a) { return 0 <= a ? F(this[a]) : F(this[this.length + a]) }, length: 0, push: Dg, sort: [].sort, splice: [].splice
    }, Eb = {}; q("multiple selected checked disabled readOnly required open".split(" "), function (a) { Eb[Q(a)] = a }); var Vc = {}; q("input select option textarea button form details".split(" "), function (a) { Vc[a] = !0 }); var bd = {
        ngMinlength: "minlength",
        ngMaxlength: "maxlength", ngMin: "min", ngMax: "max", ngPattern: "pattern"
    }; q({ data: Yb, removeData: eb, hasData: function (a) { for (var b in fb[a.ng339]) return !0; return !1 }, cleanData: function (a) { for (var b = 0, d = a.length; b < d; b++) eb(a[b]) } }, function (a, b) { O[b] = a }); q({
        data: Yb, inheritedData: Cb, scope: function (a) { return F.data(a, "$scope") || Cb(a.parentNode || a, ["$isolateScope", "$scope"]) }, isolateScope: function (a) { return F.data(a, "$isolateScope") || F.data(a, "$isolateScopeNoTemplate") }, controller: Sc, injector: function (a) {
            return Cb(a,
            "$injector")
        }, removeAttr: function (a, b) { a.removeAttribute(b) }, hasClass: zb, css: function (a, b, d) { b = db(b); if (w(d)) a.style[b] = d; else return a.style[b] }, attr: function (a, b, d) { var c = a.nodeType; if (c !== Ma && 2 !== c && 8 !== c) if (c = Q(b), Eb[c]) if (w(d)) d ? (a[b] = !0, a.setAttribute(b, c)) : (a[b] = !1, a.removeAttribute(c)); else return a[b] || (a.attributes.getNamedItem(b) || A).specified ? c : void 0; else if (w(d)) a.setAttribute(b, d); else if (a.getAttribute) return a = a.getAttribute(b, 2), null === a ? void 0 : a }, prop: function (a, b, d) {
            if (w(d)) a[b] =
            d; else return a[b]
        }, text: function () { function a(a, d) { if (y(d)) { var c = a.nodeType; return 1 === c || c === Ma ? a.textContent : "" } a.textContent = d } a.$dv = ""; return a }(), val: function (a, b) { if (y(b)) { if (a.multiple && "select" === wa(a)) { var d = []; q(a.options, function (a) { a.selected && d.push(a.value || a.text) }); return 0 === d.length ? null : d } return a.value } a.value = b }, html: function (a, b) { if (y(b)) return a.innerHTML; wb(a, !0); a.innerHTML = b }, empty: Tc
    }, function (a, b) {
        O.prototype[b] = function (b, c) {
            var e, f, g = this.length; if (a !== Tc && y(2 == a.length &&
            a !== zb && a !== Sc ? b : c)) { if (D(b)) { for (e = 0; e < g; e++) if (a === Yb) a(this[e], b); else for (f in b) a(this[e], f, b[f]); return this } e = a.$dv; g = y(e) ? Math.min(g, 1) : g; for (f = 0; f < g; f++) { var h = a(this[f], b, c); e = e ? e + h : h } return e } for (e = 0; e < g; e++) a(this[e], b, c); return this
        }
    }); q({
        removeData: eb, on: function (a, b, d, c) {
            if (w(c)) throw Wb("onargs"); if (Nc(a)) {
                c = xb(a, !0); var e = c.events, f = c.handle; f || (f = c.handle = Rf(a, e)); c = 0 <= b.indexOf(" ") ? b.split(" ") : [b]; for (var g = c.length, h = function (b, c, g) {
                var h = e[b]; h || (h = e[b] = [], h.specialHandlerWrapper =
                c, "$destroy" === b || g || a.addEventListener(b, f, !1)); h.push(d)
                }; g--;) b = c[g], yb[b] ? (h(yb[b], Tf), h(b, void 0, !0)) : h(b)
            }
        }, off: Rc, one: function (a, b, d) { a = F(a); a.on(b, function e() { a.off(b, d); a.off(b, e) }); a.on(b, d) }, replaceWith: function (a, b) { var d, c = a.parentNode; wb(a); q(new O(b), function (b) { d ? c.insertBefore(b, d.nextSibling) : c.replaceChild(b, a); d = b }) }, children: function (a) { var b = []; q(a.childNodes, function (a) { 1 === a.nodeType && b.push(a) }); return b }, contents: function (a) { return a.contentDocument || a.childNodes || [] }, append: function (a,
        b) { var d = a.nodeType; if (1 === d || 11 === d) { b = new O(b); for (var d = 0, c = b.length; d < c; d++) a.appendChild(b[d]) } }, prepend: function (a, b) { if (1 === a.nodeType) { var d = a.firstChild; q(new O(b), function (b) { a.insertBefore(b, d) }) } }, wrap: function (a, b) { Pc(a, F(b).eq(0).clone()[0]) }, remove: Db, detach: function (a) { Db(a, !0) }, after: function (a, b) { var d = a, c = a.parentNode; b = new O(b); for (var e = 0, f = b.length; e < f; e++) { var g = b[e]; c.insertBefore(g, d.nextSibling); d = g } }, addClass: Bb, removeClass: Ab, toggleClass: function (a, b, d) {
            b && q(b.split(" "),
            function (b) { var e = d; y(e) && (e = !zb(a, b)); (e ? Bb : Ab)(a, b) })
        }, parent: function (a) { return (a = a.parentNode) && 11 !== a.nodeType ? a : null }, next: function (a) { return a.nextElementSibling }, find: function (a, b) { return a.getElementsByTagName ? a.getElementsByTagName(b) : [] }, clone: Xb, triggerHandler: function (a, b, d) {
            var c, e, f = b.type || b, g = xb(a); if (g = (g = g && g.events) && g[f]) c = {
                preventDefault: function () { this.defaultPrevented = !0 }, isDefaultPrevented: function () { return !0 === this.defaultPrevented }, stopImmediatePropagation: function () {
                    this.immediatePropagationStopped =
                    !0
                }, isImmediatePropagationStopped: function () { return !0 === this.immediatePropagationStopped }, stopPropagation: A, type: f, target: a
            }, b.type && (c = S(c, b)), b = ia(g), e = d ? [c].concat(d) : [c], q(b, function (b) { c.isImmediatePropagationStopped() || b.apply(a, e) })
        }
    }, function (a, b) { O.prototype[b] = function (b, c, e) { for (var f, g = 0, h = this.length; g < h; g++) y(f) ? (f = a(this[g], b, c, e), w(f) && (f = F(f))) : Qc(f, a(this[g], b, c, e)); return w(f) ? f : this }; O.prototype.bind = O.prototype.on; O.prototype.unbind = O.prototype.off }); Ra.prototype = {
        put: function (a,
        b) { this[Ca(a, this.nextUid)] = b }, get: function (a) { return this[Ca(a, this.nextUid)] }, remove: function (a) { var b = this[a = Ca(a, this.nextUid)]; delete this[a]; return b }
    }; var If = [function () { this.$get = [function () { return Ra }] }], Wf = /^([^\(]+?)=>/, Xf = /^[^\(]*\(\s*([^\)]*)\)/m, Eg = /,/, Fg = /^\s*(_?)(\S+?)\1\s*$/, Vf = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, Ha = N("$injector"); cb.$$annotate = function (a, b, d) {
        var c; if ("function" === typeof a) {
            if (!(c = a.$inject)) {
                c = []; if (a.length) {
                    if (b) throw G(d) && d || (d = a.name || Yf(a)), Ha("strictdi", d);
                    b = Wc(a); q(b[1].split(Eg), function (a) { a.replace(Fg, function (a, b, d) { c.push(d) }) })
                } a.$inject = c
            }
        } else L(a) ? (b = a.length - 1, Pa(a[b], "fn"), c = a.slice(0, b)) : Pa(a, "fn", !0); return c
    }; var Rd = N("$animate"), $e = function () { this.$get = A }, af = function () {
        var a = new Ra, b = []; this.$get = ["$$AnimateRunner", "$rootScope", function (d, c) {
            function e(a, b, c) { var d = !1; b && (b = G(b) ? b.split(" ") : L(b) ? b : [], q(b, function (b) { b && (d = !0, a[b] = c) })); return d } function f() {
                q(b, function (b) {
                    var c = a.get(b); if (c) {
                        var d = Zf(b.attr("class")), e = "", f = ""; q(c,
                        function (a, b) { a !== !!d[b] && (a ? e += (e.length ? " " : "") + b : f += (f.length ? " " : "") + b) }); q(b, function (a) { e && Bb(a, e); f && Ab(a, f) }); a.remove(b)
                    }
                }); b.length = 0
            } return { enabled: A, on: A, off: A, pin: A, push: function (g, h, k, l) { l && l(); k = k || {}; k.from && g.css(k.from); k.to && g.css(k.to); if (k.addClass || k.removeClass) if (h = k.addClass, l = k.removeClass, k = a.get(g) || {}, h = e(k, h, !0), l = e(k, l, !1), h || l) a.put(g, k), b.push(g), 1 === b.length && c.$$postDigest(f); g = new d; g.complete(); return g } }
        }]
    }, Ye = ["$provide", function (a) {
        var b = this; this.$$registeredAnimations =
        Object.create(null); this.register = function (d, c) { if (d && "." !== d.charAt(0)) throw Rd("notcsel", d); var e = d + "-animation"; b.$$registeredAnimations[d.substr(1)] = e; a.factory(e, c) }; this.classNameFilter = function (a) { if (1 === arguments.length && (this.$$classNameFilter = a instanceof RegExp ? a : null) && /(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString())) throw Rd("nongcls", "ng-animate"); return this.$$classNameFilter }; this.$get = ["$$animateQueue", function (a) {
            function b(a, c, d) {
                if (d) {
                    var h; a: {
                        for (h = 0; h < d.length; h++) {
                            var k =
                            d[h]; if (1 === k.nodeType) { h = k; break a }
                        } h = void 0
                    } !h || h.parentNode || h.previousElementSibling || (d = null)
                } d ? d.after(a) : c.prepend(a)
            } return {
                on: a.on, off: a.off, pin: a.pin, enabled: a.enabled, cancel: function (a) { a.end && a.end() }, enter: function (e, f, g, h) { f = f && F(f); g = g && F(g); f = f || g.parent(); b(e, f, g); return a.push(e, "enter", Ia(h)) }, move: function (e, f, g, h) { f = f && F(f); g = g && F(g); f = f || g.parent(); b(e, f, g); return a.push(e, "move", Ia(h)) }, leave: function (b, c) { return a.push(b, "leave", Ia(c), function () { b.remove() }) }, addClass: function (b,
                c, g) { g = Ia(g); g.addClass = gb(g.addclass, c); return a.push(b, "addClass", g) }, removeClass: function (b, c, g) { g = Ia(g); g.removeClass = gb(g.removeClass, c); return a.push(b, "removeClass", g) }, setClass: function (b, c, g, h) { h = Ia(h); h.addClass = gb(h.addClass, c); h.removeClass = gb(h.removeClass, g); return a.push(b, "setClass", h) }, animate: function (b, c, g, h, k) { k = Ia(k); k.from = k.from ? S(k.from, c) : c; k.to = k.to ? S(k.to, g) : g; k.tempClasses = gb(k.tempClasses, h || "ng-inline-animate"); return a.push(b, "animate", k) }
            }
        }]
    }], cf = function () {
        this.$get =
        ["$$rAF", function (a) { function b(b) { d.push(b); 1 < d.length || a(function () { for (var a = 0; a < d.length; a++) d[a](); d = [] }) } var d = []; return function () { var a = !1; b(function () { a = !0 }); return function (d) { a ? d() : b(d) } } }]
    }, bf = function () {
        this.$get = ["$q", "$sniffer", "$$animateAsyncRun", "$document", "$timeout", function (a, b, d, c, e) {
            function f(a) { this.setHost(a); var b = d(); this._doneCallbacks = []; this._tick = function (a) { var d = c[0]; d && d.hidden ? e(a, 0, !1) : b(a) }; this._state = 0 } f.chain = function (a, b) {
                function c() {
                    if (d === a.length) b(!0);
                    else a[d](function (a) { !1 === a ? b(!1) : (d++, c()) })
                } var d = 0; c()
            }; f.all = function (a, b) { function c(f) { e = e && f; ++d === a.length && b(e) } var d = 0, e = !0; q(a, function (a) { a.done(c) }) }; f.prototype = {
                setHost: function (a) { this.host = a || {} }, done: function (a) { 2 === this._state ? a() : this._doneCallbacks.push(a) }, progress: A, getPromise: function () { if (!this.promise) { var b = this; this.promise = a(function (a, c) { b.done(function (b) { !1 === b ? c() : a() }) }) } return this.promise }, then: function (a, b) { return this.getPromise().then(a, b) }, "catch": function (a) { return this.getPromise()["catch"](a) },
                "finally": function (a) { return this.getPromise()["finally"](a) }, pause: function () { this.host.pause && this.host.pause() }, resume: function () { this.host.resume && this.host.resume() }, end: function () { this.host.end && this.host.end(); this._resolve(!0) }, cancel: function () { this.host.cancel && this.host.cancel(); this._resolve(!1) }, complete: function (a) { var b = this; 0 === b._state && (b._state = 1, b._tick(function () { b._resolve(a) })) }, _resolve: function (a) {
                    2 !== this._state && (q(this._doneCallbacks, function (b) { b(a) }), this._doneCallbacks.length =
                    0, this._state = 2)
                }
            }; return f
        }]
    }, Ze = function () { this.$get = ["$$rAF", "$q", "$$AnimateRunner", function (a, b, d) { return function (b, e) { function f() { a(function () { g.addClass && (b.addClass(g.addClass), g.addClass = null); g.removeClass && (b.removeClass(g.removeClass), g.removeClass = null); g.to && (b.css(g.to), g.to = null); h || k.complete(); h = !0 }); return k } var g = e || {}; g.$$prepared || (g = pa(g)); g.cleanupStyles && (g.from = g.to = null); g.from && (b.css(g.from), g.from = null); var h, k = new d; return { start: f, end: f } } }] }, ga = N("$compile"), bc = new function () { };
    Fc.$inject = ["$provide", "$$sanitizeUriProvider"]; Fb.prototype.isFirstChange = function () { return this.previousValue === bc }; var Yc = /^((?:x|data)[\:\-_])/i, cg = N("$controller"), cd = /^(\S+)(\s+as\s+([\w$]+))?$/, jf = function () { this.$get = ["$document", function (a) { return function (b) { b ? !b.nodeType && b instanceof F && (b = b[0]) : b = a[0].body; return b.offsetWidth + 1 } }] }, dd = "application/json", ec = { "Content-Type": dd + ";charset=utf-8" }, eg = /^\[|^\{(?!\{)/, fg = { "[": /]$/, "{": /}$/ }, dg = /^\)\]\}',?\n/, Gg = N("$http"), hd = function (a) {
        return function () {
            throw Gg("legacy",
            a);
        }
    }, Ka = ca.$interpolateMinErr = N("$interpolate"); Ka.throwNoconcat = function (a) { throw Ka("noconcat", a); }; Ka.interr = function (a, b) { return Ka("interr", a, b.toString()) }; var rf = function () {
        this.$get = ["$window", function (a) {
            function b(a) { var b = function (a) { b.data = a; b.called = !0 }; b.id = a; return b } var d = a.angular.callbacks, c = {}; return {
                createCallback: function (a) { a = "_" + (d.$$counter++).toString(36); var f = "angular.callbacks." + a, g = b(a); c[f] = d[a] = g; return f }, wasCalled: function (a) { return c[a].called }, getResponse: function (a) { return c[a].data },
                removeCallback: function (a) { delete d[c[a].id]; delete c[a] }
            }
        }]
    }, Hg = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, hg = { http: 80, https: 443, ftp: 21 }, Gb = N("$location"), Ig = {
        $$absUrl: "", $$html5: !1, $$replace: !1, absUrl: Hb("$$absUrl"), url: function (a) { if (y(a)) return this.$$url; var b = Hg.exec(a); (b[1] || "" === a) && this.path(decodeURIComponent(b[1])); (b[2] || b[1] || "" === a) && this.search(b[3] || ""); this.hash(b[5] || ""); return this }, protocol: Hb("$$protocol"), host: Hb("$$host"), port: Hb("$$port"), path: md("$$path", function (a) {
            a = null !== a ? a.toString() :
            ""; return "/" == a.charAt(0) ? a : "/" + a
        }), search: function (a, b) { switch (arguments.length) { case 0: return this.$$search; case 1: if (G(a) || T(a)) a = a.toString(), this.$$search = Ac(a); else if (D(a)) a = pa(a, {}), q(a, function (b, c) { null == b && delete a[c] }), this.$$search = a; else throw Gb("isrcharg"); break; default: y(b) || null === b ? delete this.$$search[a] : this.$$search[a] = b } this.$$compose(); return this }, hash: md("$$hash", function (a) { return null !== a ? a.toString() : "" }), replace: function () { this.$$replace = !0; return this }
    }; q([ld, hc, gc],
    function (a) { a.prototype = Object.create(Ig); a.prototype.state = function (b) { if (!arguments.length) return this.$$state; if (a !== gc || !this.$$html5) throw Gb("nostate"); this.$$state = y(b) ? null : b; return this } }); var X = N("$parse"), jg = Function.prototype.call, kg = Function.prototype.apply, lg = Function.prototype.bind, Ob = U(); q("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function (a) { Ob[a] = !0 }); var Jg = { n: "\n", f: "\f", r: "\r", t: "\t", v: "\v", "'": "'", '"': '"' }, jc = function (a) { this.options = a }; jc.prototype = {
        constructor: jc,
        lex: function (a) {
            this.text = a; this.index = 0; for (this.tokens = []; this.index < this.text.length;) if (a = this.text.charAt(this.index), '"' === a || "'" === a) this.readString(a); else if (this.isNumber(a) || "." === a && this.isNumber(this.peek())) this.readNumber(); else if (this.isIdentifierStart(this.peekMultichar())) this.readIdent(); else if (this.is(a, "(){}[].,;:?")) this.tokens.push({ index: this.index, text: a }), this.index++; else if (this.isWhitespace(a)) this.index++; else {
                var b = a + this.peek(), d = b + this.peek(2), c = Ob[b], e = Ob[d]; Ob[a] ||
                c || e ? (a = e ? d : c ? b : a, this.tokens.push({ index: this.index, text: a, operator: !0 }), this.index += a.length) : this.throwError("Unexpected next character ", this.index, this.index + 1)
            } return this.tokens
        }, is: function (a, b) { return -1 !== b.indexOf(a) }, peek: function (a) { a = a || 1; return this.index + a < this.text.length ? this.text.charAt(this.index + a) : !1 }, isNumber: function (a) { return "0" <= a && "9" >= a && "string" === typeof a }, isWhitespace: function (a) { return " " === a || "\r" === a || "\t" === a || "\n" === a || "\v" === a || "\u00a0" === a }, isIdentifierStart: function (a) {
            return this.options.isIdentifierStart ?
            this.options.isIdentifierStart(a, this.codePointAt(a)) : this.isValidIdentifierStart(a)
        }, isValidIdentifierStart: function (a) { return "a" <= a && "z" >= a || "A" <= a && "Z" >= a || "_" === a || "$" === a }, isIdentifierContinue: function (a) { return this.options.isIdentifierContinue ? this.options.isIdentifierContinue(a, this.codePointAt(a)) : this.isValidIdentifierContinue(a) }, isValidIdentifierContinue: function (a, b) { return this.isValidIdentifierStart(a, b) || this.isNumber(a) }, codePointAt: function (a) {
            return 1 === a.length ? a.charCodeAt(0) :
            (a.charCodeAt(0) << 10) + a.charCodeAt(1) - 56613888
        }, peekMultichar: function () { var a = this.text.charAt(this.index), b = this.peek(); if (!b) return a; var d = a.charCodeAt(0), c = b.charCodeAt(0); return 55296 <= d && 56319 >= d && 56320 <= c && 57343 >= c ? a + b : a }, isExpOperator: function (a) { return "-" === a || "+" === a || this.isNumber(a) }, throwError: function (a, b, d) { d = d || this.index; b = w(b) ? "s " + b + "-" + this.index + " [" + this.text.substring(b, d) + "]" : " " + d; throw X("lexerr", a, b, this.text); }, readNumber: function () {
            for (var a = "", b = this.index; this.index <
            this.text.length;) { var d = Q(this.text.charAt(this.index)); if ("." == d || this.isNumber(d)) a += d; else { var c = this.peek(); if ("e" == d && this.isExpOperator(c)) a += d; else if (this.isExpOperator(d) && c && this.isNumber(c) && "e" == a.charAt(a.length - 1)) a += d; else if (!this.isExpOperator(d) || c && this.isNumber(c) || "e" != a.charAt(a.length - 1)) break; else this.throwError("Invalid exponent") } this.index++ } this.tokens.push({ index: b, text: a, constant: !0, value: Number(a) })
        }, readIdent: function () {
            var a = this.index; for (this.index += this.peekMultichar().length; this.index <
            this.text.length;) { var b = this.peekMultichar(); if (!this.isIdentifierContinue(b)) break; this.index += b.length } this.tokens.push({ index: a, text: this.text.slice(a, this.index), identifier: !0 })
        }, readString: function (a) {
            var b = this.index; this.index++; for (var d = "", c = a, e = !1; this.index < this.text.length;) {
                var f = this.text.charAt(this.index), c = c + f; if (e) "u" === f ? (e = this.text.substring(this.index + 1, this.index + 5), e.match(/[\da-f]{4}/i) || this.throwError("Invalid unicode escape [\\u" + e + "]"), this.index += 4, d += String.fromCharCode(parseInt(e,
                16))) : d += Jg[f] || f, e = !1; else if ("\\" === f) e = !0; else { if (f === a) { this.index++; this.tokens.push({ index: b, text: c, constant: !0, value: d }); return } d += f } this.index++
            } this.throwError("Unterminated quote", b)
        }
    }; var s = function (a, b) { this.lexer = a; this.options = b }; s.Program = "Program"; s.ExpressionStatement = "ExpressionStatement"; s.AssignmentExpression = "AssignmentExpression"; s.ConditionalExpression = "ConditionalExpression"; s.LogicalExpression = "LogicalExpression"; s.BinaryExpression = "BinaryExpression"; s.UnaryExpression = "UnaryExpression";
    s.CallExpression = "CallExpression"; s.MemberExpression = "MemberExpression"; s.Identifier = "Identifier"; s.Literal = "Literal"; s.ArrayExpression = "ArrayExpression"; s.Property = "Property"; s.ObjectExpression = "ObjectExpression"; s.ThisExpression = "ThisExpression"; s.LocalsExpression = "LocalsExpression"; s.NGValueParameter = "NGValueParameter"; s.prototype = {
        ast: function (a) { this.text = a; this.tokens = this.lexer.lex(a); a = this.program(); 0 !== this.tokens.length && this.throwError("is an unexpected token", this.tokens[0]); return a },
        program: function () { for (var a = []; ;) if (0 < this.tokens.length && !this.peek("}", ")", ";", "]") && a.push(this.expressionStatement()), !this.expect(";")) return { type: s.Program, body: a } }, expressionStatement: function () { return { type: s.ExpressionStatement, expression: this.filterChain() } }, filterChain: function () { for (var a = this.expression() ; this.expect("|") ;) a = this.filter(a); return a }, expression: function () { return this.assignment() }, assignment: function () {
            var a = this.ternary(); this.expect("=") && (a = {
                type: s.AssignmentExpression,
                left: a, right: this.assignment(), operator: "="
            }); return a
        }, ternary: function () { var a = this.logicalOR(), b, d; return this.expect("?") && (b = this.expression(), this.consume(":")) ? (d = this.expression(), { type: s.ConditionalExpression, test: a, alternate: b, consequent: d }) : a }, logicalOR: function () { for (var a = this.logicalAND() ; this.expect("||") ;) a = { type: s.LogicalExpression, operator: "||", left: a, right: this.logicalAND() }; return a }, logicalAND: function () {
            for (var a = this.equality() ; this.expect("&&") ;) a = {
                type: s.LogicalExpression,
                operator: "&&", left: a, right: this.equality()
            }; return a
        }, equality: function () { for (var a = this.relational(), b; b = this.expect("==", "!=", "===", "!==") ;) a = { type: s.BinaryExpression, operator: b.text, left: a, right: this.relational() }; return a }, relational: function () { for (var a = this.additive(), b; b = this.expect("<", ">", "<=", ">=") ;) a = { type: s.BinaryExpression, operator: b.text, left: a, right: this.additive() }; return a }, additive: function () {
            for (var a = this.multiplicative(), b; b = this.expect("+", "-") ;) a = {
                type: s.BinaryExpression, operator: b.text,
                left: a, right: this.multiplicative()
            }; return a
        }, multiplicative: function () { for (var a = this.unary(), b; b = this.expect("*", "/", "%") ;) a = { type: s.BinaryExpression, operator: b.text, left: a, right: this.unary() }; return a }, unary: function () { var a; return (a = this.expect("+", "-", "!")) ? { type: s.UnaryExpression, operator: a.text, prefix: !0, argument: this.unary() } : this.primary() }, primary: function () {
            var a; this.expect("(") ? (a = this.filterChain(), this.consume(")")) : this.expect("[") ? a = this.arrayDeclaration() : this.expect("{") ? a = this.object() :
            this.selfReferential.hasOwnProperty(this.peek().text) ? a = pa(this.selfReferential[this.consume().text]) : this.options.literals.hasOwnProperty(this.peek().text) ? a = { type: s.Literal, value: this.options.literals[this.consume().text] } : this.peek().identifier ? a = this.identifier() : this.peek().constant ? a = this.constant() : this.throwError("not a primary expression", this.peek()); for (var b; b = this.expect("(", "[", ".") ;) "(" === b.text ? (a = { type: s.CallExpression, callee: a, arguments: this.parseArguments() }, this.consume(")")) :
            "[" === b.text ? (a = { type: s.MemberExpression, object: a, property: this.expression(), computed: !0 }, this.consume("]")) : "." === b.text ? a = { type: s.MemberExpression, object: a, property: this.identifier(), computed: !1 } : this.throwError("IMPOSSIBLE"); return a
        }, filter: function (a) { a = [a]; for (var b = { type: s.CallExpression, callee: this.identifier(), arguments: a, filter: !0 }; this.expect(":") ;) a.push(this.expression()); return b }, parseArguments: function () {
            var a = []; if (")" !== this.peekToken().text) {
                do a.push(this.filterChain()); while (this.expect(","))
            } return a
        }, identifier: function () { var a = this.consume(); a.identifier || this.throwError("is not a valid identifier", a); return { type: s.Identifier, name: a.text } }, constant: function () { return { type: s.Literal, value: this.consume().value } }, arrayDeclaration: function () { var a = []; if ("]" !== this.peekToken().text) { do { if (this.peek("]")) break; a.push(this.expression()) } while (this.expect(",")) } this.consume("]"); return { type: s.ArrayExpression, elements: a } }, object: function () {
            var a = [], b; if ("}" !== this.peekToken().text) {
                do {
                    if (this.peek("}")) break;
                    b = { type: s.Property, kind: "init" }; this.peek().constant ? (b.key = this.constant(), b.computed = !1, this.consume(":"), b.value = this.expression()) : this.peek().identifier ? (b.key = this.identifier(), b.computed = !1, this.peek(":") ? (this.consume(":"), b.value = this.expression()) : b.value = b.key) : this.peek("[") ? (this.consume("["), b.key = this.expression(), this.consume("]"), b.computed = !0, this.consume(":"), b.value = this.expression()) : this.throwError("invalid key", this.peek()); a.push(b)
                } while (this.expect(","))
            } this.consume("}");
            return { type: s.ObjectExpression, properties: a }
        }, throwError: function (a, b) { throw X("syntax", b.text, a, b.index + 1, this.text, this.text.substring(b.index)); }, consume: function (a) { if (0 === this.tokens.length) throw X("ueoe", this.text); var b = this.expect(a); b || this.throwError("is unexpected, expecting [" + a + "]", this.peek()); return b }, peekToken: function () { if (0 === this.tokens.length) throw X("ueoe", this.text); return this.tokens[0] }, peek: function (a, b, d, c) { return this.peekAhead(0, a, b, d, c) }, peekAhead: function (a, b, d, c, e) {
            if (this.tokens.length >
            a) { a = this.tokens[a]; var f = a.text; if (f === b || f === d || f === c || f === e || !(b || d || c || e)) return a } return !1
        }, expect: function (a, b, d, c) { return (a = this.peek(a, b, d, c)) ? (this.tokens.shift(), a) : !1 }, selfReferential: { "this": { type: s.ThisExpression }, $locals: { type: s.LocalsExpression } }
    }; td.prototype = {
        compile: function (a, b) {
            var d = this, c = this.astBuilder.ast(a); this.state = { nextId: 0, filters: {}, expensiveChecks: b, fn: { vars: [], body: [], own: {} }, assign: { vars: [], body: [], own: {} }, inputs: [] }; V(c, d.$filter); var e = "", f; this.stage = "assign";
            if (f = rd(c)) this.state.computing = "assign", e = this.nextId(), this.recurse(f, e), this.return_(e), e = "fn.assign=" + this.generateFunction("assign", "s,v,l"); f = pd(c.body); d.stage = "inputs"; q(f, function (a, b) { var c = "fn" + b; d.state[c] = { vars: [], body: [], own: {} }; d.state.computing = c; var e = d.nextId(); d.recurse(a, e); d.return_(e); d.state.inputs.push(c); a.watchId = b }); this.state.computing = "fn"; this.stage = "main"; this.recurse(c); e = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") +
            e + this.watchFns() + "return fn;"; e = (new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", e))(this.$filter, Sa, ra, nd, ig, Ib, mg, od, a); this.state = this.stage = void 0; e.literal = sd(c); e.constant = c.constant; return e
        }, USE: "use", STRICT: "strict", watchFns: function () {
            var a = [], b = this.state.inputs, d = this; q(b, function (b) { a.push("var " + b + "=" + d.generateFunction(b, "s")) }); b.length && a.push("fn.inputs=[" + b.join(",") + "];");
            return a.join("")
        }, generateFunction: function (a, b) { return "function(" + b + "){" + this.varsPrefix(a) + this.body(a) + "};" }, filterPrefix: function () { var a = [], b = this; q(this.state.filters, function (d, c) { a.push(d + "=$filter(" + b.escape(c) + ")") }); return a.length ? "var " + a.join(",") + ";" : "" }, varsPrefix: function (a) { return this.state[a].vars.length ? "var " + this.state[a].vars.join(",") + ";" : "" }, body: function (a) { return this.state[a].body.join("") }, recurse: function (a, b, d, c, e, f) {
            var g, h, k = this, l, m, n; c = c || A; if (!f && w(a.watchId)) b =
            b || this.nextId(), this.if_("i", this.lazyAssign(b, this.computedMember("i", a.watchId)), this.lazyRecurse(a, b, d, c, e, !0)); else switch (a.type) {
                case s.Program: q(a.body, function (b, c) { k.recurse(b.expression, void 0, void 0, function (a) { h = a }); c !== a.body.length - 1 ? k.current().body.push(h, ";") : k.return_(h) }); break; case s.Literal: m = this.escape(a.value); this.assign(b, m); c(m); break; case s.UnaryExpression: this.recurse(a.argument, void 0, void 0, function (a) { h = a }); m = a.operator + "(" + this.ifDefined(h, 0) + ")"; this.assign(b, m);
                    c(m); break; case s.BinaryExpression: this.recurse(a.left, void 0, void 0, function (a) { g = a }); this.recurse(a.right, void 0, void 0, function (a) { h = a }); m = "+" === a.operator ? this.plus(g, h) : "-" === a.operator ? this.ifDefined(g, 0) + a.operator + this.ifDefined(h, 0) : "(" + g + ")" + a.operator + "(" + h + ")"; this.assign(b, m); c(m); break; case s.LogicalExpression: b = b || this.nextId(); k.recurse(a.left, b); k.if_("&&" === a.operator ? b : k.not(b), k.lazyRecurse(a.right, b)); c(b); break; case s.ConditionalExpression: b = b || this.nextId(); k.recurse(a.test,
                    b); k.if_(b, k.lazyRecurse(a.alternate, b), k.lazyRecurse(a.consequent, b)); c(b); break; case s.Identifier: b = b || this.nextId(); d && (d.context = "inputs" === k.stage ? "s" : this.assign(this.nextId(), this.getHasOwnProperty("l", a.name) + "?l:s"), d.computed = !1, d.name = a.name); Sa(a.name); k.if_("inputs" === k.stage || k.not(k.getHasOwnProperty("l", a.name)), function () {
                        k.if_("inputs" === k.stage || "s", function () {
                            e && 1 !== e && k.if_(k.not(k.nonComputedMember("s", a.name)), k.lazyAssign(k.nonComputedMember("s", a.name), "{}")); k.assign(b, k.nonComputedMember("s",
                            a.name))
                        })
                    }, b && k.lazyAssign(b, k.nonComputedMember("l", a.name))); (k.state.expensiveChecks || Jb(a.name)) && k.addEnsureSafeObject(b); c(b); break; case s.MemberExpression: g = d && (d.context = this.nextId()) || this.nextId(); b = b || this.nextId(); k.recurse(a.object, g, void 0, function () {
                        k.if_(k.notNull(g), function () {
                            e && 1 !== e && k.addEnsureSafeAssignContext(g); if (a.computed) h = k.nextId(), k.recurse(a.property, h), k.getStringValue(h), k.addEnsureSafeMemberName(h), e && 1 !== e && k.if_(k.not(k.computedMember(g, h)), k.lazyAssign(k.computedMember(g,
                            h), "{}")), m = k.ensureSafeObject(k.computedMember(g, h)), k.assign(b, m), d && (d.computed = !0, d.name = h); else { Sa(a.property.name); e && 1 !== e && k.if_(k.not(k.nonComputedMember(g, a.property.name)), k.lazyAssign(k.nonComputedMember(g, a.property.name), "{}")); m = k.nonComputedMember(g, a.property.name); if (k.state.expensiveChecks || Jb(a.property.name)) m = k.ensureSafeObject(m); k.assign(b, m); d && (d.computed = !1, d.name = a.property.name) }
                        }, function () { k.assign(b, "undefined") }); c(b)
                    }, !!e); break; case s.CallExpression: b = b || this.nextId();
                        a.filter ? (h = k.filter(a.callee.name), l = [], q(a.arguments, function (a) { var b = k.nextId(); k.recurse(a, b); l.push(b) }), m = h + "(" + l.join(",") + ")", k.assign(b, m), c(b)) : (h = k.nextId(), g = {}, l = [], k.recurse(a.callee, h, g, function () {
                            k.if_(k.notNull(h), function () {
                                k.addEnsureSafeFunction(h); q(a.arguments, function (a) { k.recurse(a, k.nextId(), void 0, function (a) { l.push(k.ensureSafeObject(a)) }) }); g.name ? (k.state.expensiveChecks || k.addEnsureSafeObject(g.context), m = k.member(g.context, g.name, g.computed) + "(" + l.join(",") + ")") : m =
                                h + "(" + l.join(",") + ")"; m = k.ensureSafeObject(m); k.assign(b, m)
                            }, function () { k.assign(b, "undefined") }); c(b)
                        })); break; case s.AssignmentExpression: h = this.nextId(); g = {}; if (!qd(a.left)) throw X("lval"); this.recurse(a.left, void 0, g, function () { k.if_(k.notNull(g.context), function () { k.recurse(a.right, h); k.addEnsureSafeObject(k.member(g.context, g.name, g.computed)); k.addEnsureSafeAssignContext(g.context); m = k.member(g.context, g.name, g.computed) + a.operator + h; k.assign(b, m); c(b || m) }) }, 1); break; case s.ArrayExpression: l =
                        []; q(a.elements, function (a) { k.recurse(a, k.nextId(), void 0, function (a) { l.push(a) }) }); m = "[" + l.join(",") + "]"; this.assign(b, m); c(m); break; case s.ObjectExpression: l = []; n = !1; q(a.properties, function (a) { a.computed && (n = !0) }); n ? (b = b || this.nextId(), this.assign(b, "{}"), q(a.properties, function (a) { a.computed ? (g = k.nextId(), k.recurse(a.key, g)) : g = a.key.type === s.Identifier ? a.key.name : "" + a.key.value; h = k.nextId(); k.recurse(a.value, h); k.assign(k.member(b, g, a.computed), h) })) : (q(a.properties, function (b) {
                            k.recurse(b.value,
                            a.constant ? void 0 : k.nextId(), void 0, function (a) { l.push(k.escape(b.key.type === s.Identifier ? b.key.name : "" + b.key.value) + ":" + a) })
                        }), m = "{" + l.join(",") + "}", this.assign(b, m)); c(b || m); break; case s.ThisExpression: this.assign(b, "s"); c("s"); break; case s.LocalsExpression: this.assign(b, "l"); c("l"); break; case s.NGValueParameter: this.assign(b, "v"), c("v")
            }
        }, getHasOwnProperty: function (a, b) { var d = a + "." + b, c = this.current().own; c.hasOwnProperty(d) || (c[d] = this.nextId(!1, a + "&&(" + this.escape(b) + " in " + a + ")")); return c[d] },
        assign: function (a, b) { if (a) return this.current().body.push(a, "=", b, ";"), a }, filter: function (a) { this.state.filters.hasOwnProperty(a) || (this.state.filters[a] = this.nextId(!0)); return this.state.filters[a] }, ifDefined: function (a, b) { return "ifDefined(" + a + "," + this.escape(b) + ")" }, plus: function (a, b) { return "plus(" + a + "," + b + ")" }, return_: function (a) { this.current().body.push("return ", a, ";") }, if_: function (a, b, d) {
            if (!0 === a) b(); else {
                var c = this.current().body; c.push("if(", a, "){"); b(); c.push("}"); d && (c.push("else{"),
                d(), c.push("}"))
            }
        }, not: function (a) { return "!(" + a + ")" }, notNull: function (a) { return a + "!=null" }, nonComputedMember: function (a, b) { var d = /[^$_a-zA-Z0-9]/g; return /[$_a-zA-Z][$_a-zA-Z0-9]*/.test(b) ? a + "." + b : a + '["' + b.replace(d, this.stringEscapeFn) + '"]' }, computedMember: function (a, b) { return a + "[" + b + "]" }, member: function (a, b, d) { return d ? this.computedMember(a, b) : this.nonComputedMember(a, b) }, addEnsureSafeObject: function (a) { this.current().body.push(this.ensureSafeObject(a), ";") }, addEnsureSafeMemberName: function (a) {
            this.current().body.push(this.ensureSafeMemberName(a),
            ";")
        }, addEnsureSafeFunction: function (a) { this.current().body.push(this.ensureSafeFunction(a), ";") }, addEnsureSafeAssignContext: function (a) { this.current().body.push(this.ensureSafeAssignContext(a), ";") }, ensureSafeObject: function (a) { return "ensureSafeObject(" + a + ",text)" }, ensureSafeMemberName: function (a) { return "ensureSafeMemberName(" + a + ",text)" }, ensureSafeFunction: function (a) { return "ensureSafeFunction(" + a + ",text)" }, getStringValue: function (a) { this.assign(a, "getStringValue(" + a + ")") }, ensureSafeAssignContext: function (a) {
            return "ensureSafeAssignContext(" +
            a + ",text)"
        }, lazyRecurse: function (a, b, d, c, e, f) { var g = this; return function () { g.recurse(a, b, d, c, e, f) } }, lazyAssign: function (a, b) { var d = this; return function () { d.assign(a, b) } }, stringEscapeRegex: /[^ a-zA-Z0-9]/g, stringEscapeFn: function (a) { return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4) }, escape: function (a) {
            if (G(a)) return "'" + a.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'"; if (T(a)) return a.toString(); if (!0 === a) return "true"; if (!1 === a) return "false"; if (null === a) return "null"; if ("undefined" ===
            typeof a) return "undefined"; throw X("esc");
        }, nextId: function (a, b) { var d = "v" + this.state.nextId++; a || this.current().vars.push(d + (b ? "=" + b : "")); return d }, current: function () { return this.state[this.state.computing] }
    }; ud.prototype = {
        compile: function (a, b) {
            var d = this, c = this.astBuilder.ast(a); this.expression = a; this.expensiveChecks = b; V(c, d.$filter); var e, f; if (e = rd(c)) f = this.recurse(e); e = pd(c.body); var g; e && (g = [], q(e, function (a, b) { var c = d.recurse(a); a.input = c; g.push(c); a.watchId = b })); var h = []; q(c.body, function (a) { h.push(d.recurse(a.expression)) });
            e = 0 === c.body.length ? A : 1 === c.body.length ? h[0] : function (a, b) { var c; q(h, function (d) { c = d(a, b) }); return c }; f && (e.assign = function (a, b, c) { return f(a, c, b) }); g && (e.inputs = g); e.literal = sd(c); e.constant = c.constant; return e
        }, recurse: function (a, b, d) {
            var c, e, f = this, g; if (a.input) return this.inputs(a.input, a.watchId); switch (a.type) {
                case s.Literal: return this.value(a.value, b); case s.UnaryExpression: return e = this.recurse(a.argument), this["unary" + a.operator](e, b); case s.BinaryExpression: return c = this.recurse(a.left),
                e = this.recurse(a.right), this["binary" + a.operator](c, e, b); case s.LogicalExpression: return c = this.recurse(a.left), e = this.recurse(a.right), this["binary" + a.operator](c, e, b); case s.ConditionalExpression: return this["ternary?:"](this.recurse(a.test), this.recurse(a.alternate), this.recurse(a.consequent), b); case s.Identifier: return Sa(a.name, f.expression), f.identifier(a.name, f.expensiveChecks || Jb(a.name), b, d, f.expression); case s.MemberExpression: return c = this.recurse(a.object, !1, !!d), a.computed || (Sa(a.property.name,
                f.expression), e = a.property.name), a.computed && (e = this.recurse(a.property)), a.computed ? this.computedMember(c, e, b, d, f.expression) : this.nonComputedMember(c, e, f.expensiveChecks, b, d, f.expression); case s.CallExpression: return g = [], q(a.arguments, function (a) { g.push(f.recurse(a)) }), a.filter && (e = this.$filter(a.callee.name)), a.filter || (e = this.recurse(a.callee, !0)), a.filter ? function (a, c, d, f) {
                    for (var n = [], p = 0; p < g.length; ++p) n.push(g[p](a, c, d, f)); a = e.apply(void 0, n, f); return b ? { context: void 0, name: void 0, value: a } :
                    a
                } : function (a, c, d, m) { var n = e(a, c, d, m), p; if (null != n.value) { ra(n.context, f.expression); nd(n.value, f.expression); p = []; for (var q = 0; q < g.length; ++q) p.push(ra(g[q](a, c, d, m), f.expression)); p = ra(n.value.apply(n.context, p), f.expression) } return b ? { value: p } : p }; case s.AssignmentExpression: return c = this.recurse(a.left, !0, 1), e = this.recurse(a.right), function (a, d, g, m) { var n = c(a, d, g, m); a = e(a, d, g, m); ra(n.value, f.expression); Ib(n.context); n.context[n.name] = a; return b ? { value: a } : a }; case s.ArrayExpression: return g = [], q(a.elements,
                function (a) { g.push(f.recurse(a)) }), function (a, c, d, e) { for (var f = [], p = 0; p < g.length; ++p) f.push(g[p](a, c, d, e)); return b ? { value: f } : f }; case s.ObjectExpression: return g = [], q(a.properties, function (a) { a.computed ? g.push({ key: f.recurse(a.key), computed: !0, value: f.recurse(a.value) }) : g.push({ key: a.key.type === s.Identifier ? a.key.name : "" + a.key.value, computed: !1, value: f.recurse(a.value) }) }), function (a, c, d, e) {
                    for (var f = {}, p = 0; p < g.length; ++p) g[p].computed ? f[g[p].key(a, c, d, e)] = g[p].value(a, c, d, e) : f[g[p].key] = g[p].value(a,
                    c, d, e); return b ? { value: f } : f
                }; case s.ThisExpression: return function (a) { return b ? { value: a } : a }; case s.LocalsExpression: return function (a, c) { return b ? { value: c } : c }; case s.NGValueParameter: return function (a, c, d) { return b ? { value: d } : d }
            }
        }, "unary+": function (a, b) { return function (d, c, e, f) { d = a(d, c, e, f); d = w(d) ? +d : 0; return b ? { value: d } : d } }, "unary-": function (a, b) { return function (d, c, e, f) { d = a(d, c, e, f); d = w(d) ? -d : 0; return b ? { value: d } : d } }, "unary!": function (a, b) {
            return function (d, c, e, f) {
                d = !a(d, c, e, f); return b ? { value: d } :
                d
            }
        }, "binary+": function (a, b, d) { return function (c, e, f, g) { var h = a(c, e, f, g); c = b(c, e, f, g); h = od(h, c); return d ? { value: h } : h } }, "binary-": function (a, b, d) { return function (c, e, f, g) { var h = a(c, e, f, g); c = b(c, e, f, g); h = (w(h) ? h : 0) - (w(c) ? c : 0); return d ? { value: h } : h } }, "binary*": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) * b(c, e, f, g); return d ? { value: c } : c } }, "binary/": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) / b(c, e, f, g); return d ? { value: c } : c } }, "binary%": function (a, b, d) {
            return function (c, e, f, g) {
                c = a(c, e,
                f, g) % b(c, e, f, g); return d ? { value: c } : c
            }
        }, "binary===": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) === b(c, e, f, g); return d ? { value: c } : c } }, "binary!==": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) !== b(c, e, f, g); return d ? { value: c } : c } }, "binary==": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) == b(c, e, f, g); return d ? { value: c } : c } }, "binary!=": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) != b(c, e, f, g); return d ? { value: c } : c } }, "binary<": function (a, b, d) {
            return function (c, e, f, g) {
                c = a(c, e,
                f, g) < b(c, e, f, g); return d ? { value: c } : c
            }
        }, "binary>": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) > b(c, e, f, g); return d ? { value: c } : c } }, "binary<=": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) <= b(c, e, f, g); return d ? { value: c } : c } }, "binary>=": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) >= b(c, e, f, g); return d ? { value: c } : c } }, "binary&&": function (a, b, d) { return function (c, e, f, g) { c = a(c, e, f, g) && b(c, e, f, g); return d ? { value: c } : c } }, "binary||": function (a, b, d) {
            return function (c, e, f, g) {
                c = a(c, e, f, g) ||
                b(c, e, f, g); return d ? { value: c } : c
            }
        }, "ternary?:": function (a, b, d, c) { return function (e, f, g, h) { e = a(e, f, g, h) ? b(e, f, g, h) : d(e, f, g, h); return c ? { value: e } : e } }, value: function (a, b) { return function () { return b ? { context: void 0, name: void 0, value: a } : a } }, identifier: function (a, b, d, c, e) { return function (f, g, h, k) { f = g && a in g ? g : f; c && 1 !== c && f && !f[a] && (f[a] = {}); g = f ? f[a] : void 0; b && ra(g, e); return d ? { context: f, name: a, value: g } : g } }, computedMember: function (a, b, d, c, e) {
            return function (f, g, h, k) {
                var l = a(f, g, h, k), m, n; null != l && (m = b(f,
                g, h, k), m += "", Sa(m, e), c && 1 !== c && (Ib(l), l && !l[m] && (l[m] = {})), n = l[m], ra(n, e)); return d ? { context: l, name: m, value: n } : n
            }
        }, nonComputedMember: function (a, b, d, c, e, f) { return function (g, h, k, l) { g = a(g, h, k, l); e && 1 !== e && (Ib(g), g && !g[b] && (g[b] = {})); h = null != g ? g[b] : void 0; (d || Jb(b)) && ra(h, f); return c ? { context: g, name: b, value: h } : h } }, inputs: function (a, b) { return function (d, c, e, f) { return f ? f[b] : a(d, c, e) } }
    }; var kc = function (a, b, d) {
        this.lexer = a; this.$filter = b; this.options = d; this.ast = new s(a, d); this.astCompiler = d.csp ? new ud(this.ast,
        b) : new td(this.ast, b)
    }; kc.prototype = { constructor: kc, parse: function (a) { return this.astCompiler.compile(a, this.options.expensiveChecks) } }; var ng = Object.prototype.valueOf, sa = N("$sce"), la = { HTML: "html", CSS: "css", URL: "url", RESOURCE_URL: "resourceUrl", JS: "js" }, pg = N("$compile"), $ = C.document.createElement("a"), yd = Y(C.location.href); zd.$inject = ["$document"]; Mc.$inject = ["$provide"]; var Gd = 22, Fd = ".", mc = "0"; Ad.$inject = ["$locale"]; Cd.$inject = ["$locale"]; var Ag = {
        yyyy: ba("FullYear", 4, 0, !1, !0), yy: ba("FullYear", 2, 0,
        !0, !0), y: ba("FullYear", 1, 0, !1, !0), MMMM: kb("Month"), MMM: kb("Month", !0), MM: ba("Month", 2, 1), M: ba("Month", 1, 1), LLLL: kb("Month", !1, !0), dd: ba("Date", 2), d: ba("Date", 1), HH: ba("Hours", 2), H: ba("Hours", 1), hh: ba("Hours", 2, -12), h: ba("Hours", 1, -12), mm: ba("Minutes", 2), m: ba("Minutes", 1), ss: ba("Seconds", 2), s: ba("Seconds", 1), sss: ba("Milliseconds", 3), EEEE: kb("Day"), EEE: kb("Day", !0), a: function (a, b) { return 12 > a.getHours() ? b.AMPMS[0] : b.AMPMS[1] }, Z: function (a, b, d) {
            a = -1 * d; return a = (0 <= a ? "+" : "") + (Kb(Math[0 < a ? "floor" : "ceil"](a /
            60), 2) + Kb(Math.abs(a % 60), 2))
        }, ww: Id(2), w: Id(1), G: nc, GG: nc, GGG: nc, GGGG: function (a, b) { return 0 >= a.getFullYear() ? b.ERANAMES[0] : b.ERANAMES[1] }
    }, zg = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, yg = /^\-?\d+$/; Bd.$inject = ["$locale"]; var tg = ha(Q), ug = ha(ub); Dd.$inject = ["$parse"]; var oe = ha({
        restrict: "E", compile: function (a, b) {
            if (!b.href && !b.xlinkHref) return function (a, b) {
                if ("a" === b[0].nodeName.toLowerCase()) {
                    var e = "[object SVGAnimatedString]" === ma.call(b.prop("href")) ?
                    "xlink:href" : "href"; b.on("click", function (a) { b.attr(e) || a.preventDefault() })
                }
            }
        }
    }), vb = {}; q(Eb, function (a, b) { function d(a, d, e) { a.$watch(e[c], function (a) { e.$set(b, !!a) }) } if ("multiple" != a) { var c = Aa("ng-" + b), e = d; "checked" === a && (e = function (a, b, e) { e.ngModel !== e[c] && d(a, b, e) }); vb[c] = function () { return { restrict: "A", priority: 100, link: e } } } }); q(bd, function (a, b) {
        vb[b] = function () {
            return {
                priority: 100, link: function (a, c, e) {
                    if ("ngPattern" === b && "/" == e.ngPattern.charAt(0) && (c = e.ngPattern.match(Cg))) {
                        e.$set("ngPattern",
                        new RegExp(c[1], c[2])); return
                    } a.$watch(e[b], function (a) { e.$set(b, a) })
                }
            }
        }
    }); q(["src", "srcset", "href"], function (a) { var b = Aa("ng-" + a); vb[b] = function () { return { priority: 99, link: function (d, c, e) { var f = a, g = a; "href" === a && "[object SVGAnimatedString]" === ma.call(c.prop("href")) && (g = "xlinkHref", e.$attr[g] = "xlink:href", f = null); e.$observe(b, function (b) { b ? (e.$set(g, b), Ea && f && c.prop(f, e[g])) : "href" === a && e.$set(g, null) }) } } } }); var Lb = {
        $addControl: A, $$renameControl: function (a, b) { a.$name = b }, $removeControl: A, $setValidity: A,
        $setDirty: A, $setPristine: A, $setSubmitted: A
    }; Jd.$inject = ["$element", "$attrs", "$scope", "$animate", "$interpolate"]; var Sd = function (a) {
        return ["$timeout", "$parse", function (b, d) {
            function c(a) { return "" === a ? d('this[""]').assign : d(a).assign || A } return {
                name: "form", restrict: a ? "EAC" : "E", require: ["form", "^^?form"], controller: Jd, compile: function (d, f) {
                    d.addClass(Ua).addClass(ob); var g = f.name ? "name" : a && f.ngForm ? "ngForm" : !1; return {
                        pre: function (a, d, e, f) {
                            var n = f[0]; if (!("action" in e)) {
                                var p = function (b) {
                                    a.$apply(function () {
                                        n.$commitViewValue();
                                        n.$setSubmitted()
                                    }); b.preventDefault()
                                }; d[0].addEventListener("submit", p, !1); d.on("$destroy", function () { b(function () { d[0].removeEventListener("submit", p, !1) }, 0, !1) })
                            } (f[1] || n.$$parentForm).$addControl(n); var q = g ? c(n.$name) : A; g && (q(a, n), e.$observe(g, function (b) { n.$name !== b && (q(a, void 0), n.$$parentForm.$$renameControl(n, b), q = c(n.$name), q(a, n)) })); d.on("$destroy", function () { n.$$parentForm.$removeControl(n); q(a, void 0); S(n, Lb) })
                        }
                    }
                }
            }
        }]
    }, pe = Sd(), Ce = Sd(!0), Bg = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/,
    Kg = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i, Lg = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/, Mg = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/, Td = /^(\d{4,})-(\d{2})-(\d{2})$/, Ud = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/, rc = /^(\d{4,})-W(\d\d)$/, Vd = /^(\d{4,})-(\d\d)$/,
    Wd = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/, Ld = U(); q(["date", "datetime-local", "month", "time", "week"], function (a) { Ld[a] = !0 }); var Xd = {
        text: function (a, b, d, c, e, f) { lb(a, b, d, c, e, f); pc(c) }, date: mb("date", Td, Nb(Td, ["yyyy", "MM", "dd"]), "yyyy-MM-dd"), "datetime-local": mb("datetimelocal", Ud, Nb(Ud, "yyyy MM dd HH mm ss sss".split(" ")), "yyyy-MM-ddTHH:mm:ss.sss"), time: mb("time", Wd, Nb(Wd, ["HH", "mm", "ss", "sss"]), "HH:mm:ss.sss"), week: mb("week", rc, function (a, b) {
            if (da(a)) return a; if (G(a)) {
                rc.lastIndex = 0; var d = rc.exec(a);
                if (d) { var c = +d[1], e = +d[2], f = d = 0, g = 0, h = 0, k = Hd(c), e = 7 * (e - 1); b && (d = b.getHours(), f = b.getMinutes(), g = b.getSeconds(), h = b.getMilliseconds()); return new Date(c, 0, k.getDate() + e, d, f, g, h) }
            } return NaN
        }, "yyyy-Www"), month: mb("month", Vd, Nb(Vd, ["yyyy", "MM"]), "yyyy-MM"), number: function (a, b, d, c, e, f) {
            Md(a, b, d, c); lb(a, b, d, c, e, f); c.$$parserName = "number"; c.$parsers.push(function (a) { if (c.$isEmpty(a)) return null; if (Mg.test(a)) return parseFloat(a) }); c.$formatters.push(function (a) {
                if (!c.$isEmpty(a)) {
                    if (!T(a)) throw nb("numfmt",
                    a); a = a.toString()
                } return a
            }); if (w(d.min) || d.ngMin) { var g; c.$validators.min = function (a) { return c.$isEmpty(a) || y(g) || a >= g }; d.$observe("min", function (a) { w(a) && !T(a) && (a = parseFloat(a)); g = T(a) && !isNaN(a) ? a : void 0; c.$validate() }) } if (w(d.max) || d.ngMax) { var h; c.$validators.max = function (a) { return c.$isEmpty(a) || y(h) || a <= h }; d.$observe("max", function (a) { w(a) && !T(a) && (a = parseFloat(a)); h = T(a) && !isNaN(a) ? a : void 0; c.$validate() }) }
        }, url: function (a, b, d, c, e, f) {
            lb(a, b, d, c, e, f); pc(c); c.$$parserName = "url"; c.$validators.url =
            function (a, b) { var d = a || b; return c.$isEmpty(d) || Kg.test(d) }
        }, email: function (a, b, d, c, e, f) { lb(a, b, d, c, e, f); pc(c); c.$$parserName = "email"; c.$validators.email = function (a, b) { var d = a || b; return c.$isEmpty(d) || Lg.test(d) } }, radio: function (a, b, d, c) { y(d.name) && b.attr("name", ++pb); b.on("click", function (a) { b[0].checked && c.$setViewValue(d.value, a && a.type) }); c.$render = function () { b[0].checked = d.value == c.$viewValue }; d.$observe("value", c.$render) }, checkbox: function (a, b, d, c, e, f, g, h) {
            var k = Nd(h, a, "ngTrueValue", d.ngTrueValue,
            !0), l = Nd(h, a, "ngFalseValue", d.ngFalseValue, !1); b.on("click", function (a) { c.$setViewValue(b[0].checked, a && a.type) }); c.$render = function () { b[0].checked = c.$viewValue }; c.$isEmpty = function (a) { return !1 === a }; c.$formatters.push(function (a) { return na(a, k) }); c.$parsers.push(function (a) { return a ? k : l })
        }, hidden: A, button: A, submit: A, reset: A, file: A
    }, Gc = ["$browser", "$sniffer", "$filter", "$parse", function (a, b, d, c) {
        return {
            restrict: "E", require: ["?ngModel"], link: {
                pre: function (e, f, g, h) {
                    h[0] && (Xd[Q(g.type)] || Xd.text)(e, f,
                    g, h[0], b, a, d, c)
                }
            }
        }
    }], Ng = /^(true|false|\d+)$/, Ue = function () { return { restrict: "A", priority: 100, compile: function (a, b) { return Ng.test(b.ngValue) ? function (a, b, e) { e.$set("value", a.$eval(e.ngValue)) } : function (a, b, e) { a.$watch(e.ngValue, function (a) { e.$set("value", a) }) } } } }, ue = ["$compile", function (a) { return { restrict: "AC", compile: function (b) { a.$$addBindingClass(b); return function (b, c, e) { a.$$addBindingInfo(c, e.ngBind); c = c[0]; b.$watch(e.ngBind, function (a) { c.textContent = y(a) ? "" : a }) } } } }], we = ["$interpolate", "$compile",
    function (a, b) { return { compile: function (d) { b.$$addBindingClass(d); return function (c, d, f) { c = a(d.attr(f.$attr.ngBindTemplate)); b.$$addBindingInfo(d, c.expressions); d = d[0]; f.$observe("ngBindTemplate", function (a) { d.textContent = y(a) ? "" : a }) } } } }], ve = ["$sce", "$parse", "$compile", function (a, b, d) {
        return {
            restrict: "A", compile: function (c, e) {
                var f = b(e.ngBindHtml), g = b(e.ngBindHtml, function (b) { return a.valueOf(b) }); d.$$addBindingClass(c); return function (b, c, e) {
                    d.$$addBindingInfo(c, e.ngBindHtml); b.$watch(g, function () {
                        var d =
                        f(b); c.html(a.getTrustedHtml(d) || "")
                    })
                }
            }
        }
    }], Te = ha({ restrict: "A", require: "ngModel", link: function (a, b, d, c) { c.$viewChangeListeners.push(function () { a.$eval(d.ngChange) }) } }), xe = qc("", !0), ze = qc("Odd", 0), ye = qc("Even", 1), Ae = Ta({ compile: function (a, b) { b.$set("ngCloak", void 0); a.removeClass("ng-cloak") } }), Be = [function () { return { restrict: "A", scope: !0, controller: "@", priority: 500 } }], Lc = {}, Og = { blur: !0, focus: !0 }; q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),
    function (a) { var b = Aa("ng-" + a); Lc[b] = ["$parse", "$rootScope", function (d, c) { return { restrict: "A", compile: function (e, f) { var g = d(f[b], null, !0); return function (b, d) { d.on(a, function (d) { var e = function () { g(b, { $event: d }) }; Og[a] && c.$$phase ? b.$evalAsync(e) : b.$apply(e) }) } } } }] }); var Ee = ["$animate", "$compile", function (a, b) {
        return {
            multiElement: !0, transclude: "element", priority: 600, terminal: !0, restrict: "A", $$tlb: !0, link: function (d, c, e, f, g) {
                var h, k, l; d.$watch(e.ngIf, function (d) {
                    d ? k || g(function (d, f) {
                        k = f; d[d.length++] =
                        b.$$createComment("end ngIf", e.ngIf); h = { clone: d }; a.enter(d, c.parent(), c)
                    }) : (l && (l.remove(), l = null), k && (k.$destroy(), k = null), h && (l = tb(h.clone), a.leave(l).then(function () { l = null }), h = null))
                })
            }
        }
    }], Fe = ["$templateRequest", "$anchorScroll", "$animate", function (a, b, d) {
        return {
            restrict: "ECA", priority: 400, terminal: !0, transclude: "element", controller: ca.noop, compile: function (c, e) {
                var f = e.ngInclude || e.src, g = e.onload || "", h = e.autoscroll; return function (c, e, m, n, p) {
                    var q = 0, s, B, r, y = function () {
                        B && (B.remove(), B = null); s &&
                        (s.$destroy(), s = null); r && (d.leave(r).then(function () { B = null }), B = r, r = null)
                    }; c.$watch(f, function (f) { var m = function () { !w(h) || h && !c.$eval(h) || b() }, t = ++q; f ? (a(f, !0).then(function (a) { if (!c.$$destroyed && t === q) { var b = c.$new(); n.template = a; a = p(b, function (a) { y(); d.enter(a, null, e).then(m) }); s = b; r = a; s.$emit("$includeContentLoaded", f); c.$eval(g) } }, function () { c.$$destroyed || t !== q || (y(), c.$emit("$includeContentError", f)) }), c.$emit("$includeContentRequested", f)) : (y(), n.template = null) })
                }
            }
        }
    }], We = ["$compile", function (a) {
        return {
            restrict: "ECA",
            priority: -400, require: "ngInclude", link: function (b, d, c, e) { ma.call(d[0]).match(/SVG/) ? (d.empty(), a(Oc(e.template, C.document).childNodes)(b, function (a) { d.append(a) }, { futureParentElement: d })) : (d.html(e.template), a(d.contents())(b)) }
        }
    }], Ge = Ta({ priority: 450, compile: function () { return { pre: function (a, b, d) { a.$eval(d.ngInit) } } } }), Se = function () {
        return {
            restrict: "A", priority: 100, require: "ngModel", link: function (a, b, d, c) {
                var e = b.attr(d.$attr.ngList) || ", ", f = "false" !== d.ngTrim, g = f ? W(e) : e; c.$parsers.push(function (a) {
                    if (!y(a)) {
                        var b =
                        []; a && q(a.split(g), function (a) { a && b.push(f ? W(a) : a) }); return b
                    }
                }); c.$formatters.push(function (a) { if (L(a)) return a.join(e) }); c.$isEmpty = function (a) { return !a || !a.length }
            }
        }
    }, ob = "ng-valid", Od = "ng-invalid", Ua = "ng-pristine", Mb = "ng-dirty", Qd = "ng-pending", nb = N("ngModel"), Pg = ["$scope", "$exceptionHandler", "$attrs", "$element", "$parse", "$animate", "$timeout", "$rootScope", "$q", "$interpolate", function (a, b, d, c, e, f, g, h, k, l) {
        this.$modelValue = this.$viewValue = Number.NaN; this.$$rawModelValue = void 0; this.$validators = {};
        this.$asyncValidators = {}; this.$parsers = []; this.$formatters = []; this.$viewChangeListeners = []; this.$untouched = !0; this.$touched = !1; this.$pristine = !0; this.$dirty = !1; this.$valid = !0; this.$invalid = !1; this.$error = {}; this.$$success = {}; this.$pending = void 0; this.$name = l(d.name || "", !1)(a); this.$$parentForm = Lb; var m = e(d.ngModel), n = m.assign, p = m, u = n, s = null, B, r = this; this.$$setOptions = function (a) {
            if ((r.$options = a) && a.getterSetter) {
                var b = e(d.ngModel + "()"), f = e(d.ngModel + "($$$p)"); p = function (a) {
                    var c = m(a); z(c) && (c = b(a));
                    return c
                }; u = function (a, b) { z(m(a)) ? f(a, { $$$p: b }) : n(a, b) }
            } else if (!m.assign) throw nb("nonassign", d.ngModel, ya(c));
        }; this.$render = A; this.$isEmpty = function (a) { return y(a) || "" === a || null === a || a !== a }; this.$$updateEmptyClasses = function (a) { r.$isEmpty(a) ? (f.removeClass(c, "ng-not-empty"), f.addClass(c, "ng-empty")) : (f.removeClass(c, "ng-empty"), f.addClass(c, "ng-not-empty")) }; var J = 0; Kd({ ctrl: this, $element: c, set: function (a, b) { a[b] = !0 }, unset: function (a, b) { delete a[b] }, $animate: f }); this.$setPristine = function () {
            r.$dirty =
            !1; r.$pristine = !0; f.removeClass(c, Mb); f.addClass(c, Ua)
        }; this.$setDirty = function () { r.$dirty = !0; r.$pristine = !1; f.removeClass(c, Ua); f.addClass(c, Mb); r.$$parentForm.$setDirty() }; this.$setUntouched = function () { r.$touched = !1; r.$untouched = !0; f.setClass(c, "ng-untouched", "ng-touched") }; this.$setTouched = function () { r.$touched = !0; r.$untouched = !1; f.setClass(c, "ng-touched", "ng-untouched") }; this.$rollbackViewValue = function () { g.cancel(s); r.$viewValue = r.$$lastCommittedViewValue; r.$render() }; this.$validate = function () {
            if (!T(r.$modelValue) ||
            !isNaN(r.$modelValue)) { var a = r.$$rawModelValue, b = r.$valid, c = r.$modelValue, d = r.$options && r.$options.allowInvalid; r.$$runValidators(a, r.$$lastCommittedViewValue, function (e) { d || b === e || (r.$modelValue = e ? a : void 0, r.$modelValue !== c && r.$$writeModelToScope()) }) }
        }; this.$$runValidators = function (a, b, c) {
            function d() { var c = !0; q(r.$validators, function (d, e) { var g = d(a, b); c = c && g; f(e, g) }); return c ? !0 : (q(r.$asyncValidators, function (a, b) { f(b, null) }), !1) } function e() {
                var c = [], d = !0; q(r.$asyncValidators, function (e, g) {
                    var h =
                    e(a, b); if (!h || !z(h.then)) throw nb("nopromise", h); f(g, void 0); c.push(h.then(function () { f(g, !0) }, function () { d = !1; f(g, !1) }))
                }); c.length ? k.all(c).then(function () { g(d) }, A) : g(!0)
            } function f(a, b) { h === J && r.$setValidity(a, b) } function g(a) { h === J && c(a) } J++; var h = J; (function () { var a = r.$$parserName || "parse"; if (y(B)) f(a, null); else return B || (q(r.$validators, function (a, b) { f(b, null) }), q(r.$asyncValidators, function (a, b) { f(b, null) })), f(a, B), B; return !0 })() ? d() ? e() : g(!1) : g(!1)
        }; this.$commitViewValue = function () {
            var a =
            r.$viewValue; g.cancel(s); if (r.$$lastCommittedViewValue !== a || "" === a && r.$$hasNativeValidators) r.$$updateEmptyClasses(a), r.$$lastCommittedViewValue = a, r.$pristine && this.$setDirty(), this.$$parseAndValidate()
        }; this.$$parseAndValidate = function () {
            var b = r.$$lastCommittedViewValue; if (B = y(b) ? void 0 : !0) for (var c = 0; c < r.$parsers.length; c++) if (b = r.$parsers[c](b), y(b)) { B = !1; break } T(r.$modelValue) && isNaN(r.$modelValue) && (r.$modelValue = p(a)); var d = r.$modelValue, e = r.$options && r.$options.allowInvalid; r.$$rawModelValue =
            b; e && (r.$modelValue = b, r.$modelValue !== d && r.$$writeModelToScope()); r.$$runValidators(b, r.$$lastCommittedViewValue, function (a) { e || (r.$modelValue = a ? b : void 0, r.$modelValue !== d && r.$$writeModelToScope()) })
        }; this.$$writeModelToScope = function () { u(a, r.$modelValue); q(r.$viewChangeListeners, function (a) { try { a() } catch (c) { b(c) } }) }; this.$setViewValue = function (a, b) { r.$viewValue = a; r.$options && !r.$options.updateOnDefault || r.$$debounceViewValueCommit(b) }; this.$$debounceViewValueCommit = function (b) {
            var c = 0, d = r.$options;
            d && w(d.debounce) && (d = d.debounce, T(d) ? c = d : T(d[b]) ? c = d[b] : T(d["default"]) && (c = d["default"])); g.cancel(s); c ? s = g(function () { r.$commitViewValue() }, c) : h.$$phase ? r.$commitViewValue() : a.$apply(function () { r.$commitViewValue() })
        }; a.$watch(function () {
            var b = p(a); if (b !== r.$modelValue && (r.$modelValue === r.$modelValue || b === b)) {
                r.$modelValue = r.$$rawModelValue = b; B = void 0; for (var c = r.$formatters, d = c.length, e = b; d--;) e = c[d](e); r.$viewValue !== e && (r.$$updateEmptyClasses(e), r.$viewValue = r.$$lastCommittedViewValue = e, r.$render(),
                r.$$runValidators(b, e, A))
            } return b
        })
    }], Re = ["$rootScope", function (a) {
        return {
            restrict: "A", require: ["ngModel", "^?form", "^?ngModelOptions"], controller: Pg, priority: 1, compile: function (b) {
                b.addClass(Ua).addClass("ng-untouched").addClass(ob); return {
                    pre: function (a, b, e, f) { var g = f[0]; b = f[1] || g.$$parentForm; g.$$setOptions(f[2] && f[2].$options); b.$addControl(g); e.$observe("name", function (a) { g.$name !== a && g.$$parentForm.$$renameControl(g, a) }); a.$on("$destroy", function () { g.$$parentForm.$removeControl(g) }) }, post: function (b,
                    c, e, f) { var g = f[0]; if (g.$options && g.$options.updateOn) c.on(g.$options.updateOn, function (a) { g.$$debounceViewValueCommit(a && a.type) }); c.on("blur", function () { g.$touched || (a.$$phase ? b.$evalAsync(g.$setTouched) : b.$apply(g.$setTouched)) }) }
                }
            }
        }
    }], Qg = /(\s+|^)default(\s+|$)/, Ve = function () {
        return {
            restrict: "A", controller: ["$scope", "$attrs", function (a, b) {
                var d = this; this.$options = pa(a.$eval(b.ngModelOptions)); w(this.$options.updateOn) ? (this.$options.updateOnDefault = !1, this.$options.updateOn = W(this.$options.updateOn.replace(Qg,
                function () { d.$options.updateOnDefault = !0; return " " }))) : this.$options.updateOnDefault = !0
            }]
        }
    }, He = Ta({ terminal: !0, priority: 1E3 }), Rg = N("ngOptions"), Sg = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/, Pe = ["$compile", "$document", "$parse", function (a, b, d) {
        function c(a, b, c) {
            function e(a, b, c, d, f) {
                this.selectValue = a; this.viewValue =
                b; this.label = c; this.group = d; this.disabled = f
            } function f(a) { var b; if (!q && ta(a)) b = a; else { b = []; for (var c in a) a.hasOwnProperty(c) && "$" !== c.charAt(0) && b.push(c) } return b } var n = a.match(Sg); if (!n) throw Rg("iexp", a, ya(b)); var p = n[5] || n[7], q = n[6]; a = / as /.test(n[0]) && n[1]; var s = n[9]; b = d(n[2] ? n[1] : p); var w = a && d(a) || b, r = s && d(s), y = s ? function (a, b) { return r(c, b) } : function (a) { return Ca(a) }, v = function (a, b) { return y(a, E(a, b)) }, A = d(n[2] || n[1]), t = d(n[3] || ""), K = d(n[4] || ""), z = d(n[8]), H = {}, E = q ? function (a, b) {
                H[q] = b; H[p] =
                a; return H
            } : function (a) { H[p] = a; return H }; return {
                trackBy: s, getTrackByValue: v, getWatchables: d(z, function (a) { var b = []; a = a || []; for (var d = f(a), e = d.length, g = 0; g < e; g++) { var h = a === d ? g : d[g], l = a[h], h = E(l, h), l = y(l, h); b.push(l); if (n[2] || n[1]) l = A(c, h), b.push(l); n[4] && (h = K(c, h), b.push(h)) } return b }), getOptions: function () {
                    for (var a = [], b = {}, d = z(c) || [], g = f(d), h = g.length, n = 0; n < h; n++) { var p = d === g ? n : g[n], q = E(d[p], p), r = w(c, q), p = y(r, q), u = A(c, q), H = t(c, q), q = K(c, q), r = new e(p, r, u, H, q); a.push(r); b[p] = r } return {
                        items: a, selectValueMap: b,
                        getOptionFromViewValue: function (a) { return b[v(a)] }, getViewValueFromOption: function (a) { return s ? ca.copy(a.viewValue) : a.viewValue }
                    }
                }
            }
        } var e = C.document.createElement("option"), f = C.document.createElement("optgroup"); return {
            restrict: "A", terminal: !0, require: ["select", "ngModel"], link: {
                pre: function (a, b, c, d) { d[0].registerOption = A }, post: function (d, h, k, l) {
                    function m(a, b) { a.element = b; b.disabled = a.disabled; a.label !== b.label && (b.label = a.label, b.textContent = a.label); a.value !== b.value && (b.value = a.selectValue) } function n() {
                        var a =
                        t && p.readValue(); if (t) for (var b = t.items.length - 1; 0 <= b; b--) { var c = t.items[b]; w(c.group) ? Db(c.element.parentNode) : Db(c.element) } t = K.getOptions(); var d = {}; v && h.prepend(B); t.items.forEach(function (a) { var b; if (w(a.group)) { b = d[a.group]; b || (b = f.cloneNode(!1), C.appendChild(b), b.label = null === a.group ? "null" : a.group, d[a.group] = b); var c = e.cloneNode(!1) } else b = C, c = e.cloneNode(!1); b.appendChild(c); m(a, c) }); h[0].appendChild(C); s.$render(); s.$isEmpty(a) || (b = p.readValue(), (K.trackBy || y ? na(a, b) : a === b) || (s.$setViewValue(b),
                        s.$render()))
                    } var p = l[0], s = l[1], y = k.multiple, B; l = 0; for (var r = h.children(), A = r.length; l < A; l++) if ("" === r[l].value) { B = r.eq(l); break } var v = !!B, z = F(e.cloneNode(!1)); z.val("?"); var t, K = c(k.ngOptions, h, d), C = b[0].createDocumentFragment(); y ? (s.$isEmpty = function (a) { return !a || 0 === a.length }, p.writeValue = function (a) { t.items.forEach(function (a) { a.element.selected = !1 }); a && a.forEach(function (a) { if (a = t.getOptionFromViewValue(a)) a.element.selected = !0 }) }, p.readValue = function () {
                        var a = h.val() || [], b = []; q(a, function (a) {
                            (a =
                            t.selectValueMap[a]) && !a.disabled && b.push(t.getViewValueFromOption(a))
                        }); return b
                    }, K.trackBy && d.$watchCollection(function () { if (L(s.$viewValue)) return s.$viewValue.map(function (a) { return K.getTrackByValue(a) }) }, function () { s.$render() })) : (p.writeValue = function (a) {
                        var b = t.getOptionFromViewValue(a); b ? (h[0].value !== b.selectValue && (z.remove(), v || B.remove(), h[0].value = b.selectValue, b.element.selected = !0), b.element.setAttribute("selected", "selected")) : null === a || v ? (z.remove(), v || h.prepend(B), h.val(""), B.prop("selected",
                        !0), B.attr("selected", !0)) : (v || B.remove(), h.prepend(z), h.val("?"), z.prop("selected", !0), z.attr("selected", !0))
                    }, p.readValue = function () { var a = t.selectValueMap[h.val()]; return a && !a.disabled ? (v || B.remove(), z.remove(), t.getViewValueFromOption(a)) : null }, K.trackBy && d.$watch(function () { return K.getTrackByValue(s.$viewValue) }, function () { s.$render() })); v ? (B.remove(), a(B)(d), B.removeClass("ng-scope")) : B = F(e.cloneNode(!1)); h.empty(); n(); d.$watchCollection(K.getWatchables, n)
                }
            }
        }
    }], Ie = ["$locale", "$interpolate",
    "$log", function (a, b, d) {
        var c = /{}/g, e = /^when(Minus)?(.+)$/; return {
            link: function (f, g, h) {
                function k(a) { g.text(a || "") } var l = h.count, m = h.$attr.when && g.attr(h.$attr.when), n = h.offset || 0, p = f.$eval(m) || {}, s = {}, w = b.startSymbol(), B = b.endSymbol(), r = w + l + "-" + n + B, z = ca.noop, v; q(h, function (a, b) { var c = e.exec(b); c && (c = (c[1] ? "-" : "") + Q(c[2]), p[c] = g.attr(h.$attr[b])) }); q(p, function (a, d) { s[d] = b(a.replace(c, r)) }); f.$watch(l, function (b) {
                    var c = parseFloat(b), e = isNaN(c); e || c in p || (c = a.pluralCat(c - n)); c === v || e && T(v) && isNaN(v) ||
                    (z(), e = s[c], y(e) ? (null != b && d.debug("ngPluralize: no rule defined for '" + c + "' in " + m), z = A, k()) : z = f.$watch(e, k), v = c)
                })
            }
        }
    }], Je = ["$parse", "$animate", "$compile", function (a, b, d) {
        var c = N("ngRepeat"), e = function (a, b, c, d, e, m, n) { a[c] = d; e && (a[e] = m); a.$index = b; a.$first = 0 === b; a.$last = b === n - 1; a.$middle = !(a.$first || a.$last); a.$odd = !(a.$even = 0 === (b & 1)) }; return {
            restrict: "A", multiElement: !0, transclude: "element", priority: 1E3, terminal: !0, $$tlb: !0, compile: function (f, g) {
                var h = g.ngRepeat, k = d.$$createComment("end ngRepeat",
                h), l = h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); if (!l) throw c("iexp", h); var m = l[1], n = l[2], p = l[3], s = l[4], l = m.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); if (!l) throw c("iidexp", m); var w = l[3] || l[1], y = l[2]; if (p && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(p) || /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(p))) throw c("badident", p); var r, z, v, A, t = { $id: Ca }; s ? r = a(s) : (v = function (a, b) { return Ca(b) },
                A = function (a) { return a }); return function (a, d, f, g, l) {
                    r && (z = function (b, c, d) { y && (t[y] = b); t[w] = c; t.$index = d; return r(a, t) }); var m = U(); a.$watchCollection(n, function (f) {
                        var g, n, r = d[0], s, u = U(), t, C, F, E, G, D, H; p && (a[p] = f); if (ta(f)) G = f, n = z || v; else for (H in n = z || A, G = [], f) ua.call(f, H) && "$" !== H.charAt(0) && G.push(H); t = G.length; H = Array(t); for (g = 0; g < t; g++) if (C = f === G ? g : G[g], F = f[C], E = n(C, F, g), m[E]) D = m[E], delete m[E], u[E] = D, H[g] = D; else {
                            if (u[E]) throw q(H, function (a) { a && a.scope && (m[a.id] = a) }), c("dupes", h, E, F); H[g] = {
                                id: E,
                                scope: void 0, clone: void 0
                            }; u[E] = !0
                        } for (s in m) { D = m[s]; E = tb(D.clone); b.leave(E); if (E[0].parentNode) for (g = 0, n = E.length; g < n; g++) E[g].$$NG_REMOVED = !0; D.scope.$destroy() } for (g = 0; g < t; g++) if (C = f === G ? g : G[g], F = f[C], D = H[g], D.scope) { s = r; do s = s.nextSibling; while (s && s.$$NG_REMOVED); D.clone[0] != s && b.move(tb(D.clone), null, r); r = D.clone[D.clone.length - 1]; e(D.scope, g, w, F, y, C, t) } else l(function (a, c) { D.scope = c; var d = k.cloneNode(!1); a[a.length++] = d; b.enter(a, null, r); r = d; D.clone = a; u[D.id] = D; e(D.scope, g, w, F, y, C, t) }); m =
                        u
                    })
                }
            }
        }
    }], Ke = ["$animate", function (a) { return { restrict: "A", multiElement: !0, link: function (b, d, c) { b.$watch(c.ngShow, function (b) { a[b ? "removeClass" : "addClass"](d, "ng-hide", { tempClasses: "ng-hide-animate" }) }) } } }], De = ["$animate", function (a) { return { restrict: "A", multiElement: !0, link: function (b, d, c) { b.$watch(c.ngHide, function (b) { a[b ? "addClass" : "removeClass"](d, "ng-hide", { tempClasses: "ng-hide-animate" }) }) } } }], Le = Ta(function (a, b, d) {
        a.$watch(d.ngStyle, function (a, d) { d && a !== d && q(d, function (a, c) { b.css(c, "") }); a && b.css(a) },
        !0)
    }), Me = ["$animate", "$compile", function (a, b) {
        return {
            require: "ngSwitch", controller: ["$scope", function () { this.cases = {} }], link: function (d, c, e, f) {
                var g = [], h = [], k = [], l = [], m = function (a, b) { return function () { a.splice(b, 1) } }; d.$watch(e.ngSwitch || e.on, function (c) {
                    var d, e; d = 0; for (e = k.length; d < e; ++d) a.cancel(k[d]); d = k.length = 0; for (e = l.length; d < e; ++d) { var s = tb(h[d].clone); l[d].$destroy(); (k[d] = a.leave(s)).then(m(k, d)) } h.length = 0; l.length = 0; (g = f.cases["!" + c] || f.cases["?"]) && q(g, function (c) {
                        c.transclude(function (d,
                        e) { l.push(e); var f = c.element; d[d.length++] = b.$$createComment("end ngSwitchWhen"); h.push({ clone: d }); a.enter(d, f.parent(), f) })
                    })
                })
            }
        }
    }], Ne = Ta({ transclude: "element", priority: 1200, require: "^ngSwitch", multiElement: !0, link: function (a, b, d, c, e) { c.cases["!" + d.ngSwitchWhen] = c.cases["!" + d.ngSwitchWhen] || []; c.cases["!" + d.ngSwitchWhen].push({ transclude: e, element: b }) } }), Oe = Ta({
        transclude: "element", priority: 1200, require: "^ngSwitch", multiElement: !0, link: function (a, b, d, c, e) {
            c.cases["?"] = c.cases["?"] || []; c.cases["?"].push({
                transclude: e,
                element: b
            })
        }
    }), Tg = N("ngTransclude"), Qe = ["$compile", function (a) { return { restrict: "EAC", terminal: !0, compile: function (b) { var d = a(b.contents()); b.empty(); return function (a, b, f, g, h) { function k() { d(a, function (a) { b.append(a) }) } if (!h) throw Tg("orphan", ya(b)); f.ngTransclude === f.$attr.ngTransclude && (f.ngTransclude = ""); f = f.ngTransclude || f.ngTranscludeSlot; h(function (a, c) { a.length ? b.append(a) : (k(), c.$destroy()) }, null, f); f && !h.isSlotFilled(f) && k() } } } }], qe = ["$templateCache", function (a) {
        return {
            restrict: "E", terminal: !0,
            compile: function (b, d) { "text/ng-template" == d.type && a.put(d.id, b[0].text) }
        }
    }], Ug = { $setViewValue: A, $render: A }, Vg = ["$element", "$scope", function (a, b) {
        var d = this, c = new Ra; d.ngModelCtrl = Ug; d.unknownOption = F(C.document.createElement("option")); d.renderUnknownOption = function (b) { b = "? " + Ca(b) + " ?"; d.unknownOption.val(b); a.prepend(d.unknownOption); a.val(b) }; b.$on("$destroy", function () { d.renderUnknownOption = A }); d.removeUnknownOption = function () { d.unknownOption.parent() && d.unknownOption.remove() }; d.readValue = function () {
            d.removeUnknownOption();
            return a.val()
        }; d.writeValue = function (b) { d.hasOption(b) ? (d.removeUnknownOption(), a.val(b), "" === b && d.emptyOption.prop("selected", !0)) : null == b && d.emptyOption ? (d.removeUnknownOption(), a.val("")) : d.renderUnknownOption(b) }; d.addOption = function (a, b) { if (8 !== b[0].nodeType) { Qa(a, '"option value"'); "" === a && (d.emptyOption = b); var g = c.get(a) || 0; c.put(a, g + 1); d.ngModelCtrl.$render(); b[0].hasAttribute("selected") && (b[0].selected = !0) } }; d.removeOption = function (a) {
            var b = c.get(a); b && (1 === b ? (c.remove(a), "" === a && (d.emptyOption =
            void 0)) : c.put(a, b - 1))
        }; d.hasOption = function (a) { return !!c.get(a) }; d.registerOption = function (a, b, c, h, k) { if (h) { var l; c.$observe("value", function (a) { w(l) && d.removeOption(l); l = a; d.addOption(a, b) }) } else k ? a.$watch(k, function (a, e) { c.$set("value", a); e !== a && d.removeOption(e); d.addOption(a, b) }) : d.addOption(c.value, b); b.on("$destroy", function () { d.removeOption(c.value); d.ngModelCtrl.$render() }) }
    }], re = function () {
        return {
            restrict: "E", require: ["select", "?ngModel"], controller: Vg, priority: 1, link: {
                pre: function (a, b,
                d, c) {
                    var e = c[1]; if (e) {
                        var f = c[0]; f.ngModelCtrl = e; b.on("change", function () { a.$apply(function () { e.$setViewValue(f.readValue()) }) }); if (d.multiple) {
                            f.readValue = function () { var a = []; q(b.find("option"), function (b) { b.selected && a.push(b.value) }); return a }; f.writeValue = function (a) { var c = new Ra(a); q(b.find("option"), function (a) { a.selected = w(c.get(a.value)) }) }; var g, h = NaN; a.$watch(function () { h !== e.$viewValue || na(g, e.$viewValue) || (g = ia(e.$viewValue), e.$render()); h = e.$viewValue }); e.$isEmpty = function (a) {
                                return !a ||
                                0 === a.length
                            }
                        }
                    }
                }, post: function (a, b, d, c) { var e = c[1]; if (e) { var f = c[0]; e.$render = function () { f.writeValue(e.$viewValue) } } }
            }
        }
    }, te = ["$interpolate", function (a) { return { restrict: "E", priority: 100, compile: function (b, d) { if (w(d.value)) var c = a(d.value, !0); else { var e = a(b.text(), !0); e || d.$set("value", b.text()) } return function (a, b, d) { var k = b.parent(); (k = k.data("$selectController") || k.parent().data("$selectController")) && k.registerOption(a, b, d, c, e) } } } }], se = ha({ restrict: "E", terminal: !1 }), Ic = function () {
        return {
            restrict: "A",
            require: "?ngModel", link: function (a, b, d, c) { c && (d.required = !0, c.$validators.required = function (a, b) { return !d.required || !c.$isEmpty(b) }, d.$observe("required", function () { c.$validate() })) }
        }
    }, Hc = function () {
        return {
            restrict: "A", require: "?ngModel", link: function (a, b, d, c) {
                if (c) {
                    var e, f = d.ngPattern || d.pattern; d.$observe("pattern", function (a) { G(a) && 0 < a.length && (a = new RegExp("^" + a + "$")); if (a && !a.test) throw N("ngPattern")("noregexp", f, a, ya(b)); e = a || void 0; c.$validate() }); c.$validators.pattern = function (a, b) {
                        return c.$isEmpty(b) ||
                        y(e) || e.test(b)
                    }
                }
            }
        }
    }, Kc = function () { return { restrict: "A", require: "?ngModel", link: function (a, b, d, c) { if (c) { var e = -1; d.$observe("maxlength", function (a) { a = Z(a); e = isNaN(a) ? -1 : a; c.$validate() }); c.$validators.maxlength = function (a, b) { return 0 > e || c.$isEmpty(b) || b.length <= e } } } } }, Jc = function () { return { restrict: "A", require: "?ngModel", link: function (a, b, d, c) { if (c) { var e = 0; d.$observe("minlength", function (a) { e = Z(a) || 0; c.$validate() }); c.$validators.minlength = function (a, b) { return c.$isEmpty(b) || b.length >= e } } } } }; C.angular.bootstrap ?
    C.console && console.log("WARNING: Tried to load angular more than once.") : (je(), le(ca), ca.module("ngLocale", [], ["$provide", function (a) {
        function b(a) { a += ""; var b = a.indexOf("."); return -1 == b ? 0 : a.length - b - 1 } a.value("$locale", {
            DATETIME_FORMATS: {
                AMPMS: ["AM", "PM"], DAY: "Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), ERANAMES: ["Before Christ", "Anno Domini"], ERAS: ["BC", "AD"], FIRSTDAYOFWEEK: 6, MONTH: "January February March April May June July August September October November December".split(" "),
                SHORTDAY: "Sun Mon Tue Wed Thu Fri Sat".split(" "), SHORTMONTH: "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "), STANDALONEMONTH: "January February March April May June July August September October November December".split(" "), WEEKENDRANGE: [5, 6], fullDate: "EEEE, MMMM d, y", longDate: "MMMM d, y", medium: "MMM d, y h:mm:ss a", mediumDate: "MMM d, y", mediumTime: "h:mm:ss a", "short": "M/d/yy h:mm a", shortDate: "M/d/yy", shortTime: "h:mm a"
            }, NUMBER_FORMATS: {
                CURRENCY_SYM: "$", DECIMAL_SEP: ".", GROUP_SEP: ",",
                PATTERNS: [{ gSize: 3, lgSize: 3, maxFrac: 3, minFrac: 0, minInt: 1, negPre: "-", negSuf: "", posPre: "", posSuf: "" }, { gSize: 3, lgSize: 3, maxFrac: 2, minFrac: 2, minInt: 1, negPre: "-\u00a4", negSuf: "", posPre: "\u00a4", posSuf: "" }]
            }, id: "en-us", localeID: "en_US", pluralCat: function (a, c) { var e = a | 0, f = c; void 0 === f && (f = Math.min(b(a), 3)); Math.pow(10, f); return 1 == e && 0 == f ? "one" : "other" }
        })
    }]), F(C.document).ready(function () { fe(C.document, Bc) }))
})(window); !window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
//# sourceMappingURL=angular.min.js.map;
/**
 * @license AngularJS v1.5.8
 * (c) 2010-2016 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function(window, angular) {'use strict';

/**
 * @ngdoc module
 * @name ngCookies
 * @description
 *
 * # ngCookies
 *
 * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
 *
 *
 * <div doc-module-components="ngCookies"></div>
 *
 * See {@link ngCookies.$cookies `$cookies`} for usage.
 */


angular.module('ngCookies', ['ng']).
  /**
   * @ngdoc provider
   * @name $cookiesProvider
   * @description
   * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
   * */
   provider('$cookies', [function $CookiesProvider() {
    /**
     * @ngdoc property
     * @name $cookiesProvider#defaults
     * @description
     *
     * Object containing default options to pass when setting cookies.
     *
     * The object may have following properties:
     *
     * - **path** - `{string}` - The cookie will be available only for this path and its
     *   sub-paths. By default, this is the URL that appears in your `<base>` tag.
     * - **domain** - `{string}` - The cookie will be available only for this domain and
     *   its sub-domains. For security reasons the user agent will not accept the cookie
     *   if the current domain is not a sub-domain of this domain or equal to it.
     * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
     *   or a Date object indicating the exact date/time this cookie will expire.
     * - **secure** - `{boolean}` - If `true`, then the cookie will only be available through a
     *   secured connection.
     *
     * Note: By default, the address that appears in your `<base>` tag will be used as the path.
     * This is important so that cookies will be visible for all routes when html5mode is enabled.
     *
     **/
    var defaults = this.defaults = {};

    function calcOptions(options) {
      return options ? angular.extend({}, defaults, options) : defaults;
    }

    /**
     * @ngdoc service
     * @name $cookies
     *
     * @description
     * Provides read/write access to browser's cookies.
     *
     * <div class="alert alert-info">
     * Up until Angular 1.3, `$cookies` exposed properties that represented the
     * current browser cookie values. In version 1.4, this behavior has changed, and
     * `$cookies` now provides a standard api of getters, setters etc.
     * </div>
     *
     * Requires the {@link ngCookies `ngCookies`} module to be installed.
     *
     * @example
     *
     * ```js
     * angular.module('cookiesExample', ['ngCookies'])
     *   .controller('ExampleController', ['$cookies', function($cookies) {
     *     // Retrieving a cookie
     *     var favoriteCookie = $cookies.get('myFavorite');
     *     // Setting a cookie
     *     $cookies.put('myFavorite', 'oatmeal');
     *   }]);
     * ```
     */
    this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
      return {
        /**
         * @ngdoc method
         * @name $cookies#get
         *
         * @description
         * Returns the value of given cookie key
         *
         * @param {string} key Id to use for lookup.
         * @returns {string} Raw cookie value.
         */
        get: function(key) {
          return $$cookieReader()[key];
        },

        /**
         * @ngdoc method
         * @name $cookies#getObject
         *
         * @description
         * Returns the deserialized value of given cookie key
         *
         * @param {string} key Id to use for lookup.
         * @returns {Object} Deserialized cookie value.
         */
        getObject: function(key) {
          var value = this.get(key);
          return value ? angular.fromJson(value) : value;
        },

        /**
         * @ngdoc method
         * @name $cookies#getAll
         *
         * @description
         * Returns a key value object with all the cookies
         *
         * @returns {Object} All cookies
         */
        getAll: function() {
          return $$cookieReader();
        },

        /**
         * @ngdoc method
         * @name $cookies#put
         *
         * @description
         * Sets a value for given cookie key
         *
         * @param {string} key Id for the `value`.
         * @param {string} value Raw value to be stored.
         * @param {Object=} options Options object.
         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
         */
        put: function(key, value, options) {
          $$cookieWriter(key, value, calcOptions(options));
        },

        /**
         * @ngdoc method
         * @name $cookies#putObject
         *
         * @description
         * Serializes and sets a value for given cookie key
         *
         * @param {string} key Id for the `value`.
         * @param {Object} value Value to be stored.
         * @param {Object=} options Options object.
         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
         */
        putObject: function(key, value, options) {
          this.put(key, angular.toJson(value), options);
        },

        /**
         * @ngdoc method
         * @name $cookies#remove
         *
         * @description
         * Remove given cookie
         *
         * @param {string} key Id of the key-value pair to delete.
         * @param {Object=} options Options object.
         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
         */
        remove: function(key, options) {
          $$cookieWriter(key, undefined, calcOptions(options));
        }
      };
    }];
  }]);

angular.module('ngCookies').
/**
 * @ngdoc service
 * @name $cookieStore
 * @deprecated
 * @requires $cookies
 *
 * @description
 * Provides a key-value (string-object) storage, that is backed by session cookies.
 * Objects put or retrieved from this storage are automatically serialized or
 * deserialized by angular's toJson/fromJson.
 *
 * Requires the {@link ngCookies `ngCookies`} module to be installed.
 *
 * <div class="alert alert-danger">
 * **Note:** The $cookieStore service is **deprecated**.
 * Please use the {@link ngCookies.$cookies `$cookies`} service instead.
 * </div>
 *
 * @example
 *
 * ```js
 * angular.module('cookieStoreExample', ['ngCookies'])
 *   .controller('ExampleController', ['$cookieStore', function($cookieStore) {
 *     // Put cookie
 *     $cookieStore.put('myFavorite','oatmeal');
 *     // Get cookie
 *     var favoriteCookie = $cookieStore.get('myFavorite');
 *     // Removing a cookie
 *     $cookieStore.remove('myFavorite');
 *   }]);
 * ```
 */
 factory('$cookieStore', ['$cookies', function($cookies) {

    return {
      /**
       * @ngdoc method
       * @name $cookieStore#get
       *
       * @description
       * Returns the value of given cookie key
       *
       * @param {string} key Id to use for lookup.
       * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
       */
      get: function(key) {
        return $cookies.getObject(key);
      },

      /**
       * @ngdoc method
       * @name $cookieStore#put
       *
       * @description
       * Sets a value for given cookie key
       *
       * @param {string} key Id for the `value`.
       * @param {Object} value Value to be stored.
       */
      put: function(key, value) {
        $cookies.putObject(key, value);
      },

      /**
       * @ngdoc method
       * @name $cookieStore#remove
       *
       * @description
       * Remove given cookie
       *
       * @param {string} key Id of the key-value pair to delete.
       */
      remove: function(key) {
        $cookies.remove(key);
      }
    };

  }]);

/**
 * @name $$cookieWriter
 * @requires $document
 *
 * @description
 * This is a private service for writing cookies
 *
 * @param {string} name Cookie name
 * @param {string=} value Cookie value (if undefined, cookie will be deleted)
 * @param {Object=} options Object with options that need to be stored for the cookie.
 */
function $$CookieWriter($document, $log, $browser) {
  var cookiePath = $browser.baseHref();
  var rawDocument = $document[0];

  function buildCookieString(name, value, options) {
    var path, expires;
    options = options || {};
    expires = options.expires;
    path = angular.isDefined(options.path) ? options.path : cookiePath;
    if (angular.isUndefined(value)) {
      expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
      value = '';
    }
    if (angular.isString(expires)) {
      expires = new Date(expires);
    }

    var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
    str += path ? ';path=' + path : '';
    str += options.domain ? ';domain=' + options.domain : '';
    str += expires ? ';expires=' + expires.toUTCString() : '';
    str += options.secure ? ';secure' : '';

    // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
    // - 300 cookies
    // - 20 cookies per unique domain
    // - 4096 bytes per cookie
    var cookieLength = str.length + 1;
    if (cookieLength > 4096) {
      $log.warn("Cookie '" + name +
        "' possibly not set or overflowed because it was too large (" +
        cookieLength + " > 4096 bytes)!");
    }

    return str;
  }

  return function(name, value, options) {
    rawDocument.cookie = buildCookieString(name, value, options);
  };
}

$$CookieWriter.$inject = ['$document', '$log', '$browser'];

angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
  this.$get = $$CookieWriter;
});


})(window, window.angular);;
/**
 * @license AngularJS v1.5.8
 * (c) 2010-2016 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function (window, angular) {
    'use strict';

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *     Any commits to this file should be reviewed with security in mind.  *
     *   Changes to this file can potentially create security vulnerabilities. *
     *          An approval from 2 Core members with history of modifying      *
     *                         this file is required.                          *
     *                                                                         *
     *  Does the change somehow allow for arbitrary javascript to be executed? *
     *    Or allows for someone to change the prototype of built-in objects?   *
     *     Or gives undesired access to variables likes document or window?    *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    var $sanitizeMinErr = angular.$$minErr('$sanitize');
    var bind;
    var extend;
    var forEach;
    var isDefined;
    var lowercase;
    var noop;
    var htmlParser;
    var htmlSanitizeWriter;

    /**
     * @ngdoc module
     * @name ngSanitize
     * @description
     *
     * # ngSanitize
     *
     * The `ngSanitize` module provides functionality to sanitize HTML.
     *
     *
     * <div doc-module-components="ngSanitize"></div>
     *
     * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
     */

    /**
     * @ngdoc service
     * @name $sanitize
     * @kind function
     *
     * @description
     *   Sanitizes an html string by stripping all potentially dangerous tokens.
     *
     *   The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
     *   then serialized back to properly escaped html string. This means that no unsafe input can make
     *   it into the returned string.
     *
     *   The whitelist for URL sanitization of attribute values is configured using the functions
     *   `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider
     *   `$compileProvider`}.
     *
     *   The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
     *
     * @param {string} html HTML input.
     * @returns {string} Sanitized HTML.
     *
     * @example
       <example module="sanitizeExample" deps="angular-sanitize.js">
       <file name="index.html">
         <script>
             angular.module('sanitizeExample', ['ngSanitize'])
               .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
                 $scope.snippet =
                   '<p style="color:blue">an html\n' +
                   '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
                   'snippet</p>';
                 $scope.deliberatelyTrustDangerousSnippet = function() {
                   return $sce.trustAsHtml($scope.snippet);
                 };
               }]);
         </script>
         <div ng-controller="ExampleController">
            Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
           <table>
             <tr>
               <td>Directive</td>
               <td>How</td>
               <td>Source</td>
               <td>Rendered</td>
             </tr>
             <tr id="bind-html-with-sanitize">
               <td>ng-bind-html</td>
               <td>Automatically uses $sanitize</td>
               <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
               <td><div ng-bind-html="snippet"></div></td>
             </tr>
             <tr id="bind-html-with-trust">
               <td>ng-bind-html</td>
               <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
               <td>
               <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
    &lt;/div&gt;</pre>
               </td>
               <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
             </tr>
             <tr id="bind-default">
               <td>ng-bind</td>
               <td>Automatically escapes</td>
               <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
               <td><div ng-bind="snippet"></div></td>
             </tr>
           </table>
           </div>
       </file>
       <file name="protractor.js" type="protractor">
         it('should sanitize the html snippet by default', function() {
           expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
             toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
         });
    
         it('should inline raw snippet if bound to a trusted value', function() {
           expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
             toBe("<p style=\"color:blue\">an html\n" +
                  "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
                  "snippet</p>");
         });
    
         it('should escape snippet without any filter', function() {
           expect(element(by.css('#bind-default div')).getInnerHtml()).
             toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
                  "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
                  "snippet&lt;/p&gt;");
         });
    
         it('should update', function() {
           element(by.model('snippet')).clear();
           element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
           expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
             toBe('new <b>text</b>');
           expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
             'new <b onclick="alert(1)">text</b>');
           expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
             "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
         });
       </file>
       </example>
     */


    /**
     * @ngdoc provider
     * @name $sanitizeProvider
     *
     * @description
     * Creates and configures {@link $sanitize} instance.
     */
    function $SanitizeProvider() {
        var svgEnabled = false;

        this.$get = ['$$sanitizeUri', function ($$sanitizeUri) {
            if (svgEnabled) {
                extend(validElements, svgElements);
            }
            return function (html) {
                var buf = [];
                htmlParser(html, htmlSanitizeWriter(buf, function (uri, isImage) {
                    return !/^unsafe:/.test($$sanitizeUri(uri, isImage));
                }));
                return buf.join('');
            };
        }];


        /**
         * @ngdoc method
         * @name $sanitizeProvider#enableSvg
         * @kind function
         *
         * @description
         * Enables a subset of svg to be supported by the sanitizer.
         *
         * <div class="alert alert-warning">
         *   <p>By enabling this setting without taking other precautions, you might expose your
         *   application to click-hijacking attacks. In these attacks, sanitized svg elements could be positioned
         *   outside of the containing element and be rendered over other elements on the page (e.g. a login
         *   link). Such behavior can then result in phishing incidents.</p>
         *
         *   <p>To protect against these, explicitly setup `overflow: hidden` css rule for all potential svg
         *   tags within the sanitized content:</p>
         *
         *   <br>
         *
         *   <pre><code>
         *   .rootOfTheIncludedContent svg {
         *     overflow: hidden !important;
         *   }
         *   </code></pre>
         * </div>
         *
         * @param {boolean=} flag Enable or disable SVG support in the sanitizer.
         * @returns {boolean|ng.$sanitizeProvider} Returns the currently configured value if called
         *    without an argument or self for chaining otherwise.
         */
        this.enableSvg = function (enableSvg) {
            if (isDefined(enableSvg)) {
                svgEnabled = enableSvg;
                return this;
            } else {
                return svgEnabled;
            }
        };

        //////////////////////////////////////////////////////////////////////////////////////////////////
        // Private stuff
        //////////////////////////////////////////////////////////////////////////////////////////////////

        bind = angular.bind;
        extend = angular.extend;
        forEach = angular.forEach;
        isDefined = angular.isDefined;
        lowercase = angular.lowercase;
        noop = angular.noop;

        htmlParser = htmlParserImpl;
        htmlSanitizeWriter = htmlSanitizeWriterImpl;

        // Regular Expressions for parsing tags and attributes
        var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
          // Match everything outside of normal chars and " (quote character)
          NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g;


        // Good source of info about elements and attributes
        // http://dev.w3.org/html5/spec/Overview.html#semantics
        // http://simon.html5.org/html-elements

        // Safe Void Elements - HTML5
        // http://dev.w3.org/html5/spec/Overview.html#void-elements
        var voidElements = toMap("area,br,col,hr,img,wbr");

        // Elements that you can, intentionally, leave open (and which close themselves)
        // http://dev.w3.org/html5/spec/Overview.html#optional-tags
        var optionalEndTagBlockElements = toMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
            optionalEndTagInlineElements = toMap("rp,rt"),
            optionalEndTagElements = extend({},
                                                    optionalEndTagInlineElements,
                                                    optionalEndTagBlockElements);

        // Safe Block Elements - HTML5
        var blockElements = extend({}, optionalEndTagBlockElements, toMap("address,article," +
                "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
                "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul"));

        // Inline Elements - HTML5
        var inlineElements = extend({}, optionalEndTagInlineElements, toMap("a,abbr,acronym,b," +
                "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
                "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));

        // SVG Elements
        // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
        // Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
        // They can potentially allow for arbitrary javascript to be executed. See #11290
        var svgElements = toMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," +
                "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," +
                "radialGradient,rect,stop,svg,switch,text,title,tspan");

        // Blocked Elements (will be stripped)
        var blockedElements = toMap("script,style");

        var validElements = extend({},
                                           voidElements,
                                           blockElements,
                                           inlineElements,
                                           optionalEndTagElements);

        //Attributes that have href and hence need to be sanitized
        var uriAttrs = toMap("background,cite,href,longdesc,src,xlink:href");

        var htmlAttrs = toMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
            'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
            'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
            'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +
            'valign,value,vspace,width');

        // SVG attributes (without "id" and "name" attributes)
        // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
        var svgAttrs = toMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
            'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
            'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
            'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
            'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +
            'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +
            'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +
            'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +
            'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +
            'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +
            'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +
            'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +
            'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +
            'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +
            'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);

        var validAttrs = extend({},
                                        uriAttrs,
                                        svgAttrs,
                                        htmlAttrs);

        function toMap(str, lowercaseKeys) {
            var obj = {}, items = str.split(','), i;
            for (i = 0; i < items.length; i++) {
                obj[lowercaseKeys ? lowercase(items[i]) : items[i]] = true;
            }
            return obj;
        }

        var inertBodyElement;
        (function (window) {
            var doc;
            if (window.document && window.document.implementation) {
                doc = window.document.implementation.createHTMLDocument("inert");
            } else {
                throw $sanitizeMinErr('noinert', "Can't create an inert html document");
            }
            var docElement = doc.documentElement || doc.getDocumentElement();
            var bodyElements = docElement.getElementsByTagName('body');

            // usually there should be only one body element in the document, but IE doesn't have any, so we need to create one
            if (bodyElements.length === 1) {
                inertBodyElement = bodyElements[0];
            } else {
                var html = doc.createElement('html');
                inertBodyElement = doc.createElement('body');
                html.appendChild(inertBodyElement);
                doc.appendChild(html);
            }
        })(window);

        /**
         * @example
         * htmlParser(htmlString, {
         *     start: function(tag, attrs) {},
         *     end: function(tag) {},
         *     chars: function(text) {},
         *     comment: function(text) {}
         * });
         *
         * @param {string} html string
         * @param {object} handler
         */
        function htmlParserImpl(html, handler) {
            if (html === null || html === undefined) {
                html = '';
            } else if (typeof html !== 'string') {
                html = '' + html;
            }
            inertBodyElement.innerHTML = html;

            //mXSS protection
            var mXSSAttempts = 5;
            do {
                if (mXSSAttempts === 0) {
                    throw $sanitizeMinErr('uinput', "Failed to sanitize html because the input is unstable");
                }
                mXSSAttempts--;

                // strip custom-namespaced attributes on IE<=11
                if (window.document.documentMode) {
                    stripCustomNsAttrs(inertBodyElement);
                }
                html = inertBodyElement.innerHTML; //trigger mXSS
                inertBodyElement.innerHTML = html;
            } while (html !== inertBodyElement.innerHTML);

            var node = inertBodyElement.firstChild;
            while (node) {
                switch (node.nodeType) {
                    case 1: // ELEMENT_NODE
                        handler.start(node.nodeName.toLowerCase(), attrToMap(node.attributes));
                        break;
                    case 3: // TEXT NODE
                        handler.chars(node.textContent);
                        break;
                }

                var nextNode;
                if (!(nextNode = node.firstChild)) {
                    if (node.nodeType == 1) {
                        handler.end(node.nodeName.toLowerCase());
                    }
                    nextNode = node.nextSibling;
                    if (!nextNode) {
                        while (nextNode == null) {
                            node = node.parentNode;
                            if (node === inertBodyElement) break;
                            nextNode = node.nextSibling;
                            if (node.nodeType == 1) {
                                handler.end(node.nodeName.toLowerCase());
                            }
                        }
                    }
                }
                node = nextNode;
            }

            while (node = inertBodyElement.firstChild) {
                inertBodyElement.removeChild(node);
            }
        }

        function attrToMap(attrs) {
            var map = {};
            for (var i = 0, ii = attrs.length; i < ii; i++) {
                var attr = attrs[i];
                map[attr.name] = attr.value;
            }
            return map;
        }


        /**
         * Escapes all potentially dangerous characters, so that the
         * resulting string can be safely inserted into attribute or
         * element text.
         * @param value
         * @returns {string} escaped text
         */
        function encodeEntities(value) {
            return value.
              replace(/&/g, '&amp;').
              replace(SURROGATE_PAIR_REGEXP, function (value) {
                  var hi = value.charCodeAt(0);
                  var low = value.charCodeAt(1);
                  return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
              }).
              replace(NON_ALPHANUMERIC_REGEXP, function (value) {
                  return '&#' + value.charCodeAt(0) + ';';
              }).
              replace(/</g, '&lt;').
              replace(/>/g, '&gt;');
        }

        /**
         * create an HTML/XML writer which writes to buffer
         * @param {Array} buf use buf.join('') to get out sanitized html string
         * @returns {object} in the form of {
         *     start: function(tag, attrs) {},
         *     end: function(tag) {},
         *     chars: function(text) {},
         *     comment: function(text) {}
         * }
         */
        function htmlSanitizeWriterImpl(buf, uriValidator) {
            var ignoreCurrentElement = false;
            var out = bind(buf, buf.push);
            return {
                start: function (tag, attrs) {
                    tag = lowercase(tag);
                    if (!ignoreCurrentElement && blockedElements[tag]) {
                        ignoreCurrentElement = tag;
                    }
                    if (!ignoreCurrentElement && validElements[tag] === true) {
                        out('<');
                        out(tag);
                        forEach(attrs, function (value, key) {
                            var lkey = lowercase(key);
                            var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
                            if (validAttrs[lkey] === true &&
                              (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
                                out(' ');
                                out(key);
                                out('="');
                                out(encodeEntities(value));
                                out('"');
                            }
                        });
                        out('>');
                    }
                },
                end: function (tag) {
                    tag = lowercase(tag);
                    if (!ignoreCurrentElement && validElements[tag] === true && voidElements[tag] !== true) {
                        out('</');
                        out(tag);
                        out('>');
                    }
                    if (tag == ignoreCurrentElement) {
                        ignoreCurrentElement = false;
                    }
                },
                chars: function (chars) {
                    if (!ignoreCurrentElement) {
                        out(encodeEntities(chars));
                    }
                }
            };
        }


        /**
         * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1' attribute to declare
         * ns1 namespace and prefixes the attribute with 'ns1' (e.g. 'ns1:xlink:foo'). This is undesirable since we don't want
         * to allow any of these custom attributes. This method strips them all.
         *
         * @param node Root element to process
         */
        function stripCustomNsAttrs(node) {
            if (node.nodeType === window.Node.ELEMENT_NODE) {
                var attrs = node.attributes;
                for (var i = 0, l = attrs.length; i < l; i++) {
                    var attrNode = attrs[i];
                    var attrName = attrNode.name.toLowerCase();
                    if (attrName === 'xmlns:ns1' || attrName.lastIndexOf('ns1:', 0) === 0) {
                        node.removeAttributeNode(attrNode);
                        i--;
                        l--;
                    }
                }
            }

            var nextNode = node.firstChild;
            if (nextNode) {
                stripCustomNsAttrs(nextNode);
            }

            nextNode = node.nextSibling;
            if (nextNode) {
                stripCustomNsAttrs(nextNode);
            }
        }
    }

    function sanitizeText(chars) {
        var buf = [];
        var writer = htmlSanitizeWriter(buf, noop);
        writer.chars(chars);
        return buf.join('');
    }


    // define ngSanitize module and register $sanitize service
    angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);

    /**
     * @ngdoc filter
     * @name linky
     * @kind function
     *
     * @description
     * Finds links in text input and turns them into html links. Supports `http/https/ftp/mailto` and
     * plain email address links.
     *
     * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
     *
     * @param {string} text Input text.
     * @param {string} target Window (`_blank|_self|_parent|_top`) or named frame to open links in.
     * @param {object|function(url)} [attributes] Add custom attributes to the link element.
     *
     *    Can be one of:
     *
     *    - `object`: A map of attributes
     *    - `function`: Takes the url as a parameter and returns a map of attributes
     *
     *    If the map of attributes contains a value for `target`, it overrides the value of
     *    the target parameter.
     *
     *
     * @returns {string} Html-linkified and {@link $sanitize sanitized} text.
     *
     * @usage
       <span ng-bind-html="linky_expression | linky"></span>
     *
     * @example
       <example module="linkyExample" deps="angular-sanitize.js">
         <file name="index.html">
           <div ng-controller="ExampleController">
           Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
           <table>
             <tr>
               <th>Filter</th>
               <th>Source</th>
               <th>Rendered</th>
             </tr>
             <tr id="linky-filter">
               <td>linky filter</td>
               <td>
                 <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
               </td>
               <td>
                 <div ng-bind-html="snippet | linky"></div>
               </td>
             </tr>
             <tr id="linky-target">
              <td>linky target</td>
              <td>
                <pre>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
              </td>
              <td>
                <div ng-bind-html="snippetWithSingleURL | linky:'_blank'"></div>
              </td>
             </tr>
             <tr id="linky-custom-attributes">
              <td>linky custom attributes</td>
              <td>
                <pre>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}"&gt;<br>&lt;/div&gt;</pre>
              </td>
              <td>
                <div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}"></div>
              </td>
             </tr>
             <tr id="escaped-html">
               <td>no filter</td>
               <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
               <td><div ng-bind="snippet"></div></td>
             </tr>
           </table>
         </file>
         <file name="script.js">
           angular.module('linkyExample', ['ngSanitize'])
             .controller('ExampleController', ['$scope', function($scope) {
               $scope.snippet =
                 'Pretty text with some links:\n'+
                 'http://angularjs.org/,\n'+
                 'mailto:us@somewhere.org,\n'+
                 'another@somewhere.org,\n'+
                 'and one more: ftp://127.0.0.1/.';
               $scope.snippetWithSingleURL = 'http://angularjs.org/';
             }]);
         </file>
         <file name="protractor.js" type="protractor">
           it('should linkify the snippet with urls', function() {
             expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
                 toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +
                      'another@somewhere.org, and one more: ftp://127.0.0.1/.');
             expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
           });
    
           it('should not linkify snippet without the linky filter', function() {
             expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
                 toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +
                      'another@somewhere.org, and one more: ftp://127.0.0.1/.');
             expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
           });
    
           it('should update', function() {
             element(by.model('snippet')).clear();
             element(by.model('snippet')).sendKeys('new http://link.');
             expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
                 toBe('new http://link.');
             expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
             expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
                 .toBe('new http://link.');
           });
    
           it('should work with the target property', function() {
            expect(element(by.id('linky-target')).
                element(by.binding("snippetWithSingleURL | linky:'_blank'")).getText()).
                toBe('http://angularjs.org/');
            expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
           });
    
           it('should optionally add custom attributes', function() {
            expect(element(by.id('linky-custom-attributes')).
                element(by.binding("snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}")).getText()).
                toBe('http://angularjs.org/');
            expect(element(by.css('#linky-custom-attributes a')).getAttribute('rel')).toEqual('nofollow');
           });
         </file>
       </example>
     */
    angular.module('ngSanitize').filter('linky', ['$sanitize', function ($sanitize) {
        var LINKY_URL_REGEXP =
              /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
            MAILTO_REGEXP = /^mailto:/i;

        var linkyMinErr = angular.$$minErr('linky');
        var isDefined = angular.isDefined;
        var isFunction = angular.isFunction;
        var isObject = angular.isObject;
        var isString = angular.isString;

        return function (text, target, attributes) {
            if (text == null || text === '') return text;
            if (!isString(text)) throw linkyMinErr('notstring', 'Expected string but received: {0}', text);

            var attributesFn =
              isFunction(attributes) ? attributes :
              isObject(attributes) ? function getAttributesObject() { return attributes; } :
              function getEmptyAttributesObject() { return {}; };

            var match;
            var raw = text;
            var html = [];
            var url;
            var i;
            while ((match = raw.match(LINKY_URL_REGEXP))) {
                // We can not end in these as they are sometimes found at the end of the sentence
                url = match[0];
                // if we did not match ftp/http/www/mailto then assume mailto
                if (!match[2] && !match[4]) {
                    url = (match[3] ? 'http://' : 'mailto:') + url;
                }
                i = match.index;
                addText(raw.substr(0, i));
                addLink(url, match[0].replace(MAILTO_REGEXP, ''));
                raw = raw.substring(i + match[0].length);
            }
            addText(raw);
            return $sanitize(html.join(''));

            function addText(text) {
                if (!text) {
                    return;
                }
                html.push(sanitizeText(text));
            }

            function addLink(url, text) {
                var key, linkAttributes = attributesFn(url);
                html.push('<a ');

                for (key in linkAttributes) {
                    html.push(key + '="' + linkAttributes[key] + '" ');
                }

                if (isDefined(target) && !('target' in linkAttributes)) {
                    html.push('target="',
                              target,
                              '" ');
                }
                html.push('href="',
                          url.replace(/"/g, '&quot;'),
                          '">');
                addText(text);
                html.push('</a>');
            }
        };
    }]);


})(window, window.angular);;
/*
 AngularJS v1.5.8
 (c) 2010-2016 Google, Inc. http://angularjs.org
 License: MIT
*/
(function (R, B) {
    'use strict'; function Da(a, b, c) { if (!a) throw Ma("areq", b || "?", c || "required"); return a } function Ea(a, b) { if (!a && !b) return ""; if (!a) return b; if (!b) return a; Y(a) && (a = a.join(" ")); Y(b) && (b = b.join(" ")); return a + " " + b } function Na(a) { var b = {}; a && (a.to || a.from) && (b.to = a.to, b.from = a.from); return b } function Z(a, b, c) { var d = ""; a = Y(a) ? a : a && G(a) && a.length ? a.split(/\s+/) : []; s(a, function (a, l) { a && 0 < a.length && (d += 0 < l ? " " : "", d += c ? b + a : a + b) }); return d } function Oa(a) {
        if (a instanceof F) switch (a.length) {
            case 0: return a;
            case 1: if (1 === a[0].nodeType) return a; break; default: return F(ta(a))
        } if (1 === a.nodeType) return F(a)
    } function ta(a) { if (!a[0]) return a; for (var b = 0; b < a.length; b++) { var c = a[b]; if (1 == c.nodeType) return c } } function Pa(a, b, c) { s(b, function (b) { a.addClass(b, c) }) } function Qa(a, b, c) { s(b, function (b) { a.removeClass(b, c) }) } function V(a) { return function (b, c) { c.addClass && (Pa(a, b, c.addClass), c.addClass = null); c.removeClass && (Qa(a, b, c.removeClass), c.removeClass = null) } } function oa(a) {
        a = a || {}; if (!a.$$prepared) {
            var b = a.domOperation ||
            P; a.domOperation = function () { a.$$domOperationFired = !0; b(); b = P }; a.$$prepared = !0
        } return a
    } function ha(a, b) { Fa(a, b); Ga(a, b) } function Fa(a, b) { b.from && (a.css(b.from), b.from = null) } function Ga(a, b) { b.to && (a.css(b.to), b.to = null) } function W(a, b, c) {
        var d = b.options || {}; c = c.options || {}; var e = (d.addClass || "") + " " + (c.addClass || ""), l = (d.removeClass || "") + " " + (c.removeClass || ""); a = Ra(a.attr("class"), e, l); c.preparationClasses && (d.preparationClasses = $(c.preparationClasses, d.preparationClasses), delete c.preparationClasses);
        e = d.domOperation !== P ? d.domOperation : null; ua(d, c); e && (d.domOperation = e); d.addClass = a.addClass ? a.addClass : null; d.removeClass = a.removeClass ? a.removeClass : null; b.addClass = d.addClass; b.removeClass = d.removeClass; return d
    } function Ra(a, b, c) {
        function d(a) { G(a) && (a = a.split(" ")); var b = {}; s(a, function (a) { a.length && (b[a] = !0) }); return b } var e = {}; a = d(a); b = d(b); s(b, function (a, b) { e[b] = 1 }); c = d(c); s(c, function (a, b) { e[b] = 1 === e[b] ? null : -1 }); var l = { addClass: "", removeClass: "" }; s(e, function (b, c) {
            var d, e; 1 === b ? (d = "addClass",
            e = !a[c] || a[c + "-remove"]) : -1 === b && (d = "removeClass", e = a[c] || a[c + "-add"]); e && (l[d].length && (l[d] += " "), l[d] += c)
        }); return l
    } function y(a) { return a instanceof F ? a[0] : a } function Sa(a, b, c) { var d = ""; b && (d = Z(b, "ng-", !0)); c.addClass && (d = $(d, Z(c.addClass, "-add"))); c.removeClass && (d = $(d, Z(c.removeClass, "-remove"))); d.length && (c.preparationClasses = d, a.addClass(d)) } function pa(a, b) { var c = b ? "-" + b + "s" : ""; la(a, [ma, c]); return [ma, c] } function va(a, b) { var c = b ? "paused" : "", d = aa + "PlayState"; la(a, [d, c]); return [d, c] } function la(a,
    b) { a.style[b[0]] = b[1] } function $(a, b) { return a ? b ? a + " " + b : a : b } function Ha(a, b, c) { var d = Object.create(null), e = a.getComputedStyle(b) || {}; s(c, function (a, b) { var c = e[a]; if (c) { var g = c.charAt(0); if ("-" === g || "+" === g || 0 <= g) c = Ta(c); 0 === c && (c = null); d[b] = c } }); return d } function Ta(a) { var b = 0; a = a.split(/\s*,\s*/); s(a, function (a) { "s" == a.charAt(a.length - 1) && (a = a.substring(0, a.length - 1)); a = parseFloat(a) || 0; b = b ? Math.max(a, b) : a }); return b } function wa(a) { return 0 === a || null != a } function Ia(a, b) {
        var c = S, d = a + "s"; b ? c += "Duration" :
        d += " linear all"; return [c, d]
    } function Ja() { var a = Object.create(null); return { flush: function () { a = Object.create(null) }, count: function (b) { return (b = a[b]) ? b.total : 0 }, get: function (b) { return (b = a[b]) && b.value }, put: function (b, c) { a[b] ? a[b].total++ : a[b] = { total: 1, value: c } } } } function Ka(a, b, c) { s(c, function (c) { a[c] = xa(a[c]) ? a[c] : b.style.getPropertyValue(c) }) } var S, ya, aa, za; void 0 === R.ontransitionend && void 0 !== R.onwebkittransitionend ? (S = "WebkitTransition", ya = "webkitTransitionEnd transitionend") : (S = "transition", ya =
    "transitionend"); void 0 === R.onanimationend && void 0 !== R.onwebkitanimationend ? (aa = "WebkitAnimation", za = "webkitAnimationEnd animationend") : (aa = "animation", za = "animationend"); var qa = aa + "Delay", Aa = aa + "Duration", ma = S + "Delay", La = S + "Duration", Ma = B.$$minErr("ng"), Ua = { transitionDuration: La, transitionDelay: ma, transitionProperty: S + "Property", animationDuration: Aa, animationDelay: qa, animationIterationCount: aa + "IterationCount" }, Va = { transitionDuration: La, transitionDelay: ma, animationDuration: Aa, animationDelay: qa },
    Ba, ua, s, Y, xa, ea, Ca, ba, G, J, F, P; B.module("ngAnimate", [], function () { P = B.noop; Ba = B.copy; ua = B.extend; F = B.element; s = B.forEach; Y = B.isArray; G = B.isString; ba = B.isObject; J = B.isUndefined; xa = B.isDefined; Ca = B.isFunction; ea = B.isElement }).directive("ngAnimateSwap", ["$animate", "$rootScope", function (a, b) {
        return {
            restrict: "A", transclude: "element", terminal: !0, priority: 600, link: function (b, d, e, l, n) {
                var I, g; b.$watchCollection(e.ngAnimateSwap || e["for"], function (e) {
                    I && a.leave(I); g && (g.$destroy(), g = null); if (e || 0 === e) g = b.$new(),
                    n(g, function (b) { I = b; a.enter(b, null, d) })
                })
            }
        }
    }]).directive("ngAnimateChildren", ["$interpolate", function (a) { return { link: function (b, c, d) { function e(a) { c.data("$$ngAnimateChildren", "on" === a || "true" === a) } var l = d.ngAnimateChildren; G(l) && 0 === l.length ? c.data("$$ngAnimateChildren", !0) : (e(a(l)(b)), d.$observe("ngAnimateChildren", e)) } } }]).factory("$$rAFScheduler", ["$$rAF", function (a) {
        function b(a) { d = d.concat(a); c() } function c() { if (d.length) { for (var b = d.shift(), n = 0; n < b.length; n++) b[n](); e || a(function () { e || c() }) } }
        var d, e; d = b.queue = []; b.waitUntilQuiet = function (b) { e && e(); e = a(function () { e = null; b(); c() }) }; return b
    }]).provider("$$animateQueue", ["$animateProvider", function (a) {
        function b(a) { if (!a) return null; a = a.split(" "); var b = Object.create(null); s(a, function (a) { b[a] = !0 }); return b } function c(a, c) { if (a && c) { var d = b(c); return a.split(" ").some(function (a) { return d[a] }) } } function d(a, b, c, d) { return l[a].some(function (a) { return a(b, c, d) }) } function e(a, b) {
            var c = 0 < (a.addClass || "").length, d = 0 < (a.removeClass || "").length;
            return b ? c && d : c || d
        } var l = this.rules = { skip: [], cancel: [], join: [] }; l.join.push(function (a, b, c) { return !b.structural && e(b) }); l.skip.push(function (a, b, c) { return !b.structural && !e(b) }); l.skip.push(function (a, b, c) { return "leave" == c.event && b.structural }); l.skip.push(function (a, b, c) { return c.structural && 2 === c.state && !b.structural }); l.cancel.push(function (a, b, c) { return c.structural && b.structural }); l.cancel.push(function (a, b, c) { return 2 === c.state && b.structural }); l.cancel.push(function (a, b, d) {
            if (d.structural) return !1;
            a = b.addClass; b = b.removeClass; var e = d.addClass; d = d.removeClass; return J(a) && J(b) || J(e) && J(d) ? !1 : c(a, d) || c(b, e)
        }); this.$get = ["$$rAF", "$rootScope", "$rootElement", "$document", "$$HashMap", "$$animation", "$$AnimateRunner", "$templateRequest", "$$jqLite", "$$forceReflow", function (b, c, g, l, C, Wa, Q, t, H, T) {
            function O() { var a = !1; return function (b) { a ? b() : c.$$postDigest(function () { a = !0; b() }) } } function x(a, b, c) {
                var f = y(b), d = y(a), N = []; (a = h[c]) && s(a, function (a) {
                    w.call(a.node, f) ? N.push(a.callback) : "leave" === c && w.call(a.node,
                    d) && N.push(a.callback)
                }); return N
            } function r(a, b, c) { var f = ta(b); return a.filter(function (a) { return !(a.node === f && (!c || a.callback === c)) }) } function p(a, h, v) {
                function r(c, f, d, h) { sa(function () { var c = x(T, a, f); c.length ? b(function () { s(c, function (b) { b(a, d, h) }); "close" !== d || a[0].parentNode || ra.off(a) }) : "close" !== d || a[0].parentNode || ra.off(a) }); c.progress(f, d, h) } function k(b) {
                    var c = a, f = m; f.preparationClasses && (c.removeClass(f.preparationClasses), f.preparationClasses = null); f.activeClasses && (c.removeClass(f.activeClasses),
                    f.activeClasses = null); E(a, m); ha(a, m); m.domOperation(); A.complete(!b)
                } var m = Ba(v), p, T; if (a = Oa(a)) p = y(a), T = a.parent(); var m = oa(m), A = new Q, sa = O(); Y(m.addClass) && (m.addClass = m.addClass.join(" ")); m.addClass && !G(m.addClass) && (m.addClass = null); Y(m.removeClass) && (m.removeClass = m.removeClass.join(" ")); m.removeClass && !G(m.removeClass) && (m.removeClass = null); m.from && !ba(m.from) && (m.from = null); m.to && !ba(m.to) && (m.to = null); if (!p) return k(), A; v = [p.className, m.addClass, m.removeClass].join(" "); if (!Xa(v)) return k(),
                A; var g = 0 <= ["enter", "move", "leave"].indexOf(h), w = l[0].hidden, t = !f || w || N.get(p); v = !t && z.get(p) || {}; var H = !!v.state; t || H && 1 == v.state || (t = !M(a, T, h)); if (t) return w && r(A, h, "start"), k(), w && r(A, h, "close"), A; g && K(a); w = { structural: g, element: a, event: h, addClass: m.addClass, removeClass: m.removeClass, close: k, options: m, runner: A }; if (H) {
                    if (d("skip", a, w, v)) { if (2 === v.state) return k(), A; W(a, v, w); return v.runner } if (d("cancel", a, w, v)) if (2 === v.state) v.runner.end(); else if (v.structural) v.close(); else return W(a, v, w), v.runner;
                    else if (d("join", a, w, v)) if (2 === v.state) W(a, w, {}); else return Sa(a, g ? h : null, m), h = w.event = v.event, m = W(a, v, w), v.runner
                } else W(a, w, {}); (H = w.structural) || (H = "animate" === w.event && 0 < Object.keys(w.options.to || {}).length || e(w)); if (!H) return k(), ka(a), A; var C = (v.counter || 0) + 1; w.counter = C; L(a, 1, w); c.$$postDigest(function () {
                    var b = z.get(p), c = !b, b = b || {}, f = 0 < (a.parent() || []).length && ("animate" === b.event || b.structural || e(b)); if (c || b.counter !== C || !f) {
                        c && (E(a, m), ha(a, m)); if (c || g && b.event !== h) m.domOperation(), A.end();
                        f || ka(a)
                    } else h = !b.structural && e(b, !0) ? "setClass" : b.event, L(a, 2), b = Wa(a, h, b.options), A.setHost(b), r(A, h, "start", {}), b.done(function (b) { k(!b); (b = z.get(p)) && b.counter === C && ka(y(a)); r(A, h, "close", {}) })
                }); return A
            } function K(a) { a = y(a).querySelectorAll("[data-ng-animate]"); s(a, function (a) { var b = parseInt(a.getAttribute("data-ng-animate")), c = z.get(a); if (c) switch (b) { case 2: c.runner.end(); case 1: z.remove(a) } }) } function ka(a) { a = y(a); a.removeAttribute("data-ng-animate"); z.remove(a) } function k(a, b) {
                return y(a) ===
                y(b)
            } function M(a, b, c) {
                c = F(l[0].body); var f = k(a, c) || "HTML" === a[0].nodeName, d = k(a, g), h = !1, r, e = N.get(y(a)); (a = F.data(a[0], "$ngAnimatePin")) && (b = a); for (b = y(b) ; b;) { d || (d = k(b, g)); if (1 !== b.nodeType) break; a = z.get(b) || {}; if (!h) { var p = N.get(b); if (!0 === p && !1 !== e) { e = !0; break } else !1 === p && (e = !1); h = a.structural } if (J(r) || !0 === r) a = F.data(b, "$$ngAnimateChildren"), xa(a) && (r = a); if (h && !1 === r) break; f || (f = k(b, c)); if (f && d) break; if (!d && (a = F.data(b, "$ngAnimatePin"))) { b = y(a); continue } b = b.parentNode } return (!h || r) && !0 !== e &&
                d && f
            } function L(a, b, c) { c = c || {}; c.state = b; a = y(a); a.setAttribute("data-ng-animate", b); c = (b = z.get(a)) ? ua(b, c) : c; z.put(a, c) } var z = new C, N = new C, f = null, A = c.$watch(function () { return 0 === t.totalPendingRequests }, function (a) { a && (A(), c.$$postDigest(function () { c.$$postDigest(function () { null === f && (f = !0) }) })) }), h = Object.create(null), sa = a.classNameFilter(), Xa = sa ? function (a) { return sa.test(a) } : function () { return !0 }, E = V(H), w = R.Node.prototype.contains || function (a) {
                return this === a || !!(this.compareDocumentPosition(a) &
                16)
            }, ra = {
                on: function (a, b, c) { var f = ta(b); h[a] = h[a] || []; h[a].push({ node: f, callback: c }); F(b).on("$destroy", function () { z.get(f) || ra.off(a, b, c) }) }, off: function (a, b, c) { if (1 !== arguments.length || G(arguments[0])) { var f = h[a]; f && (h[a] = 1 === arguments.length ? null : r(f, b, c)) } else for (f in b = arguments[0], h) h[f] = r(h[f], b) }, pin: function (a, b) { Da(ea(a), "element", "not an element"); Da(ea(b), "parentElement", "not an element"); a.data("$ngAnimatePin", b) }, push: function (a, b, c, f) { c = c || {}; c.domOperation = f; return p(a, b, c) }, enabled: function (a,
                b) { var c = arguments.length; if (0 === c) b = !!f; else if (ea(a)) { var d = y(a); 1 === c ? b = !N.get(d) : N.put(d, !b) } else b = f = !!a; return b }
            }; return ra
        }]
    }]).provider("$$animation", ["$animateProvider", function (a) {
        var b = this.drivers = []; this.$get = ["$$jqLite", "$rootScope", "$injector", "$$AnimateRunner", "$$HashMap", "$$rAFScheduler", function (a, d, e, l, n, I) {
            function g(a) {
                function b(a) {
                    if (a.processed) return a; a.processed = !0; var d = a.domNode, p = d.parentNode; e.put(d, a); for (var K; p;) { if (K = e.get(p)) { K.processed || (K = b(K)); break } p = p.parentNode } (K ||
                    c).children.push(a); return a
                } var c = { children: [] }, d, e = new n; for (d = 0; d < a.length; d++) { var g = a[d]; e.put(g.domNode, a[d] = { domNode: g.domNode, fn: g.fn, children: [] }) } for (d = 0; d < a.length; d++) b(a[d]); return function (a) { var b = [], c = [], d; for (d = 0; d < a.children.length; d++) c.push(a.children[d]); a = c.length; var e = 0, k = []; for (d = 0; d < c.length; d++) { var g = c[d]; 0 >= a && (a = e, e = 0, b.push(k), k = []); k.push(g.fn); g.children.forEach(function (a) { e++; c.push(a) }); a-- } k.length && b.push(k); return b }(c)
            } var u = [], C = V(a); return function (n, Q, t) {
                function H(a) {
                    a =
                    a.hasAttribute("ng-animate-ref") ? [a] : a.querySelectorAll("[ng-animate-ref]"); var b = []; s(a, function (a) { var c = a.getAttribute("ng-animate-ref"); c && c.length && b.push(a) }); return b
                } function T(a) {
                    var b = [], c = {}; s(a, function (a, d) { var h = y(a.element), e = 0 <= ["enter", "move"].indexOf(a.event), h = a.structural ? H(h) : []; if (h.length) { var k = e ? "to" : "from"; s(h, function (a) { var b = a.getAttribute("ng-animate-ref"); c[b] = c[b] || {}; c[b][k] = { animationID: d, element: F(a) } }) } else b.push(a) }); var d = {}, e = {}; s(c, function (c, k) {
                        var r = c.from,
                        p = c.to; if (r && p) { var z = a[r.animationID], g = a[p.animationID], A = r.animationID.toString(); if (!e[A]) { var n = e[A] = { structural: !0, beforeStart: function () { z.beforeStart(); g.beforeStart() }, close: function () { z.close(); g.close() }, classes: O(z.classes, g.classes), from: z, to: g, anchors: [] }; n.classes.length ? b.push(n) : (b.push(z), b.push(g)) } e[A].anchors.push({ out: r.element, "in": p.element }) } else r = r ? r.animationID : p.animationID, p = r.toString(), d[p] || (d[p] = !0, b.push(a[r]))
                    }); return b
                } function O(a, b) {
                    a = a.split(" "); b = b.split(" ");
                    for (var c = [], d = 0; d < a.length; d++) { var e = a[d]; if ("ng-" !== e.substring(0, 3)) for (var r = 0; r < b.length; r++) if (e === b[r]) { c.push(e); break } } return c.join(" ")
                } function x(a) { for (var c = b.length - 1; 0 <= c; c--) { var d = e.get(b[c])(a); if (d) return d } } function r(a, b) { function c(a) { (a = a.data("$$animationRunner")) && a.setHost(b) } a.from && a.to ? (c(a.from.element), c(a.to.element)) : c(a.element) } function p() { var a = n.data("$$animationRunner"); !a || "leave" === Q && t.$$domOperationFired || a.end() } function K(b) {
                    n.off("$destroy", p); n.removeData("$$animationRunner");
                    C(n, t); ha(n, t); t.domOperation(); L && a.removeClass(n, L); n.removeClass("ng-animate"); k.complete(!b)
                } t = oa(t); var ka = 0 <= ["enter", "move", "leave"].indexOf(Q), k = new l({ end: function () { K() }, cancel: function () { K(!0) } }); if (!b.length) return K(), k; n.data("$$animationRunner", k); var M = Ea(n.attr("class"), Ea(t.addClass, t.removeClass)), L = t.tempClasses; L && (M += " " + L, t.tempClasses = null); var z; ka && (z = "ng-" + Q + "-prepare", a.addClass(n, z)); u.push({
                    element: n, classes: M, event: Q, structural: ka, options: t, beforeStart: function () {
                        n.addClass("ng-animate");
                        L && a.addClass(n, L); z && (a.removeClass(n, z), z = null)
                    }, close: K
                }); n.on("$destroy", p); if (1 < u.length) return k; d.$$postDigest(function () {
                    var a = []; s(u, function (b) { b.element.data("$$animationRunner") ? a.push(b) : b.close() }); u.length = 0; var b = T(a), c = []; s(b, function (a) {
                        c.push({
                            domNode: y(a.from ? a.from.element : a.element), fn: function () {
                                a.beforeStart(); var b, c = a.close; if ((a.anchors ? a.from.element || a.to.element : a.element).data("$$animationRunner")) { var d = x(a); d && (b = d.start) } b ? (b = b(), b.done(function (a) { c(!a) }), r(a, b)) :
                                c()
                            }
                        })
                    }); I(g(c))
                }); return k
            }
        }]
    }]).provider("$animateCss", ["$animateProvider", function (a) {
        var b = Ja(), c = Ja(); this.$get = ["$window", "$$jqLite", "$$AnimateRunner", "$timeout", "$$forceReflow", "$sniffer", "$$rAFScheduler", "$$animateQueue", function (a, e, l, n, I, g, u, C) {
            function B(a, b) { var c = a.parentNode; return (c.$$ngAnimateParentKey || (c.$$ngAnimateParentKey = ++O)) + "-" + a.getAttribute("class") + "-" + b } function Q(r, p, g, n) {
                var k; 0 < b.count(g) && (k = c.get(g), k || (p = Z(p, "-stagger"), e.addClass(r, p), k = Ha(a, r, n), k.animationDuration =
                Math.max(k.animationDuration, 0), k.transitionDuration = Math.max(k.transitionDuration, 0), e.removeClass(r, p), c.put(g, k))); return k || {}
            } function t(a) { x.push(a); u.waitUntilQuiet(function () { b.flush(); c.flush(); for (var a = I(), d = 0; d < x.length; d++) x[d](a); x.length = 0 }) } function H(c, e, g) {
                e = b.get(g); e || (e = Ha(a, c, Ua), "infinite" === e.animationIterationCount && (e.animationIterationCount = 1)); b.put(g, e); c = e; g = c.animationDelay; e = c.transitionDelay; c.maxDelay = g && e ? Math.max(g, e) : g || e; c.maxDuration = Math.max(c.animationDuration *
                c.animationIterationCount, c.transitionDuration); return c
            } var T = V(e), O = 0, x = []; return function (a, c) {
                function d() { k() } function u() { k(!0) } function k(b) {
                    if (!(w || F && O)) {
                        w = !0; O = !1; f.$$skipPreparationClasses || e.removeClass(a, ga); e.removeClass(a, ea); va(h, !1); pa(h, !1); s(x, function (a) { h.style[a[0]] = "" }); T(a, f); ha(a, f); Object.keys(A).length && s(A, function (a, b) { a ? h.style.setProperty(b, a) : h.style.removeProperty(b) }); if (f.onDone) f.onDone(); fa && fa.length && a.off(fa.join(" "), z); var c = a.data("$$animateCss"); c && (n.cancel(c[0].timer),
                        a.removeData("$$animateCss")); G && G.complete(!b)
                    }
                } function M(a) { q.blockTransition && pa(h, a); q.blockKeyframeAnimation && va(h, !!a) } function L() { G = new l({ end: d, cancel: u }); t(P); k(); return { $$willAnimate: !1, start: function () { return G }, end: d } } function z(a) { a.stopPropagation(); var b = a.originalEvent || a; a = b.$manualTimeStamp || Date.now(); b = parseFloat(b.elapsedTime.toFixed(3)); Math.max(a - W, 0) >= R && b >= m && (F = !0, k()) } function N() {
                    function b() {
                        if (!w) {
                            M(!1); s(x, function (a) { h.style[a[0]] = a[1] }); T(a, f); e.addClass(a, ea); if (q.recalculateTimingStyles) {
                                na =
                                h.className + " " + ga; ia = B(h, na); D = H(h, na, ia); ca = D.maxDelay; J = Math.max(ca, 0); m = D.maxDuration; if (0 === m) { k(); return } q.hasTransitions = 0 < D.transitionDuration; q.hasAnimations = 0 < D.animationDuration
                            } q.applyAnimationDelay && (ca = "boolean" !== typeof f.delay && wa(f.delay) ? parseFloat(f.delay) : ca, J = Math.max(ca, 0), D.animationDelay = ca, da = [qa, ca + "s"], x.push(da), h.style[da[0]] = da[1]); R = 1E3 * J; V = 1E3 * m; if (f.easing) {
                                var d, g = f.easing; q.hasTransitions && (d = S + "TimingFunction", x.push([d, g]), h.style[d] = g); q.hasAnimations && (d = aa +
                                "TimingFunction", x.push([d, g]), h.style[d] = g)
                            } D.transitionDuration && fa.push(ya); D.animationDuration && fa.push(za); W = Date.now(); var p = R + 1.5 * V; d = W + p; var g = a.data("$$animateCss") || [], N = !0; if (g.length) { var l = g[0]; (N = d > l.expectedEndTime) ? n.cancel(l.timer) : g.push(k) } N && (p = n(c, p, !1), g[0] = { timer: p, expectedEndTime: d }, g.push(k), a.data("$$animateCss", g)); if (fa.length) a.on(fa.join(" "), z); f.to && (f.cleanupStyles && Ka(A, h, Object.keys(f.to)), Ga(a, f))
                        }
                    } function c() {
                        var b = a.data("$$animateCss"); if (b) {
                            for (var d = 1; d < b.length; d++) b[d]();
                            a.removeData("$$animateCss")
                        }
                    } if (!w) if (h.parentNode) { var d = function (a) { if (F) O && a && (O = !1, k()); else if (O = !a, D.animationDuration) if (a = va(h, O), O) x.push(a); else { var b = x, c = b.indexOf(a); 0 <= a && b.splice(c, 1) } }, g = 0 < ba && (D.transitionDuration && 0 === X.transitionDuration || D.animationDuration && 0 === X.animationDuration) && Math.max(X.animationDelay, X.transitionDelay); g ? n(b, Math.floor(g * ba * 1E3), !1) : b(); v.resume = function () { d(!0) }; v.pause = function () { d(!1) } } else k()
                } var f = c || {}; f.$$prepared || (f = oa(Ba(f))); var A = {}, h = y(a);
                if (!h || !h.parentNode || !C.enabled()) return L(); var x = [], I = a.attr("class"), E = Na(f), w, O, F, G, v, J, R, m, V, W, fa = []; if (0 === f.duration || !g.animations && !g.transitions) return L(); var ja = f.event && Y(f.event) ? f.event.join(" ") : f.event, $ = "", U = ""; ja && f.structural ? $ = Z(ja, "ng-", !0) : ja && ($ = ja); f.addClass && (U += Z(f.addClass, "-add")); f.removeClass && (U.length && (U += " "), U += Z(f.removeClass, "-remove")); f.applyClassesEarly && U.length && T(a, f); var ga = [$, U].join(" ").trim(), na = I + " " + ga, ea = Z(ga, "-active"), I = E.to && 0 < Object.keys(E.to).length;
                if (!(0 < (f.keyframeStyle || "").length || I || ga)) return L(); var ia, X; 0 < f.stagger ? (E = parseFloat(f.stagger), X = { transitionDelay: E, animationDelay: E, transitionDuration: 0, animationDuration: 0 }) : (ia = B(h, na), X = Q(h, ga, ia, Va)); f.$$skipPreparationClasses || e.addClass(a, ga); f.transitionStyle && (E = [S, f.transitionStyle], la(h, E), x.push(E)); 0 <= f.duration && (E = 0 < h.style[S].length, E = Ia(f.duration, E), la(h, E), x.push(E)); f.keyframeStyle && (E = [aa, f.keyframeStyle], la(h, E), x.push(E)); var ba = X ? 0 <= f.staggerIndex ? f.staggerIndex : b.count(ia) :
                0; (ja = 0 === ba) && !f.skipBlocking && pa(h, 9999); var D = H(h, na, ia), ca = D.maxDelay; J = Math.max(ca, 0); m = D.maxDuration; var q = {}; q.hasTransitions = 0 < D.transitionDuration; q.hasAnimations = 0 < D.animationDuration; q.hasTransitionAll = q.hasTransitions && "all" == D.transitionProperty; q.applyTransitionDuration = I && (q.hasTransitions && !q.hasTransitionAll || q.hasAnimations && !q.hasTransitions); q.applyAnimationDuration = f.duration && q.hasAnimations; q.applyTransitionDelay = wa(f.delay) && (q.applyTransitionDuration || q.hasTransitions); q.applyAnimationDelay =
                wa(f.delay) && q.hasAnimations; q.recalculateTimingStyles = 0 < U.length; if (q.applyTransitionDuration || q.applyAnimationDuration) m = f.duration ? parseFloat(f.duration) : m, q.applyTransitionDuration && (q.hasTransitions = !0, D.transitionDuration = m, E = 0 < h.style[S + "Property"].length, x.push(Ia(m, E))), q.applyAnimationDuration && (q.hasAnimations = !0, D.animationDuration = m, x.push([Aa, m + "s"])); if (0 === m && !q.recalculateTimingStyles) return L(); if (null != f.delay) {
                    var da; "boolean" !== typeof f.delay && (da = parseFloat(f.delay), J = Math.max(da,
                    0)); q.applyTransitionDelay && x.push([ma, da + "s"]); q.applyAnimationDelay && x.push([qa, da + "s"])
                } null == f.duration && 0 < D.transitionDuration && (q.recalculateTimingStyles = q.recalculateTimingStyles || ja); R = 1E3 * J; V = 1E3 * m; f.skipBlocking || (q.blockTransition = 0 < D.transitionDuration, q.blockKeyframeAnimation = 0 < D.animationDuration && 0 < X.animationDelay && 0 === X.animationDuration); f.from && (f.cleanupStyles && Ka(A, h, Object.keys(f.from)), Fa(a, f)); q.blockTransition || q.blockKeyframeAnimation ? M(m) : f.skipBlocking || pa(h, !1); return {
                    $$willAnimate: !0,
                    end: d, start: function () { if (!w) return v = { end: d, cancel: u, resume: null, pause: null }, G = new l(v), t(N), G }
                }
            }
        }]
    }]).provider("$$animateCssDriver", ["$$animationProvider", function (a) {
        a.drivers.push("$$animateCssDriver"); this.$get = ["$animateCss", "$rootScope", "$$AnimateRunner", "$rootElement", "$sniffer", "$$jqLite", "$document", function (a, c, d, e, l, n, I) {
            function g(a) { return a.replace(/\bng-\S+\b/g, "") } function u(a, b) { G(a) && (a = a.split(" ")); G(b) && (b = b.split(" ")); return a.filter(function (a) { return -1 === b.indexOf(a) }).join(" ") }
            function C(c, e, n) {
                function l(a) { var b = {}, c = y(a).getBoundingClientRect(); s(["width", "height", "top", "left"], function (a) { var d = c[a]; switch (a) { case "top": d += t.scrollTop; break; case "left": d += t.scrollLeft } b[a] = Math.floor(d) + "px" }); return b } function p() { var c = g(n.attr("class") || ""), d = u(c, k), c = u(k, c), d = a(C, { to: l(n), addClass: "ng-anchor-in " + d, removeClass: "ng-anchor-out " + c, delay: !0 }); return d.$$willAnimate ? d : null } function I() { C.remove(); e.removeClass("ng-animate-shim"); n.removeClass("ng-animate-shim") } var C =
                F(y(e).cloneNode(!0)), k = g(C.attr("class") || ""); e.addClass("ng-animate-shim"); n.addClass("ng-animate-shim"); C.addClass("ng-anchor"); H.append(C); var M; c = function () { var c = a(C, { addClass: "ng-anchor-out", delay: !0, from: l(e) }); return c.$$willAnimate ? c : null }(); if (!c && (M = p(), !M)) return I(); var L = c || M; return {
                    start: function () {
                        function a() { c && c.end() } var b, c = L.start(); c.done(function () { c = null; if (!M && (M = p())) return c = M.start(), c.done(function () { c = null; I(); b.complete() }), c; I(); b.complete() }); return b = new d({
                            end: a,
                            cancel: a
                        })
                    }
                }
            } function B(a, b, c, e) { var g = Q(a, P), n = Q(b, P), l = []; s(e, function (a) { (a = C(c, a.out, a["in"])) && l.push(a) }); if (g || n || 0 !== l.length) return { start: function () { function a() { s(b, function (a) { a.end() }) } var b = []; g && b.push(g.start()); n && b.push(n.start()); s(l, function (a) { b.push(a.start()) }); var c = new d({ end: a, cancel: a }); d.all(b, function (a) { c.complete(a) }); return c } } } function Q(c) {
                var d = c.element, e = c.options || {}; c.structural && (e.event = c.event, e.structural = !0, e.applyClassesEarly = !0, "leave" === c.event && (e.onDone =
                e.domOperation)); e.preparationClasses && (e.event = $(e.event, e.preparationClasses)); c = a(d, e); return c.$$willAnimate ? c : null
            } if (!l.animations && !l.transitions) return P; var t = I[0].body; c = y(e); var H = F(c.parentNode && 11 === c.parentNode.nodeType || t.contains(c) ? c : t); V(n); return function (a) { return a.from && a.to ? B(a.from, a.to, a.classes, a.anchors) : Q(a) }
        }]
    }]).provider("$$animateJs", ["$animateProvider", function (a) {
        this.$get = ["$injector", "$$AnimateRunner", "$$jqLite", function (b, c, d) {
            function e(c) {
                c = Y(c) ? c : c.split(" ");
                for (var d = [], e = {}, l = 0; l < c.length; l++) { var s = c[l], B = a.$$registeredAnimations[s]; B && !e[s] && (d.push(b.get(B)), e[s] = !0) } return d
            } var l = V(d); return function (a, b, d, u) {
                function C() { u.domOperation(); l(a, u) } function B(a, b, d, e, f) { switch (d) { case "animate": b = [b, e.from, e.to, f]; break; case "setClass": b = [b, F, G, f]; break; case "addClass": b = [b, F, f]; break; case "removeClass": b = [b, G, f]; break; default: b = [b, f] } b.push(e); if (a = a.apply(a, b)) if (Ca(a.start) && (a = a.start()), a instanceof c) a.done(f); else if (Ca(a)) return a; return P }
                function y(a, b, d, e, f) { var g = []; s(e, function (e) { var k = e[f]; k && g.push(function () { var e, f, g = !1, h = function (a) { g || (g = !0, (f || P)(a), e.complete(!a)) }; e = new c({ end: function () { h() }, cancel: function () { h(!0) } }); f = B(k, a, b, d, function (a) { h(!1 === a) }); return e }) }); return g } function t(a, b, d, e, f) {
                    var g = y(a, b, d, e, f); if (0 === g.length) {
                        var h, k; "beforeSetClass" === f ? (h = y(a, "removeClass", d, e, "beforeRemoveClass"), k = y(a, "addClass", d, e, "beforeAddClass")) : "setClass" === f && (h = y(a, "removeClass", d, e, "removeClass"), k = y(a, "addClass",
                        d, e, "addClass")); h && (g = g.concat(h)); k && (g = g.concat(k))
                    } if (0 !== g.length) return function (a) { var b = []; g.length && s(g, function (a) { b.push(a()) }); b.length ? c.all(b, a) : a(); return function (a) { s(b, function (b) { a ? b.cancel() : b.end() }) } }
                } var H = !1; 3 === arguments.length && ba(d) && (u = d, d = null); u = oa(u); d || (d = a.attr("class") || "", u.addClass && (d += " " + u.addClass), u.removeClass && (d += " " + u.removeClass)); var F = u.addClass, G = u.removeClass, x = e(d), r, p; if (x.length) {
                    var K, J; "leave" == b ? (J = "leave", K = "afterLeave") : (J = "before" + b.charAt(0).toUpperCase() +
                    b.substr(1), K = b); "enter" !== b && "move" !== b && (r = t(a, b, u, x, J)); p = t(a, b, u, x, K)
                } if (r || p) {
                    var k; return {
                        $$willAnimate: !0, end: function () { k ? k.end() : (H = !0, C(), ha(a, u), k = new c, k.complete(!0)); return k }, start: function () {
                            function b(c) { H = !0; C(); ha(a, u); k.complete(c) } if (k) return k; k = new c; var d, e = []; r && e.push(function (a) { d = r(a) }); e.length ? e.push(function (a) { C(); a(!0) }) : C(); p && e.push(function (a) { d = p(a) }); k.setHost({ end: function () { H || ((d || P)(void 0), b(void 0)) }, cancel: function () { H || ((d || P)(!0), b(!0)) } }); c.chain(e,
                            b); return k
                        }
                    }
                }
            }
        }]
    }]).provider("$$animateJsDriver", ["$$animationProvider", function (a) {
        a.drivers.push("$$animateJsDriver"); this.$get = ["$$animateJs", "$$AnimateRunner", function (a, c) {
            function d(c) { return a(c.element, c.event, c.classes, c.options) } return function (a) {
                if (a.from && a.to) {
                    var b = d(a.from), n = d(a.to); if (b || n) return {
                        start: function () {
                            function a() { return function () { s(d, function (a) { a.end() }) } } var d = []; b && d.push(b.start()); n && d.push(n.start()); c.all(d, function (a) { e.complete(a) }); var e = new c({ end: a(), cancel: a() });
                            return e
                        }
                    }
                } else return d(a)
            }
        }]
    }])
})(window, window.angular);
//# sourceMappingURL=angular-animate.min.js.map;
/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 2.3.0 - 2016-11-26
 * License: MIT
 */angular.module("ui.bootstrap", ["ui.bootstrap.collapse", "ui.bootstrap.tabindex", "ui.bootstrap.accordion", "ui.bootstrap.alert", "ui.bootstrap.buttons", "ui.bootstrap.carousel", "ui.bootstrap.dateparser", "ui.bootstrap.isClass", "ui.bootstrap.datepicker", "ui.bootstrap.position", "ui.bootstrap.datepickerPopup", "ui.bootstrap.debounce", "ui.bootstrap.dropdown", "ui.bootstrap.stackedMap", "ui.bootstrap.modal", "ui.bootstrap.paging", "ui.bootstrap.pager", "ui.bootstrap.pagination", "ui.bootstrap.tooltip", "ui.bootstrap.popover", "ui.bootstrap.progressbar", "ui.bootstrap.rating", "ui.bootstrap.tabs", "ui.bootstrap.timepicker", "ui.bootstrap.typeahead"]);
angular.module('ui.bootstrap.collapse', [])

  .directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function ($animate, $q, $parse, $injector) {
      var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;
      return {
          link: function (scope, element, attrs) {
              var expandingExpr = $parse(attrs.expanding),
                expandedExpr = $parse(attrs.expanded),
                collapsingExpr = $parse(attrs.collapsing),
                collapsedExpr = $parse(attrs.collapsed),
                horizontal = false,
                css = {},
                cssTo = {};

              init();

              function init() {
                  horizontal = !!('horizontal' in attrs);
                  if (horizontal) {
                      css = {
                          width: ''
                      };
                      cssTo = { width: '0' };
                  } else {
                      css = {
                          height: ''
                      };
                      cssTo = { height: '0' };
                  }
                  if (!scope.$eval(attrs.uibCollapse)) {
                      element.addClass('in')
                        .addClass('collapse')
                        .attr('aria-expanded', true)
                        .attr('aria-hidden', false)
                        .css(css);
                  }
              }

              function getScrollFromElement(element) {
                  if (horizontal) {
                      return { width: element.scrollWidth + 'px' };
                  }
                  return { height: element.scrollHeight + 'px' };
              }

              function expand() {
                  if (element.hasClass('collapse') && element.hasClass('in')) {
                      return;
                  }

                  $q.resolve(expandingExpr(scope))
                    .then(function () {
                        element.removeClass('collapse')
                          .addClass('collapsing')
                          .attr('aria-expanded', true)
                          .attr('aria-hidden', false);

                        if ($animateCss) {
                            $animateCss(element, {
                                addClass: 'in',
                                easing: 'ease',
                                css: {
                                    overflow: 'hidden'
                                },
                                to: getScrollFromElement(element[0])
                            }).start()['finally'](expandDone);
                        } else {
                            $animate.addClass(element, 'in', {
                                css: {
                                    overflow: 'hidden'
                                },
                                to: getScrollFromElement(element[0])
                            }).then(expandDone);
                        }
                    });
              }

              function expandDone() {
                  element.removeClass('collapsing')
                    .addClass('collapse')
                    .css(css);
                  expandedExpr(scope);
              }

              function collapse() {
                  if (!element.hasClass('collapse') && !element.hasClass('in')) {
                      return collapseDone();
                  }

                  $q.resolve(collapsingExpr(scope))
                    .then(function () {
                        element
                        // IMPORTANT: The width must be set before adding "collapsing" class.
                        // Otherwise, the browser attempts to animate from width 0 (in
                        // collapsing class) to the given width here.
                          .css(getScrollFromElement(element[0]))
                          // initially all panel collapse have the collapse class, this removal
                          // prevents the animation from jumping to collapsed state
                          .removeClass('collapse')
                          .addClass('collapsing')
                          .attr('aria-expanded', false)
                          .attr('aria-hidden', true);

                        if ($animateCss) {
                            $animateCss(element, {
                                removeClass: 'in',
                                to: cssTo
                            }).start()['finally'](collapseDone);
                        } else {
                            $animate.removeClass(element, 'in', {
                                to: cssTo
                            }).then(collapseDone);
                        }
                    });
              }

              function collapseDone() {
                  element.css(cssTo); // Required so that collapse works when animation is disabled
                  element.removeClass('collapsing')
                    .addClass('collapse');
                  collapsedExpr(scope);
              }

              scope.$watch(attrs.uibCollapse, function (shouldCollapse) {
                  if (shouldCollapse) {
                      collapse();
                  } else {
                      expand();
                  }
              });
          }
      };
  }]);

angular.module('ui.bootstrap.tabindex', [])

.directive('uibTabindexToggle', function () {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            attrs.$observe('disabled', function (disabled) {
                attrs.$set('tabindex', disabled ? -1 : null);
            });
        }
    };
});

angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex'])

.constant('uibAccordionConfig', {
    closeOthers: true
})

.controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function ($scope, $attrs, accordionConfig) {
    // This array keeps track of the accordion groups
    this.groups = [];

    // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
    this.closeOthers = function (openGroup) {
        var closeOthers = angular.isDefined($attrs.closeOthers) ?
          $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
        if (closeOthers) {
            angular.forEach(this.groups, function (group) {
                if (group !== openGroup) {
                    group.isOpen = false;
                }
            });
        }
    };

    // This is called from the accordion-group directive to add itself to the accordion
    this.addGroup = function (groupScope) {
        var that = this;
        this.groups.push(groupScope);

        groupScope.$on('$destroy', function (event) {
            that.removeGroup(groupScope);
        });
    };

    // This is called from the accordion-group directive when to remove itself
    this.removeGroup = function (group) {
        var index = this.groups.indexOf(group);
        if (index !== -1) {
            this.groups.splice(index, 1);
        }
    };
}])

// The accordion directive simply sets up the directive controller
// and adds an accordion CSS class to itself element.
.directive('uibAccordion', function () {
    return {
        controller: 'UibAccordionController',
        controllerAs: 'accordion',
        transclude: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/accordion/accordion.html';
        }
    };
})

// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
.directive('uibAccordionGroup', function () {
    return {
        require: '^uibAccordion',         // We need this directive to be inside an accordion
        transclude: true,              // It transcludes the contents of the directive into the template
        restrict: 'A',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
        },
        scope: {
            heading: '@',               // Interpolate the heading attribute onto this scope
            panelClass: '@?',           // Ditto with panelClass
            isOpen: '=?',
            isDisabled: '=?'
        },
        controller: function () {
            this.setHeading = function (element) {
                this.heading = element;
            };
        },
        link: function (scope, element, attrs, accordionCtrl) {
            element.addClass('panel');
            accordionCtrl.addGroup(scope);

            scope.openClass = attrs.openClass || 'panel-open';
            scope.panelClass = attrs.panelClass || 'panel-default';
            scope.$watch('isOpen', function (value) {
                element.toggleClass(scope.openClass, !!value);
                if (value) {
                    accordionCtrl.closeOthers(scope);
                }
            });

            scope.toggleOpen = function ($event) {
                if (!scope.isDisabled) {
                    if (!$event || $event.which === 32) {
                        scope.isOpen = !scope.isOpen;
                    }
                }
            };

            var id = 'accordiongroup-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
            scope.headingId = id + '-tab';
            scope.panelId = id + '-panel';
        }
    };
})

// Use accordion-heading below an accordion-group to provide a heading containing HTML
.directive('uibAccordionHeading', function () {
    return {
        transclude: true,   // Grab the contents to be used as the heading
        template: '',       // In effect remove this element!
        replace: true,
        require: '^uibAccordionGroup',
        link: function (scope, element, attrs, accordionGroupCtrl, transclude) {
            // Pass the heading to the accordion-group controller
            // so that it can be transcluded into the right place in the template
            // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
            accordionGroupCtrl.setHeading(transclude(scope, angular.noop));
        }
    };
})

// Use in the accordion-group template to indicate where you want the heading to be transcluded
// You must provide the property on the accordion-group controller that will hold the transcluded element
.directive('uibAccordionTransclude', function () {
    return {
        require: '^uibAccordionGroup',
        link: function (scope, element, attrs, controller) {
            scope.$watch(function () { return controller[attrs.uibAccordionTransclude]; }, function (heading) {
                if (heading) {
                    var elem = angular.element(element[0].querySelector(getHeaderSelectors()));
                    elem.html('');
                    elem.append(heading);
                }
            });
        }
    };

    function getHeaderSelectors() {
        return 'uib-accordion-header,' +
            'data-uib-accordion-header,' +
            'x-uib-accordion-header,' +
            'uib\\:accordion-header,' +
            '[uib-accordion-header],' +
            '[data-uib-accordion-header],' +
            '[x-uib-accordion-header]';
    }
});

angular.module('ui.bootstrap.alert', [])

.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function ($scope, $element, $attrs, $interpolate, $timeout) {
    $scope.closeable = !!$attrs.close;
    $element.addClass('alert');
    $attrs.$set('role', 'alert');
    if ($scope.closeable) {
        $element.addClass('alert-dismissible');
    }

    var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?
      $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;

    if (dismissOnTimeout) {
        $timeout(function () {
            $scope.close();
        }, parseInt(dismissOnTimeout, 10));
    }
}])

.directive('uibAlert', function () {
    return {
        controller: 'UibAlertController',
        controllerAs: 'alert',
        restrict: 'A',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/alert/alert.html';
        },
        transclude: true,
        scope: {
            close: '&'
        }
    };
});

angular.module('ui.bootstrap.buttons', [])

.constant('uibButtonConfig', {
    activeClass: 'active',
    toggleEvent: 'click'
})

.controller('UibButtonsController', ['uibButtonConfig', function (buttonConfig) {
    this.activeClass = buttonConfig.activeClass || 'active';
    this.toggleEvent = buttonConfig.toggleEvent || 'click';
}])

.directive('uibBtnRadio', ['$parse', function ($parse) {
    return {
        require: ['uibBtnRadio', 'ngModel'],
        controller: 'UibButtonsController',
        controllerAs: 'buttons',
        link: function (scope, element, attrs, ctrls) {
            var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
            var uncheckableExpr = $parse(attrs.uibUncheckable);

            element.find('input').css({ display: 'none' });

            //model -> UI
            ngModelCtrl.$render = function () {
                element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));
            };

            //ui->model
            element.on(buttonsCtrl.toggleEvent, function () {
                if (attrs.disabled) {
                    return;
                }

                var isActive = element.hasClass(buttonsCtrl.activeClass);

                if (!isActive || angular.isDefined(attrs.uncheckable)) {
                    scope.$apply(function () {
                        ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));
                        ngModelCtrl.$render();
                    });
                }
            });

            if (attrs.uibUncheckable) {
                scope.$watch(uncheckableExpr, function (uncheckable) {
                    attrs.$set('uncheckable', uncheckable ? '' : undefined);
                });
            }
        }
    };
}])

.directive('uibBtnCheckbox', function () {
    return {
        require: ['uibBtnCheckbox', 'ngModel'],
        controller: 'UibButtonsController',
        controllerAs: 'button',
        link: function (scope, element, attrs, ctrls) {
            var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            element.find('input').css({ display: 'none' });

            function getTrueValue() {
                return getCheckboxValue(attrs.btnCheckboxTrue, true);
            }

            function getFalseValue() {
                return getCheckboxValue(attrs.btnCheckboxFalse, false);
            }

            function getCheckboxValue(attribute, defaultValue) {
                return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;
            }

            //model -> UI
            ngModelCtrl.$render = function () {
                element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
            };

            //ui->model
            element.on(buttonsCtrl.toggleEvent, function () {
                if (attrs.disabled) {
                    return;
                }

                scope.$apply(function () {
                    ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
                    ngModelCtrl.$render();
                });
            });
        }
    };
});

angular.module('ui.bootstrap.carousel', [])

.controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function ($scope, $element, $interval, $timeout, $animate) {
    var self = this,
      slides = self.slides = $scope.slides = [],
      SLIDE_DIRECTION = 'uib-slideDirection',
      currentIndex = $scope.active,
      currentInterval, isPlaying, bufferedTransitions = [];

    var destroyed = false;
    $element.addClass('carousel');

    self.addSlide = function (slide, element) {
        slides.push({
            slide: slide,
            element: element
        });
        slides.sort(function (a, b) {
            return +a.slide.index - +b.slide.index;
        });
        //if this is the first slide or the slide is set to active, select it
        if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) {
            if ($scope.$currentTransition) {
                $scope.$currentTransition = null;
            }

            currentIndex = slide.index;
            $scope.active = slide.index;
            setActive(currentIndex);
            self.select(slides[findSlideIndex(slide)]);
            if (slides.length === 1) {
                $scope.play();
            }
        }
    };

    self.getCurrentIndex = function () {
        for (var i = 0; i < slides.length; i++) {
            if (slides[i].slide.index === currentIndex) {
                return i;
            }
        }
    };

    self.next = $scope.next = function () {
        var newIndex = (self.getCurrentIndex() + 1) % slides.length;

        if (newIndex === 0 && $scope.noWrap()) {
            $scope.pause();
            return;
        }

        return self.select(slides[newIndex], 'next');
    };

    self.prev = $scope.prev = function () {
        var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;

        if ($scope.noWrap() && newIndex === slides.length - 1) {
            $scope.pause();
            return;
        }

        return self.select(slides[newIndex], 'prev');
    };

    self.removeSlide = function (slide) {
        var index = findSlideIndex(slide);

        var bufferedIndex = bufferedTransitions.indexOf(slides[index]);
        if (bufferedIndex !== -1) {
            bufferedTransitions.splice(bufferedIndex, 1);
        }

        //get the index of the slide inside the carousel
        slides.splice(index, 1);
        if (slides.length > 0 && currentIndex === index) {
            if (index >= slides.length) {
                currentIndex = slides.length - 1;
                $scope.active = currentIndex;
                setActive(currentIndex);
                self.select(slides[slides.length - 1]);
            } else {
                currentIndex = index;
                $scope.active = currentIndex;
                setActive(currentIndex);
                self.select(slides[index]);
            }
        } else if (currentIndex > index) {
            currentIndex--;
            $scope.active = currentIndex;
        }

        //clean the active value when no more slide
        if (slides.length === 0) {
            currentIndex = null;
            $scope.active = null;
            clearBufferedTransitions();
        }
    };

    /* direction: "prev" or "next" */
    self.select = $scope.select = function (nextSlide, direction) {
        var nextIndex = findSlideIndex(nextSlide.slide);
        //Decide direction if it's not given
        if (direction === undefined) {
            direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
        }
        //Prevent this user-triggered transition from occurring if there is already one in progress
        if (nextSlide.slide.index !== currentIndex &&
          !$scope.$currentTransition) {
            goNext(nextSlide.slide, nextIndex, direction);
        } else if (nextSlide && nextSlide.slide.index !== currentIndex && $scope.$currentTransition) {
            bufferedTransitions.push(slides[nextIndex]);
        }
    };

    /* Allow outside people to call indexOf on slides array */
    $scope.indexOfSlide = function (slide) {
        return +slide.slide.index;
    };

    $scope.isActive = function (slide) {
        return $scope.active === slide.slide.index;
    };

    $scope.isPrevDisabled = function () {
        return $scope.active === 0 && $scope.noWrap();
    };

    $scope.isNextDisabled = function () {
        return $scope.active === slides.length - 1 && $scope.noWrap();
    };

    $scope.pause = function () {
        if (!$scope.noPause) {
            isPlaying = false;
            resetTimer();
        }
    };

    $scope.play = function () {
        if (!isPlaying) {
            isPlaying = true;
            restartTimer();
        }
    };

    $element.on('mouseenter', $scope.pause);
    $element.on('mouseleave', $scope.play);

    $scope.$on('$destroy', function () {
        destroyed = true;
        resetTimer();
    });

    $scope.$watch('noTransition', function (noTransition) {
        $animate.enabled($element, !noTransition);
    });

    $scope.$watch('interval', restartTimer);

    $scope.$watchCollection('slides', resetTransition);

    $scope.$watch('active', function (index) {
        if (angular.isNumber(index) && currentIndex !== index) {
            for (var i = 0; i < slides.length; i++) {
                if (slides[i].slide.index === index) {
                    index = i;
                    break;
                }
            }

            var slide = slides[index];
            if (slide) {
                setActive(index);
                self.select(slides[index]);
                currentIndex = index;
            }
        }
    });

    function clearBufferedTransitions() {
        while (bufferedTransitions.length) {
            bufferedTransitions.shift();
        }
    }

    function getSlideByIndex(index) {
        for (var i = 0, l = slides.length; i < l; ++i) {
            if (slides[i].index === index) {
                return slides[i];
            }
        }
    }

    function setActive(index) {
        for (var i = 0; i < slides.length; i++) {
            slides[i].slide.active = i === index;
        }
    }

    function goNext(slide, index, direction) {
        if (destroyed) {
            return;
        }

        angular.extend(slide, { direction: direction });
        angular.extend(slides[currentIndex].slide || {}, { direction: direction });
        if ($animate.enabled($element) && !$scope.$currentTransition &&
          slides[index].element && self.slides.length > 1) {
            slides[index].element.data(SLIDE_DIRECTION, slide.direction);
            var currentIdx = self.getCurrentIndex();

            if (angular.isNumber(currentIdx) && slides[currentIdx].element) {
                slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction);
            }

            $scope.$currentTransition = true;
            $animate.on('addClass', slides[index].element, function (element, phase) {
                if (phase === 'close') {
                    $scope.$currentTransition = null;
                    $animate.off('addClass', element);
                    if (bufferedTransitions.length) {
                        var nextSlide = bufferedTransitions.pop().slide;
                        var nextIndex = nextSlide.index;
                        var nextDirection = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
                        clearBufferedTransitions();

                        goNext(nextSlide, nextIndex, nextDirection);
                    }
                }
            });
        }

        $scope.active = slide.index;
        currentIndex = slide.index;
        setActive(index);

        //every time you change slides, reset the timer
        restartTimer();
    }

    function findSlideIndex(slide) {
        for (var i = 0; i < slides.length; i++) {
            if (slides[i].slide === slide) {
                return i;
            }
        }
    }

    function resetTimer() {
        if (currentInterval) {
            $interval.cancel(currentInterval);
            currentInterval = null;
        }
    }

    function resetTransition(slides) {
        if (!slides.length) {
            $scope.$currentTransition = null;
            clearBufferedTransitions();
        }
    }

    function restartTimer() {
        resetTimer();
        var interval = +$scope.interval;
        if (!isNaN(interval) && interval > 0) {
            currentInterval = $interval(timerFn, interval);
        }
    }

    function timerFn() {
        var interval = +$scope.interval;
        if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
            $scope.next();
        } else {
            $scope.pause();
        }
    }
}])

.directive('uibCarousel', function () {
    return {
        transclude: true,
        controller: 'UibCarouselController',
        controllerAs: 'carousel',
        restrict: 'A',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/carousel/carousel.html';
        },
        scope: {
            active: '=',
            interval: '=',
            noTransition: '=',
            noPause: '=',
            noWrap: '&'
        }
    };
})

.directive('uibSlide', ['$animate', function ($animate) {
    return {
        require: '^uibCarousel',
        restrict: 'A',
        transclude: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/carousel/slide.html';
        },
        scope: {
            actual: '=?',
            index: '=?'
        },
        link: function (scope, element, attrs, carouselCtrl) {
            element.addClass('item');
            carouselCtrl.addSlide(scope, element);
            //when the scope is destroyed then remove the slide from the current slides array
            scope.$on('$destroy', function () {
                carouselCtrl.removeSlide(scope);
            });

            scope.$watch('active', function (active) {
                $animate[active ? 'addClass' : 'removeClass'](element, 'active');
            });
        }
    };
}])

.animation('.item', ['$animateCss',
function ($animateCss) {
    var SLIDE_DIRECTION = 'uib-slideDirection';

    function removeClass(element, className, callback) {
        element.removeClass(className);
        if (callback) {
            callback();
        }
    }

    return {
        beforeAddClass: function (element, className, done) {
            if (className === 'active') {
                var stopped = false;
                var direction = element.data(SLIDE_DIRECTION);
                var directionClass = direction === 'next' ? 'left' : 'right';
                var removeClassFn = removeClass.bind(this, element,
                  directionClass + ' ' + direction, done);
                element.addClass(direction);

                $animateCss(element, { addClass: directionClass })
                  .start()
                  .done(removeClassFn);

                return function () {
                    stopped = true;
                };
            }
            done();
        },
        beforeRemoveClass: function (element, className, done) {
            if (className === 'active') {
                var stopped = false;
                var direction = element.data(SLIDE_DIRECTION);
                var directionClass = direction === 'next' ? 'left' : 'right';
                var removeClassFn = removeClass.bind(this, element, directionClass, done);

                $animateCss(element, { addClass: directionClass })
                  .start()
                  .done(removeClassFn);

                return function () {
                    stopped = true;
                };
            }
            done();
        }
    };
}]);

angular.module('ui.bootstrap.dateparser', [])

.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', function ($log, $locale, dateFilter, orderByFilter) {
    // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js
    var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;

    var localeId;
    var formatCodeToRegex;

    this.init = function () {
        localeId = $locale.id;

        this.parsers = {};
        this.formatters = {};

        formatCodeToRegex = [
          {
              key: 'yyyy',
              regex: '\\d{4}',
              apply: function (value) { this.year = +value; },
              formatter: function (date) {
                  var _date = new Date();
                  _date.setFullYear(Math.abs(date.getFullYear()));
                  return dateFilter(_date, 'yyyy');
              }
          },
          {
              key: 'yy',
              regex: '\\d{2}',
              apply: function (value) { value = +value; this.year = value < 69 ? value + 2000 : value + 1900; },
              formatter: function (date) {
                  var _date = new Date();
                  _date.setFullYear(Math.abs(date.getFullYear()));
                  return dateFilter(_date, 'yy');
              }
          },
          {
              key: 'y',
              regex: '\\d{1,4}',
              apply: function (value) { this.year = +value; },
              formatter: function (date) {
                  var _date = new Date();
                  _date.setFullYear(Math.abs(date.getFullYear()));
                  return dateFilter(_date, 'y');
              }
          },
          {
              key: 'M!',
              regex: '0?[1-9]|1[0-2]',
              apply: function (value) { this.month = value - 1; },
              formatter: function (date) {
                  var value = date.getMonth();
                  if (/^[0-9]$/.test(value)) {
                      return dateFilter(date, 'MM');
                  }

                  return dateFilter(date, 'M');
              }
          },
          {
              key: 'MMMM',
              regex: $locale.DATETIME_FORMATS.MONTH.join('|'),
              apply: function (value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); },
              formatter: function (date) { return dateFilter(date, 'MMMM'); }
          },
          {
              key: 'MMM',
              regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
              apply: function (value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); },
              formatter: function (date) { return dateFilter(date, 'MMM'); }
          },
          {
              key: 'MM',
              regex: '0[1-9]|1[0-2]',
              apply: function (value) { this.month = value - 1; },
              formatter: function (date) { return dateFilter(date, 'MM'); }
          },
          {
              key: 'M',
              regex: '[1-9]|1[0-2]',
              apply: function (value) { this.month = value - 1; },
              formatter: function (date) { return dateFilter(date, 'M'); }
          },
          {
              key: 'LLLL',
              regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'),
              apply: function (value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); },
              formatter: function (date) { return dateFilter(date, 'LLLL'); }
          },
          {
              key: 'd!',
              regex: '[0-2]?[0-9]{1}|3[0-1]{1}',
              apply: function (value) { this.date = +value; },
              formatter: function (date) {
                  var value = date.getDate();
                  if (/^[1-9]$/.test(value)) {
                      return dateFilter(date, 'dd');
                  }

                  return dateFilter(date, 'd');
              }
          },
          {
              key: 'dd',
              regex: '[0-2][0-9]{1}|3[0-1]{1}',
              apply: function (value) { this.date = +value; },
              formatter: function (date) { return dateFilter(date, 'dd'); }
          },
          {
              key: 'd',
              regex: '[1-2]?[0-9]{1}|3[0-1]{1}',
              apply: function (value) { this.date = +value; },
              formatter: function (date) { return dateFilter(date, 'd'); }
          },
          {
              key: 'EEEE',
              regex: $locale.DATETIME_FORMATS.DAY.join('|'),
              formatter: function (date) { return dateFilter(date, 'EEEE'); }
          },
          {
              key: 'EEE',
              regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
              formatter: function (date) { return dateFilter(date, 'EEE'); }
          },
          {
              key: 'HH',
              regex: '(?:0|1)[0-9]|2[0-3]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'HH'); }
          },
          {
              key: 'hh',
              regex: '0[0-9]|1[0-2]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'hh'); }
          },
          {
              key: 'H',
              regex: '1?[0-9]|2[0-3]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'H'); }
          },
          {
              key: 'h',
              regex: '[0-9]|1[0-2]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'h'); }
          },
          {
              key: 'mm',
              regex: '[0-5][0-9]',
              apply: function (value) { this.minutes = +value; },
              formatter: function (date) { return dateFilter(date, 'mm'); }
          },
          {
              key: 'm',
              regex: '[0-9]|[1-5][0-9]',
              apply: function (value) { this.minutes = +value; },
              formatter: function (date) { return dateFilter(date, 'm'); }
          },
          {
              key: 'sss',
              regex: '[0-9][0-9][0-9]',
              apply: function (value) { this.milliseconds = +value; },
              formatter: function (date) { return dateFilter(date, 'sss'); }
          },
          {
              key: 'ss',
              regex: '[0-5][0-9]',
              apply: function (value) { this.seconds = +value; },
              formatter: function (date) { return dateFilter(date, 'ss'); }
          },
          {
              key: 's',
              regex: '[0-9]|[1-5][0-9]',
              apply: function (value) { this.seconds = +value; },
              formatter: function (date) { return dateFilter(date, 's'); }
          },
          {
              key: 'a',
              regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),
              apply: function (value) {
                  if (this.hours === 12) {
                      this.hours = 0;
                  }

                  if (value === 'PM') {
                      this.hours += 12;
                  }
              },
              formatter: function (date) { return dateFilter(date, 'a'); }
          },
          {
              key: 'Z',
              regex: '[+-]\\d{4}',
              apply: function (value) {
                  var matches = value.match(/([+-])(\d{2})(\d{2})/),
                    sign = matches[1],
                    hours = matches[2],
                    minutes = matches[3];
                  this.hours += toInt(sign + hours);
                  this.minutes += toInt(sign + minutes);
              },
              formatter: function (date) {
                  return dateFilter(date, 'Z');
              }
          },
          {
              key: 'ww',
              regex: '[0-4][0-9]|5[0-3]',
              formatter: function (date) { return dateFilter(date, 'ww'); }
          },
          {
              key: 'w',
              regex: '[0-9]|[1-4][0-9]|5[0-3]',
              formatter: function (date) { return dateFilter(date, 'w'); }
          },
          {
              key: 'GGGG',
              regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\s/g, '\\s'),
              formatter: function (date) { return dateFilter(date, 'GGGG'); }
          },
          {
              key: 'GGG',
              regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
              formatter: function (date) { return dateFilter(date, 'GGG'); }
          },
          {
              key: 'GG',
              regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
              formatter: function (date) { return dateFilter(date, 'GG'); }
          },
          {
              key: 'G',
              regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
              formatter: function (date) { return dateFilter(date, 'G'); }
          }
        ];
    };

    this.init();

    function createParser(format) {
        var map = [], regex = format.split('');

        // check for literal values
        var quoteIndex = format.indexOf('\'');
        if (quoteIndex > -1) {
            var inLiteral = false;
            format = format.split('');
            for (var i = quoteIndex; i < format.length; i++) {
                if (inLiteral) {
                    if (format[i] === '\'') {
                        if (i + 1 < format.length && format[i + 1] === '\'') { // escaped single quote
                            format[i + 1] = '$';
                            regex[i + 1] = '';
                        } else { // end of literal
                            regex[i] = '';
                            inLiteral = false;
                        }
                    }
                    format[i] = '$';
                } else {
                    if (format[i] === '\'') { // start of literal
                        format[i] = '$';
                        regex[i] = '';
                        inLiteral = true;
                    }
                }
            }

            format = format.join('');
        }

        angular.forEach(formatCodeToRegex, function (data) {
            var index = format.indexOf(data.key);

            if (index > -1) {
                format = format.split('');

                regex[index] = '(' + data.regex + ')';
                format[index] = '$'; // Custom symbol to define consumed part of format
                for (var i = index + 1, n = index + data.key.length; i < n; i++) {
                    regex[i] = '';
                    format[i] = '$';
                }
                format = format.join('');

                map.push({
                    index: index,
                    key: data.key,
                    apply: data.apply,
                    matcher: data.regex
                });
            }
        });

        return {
            regex: new RegExp('^' + regex.join('') + '$'),
            map: orderByFilter(map, 'index')
        };
    }

    function createFormatter(format) {
        var formatters = [];
        var i = 0;
        var formatter, literalIdx;
        while (i < format.length) {
            if (angular.isNumber(literalIdx)) {
                if (format.charAt(i) === '\'') {
                    if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') {
                        formatters.push(constructLiteralFormatter(format, literalIdx, i));
                        literalIdx = null;
                    }
                } else if (i === format.length) {
                    while (literalIdx < format.length) {
                        formatter = constructFormatterFromIdx(format, literalIdx);
                        formatters.push(formatter);
                        literalIdx = formatter.endIdx;
                    }
                }

                i++;
                continue;
            }

            if (format.charAt(i) === '\'') {
                literalIdx = i;
                i++;
                continue;
            }

            formatter = constructFormatterFromIdx(format, i);

            formatters.push(formatter.parser);
            i = formatter.endIdx;
        }

        return formatters;
    }

    function constructLiteralFormatter(format, literalIdx, endIdx) {
        return function () {
            return format.substr(literalIdx + 1, endIdx - literalIdx - 1);
        };
    }

    function constructFormatterFromIdx(format, i) {
        var currentPosStr = format.substr(i);
        for (var j = 0; j < formatCodeToRegex.length; j++) {
            if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {
                var data = formatCodeToRegex[j];
                return {
                    endIdx: i + data.key.length,
                    parser: data.formatter
                };
            }
        }

        return {
            endIdx: i + 1,
            parser: function () {
                return currentPosStr.charAt(0);
            }
        };
    }

    this.filter = function (date, format) {
        if (!angular.isDate(date) || isNaN(date) || !format) {
            return '';
        }

        format = $locale.DATETIME_FORMATS[format] || format;

        if ($locale.id !== localeId) {
            this.init();
        }

        if (!this.formatters[format]) {
            this.formatters[format] = createFormatter(format);
        }

        var formatters = this.formatters[format];

        return formatters.reduce(function (str, formatter) {
            return str + formatter(date);
        }, '');
    };

    this.parse = function (input, format, baseDate) {
        if (!angular.isString(input) || !format) {
            return input;
        }

        format = $locale.DATETIME_FORMATS[format] || format;
        format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&');

        if ($locale.id !== localeId) {
            this.init();
        }

        if (!this.parsers[format]) {
            this.parsers[format] = createParser(format, 'apply');
        }

        var parser = this.parsers[format],
            regex = parser.regex,
            map = parser.map,
            results = input.match(regex),
            tzOffset = false;
        if (results && results.length) {
            var fields, dt;
            if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {
                fields = {
                    year: baseDate.getFullYear(),
                    month: baseDate.getMonth(),
                    date: baseDate.getDate(),
                    hours: baseDate.getHours(),
                    minutes: baseDate.getMinutes(),
                    seconds: baseDate.getSeconds(),
                    milliseconds: baseDate.getMilliseconds()
                };
            } else {
                if (baseDate) {
                    $log.warn('dateparser:', 'baseDate is not a valid date');
                }
                fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
            }

            for (var i = 1, n = results.length; i < n; i++) {
                var mapper = map[i - 1];
                if (mapper.matcher === 'Z') {
                    tzOffset = true;
                }

                if (mapper.apply) {
                    mapper.apply.call(fields, results[i]);
                }
            }

            var datesetter = tzOffset ? Date.prototype.setUTCFullYear :
              Date.prototype.setFullYear;
            var timesetter = tzOffset ? Date.prototype.setUTCHours :
              Date.prototype.setHours;

            if (isValid(fields.year, fields.month, fields.date)) {
                if (angular.isDate(baseDate) && !isNaN(baseDate.getTime()) && !tzOffset) {
                    dt = new Date(baseDate);
                    datesetter.call(dt, fields.year, fields.month, fields.date);
                    timesetter.call(dt, fields.hours, fields.minutes,
                      fields.seconds, fields.milliseconds);
                } else {
                    dt = new Date(0);
                    datesetter.call(dt, fields.year, fields.month, fields.date);
                    timesetter.call(dt, fields.hours || 0, fields.minutes || 0,
                      fields.seconds || 0, fields.milliseconds || 0);
                }
            }

            return dt;
        }
    };

    // Check if date is valid for specific month (and year for February).
    // Month: 0 = Jan, 1 = Feb, etc
    function isValid(year, month, date) {
        if (date < 1) {
            return false;
        }

        if (month === 1 && date > 28) {
            return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0);
        }

        if (month === 3 || month === 5 || month === 8 || month === 10) {
            return date < 31;
        }

        return true;
    }

    function toInt(str) {
        return parseInt(str, 10);
    }

    this.toTimezone = toTimezone;
    this.fromTimezone = fromTimezone;
    this.timezoneToOffset = timezoneToOffset;
    this.addDateMinutes = addDateMinutes;
    this.convertTimezoneToLocal = convertTimezoneToLocal;

    function toTimezone(date, timezone) {
        return date && timezone ? convertTimezoneToLocal(date, timezone) : date;
    }

    function fromTimezone(date, timezone) {
        return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;
    }

    //https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207
    function timezoneToOffset(timezone, fallback) {
        timezone = timezone.replace(/:/g, '');
        var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
        return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
    }

    function addDateMinutes(date, minutes) {
        date = new Date(date.getTime());
        date.setMinutes(date.getMinutes() + minutes);
        return date;
    }

    function convertTimezoneToLocal(date, timezone, reverse) {
        reverse = reverse ? -1 : 1;
        var dateTimezoneOffset = date.getTimezoneOffset();
        var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
        return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
    }
}]);

// Avoiding use of ng-class as it creates a lot of watchers when a class is to be applied to
// at most one element.
angular.module('ui.bootstrap.isClass', [])
.directive('uibIsClass', [
         '$animate',
function ($animate) {
    //                    11111111          22222222
    var ON_REGEXP = /^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/;
    //                    11111111           22222222
    var IS_REGEXP = /^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;

    var dataPerTracked = {};

    return {
        restrict: 'A',
        compile: function (tElement, tAttrs) {
            var linkedScopes = [];
            var instances = [];
            var expToData = {};
            var lastActivated = null;
            var onExpMatches = tAttrs.uibIsClass.match(ON_REGEXP);
            var onExp = onExpMatches[2];
            var expsStr = onExpMatches[1];
            var exps = expsStr.split(',');

            return linkFn;

            function linkFn(scope, element, attrs) {
                linkedScopes.push(scope);
                instances.push({
                    scope: scope,
                    element: element
                });

                exps.forEach(function (exp, k) {
                    addForExp(exp, scope);
                });

                scope.$on('$destroy', removeScope);
            }

            function addForExp(exp, scope) {
                var matches = exp.match(IS_REGEXP);
                var clazz = scope.$eval(matches[1]);
                var compareWithExp = matches[2];
                var data = expToData[exp];
                if (!data) {
                    var watchFn = function (compareWithVal) {
                        var newActivated = null;
                        instances.some(function (instance) {
                            var thisVal = instance.scope.$eval(onExp);
                            if (thisVal === compareWithVal) {
                                newActivated = instance;
                                return true;
                            }
                        });
                        if (data.lastActivated !== newActivated) {
                            if (data.lastActivated) {
                                $animate.removeClass(data.lastActivated.element, clazz);
                            }
                            if (newActivated) {
                                $animate.addClass(newActivated.element, clazz);
                            }
                            data.lastActivated = newActivated;
                        }
                    };
                    expToData[exp] = data = {
                        lastActivated: null,
                        scope: scope,
                        watchFn: watchFn,
                        compareWithExp: compareWithExp,
                        watcher: scope.$watch(compareWithExp, watchFn)
                    };
                }
                data.watchFn(scope.$eval(compareWithExp));
            }

            function removeScope(e) {
                var removedScope = e.targetScope;
                var index = linkedScopes.indexOf(removedScope);
                linkedScopes.splice(index, 1);
                instances.splice(index, 1);
                if (linkedScopes.length) {
                    var newWatchScope = linkedScopes[0];
                    angular.forEach(expToData, function (data) {
                        if (data.scope === removedScope) {
                            data.watcher = newWatchScope.$watch(data.compareWithExp, data.watchFn);
                            data.scope = newWatchScope;
                        }
                    });
                } else {
                    expToData = {};
                }
            }
        }
    };
}]);
angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass'])

.value('$datepickerSuppressError', false)

.value('$datepickerLiteralWarning', true)

.constant('uibDatepickerConfig', {
    datepickerMode: 'day',
    formatDay: 'dd',
    formatMonth: 'MMMM',
    formatYear: 'yyyy',
    formatDayHeader: 'EEE',
    formatDayTitle: 'MMMM yyyy',
    formatMonthTitle: 'yyyy',
    maxDate: null,
    maxMode: 'year',
    minDate: null,
    minMode: 'day',
    monthColumns: 3,
    ngModelOptions: {},
    shortcutPropagation: false,
    showWeeks: true,
    yearColumns: 5,
    yearRows: 4
})

.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
  function ($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
      var self = this,
          ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
          ngModelOptions = {},
          watchListeners = [];

      $element.addClass('uib-datepicker');
      $attrs.$set('role', 'application');

      if (!$scope.datepickerOptions) {
          $scope.datepickerOptions = {};
      }

      // Modes chain
      this.modes = ['day', 'month', 'year'];

      [
        'customClass',
        'dateDisabled',
        'datepickerMode',
        'formatDay',
        'formatDayHeader',
        'formatDayTitle',
        'formatMonth',
        'formatMonthTitle',
        'formatYear',
        'maxDate',
        'maxMode',
        'minDate',
        'minMode',
        'monthColumns',
        'showWeeks',
        'shortcutPropagation',
        'startingDay',
        'yearColumns',
        'yearRows'
      ].forEach(function (key) {
          switch (key) {
              case 'customClass':
              case 'dateDisabled':
                  $scope[key] = $scope.datepickerOptions[key] || angular.noop;
                  break;
              case 'datepickerMode':
                  $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ?
                    $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode;
                  break;
              case 'formatDay':
              case 'formatDayHeader':
              case 'formatDayTitle':
              case 'formatMonth':
              case 'formatMonthTitle':
              case 'formatYear':
                  self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
                    $interpolate($scope.datepickerOptions[key])($scope.$parent) :
                    datepickerConfig[key];
                  break;
              case 'monthColumns':
              case 'showWeeks':
              case 'shortcutPropagation':
              case 'yearColumns':
              case 'yearRows':
                  self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
                    $scope.datepickerOptions[key] : datepickerConfig[key];
                  break;
              case 'startingDay':
                  if (angular.isDefined($scope.datepickerOptions.startingDay)) {
                      self.startingDay = $scope.datepickerOptions.startingDay;
                  } else if (angular.isNumber(datepickerConfig.startingDay)) {
                      self.startingDay = datepickerConfig.startingDay;
                  } else {
                      self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
                  }

                  break;
              case 'maxDate':
              case 'minDate':
                  $scope.$watch('datepickerOptions.' + key, function (value) {
                      if (value) {
                          if (angular.isDate(value)) {
                              self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone);
                          } else {
                              if ($datepickerLiteralWarning) {
                                  $log.warn('Literal date support has been deprecated, please switch to date object usage');
                              }

                              self[key] = new Date(dateFilter(value, 'medium'));
                          }
                      } else {
                          self[key] = datepickerConfig[key] ?
                            dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) :
                            null;
                      }

                      self.refreshView();
                  });

                  break;
              case 'maxMode':
              case 'minMode':
                  if ($scope.datepickerOptions[key]) {
                      $scope.$watch(function () { return $scope.datepickerOptions[key]; }, function (value) {
                          self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key];
                          if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||
                            key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {
                              $scope.datepickerMode = self[key];
                              $scope.datepickerOptions.datepickerMode = self[key];
                          }
                      });
                  } else {
                      self[key] = $scope[key] = datepickerConfig[key] || null;
                  }

                  break;
          }
      });

      $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);

      $scope.disabled = angular.isDefined($attrs.disabled) || false;
      if (angular.isDefined($attrs.ngDisabled)) {
          watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function (disabled) {
              $scope.disabled = disabled;
              self.refreshView();
          }));
      }

      $scope.isActive = function (dateObject) {
          if (self.compare(dateObject.date, self.activeDate) === 0) {
              $scope.activeDateId = dateObject.uid;
              return true;
          }
          return false;
      };

      this.init = function (ngModelCtrl_) {
          ngModelCtrl = ngModelCtrl_;
          ngModelOptions = ngModelCtrl_.$options ||
            $scope.datepickerOptions.ngModelOptions ||
            datepickerConfig.ngModelOptions;
          if ($scope.datepickerOptions.initDate) {
              self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date();
              $scope.$watch('datepickerOptions.initDate', function (initDate) {
                  if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
                      self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
                      self.refreshView();
                  }
              });
          } else {
              self.activeDate = new Date();
          }

          var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
          this.activeDate = !isNaN(date) ?
            dateParser.fromTimezone(date, ngModelOptions.timezone) :
            dateParser.fromTimezone(new Date(), ngModelOptions.timezone);

          ngModelCtrl.$render = function () {
              self.render();
          };
      };

      this.render = function () {
          if (ngModelCtrl.$viewValue) {
              var date = new Date(ngModelCtrl.$viewValue),
                  isValid = !isNaN(date);

              if (isValid) {
                  this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone);
              } else if (!$datepickerSuppressError) {
                  $log.error('Datepicker directive: "ng-model" value must be a Date object');
              }
          }
          this.refreshView();
      };

      this.refreshView = function () {
          if (this.element) {
              $scope.selectedDt = null;
              this._refreshView();
              if ($scope.activeDt) {
                  $scope.activeDateId = $scope.activeDt.uid;
              }

              var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
              date = dateParser.fromTimezone(date, ngModelOptions.timezone);
              ngModelCtrl.$setValidity('dateDisabled', !date ||
                this.element && !this.isDisabled(date));
          }
      };

      this.createDateObject = function (date, format) {
          var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
          model = dateParser.fromTimezone(model, ngModelOptions.timezone);
          var today = new Date();
          today = dateParser.fromTimezone(today, ngModelOptions.timezone);
          var time = this.compare(date, today);
          var dt = {
              date: date,
              label: dateParser.filter(date, format),
              selected: model && this.compare(date, model) === 0,
              disabled: this.isDisabled(date),
              past: time < 0,
              current: time === 0,
              future: time > 0,
              customClass: this.customClass(date) || null
          };

          if (model && this.compare(date, model) === 0) {
              $scope.selectedDt = dt;
          }

          if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {
              $scope.activeDt = dt;
          }

          return dt;
      };

      this.isDisabled = function (date) {
          return $scope.disabled ||
            this.minDate && this.compare(date, this.minDate) < 0 ||
            this.maxDate && this.compare(date, this.maxDate) > 0 ||
            $scope.dateDisabled && $scope.dateDisabled({ date: date, mode: $scope.datepickerMode });
      };

      this.customClass = function (date) {
          return $scope.customClass({ date: date, mode: $scope.datepickerMode });
      };

      // Split array into smaller arrays
      this.split = function (arr, size) {
          var arrays = [];
          while (arr.length > 0) {
              arrays.push(arr.splice(0, size));
          }
          return arrays;
      };

      $scope.select = function (date) {
          if ($scope.datepickerMode === self.minMode) {
              var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0);
              dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
              dt = dateParser.toTimezone(dt, ngModelOptions.timezone);
              ngModelCtrl.$setViewValue(dt);
              ngModelCtrl.$render();
          } else {
              self.activeDate = date;
              setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);

              $scope.$emit('uib:datepicker.mode');
          }

          $scope.$broadcast('uib:datepicker.focus');
      };

      $scope.move = function (direction) {
          var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
              month = self.activeDate.getMonth() + direction * (self.step.months || 0);
          self.activeDate.setFullYear(year, month, 1);
          self.refreshView();
      };

      $scope.toggleMode = function (direction) {
          direction = direction || 1;

          if ($scope.datepickerMode === self.maxMode && direction === 1 ||
            $scope.datepickerMode === self.minMode && direction === -1) {
              return;
          }

          setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]);

          $scope.$emit('uib:datepicker.mode');
      };

      // Key event mapper
      $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };

      var focusElement = function () {
          self.element[0].focus();
      };

      // Listen for focus requests from popup directive
      $scope.$on('uib:datepicker.focus', focusElement);

      $scope.keydown = function (evt) {
          var key = $scope.keys[evt.which];

          if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
              return;
          }

          evt.preventDefault();
          if (!self.shortcutPropagation) {
              evt.stopPropagation();
          }

          if (key === 'enter' || key === 'space') {
              if (self.isDisabled(self.activeDate)) {
                  return; // do nothing
              }
              $scope.select(self.activeDate);
          } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
              $scope.toggleMode(key === 'up' ? 1 : -1);
          } else {
              self.handleKeyDown(key, evt);
              self.refreshView();
          }
      };

      $element.on('keydown', function (evt) {
          $scope.$apply(function () {
              $scope.keydown(evt);
          });
      });

      $scope.$on('$destroy', function () {
          //Clear all watch listeners on destroy
          while (watchListeners.length) {
              watchListeners.shift()();
          }
      });

      function setMode(mode) {
          $scope.datepickerMode = mode;
          $scope.datepickerOptions.datepickerMode = mode;
      }
  }])

.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function (scope, $element, dateFilter) {
    var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    this.step = { months: 1 };
    this.element = $element;
    function getDaysInMonth(year, month) {
        return month === 1 && year % 4 === 0 &&
          (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];
    }

    this.init = function (ctrl) {
        angular.extend(ctrl, this);
        scope.showWeeks = ctrl.showWeeks;
        ctrl.refreshView();
    };

    this.getDates = function (startDate, n) {
        var dates = new Array(n), current = new Date(startDate), i = 0, date;
        while (i < n) {
            date = new Date(current);
            dates[i++] = date;
            current.setDate(current.getDate() + 1);
        }
        return dates;
    };

    this._refreshView = function () {
        var year = this.activeDate.getFullYear(),
          month = this.activeDate.getMonth(),
          firstDayOfMonth = new Date(this.activeDate);

        firstDayOfMonth.setFullYear(year, month, 1);

        var difference = this.startingDay - firstDayOfMonth.getDay(),
          numDisplayedFromPreviousMonth = difference > 0 ?
            7 - difference : -difference,
          firstDate = new Date(firstDayOfMonth);

        if (numDisplayedFromPreviousMonth > 0) {
            firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
        }

        // 42 is the number of days on a six-week calendar
        var days = this.getDates(firstDate, 42);
        for (var i = 0; i < 42; i++) {
            days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {
                secondary: days[i].getMonth() !== month,
                uid: scope.uniqueId + '-' + i
            });
        }

        scope.labels = new Array(7);
        for (var j = 0; j < 7; j++) {
            scope.labels[j] = {
                abbr: dateFilter(days[j].date, this.formatDayHeader),
                full: dateFilter(days[j].date, 'EEEE')
            };
        }

        scope.title = dateFilter(this.activeDate, this.formatDayTitle);
        scope.rows = this.split(days, 7);

        if (scope.showWeeks) {
            scope.weekNumbers = [];
            var thursdayIndex = (4 + 7 - this.startingDay) % 7,
                numWeeks = scope.rows.length;
            for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
                scope.weekNumbers.push(
                  getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));
            }
        }
    };

    this.compare = function (date1, date2) {
        var _date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
        var _date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
        _date1.setFullYear(date1.getFullYear());
        _date2.setFullYear(date2.getFullYear());
        return _date1 - _date2;
    };

    function getISO8601WeekNumber(date) {
        var checkDate = new Date(date);
        checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
        var time = checkDate.getTime();
        checkDate.setMonth(0); // Compare with Jan 1
        checkDate.setDate(1);
        return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
    }

    this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getDate();

        if (key === 'left') {
            date = date - 1;
        } else if (key === 'up') {
            date = date - 7;
        } else if (key === 'right') {
            date = date + 1;
        } else if (key === 'down') {
            date = date + 7;
        } else if (key === 'pageup' || key === 'pagedown') {
            var month = this.activeDate.getMonth() + (key === 'pageup' ? -1 : 1);
            this.activeDate.setMonth(month, 1);
            date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);
        } else if (key === 'home') {
            date = 1;
        } else if (key === 'end') {
            date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());
        }
        this.activeDate.setDate(date);
    };
}])

.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function (scope, $element, dateFilter) {
    this.step = { years: 1 };
    this.element = $element;

    this.init = function (ctrl) {
        angular.extend(ctrl, this);
        ctrl.refreshView();
    };

    this._refreshView = function () {
        var months = new Array(12),
            year = this.activeDate.getFullYear(),
            date;

        for (var i = 0; i < 12; i++) {
            date = new Date(this.activeDate);
            date.setFullYear(year, i, 1);
            months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {
                uid: scope.uniqueId + '-' + i
            });
        }

        scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
        scope.rows = this.split(months, this.monthColumns);
        scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1;
    };

    this.compare = function (date1, date2) {
        var _date1 = new Date(date1.getFullYear(), date1.getMonth());
        var _date2 = new Date(date2.getFullYear(), date2.getMonth());
        _date1.setFullYear(date1.getFullYear());
        _date2.setFullYear(date2.getFullYear());
        return _date1 - _date2;
    };

    this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getMonth();

        if (key === 'left') {
            date = date - 1;
        } else if (key === 'up') {
            date = date - this.monthColumns;
        } else if (key === 'right') {
            date = date + 1;
        } else if (key === 'down') {
            date = date + this.monthColumns;
        } else if (key === 'pageup' || key === 'pagedown') {
            var year = this.activeDate.getFullYear() + (key === 'pageup' ? -1 : 1);
            this.activeDate.setFullYear(year);
        } else if (key === 'home') {
            date = 0;
        } else if (key === 'end') {
            date = 11;
        }
        this.activeDate.setMonth(date);
    };
}])

.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function (scope, $element, dateFilter) {
    var columns, range;
    this.element = $element;

    function getStartingYear(year) {
        return parseInt((year - 1) / range, 10) * range + 1;
    }

    this.yearpickerInit = function () {
        columns = this.yearColumns;
        range = this.yearRows * columns;
        this.step = { years: range };
    };

    this._refreshView = function () {
        var years = new Array(range), date;

        for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()) ; i < range; i++) {
            date = new Date(this.activeDate);
            date.setFullYear(start + i, 0, 1);
            years[i] = angular.extend(this.createDateObject(date, this.formatYear), {
                uid: scope.uniqueId + '-' + i
            });
        }

        scope.title = [years[0].label, years[range - 1].label].join(' - ');
        scope.rows = this.split(years, columns);
        scope.columns = columns;
    };

    this.compare = function (date1, date2) {
        return date1.getFullYear() - date2.getFullYear();
    };

    this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getFullYear();

        if (key === 'left') {
            date = date - 1;
        } else if (key === 'up') {
            date = date - columns;
        } else if (key === 'right') {
            date = date + 1;
        } else if (key === 'down') {
            date = date + columns;
        } else if (key === 'pageup' || key === 'pagedown') {
            date += (key === 'pageup' ? -1 : 1) * range;
        } else if (key === 'home') {
            date = getStartingYear(this.activeDate.getFullYear());
        } else if (key === 'end') {
            date = getStartingYear(this.activeDate.getFullYear()) + range - 1;
        }
        this.activeDate.setFullYear(date);
    };
}])

.directive('uibDatepicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';
        },
        scope: {
            datepickerOptions: '=?'
        },
        require: ['uibDatepicker', '^ngModel'],
        restrict: 'A',
        controller: 'UibDatepickerController',
        controllerAs: 'datepicker',
        link: function (scope, element, attrs, ctrls) {
            var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            datepickerCtrl.init(ngModelCtrl);
        }
    };
})

.directive('uibDaypicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/day.html';
        },
        require: ['^uibDatepicker', 'uibDaypicker'],
        restrict: 'A',
        controller: 'UibDaypickerController',
        link: function (scope, element, attrs, ctrls) {
            var datepickerCtrl = ctrls[0],
              daypickerCtrl = ctrls[1];

            daypickerCtrl.init(datepickerCtrl);
        }
    };
})

.directive('uibMonthpicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/month.html';
        },
        require: ['^uibDatepicker', 'uibMonthpicker'],
        restrict: 'A',
        controller: 'UibMonthpickerController',
        link: function (scope, element, attrs, ctrls) {
            var datepickerCtrl = ctrls[0],
              monthpickerCtrl = ctrls[1];

            monthpickerCtrl.init(datepickerCtrl);
        }
    };
})

.directive('uibYearpicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/year.html';
        },
        require: ['^uibDatepicker', 'uibYearpicker'],
        restrict: 'A',
        controller: 'UibYearpickerController',
        link: function (scope, element, attrs, ctrls) {
            var ctrl = ctrls[0];
            angular.extend(ctrl, ctrls[1]);
            ctrl.yearpickerInit();

            ctrl.refreshView();
        }
    };
});

angular.module('ui.bootstrap.position', [])

/**
 * A set of utility methods for working with the DOM.
 * It is meant to be used where we need to absolute-position elements in
 * relation to another element (this is the case for tooltips, popovers,
 * typeahead suggestions etc.).
 */
  .factory('$uibPosition', ['$document', '$window', function ($document, $window) {
      /**
       * Used by scrollbarWidth() function to cache scrollbar's width.
       * Do not access this variable directly, use scrollbarWidth() instead.
       */
      var SCROLLBAR_WIDTH;
      /**
       * scrollbar on body and html element in IE and Edge overlay
       * content and should be considered 0 width.
       */
      var BODY_SCROLLBAR_WIDTH;
      var OVERFLOW_REGEX = {
          normal: /(auto|scroll)/,
          hidden: /(auto|scroll|hidden)/
      };
      var PLACEMENT_REGEX = {
          auto: /\s?auto?\s?/i,
          primary: /^(top|bottom|left|right)$/,
          secondary: /^(top|bottom|left|right|center)$/,
          vertical: /^(top|bottom)$/
      };
      var BODY_REGEX = /(HTML|BODY)/;

      return {

          /**
           * Provides a raw DOM element from a jQuery/jQLite element.
           *
           * @param {element} elem - The element to convert.
           *
           * @returns {element} A HTML element.
           */
          getRawNode: function (elem) {
              return elem.nodeName ? elem : elem[0] || elem;
          },

          /**
           * Provides a parsed number for a style property.  Strips
           * units and casts invalid numbers to 0.
           *
           * @param {string} value - The style value to parse.
           *
           * @returns {number} A valid number.
           */
          parseStyle: function (value) {
              value = parseFloat(value);
              return isFinite(value) ? value : 0;
          },

          /**
           * Provides the closest positioned ancestor.
           *
           * @param {element} element - The element to get the offest parent for.
           *
           * @returns {element} The closest positioned ancestor.
           */
          offsetParent: function (elem) {
              elem = this.getRawNode(elem);

              var offsetParent = elem.offsetParent || $document[0].documentElement;

              function isStaticPositioned(el) {
                  return ($window.getComputedStyle(el).position || 'static') === 'static';
              }

              while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {
                  offsetParent = offsetParent.offsetParent;
              }

              return offsetParent || $document[0].documentElement;
          },

          /**
           * Provides the scrollbar width, concept from TWBS measureScrollbar()
           * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js
           * In IE and Edge, scollbar on body and html element overlay and should
           * return a width of 0.
           *
           * @returns {number} The width of the browser scollbar.
           */
          scrollbarWidth: function (isBody) {
              if (isBody) {
                  if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {
                      var bodyElem = $document.find('body');
                      bodyElem.addClass('uib-position-body-scrollbar-measure');
                      BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;
                      BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;
                      bodyElem.removeClass('uib-position-body-scrollbar-measure');
                  }
                  return BODY_SCROLLBAR_WIDTH;
              }

              if (angular.isUndefined(SCROLLBAR_WIDTH)) {
                  var scrollElem = angular.element('<div class="uib-position-scrollbar-measure"></div>');
                  $document.find('body').append(scrollElem);
                  SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;
                  SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;
                  scrollElem.remove();
              }

              return SCROLLBAR_WIDTH;
          },

          /**
           * Provides the padding required on an element to replace the scrollbar.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**scrollbarWidth**: the width of the scrollbar</li>
           *     <li>**widthOverflow**: whether the the width is overflowing</li>
           *     <li>**right**: the amount of right padding on the element needed to replace the scrollbar</li>
           *     <li>**rightOriginal**: the amount of right padding currently on the element</li>
           *     <li>**heightOverflow**: whether the the height is overflowing</li>
           *     <li>**bottom**: the amount of bottom padding on the element needed to replace the scrollbar</li>
           *     <li>**bottomOriginal**: the amount of bottom padding currently on the element</li>
           *   </ul>
           */
          scrollbarPadding: function (elem) {
              elem = this.getRawNode(elem);

              var elemStyle = $window.getComputedStyle(elem);
              var paddingRight = this.parseStyle(elemStyle.paddingRight);
              var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
              var scrollParent = this.scrollParent(elem, false, true);
              var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));

              return {
                  scrollbarWidth: scrollbarWidth,
                  widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
                  right: paddingRight + scrollbarWidth,
                  originalRight: paddingRight,
                  heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
                  bottom: paddingBottom + scrollbarWidth,
                  originalBottom: paddingBottom
              };
          },

          /**
           * Checks to see if the element is scrollable.
           *
           * @param {element} elem - The element to check.
           * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
           *   default is false.
           *
           * @returns {boolean} Whether the element is scrollable.
           */
          isScrollable: function (elem, includeHidden) {
              elem = this.getRawNode(elem);

              var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
              var elemStyle = $window.getComputedStyle(elem);
              return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
          },

          /**
           * Provides the closest scrollable ancestor.
           * A port of the jQuery UI scrollParent method:
           * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
           *
           * @param {element} elem - The element to find the scroll parent of.
           * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
           *   default is false.
           * @param {boolean=} [includeSelf=false] - Should the element being passed be
           * included in the scrollable llokup.
           *
           * @returns {element} A HTML element.
           */
          scrollParent: function (elem, includeHidden, includeSelf) {
              elem = this.getRawNode(elem);

              var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
              var documentEl = $document[0].documentElement;
              var elemStyle = $window.getComputedStyle(elem);
              if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
                  return elem;
              }
              var excludeStatic = elemStyle.position === 'absolute';
              var scrollParent = elem.parentElement || documentEl;

              if (scrollParent === documentEl || elemStyle.position === 'fixed') {
                  return documentEl;
              }

              while (scrollParent.parentElement && scrollParent !== documentEl) {
                  var spStyle = $window.getComputedStyle(scrollParent);
                  if (excludeStatic && spStyle.position !== 'static') {
                      excludeStatic = false;
                  }

                  if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
                      break;
                  }
                  scrollParent = scrollParent.parentElement;
              }

              return scrollParent;
          },

          /**
           * Provides read-only equivalent of jQuery's position function:
           * http://api.jquery.com/position/ - distance to closest positioned
           * ancestor.  Does not account for margins by default like jQuery position.
           *
           * @param {element} elem - The element to caclulate the position on.
           * @param {boolean=} [includeMargins=false] - Should margins be accounted
           * for, default is false.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**width**: the width of the element</li>
           *     <li>**height**: the height of the element</li>
           *     <li>**top**: distance to top edge of offset parent</li>
           *     <li>**left**: distance to left edge of offset parent</li>
           *   </ul>
           */
          position: function (elem, includeMagins) {
              elem = this.getRawNode(elem);

              var elemOffset = this.offset(elem);
              if (includeMagins) {
                  var elemStyle = $window.getComputedStyle(elem);
                  elemOffset.top -= this.parseStyle(elemStyle.marginTop);
                  elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
              }
              var parent = this.offsetParent(elem);
              var parentOffset = { top: 0, left: 0 };

              if (parent !== $document[0].documentElement) {
                  parentOffset = this.offset(parent);
                  parentOffset.top += parent.clientTop - parent.scrollTop;
                  parentOffset.left += parent.clientLeft - parent.scrollLeft;
              }

              return {
                  width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
                  height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
                  top: Math.round(elemOffset.top - parentOffset.top),
                  left: Math.round(elemOffset.left - parentOffset.left)
              };
          },

          /**
           * Provides read-only equivalent of jQuery's offset function:
           * http://api.jquery.com/offset/ - distance to viewport.  Does
           * not account for borders, margins, or padding on the body
           * element.
           *
           * @param {element} elem - The element to calculate the offset on.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**width**: the width of the element</li>
           *     <li>**height**: the height of the element</li>
           *     <li>**top**: distance to top edge of viewport</li>
           *     <li>**right**: distance to bottom edge of viewport</li>
           *   </ul>
           */
          offset: function (elem) {
              elem = this.getRawNode(elem);

              var elemBCR = elem.getBoundingClientRect();
              return {
                  width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
                  height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
                  top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
                  left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
              };
          },

          /**
           * Provides offset distance to the closest scrollable ancestor
           * or viewport.  Accounts for border and scrollbar width.
           *
           * Right and bottom dimensions represent the distance to the
           * respective edge of the viewport element.  If the element
           * edge extends beyond the viewport, a negative value will be
           * reported.
           *
           * @param {element} elem - The element to get the viewport offset for.
           * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
           * of the first scrollable element, default is false.
           * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
           * be accounted for, default is true.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**top**: distance to the top content edge of viewport element</li>
           *     <li>**bottom**: distance to the bottom content edge of viewport element</li>
           *     <li>**left**: distance to the left content edge of viewport element</li>
           *     <li>**right**: distance to the right content edge of viewport element</li>
           *   </ul>
           */
          viewportOffset: function (elem, useDocument, includePadding) {
              elem = this.getRawNode(elem);
              includePadding = includePadding !== false ? true : false;

              var elemBCR = elem.getBoundingClientRect();
              var offsetBCR = { top: 0, left: 0, bottom: 0, right: 0 };

              var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
              var offsetParentBCR = offsetParent.getBoundingClientRect();

              offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
              offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
              if (offsetParent === $document[0].documentElement) {
                  offsetBCR.top += $window.pageYOffset;
                  offsetBCR.left += $window.pageXOffset;
              }
              offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
              offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;

              if (includePadding) {
                  var offsetParentStyle = $window.getComputedStyle(offsetParent);
                  offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
                  offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
                  offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
                  offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
              }

              return {
                  top: Math.round(elemBCR.top - offsetBCR.top),
                  bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
                  left: Math.round(elemBCR.left - offsetBCR.left),
                  right: Math.round(offsetBCR.right - elemBCR.right)
              };
          },

          /**
           * Provides an array of placement values parsed from a placement string.
           * Along with the 'auto' indicator, supported placement strings are:
           *   <ul>
           *     <li>top: element on top, horizontally centered on host element.</li>
           *     <li>top-left: element on top, left edge aligned with host element left edge.</li>
           *     <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>
           *     <li>bottom: element on bottom, horizontally centered on host element.</li>
           *     <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>
           *     <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>
           *     <li>left: element on left, vertically centered on host element.</li>
           *     <li>left-top: element on left, top edge aligned with host element top edge.</li>
           *     <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>
           *     <li>right: element on right, vertically centered on host element.</li>
           *     <li>right-top: element on right, top edge aligned with host element top edge.</li>
           *     <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>
           *   </ul>
           * A placement string with an 'auto' indicator is expected to be
           * space separated from the placement, i.e: 'auto bottom-left'  If
           * the primary and secondary placement values do not match 'top,
           * bottom, left, right' then 'top' will be the primary placement and
           * 'center' will be the secondary placement.  If 'auto' is passed, true
           * will be returned as the 3rd value of the array.
           *
           * @param {string} placement - The placement string to parse.
           *
           * @returns {array} An array with the following values
           * <ul>
           *   <li>**[0]**: The primary placement.</li>
           *   <li>**[1]**: The secondary placement.</li>
           *   <li>**[2]**: If auto is passed: true, else undefined.</li>
           * </ul>
           */
          parsePlacement: function (placement) {
              var autoPlace = PLACEMENT_REGEX.auto.test(placement);
              if (autoPlace) {
                  placement = placement.replace(PLACEMENT_REGEX.auto, '');
              }

              placement = placement.split('-');

              placement[0] = placement[0] || 'top';
              if (!PLACEMENT_REGEX.primary.test(placement[0])) {
                  placement[0] = 'top';
              }

              placement[1] = placement[1] || 'center';
              if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
                  placement[1] = 'center';
              }

              if (autoPlace) {
                  placement[2] = true;
              } else {
                  placement[2] = false;
              }

              return placement;
          },

          /**
           * Provides coordinates for an element to be positioned relative to
           * another element.  Passing 'auto' as part of the placement parameter
           * will enable smart placement - where the element fits. i.e:
           * 'auto left-top' will check to see if there is enough space to the left
           * of the hostElem to fit the targetElem, if not place right (same for secondary
           * top placement).  Available space is calculated using the viewportOffset
           * function.
           *
           * @param {element} hostElem - The element to position against.
           * @param {element} targetElem - The element to position.
           * @param {string=} [placement=top] - The placement for the targetElem,
           *   default is 'top'. 'center' is assumed as secondary placement for
           *   'top', 'left', 'right', and 'bottom' placements.  Available placements are:
           *   <ul>
           *     <li>top</li>
           *     <li>top-right</li>
           *     <li>top-left</li>
           *     <li>bottom</li>
           *     <li>bottom-left</li>
           *     <li>bottom-right</li>
           *     <li>left</li>
           *     <li>left-top</li>
           *     <li>left-bottom</li>
           *     <li>right</li>
           *     <li>right-top</li>
           *     <li>right-bottom</li>
           *   </ul>
           * @param {boolean=} [appendToBody=false] - Should the top and left values returned
           *   be calculated from the body element, default is false.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**top**: Value for targetElem top.</li>
           *     <li>**left**: Value for targetElem left.</li>
           *     <li>**placement**: The resolved placement.</li>
           *   </ul>
           */
          positionElements: function (hostElem, targetElem, placement, appendToBody) {
              hostElem = this.getRawNode(hostElem);
              targetElem = this.getRawNode(targetElem);

              // need to read from prop to support tests.
              var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
              var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');

              placement = this.parsePlacement(placement);

              var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
              var targetElemPos = { top: 0, left: 0, placement: '' };

              if (placement[2]) {
                  var viewportOffset = this.viewportOffset(hostElem, appendToBody);

                  var targetElemStyle = $window.getComputedStyle(targetElem);
                  var adjustedSize = {
                      width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
                      height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
                  };

                  placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
                                 placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
                                 placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
                                 placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
                                 placement[0];

                  placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
                                 placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
                                 placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
                                 placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
                                 placement[1];

                  if (placement[1] === 'center') {
                      if (PLACEMENT_REGEX.vertical.test(placement[0])) {
                          var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
                          if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
                              placement[1] = 'left';
                          } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
                              placement[1] = 'right';
                          }
                      } else {
                          var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
                          if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
                              placement[1] = 'top';
                          } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
                              placement[1] = 'bottom';
                          }
                      }
                  }
              }

              switch (placement[0]) {
                  case 'top':
                      targetElemPos.top = hostElemPos.top - targetHeight;
                      break;
                  case 'bottom':
                      targetElemPos.top = hostElemPos.top + hostElemPos.height;
                      break;
                  case 'left':
                      targetElemPos.left = hostElemPos.left - targetWidth;
                      break;
                  case 'right':
                      targetElemPos.left = hostElemPos.left + hostElemPos.width;
                      break;
              }

              switch (placement[1]) {
                  case 'top':
                      targetElemPos.top = hostElemPos.top;
                      break;
                  case 'bottom':
                      targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
                      break;
                  case 'left':
                      targetElemPos.left = hostElemPos.left;
                      break;
                  case 'right':
                      targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
                      break;
                  case 'center':
                      if (PLACEMENT_REGEX.vertical.test(placement[0])) {
                          targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
                      } else {
                          targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
                      }
                      break;
              }

              targetElemPos.top = Math.round(targetElemPos.top);
              targetElemPos.left = Math.round(targetElemPos.left);
              targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];

              return targetElemPos;
          },

          /**
           * Provides a way to adjust the top positioning after first
           * render to correctly align element to top after content
           * rendering causes resized element height
           *
           * @param {array} placementClasses - The array of strings of classes
           * element should have.
           * @param {object} containerPosition - The object with container
           * position information
           * @param {number} initialHeight - The initial height for the elem.
           * @param {number} currentHeight - The current height for the elem.
           */
          adjustTop: function (placementClasses, containerPosition, initialHeight, currentHeight) {
              if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) {
                  return {
                      top: containerPosition.top - currentHeight + 'px'
                  };
              }
          },

          /**
           * Provides a way for positioning tooltip & dropdown
           * arrows when using placement options beyond the standard
           * left, right, top, or bottom.
           *
           * @param {element} elem - The tooltip/dropdown element.
           * @param {string} placement - The placement for the elem.
           */
          positionArrow: function (elem, placement) {
              elem = this.getRawNode(elem);

              var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
              if (!innerElem) {
                  return;
              }

              var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');

              var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
              if (!arrowElem) {
                  return;
              }

              var arrowCss = {
                  top: '',
                  bottom: '',
                  left: '',
                  right: ''
              };

              placement = this.parsePlacement(placement);
              if (placement[1] === 'center') {
                  // no adjustment necessary - just reset styles
                  angular.element(arrowElem).css(arrowCss);
                  return;
              }

              var borderProp = 'border-' + placement[0] + '-width';
              var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];

              var borderRadiusProp = 'border-';
              if (PLACEMENT_REGEX.vertical.test(placement[0])) {
                  borderRadiusProp += placement[0] + '-' + placement[1];
              } else {
                  borderRadiusProp += placement[1] + '-' + placement[0];
              }
              borderRadiusProp += '-radius';
              var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];

              switch (placement[0]) {
                  case 'top':
                      arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
                      break;
                  case 'bottom':
                      arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
                      break;
                  case 'left':
                      arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
                      break;
                  case 'right':
                      arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
                      break;
              }

              arrowCss[placement[1]] = borderRadius;

              angular.element(arrowElem).css(arrowCss);
          }
      };
  }]);

angular.module('ui.bootstrap.datepickerPopup', ['ui.bootstrap.datepicker', 'ui.bootstrap.position'])

.value('$datepickerPopupLiteralWarning', true)

.constant('uibDatepickerPopupConfig', {
    altInputFormats: [],
    appendToBody: false,
    clearText: 'Clear',
    closeOnDateSelection: true,
    closeText: 'Done',
    currentText: 'Today',
    datepickerPopup: 'yyyy-MM-dd',
    datepickerPopupTemplateUrl: 'uib/template/datepickerPopup/popup.html',
    datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',
    html5Types: {
        date: 'yyyy-MM-dd',
        'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
        'month': 'yyyy-MM'
    },
    onOpenFocus: true,
    showButtonBar: true,
    placement: 'auto bottom-left'
})

.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
function ($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
    var cache = {},
      isHtml5DateInput = false;
    var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
      datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
      ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];

    this.init = function (_ngModel_) {
        ngModel = _ngModel_;
        ngModelOptions = angular.isObject(_ngModel_.$options) ?
          _ngModel_.$options :
      {
          timezone: null
      };
        closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
          $scope.$parent.$eval($attrs.closeOnDateSelection) :
          datepickerPopupConfig.closeOnDateSelection;
        appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
          $scope.$parent.$eval($attrs.datepickerAppendToBody) :
          datepickerPopupConfig.appendToBody;
        onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
          $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
        datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
          $attrs.datepickerPopupTemplateUrl :
          datepickerPopupConfig.datepickerPopupTemplateUrl;
        datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
          $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
        altInputFormats = angular.isDefined($attrs.altInputFormats) ?
          $scope.$parent.$eval($attrs.altInputFormats) :
          datepickerPopupConfig.altInputFormats;

        $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
          $scope.$parent.$eval($attrs.showButtonBar) :
          datepickerPopupConfig.showButtonBar;

        if (datepickerPopupConfig.html5Types[$attrs.type]) {
            dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
            isHtml5DateInput = true;
        } else {
            dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
            $attrs.$observe('uibDatepickerPopup', function (value, oldValue) {
                var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
                // Invalidate the $modelValue to ensure that formatters re-run
                // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
                if (newDateFormat !== dateFormat) {
                    dateFormat = newDateFormat;
                    ngModel.$modelValue = null;

                    if (!dateFormat) {
                        throw new Error('uibDatepickerPopup must have a date format specified.');
                    }
                }
            });
        }

        if (!dateFormat) {
            throw new Error('uibDatepickerPopup must have a date format specified.');
        }

        if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
            throw new Error('HTML5 date input types do not support custom formats.');
        }

        // popup element used to display calendar
        popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');

        popupEl.attr({
            'ng-model': 'date',
            'ng-change': 'dateSelection(date)',
            'template-url': datepickerPopupTemplateUrl
        });

        // datepicker element
        datepickerEl = angular.element(popupEl.children()[0]);
        datepickerEl.attr('template-url', datepickerTemplateUrl);

        if (!$scope.datepickerOptions) {
            $scope.datepickerOptions = {};
        }

        if (isHtml5DateInput) {
            if ($attrs.type === 'month') {
                $scope.datepickerOptions.datepickerMode = 'month';
                $scope.datepickerOptions.minMode = 'month';
            }
        }

        datepickerEl.attr('datepicker-options', 'datepickerOptions');

        if (!isHtml5DateInput) {
            // Internal API to maintain the correct ng-invalid-[key] class
            ngModel.$$parserName = 'date';
            ngModel.$validators.date = validator;
            ngModel.$parsers.unshift(parseDate);
            ngModel.$formatters.push(function (value) {
                if (ngModel.$isEmpty(value)) {
                    $scope.date = value;
                    return value;
                }

                if (angular.isNumber(value)) {
                    value = new Date(value);
                }

                $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);

                return dateParser.filter($scope.date, dateFormat);
            });
        } else {
            ngModel.$formatters.push(function (value) {
                $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);
                return value;
            });
        }

        // Detect changes in the view from the text box
        ngModel.$viewChangeListeners.push(function () {
            $scope.date = parseDateString(ngModel.$viewValue);
        });

        $element.on('keydown', inputKeydownBind);

        $popup = $compile(popupEl)($scope);
        // Prevent jQuery cache memory leak (template is now redundant after linking)
        popupEl.remove();

        if (appendToBody) {
            $document.find('body').append($popup);
        } else {
            $element.after($popup);
        }

        $scope.$on('$destroy', function () {
            if ($scope.isOpen === true) {
                if (!$rootScope.$$phase) {
                    $scope.$apply(function () {
                        $scope.isOpen = false;
                    });
                }
            }

            $popup.remove();
            $element.off('keydown', inputKeydownBind);
            $document.off('click', documentClickBind);
            if (scrollParentEl) {
                scrollParentEl.off('scroll', positionPopup);
            }
            angular.element($window).off('resize', positionPopup);

            //Clear all watch listeners on destroy
            while (watchListeners.length) {
                watchListeners.shift()();
            }
        });
    };

    $scope.getText = function (key) {
        return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
    };

    $scope.isDisabled = function (date) {
        if (date === 'today') {
            date = dateParser.fromTimezone(new Date(), ngModelOptions.timezone);
        }

        var dates = {};
        angular.forEach(['minDate', 'maxDate'], function (key) {
            if (!$scope.datepickerOptions[key]) {
                dates[key] = null;
            } else if (angular.isDate($scope.datepickerOptions[key])) {
                dates[key] = new Date($scope.datepickerOptions[key]);
            } else {
                if ($datepickerPopupLiteralWarning) {
                    $log.warn('Literal date support has been deprecated, please switch to date object usage');
                }

                dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
            }
        });

        return $scope.datepickerOptions &&
          dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
          dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
    };

    $scope.compare = function (date1, date2) {
        return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
    };

    // Inner change
    $scope.dateSelection = function (dt) {
        $scope.date = dt;
        var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
        $element.val(date);
        ngModel.$setViewValue(date);

        if (closeOnDateSelection) {
            $scope.isOpen = false;
            $element[0].focus();
        }
    };

    $scope.keydown = function (evt) {
        if (evt.which === 27) {
            evt.stopPropagation();
            $scope.isOpen = false;
            $element[0].focus();
        }
    };

    $scope.select = function (date, evt) {
        evt.stopPropagation();

        if (date === 'today') {
            var today = new Date();
            if (angular.isDate($scope.date)) {
                date = new Date($scope.date);
                date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
            } else {
                date = dateParser.fromTimezone(today, ngModelOptions.timezone);
                date.setHours(0, 0, 0, 0);
            }
        }
        $scope.dateSelection(date);
    };

    $scope.close = function (evt) {
        evt.stopPropagation();

        $scope.isOpen = false;
        $element[0].focus();
    };

    $scope.disabled = angular.isDefined($attrs.disabled) || false;
    if ($attrs.ngDisabled) {
        watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function (disabled) {
            $scope.disabled = disabled;
        }));
    }

    $scope.$watch('isOpen', function (value) {
        if (value) {
            if (!$scope.disabled) {
                $timeout(function () {
                    positionPopup();

                    if (onOpenFocus) {
                        $scope.$broadcast('uib:datepicker.focus');
                    }

                    $document.on('click', documentClickBind);

                    var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
                    if (appendToBody || $position.parsePlacement(placement)[2]) {
                        scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
                        if (scrollParentEl) {
                            scrollParentEl.on('scroll', positionPopup);
                        }
                    } else {
                        scrollParentEl = null;
                    }

                    angular.element($window).on('resize', positionPopup);
                }, 0, false);
            } else {
                $scope.isOpen = false;
            }
        } else {
            $document.off('click', documentClickBind);
            if (scrollParentEl) {
                scrollParentEl.off('scroll', positionPopup);
            }
            angular.element($window).off('resize', positionPopup);
        }
    });

    function cameltoDash(string) {
        return string.replace(/([A-Z])/g, function ($1) { return '-' + $1.toLowerCase(); });
    }

    function parseDateString(viewValue) {
        var date = dateParser.parse(viewValue, dateFormat, $scope.date);
        if (isNaN(date)) {
            for (var i = 0; i < altInputFormats.length; i++) {
                date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
                if (!isNaN(date)) {
                    return date;
                }
            }
        }
        return date;
    }

    function parseDate(viewValue) {
        if (angular.isNumber(viewValue)) {
            // presumably timestamp to date object
            viewValue = new Date(viewValue);
        }

        if (!viewValue) {
            return null;
        }

        if (angular.isDate(viewValue) && !isNaN(viewValue)) {
            return viewValue;
        }

        if (angular.isString(viewValue)) {
            var date = parseDateString(viewValue);
            if (!isNaN(date)) {
                return dateParser.fromTimezone(date, ngModelOptions.timezone);
            }
        }

        return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined;
    }

    function validator(modelValue, viewValue) {
        var value = modelValue || viewValue;

        if (!$attrs.ngRequired && !value) {
            return true;
        }

        if (angular.isNumber(value)) {
            value = new Date(value);
        }

        if (!value) {
            return true;
        }

        if (angular.isDate(value) && !isNaN(value)) {
            return true;
        }

        if (angular.isString(value)) {
            return !isNaN(parseDateString(value));
        }

        return false;
    }

    function documentClickBind(event) {
        if (!$scope.isOpen && $scope.disabled) {
            return;
        }

        var popup = $popup[0];
        var dpContainsTarget = $element[0].contains(event.target);
        // The popup node may not be an element node
        // In some browsers (IE) only element nodes have the 'contains' function
        var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
        if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
            $scope.$apply(function () {
                $scope.isOpen = false;
            });
        }
    }

    function inputKeydownBind(evt) {
        if (evt.which === 27 && $scope.isOpen) {
            evt.preventDefault();
            evt.stopPropagation();
            $scope.$apply(function () {
                $scope.isOpen = false;
            });
            $element[0].focus();
        } else if (evt.which === 40 && !$scope.isOpen) {
            evt.preventDefault();
            evt.stopPropagation();
            $scope.$apply(function () {
                $scope.isOpen = true;
            });
        }
    }

    function positionPopup() {
        if ($scope.isOpen) {
            var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
            var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
            var position = $position.positionElements($element, dpElement, placement, appendToBody);
            dpElement.css({ top: position.top + 'px', left: position.left + 'px' });
            if (dpElement.hasClass('uib-position-measure')) {
                dpElement.removeClass('uib-position-measure');
            }
        }
    }

    $scope.$on('uib:datepicker.mode', function () {
        $timeout(positionPopup, 0, false);
    });
}])

.directive('uibDatepickerPopup', function () {
    return {
        require: ['ngModel', 'uibDatepickerPopup'],
        controller: 'UibDatepickerPopupController',
        scope: {
            datepickerOptions: '=?',
            isOpen: '=?',
            currentText: '@',
            clearText: '@',
            closeText: '@'
        },
        link: function (scope, element, attrs, ctrls) {
            var ngModel = ctrls[0],
              ctrl = ctrls[1];

            ctrl.init(ngModel);
        }
    };
})

.directive('uibDatepickerPopupWrap', function () {
    return {
        restrict: 'A',
        transclude: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';
        }
    };
});

angular.module('ui.bootstrap.debounce', [])
/**
 * A helper, internal service that debounces a function
 */
  .factory('$$debounce', ['$timeout', function ($timeout) {
      return function (callback, debounceTime) {
          var timeoutPromise;

          return function () {
              var self = this;
              var args = Array.prototype.slice.call(arguments);
              if (timeoutPromise) {
                  $timeout.cancel(timeoutPromise);
              }

              timeoutPromise = $timeout(function () {
                  callback.apply(self, args);
              }, debounceTime);
          };
      };
  }]);

angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])

.constant('uibDropdownConfig', {
    appendToOpenClass: 'uib-dropdown-open',
    openClass: 'open'
})

.service('uibDropdownService', ['$document', '$rootScope', function ($document, $rootScope) {
    var openScope = null;

    this.open = function (dropdownScope, element) {
        if (!openScope) {
            $document.on('click', closeDropdown);
        }

        if (openScope && openScope !== dropdownScope) {
            openScope.isOpen = false;
        }

        openScope = dropdownScope;
    };

    this.close = function (dropdownScope, element) {
        if (openScope === dropdownScope) {
            $document.off('click', closeDropdown);
            $document.off('keydown', this.keybindFilter);
            openScope = null;
        }
    };

    var closeDropdown = function (evt) {
        // This method may still be called during the same mouse event that
        // unbound this event handler. So check openScope before proceeding.
        if (!openScope) { return; }

        if (evt && openScope.getAutoClose() === 'disabled') { return; }

        if (evt && evt.which === 3) { return; }

        var toggleElement = openScope.getToggleElement();
        if (evt && toggleElement && toggleElement[0].contains(evt.target)) {
            return;
        }

        var dropdownElement = openScope.getDropdownElement();
        if (evt && openScope.getAutoClose() === 'outsideClick' &&
          dropdownElement && dropdownElement[0].contains(evt.target)) {
            return;
        }

        openScope.focusToggleElement();
        openScope.isOpen = false;

        if (!$rootScope.$$phase) {
            openScope.$apply();
        }
    };

    this.keybindFilter = function (evt) {
        if (!openScope) {
            // see this.close as ESC could have been pressed which kills the scope so we can not proceed
            return;
        }

        var dropdownElement = openScope.getDropdownElement();
        var toggleElement = openScope.getToggleElement();
        var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);
        var toggleElementTargeted = toggleElement && toggleElement[0].contains(evt.target);
        if (evt.which === 27) {
            evt.stopPropagation();
            openScope.focusToggleElement();
            closeDropdown();
        } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen && (dropdownElementTargeted || toggleElementTargeted)) {
            evt.preventDefault();
            evt.stopPropagation();
            openScope.focusDropdownEntry(evt.which);
        }
    };
}])

.controller('UibDropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', function ($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest) {
    var self = this,
      scope = $scope.$new(), // create a child scope so we are not polluting original one
      templateScope,
      appendToOpenClass = dropdownConfig.appendToOpenClass,
      openClass = dropdownConfig.openClass,
      getIsOpen,
      setIsOpen = angular.noop,
      toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
      appendToBody = false,
      appendTo = null,
      keynavEnabled = false,
      selectedOption = null,
      body = $document.find('body');

    $element.addClass('dropdown');

    this.init = function () {
        if ($attrs.isOpen) {
            getIsOpen = $parse($attrs.isOpen);
            setIsOpen = getIsOpen.assign;

            $scope.$watch(getIsOpen, function (value) {
                scope.isOpen = !!value;
            });
        }

        if (angular.isDefined($attrs.dropdownAppendTo)) {
            var appendToEl = $parse($attrs.dropdownAppendTo)(scope);
            if (appendToEl) {
                appendTo = angular.element(appendToEl);
            }
        }

        appendToBody = angular.isDefined($attrs.dropdownAppendToBody);
        keynavEnabled = angular.isDefined($attrs.keyboardNav);

        if (appendToBody && !appendTo) {
            appendTo = body;
        }

        if (appendTo && self.dropdownMenu) {
            appendTo.append(self.dropdownMenu);
            $element.on('$destroy', function handleDestroyEvent() {
                self.dropdownMenu.remove();
            });
        }
    };

    this.toggle = function (open) {
        scope.isOpen = arguments.length ? !!open : !scope.isOpen;
        if (angular.isFunction(setIsOpen)) {
            setIsOpen(scope, scope.isOpen);
        }

        return scope.isOpen;
    };

    // Allow other directives to watch status
    this.isOpen = function () {
        return scope.isOpen;
    };

    scope.getToggleElement = function () {
        return self.toggleElement;
    };

    scope.getAutoClose = function () {
        return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'
    };

    scope.getElement = function () {
        return $element;
    };

    scope.isKeynavEnabled = function () {
        return keynavEnabled;
    };

    scope.focusDropdownEntry = function (keyCode) {
        var elems = self.dropdownMenu ? //If append to body is used.
          angular.element(self.dropdownMenu).find('a') :
          $element.find('ul').eq(0).find('a');

        switch (keyCode) {
            case 40: {
                if (!angular.isNumber(self.selectedOption)) {
                    self.selectedOption = 0;
                } else {
                    self.selectedOption = self.selectedOption === elems.length - 1 ?
                      self.selectedOption :
                      self.selectedOption + 1;
                }
                break;
            }
            case 38: {
                if (!angular.isNumber(self.selectedOption)) {
                    self.selectedOption = elems.length - 1;
                } else {
                    self.selectedOption = self.selectedOption === 0 ?
                      0 : self.selectedOption - 1;
                }
                break;
            }
        }
        elems[self.selectedOption].focus();
    };

    scope.getDropdownElement = function () {
        return self.dropdownMenu;
    };

    scope.focusToggleElement = function () {
        if (self.toggleElement) {
            self.toggleElement[0].focus();
        }
    };

    scope.$watch('isOpen', function (isOpen, wasOpen) {
        if (appendTo && self.dropdownMenu) {
            var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true),
              css,
              rightalign,
              scrollbarPadding,
              scrollbarWidth = 0;

            css = {
                top: pos.top + 'px',
                display: isOpen ? 'block' : 'none'
            };

            rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');
            if (!rightalign) {
                css.left = pos.left + 'px';
                css.right = 'auto';
            } else {
                css.left = 'auto';
                scrollbarPadding = $position.scrollbarPadding(appendTo);

                if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
                    scrollbarWidth = scrollbarPadding.scrollbarWidth;
                }

                css.right = window.innerWidth - scrollbarWidth -
                  (pos.left + $element.prop('offsetWidth')) + 'px';
            }

            // Need to adjust our positioning to be relative to the appendTo container
            // if it's not the body element
            if (!appendToBody) {
                var appendOffset = $position.offset(appendTo);

                css.top = pos.top - appendOffset.top + 'px';

                if (!rightalign) {
                    css.left = pos.left - appendOffset.left + 'px';
                } else {
                    css.right = window.innerWidth -
                      (pos.left - appendOffset.left + $element.prop('offsetWidth')) + 'px';
                }
            }

            self.dropdownMenu.css(css);
        }

        var openContainer = appendTo ? appendTo : $element;
        var hasOpenClass = openContainer.hasClass(appendTo ? appendToOpenClass : openClass);

        if (hasOpenClass === !isOpen) {
            $animate[isOpen ? 'addClass' : 'removeClass'](openContainer, appendTo ? appendToOpenClass : openClass).then(function () {
                if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
                    toggleInvoker($scope, { open: !!isOpen });
                }
            });
        }

        if (isOpen) {
            if (self.dropdownMenuTemplateUrl) {
                $templateRequest(self.dropdownMenuTemplateUrl).then(function (tplContent) {
                    templateScope = scope.$new();
                    $compile(tplContent.trim())(templateScope, function (dropdownElement) {
                        var newEl = dropdownElement;
                        self.dropdownMenu.replaceWith(newEl);
                        self.dropdownMenu = newEl;
                        $document.on('keydown', uibDropdownService.keybindFilter);
                    });
                });
            } else {
                $document.on('keydown', uibDropdownService.keybindFilter);
            }

            scope.focusToggleElement();
            uibDropdownService.open(scope, $element);
        } else {
            uibDropdownService.close(scope, $element);
            if (self.dropdownMenuTemplateUrl) {
                if (templateScope) {
                    templateScope.$destroy();
                }
                var newEl = angular.element('<ul class="dropdown-menu"></ul>');
                self.dropdownMenu.replaceWith(newEl);
                self.dropdownMenu = newEl;
            }

            self.selectedOption = null;
        }

        if (angular.isFunction(setIsOpen)) {
            setIsOpen($scope, isOpen);
        }
    });
}])

.directive('uibDropdown', function () {
    return {
        controller: 'UibDropdownController',
        link: function (scope, element, attrs, dropdownCtrl) {
            dropdownCtrl.init();
        }
    };
})

.directive('uibDropdownMenu', function () {
    return {
        restrict: 'A',
        require: '?^uibDropdown',
        link: function (scope, element, attrs, dropdownCtrl) {
            if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {
                return;
            }

            element.addClass('dropdown-menu');

            var tplUrl = attrs.templateUrl;
            if (tplUrl) {
                dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;
            }

            if (!dropdownCtrl.dropdownMenu) {
                dropdownCtrl.dropdownMenu = element;
            }
        }
    };
})

.directive('uibDropdownToggle', function () {
    return {
        require: '?^uibDropdown',
        link: function (scope, element, attrs, dropdownCtrl) {
            if (!dropdownCtrl) {
                return;
            }

            element.addClass('dropdown-toggle');

            dropdownCtrl.toggleElement = element;

            var toggleDropdown = function (event) {
                event.preventDefault();

                if (!element.hasClass('disabled') && !attrs.disabled) {
                    scope.$apply(function () {
                        dropdownCtrl.toggle();
                    });
                }
            };

            element.bind('click', toggleDropdown);

            // WAI-ARIA
            element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
            scope.$watch(dropdownCtrl.isOpen, function (isOpen) {
                element.attr('aria-expanded', !!isOpen);
            });

            scope.$on('$destroy', function () {
                element.unbind('click', toggleDropdown);
            });
        }
    };
});

angular.module('ui.bootstrap.stackedMap', [])
/**
 * A helper, internal data structure that acts as a map but also allows getting / removing
 * elements in the LIFO order
 */
  .factory('$$stackedMap', function () {
      return {
          createNew: function () {
              var stack = [];

              return {
                  add: function (key, value) {
                      stack.push({
                          key: key,
                          value: value
                      });
                  },
                  get: function (key) {
                      for (var i = 0; i < stack.length; i++) {
                          if (key === stack[i].key) {
                              return stack[i];
                          }
                      }
                  },
                  keys: function () {
                      var keys = [];
                      for (var i = 0; i < stack.length; i++) {
                          keys.push(stack[i].key);
                      }
                      return keys;
                  },
                  top: function () {
                      return stack[stack.length - 1];
                  },
                  remove: function (key) {
                      var idx = -1;
                      for (var i = 0; i < stack.length; i++) {
                          if (key === stack[i].key) {
                              idx = i;
                              break;
                          }
                      }
                      return stack.splice(idx, 1)[0];
                  },
                  removeTop: function () {
                      return stack.pop();
                  },
                  length: function () {
                      return stack.length;
                  }
              };
          }
      };
  });
angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.position'])
/**
 * A helper, internal data structure that stores all references attached to key
 */
  .factory('$$multiMap', function () {
      return {
          createNew: function () {
              var map = {};

              return {
                  entries: function () {
                      return Object.keys(map).map(function (key) {
                          return {
                              key: key,
                              value: map[key]
                          };
                      });
                  },
                  get: function (key) {
                      return map[key];
                  },
                  hasKey: function (key) {
                      return !!map[key];
                  },
                  keys: function () {
                      return Object.keys(map);
                  },
                  put: function (key, value) {
                      if (!map[key]) {
                          map[key] = [];
                      }

                      map[key].push(value);
                  },
                  remove: function (key, value) {
                      var values = map[key];

                      if (!values) {
                          return;
                      }

                      var idx = values.indexOf(value);

                      if (idx !== -1) {
                          values.splice(idx, 1);
                      }

                      if (!values.length) {
                          delete map[key];
                      }
                  }
              };
          }
      };
  })

/**
 * Pluggable resolve mechanism for the modal resolve resolution
 * Supports UI Router's $resolve service
 */
  .provider('$uibResolve', function () {
      var resolve = this;
      this.resolver = null;

      this.setResolver = function (resolver) {
          this.resolver = resolver;
      };

      this.$get = ['$injector', '$q', function ($injector, $q) {
          var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
          return {
              resolve: function (invocables, locals, parent, self) {
                  if (resolver) {
                      return resolver.resolve(invocables, locals, parent, self);
                  }

                  var promises = [];

                  angular.forEach(invocables, function (value) {
                      if (angular.isFunction(value) || angular.isArray(value)) {
                          promises.push($q.resolve($injector.invoke(value)));
                      } else if (angular.isString(value)) {
                          promises.push($q.resolve($injector.get(value)));
                      } else {
                          promises.push($q.resolve(value));
                      }
                  });

                  return $q.all(promises).then(function (resolves) {
                      var resolveObj = {};
                      var resolveIter = 0;
                      angular.forEach(invocables, function (value, key) {
                          resolveObj[key] = resolves[resolveIter++];
                      });

                      return resolveObj;
                  });
              }
          };
      }];
  })

/**
 * A helper directive for the $modal service. It creates a backdrop element.
 */
  .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
  function ($animate, $injector, $modalStack) {
      return {
          restrict: 'A',
          compile: function (tElement, tAttrs) {
              tElement.addClass(tAttrs.backdropClass);
              return linkFn;
          }
      };

      function linkFn(scope, element, attrs) {
          if (attrs.modalInClass) {
              $animate.addClass(element, attrs.modalInClass);

              scope.$on($modalStack.NOW_CLOSING_EVENT, function (e, setIsAsync) {
                  var done = setIsAsync();
                  if (scope.modalOptions.animation) {
                      $animate.removeClass(element, attrs.modalInClass).then(done);
                  } else {
                      done();
                  }
              });
          }
      }
  }])

  .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',
  function ($modalStack, $q, $animateCss, $document) {
      return {
          scope: {
              index: '@'
          },
          restrict: 'A',
          transclude: true,
          templateUrl: function (tElement, tAttrs) {
              return tAttrs.templateUrl || 'uib/template/modal/window.html';
          },
          link: function (scope, element, attrs) {
              element.addClass(attrs.windowTopClass || '');
              scope.size = attrs.size;

              scope.close = function (evt) {
                  var modal = $modalStack.getTop();
                  if (modal && modal.value.backdrop &&
                    modal.value.backdrop !== 'static' &&
                    evt.target === evt.currentTarget) {
                      evt.preventDefault();
                      evt.stopPropagation();
                      $modalStack.dismiss(modal.key, 'backdrop click');
                  }
              };

              // moved from template to fix issue #2280
              element.on('click', scope.close);

              // This property is only added to the scope for the purpose of detecting when this directive is rendered.
              // We can detect that by using this property in the template associated with this directive and then use
              // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
              scope.$isRendered = true;

              // Deferred object that will be resolved when this modal is rendered.
              var modalRenderDeferObj = $q.defer();
              // Resolve render promise post-digest
              scope.$$postDigest(function () {
                  modalRenderDeferObj.resolve();
              });

              modalRenderDeferObj.promise.then(function () {
                  var animationPromise = null;

                  if (attrs.modalInClass) {
                      animationPromise = $animateCss(element, {
                          addClass: attrs.modalInClass
                      }).start();

                      scope.$on($modalStack.NOW_CLOSING_EVENT, function (e, setIsAsync) {
                          var done = setIsAsync();
                          $animateCss(element, {
                              removeClass: attrs.modalInClass
                          }).start().then(done);
                      });
                  }


                  $q.when(animationPromise).then(function () {
                      // Notify {@link $modalStack} that modal is rendered.
                      var modal = $modalStack.getTop();
                      if (modal) {
                          $modalStack.modalRendered(modal.key);
                      }

                      /**
                       * If something within the freshly-opened modal already has focus (perhaps via a
                       * directive that causes focus) then there's no need to try to focus anything.
                       */
                      if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
                          var inputWithAutofocus = element[0].querySelector('[autofocus]');
                          /**
                           * Auto-focusing of a freshly-opened modal element causes any child elements
                           * with the autofocus attribute to lose focus. This is an issue on touch
                           * based devices which will show and then hide the onscreen keyboard.
                           * Attempts to refocus the autofocus element via JavaScript will not reopen
                           * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
                           * the modal element if the modal does not contain an autofocus element.
                           */
                          if (inputWithAutofocus) {
                              inputWithAutofocus.focus();
                          } else {
                              element[0].focus();
                          }
                      }
                  });
              });
          }
      };
  }])

  .directive('uibModalAnimationClass', function () {
      return {
          compile: function (tElement, tAttrs) {
              if (tAttrs.modalAnimation) {
                  tElement.addClass(tAttrs.uibModalAnimationClass);
              }
          }
      };
  })

  .directive('uibModalTransclude', ['$animate', function ($animate) {
      return {
          link: function (scope, element, attrs, controller, transclude) {
              transclude(scope.$parent, function (clone) {
                  element.empty();
                  $animate.enter(clone, element);
              });
          }
      };
  }])

  .factory('$uibModalStack', ['$animate', '$animateCss', '$document',
    '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
    function ($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {
        var OPENED_MODAL_CLASS = 'modal-open';

        var backdropDomEl, backdropScope;
        var openedWindows = $$stackedMap.createNew();
        var openedClasses = $$multiMap.createNew();
        var $modalStack = {
            NOW_CLOSING_EVENT: 'modal.stack.now-closing'
        };
        var topModalIndex = 0;
        var previousTopOpenedModal = null;
        var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count';

        //Modal focus behavior
        var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
          'button:not([disabled]):not([tabindex=\'-1\']),select:not([disabled]):not([tabindex=\'-1\']), textarea:not([disabled]):not([tabindex=\'-1\']), ' +
          'iframe, object, embed, *[tabindex]:not([tabindex=\'-1\']), *[contenteditable=true]';
        var scrollbarPadding;
        var SNAKE_CASE_REGEXP = /[A-Z]/g;

        // TODO: extract into common dependency with tooltip
        function snake_case(name) {
            var separator = '-';
            return name.replace(SNAKE_CASE_REGEXP, function (letter, pos) {
                return (pos ? separator : '') + letter.toLowerCase();
            });
        }

        function isVisible(element) {
            return !!(element.offsetWidth ||
              element.offsetHeight ||
              element.getClientRects().length);
        }

        function backdropIndex() {
            var topBackdropIndex = -1;
            var opened = openedWindows.keys();
            for (var i = 0; i < opened.length; i++) {
                if (openedWindows.get(opened[i]).value.backdrop) {
                    topBackdropIndex = i;
                }
            }

            // If any backdrop exist, ensure that it's index is always
            // right below the top modal
            if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
                topBackdropIndex = topModalIndex;
            }
            return topBackdropIndex;
        }

        $rootScope.$watch(backdropIndex, function (newBackdropIndex) {
            if (backdropScope) {
                backdropScope.index = newBackdropIndex;
            }
        });

        function removeModalWindow(modalInstance, elementToReceiveFocus) {
            var modalWindow = openedWindows.get(modalInstance).value;
            var appendToElement = modalWindow.appendTo;

            //clean up the stack
            openedWindows.remove(modalInstance);
            previousTopOpenedModal = openedWindows.top();
            if (previousTopOpenedModal) {
                topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
            }

            removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function () {
                var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
                openedClasses.remove(modalBodyClass, modalInstance);
                var areAnyOpen = openedClasses.hasKey(modalBodyClass);
                appendToElement.toggleClass(modalBodyClass, areAnyOpen);
                if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
                    if (scrollbarPadding.originalRight) {
                        appendToElement.css({ paddingRight: scrollbarPadding.originalRight + 'px' });
                    } else {
                        appendToElement.css({ paddingRight: '' });
                    }
                    scrollbarPadding = null;
                }
                toggleTopWindowClass(true);
            }, modalWindow.closedDeferred);
            checkRemoveBackdrop();

            //move focus to specified element if available, or else to body
            if (elementToReceiveFocus && elementToReceiveFocus.focus) {
                elementToReceiveFocus.focus();
            } else if (appendToElement.focus) {
                appendToElement.focus();
            }
        }

        // Add or remove "windowTopClass" from the top window in the stack
        function toggleTopWindowClass(toggleSwitch) {
            var modalWindow;

            if (openedWindows.length() > 0) {
                modalWindow = openedWindows.top().value;
                modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
            }
        }

        function checkRemoveBackdrop() {
            //remove backdrop if no longer needed
            if (backdropDomEl && backdropIndex() === -1) {
                var backdropScopeRef = backdropScope;
                removeAfterAnimate(backdropDomEl, backdropScope, function () {
                    backdropScopeRef = null;
                });
                backdropDomEl = undefined;
                backdropScope = undefined;
            }
        }

        function removeAfterAnimate(domEl, scope, done, closedDeferred) {
            var asyncDeferred;
            var asyncPromise = null;
            var setIsAsync = function () {
                if (!asyncDeferred) {
                    asyncDeferred = $q.defer();
                    asyncPromise = asyncDeferred.promise;
                }

                return function asyncDone() {
                    asyncDeferred.resolve();
                };
            };
            scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);

            // Note that it's intentional that asyncPromise might be null.
            // That's when setIsAsync has not been called during the
            // NOW_CLOSING_EVENT broadcast.
            return $q.when(asyncPromise).then(afterAnimating);

            function afterAnimating() {
                if (afterAnimating.done) {
                    return;
                }
                afterAnimating.done = true;

                $animate.leave(domEl).then(function () {
                    if (done) {
                        done();
                    }

                    domEl.remove();
                    if (closedDeferred) {
                        closedDeferred.resolve();
                    }
                });

                scope.$destroy();
            }
        }

        $document.on('keydown', keydownListener);

        $rootScope.$on('$destroy', function () {
            $document.off('keydown', keydownListener);
        });

        function keydownListener(evt) {
            if (evt.isDefaultPrevented()) {
                return evt;
            }

            var modal = openedWindows.top();
            if (modal) {
                switch (evt.which) {
                    case 27: {
                        if (modal.value.keyboard) {
                            evt.preventDefault();
                            $rootScope.$apply(function () {
                                $modalStack.dismiss(modal.key, 'escape key press');
                            });
                        }
                        break;
                    }
                    case 9: {
                        var list = $modalStack.loadFocusElementList(modal);
                        var focusChanged = false;
                        if (evt.shiftKey) {
                            if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {
                                focusChanged = $modalStack.focusLastFocusableElement(list);
                            }
                        } else {
                            if ($modalStack.isFocusInLastItem(evt, list)) {
                                focusChanged = $modalStack.focusFirstFocusableElement(list);
                            }
                        }

                        if (focusChanged) {
                            evt.preventDefault();
                            evt.stopPropagation();
                        }

                        break;
                    }
                }
            }
        }

        $modalStack.open = function (modalInstance, modal) {
            var modalOpener = $document[0].activeElement,
              modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;

            toggleTopWindowClass(false);

            // Store the current top first, to determine what index we ought to use
            // for the current top modal
            previousTopOpenedModal = openedWindows.top();

            openedWindows.add(modalInstance, {
                deferred: modal.deferred,
                renderDeferred: modal.renderDeferred,
                closedDeferred: modal.closedDeferred,
                modalScope: modal.scope,
                backdrop: modal.backdrop,
                keyboard: modal.keyboard,
                openedClass: modal.openedClass,
                windowTopClass: modal.windowTopClass,
                animation: modal.animation,
                appendTo: modal.appendTo
            });

            openedClasses.put(modalBodyClass, modalInstance);

            var appendToElement = modal.appendTo,
                currBackdropIndex = backdropIndex();

            if (!appendToElement.length) {
                throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
            }

            if (currBackdropIndex >= 0 && !backdropDomEl) {
                backdropScope = $rootScope.$new(true);
                backdropScope.modalOptions = modal;
                backdropScope.index = currBackdropIndex;
                backdropDomEl = angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');
                backdropDomEl.attr({
                    'class': 'modal-backdrop',
                    'ng-style': '{\'z-index\': 1040 + (index && 1 || 0) + index*10}',
                    'uib-modal-animation-class': 'fade',
                    'modal-in-class': 'in'
                });
                if (modal.backdropClass) {
                    backdropDomEl.addClass(modal.backdropClass);
                }

                if (modal.animation) {
                    backdropDomEl.attr('modal-animation', 'true');
                }
                $compile(backdropDomEl)(backdropScope);
                $animate.enter(backdropDomEl, appendToElement);
                if ($uibPosition.isScrollable(appendToElement)) {
                    scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
                    if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
                        appendToElement.css({ paddingRight: scrollbarPadding.right + 'px' });
                    }
                }
            }

            var content;
            if (modal.component) {
                content = document.createElement(snake_case(modal.component.name));
                content = angular.element(content);
                content.attr({
                    resolve: '$resolve',
                    'modal-instance': '$uibModalInstance',
                    close: '$close($value)',
                    dismiss: '$dismiss($value)'
                });
            } else {
                content = modal.content;
            }

            // Set the top modal index based on the index of the previous top modal
            topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
            var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
            angularDomEl.attr({
                'class': 'modal',
                'template-url': modal.windowTemplateUrl,
                'window-top-class': modal.windowTopClass,
                'role': 'dialog',
                'aria-labelledby': modal.ariaLabelledBy,
                'aria-describedby': modal.ariaDescribedBy,
                'size': modal.size,
                'index': topModalIndex,
                'animate': 'animate',
                'ng-style': '{\'z-index\': 1050 + $$topModalIndex*10, display: \'block\'}',
                'tabindex': -1,
                'uib-modal-animation-class': 'fade',
                'modal-in-class': 'in'
            }).append(content);
            if (modal.windowClass) {
                angularDomEl.addClass(modal.windowClass);
            }

            if (modal.animation) {
                angularDomEl.attr('modal-animation', 'true');
            }

            appendToElement.addClass(modalBodyClass);
            if (modal.scope) {
                // we need to explicitly add the modal index to the modal scope
                // because it is needed by ngStyle to compute the zIndex property.
                modal.scope.$$topModalIndex = topModalIndex;
            }
            $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);

            openedWindows.top().value.modalDomEl = angularDomEl;
            openedWindows.top().value.modalOpener = modalOpener;

            applyAriaHidden(angularDomEl);

            function applyAriaHidden(el) {
                if (!el || el[0].tagName === 'BODY') {
                    return;
                }

                getSiblings(el).forEach(function (sibling) {
                    var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true',
                      ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10);

                    if (!ariaHiddenCount) {
                        ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0;
                    }

                    sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1);
                    sibling.setAttribute('aria-hidden', 'true');
                });

                return applyAriaHidden(el.parent());

                function getSiblings(el) {
                    var children = el.parent() ? el.parent().children() : [];

                    return Array.prototype.filter.call(children, function (child) {
                        return child !== el[0];
                    });
                }
            }
        };

        function broadcastClosing(modalWindow, resultOrReason, closing) {
            return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
        }

        function unhideBackgroundElements() {
            Array.prototype.forEach.call(
              document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'),
              function (hiddenEl) {
                  var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10),
                    newHiddenCount = ariaHiddenCount - 1;
                  hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount);

                  if (!newHiddenCount) {
                      hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME);
                      hiddenEl.removeAttribute('aria-hidden');
                  }
              }
            );
        }

        $modalStack.close = function (modalInstance, result) {
            var modalWindow = openedWindows.get(modalInstance);
            unhideBackgroundElements();
            if (modalWindow && broadcastClosing(modalWindow, result, true)) {
                modalWindow.value.modalScope.$$uibDestructionScheduled = true;
                modalWindow.value.deferred.resolve(result);
                removeModalWindow(modalInstance, modalWindow.value.modalOpener);
                return true;
            }

            return !modalWindow;
        };

        $modalStack.dismiss = function (modalInstance, reason) {
            var modalWindow = openedWindows.get(modalInstance);
            unhideBackgroundElements();
            if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
                modalWindow.value.modalScope.$$uibDestructionScheduled = true;
                modalWindow.value.deferred.reject(reason);
                removeModalWindow(modalInstance, modalWindow.value.modalOpener);
                return true;
            }
            return !modalWindow;
        };

        $modalStack.dismissAll = function (reason) {
            var topModal = this.getTop();
            while (topModal && this.dismiss(topModal.key, reason)) {
                topModal = this.getTop();
            }
        };

        $modalStack.getTop = function () {
            return openedWindows.top();
        };

        $modalStack.modalRendered = function (modalInstance) {
            var modalWindow = openedWindows.get(modalInstance);
            $modalStack.focusFirstFocusableElement($modalStack.loadFocusElementList(modalWindow));
            if (modalWindow) {
                modalWindow.value.renderDeferred.resolve();
            }
        };

        $modalStack.focusFirstFocusableElement = function (list) {
            if (list.length > 0) {
                list[0].focus();
                return true;
            }
            return false;
        };

        $modalStack.focusLastFocusableElement = function (list) {
            if (list.length > 0) {
                list[list.length - 1].focus();
                return true;
            }
            return false;
        };

        $modalStack.isModalFocused = function (evt, modalWindow) {
            if (evt && modalWindow) {
                var modalDomEl = modalWindow.value.modalDomEl;
                if (modalDomEl && modalDomEl.length) {
                    return (evt.target || evt.srcElement) === modalDomEl[0];
                }
            }
            return false;
        };

        $modalStack.isFocusInFirstItem = function (evt, list) {
            if (list.length > 0) {
                return (evt.target || evt.srcElement) === list[0];
            }
            return false;
        };

        $modalStack.isFocusInLastItem = function (evt, list) {
            if (list.length > 0) {
                return (evt.target || evt.srcElement) === list[list.length - 1];
            }
            return false;
        };

        $modalStack.loadFocusElementList = function (modalWindow) {
            if (modalWindow) {
                var modalDomE1 = modalWindow.value.modalDomEl;
                if (modalDomE1 && modalDomE1.length) {
                    var elements = modalDomE1[0].querySelectorAll(tabbableSelector);
                    return elements ?
                      Array.prototype.filter.call(elements, function (element) {
                          return isVisible(element);
                      }) : elements;
                }
            }
        };

        return $modalStack;
    }])

  .provider('$uibModal', function () {
      var $modalProvider = {
          options: {
              animation: true,
              backdrop: true, //can also be false or 'static'
              keyboard: true
          },
          $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
            function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
                var $modal = {};

                function getTemplatePromise(options) {
                    return options.template ? $q.when(options.template) :
                      $templateRequest(angular.isFunction(options.templateUrl) ?
                        options.templateUrl() : options.templateUrl);
                }

                var promiseChain = null;
                $modal.getPromiseChain = function () {
                    return promiseChain;
                };

                $modal.open = function (modalOptions) {
                    var modalResultDeferred = $q.defer();
                    var modalOpenedDeferred = $q.defer();
                    var modalClosedDeferred = $q.defer();
                    var modalRenderDeferred = $q.defer();

                    //prepare an instance of a modal to be injected into controllers and returned to a caller
                    var modalInstance = {
                        result: modalResultDeferred.promise,
                        opened: modalOpenedDeferred.promise,
                        closed: modalClosedDeferred.promise,
                        rendered: modalRenderDeferred.promise,
                        close: function (result) {
                            return $modalStack.close(modalInstance, result);
                        },
                        dismiss: function (reason) {
                            return $modalStack.dismiss(modalInstance, reason);
                        }
                    };

                    //merge and clean up options
                    modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
                    modalOptions.resolve = modalOptions.resolve || {};
                    modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);

                    //verify options
                    if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) {
                        throw new Error('One of component or template or templateUrl options is required.');
                    }

                    var templateAndResolvePromise;
                    if (modalOptions.component) {
                        templateAndResolvePromise = $q.when($uibResolve.resolve(modalOptions.resolve, {}, null, null));
                    } else {
                        templateAndResolvePromise =
                          $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
                    }

                    function resolveWithTemplate() {
                        return templateAndResolvePromise;
                    }

                    // Wait for the resolution of the existing promise chain.
                    // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
                    // Then add to $modalStack and resolve opened.
                    // Finally clean up the chain variable if no subsequent modal has overwritten it.
                    var samePromise;
                    samePromise = promiseChain = $q.all([promiseChain])
                      .then(resolveWithTemplate, resolveWithTemplate)
                      .then(function resolveSuccess(tplAndVars) {
                          var providedScope = modalOptions.scope || $rootScope;

                          var modalScope = providedScope.$new();
                          modalScope.$close = modalInstance.close;
                          modalScope.$dismiss = modalInstance.dismiss;

                          modalScope.$on('$destroy', function () {
                              if (!modalScope.$$uibDestructionScheduled) {
                                  modalScope.$dismiss('$uibUnscheduledDestruction');
                              }
                          });

                          var modal = {
                              scope: modalScope,
                              deferred: modalResultDeferred,
                              renderDeferred: modalRenderDeferred,
                              closedDeferred: modalClosedDeferred,
                              animation: modalOptions.animation,
                              backdrop: modalOptions.backdrop,
                              keyboard: modalOptions.keyboard,
                              backdropClass: modalOptions.backdropClass,
                              windowTopClass: modalOptions.windowTopClass,
                              windowClass: modalOptions.windowClass,
                              windowTemplateUrl: modalOptions.windowTemplateUrl,
                              ariaLabelledBy: modalOptions.ariaLabelledBy,
                              ariaDescribedBy: modalOptions.ariaDescribedBy,
                              size: modalOptions.size,
                              openedClass: modalOptions.openedClass,
                              appendTo: modalOptions.appendTo
                          };

                          var component = {};
                          var ctrlInstance, ctrlInstantiate, ctrlLocals = {};

                          if (modalOptions.component) {
                              constructLocals(component, false, true, false);
                              component.name = modalOptions.component;
                              modal.component = component;
                          } else if (modalOptions.controller) {
                              constructLocals(ctrlLocals, true, false, true);

                              // the third param will make the controller instantiate later,private api
                              // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
                              ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
                              if (modalOptions.controllerAs && modalOptions.bindToController) {
                                  ctrlInstance = ctrlInstantiate.instance;
                                  ctrlInstance.$close = modalScope.$close;
                                  ctrlInstance.$dismiss = modalScope.$dismiss;
                                  angular.extend(ctrlInstance, {
                                      $resolve: ctrlLocals.$scope.$resolve
                                  }, providedScope);
                              }

                              ctrlInstance = ctrlInstantiate();

                              if (angular.isFunction(ctrlInstance.$onInit)) {
                                  ctrlInstance.$onInit();
                              }
                          }

                          if (!modalOptions.component) {
                              modal.content = tplAndVars[0];
                          }

                          $modalStack.open(modalInstance, modal);
                          modalOpenedDeferred.resolve(true);

                          function constructLocals(obj, template, instanceOnScope, injectable) {
                              obj.$scope = modalScope;
                              obj.$scope.$resolve = {};
                              if (instanceOnScope) {
                                  obj.$scope.$uibModalInstance = modalInstance;
                              } else {
                                  obj.$uibModalInstance = modalInstance;
                              }

                              var resolves = template ? tplAndVars[1] : tplAndVars;
                              angular.forEach(resolves, function (value, key) {
                                  if (injectable) {
                                      obj[key] = value;
                                  }

                                  obj.$scope.$resolve[key] = value;
                              });
                          }
                      }, function resolveError(reason) {
                          modalOpenedDeferred.reject(reason);
                          modalResultDeferred.reject(reason);
                      })['finally'](function () {
                          if (promiseChain === samePromise) {
                              promiseChain = null;
                          }
                      });

                    return modalInstance;
                };

                return $modal;
            }
          ]
      };

      return $modalProvider;
  });

angular.module('ui.bootstrap.paging', [])
/**
 * Helper internal service for generating common controller code between the
 * pager and pagination components
 */
.factory('uibPaging', ['$parse', function ($parse) {
    return {
        create: function (ctrl, $scope, $attrs) {
            ctrl.setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
            ctrl.ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl
            ctrl._watchers = [];

            ctrl.init = function (ngModelCtrl, config) {
                ctrl.ngModelCtrl = ngModelCtrl;
                ctrl.config = config;

                ngModelCtrl.$render = function () {
                    ctrl.render();
                };

                if ($attrs.itemsPerPage) {
                    ctrl._watchers.push($scope.$parent.$watch($attrs.itemsPerPage, function (value) {
                        ctrl.itemsPerPage = parseInt(value, 10);
                        $scope.totalPages = ctrl.calculateTotalPages();
                        ctrl.updatePage();
                    }));
                } else {
                    ctrl.itemsPerPage = config.itemsPerPage;
                }

                $scope.$watch('totalItems', function (newTotal, oldTotal) {
                    if (angular.isDefined(newTotal) || newTotal !== oldTotal) {
                        $scope.totalPages = ctrl.calculateTotalPages();
                        ctrl.updatePage();
                    }
                });
            };

            ctrl.calculateTotalPages = function () {
                var totalPages = ctrl.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / ctrl.itemsPerPage);
                return Math.max(totalPages || 0, 1);
            };

            ctrl.render = function () {
                $scope.page = parseInt(ctrl.ngModelCtrl.$viewValue, 10) || 1;
            };

            $scope.selectPage = function (page, evt) {
                if (evt) {
                    evt.preventDefault();
                }

                var clickAllowed = !$scope.ngDisabled || !evt;
                if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {
                    if (evt && evt.target) {
                        evt.target.blur();
                    }
                    ctrl.ngModelCtrl.$setViewValue(page);
                    ctrl.ngModelCtrl.$render();
                }
            };

            $scope.getText = function (key) {
                return $scope[key + 'Text'] || ctrl.config[key + 'Text'];
            };

            $scope.noPrevious = function () {
                return $scope.page === 1;
            };

            $scope.noNext = function () {
                return $scope.page === $scope.totalPages;
            };

            ctrl.updatePage = function () {
                ctrl.setNumPages($scope.$parent, $scope.totalPages); // Readonly variable

                if ($scope.page > $scope.totalPages) {
                    $scope.selectPage($scope.totalPages);
                } else {
                    ctrl.ngModelCtrl.$render();
                }
            };

            $scope.$on('$destroy', function () {
                while (ctrl._watchers.length) {
                    ctrl._watchers.shift()();
                }
            });
        }
    };
}]);

angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])

.controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function ($scope, $attrs, uibPaging, uibPagerConfig) {
    $scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align;

    uibPaging.create(this, $scope, $attrs);
}])

.constant('uibPagerConfig', {
    itemsPerPage: 10,
    previousText: '« Previous',
    nextText: 'Next »',
    align: true
})

.directive('uibPager', ['uibPagerConfig', function (uibPagerConfig) {
    return {
        scope: {
            totalItems: '=',
            previousText: '@',
            nextText: '@',
            ngDisabled: '='
        },
        require: ['uibPager', '?ngModel'],
        restrict: 'A',
        controller: 'UibPagerController',
        controllerAs: 'pager',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/pager/pager.html';
        },
        link: function (scope, element, attrs, ctrls) {
            element.addClass('pager');
            var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            if (!ngModelCtrl) {
                return; // do nothing if no ng-model
            }

            paginationCtrl.init(ngModelCtrl, uibPagerConfig);
        }
    };
}]);

angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
.controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function ($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {
    var ctrl = this;
    // Setup configuration parameters
    var maxSize = angular.isDefined($attrs.maxSize) ? $scope.$parent.$eval($attrs.maxSize) : uibPaginationConfig.maxSize,
      rotate = angular.isDefined($attrs.rotate) ? $scope.$parent.$eval($attrs.rotate) : uibPaginationConfig.rotate,
      forceEllipses = angular.isDefined($attrs.forceEllipses) ? $scope.$parent.$eval($attrs.forceEllipses) : uibPaginationConfig.forceEllipses,
      boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers,
      pageLabel = angular.isDefined($attrs.pageLabel) ? function (idx) { return $scope.$parent.$eval($attrs.pageLabel, { $page: idx }); } : angular.identity;
    $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks;
    $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks;

    uibPaging.create(this, $scope, $attrs);

    if ($attrs.maxSize) {
        ctrl._watchers.push($scope.$parent.$watch($parse($attrs.maxSize), function (value) {
            maxSize = parseInt(value, 10);
            ctrl.render();
        }));
    }

    // Create page object used in template
    function makePage(number, text, isActive) {
        return {
            number: number,
            text: text,
            active: isActive
        };
    }

    function getPages(currentPage, totalPages) {
        var pages = [];

        // Default page limits
        var startPage = 1, endPage = totalPages;
        var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;

        // recompute if maxSize
        if (isMaxSized) {
            if (rotate) {
                // Current page is displayed in the middle of the visible ones
                startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
                endPage = startPage + maxSize - 1;

                // Adjust if limit is exceeded
                if (endPage > totalPages) {
                    endPage = totalPages;
                    startPage = endPage - maxSize + 1;
                }
            } else {
                // Visible pages are paginated with maxSize
                startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1;

                // Adjust last page if limit is exceeded
                endPage = Math.min(startPage + maxSize - 1, totalPages);
            }
        }

        // Add page number links
        for (var number = startPage; number <= endPage; number++) {
            var page = makePage(number, pageLabel(number), number === currentPage);
            pages.push(page);
        }

        // Add links to move between page sets
        if (isMaxSized && maxSize > 0 && (!rotate || forceEllipses || boundaryLinkNumbers)) {
            if (startPage > 1) {
                if (!boundaryLinkNumbers || startPage > 3) { //need ellipsis for all options unless range is too close to beginning
                    var previousPageSet = makePage(startPage - 1, '...', false);
                    pages.unshift(previousPageSet);
                }
                if (boundaryLinkNumbers) {
                    if (startPage === 3) { //need to replace ellipsis when the buttons would be sequential
                        var secondPageLink = makePage(2, '2', false);
                        pages.unshift(secondPageLink);
                    }
                    //add the first page
                    var firstPageLink = makePage(1, '1', false);
                    pages.unshift(firstPageLink);
                }
            }

            if (endPage < totalPages) {
                if (!boundaryLinkNumbers || endPage < totalPages - 2) { //need ellipsis for all options unless range is too close to end
                    var nextPageSet = makePage(endPage + 1, '...', false);
                    pages.push(nextPageSet);
                }
                if (boundaryLinkNumbers) {
                    if (endPage === totalPages - 2) { //need to replace ellipsis when the buttons would be sequential
                        var secondToLastPageLink = makePage(totalPages - 1, totalPages - 1, false);
                        pages.push(secondToLastPageLink);
                    }
                    //add the last page
                    var lastPageLink = makePage(totalPages, totalPages, false);
                    pages.push(lastPageLink);
                }
            }
        }
        return pages;
    }

    var originalRender = this.render;
    this.render = function () {
        originalRender();
        if ($scope.page > 0 && $scope.page <= $scope.totalPages) {
            $scope.pages = getPages($scope.page, $scope.totalPages);
        }
    };
}])

.constant('uibPaginationConfig', {
    itemsPerPage: 10,
    boundaryLinks: false,
    boundaryLinkNumbers: false,
    directionLinks: true,
    firstText: 'First',
    previousText: 'Previous',
    nextText: 'Next',
    lastText: 'Last',
    rotate: true,
    forceEllipses: false
})

.directive('uibPagination', ['$parse', 'uibPaginationConfig', function ($parse, uibPaginationConfig) {
    return {
        scope: {
            totalItems: '=',
            firstText: '@',
            previousText: '@',
            nextText: '@',
            lastText: '@',
            ngDisabled: '='
        },
        require: ['uibPagination', '?ngModel'],
        restrict: 'A',
        controller: 'UibPaginationController',
        controllerAs: 'pagination',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/pagination/pagination.html';
        },
        link: function (scope, element, attrs, ctrls) {
            element.addClass('pagination');
            var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            if (!ngModelCtrl) {
                return; // do nothing if no ng-model
            }

            paginationCtrl.init(ngModelCtrl, uibPaginationConfig);
        }
    };
}]);

/**
 * The following features are still outstanding: animation as a
 * function, placement as a function, inside, support for more triggers than
 * just mouse enter/leave, html tooltips, and selector delegation.
 */
angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])

/**
 * The $tooltip service creates tooltip- and popover-like directives as well as
 * houses global options for them.
 */
.provider('$uibTooltip', function () {
    // The default options tooltip and popover.
    var defaultOptions = {
        placement: 'top',
        placementClassPrefix: '',
        animation: true,
        popupDelay: 0,
        popupCloseDelay: 0,
        useContentExp: false
    };

    // Default hide triggers for each show trigger
    var triggerMap = {
        'mouseenter': 'mouseleave',
        'click': 'click',
        'outsideClick': 'outsideClick',
        'focus': 'blur',
        'none': ''
    };

    // The options specified to the provider globally.
    var globalOptions = {};

    /**
     * `options({})` allows global configuration of all tooltips in the
     * application.
     *
     *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
     *     // place tooltips left instead of top by default
     *     $tooltipProvider.options( { placement: 'left' } );
     *   });
     */
    this.options = function (value) {
        angular.extend(globalOptions, value);
    };

    /**
     * This allows you to extend the set of trigger mappings available. E.g.:
     *
     *   $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
     */
    this.setTriggers = function setTriggers(triggers) {
        angular.extend(triggerMap, triggers);
    };

    /**
     * This is a helper function for translating camel-case to snake_case.
     */
    function snake_case(name) {
        var regexp = /[A-Z]/g;
        var separator = '-';
        return name.replace(regexp, function (letter, pos) {
            return (pos ? separator : '') + letter.toLowerCase();
        });
    }

    /**
     * Returns the actual instance of the $tooltip service.
     * TODO support multiple triggers
     */
    this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function ($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
        var openedTooltips = $$stackedMap.createNew();
        $document.on('keyup', keypressListener);

        $rootScope.$on('$destroy', function () {
            $document.off('keyup', keypressListener);
        });

        function keypressListener(e) {
            if (e.which === 27) {
                var last = openedTooltips.top();
                if (last) {
                    last.value.close();
                    last = null;
                }
            }
        }

        return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
            options = angular.extend({}, defaultOptions, globalOptions, options);

            /**
             * Returns an object of show and hide triggers.
             *
             * If a trigger is supplied,
             * it is used to show the tooltip; otherwise, it will use the `trigger`
             * option passed to the `$tooltipProvider.options` method; else it will
             * default to the trigger supplied to this directive factory.
             *
             * The hide trigger is based on the show trigger. If the `trigger` option
             * was passed to the `$tooltipProvider.options` method, it will use the
             * mapped trigger from `triggerMap` or the passed trigger if the map is
             * undefined; otherwise, it uses the `triggerMap` value of the show
             * trigger; else it will just use the show trigger.
             */
            function getTriggers(trigger) {
                var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
                var hide = show.map(function (trigger) {
                    return triggerMap[trigger] || trigger;
                });
                return {
                    show: show,
                    hide: hide
                };
            }

            var directiveName = snake_case(ttType);

            var startSym = $interpolate.startSymbol();
            var endSym = $interpolate.endSymbol();
            var template =
              '<div ' + directiveName + '-popup ' +
                'uib-title="' + startSym + 'title' + endSym + '" ' +
                (options.useContentExp ?
                  'content-exp="contentExp()" ' :
                  'content="' + startSym + 'content' + endSym + '" ') +
                'origin-scope="origScope" ' +
                'class="uib-position-measure ' + prefix + '" ' +
                'tooltip-animation-class="fade"' +
                'uib-tooltip-classes ' +
                'ng-class="{ in: isOpen }" ' +
                '>' +
              '</div>';

            return {
                compile: function (tElem, tAttrs) {
                    var tooltipLinker = $compile(template);

                    return function link(scope, element, attrs, tooltipCtrl) {
                        var tooltip;
                        var tooltipLinkedScope;
                        var transitionTimeout;
                        var showTimeout;
                        var hideTimeout;
                        var positionTimeout;
                        var adjustmentTimeout;
                        var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
                        var triggers = getTriggers(undefined);
                        var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
                        var ttScope = scope.$new(true);
                        var repositionScheduled = false;
                        var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;
                        var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;
                        var observers = [];
                        var lastPlacement;

                        var positionTooltip = function () {
                            // check if tooltip exists and is not empty
                            if (!tooltip || !tooltip.html()) { return; }

                            if (!positionTimeout) {
                                positionTimeout = $timeout(function () {
                                    var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
                                    var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
                                    var elementPos = appendToBody ? $position.offset(element) : $position.position(element);
                                    tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });
                                    var placementClasses = ttPosition.placement.split('-');

                                    if (!tooltip.hasClass(placementClasses[0])) {
                                        tooltip.removeClass(lastPlacement.split('-')[0]);
                                        tooltip.addClass(placementClasses[0]);
                                    }

                                    if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {
                                        tooltip.removeClass(options.placementClassPrefix + lastPlacement);
                                        tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
                                    }

                                    adjustmentTimeout = $timeout(function () {
                                        var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
                                        var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);
                                        if (adjustment) {
                                            tooltip.css(adjustment);
                                        }
                                        adjustmentTimeout = null;
                                    }, 0, false);

                                    // first time through tt element will have the
                                    // uib-position-measure class or if the placement
                                    // has changed we need to position the arrow.
                                    if (tooltip.hasClass('uib-position-measure')) {
                                        $position.positionArrow(tooltip, ttPosition.placement);
                                        tooltip.removeClass('uib-position-measure');
                                    } else if (lastPlacement !== ttPosition.placement) {
                                        $position.positionArrow(tooltip, ttPosition.placement);
                                    }
                                    lastPlacement = ttPosition.placement;

                                    positionTimeout = null;
                                }, 0, false);
                            }
                        };

                        // Set up the correct scope to allow transclusion later
                        ttScope.origScope = scope;

                        // By default, the tooltip is not open.
                        // TODO add ability to start tooltip opened
                        ttScope.isOpen = false;

                        function toggleTooltipBind() {
                            if (!ttScope.isOpen) {
                                showTooltipBind();
                            } else {
                                hideTooltipBind();
                            }
                        }

                        // Show the tooltip with delay if specified, otherwise show it immediately
                        function showTooltipBind() {
                            if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
                                return;
                            }

                            cancelHide();
                            prepareTooltip();

                            if (ttScope.popupDelay) {
                                // Do nothing if the tooltip was already scheduled to pop-up.
                                // This happens if show is triggered multiple times before any hide is triggered.
                                if (!showTimeout) {
                                    showTimeout = $timeout(show, ttScope.popupDelay, false);
                                }
                            } else {
                                show();
                            }
                        }

                        function hideTooltipBind() {
                            cancelShow();

                            if (ttScope.popupCloseDelay) {
                                if (!hideTimeout) {
                                    hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
                                }
                            } else {
                                hide();
                            }
                        }

                        // Show the tooltip popup element.
                        function show() {
                            cancelShow();
                            cancelHide();

                            // Don't show empty tooltips.
                            if (!ttScope.content) {
                                return angular.noop;
                            }

                            createTooltip();

                            // And show the tooltip.
                            ttScope.$evalAsync(function () {
                                ttScope.isOpen = true;
                                assignIsOpen(true);
                                positionTooltip();
                            });
                        }

                        function cancelShow() {
                            if (showTimeout) {
                                $timeout.cancel(showTimeout);
                                showTimeout = null;
                            }

                            if (positionTimeout) {
                                $timeout.cancel(positionTimeout);
                                positionTimeout = null;
                            }
                        }

                        // Hide the tooltip popup element.
                        function hide() {
                            if (!ttScope) {
                                return;
                            }

                            // First things first: we don't show it anymore.
                            ttScope.$evalAsync(function () {
                                if (ttScope) {
                                    ttScope.isOpen = false;
                                    assignIsOpen(false);
                                    // And now we remove it from the DOM. However, if we have animation, we
                                    // need to wait for it to expire beforehand.
                                    // FIXME: this is a placeholder for a port of the transitions library.
                                    // The fade transition in TWBS is 150ms.
                                    if (ttScope.animation) {
                                        if (!transitionTimeout) {
                                            transitionTimeout = $timeout(removeTooltip, 150, false);
                                        }
                                    } else {
                                        removeTooltip();
                                    }
                                }
                            });
                        }

                        function cancelHide() {
                            if (hideTimeout) {
                                $timeout.cancel(hideTimeout);
                                hideTimeout = null;
                            }

                            if (transitionTimeout) {
                                $timeout.cancel(transitionTimeout);
                                transitionTimeout = null;
                            }
                        }

                        function createTooltip() {
                            // There can only be one tooltip element per directive shown at once.
                            if (tooltip) {
                                return;
                            }

                            tooltipLinkedScope = ttScope.$new();
                            tooltip = tooltipLinker(tooltipLinkedScope, function (tooltip) {
                                if (appendToBody) {
                                    $document.find('body').append(tooltip);
                                } else {
                                    element.after(tooltip);
                                }
                            });

                            openedTooltips.add(ttScope, {
                                close: hide
                            });

                            prepObservers();
                        }

                        function removeTooltip() {
                            cancelShow();
                            cancelHide();
                            unregisterObservers();

                            if (tooltip) {
                                tooltip.remove();

                                tooltip = null;
                                if (adjustmentTimeout) {
                                    $timeout.cancel(adjustmentTimeout);
                                }
                            }

                            openedTooltips.remove(ttScope);

                            if (tooltipLinkedScope) {
                                tooltipLinkedScope.$destroy();
                                tooltipLinkedScope = null;
                            }
                        }

                        /**
                         * Set the initial scope values. Once
                         * the tooltip is created, the observers
                         * will be added to keep things in sync.
                         */
                        function prepareTooltip() {
                            ttScope.title = attrs[prefix + 'Title'];
                            if (contentParse) {
                                ttScope.content = contentParse(scope);
                            } else {
                                ttScope.content = attrs[ttType];
                            }

                            ttScope.popupClass = attrs[prefix + 'Class'];
                            ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;
                            var placement = $position.parsePlacement(ttScope.placement);
                            lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];

                            var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);
                            var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);
                            ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;
                            ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;
                        }

                        function assignIsOpen(isOpen) {
                            if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
                                isOpenParse.assign(scope, isOpen);
                            }
                        }

                        ttScope.contentExp = function () {
                            return ttScope.content;
                        };

                        /**
                         * Observe the relevant attributes.
                         */
                        attrs.$observe('disabled', function (val) {
                            if (val) {
                                cancelShow();
                            }

                            if (val && ttScope.isOpen) {
                                hide();
                            }
                        });

                        if (isOpenParse) {
                            scope.$watch(isOpenParse, function (val) {
                                if (ttScope && !val === ttScope.isOpen) {
                                    toggleTooltipBind();
                                }
                            });
                        }

                        function prepObservers() {
                            observers.length = 0;

                            if (contentParse) {
                                observers.push(
                                  scope.$watch(contentParse, function (val) {
                                      ttScope.content = val;
                                      if (!val && ttScope.isOpen) {
                                          hide();
                                      }
                                  })
                                );

                                observers.push(
                                  tooltipLinkedScope.$watch(function () {
                                      if (!repositionScheduled) {
                                          repositionScheduled = true;
                                          tooltipLinkedScope.$$postDigest(function () {
                                              repositionScheduled = false;
                                              if (ttScope && ttScope.isOpen) {
                                                  positionTooltip();
                                              }
                                          });
                                      }
                                  })
                                );
                            } else {
                                observers.push(
                                  attrs.$observe(ttType, function (val) {
                                      ttScope.content = val;
                                      if (!val && ttScope.isOpen) {
                                          hide();
                                      } else {
                                          positionTooltip();
                                      }
                                  })
                                );
                            }

                            observers.push(
                              attrs.$observe(prefix + 'Title', function (val) {
                                  ttScope.title = val;
                                  if (ttScope.isOpen) {
                                      positionTooltip();
                                  }
                              })
                            );

                            observers.push(
                              attrs.$observe(prefix + 'Placement', function (val) {
                                  ttScope.placement = val ? val : options.placement;
                                  if (ttScope.isOpen) {
                                      positionTooltip();
                                  }
                              })
                            );
                        }

                        function unregisterObservers() {
                            if (observers.length) {
                                angular.forEach(observers, function (observer) {
                                    observer();
                                });
                                observers.length = 0;
                            }
                        }

                        // hide tooltips/popovers for outsideClick trigger
                        function bodyHideTooltipBind(e) {
                            if (!ttScope || !ttScope.isOpen || !tooltip) {
                                return;
                            }
                            // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked
                            if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {
                                hideTooltipBind();
                            }
                        }

                        var unregisterTriggers = function () {
                            triggers.show.forEach(function (trigger) {
                                if (trigger === 'outsideClick') {
                                    element.off('click', toggleTooltipBind);
                                } else {
                                    element.off(trigger, showTooltipBind);
                                    element.off(trigger, toggleTooltipBind);
                                }
                            });
                            triggers.hide.forEach(function (trigger) {
                                if (trigger === 'outsideClick') {
                                    $document.off('click', bodyHideTooltipBind);
                                } else {
                                    element.off(trigger, hideTooltipBind);
                                }
                            });
                        };

                        function prepTriggers() {
                            var showTriggers = [], hideTriggers = [];
                            var val = scope.$eval(attrs[prefix + 'Trigger']);
                            unregisterTriggers();

                            if (angular.isObject(val)) {
                                Object.keys(val).forEach(function (key) {
                                    showTriggers.push(key);
                                    hideTriggers.push(val[key]);
                                });
                                triggers = {
                                    show: showTriggers,
                                    hide: hideTriggers
                                };
                            } else {
                                triggers = getTriggers(val);
                            }

                            if (triggers.show !== 'none') {
                                triggers.show.forEach(function (trigger, idx) {
                                    if (trigger === 'outsideClick') {
                                        element.on('click', toggleTooltipBind);
                                        $document.on('click', bodyHideTooltipBind);
                                    } else if (trigger === triggers.hide[idx]) {
                                        element.on(trigger, toggleTooltipBind);
                                    } else if (trigger) {
                                        element.on(trigger, showTooltipBind);
                                        element.on(triggers.hide[idx], hideTooltipBind);
                                    }

                                    element.on('keypress', function (e) {
                                        if (e.which === 27) {
                                            hideTooltipBind();
                                        }
                                    });
                                });
                            }
                        }

                        prepTriggers();

                        var animation = scope.$eval(attrs[prefix + 'Animation']);
                        ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;

                        var appendToBodyVal;
                        var appendKey = prefix + 'AppendToBody';
                        if (appendKey in attrs && attrs[appendKey] === undefined) {
                            appendToBodyVal = true;
                        } else {
                            appendToBodyVal = scope.$eval(attrs[appendKey]);
                        }

                        appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;

                        // Make sure tooltip is destroyed and removed.
                        scope.$on('$destroy', function onDestroyTooltip() {
                            unregisterTriggers();
                            removeTooltip();
                            ttScope = null;
                        });
                    };
                }
            };
        };
    }];
})

// This is mostly ngInclude code but with a custom scope
.directive('uibTooltipTemplateTransclude', [
         '$animate', '$sce', '$compile', '$templateRequest',
function ($animate, $sce, $compile, $templateRequest) {
    return {
        link: function (scope, elem, attrs) {
            var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);

            var changeCounter = 0,
              currentScope,
              previousElement,
              currentElement;

            var cleanupLastIncludeContent = function () {
                if (previousElement) {
                    previousElement.remove();
                    previousElement = null;
                }

                if (currentScope) {
                    currentScope.$destroy();
                    currentScope = null;
                }

                if (currentElement) {
                    $animate.leave(currentElement).then(function () {
                        previousElement = null;
                    });
                    previousElement = currentElement;
                    currentElement = null;
                }
            };

            scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function (src) {
                var thisChangeId = ++changeCounter;

                if (src) {
                    //set the 2nd param to true to ignore the template request error so that the inner
                    //contents and scope can be cleaned up.
                    $templateRequest(src, true).then(function (response) {
                        if (thisChangeId !== changeCounter) { return; }
                        var newScope = origScope.$new();
                        var template = response;

                        var clone = $compile(template)(newScope, function (clone) {
                            cleanupLastIncludeContent();
                            $animate.enter(clone, elem);
                        });

                        currentScope = newScope;
                        currentElement = clone;

                        currentScope.$emit('$includeContentLoaded', src);
                    }, function () {
                        if (thisChangeId === changeCounter) {
                            cleanupLastIncludeContent();
                            scope.$emit('$includeContentError', src);
                        }
                    });
                    scope.$emit('$includeContentRequested', src);
                } else {
                    cleanupLastIncludeContent();
                }
            });

            scope.$on('$destroy', cleanupLastIncludeContent);
        }
    };
}])

/**
 * Note that it's intentional that these classes are *not* applied through $animate.
 * They must not be animated as they're expected to be present on the tooltip on
 * initialization.
 */
.directive('uibTooltipClasses', ['$uibPosition', function ($uibPosition) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            // need to set the primary position so the
            // arrow has space during position measure.
            // tooltip.positionTooltip()
            if (scope.placement) {
                // // There are no top-left etc... classes
                // // in TWBS, so we need the primary position.
                var position = $uibPosition.parsePlacement(scope.placement);
                element.addClass(position[0]);
            }

            if (scope.popupClass) {
                element.addClass(scope.popupClass);
            }

            if (scope.animation) {
                element.addClass(attrs.tooltipAnimationClass);
            }
        }
    };
}])

.directive('uibTooltipPopup', function () {
    return {
        restrict: 'A',
        scope: { content: '@' },
        templateUrl: 'uib/template/tooltip/tooltip-popup.html'
    };
})

.directive('uibTooltip', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');
}])

.directive('uibTooltipTemplatePopup', function () {
    return {
        restrict: 'A',
        scope: { contentExp: '&', originScope: '&' },
        templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'
    };
})

.directive('uibTooltipTemplate', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {
        useContentExp: true
    });
}])

.directive('uibTooltipHtmlPopup', function () {
    return {
        restrict: 'A',
        scope: { contentExp: '&' },
        templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'
    };
})

.directive('uibTooltipHtml', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {
        useContentExp: true
    });
}]);

/**
 * The following features are still outstanding: popup delay, animation as a
 * function, placement as a function, inside, support for more triggers than
 * just mouse enter/leave, and selector delegatation.
 */
angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])

.directive('uibPopoverTemplatePopup', function () {
    return {
        restrict: 'A',
        scope: { uibTitle: '@', contentExp: '&', originScope: '&' },
        templateUrl: 'uib/template/popover/popover-template.html'
    };
})

.directive('uibPopoverTemplate', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {
        useContentExp: true
    });
}])

.directive('uibPopoverHtmlPopup', function () {
    return {
        restrict: 'A',
        scope: { contentExp: '&', uibTitle: '@' },
        templateUrl: 'uib/template/popover/popover-html.html'
    };
})

.directive('uibPopoverHtml', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibPopoverHtml', 'popover', 'click', {
        useContentExp: true
    });
}])

.directive('uibPopoverPopup', function () {
    return {
        restrict: 'A',
        scope: { uibTitle: '@', content: '@' },
        templateUrl: 'uib/template/popover/popover.html'
    };
})

.directive('uibPopover', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibPopover', 'popover', 'click');
}]);

angular.module('ui.bootstrap.progressbar', [])

.constant('uibProgressConfig', {
    animate: true,
    max: 100
})

.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function ($scope, $attrs, progressConfig) {
    var self = this,
        animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;

    this.bars = [];
    $scope.max = getMaxOrDefault();

    this.addBar = function (bar, element, attrs) {
        if (!animate) {
            element.css({ 'transition': 'none' });
        }

        this.bars.push(bar);

        bar.max = getMaxOrDefault();
        bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';

        bar.$watch('value', function (value) {
            bar.recalculatePercentage();
        });

        bar.recalculatePercentage = function () {
            var totalPercentage = self.bars.reduce(function (total, bar) {
                bar.percent = +(100 * bar.value / bar.max).toFixed(2);
                return total + bar.percent;
            }, 0);

            if (totalPercentage > 100) {
                bar.percent -= totalPercentage - 100;
            }
        };

        bar.$on('$destroy', function () {
            element = null;
            self.removeBar(bar);
        });
    };

    this.removeBar = function (bar) {
        this.bars.splice(this.bars.indexOf(bar), 1);
        this.bars.forEach(function (bar) {
            bar.recalculatePercentage();
        });
    };

    //$attrs.$observe('maxParam', function(maxParam) {
    $scope.$watch('maxParam', function (maxParam) {
        self.bars.forEach(function (bar) {
            bar.max = getMaxOrDefault();
            bar.recalculatePercentage();
        });
    });

    function getMaxOrDefault() {
        return angular.isDefined($scope.maxParam) ? $scope.maxParam : progressConfig.max;
    }
}])

.directive('uibProgress', function () {
    return {
        replace: true,
        transclude: true,
        controller: 'UibProgressController',
        require: 'uibProgress',
        scope: {
            maxParam: '=?max'
        },
        templateUrl: 'uib/template/progressbar/progress.html'
    };
})

.directive('uibBar', function () {
    return {
        replace: true,
        transclude: true,
        require: '^uibProgress',
        scope: {
            value: '=',
            type: '@'
        },
        templateUrl: 'uib/template/progressbar/bar.html',
        link: function (scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, element, attrs);
        }
    };
})

.directive('uibProgressbar', function () {
    return {
        replace: true,
        transclude: true,
        controller: 'UibProgressController',
        scope: {
            value: '=',
            maxParam: '=?max',
            type: '@'
        },
        templateUrl: 'uib/template/progressbar/progressbar.html',
        link: function (scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, angular.element(element.children()[0]), { title: attrs.title });
        }
    };
});

angular.module('ui.bootstrap.rating', [])

.constant('uibRatingConfig', {
    max: 5,
    stateOn: null,
    stateOff: null,
    enableReset: true,
    titles: ['one', 'two', 'three', 'four', 'five']
})

.controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function ($scope, $attrs, ratingConfig) {
    var ngModelCtrl = { $setViewValue: angular.noop },
      self = this;

    this.init = function (ngModelCtrl_) {
        ngModelCtrl = ngModelCtrl_;
        ngModelCtrl.$render = this.render;

        ngModelCtrl.$formatters.push(function (value) {
            if (angular.isNumber(value) && value << 0 !== value) {
                value = Math.round(value);
            }

            return value;
        });

        this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
        this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;
        this.enableReset = angular.isDefined($attrs.enableReset) ?
          $scope.$parent.$eval($attrs.enableReset) : ratingConfig.enableReset;
        var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles;
        this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?
            tmpTitles : ratingConfig.titles;

        var ratingStates = angular.isDefined($attrs.ratingStates) ?
          $scope.$parent.$eval($attrs.ratingStates) :
          new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max);
        $scope.range = this.buildTemplateObjects(ratingStates);
    };

    this.buildTemplateObjects = function (states) {
        for (var i = 0, n = states.length; i < n; i++) {
            states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);
        }
        return states;
    };

    this.getTitle = function (index) {
        if (index >= this.titles.length) {
            return index + 1;
        }

        return this.titles[index];
    };

    $scope.rate = function (value) {
        if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {
            var newViewValue = self.enableReset && ngModelCtrl.$viewValue === value ? 0 : value;
            ngModelCtrl.$setViewValue(newViewValue);
            ngModelCtrl.$render();
        }
    };

    $scope.enter = function (value) {
        if (!$scope.readonly) {
            $scope.value = value;
        }
        $scope.onHover({ value: value });
    };

    $scope.reset = function () {
        $scope.value = ngModelCtrl.$viewValue;
        $scope.onLeave();
    };

    $scope.onKeydown = function (evt) {
        if (/(37|38|39|40)/.test(evt.which)) {
            evt.preventDefault();
            evt.stopPropagation();
            $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));
        }
    };

    this.render = function () {
        $scope.value = ngModelCtrl.$viewValue;
        $scope.title = self.getTitle($scope.value - 1);
    };
}])

.directive('uibRating', function () {
    return {
        require: ['uibRating', 'ngModel'],
        restrict: 'A',
        scope: {
            readonly: '=?readOnly',
            onHover: '&',
            onLeave: '&'
        },
        controller: 'UibRatingController',
        templateUrl: 'uib/template/rating/rating.html',
        link: function (scope, element, attrs, ctrls) {
            var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
            ratingCtrl.init(ngModelCtrl);
        }
    };
});

angular.module('ui.bootstrap.tabs', [])

.controller('UibTabsetController', ['$scope', function ($scope) {
    var ctrl = this,
      oldIndex;
    ctrl.tabs = [];

    ctrl.select = function (index, evt) {
        if (!destroyed) {
            var previousIndex = findTabIndex(oldIndex);
            var previousSelected = ctrl.tabs[previousIndex];
            if (previousSelected) {
                previousSelected.tab.onDeselect({
                    $event: evt,
                    $selectedIndex: index
                });
                if (evt && evt.isDefaultPrevented()) {
                    return;
                }
                previousSelected.tab.active = false;
            }

            var selected = ctrl.tabs[index];
            if (selected) {
                selected.tab.onSelect({
                    $event: evt
                });
                selected.tab.active = true;
                ctrl.active = selected.index;
                oldIndex = selected.index;
            } else if (!selected && angular.isDefined(oldIndex)) {
                ctrl.active = null;
                oldIndex = null;
            }
        }
    };

    ctrl.addTab = function addTab(tab) {
        ctrl.tabs.push({
            tab: tab,
            index: tab.index
        });
        ctrl.tabs.sort(function (t1, t2) {
            if (t1.index > t2.index) {
                return 1;
            }

            if (t1.index < t2.index) {
                return -1;
            }

            return 0;
        });

        if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
            var newActiveIndex = findTabIndex(tab.index);
            ctrl.select(newActiveIndex);
        }
    };

    ctrl.removeTab = function removeTab(tab) {
        var index;
        for (var i = 0; i < ctrl.tabs.length; i++) {
            if (ctrl.tabs[i].tab === tab) {
                index = i;
                break;
            }
        }

        if (ctrl.tabs[index].index === ctrl.active) {
            var newActiveTabIndex = index === ctrl.tabs.length - 1 ?
              index - 1 : index + 1 % ctrl.tabs.length;
            ctrl.select(newActiveTabIndex);
        }

        ctrl.tabs.splice(index, 1);
    };

    $scope.$watch('tabset.active', function (val) {
        if (angular.isDefined(val) && val !== oldIndex) {
            ctrl.select(findTabIndex(val));
        }
    });

    var destroyed;
    $scope.$on('$destroy', function () {
        destroyed = true;
    });

    function findTabIndex(index) {
        for (var i = 0; i < ctrl.tabs.length; i++) {
            if (ctrl.tabs[i].index === index) {
                return i;
            }
        }
    }
}])

.directive('uibTabset', function () {
    return {
        transclude: true,
        replace: true,
        scope: {},
        bindToController: {
            active: '=?',
            type: '@'
        },
        controller: 'UibTabsetController',
        controllerAs: 'tabset',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/tabs/tabset.html';
        },
        link: function (scope, element, attrs) {
            scope.vertical = angular.isDefined(attrs.vertical) ?
              scope.$parent.$eval(attrs.vertical) : false;
            scope.justified = angular.isDefined(attrs.justified) ?
              scope.$parent.$eval(attrs.justified) : false;
        }
    };
})

.directive('uibTab', ['$parse', function ($parse) {
    return {
        require: '^uibTabset',
        replace: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/tabs/tab.html';
        },
        transclude: true,
        scope: {
            heading: '@',
            index: '=?',
            classes: '@?',
            onSelect: '&select', //This callback is called in contentHeadingTransclude
            //once it inserts the tab's content into the dom
            onDeselect: '&deselect'
        },
        controller: function () {
            //Empty controller so other directives can require being 'under' a tab
        },
        controllerAs: 'tab',
        link: function (scope, elm, attrs, tabsetCtrl, transclude) {
            scope.disabled = false;
            if (attrs.disable) {
                scope.$parent.$watch($parse(attrs.disable), function (value) {
                    scope.disabled = !!value;
                });
            }

            if (angular.isUndefined(attrs.index)) {
                if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {
                    scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function (t) { return t.index; })) + 1;
                } else {
                    scope.index = 0;
                }
            }

            if (angular.isUndefined(attrs.classes)) {
                scope.classes = '';
            }

            scope.select = function (evt) {
                if (!scope.disabled) {
                    var index;
                    for (var i = 0; i < tabsetCtrl.tabs.length; i++) {
                        if (tabsetCtrl.tabs[i].tab === scope) {
                            index = i;
                            break;
                        }
                    }

                    tabsetCtrl.select(index, evt);
                }
            };

            tabsetCtrl.addTab(scope);
            scope.$on('$destroy', function () {
                tabsetCtrl.removeTab(scope);
            });

            //We need to transclude later, once the content container is ready.
            //when this link happens, we're inside a tab heading.
            scope.$transcludeFn = transclude;
        }
    };
}])

.directive('uibTabHeadingTransclude', function () {
    return {
        restrict: 'A',
        require: '^uibTab',
        link: function (scope, elm) {
            scope.$watch('headingElement', function updateHeadingElement(heading) {
                if (heading) {
                    elm.html('');
                    elm.append(heading);
                }
            });
        }
    };
})

.directive('uibTabContentTransclude', function () {
    return {
        restrict: 'A',
        require: '^uibTabset',
        link: function (scope, elm, attrs) {
            var tab = scope.$eval(attrs.uibTabContentTransclude).tab;

            //Now our tab is ready to be transcluded: both the tab heading area
            //and the tab content area are loaded.  Transclude 'em both.
            tab.$transcludeFn(tab.$parent, function (contents) {
                angular.forEach(contents, function (node) {
                    if (isTabHeading(node)) {
                        //Let tabHeadingTransclude know.
                        tab.headingElement = node;
                    } else {
                        elm.append(node);
                    }
                });
            });
        }
    };

    function isTabHeading(node) {
        return node.tagName && (
          node.hasAttribute('uib-tab-heading') ||
          node.hasAttribute('data-uib-tab-heading') ||
          node.hasAttribute('x-uib-tab-heading') ||
          node.tagName.toLowerCase() === 'uib-tab-heading' ||
          node.tagName.toLowerCase() === 'data-uib-tab-heading' ||
          node.tagName.toLowerCase() === 'x-uib-tab-heading' ||
          node.tagName.toLowerCase() === 'uib:tab-heading'
        );
    }
});

angular.module('ui.bootstrap.timepicker', [])

.constant('uibTimepickerConfig', {
    hourStep: 1,
    minuteStep: 1,
    secondStep: 1,
    showMeridian: true,
    showSeconds: false,
    meridians: null,
    readonlyInput: false,
    mousewheel: true,
    arrowkeys: true,
    showSpinners: true,
    templateUrl: 'uib/template/timepicker/timepicker.html'
})

.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function ($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
    var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl;
    var selected = new Date(),
      watchers = [],
      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
      meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS,
      padHours = angular.isDefined($attrs.padHours) ? $scope.$parent.$eval($attrs.padHours) : true;

    $scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;
    $element.removeAttr('tabindex');

    this.init = function (ngModelCtrl_, inputs) {
        ngModelCtrl = ngModelCtrl_;
        ngModelCtrl.$render = this.render;

        ngModelCtrl.$formatters.unshift(function (modelValue) {
            return modelValue ? new Date(modelValue) : null;
        });

        var hoursInputEl = inputs.eq(0),
            minutesInputEl = inputs.eq(1),
            secondsInputEl = inputs.eq(2);

        hoursModelCtrl = hoursInputEl.controller('ngModel');
        minutesModelCtrl = minutesInputEl.controller('ngModel');
        secondsModelCtrl = secondsInputEl.controller('ngModel');

        var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;

        if (mousewheel) {
            this.setupMousewheelEvents(hoursInputEl, minutesInputEl, secondsInputEl);
        }

        var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;
        if (arrowkeys) {
            this.setupArrowkeyEvents(hoursInputEl, minutesInputEl, secondsInputEl);
        }

        $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
        this.setupInputEvents(hoursInputEl, minutesInputEl, secondsInputEl);
    };

    var hourStep = timepickerConfig.hourStep;
    if ($attrs.hourStep) {
        watchers.push($scope.$parent.$watch($parse($attrs.hourStep), function (value) {
            hourStep = +value;
        }));
    }

    var minuteStep = timepickerConfig.minuteStep;
    if ($attrs.minuteStep) {
        watchers.push($scope.$parent.$watch($parse($attrs.minuteStep), function (value) {
            minuteStep = +value;
        }));
    }

    var min;
    watchers.push($scope.$parent.$watch($parse($attrs.min), function (value) {
        var dt = new Date(value);
        min = isNaN(dt) ? undefined : dt;
    }));

    var max;
    watchers.push($scope.$parent.$watch($parse($attrs.max), function (value) {
        var dt = new Date(value);
        max = isNaN(dt) ? undefined : dt;
    }));

    var disabled = false;
    if ($attrs.ngDisabled) {
        watchers.push($scope.$parent.$watch($parse($attrs.ngDisabled), function (value) {
            disabled = value;
        }));
    }

    $scope.noIncrementHours = function () {
        var incrementedSelected = addMinutes(selected, hourStep * 60);
        return disabled || incrementedSelected > max ||
          incrementedSelected < selected && incrementedSelected < min;
    };

    $scope.noDecrementHours = function () {
        var decrementedSelected = addMinutes(selected, -hourStep * 60);
        return disabled || decrementedSelected < min ||
          decrementedSelected > selected && decrementedSelected > max;
    };

    $scope.noIncrementMinutes = function () {
        var incrementedSelected = addMinutes(selected, minuteStep);
        return disabled || incrementedSelected > max ||
          incrementedSelected < selected && incrementedSelected < min;
    };

    $scope.noDecrementMinutes = function () {
        var decrementedSelected = addMinutes(selected, -minuteStep);
        return disabled || decrementedSelected < min ||
          decrementedSelected > selected && decrementedSelected > max;
    };

    $scope.noIncrementSeconds = function () {
        var incrementedSelected = addSeconds(selected, secondStep);
        return disabled || incrementedSelected > max ||
          incrementedSelected < selected && incrementedSelected < min;
    };

    $scope.noDecrementSeconds = function () {
        var decrementedSelected = addSeconds(selected, -secondStep);
        return disabled || decrementedSelected < min ||
          decrementedSelected > selected && decrementedSelected > max;
    };

    $scope.noToggleMeridian = function () {
        if (selected.getHours() < 12) {
            return disabled || addMinutes(selected, 12 * 60) > max;
        }

        return disabled || addMinutes(selected, -12 * 60) < min;
    };

    var secondStep = timepickerConfig.secondStep;
    if ($attrs.secondStep) {
        watchers.push($scope.$parent.$watch($parse($attrs.secondStep), function (value) {
            secondStep = +value;
        }));
    }

    $scope.showSeconds = timepickerConfig.showSeconds;
    if ($attrs.showSeconds) {
        watchers.push($scope.$parent.$watch($parse($attrs.showSeconds), function (value) {
            $scope.showSeconds = !!value;
        }));
    }

    // 12H / 24H mode
    $scope.showMeridian = timepickerConfig.showMeridian;
    if ($attrs.showMeridian) {
        watchers.push($scope.$parent.$watch($parse($attrs.showMeridian), function (value) {
            $scope.showMeridian = !!value;

            if (ngModelCtrl.$error.time) {
                // Evaluate from template
                var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
                if (angular.isDefined(hours) && angular.isDefined(minutes)) {
                    selected.setHours(hours);
                    refresh();
                }
            } else {
                updateTemplate();
            }
        }));
    }

    // Get $scope.hours in 24H mode if valid
    function getHoursFromTemplate() {
        var hours = +$scope.hours;
        var valid = $scope.showMeridian ? hours > 0 && hours < 13 :
          hours >= 0 && hours < 24;
        if (!valid || $scope.hours === '') {
            return undefined;
        }

        if ($scope.showMeridian) {
            if (hours === 12) {
                hours = 0;
            }
            if ($scope.meridian === meridians[1]) {
                hours = hours + 12;
            }
        }
        return hours;
    }

    function getMinutesFromTemplate() {
        var minutes = +$scope.minutes;
        var valid = minutes >= 0 && minutes < 60;
        if (!valid || $scope.minutes === '') {
            return undefined;
        }
        return minutes;
    }

    function getSecondsFromTemplate() {
        var seconds = +$scope.seconds;
        return seconds >= 0 && seconds < 60 ? seconds : undefined;
    }

    function pad(value, noPad) {
        if (value === null) {
            return '';
        }

        return angular.isDefined(value) && value.toString().length < 2 && !noPad ?
          '0' + value : value.toString();
    }

    // Respond on mousewheel spin
    this.setupMousewheelEvents = function (hoursInputEl, minutesInputEl, secondsInputEl) {
        var isScrollingUp = function (e) {
            if (e.originalEvent) {
                e = e.originalEvent;
            }
            //pick correct delta variable depending on event
            var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY;
            return e.detail || delta > 0;
        };

        hoursInputEl.bind('mousewheel wheel', function (e) {
            if (!disabled) {
                $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
            }
            e.preventDefault();
        });

        minutesInputEl.bind('mousewheel wheel', function (e) {
            if (!disabled) {
                $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
            }
            e.preventDefault();
        });

        secondsInputEl.bind('mousewheel wheel', function (e) {
            if (!disabled) {
                $scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds());
            }
            e.preventDefault();
        });
    };

    // Respond on up/down arrowkeys
    this.setupArrowkeyEvents = function (hoursInputEl, minutesInputEl, secondsInputEl) {
        hoursInputEl.bind('keydown', function (e) {
            if (!disabled) {
                if (e.which === 38) { // up
                    e.preventDefault();
                    $scope.incrementHours();
                    $scope.$apply();
                } else if (e.which === 40) { // down
                    e.preventDefault();
                    $scope.decrementHours();
                    $scope.$apply();
                }
            }
        });

        minutesInputEl.bind('keydown', function (e) {
            if (!disabled) {
                if (e.which === 38) { // up
                    e.preventDefault();
                    $scope.incrementMinutes();
                    $scope.$apply();
                } else if (e.which === 40) { // down
                    e.preventDefault();
                    $scope.decrementMinutes();
                    $scope.$apply();
                }
            }
        });

        secondsInputEl.bind('keydown', function (e) {
            if (!disabled) {
                if (e.which === 38) { // up
                    e.preventDefault();
                    $scope.incrementSeconds();
                    $scope.$apply();
                } else if (e.which === 40) { // down
                    e.preventDefault();
                    $scope.decrementSeconds();
                    $scope.$apply();
                }
            }
        });
    };

    this.setupInputEvents = function (hoursInputEl, minutesInputEl, secondsInputEl) {
        if ($scope.readonlyInput) {
            $scope.updateHours = angular.noop;
            $scope.updateMinutes = angular.noop;
            $scope.updateSeconds = angular.noop;
            return;
        }

        var invalidate = function (invalidHours, invalidMinutes, invalidSeconds) {
            ngModelCtrl.$setViewValue(null);
            ngModelCtrl.$setValidity('time', false);
            if (angular.isDefined(invalidHours)) {
                $scope.invalidHours = invalidHours;
                if (hoursModelCtrl) {
                    hoursModelCtrl.$setValidity('hours', false);
                }
            }

            if (angular.isDefined(invalidMinutes)) {
                $scope.invalidMinutes = invalidMinutes;
                if (minutesModelCtrl) {
                    minutesModelCtrl.$setValidity('minutes', false);
                }
            }

            if (angular.isDefined(invalidSeconds)) {
                $scope.invalidSeconds = invalidSeconds;
                if (secondsModelCtrl) {
                    secondsModelCtrl.$setValidity('seconds', false);
                }
            }
        };

        $scope.updateHours = function () {
            var hours = getHoursFromTemplate(),
              minutes = getMinutesFromTemplate();

            ngModelCtrl.$setDirty();

            if (angular.isDefined(hours) && angular.isDefined(minutes)) {
                selected.setHours(hours);
                selected.setMinutes(minutes);
                if (selected < min || selected > max) {
                    invalidate(true);
                } else {
                    refresh('h');
                }
            } else {
                invalidate(true);
            }
        };

        hoursInputEl.bind('blur', function (e) {
            ngModelCtrl.$setTouched();
            if (modelIsEmpty()) {
                makeValid();
            } else if ($scope.hours === null || $scope.hours === '') {
                invalidate(true);
            } else if (!$scope.invalidHours && $scope.hours < 10) {
                $scope.$apply(function () {
                    $scope.hours = pad($scope.hours, !padHours);
                });
            }
        });

        $scope.updateMinutes = function () {
            var minutes = getMinutesFromTemplate(),
              hours = getHoursFromTemplate();

            ngModelCtrl.$setDirty();

            if (angular.isDefined(minutes) && angular.isDefined(hours)) {
                selected.setHours(hours);
                selected.setMinutes(minutes);
                if (selected < min || selected > max) {
                    invalidate(undefined, true);
                } else {
                    refresh('m');
                }
            } else {
                invalidate(undefined, true);
            }
        };

        minutesInputEl.bind('blur', function (e) {
            ngModelCtrl.$setTouched();
            if (modelIsEmpty()) {
                makeValid();
            } else if ($scope.minutes === null) {
                invalidate(undefined, true);
            } else if (!$scope.invalidMinutes && $scope.minutes < 10) {
                $scope.$apply(function () {
                    $scope.minutes = pad($scope.minutes);
                });
            }
        });

        $scope.updateSeconds = function () {
            var seconds = getSecondsFromTemplate();

            ngModelCtrl.$setDirty();

            if (angular.isDefined(seconds)) {
                selected.setSeconds(seconds);
                refresh('s');
            } else {
                invalidate(undefined, undefined, true);
            }
        };

        secondsInputEl.bind('blur', function (e) {
            if (modelIsEmpty()) {
                makeValid();
            } else if (!$scope.invalidSeconds && $scope.seconds < 10) {
                $scope.$apply(function () {
                    $scope.seconds = pad($scope.seconds);
                });
            }
        });

    };

    this.render = function () {
        var date = ngModelCtrl.$viewValue;

        if (isNaN(date)) {
            ngModelCtrl.$setValidity('time', false);
            $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
        } else {
            if (date) {
                selected = date;
            }

            if (selected < min || selected > max) {
                ngModelCtrl.$setValidity('time', false);
                $scope.invalidHours = true;
                $scope.invalidMinutes = true;
            } else {
                makeValid();
            }
            updateTemplate();
        }
    };

    // Call internally when we know that model is valid.
    function refresh(keyboardChange) {
        makeValid();
        ngModelCtrl.$setViewValue(new Date(selected));
        updateTemplate(keyboardChange);
    }

    function makeValid() {
        if (hoursModelCtrl) {
            hoursModelCtrl.$setValidity('hours', true);
        }

        if (minutesModelCtrl) {
            minutesModelCtrl.$setValidity('minutes', true);
        }

        if (secondsModelCtrl) {
            secondsModelCtrl.$setValidity('seconds', true);
        }

        ngModelCtrl.$setValidity('time', true);
        $scope.invalidHours = false;
        $scope.invalidMinutes = false;
        $scope.invalidSeconds = false;
    }

    function updateTemplate(keyboardChange) {
        if (!ngModelCtrl.$modelValue) {
            $scope.hours = null;
            $scope.minutes = null;
            $scope.seconds = null;
            $scope.meridian = meridians[0];
        } else {
            var hours = selected.getHours(),
              minutes = selected.getMinutes(),
              seconds = selected.getSeconds();

            if ($scope.showMeridian) {
                hours = hours === 0 || hours === 12 ? 12 : hours % 12; // Convert 24 to 12 hour system
            }

            $scope.hours = keyboardChange === 'h' ? hours : pad(hours, !padHours);
            if (keyboardChange !== 'm') {
                $scope.minutes = pad(minutes);
            }
            $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];

            if (keyboardChange !== 's') {
                $scope.seconds = pad(seconds);
            }
            $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
        }
    }

    function addSecondsToSelected(seconds) {
        selected = addSeconds(selected, seconds);
        refresh();
    }

    function addMinutes(selected, minutes) {
        return addSeconds(selected, minutes * 60);
    }

    function addSeconds(date, seconds) {
        var dt = new Date(date.getTime() + seconds * 1000);
        var newDate = new Date(date);
        newDate.setHours(dt.getHours(), dt.getMinutes(), dt.getSeconds());
        return newDate;
    }

    function modelIsEmpty() {
        return ($scope.hours === null || $scope.hours === '') &&
          ($scope.minutes === null || $scope.minutes === '') &&
          (!$scope.showSeconds || $scope.showSeconds && ($scope.seconds === null || $scope.seconds === ''));
    }

    $scope.showSpinners = angular.isDefined($attrs.showSpinners) ?
      $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;

    $scope.incrementHours = function () {
        if (!$scope.noIncrementHours()) {
            addSecondsToSelected(hourStep * 60 * 60);
        }
    };

    $scope.decrementHours = function () {
        if (!$scope.noDecrementHours()) {
            addSecondsToSelected(-hourStep * 60 * 60);
        }
    };

    $scope.incrementMinutes = function () {
        if (!$scope.noIncrementMinutes()) {
            addSecondsToSelected(minuteStep * 60);
        }
    };

    $scope.decrementMinutes = function () {
        if (!$scope.noDecrementMinutes()) {
            addSecondsToSelected(-minuteStep * 60);
        }
    };

    $scope.incrementSeconds = function () {
        if (!$scope.noIncrementSeconds()) {
            addSecondsToSelected(secondStep);
        }
    };

    $scope.decrementSeconds = function () {
        if (!$scope.noDecrementSeconds()) {
            addSecondsToSelected(-secondStep);
        }
    };

    $scope.toggleMeridian = function () {
        var minutes = getMinutesFromTemplate(),
            hours = getHoursFromTemplate();

        if (!$scope.noToggleMeridian()) {
            if (angular.isDefined(minutes) && angular.isDefined(hours)) {
                addSecondsToSelected(12 * 60 * (selected.getHours() < 12 ? 60 : -60));
            } else {
                $scope.meridian = $scope.meridian === meridians[0] ? meridians[1] : meridians[0];
            }
        }
    };

    $scope.blur = function () {
        ngModelCtrl.$setTouched();
    };

    $scope.$on('$destroy', function () {
        while (watchers.length) {
            watchers.shift()();
        }
    });
}])

.directive('uibTimepicker', ['uibTimepickerConfig', function (uibTimepickerConfig) {
    return {
        require: ['uibTimepicker', '?^ngModel'],
        restrict: 'A',
        controller: 'UibTimepickerController',
        controllerAs: 'timepicker',
        scope: {},
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || uibTimepickerConfig.templateUrl;
        },
        link: function (scope, element, attrs, ctrls) {
            var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            if (ngModelCtrl) {
                timepickerCtrl.init(ngModelCtrl, element.find('input'));
            }
        }
    };
}]);

angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap.position'])

/**
 * A helper service that can parse typeahead's syntax (string provided by users)
 * Extracted to a separate service for ease of unit testing
 */
  .factory('uibTypeaheadParser', ['$parse', function ($parse) {
      //                      000001111111100000000000002222222200000000000000003333333333333330000000000044444444000
      var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
      return {
          parse: function (input) {
              var match = input.match(TYPEAHEAD_REGEXP);
              if (!match) {
                  throw new Error(
                    'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' +
                      ' but got "' + input + '".');
              }

              return {
                  itemName: match[3],
                  source: $parse(match[4]),
                  viewMapper: $parse(match[2] || match[1]),
                  modelMapper: $parse(match[1])
              };
          }
      };
  }])

  .controller('UibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$$debounce', '$uibPosition', 'uibTypeaheadParser',
    function (originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $$debounce, $position, typeaheadParser) {
        var HOT_KEYS = [9, 13, 27, 38, 40];
        var eventDebounceTime = 200;
        var modelCtrl, ngModelOptions;
        //SUPPORTED ATTRIBUTES (OPTIONS)

        //minimal no of characters that needs to be entered before typeahead kicks-in
        var minLength = originalScope.$eval(attrs.typeaheadMinLength);
        if (!minLength && minLength !== 0) {
            minLength = 1;
        }

        originalScope.$watch(attrs.typeaheadMinLength, function (newVal) {
            minLength = !newVal && newVal !== 0 ? 1 : newVal;
        });

        //minimal wait time after last character typed before typeahead kicks-in
        var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;

        //should it restrict model values to the ones selected from the popup only?
        var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
        originalScope.$watch(attrs.typeaheadEditable, function (newVal) {
            isEditable = newVal !== false;
        });

        //binding to a variable that indicates if matches are being retrieved asynchronously
        var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;

        //a function to determine if an event should cause selection
        var isSelectEvent = attrs.typeaheadShouldSelect ? $parse(attrs.typeaheadShouldSelect) : function (scope, vals) {
            var evt = vals.$event;
            return evt.which === 13 || evt.which === 9;
        };

        //a callback executed when a match is selected
        var onSelectCallback = $parse(attrs.typeaheadOnSelect);

        //should it select highlighted popup value when losing focus?
        var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;

        //binding to a variable that indicates if there were no results after the query is completed
        var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;

        var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;

        var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;

        var appendTo = attrs.typeaheadAppendTo ?
          originalScope.$eval(attrs.typeaheadAppendTo) : null;

        var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;

        //If input matches an item of the list exactly, select it automatically
        var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;

        //binding to a variable that indicates if dropdown is open
        var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;

        var showHint = originalScope.$eval(attrs.typeaheadShowHint) || false;

        //INTERNAL VARIABLES

        //model setter executed upon match selection
        var parsedModel = $parse(attrs.ngModel);
        var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');
        var $setModelValue = function (scope, newValue) {
            if (angular.isFunction(parsedModel(originalScope)) &&
              ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) {
                return invokeModelSetter(scope, { $$$p: newValue });
            }

            return parsedModel.assign(scope, newValue);
        };

        //expressions used by typeahead
        var parserResult = typeaheadParser.parse(attrs.uibTypeahead);

        var hasFocus;

        //Used to avoid bug in iOS webview where iOS keyboard does not fire
        //mousedown & mouseup events
        //Issue #3699
        var selected;

        //create a child scope for the typeahead directive so we are not polluting original scope
        //with typeahead-specific data (matches, query etc.)
        var scope = originalScope.$new();
        var offDestroy = originalScope.$on('$destroy', function () {
            scope.$destroy();
        });
        scope.$on('$destroy', offDestroy);

        // WAI-ARIA
        var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
        element.attr({
            'aria-autocomplete': 'list',
            'aria-expanded': false,
            'aria-owns': popupId
        });

        var inputsContainer, hintInputElem;
        //add read-only input to show hint
        if (showHint) {
            inputsContainer = angular.element('<div></div>');
            inputsContainer.css('position', 'relative');
            element.after(inputsContainer);
            hintInputElem = element.clone();
            hintInputElem.attr('placeholder', '');
            hintInputElem.attr('tabindex', '-1');
            hintInputElem.val('');
            hintInputElem.css({
                'position': 'absolute',
                'top': '0px',
                'left': '0px',
                'border-color': 'transparent',
                'box-shadow': 'none',
                'opacity': 1,
                'background': 'none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)',
                'color': '#999'
            });
            element.css({
                'position': 'relative',
                'vertical-align': 'top',
                'background-color': 'transparent'
            });

            if (hintInputElem.attr('id')) {
                hintInputElem.removeAttr('id'); // remove duplicate id if present.
            }
            inputsContainer.append(hintInputElem);
            hintInputElem.after(element);
        }

        //pop-up element used to display matches
        var popUpEl = angular.element('<div uib-typeahead-popup></div>');
        popUpEl.attr({
            id: popupId,
            matches: 'matches',
            active: 'activeIdx',
            select: 'select(activeIdx, evt)',
            'move-in-progress': 'moveInProgress',
            query: 'query',
            position: 'position',
            'assign-is-open': 'assignIsOpen(isOpen)',
            debounce: 'debounceUpdate'
        });
        //custom item template
        if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
            popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
        }

        if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {
            popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);
        }

        var resetHint = function () {
            if (showHint) {
                hintInputElem.val('');
            }
        };

        var resetMatches = function () {
            scope.matches = [];
            scope.activeIdx = -1;
            element.attr('aria-expanded', false);
            resetHint();
        };

        var getMatchId = function (index) {
            return popupId + '-option-' + index;
        };

        // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.
        // This attribute is added or removed automatically when the `activeIdx` changes.
        scope.$watch('activeIdx', function (index) {
            if (index < 0) {
                element.removeAttr('aria-activedescendant');
            } else {
                element.attr('aria-activedescendant', getMatchId(index));
            }
        });

        var inputIsExactMatch = function (inputValue, index) {
            if (scope.matches.length > index && inputValue) {
                return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();
            }

            return false;
        };

        var getMatchesAsync = function (inputValue, evt) {
            var locals = { $viewValue: inputValue };
            isLoadingSetter(originalScope, true);
            isNoResultsSetter(originalScope, false);
            $q.when(parserResult.source(originalScope, locals)).then(function (matches) {
                //it might happen that several async queries were in progress if a user were typing fast
                //but we are interested only in responses that correspond to the current view value
                var onCurrentRequest = inputValue === modelCtrl.$viewValue;
                if (onCurrentRequest && hasFocus) {
                    if (matches && matches.length > 0) {
                        scope.activeIdx = focusFirst ? 0 : -1;
                        isNoResultsSetter(originalScope, false);
                        scope.matches.length = 0;

                        //transform labels
                        for (var i = 0; i < matches.length; i++) {
                            locals[parserResult.itemName] = matches[i];
                            scope.matches.push({
                                id: getMatchId(i),
                                label: parserResult.viewMapper(scope, locals),
                                model: matches[i]
                            });
                        }

                        scope.query = inputValue;
                        //position pop-up with matches - we need to re-calculate its position each time we are opening a window
                        //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
                        //due to other elements being rendered
                        recalculatePosition();

                        element.attr('aria-expanded', true);

                        //Select the single remaining option if user input matches
                        if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {
                            if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
                                $$debounce(function () {
                                    scope.select(0, evt);
                                }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
                            } else {
                                scope.select(0, evt);
                            }
                        }

                        if (showHint) {
                            var firstLabel = scope.matches[0].label;
                            if (angular.isString(inputValue) &&
                              inputValue.length > 0 &&
                              firstLabel.slice(0, inputValue.length).toUpperCase() === inputValue.toUpperCase()) {
                                hintInputElem.val(inputValue + firstLabel.slice(inputValue.length));
                            } else {
                                hintInputElem.val('');
                            }
                        }
                    } else {
                        resetMatches();
                        isNoResultsSetter(originalScope, true);
                    }
                }
                if (onCurrentRequest) {
                    isLoadingSetter(originalScope, false);
                }
            }, function () {
                resetMatches();
                isLoadingSetter(originalScope, false);
                isNoResultsSetter(originalScope, true);
            });
        };

        // bind events only if appendToBody params exist - performance feature
        if (appendToBody) {
            angular.element($window).on('resize', fireRecalculating);
            $document.find('body').on('scroll', fireRecalculating);
        }

        // Declare the debounced function outside recalculating for
        // proper debouncing
        var debouncedRecalculate = $$debounce(function () {
            // if popup is visible
            if (scope.matches.length) {
                recalculatePosition();
            }

            scope.moveInProgress = false;
        }, eventDebounceTime);

        // Default progress type
        scope.moveInProgress = false;

        function fireRecalculating() {
            if (!scope.moveInProgress) {
                scope.moveInProgress = true;
                scope.$digest();
            }

            debouncedRecalculate();
        }

        // recalculate actual position and set new values to scope
        // after digest loop is popup in right position
        function recalculatePosition() {
            scope.position = appendToBody ? $position.offset(element) : $position.position(element);
            scope.position.top += element.prop('offsetHeight');
        }

        //we need to propagate user's query so we can higlight matches
        scope.query = undefined;

        //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
        var timeoutPromise;

        var scheduleSearchWithTimeout = function (inputValue) {
            timeoutPromise = $timeout(function () {
                getMatchesAsync(inputValue);
            }, waitTime);
        };

        var cancelPreviousTimeout = function () {
            if (timeoutPromise) {
                $timeout.cancel(timeoutPromise);
            }
        };

        resetMatches();

        scope.assignIsOpen = function (isOpen) {
            isOpenSetter(originalScope, isOpen);
        };

        scope.select = function (activeIdx, evt) {
            //called from within the $digest() cycle
            var locals = {};
            var model, item;

            selected = true;
            locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
            model = parserResult.modelMapper(originalScope, locals);
            $setModelValue(originalScope, model);
            modelCtrl.$setValidity('editable', true);
            modelCtrl.$setValidity('parse', true);

            onSelectCallback(originalScope, {
                $item: item,
                $model: model,
                $label: parserResult.viewMapper(originalScope, locals),
                $event: evt
            });

            resetMatches();

            //return focus to the input element if a match was selected via a mouse click event
            // use timeout to avoid $rootScope:inprog error
            if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {
                $timeout(function () { element[0].focus(); }, 0, false);
            }
        };

        //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
        element.on('keydown', function (evt) {
            //typeahead is open and an "interesting" key was pressed
            if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
                return;
            }

            var shouldSelect = isSelectEvent(originalScope, { $event: evt });

            /**
             * if there's nothing selected (i.e. focusFirst) and enter or tab is hit
             * or
             * shift + tab is pressed to bring focus to the previous element
             * then clear the results
             */
            if (scope.activeIdx === -1 && shouldSelect || evt.which === 9 && !!evt.shiftKey) {
                resetMatches();
                scope.$digest();
                return;
            }

            evt.preventDefault();
            var target;
            switch (evt.which) {
                case 27: // escape
                    evt.stopPropagation();

                    resetMatches();
                    originalScope.$digest();
                    break;
                case 38: // up arrow
                    scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
                    scope.$digest();
                    target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
                    target.parentNode.scrollTop = target.offsetTop;
                    break;
                case 40: // down arrow
                    scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
                    scope.$digest();
                    target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
                    target.parentNode.scrollTop = target.offsetTop;
                    break;
                default:
                    if (shouldSelect) {
                        scope.$apply(function () {
                            if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
                                $$debounce(function () {
                                    scope.select(scope.activeIdx, evt);
                                }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
                            } else {
                                scope.select(scope.activeIdx, evt);
                            }
                        });
                    }
            }
        });

        element.bind('focus', function (evt) {
            hasFocus = true;
            if (minLength === 0 && !modelCtrl.$viewValue) {
                $timeout(function () {
                    getMatchesAsync(modelCtrl.$viewValue, evt);
                }, 0);
            }
        });

        element.bind('blur', function (evt) {
            if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {
                selected = true;
                scope.$apply(function () {
                    if (angular.isObject(scope.debounceUpdate) && angular.isNumber(scope.debounceUpdate.blur)) {
                        $$debounce(function () {
                            scope.select(scope.activeIdx, evt);
                        }, scope.debounceUpdate.blur);
                    } else {
                        scope.select(scope.activeIdx, evt);
                    }
                });
            }
            if (!isEditable && modelCtrl.$error.editable) {
                modelCtrl.$setViewValue();
                scope.$apply(function () {
                    // Reset validity as we are clearing
                    modelCtrl.$setValidity('editable', true);
                    modelCtrl.$setValidity('parse', true);
                });
                element.val('');
            }
            hasFocus = false;
            selected = false;
        });

        // Keep reference to click handler to unbind it.
        var dismissClickHandler = function (evt) {
            // Issue #3973
            // Firefox treats right click as a click on document
            if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {
                resetMatches();
                if (!$rootScope.$$phase) {
                    originalScope.$digest();
                }
            }
        };

        $document.on('click', dismissClickHandler);

        originalScope.$on('$destroy', function () {
            $document.off('click', dismissClickHandler);
            if (appendToBody || appendTo) {
                $popup.remove();
            }

            if (appendToBody) {
                angular.element($window).off('resize', fireRecalculating);
                $document.find('body').off('scroll', fireRecalculating);
            }
            // Prevent jQuery cache memory leak
            popUpEl.remove();

            if (showHint) {
                inputsContainer.remove();
            }
        });

        var $popup = $compile(popUpEl)(scope);

        if (appendToBody) {
            $document.find('body').append($popup);
        } else if (appendTo) {
            angular.element(appendTo).eq(0).append($popup);
        } else {
            element.after($popup);
        }

        this.init = function (_modelCtrl, _ngModelOptions) {
            modelCtrl = _modelCtrl;
            ngModelOptions = _ngModelOptions;

            scope.debounceUpdate = modelCtrl.$options && $parse(modelCtrl.$options.debounce)(originalScope);

            //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
            //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
            modelCtrl.$parsers.unshift(function (inputValue) {
                hasFocus = true;

                if (minLength === 0 || inputValue && inputValue.length >= minLength) {
                    if (waitTime > 0) {
                        cancelPreviousTimeout();
                        scheduleSearchWithTimeout(inputValue);
                    } else {
                        getMatchesAsync(inputValue);
                    }
                } else {
                    isLoadingSetter(originalScope, false);
                    cancelPreviousTimeout();
                    resetMatches();
                }

                if (isEditable) {
                    return inputValue;
                }

                if (!inputValue) {
                    // Reset in case user had typed something previously.
                    modelCtrl.$setValidity('editable', true);
                    return null;
                }

                modelCtrl.$setValidity('editable', false);
                return undefined;
            });

            modelCtrl.$formatters.push(function (modelValue) {
                var candidateViewValue, emptyViewValue;
                var locals = {};

                // The validity may be set to false via $parsers (see above) if
                // the model is restricted to selected values. If the model
                // is set manually it is considered to be valid.
                if (!isEditable) {
                    modelCtrl.$setValidity('editable', true);
                }

                if (inputFormatter) {
                    locals.$model = modelValue;
                    return inputFormatter(originalScope, locals);
                }

                //it might happen that we don't have enough info to properly render input value
                //we need to check for this situation and simply return model value if we can't apply custom formatting
                locals[parserResult.itemName] = modelValue;
                candidateViewValue = parserResult.viewMapper(originalScope, locals);
                locals[parserResult.itemName] = undefined;
                emptyViewValue = parserResult.viewMapper(originalScope, locals);

                return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;
            });
        };
    }])

  .directive('uibTypeahead', function () {
      return {
          controller: 'UibTypeaheadController',
          require: ['ngModel', '^?ngModelOptions', 'uibTypeahead'],
          link: function (originalScope, element, attrs, ctrls) {
              ctrls[2].init(ctrls[0], ctrls[1]);
          }
      };
  })

  .directive('uibTypeaheadPopup', ['$$debounce', function ($$debounce) {
      return {
          scope: {
              matches: '=',
              query: '=',
              active: '=',
              position: '&',
              moveInProgress: '=',
              select: '&',
              assignIsOpen: '&',
              debounce: '&'
          },
          replace: true,
          templateUrl: function (element, attrs) {
              return attrs.popupTemplateUrl || 'uib/template/typeahead/typeahead-popup.html';
          },
          link: function (scope, element, attrs) {
              scope.templateUrl = attrs.templateUrl;

              scope.isOpen = function () {
                  var isDropdownOpen = scope.matches.length > 0;
                  scope.assignIsOpen({ isOpen: isDropdownOpen });
                  return isDropdownOpen;
              };

              scope.isActive = function (matchIdx) {
                  return scope.active === matchIdx;
              };

              scope.selectActive = function (matchIdx) {
                  scope.active = matchIdx;
              };

              scope.selectMatch = function (activeIdx, evt) {
                  var debounce = scope.debounce();
                  if (angular.isNumber(debounce) || angular.isObject(debounce)) {
                      $$debounce(function () {
                          scope.select({ activeIdx: activeIdx, evt: evt });
                      }, angular.isNumber(debounce) ? debounce : debounce['default']);
                  } else {
                      scope.select({ activeIdx: activeIdx, evt: evt });
                  }
              };
          }
      };
  }])

  .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function ($templateRequest, $compile, $parse) {
      return {
          scope: {
              index: '=',
              match: '=',
              query: '='
          },
          link: function (scope, element, attrs) {
              var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'uib/template/typeahead/typeahead-match.html';
              $templateRequest(tplUrl).then(function (tplContent) {
                  var tplEl = angular.element(tplContent.trim());
                  element.replaceWith(tplEl);
                  $compile(tplEl)(scope);
              });
          }
      };
  }])

  .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function ($sce, $injector, $log) {
      var isSanitizePresent;
      isSanitizePresent = $injector.has('$sanitize');

      function escapeRegexp(queryToEscape) {
          // Regex: capture the whole query string and replace it with the string that will be used to match
          // the results, for example if the capture is "a" the result will be \a
          return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
      }

      function containsHtml(matchItem) {
          return /<.*>/g.test(matchItem);
      }

      return function (matchItem, query) {
          if (!isSanitizePresent && containsHtml(matchItem)) {
              $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger
          }
          matchItem = query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem; // Replaces the capture string with a the same string inside of a "strong" tag
          if (!isSanitizePresent) {
              matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive
          }
          return matchItem;
      };
  }]);
angular.module('ui.bootstrap.carousel').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibCarouselCss && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'); angular.$$uibCarouselCss = true; });
angular.module('ui.bootstrap.datepicker').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibDatepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'); angular.$$uibDatepickerCss = true; });
angular.module('ui.bootstrap.position').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibPositionCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'); angular.$$uibPositionCss = true; });
angular.module('ui.bootstrap.datepickerPopup').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibDatepickerpopupCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'); angular.$$uibDatepickerpopupCss = true; });
angular.module('ui.bootstrap.tooltip').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });
angular.module('ui.bootstrap.timepicker').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibTimepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-time input{width:50px;}</style>'); angular.$$uibTimepickerCss = true; });
angular.module('ui.bootstrap.typeahead').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; });;
/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/
 * Version: 2.3.0 - 2016-11-26
 * License: MIT
 */angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.collapse", "ui.bootstrap.tabindex", "ui.bootstrap.accordion", "ui.bootstrap.alert", "ui.bootstrap.buttons", "ui.bootstrap.carousel", "ui.bootstrap.dateparser", "ui.bootstrap.isClass", "ui.bootstrap.datepicker", "ui.bootstrap.position", "ui.bootstrap.datepickerPopup", "ui.bootstrap.debounce", "ui.bootstrap.dropdown", "ui.bootstrap.stackedMap", "ui.bootstrap.modal", "ui.bootstrap.paging", "ui.bootstrap.pager", "ui.bootstrap.pagination", "ui.bootstrap.tooltip", "ui.bootstrap.popover", "ui.bootstrap.progressbar", "ui.bootstrap.rating", "ui.bootstrap.tabs", "ui.bootstrap.timepicker", "ui.bootstrap.typeahead"]);
angular.module("ui.bootstrap.tpls", ["uib/template/accordion/accordion-group.html", "uib/template/accordion/accordion.html", "uib/template/alert/alert.html", "uib/template/carousel/carousel.html", "uib/template/carousel/slide.html", "uib/template/datepicker/datepicker.html", "uib/template/datepicker/day.html", "uib/template/datepicker/month.html", "uib/template/datepicker/year.html", "uib/template/datepickerPopup/popup.html", "uib/template/modal/window.html", "uib/template/pager/pager.html", "uib/template/pagination/pagination.html", "uib/template/tooltip/tooltip-html-popup.html", "uib/template/tooltip/tooltip-popup.html", "uib/template/tooltip/tooltip-template-popup.html", "uib/template/popover/popover-html.html", "uib/template/popover/popover-template.html", "uib/template/popover/popover.html", "uib/template/progressbar/bar.html", "uib/template/progressbar/progress.html", "uib/template/progressbar/progressbar.html", "uib/template/rating/rating.html", "uib/template/tabs/tab.html", "uib/template/tabs/tabset.html", "uib/template/timepicker/timepicker.html", "uib/template/typeahead/typeahead-match.html", "uib/template/typeahead/typeahead-popup.html"]);
angular.module('ui.bootstrap.collapse', [])

  .directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function ($animate, $q, $parse, $injector) {
      var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;
      return {
          link: function (scope, element, attrs) {
              var expandingExpr = $parse(attrs.expanding),
                expandedExpr = $parse(attrs.expanded),
                collapsingExpr = $parse(attrs.collapsing),
                collapsedExpr = $parse(attrs.collapsed),
                horizontal = false,
                css = {},
                cssTo = {};

              init();

              function init() {
                  horizontal = !!('horizontal' in attrs);
                  if (horizontal) {
                      css = {
                          width: ''
                      };
                      cssTo = { width: '0' };
                  } else {
                      css = {
                          height: ''
                      };
                      cssTo = { height: '0' };
                  }
                  if (!scope.$eval(attrs.uibCollapse)) {
                      element.addClass('in')
                        .addClass('collapse')
                        .attr('aria-expanded', true)
                        .attr('aria-hidden', false)
                        .css(css);
                  }
              }

              function getScrollFromElement(element) {
                  if (horizontal) {
                      return { width: element.scrollWidth + 'px' };
                  }
                  return { height: element.scrollHeight + 'px' };
              }

              function expand() {
                  if (element.hasClass('collapse') && element.hasClass('in')) {
                      return;
                  }

                  $q.resolve(expandingExpr(scope))
                    .then(function () {
                        element.removeClass('collapse')
                          .addClass('collapsing')
                          .attr('aria-expanded', true)
                          .attr('aria-hidden', false);

                        if ($animateCss) {
                            $animateCss(element, {
                                addClass: 'in',
                                easing: 'ease',
                                css: {
                                    overflow: 'hidden'
                                },
                                to: getScrollFromElement(element[0])
                            }).start()['finally'](expandDone);
                        } else {
                            $animate.addClass(element, 'in', {
                                css: {
                                    overflow: 'hidden'
                                },
                                to: getScrollFromElement(element[0])
                            }).then(expandDone);
                        }
                    });
              }

              function expandDone() {
                  element.removeClass('collapsing')
                    .addClass('collapse')
                    .css(css);
                  expandedExpr(scope);
              }

              function collapse() {
                  if (!element.hasClass('collapse') && !element.hasClass('in')) {
                      return collapseDone();
                  }

                  $q.resolve(collapsingExpr(scope))
                    .then(function () {
                        element
                        // IMPORTANT: The width must be set before adding "collapsing" class.
                        // Otherwise, the browser attempts to animate from width 0 (in
                        // collapsing class) to the given width here.
                          .css(getScrollFromElement(element[0]))
                          // initially all panel collapse have the collapse class, this removal
                          // prevents the animation from jumping to collapsed state
                          .removeClass('collapse')
                          .addClass('collapsing')
                          .attr('aria-expanded', false)
                          .attr('aria-hidden', true);

                        if ($animateCss) {
                            $animateCss(element, {
                                removeClass: 'in',
                                to: cssTo
                            }).start()['finally'](collapseDone);
                        } else {
                            $animate.removeClass(element, 'in', {
                                to: cssTo
                            }).then(collapseDone);
                        }
                    });
              }

              function collapseDone() {
                  element.css(cssTo); // Required so that collapse works when animation is disabled
                  element.removeClass('collapsing')
                    .addClass('collapse');
                  collapsedExpr(scope);
              }

              scope.$watch(attrs.uibCollapse, function (shouldCollapse) {
                  if (shouldCollapse) {
                      collapse();
                  } else {
                      expand();
                  }
              });
          }
      };
  }]);

angular.module('ui.bootstrap.tabindex', [])

.directive('uibTabindexToggle', function () {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            attrs.$observe('disabled', function (disabled) {
                attrs.$set('tabindex', disabled ? -1 : null);
            });
        }
    };
});

angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex'])

.constant('uibAccordionConfig', {
    closeOthers: true
})

.controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function ($scope, $attrs, accordionConfig) {
    // This array keeps track of the accordion groups
    this.groups = [];

    // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
    this.closeOthers = function (openGroup) {
        var closeOthers = angular.isDefined($attrs.closeOthers) ?
          $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
        if (closeOthers) {
            angular.forEach(this.groups, function (group) {
                if (group !== openGroup) {
                    group.isOpen = false;
                }
            });
        }
    };

    // This is called from the accordion-group directive to add itself to the accordion
    this.addGroup = function (groupScope) {
        var that = this;
        this.groups.push(groupScope);

        groupScope.$on('$destroy', function (event) {
            that.removeGroup(groupScope);
        });
    };

    // This is called from the accordion-group directive when to remove itself
    this.removeGroup = function (group) {
        var index = this.groups.indexOf(group);
        if (index !== -1) {
            this.groups.splice(index, 1);
        }
    };
}])

// The accordion directive simply sets up the directive controller
// and adds an accordion CSS class to itself element.
.directive('uibAccordion', function () {
    return {
        controller: 'UibAccordionController',
        controllerAs: 'accordion',
        transclude: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/accordion/accordion.html';
        }
    };
})

// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
.directive('uibAccordionGroup', function () {
    return {
        require: '^uibAccordion',         // We need this directive to be inside an accordion
        transclude: true,              // It transcludes the contents of the directive into the template
        restrict: 'A',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
        },
        scope: {
            heading: '@',               // Interpolate the heading attribute onto this scope
            panelClass: '@?',           // Ditto with panelClass
            isOpen: '=?',
            isDisabled: '=?'
        },
        controller: function () {
            this.setHeading = function (element) {
                this.heading = element;
            };
        },
        link: function (scope, element, attrs, accordionCtrl) {
            element.addClass('panel');
            accordionCtrl.addGroup(scope);

            scope.openClass = attrs.openClass || 'panel-open';
            scope.panelClass = attrs.panelClass || 'panel-default';
            scope.$watch('isOpen', function (value) {
                element.toggleClass(scope.openClass, !!value);
                if (value) {
                    accordionCtrl.closeOthers(scope);
                }
            });

            scope.toggleOpen = function ($event) {
                if (!scope.isDisabled) {
                    if (!$event || $event.which === 32) {
                        scope.isOpen = !scope.isOpen;
                    }
                }
            };

            var id = 'accordiongroup-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
            scope.headingId = id + '-tab';
            scope.panelId = id + '-panel';
        }
    };
})

// Use accordion-heading below an accordion-group to provide a heading containing HTML
.directive('uibAccordionHeading', function () {
    return {
        transclude: true,   // Grab the contents to be used as the heading
        template: '',       // In effect remove this element!
        replace: true,
        require: '^uibAccordionGroup',
        link: function (scope, element, attrs, accordionGroupCtrl, transclude) {
            // Pass the heading to the accordion-group controller
            // so that it can be transcluded into the right place in the template
            // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
            accordionGroupCtrl.setHeading(transclude(scope, angular.noop));
        }
    };
})

// Use in the accordion-group template to indicate where you want the heading to be transcluded
// You must provide the property on the accordion-group controller that will hold the transcluded element
.directive('uibAccordionTransclude', function () {
    return {
        require: '^uibAccordionGroup',
        link: function (scope, element, attrs, controller) {
            scope.$watch(function () { return controller[attrs.uibAccordionTransclude]; }, function (heading) {
                if (heading) {
                    var elem = angular.element(element[0].querySelector(getHeaderSelectors()));
                    elem.html('');
                    elem.append(heading);
                }
            });
        }
    };

    function getHeaderSelectors() {
        return 'uib-accordion-header,' +
            'data-uib-accordion-header,' +
            'x-uib-accordion-header,' +
            'uib\\:accordion-header,' +
            '[uib-accordion-header],' +
            '[data-uib-accordion-header],' +
            '[x-uib-accordion-header]';
    }
});

angular.module('ui.bootstrap.alert', [])

.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function ($scope, $element, $attrs, $interpolate, $timeout) {
    $scope.closeable = !!$attrs.close;
    $element.addClass('alert');
    $attrs.$set('role', 'alert');
    if ($scope.closeable) {
        $element.addClass('alert-dismissible');
    }

    var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?
      $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;

    if (dismissOnTimeout) {
        $timeout(function () {
            $scope.close();
        }, parseInt(dismissOnTimeout, 10));
    }
}])

.directive('uibAlert', function () {
    return {
        controller: 'UibAlertController',
        controllerAs: 'alert',
        restrict: 'A',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/alert/alert.html';
        },
        transclude: true,
        scope: {
            close: '&'
        }
    };
});

angular.module('ui.bootstrap.buttons', [])

.constant('uibButtonConfig', {
    activeClass: 'active',
    toggleEvent: 'click'
})

.controller('UibButtonsController', ['uibButtonConfig', function (buttonConfig) {
    this.activeClass = buttonConfig.activeClass || 'active';
    this.toggleEvent = buttonConfig.toggleEvent || 'click';
}])

.directive('uibBtnRadio', ['$parse', function ($parse) {
    return {
        require: ['uibBtnRadio', 'ngModel'],
        controller: 'UibButtonsController',
        controllerAs: 'buttons',
        link: function (scope, element, attrs, ctrls) {
            var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
            var uncheckableExpr = $parse(attrs.uibUncheckable);

            element.find('input').css({ display: 'none' });

            //model -> UI
            ngModelCtrl.$render = function () {
                element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));
            };

            //ui->model
            element.on(buttonsCtrl.toggleEvent, function () {
                if (attrs.disabled) {
                    return;
                }

                var isActive = element.hasClass(buttonsCtrl.activeClass);

                if (!isActive || angular.isDefined(attrs.uncheckable)) {
                    scope.$apply(function () {
                        ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));
                        ngModelCtrl.$render();
                    });
                }
            });

            if (attrs.uibUncheckable) {
                scope.$watch(uncheckableExpr, function (uncheckable) {
                    attrs.$set('uncheckable', uncheckable ? '' : undefined);
                });
            }
        }
    };
}])

.directive('uibBtnCheckbox', function () {
    return {
        require: ['uibBtnCheckbox', 'ngModel'],
        controller: 'UibButtonsController',
        controllerAs: 'button',
        link: function (scope, element, attrs, ctrls) {
            var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            element.find('input').css({ display: 'none' });

            function getTrueValue() {
                return getCheckboxValue(attrs.btnCheckboxTrue, true);
            }

            function getFalseValue() {
                return getCheckboxValue(attrs.btnCheckboxFalse, false);
            }

            function getCheckboxValue(attribute, defaultValue) {
                return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;
            }

            //model -> UI
            ngModelCtrl.$render = function () {
                element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
            };

            //ui->model
            element.on(buttonsCtrl.toggleEvent, function () {
                if (attrs.disabled) {
                    return;
                }

                scope.$apply(function () {
                    ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
                    ngModelCtrl.$render();
                });
            });
        }
    };
});

angular.module('ui.bootstrap.carousel', [])

.controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function ($scope, $element, $interval, $timeout, $animate) {
    var self = this,
      slides = self.slides = $scope.slides = [],
      SLIDE_DIRECTION = 'uib-slideDirection',
      currentIndex = $scope.active,
      currentInterval, isPlaying, bufferedTransitions = [];

    var destroyed = false;
    $element.addClass('carousel');

    self.addSlide = function (slide, element) {
        slides.push({
            slide: slide,
            element: element
        });
        slides.sort(function (a, b) {
            return +a.slide.index - +b.slide.index;
        });
        //if this is the first slide or the slide is set to active, select it
        if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) {
            if ($scope.$currentTransition) {
                $scope.$currentTransition = null;
            }

            currentIndex = slide.index;
            $scope.active = slide.index;
            setActive(currentIndex);
            self.select(slides[findSlideIndex(slide)]);
            if (slides.length === 1) {
                $scope.play();
            }
        }
    };

    self.getCurrentIndex = function () {
        for (var i = 0; i < slides.length; i++) {
            if (slides[i].slide.index === currentIndex) {
                return i;
            }
        }
    };

    self.next = $scope.next = function () {
        var newIndex = (self.getCurrentIndex() + 1) % slides.length;

        if (newIndex === 0 && $scope.noWrap()) {
            $scope.pause();
            return;
        }

        return self.select(slides[newIndex], 'next');
    };

    self.prev = $scope.prev = function () {
        var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;

        if ($scope.noWrap() && newIndex === slides.length - 1) {
            $scope.pause();
            return;
        }

        return self.select(slides[newIndex], 'prev');
    };

    self.removeSlide = function (slide) {
        var index = findSlideIndex(slide);

        var bufferedIndex = bufferedTransitions.indexOf(slides[index]);
        if (bufferedIndex !== -1) {
            bufferedTransitions.splice(bufferedIndex, 1);
        }

        //get the index of the slide inside the carousel
        slides.splice(index, 1);
        if (slides.length > 0 && currentIndex === index) {
            if (index >= slides.length) {
                currentIndex = slides.length - 1;
                $scope.active = currentIndex;
                setActive(currentIndex);
                self.select(slides[slides.length - 1]);
            } else {
                currentIndex = index;
                $scope.active = currentIndex;
                setActive(currentIndex);
                self.select(slides[index]);
            }
        } else if (currentIndex > index) {
            currentIndex--;
            $scope.active = currentIndex;
        }

        //clean the active value when no more slide
        if (slides.length === 0) {
            currentIndex = null;
            $scope.active = null;
            clearBufferedTransitions();
        }
    };

    /* direction: "prev" or "next" */
    self.select = $scope.select = function (nextSlide, direction) {
        var nextIndex = findSlideIndex(nextSlide.slide);
        //Decide direction if it's not given
        if (direction === undefined) {
            direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
        }
        //Prevent this user-triggered transition from occurring if there is already one in progress
        if (nextSlide.slide.index !== currentIndex &&
          !$scope.$currentTransition) {
            goNext(nextSlide.slide, nextIndex, direction);
        } else if (nextSlide && nextSlide.slide.index !== currentIndex && $scope.$currentTransition) {
            bufferedTransitions.push(slides[nextIndex]);
        }
    };

    /* Allow outside people to call indexOf on slides array */
    $scope.indexOfSlide = function (slide) {
        return +slide.slide.index;
    };

    $scope.isActive = function (slide) {
        return $scope.active === slide.slide.index;
    };

    $scope.isPrevDisabled = function () {
        return $scope.active === 0 && $scope.noWrap();
    };

    $scope.isNextDisabled = function () {
        return $scope.active === slides.length - 1 && $scope.noWrap();
    };

    $scope.pause = function () {
        if (!$scope.noPause) {
            isPlaying = false;
            resetTimer();
        }
    };

    $scope.play = function () {
        if (!isPlaying) {
            isPlaying = true;
            restartTimer();
        }
    };

    $element.on('mouseenter', $scope.pause);
    $element.on('mouseleave', $scope.play);

    $scope.$on('$destroy', function () {
        destroyed = true;
        resetTimer();
    });

    $scope.$watch('noTransition', function (noTransition) {
        $animate.enabled($element, !noTransition);
    });

    $scope.$watch('interval', restartTimer);

    $scope.$watchCollection('slides', resetTransition);

    $scope.$watch('active', function (index) {
        if (angular.isNumber(index) && currentIndex !== index) {
            for (var i = 0; i < slides.length; i++) {
                if (slides[i].slide.index === index) {
                    index = i;
                    break;
                }
            }

            var slide = slides[index];
            if (slide) {
                setActive(index);
                self.select(slides[index]);
                currentIndex = index;
            }
        }
    });

    function clearBufferedTransitions() {
        while (bufferedTransitions.length) {
            bufferedTransitions.shift();
        }
    }

    function getSlideByIndex(index) {
        for (var i = 0, l = slides.length; i < l; ++i) {
            if (slides[i].index === index) {
                return slides[i];
            }
        }
    }

    function setActive(index) {
        for (var i = 0; i < slides.length; i++) {
            slides[i].slide.active = i === index;
        }
    }

    function goNext(slide, index, direction) {
        if (destroyed) {
            return;
        }

        angular.extend(slide, { direction: direction });
        angular.extend(slides[currentIndex].slide || {}, { direction: direction });
        if ($animate.enabled($element) && !$scope.$currentTransition &&
          slides[index].element && self.slides.length > 1) {
            slides[index].element.data(SLIDE_DIRECTION, slide.direction);
            var currentIdx = self.getCurrentIndex();

            if (angular.isNumber(currentIdx) && slides[currentIdx].element) {
                slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction);
            }

            $scope.$currentTransition = true;
            $animate.on('addClass', slides[index].element, function (element, phase) {
                if (phase === 'close') {
                    $scope.$currentTransition = null;
                    $animate.off('addClass', element);
                    if (bufferedTransitions.length) {
                        var nextSlide = bufferedTransitions.pop().slide;
                        var nextIndex = nextSlide.index;
                        var nextDirection = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
                        clearBufferedTransitions();

                        goNext(nextSlide, nextIndex, nextDirection);
                    }
                }
            });
        }

        $scope.active = slide.index;
        currentIndex = slide.index;
        setActive(index);

        //every time you change slides, reset the timer
        restartTimer();
    }

    function findSlideIndex(slide) {
        for (var i = 0; i < slides.length; i++) {
            if (slides[i].slide === slide) {
                return i;
            }
        }
    }

    function resetTimer() {
        if (currentInterval) {
            $interval.cancel(currentInterval);
            currentInterval = null;
        }
    }

    function resetTransition(slides) {
        if (!slides.length) {
            $scope.$currentTransition = null;
            clearBufferedTransitions();
        }
    }

    function restartTimer() {
        resetTimer();
        var interval = +$scope.interval;
        if (!isNaN(interval) && interval > 0) {
            currentInterval = $interval(timerFn, interval);
        }
    }

    function timerFn() {
        var interval = +$scope.interval;
        if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
            $scope.next();
        } else {
            $scope.pause();
        }
    }
}])

.directive('uibCarousel', function () {
    return {
        transclude: true,
        controller: 'UibCarouselController',
        controllerAs: 'carousel',
        restrict: 'A',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/carousel/carousel.html';
        },
        scope: {
            active: '=',
            interval: '=',
            noTransition: '=',
            noPause: '=',
            noWrap: '&'
        }
    };
})

.directive('uibSlide', ['$animate', function ($animate) {
    return {
        require: '^uibCarousel',
        restrict: 'A',
        transclude: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/carousel/slide.html';
        },
        scope: {
            actual: '=?',
            index: '=?'
        },
        link: function (scope, element, attrs, carouselCtrl) {
            element.addClass('item');
            carouselCtrl.addSlide(scope, element);
            //when the scope is destroyed then remove the slide from the current slides array
            scope.$on('$destroy', function () {
                carouselCtrl.removeSlide(scope);
            });

            scope.$watch('active', function (active) {
                $animate[active ? 'addClass' : 'removeClass'](element, 'active');
            });
        }
    };
}])

.animation('.item', ['$animateCss',
function ($animateCss) {
    var SLIDE_DIRECTION = 'uib-slideDirection';

    function removeClass(element, className, callback) {
        element.removeClass(className);
        if (callback) {
            callback();
        }
    }

    return {
        beforeAddClass: function (element, className, done) {
            if (className === 'active') {
                var stopped = false;
                var direction = element.data(SLIDE_DIRECTION);
                var directionClass = direction === 'next' ? 'left' : 'right';
                var removeClassFn = removeClass.bind(this, element,
                  directionClass + ' ' + direction, done);
                element.addClass(direction);

                $animateCss(element, { addClass: directionClass })
                  .start()
                  .done(removeClassFn);

                return function () {
                    stopped = true;
                };
            }
            done();
        },
        beforeRemoveClass: function (element, className, done) {
            if (className === 'active') {
                var stopped = false;
                var direction = element.data(SLIDE_DIRECTION);
                var directionClass = direction === 'next' ? 'left' : 'right';
                var removeClassFn = removeClass.bind(this, element, directionClass, done);

                $animateCss(element, { addClass: directionClass })
                  .start()
                  .done(removeClassFn);

                return function () {
                    stopped = true;
                };
            }
            done();
        }
    };
}]);

angular.module('ui.bootstrap.dateparser', [])

.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', function ($log, $locale, dateFilter, orderByFilter) {
    // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js
    var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;

    var localeId;
    var formatCodeToRegex;

    this.init = function () {
        localeId = $locale.id;

        this.parsers = {};
        this.formatters = {};

        formatCodeToRegex = [
          {
              key: 'yyyy',
              regex: '\\d{4}',
              apply: function (value) { this.year = +value; },
              formatter: function (date) {
                  var _date = new Date();
                  _date.setFullYear(Math.abs(date.getFullYear()));
                  return dateFilter(_date, 'yyyy');
              }
          },
          {
              key: 'yy',
              regex: '\\d{2}',
              apply: function (value) { value = +value; this.year = value < 69 ? value + 2000 : value + 1900; },
              formatter: function (date) {
                  var _date = new Date();
                  _date.setFullYear(Math.abs(date.getFullYear()));
                  return dateFilter(_date, 'yy');
              }
          },
          {
              key: 'y',
              regex: '\\d{1,4}',
              apply: function (value) { this.year = +value; },
              formatter: function (date) {
                  var _date = new Date();
                  _date.setFullYear(Math.abs(date.getFullYear()));
                  return dateFilter(_date, 'y');
              }
          },
          {
              key: 'M!',
              regex: '0?[1-9]|1[0-2]',
              apply: function (value) { this.month = value - 1; },
              formatter: function (date) {
                  var value = date.getMonth();
                  if (/^[0-9]$/.test(value)) {
                      return dateFilter(date, 'MM');
                  }

                  return dateFilter(date, 'M');
              }
          },
          {
              key: 'MMMM',
              regex: $locale.DATETIME_FORMATS.MONTH.join('|'),
              apply: function (value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); },
              formatter: function (date) { return dateFilter(date, 'MMMM'); }
          },
          {
              key: 'MMM',
              regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
              apply: function (value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); },
              formatter: function (date) { return dateFilter(date, 'MMM'); }
          },
          {
              key: 'MM',
              regex: '0[1-9]|1[0-2]',
              apply: function (value) { this.month = value - 1; },
              formatter: function (date) { return dateFilter(date, 'MM'); }
          },
          {
              key: 'M',
              regex: '[1-9]|1[0-2]',
              apply: function (value) { this.month = value - 1; },
              formatter: function (date) { return dateFilter(date, 'M'); }
          },
          {
              key: 'LLLL',
              regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'),
              apply: function (value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); },
              formatter: function (date) { return dateFilter(date, 'LLLL'); }
          },
          {
              key: 'd!',
              regex: '[0-2]?[0-9]{1}|3[0-1]{1}',
              apply: function (value) { this.date = +value; },
              formatter: function (date) {
                  var value = date.getDate();
                  if (/^[1-9]$/.test(value)) {
                      return dateFilter(date, 'dd');
                  }

                  return dateFilter(date, 'd');
              }
          },
          {
              key: 'dd',
              regex: '[0-2][0-9]{1}|3[0-1]{1}',
              apply: function (value) { this.date = +value; },
              formatter: function (date) { return dateFilter(date, 'dd'); }
          },
          {
              key: 'd',
              regex: '[1-2]?[0-9]{1}|3[0-1]{1}',
              apply: function (value) { this.date = +value; },
              formatter: function (date) { return dateFilter(date, 'd'); }
          },
          {
              key: 'EEEE',
              regex: $locale.DATETIME_FORMATS.DAY.join('|'),
              formatter: function (date) { return dateFilter(date, 'EEEE'); }
          },
          {
              key: 'EEE',
              regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
              formatter: function (date) { return dateFilter(date, 'EEE'); }
          },
          {
              key: 'HH',
              regex: '(?:0|1)[0-9]|2[0-3]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'HH'); }
          },
          {
              key: 'hh',
              regex: '0[0-9]|1[0-2]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'hh'); }
          },
          {
              key: 'H',
              regex: '1?[0-9]|2[0-3]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'H'); }
          },
          {
              key: 'h',
              regex: '[0-9]|1[0-2]',
              apply: function (value) { this.hours = +value; },
              formatter: function (date) { return dateFilter(date, 'h'); }
          },
          {
              key: 'mm',
              regex: '[0-5][0-9]',
              apply: function (value) { this.minutes = +value; },
              formatter: function (date) { return dateFilter(date, 'mm'); }
          },
          {
              key: 'm',
              regex: '[0-9]|[1-5][0-9]',
              apply: function (value) { this.minutes = +value; },
              formatter: function (date) { return dateFilter(date, 'm'); }
          },
          {
              key: 'sss',
              regex: '[0-9][0-9][0-9]',
              apply: function (value) { this.milliseconds = +value; },
              formatter: function (date) { return dateFilter(date, 'sss'); }
          },
          {
              key: 'ss',
              regex: '[0-5][0-9]',
              apply: function (value) { this.seconds = +value; },
              formatter: function (date) { return dateFilter(date, 'ss'); }
          },
          {
              key: 's',
              regex: '[0-9]|[1-5][0-9]',
              apply: function (value) { this.seconds = +value; },
              formatter: function (date) { return dateFilter(date, 's'); }
          },
          {
              key: 'a',
              regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),
              apply: function (value) {
                  if (this.hours === 12) {
                      this.hours = 0;
                  }

                  if (value === 'PM') {
                      this.hours += 12;
                  }
              },
              formatter: function (date) { return dateFilter(date, 'a'); }
          },
          {
              key: 'Z',
              regex: '[+-]\\d{4}',
              apply: function (value) {
                  var matches = value.match(/([+-])(\d{2})(\d{2})/),
                    sign = matches[1],
                    hours = matches[2],
                    minutes = matches[3];
                  this.hours += toInt(sign + hours);
                  this.minutes += toInt(sign + minutes);
              },
              formatter: function (date) {
                  return dateFilter(date, 'Z');
              }
          },
          {
              key: 'ww',
              regex: '[0-4][0-9]|5[0-3]',
              formatter: function (date) { return dateFilter(date, 'ww'); }
          },
          {
              key: 'w',
              regex: '[0-9]|[1-4][0-9]|5[0-3]',
              formatter: function (date) { return dateFilter(date, 'w'); }
          },
          {
              key: 'GGGG',
              regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\s/g, '\\s'),
              formatter: function (date) { return dateFilter(date, 'GGGG'); }
          },
          {
              key: 'GGG',
              regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
              formatter: function (date) { return dateFilter(date, 'GGG'); }
          },
          {
              key: 'GG',
              regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
              formatter: function (date) { return dateFilter(date, 'GG'); }
          },
          {
              key: 'G',
              regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
              formatter: function (date) { return dateFilter(date, 'G'); }
          }
        ];
    };

    this.init();

    function createParser(format) {
        var map = [], regex = format.split('');

        // check for literal values
        var quoteIndex = format.indexOf('\'');
        if (quoteIndex > -1) {
            var inLiteral = false;
            format = format.split('');
            for (var i = quoteIndex; i < format.length; i++) {
                if (inLiteral) {
                    if (format[i] === '\'') {
                        if (i + 1 < format.length && format[i + 1] === '\'') { // escaped single quote
                            format[i + 1] = '$';
                            regex[i + 1] = '';
                        } else { // end of literal
                            regex[i] = '';
                            inLiteral = false;
                        }
                    }
                    format[i] = '$';
                } else {
                    if (format[i] === '\'') { // start of literal
                        format[i] = '$';
                        regex[i] = '';
                        inLiteral = true;
                    }
                }
            }

            format = format.join('');
        }

        angular.forEach(formatCodeToRegex, function (data) {
            var index = format.indexOf(data.key);

            if (index > -1) {
                format = format.split('');

                regex[index] = '(' + data.regex + ')';
                format[index] = '$'; // Custom symbol to define consumed part of format
                for (var i = index + 1, n = index + data.key.length; i < n; i++) {
                    regex[i] = '';
                    format[i] = '$';
                }
                format = format.join('');

                map.push({
                    index: index,
                    key: data.key,
                    apply: data.apply,
                    matcher: data.regex
                });
            }
        });

        return {
            regex: new RegExp('^' + regex.join('') + '$'),
            map: orderByFilter(map, 'index')
        };
    }

    function createFormatter(format) {
        var formatters = [];
        var i = 0;
        var formatter, literalIdx;
        while (i < format.length) {
            if (angular.isNumber(literalIdx)) {
                if (format.charAt(i) === '\'') {
                    if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') {
                        formatters.push(constructLiteralFormatter(format, literalIdx, i));
                        literalIdx = null;
                    }
                } else if (i === format.length) {
                    while (literalIdx < format.length) {
                        formatter = constructFormatterFromIdx(format, literalIdx);
                        formatters.push(formatter);
                        literalIdx = formatter.endIdx;
                    }
                }

                i++;
                continue;
            }

            if (format.charAt(i) === '\'') {
                literalIdx = i;
                i++;
                continue;
            }

            formatter = constructFormatterFromIdx(format, i);

            formatters.push(formatter.parser);
            i = formatter.endIdx;
        }

        return formatters;
    }

    function constructLiteralFormatter(format, literalIdx, endIdx) {
        return function () {
            return format.substr(literalIdx + 1, endIdx - literalIdx - 1);
        };
    }

    function constructFormatterFromIdx(format, i) {
        var currentPosStr = format.substr(i);
        for (var j = 0; j < formatCodeToRegex.length; j++) {
            if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {
                var data = formatCodeToRegex[j];
                return {
                    endIdx: i + data.key.length,
                    parser: data.formatter
                };
            }
        }

        return {
            endIdx: i + 1,
            parser: function () {
                return currentPosStr.charAt(0);
            }
        };
    }

    this.filter = function (date, format) {
        if (!angular.isDate(date) || isNaN(date) || !format) {
            return '';
        }

        format = $locale.DATETIME_FORMATS[format] || format;

        if ($locale.id !== localeId) {
            this.init();
        }

        if (!this.formatters[format]) {
            this.formatters[format] = createFormatter(format);
        }

        var formatters = this.formatters[format];

        return formatters.reduce(function (str, formatter) {
            return str + formatter(date);
        }, '');
    };

    this.parse = function (input, format, baseDate) {
        if (!angular.isString(input) || !format) {
            return input;
        }

        format = $locale.DATETIME_FORMATS[format] || format;
        format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&');

        if ($locale.id !== localeId) {
            this.init();
        }

        if (!this.parsers[format]) {
            this.parsers[format] = createParser(format, 'apply');
        }

        var parser = this.parsers[format],
            regex = parser.regex,
            map = parser.map,
            results = input.match(regex),
            tzOffset = false;
        if (results && results.length) {
            var fields, dt;
            if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {
                fields = {
                    year: baseDate.getFullYear(),
                    month: baseDate.getMonth(),
                    date: baseDate.getDate(),
                    hours: baseDate.getHours(),
                    minutes: baseDate.getMinutes(),
                    seconds: baseDate.getSeconds(),
                    milliseconds: baseDate.getMilliseconds()
                };
            } else {
                if (baseDate) {
                    $log.warn('dateparser:', 'baseDate is not a valid date');
                }
                fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
            }

            for (var i = 1, n = results.length; i < n; i++) {
                var mapper = map[i - 1];
                if (mapper.matcher === 'Z') {
                    tzOffset = true;
                }

                if (mapper.apply) {
                    mapper.apply.call(fields, results[i]);
                }
            }

            var datesetter = tzOffset ? Date.prototype.setUTCFullYear :
              Date.prototype.setFullYear;
            var timesetter = tzOffset ? Date.prototype.setUTCHours :
              Date.prototype.setHours;

            if (isValid(fields.year, fields.month, fields.date)) {
                if (angular.isDate(baseDate) && !isNaN(baseDate.getTime()) && !tzOffset) {
                    dt = new Date(baseDate);
                    datesetter.call(dt, fields.year, fields.month, fields.date);
                    timesetter.call(dt, fields.hours, fields.minutes,
                      fields.seconds, fields.milliseconds);
                } else {
                    dt = new Date(0);
                    datesetter.call(dt, fields.year, fields.month, fields.date);
                    timesetter.call(dt, fields.hours || 0, fields.minutes || 0,
                      fields.seconds || 0, fields.milliseconds || 0);
                }
            }

            return dt;
        }
    };

    // Check if date is valid for specific month (and year for February).
    // Month: 0 = Jan, 1 = Feb, etc
    function isValid(year, month, date) {
        if (date < 1) {
            return false;
        }

        if (month === 1 && date > 28) {
            return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0);
        }

        if (month === 3 || month === 5 || month === 8 || month === 10) {
            return date < 31;
        }

        return true;
    }

    function toInt(str) {
        return parseInt(str, 10);
    }

    this.toTimezone = toTimezone;
    this.fromTimezone = fromTimezone;
    this.timezoneToOffset = timezoneToOffset;
    this.addDateMinutes = addDateMinutes;
    this.convertTimezoneToLocal = convertTimezoneToLocal;

    function toTimezone(date, timezone) {
        return date && timezone ? convertTimezoneToLocal(date, timezone) : date;
    }

    function fromTimezone(date, timezone) {
        return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;
    }

    //https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207
    function timezoneToOffset(timezone, fallback) {
        timezone = timezone.replace(/:/g, '');
        var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
        return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
    }

    function addDateMinutes(date, minutes) {
        date = new Date(date.getTime());
        date.setMinutes(date.getMinutes() + minutes);
        return date;
    }

    function convertTimezoneToLocal(date, timezone, reverse) {
        reverse = reverse ? -1 : 1;
        var dateTimezoneOffset = date.getTimezoneOffset();
        var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
        return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
    }
}]);

// Avoiding use of ng-class as it creates a lot of watchers when a class is to be applied to
// at most one element.
angular.module('ui.bootstrap.isClass', [])
.directive('uibIsClass', [
         '$animate',
function ($animate) {
    //                    11111111          22222222
    var ON_REGEXP = /^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/;
    //                    11111111           22222222
    var IS_REGEXP = /^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;

    var dataPerTracked = {};

    return {
        restrict: 'A',
        compile: function (tElement, tAttrs) {
            var linkedScopes = [];
            var instances = [];
            var expToData = {};
            var lastActivated = null;
            var onExpMatches = tAttrs.uibIsClass.match(ON_REGEXP);
            var onExp = onExpMatches[2];
            var expsStr = onExpMatches[1];
            var exps = expsStr.split(',');

            return linkFn;

            function linkFn(scope, element, attrs) {
                linkedScopes.push(scope);
                instances.push({
                    scope: scope,
                    element: element
                });

                exps.forEach(function (exp, k) {
                    addForExp(exp, scope);
                });

                scope.$on('$destroy', removeScope);
            }

            function addForExp(exp, scope) {
                var matches = exp.match(IS_REGEXP);
                var clazz = scope.$eval(matches[1]);
                var compareWithExp = matches[2];
                var data = expToData[exp];
                if (!data) {
                    var watchFn = function (compareWithVal) {
                        var newActivated = null;
                        instances.some(function (instance) {
                            var thisVal = instance.scope.$eval(onExp);
                            if (thisVal === compareWithVal) {
                                newActivated = instance;
                                return true;
                            }
                        });
                        if (data.lastActivated !== newActivated) {
                            if (data.lastActivated) {
                                $animate.removeClass(data.lastActivated.element, clazz);
                            }
                            if (newActivated) {
                                $animate.addClass(newActivated.element, clazz);
                            }
                            data.lastActivated = newActivated;
                        }
                    };
                    expToData[exp] = data = {
                        lastActivated: null,
                        scope: scope,
                        watchFn: watchFn,
                        compareWithExp: compareWithExp,
                        watcher: scope.$watch(compareWithExp, watchFn)
                    };
                }
                data.watchFn(scope.$eval(compareWithExp));
            }

            function removeScope(e) {
                var removedScope = e.targetScope;
                var index = linkedScopes.indexOf(removedScope);
                linkedScopes.splice(index, 1);
                instances.splice(index, 1);
                if (linkedScopes.length) {
                    var newWatchScope = linkedScopes[0];
                    angular.forEach(expToData, function (data) {
                        if (data.scope === removedScope) {
                            data.watcher = newWatchScope.$watch(data.compareWithExp, data.watchFn);
                            data.scope = newWatchScope;
                        }
                    });
                } else {
                    expToData = {};
                }
            }
        }
    };
}]);
angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass'])

.value('$datepickerSuppressError', false)

.value('$datepickerLiteralWarning', true)

.constant('uibDatepickerConfig', {
    datepickerMode: 'day',
    formatDay: 'dd',
    formatMonth: 'MMMM',
    formatYear: 'yyyy',
    formatDayHeader: 'EEE',
    formatDayTitle: 'MMMM yyyy',
    formatMonthTitle: 'yyyy',
    maxDate: null,
    maxMode: 'year',
    minDate: null,
    minMode: 'day',
    monthColumns: 3,
    ngModelOptions: {},
    shortcutPropagation: false,
    showWeeks: true,
    yearColumns: 5,
    yearRows: 4
})

.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
  function ($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
      var self = this,
          ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
          ngModelOptions = {},
          watchListeners = [];

      $element.addClass('uib-datepicker');
      $attrs.$set('role', 'application');

      if (!$scope.datepickerOptions) {
          $scope.datepickerOptions = {};
      }

      // Modes chain
      this.modes = ['day', 'month', 'year'];

      [
        'customClass',
        'dateDisabled',
        'datepickerMode',
        'formatDay',
        'formatDayHeader',
        'formatDayTitle',
        'formatMonth',
        'formatMonthTitle',
        'formatYear',
        'maxDate',
        'maxMode',
        'minDate',
        'minMode',
        'monthColumns',
        'showWeeks',
        'shortcutPropagation',
        'startingDay',
        'yearColumns',
        'yearRows'
      ].forEach(function (key) {
          switch (key) {
              case 'customClass':
              case 'dateDisabled':
                  $scope[key] = $scope.datepickerOptions[key] || angular.noop;
                  break;
              case 'datepickerMode':
                  $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ?
                    $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode;
                  break;
              case 'formatDay':
              case 'formatDayHeader':
              case 'formatDayTitle':
              case 'formatMonth':
              case 'formatMonthTitle':
              case 'formatYear':
                  self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
                    $interpolate($scope.datepickerOptions[key])($scope.$parent) :
                    datepickerConfig[key];
                  break;
              case 'monthColumns':
              case 'showWeeks':
              case 'shortcutPropagation':
              case 'yearColumns':
              case 'yearRows':
                  self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
                    $scope.datepickerOptions[key] : datepickerConfig[key];
                  break;
              case 'startingDay':
                  if (angular.isDefined($scope.datepickerOptions.startingDay)) {
                      self.startingDay = $scope.datepickerOptions.startingDay;
                  } else if (angular.isNumber(datepickerConfig.startingDay)) {
                      self.startingDay = datepickerConfig.startingDay;
                  } else {
                      self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
                  }

                  break;
              case 'maxDate':
              case 'minDate':
                  $scope.$watch('datepickerOptions.' + key, function (value) {
                      if (value) {
                          if (angular.isDate(value)) {
                              self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone);
                          } else {
                              if ($datepickerLiteralWarning) {
                                  $log.warn('Literal date support has been deprecated, please switch to date object usage');
                              }

                              self[key] = new Date(dateFilter(value, 'medium'));
                          }
                      } else {
                          self[key] = datepickerConfig[key] ?
                            dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) :
                            null;
                      }

                      self.refreshView();
                  });

                  break;
              case 'maxMode':
              case 'minMode':
                  if ($scope.datepickerOptions[key]) {
                      $scope.$watch(function () { return $scope.datepickerOptions[key]; }, function (value) {
                          self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key];
                          if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||
                            key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {
                              $scope.datepickerMode = self[key];
                              $scope.datepickerOptions.datepickerMode = self[key];
                          }
                      });
                  } else {
                      self[key] = $scope[key] = datepickerConfig[key] || null;
                  }

                  break;
          }
      });

      $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);

      $scope.disabled = angular.isDefined($attrs.disabled) || false;
      if (angular.isDefined($attrs.ngDisabled)) {
          watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function (disabled) {
              $scope.disabled = disabled;
              self.refreshView();
          }));
      }

      $scope.isActive = function (dateObject) {
          if (self.compare(dateObject.date, self.activeDate) === 0) {
              $scope.activeDateId = dateObject.uid;
              return true;
          }
          return false;
      };

      this.init = function (ngModelCtrl_) {
          ngModelCtrl = ngModelCtrl_;
          ngModelOptions = ngModelCtrl_.$options ||
            $scope.datepickerOptions.ngModelOptions ||
            datepickerConfig.ngModelOptions;
          if ($scope.datepickerOptions.initDate) {
              self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date();
              $scope.$watch('datepickerOptions.initDate', function (initDate) {
                  if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
                      self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
                      self.refreshView();
                  }
              });
          } else {
              self.activeDate = new Date();
          }

          var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
          this.activeDate = !isNaN(date) ?
            dateParser.fromTimezone(date, ngModelOptions.timezone) :
            dateParser.fromTimezone(new Date(), ngModelOptions.timezone);

          ngModelCtrl.$render = function () {
              self.render();
          };
      };

      this.render = function () {
          if (ngModelCtrl.$viewValue) {
              var date = new Date(ngModelCtrl.$viewValue),
                  isValid = !isNaN(date);

              if (isValid) {
                  this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone);
              } else if (!$datepickerSuppressError) {
                  $log.error('Datepicker directive: "ng-model" value must be a Date object');
              }
          }
          this.refreshView();
      };

      this.refreshView = function () {
          if (this.element) {
              $scope.selectedDt = null;
              this._refreshView();
              if ($scope.activeDt) {
                  $scope.activeDateId = $scope.activeDt.uid;
              }

              var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
              date = dateParser.fromTimezone(date, ngModelOptions.timezone);
              ngModelCtrl.$setValidity('dateDisabled', !date ||
                this.element && !this.isDisabled(date));
          }
      };

      this.createDateObject = function (date, format) {
          var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
          model = dateParser.fromTimezone(model, ngModelOptions.timezone);
          var today = new Date();
          today = dateParser.fromTimezone(today, ngModelOptions.timezone);
          var time = this.compare(date, today);
          var dt = {
              date: date,
              label: dateParser.filter(date, format),
              selected: model && this.compare(date, model) === 0,
              disabled: this.isDisabled(date),
              past: time < 0,
              current: time === 0,
              future: time > 0,
              customClass: this.customClass(date) || null
          };

          if (model && this.compare(date, model) === 0) {
              $scope.selectedDt = dt;
          }

          if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {
              $scope.activeDt = dt;
          }

          return dt;
      };

      this.isDisabled = function (date) {
          return $scope.disabled ||
            this.minDate && this.compare(date, this.minDate) < 0 ||
            this.maxDate && this.compare(date, this.maxDate) > 0 ||
            $scope.dateDisabled && $scope.dateDisabled({ date: date, mode: $scope.datepickerMode });
      };

      this.customClass = function (date) {
          return $scope.customClass({ date: date, mode: $scope.datepickerMode });
      };

      // Split array into smaller arrays
      this.split = function (arr, size) {
          var arrays = [];
          while (arr.length > 0) {
              arrays.push(arr.splice(0, size));
          }
          return arrays;
      };

      $scope.select = function (date) {
          if ($scope.datepickerMode === self.minMode) {
              var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0);
              dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
              dt = dateParser.toTimezone(dt, ngModelOptions.timezone);
              ngModelCtrl.$setViewValue(dt);
              ngModelCtrl.$render();
          } else {
              self.activeDate = date;
              setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);

              $scope.$emit('uib:datepicker.mode');
          }

          $scope.$broadcast('uib:datepicker.focus');
      };

      $scope.move = function (direction) {
          var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
              month = self.activeDate.getMonth() + direction * (self.step.months || 0);
          self.activeDate.setFullYear(year, month, 1);
          self.refreshView();
      };

      $scope.toggleMode = function (direction) {
          direction = direction || 1;

          if ($scope.datepickerMode === self.maxMode && direction === 1 ||
            $scope.datepickerMode === self.minMode && direction === -1) {
              return;
          }

          setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]);

          $scope.$emit('uib:datepicker.mode');
      };

      // Key event mapper
      $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };

      var focusElement = function () {
          self.element[0].focus();
      };

      // Listen for focus requests from popup directive
      $scope.$on('uib:datepicker.focus', focusElement);

      $scope.keydown = function (evt) {
          var key = $scope.keys[evt.which];

          if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
              return;
          }

          evt.preventDefault();
          if (!self.shortcutPropagation) {
              evt.stopPropagation();
          }

          if (key === 'enter' || key === 'space') {
              if (self.isDisabled(self.activeDate)) {
                  return; // do nothing
              }
              $scope.select(self.activeDate);
          } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
              $scope.toggleMode(key === 'up' ? 1 : -1);
          } else {
              self.handleKeyDown(key, evt);
              self.refreshView();
          }
      };

      $element.on('keydown', function (evt) {
          $scope.$apply(function () {
              $scope.keydown(evt);
          });
      });

      $scope.$on('$destroy', function () {
          //Clear all watch listeners on destroy
          while (watchListeners.length) {
              watchListeners.shift()();
          }
      });

      function setMode(mode) {
          $scope.datepickerMode = mode;
          $scope.datepickerOptions.datepickerMode = mode;
      }
  }])

.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function (scope, $element, dateFilter) {
    var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    this.step = { months: 1 };
    this.element = $element;
    function getDaysInMonth(year, month) {
        return month === 1 && year % 4 === 0 &&
          (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];
    }

    this.init = function (ctrl) {
        angular.extend(ctrl, this);
        scope.showWeeks = ctrl.showWeeks;
        ctrl.refreshView();
    };

    this.getDates = function (startDate, n) {
        var dates = new Array(n), current = new Date(startDate), i = 0, date;
        while (i < n) {
            date = new Date(current);
            dates[i++] = date;
            current.setDate(current.getDate() + 1);
        }
        return dates;
    };

    this._refreshView = function () {
        var year = this.activeDate.getFullYear(),
          month = this.activeDate.getMonth(),
          firstDayOfMonth = new Date(this.activeDate);

        firstDayOfMonth.setFullYear(year, month, 1);

        var difference = this.startingDay - firstDayOfMonth.getDay(),
          numDisplayedFromPreviousMonth = difference > 0 ?
            7 - difference : -difference,
          firstDate = new Date(firstDayOfMonth);

        if (numDisplayedFromPreviousMonth > 0) {
            firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
        }

        // 42 is the number of days on a six-week calendar
        var days = this.getDates(firstDate, 42);
        for (var i = 0; i < 42; i++) {
            days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {
                secondary: days[i].getMonth() !== month,
                uid: scope.uniqueId + '-' + i
            });
        }

        scope.labels = new Array(7);
        for (var j = 0; j < 7; j++) {
            scope.labels[j] = {
                abbr: dateFilter(days[j].date, this.formatDayHeader),
                full: dateFilter(days[j].date, 'EEEE')
            };
        }

        scope.title = dateFilter(this.activeDate, this.formatDayTitle);
        scope.rows = this.split(days, 7);

        if (scope.showWeeks) {
            scope.weekNumbers = [];
            var thursdayIndex = (4 + 7 - this.startingDay) % 7,
                numWeeks = scope.rows.length;
            for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
                scope.weekNumbers.push(
                  getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));
            }
        }
    };

    this.compare = function (date1, date2) {
        var _date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
        var _date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
        _date1.setFullYear(date1.getFullYear());
        _date2.setFullYear(date2.getFullYear());
        return _date1 - _date2;
    };

    function getISO8601WeekNumber(date) {
        var checkDate = new Date(date);
        checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
        var time = checkDate.getTime();
        checkDate.setMonth(0); // Compare with Jan 1
        checkDate.setDate(1);
        return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
    }

    this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getDate();

        if (key === 'left') {
            date = date - 1;
        } else if (key === 'up') {
            date = date - 7;
        } else if (key === 'right') {
            date = date + 1;
        } else if (key === 'down') {
            date = date + 7;
        } else if (key === 'pageup' || key === 'pagedown') {
            var month = this.activeDate.getMonth() + (key === 'pageup' ? -1 : 1);
            this.activeDate.setMonth(month, 1);
            date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);
        } else if (key === 'home') {
            date = 1;
        } else if (key === 'end') {
            date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());
        }
        this.activeDate.setDate(date);
    };
}])

.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function (scope, $element, dateFilter) {
    this.step = { years: 1 };
    this.element = $element;

    this.init = function (ctrl) {
        angular.extend(ctrl, this);
        ctrl.refreshView();
    };

    this._refreshView = function () {
        var months = new Array(12),
            year = this.activeDate.getFullYear(),
            date;

        for (var i = 0; i < 12; i++) {
            date = new Date(this.activeDate);
            date.setFullYear(year, i, 1);
            months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {
                uid: scope.uniqueId + '-' + i
            });
        }

        scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
        scope.rows = this.split(months, this.monthColumns);
        scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1;
    };

    this.compare = function (date1, date2) {
        var _date1 = new Date(date1.getFullYear(), date1.getMonth());
        var _date2 = new Date(date2.getFullYear(), date2.getMonth());
        _date1.setFullYear(date1.getFullYear());
        _date2.setFullYear(date2.getFullYear());
        return _date1 - _date2;
    };

    this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getMonth();

        if (key === 'left') {
            date = date - 1;
        } else if (key === 'up') {
            date = date - this.monthColumns;
        } else if (key === 'right') {
            date = date + 1;
        } else if (key === 'down') {
            date = date + this.monthColumns;
        } else if (key === 'pageup' || key === 'pagedown') {
            var year = this.activeDate.getFullYear() + (key === 'pageup' ? -1 : 1);
            this.activeDate.setFullYear(year);
        } else if (key === 'home') {
            date = 0;
        } else if (key === 'end') {
            date = 11;
        }
        this.activeDate.setMonth(date);
    };
}])

.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function (scope, $element, dateFilter) {
    var columns, range;
    this.element = $element;

    function getStartingYear(year) {
        return parseInt((year - 1) / range, 10) * range + 1;
    }

    this.yearpickerInit = function () {
        columns = this.yearColumns;
        range = this.yearRows * columns;
        this.step = { years: range };
    };

    this._refreshView = function () {
        var years = new Array(range), date;

        for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()) ; i < range; i++) {
            date = new Date(this.activeDate);
            date.setFullYear(start + i, 0, 1);
            years[i] = angular.extend(this.createDateObject(date, this.formatYear), {
                uid: scope.uniqueId + '-' + i
            });
        }

        scope.title = [years[0].label, years[range - 1].label].join(' - ');
        scope.rows = this.split(years, columns);
        scope.columns = columns;
    };

    this.compare = function (date1, date2) {
        return date1.getFullYear() - date2.getFullYear();
    };

    this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getFullYear();

        if (key === 'left') {
            date = date - 1;
        } else if (key === 'up') {
            date = date - columns;
        } else if (key === 'right') {
            date = date + 1;
        } else if (key === 'down') {
            date = date + columns;
        } else if (key === 'pageup' || key === 'pagedown') {
            date += (key === 'pageup' ? -1 : 1) * range;
        } else if (key === 'home') {
            date = getStartingYear(this.activeDate.getFullYear());
        } else if (key === 'end') {
            date = getStartingYear(this.activeDate.getFullYear()) + range - 1;
        }
        this.activeDate.setFullYear(date);
    };
}])

.directive('uibDatepicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';
        },
        scope: {
            datepickerOptions: '=?'
        },
        require: ['uibDatepicker', '^ngModel'],
        restrict: 'A',
        controller: 'UibDatepickerController',
        controllerAs: 'datepicker',
        link: function (scope, element, attrs, ctrls) {
            var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            datepickerCtrl.init(ngModelCtrl);
        }
    };
})

.directive('uibDaypicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/day.html';
        },
        require: ['^uibDatepicker', 'uibDaypicker'],
        restrict: 'A',
        controller: 'UibDaypickerController',
        link: function (scope, element, attrs, ctrls) {
            var datepickerCtrl = ctrls[0],
              daypickerCtrl = ctrls[1];

            daypickerCtrl.init(datepickerCtrl);
        }
    };
})

.directive('uibMonthpicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/month.html';
        },
        require: ['^uibDatepicker', 'uibMonthpicker'],
        restrict: 'A',
        controller: 'UibMonthpickerController',
        link: function (scope, element, attrs, ctrls) {
            var datepickerCtrl = ctrls[0],
              monthpickerCtrl = ctrls[1];

            monthpickerCtrl.init(datepickerCtrl);
        }
    };
})

.directive('uibYearpicker', function () {
    return {
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepicker/year.html';
        },
        require: ['^uibDatepicker', 'uibYearpicker'],
        restrict: 'A',
        controller: 'UibYearpickerController',
        link: function (scope, element, attrs, ctrls) {
            var ctrl = ctrls[0];
            angular.extend(ctrl, ctrls[1]);
            ctrl.yearpickerInit();

            ctrl.refreshView();
        }
    };
});

angular.module('ui.bootstrap.position', [])

/**
 * A set of utility methods for working with the DOM.
 * It is meant to be used where we need to absolute-position elements in
 * relation to another element (this is the case for tooltips, popovers,
 * typeahead suggestions etc.).
 */
  .factory('$uibPosition', ['$document', '$window', function ($document, $window) {
      /**
       * Used by scrollbarWidth() function to cache scrollbar's width.
       * Do not access this variable directly, use scrollbarWidth() instead.
       */
      var SCROLLBAR_WIDTH;
      /**
       * scrollbar on body and html element in IE and Edge overlay
       * content and should be considered 0 width.
       */
      var BODY_SCROLLBAR_WIDTH;
      var OVERFLOW_REGEX = {
          normal: /(auto|scroll)/,
          hidden: /(auto|scroll|hidden)/
      };
      var PLACEMENT_REGEX = {
          auto: /\s?auto?\s?/i,
          primary: /^(top|bottom|left|right)$/,
          secondary: /^(top|bottom|left|right|center)$/,
          vertical: /^(top|bottom)$/
      };
      var BODY_REGEX = /(HTML|BODY)/;

      return {

          /**
           * Provides a raw DOM element from a jQuery/jQLite element.
           *
           * @param {element} elem - The element to convert.
           *
           * @returns {element} A HTML element.
           */
          getRawNode: function (elem) {
              return elem.nodeName ? elem : elem[0] || elem;
          },

          /**
           * Provides a parsed number for a style property.  Strips
           * units and casts invalid numbers to 0.
           *
           * @param {string} value - The style value to parse.
           *
           * @returns {number} A valid number.
           */
          parseStyle: function (value) {
              value = parseFloat(value);
              return isFinite(value) ? value : 0;
          },

          /**
           * Provides the closest positioned ancestor.
           *
           * @param {element} element - The element to get the offest parent for.
           *
           * @returns {element} The closest positioned ancestor.
           */
          offsetParent: function (elem) {
              elem = this.getRawNode(elem);

              var offsetParent = elem.offsetParent || $document[0].documentElement;

              function isStaticPositioned(el) {
                  return ($window.getComputedStyle(el).position || 'static') === 'static';
              }

              while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {
                  offsetParent = offsetParent.offsetParent;
              }

              return offsetParent || $document[0].documentElement;
          },

          /**
           * Provides the scrollbar width, concept from TWBS measureScrollbar()
           * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js
           * In IE and Edge, scollbar on body and html element overlay and should
           * return a width of 0.
           *
           * @returns {number} The width of the browser scollbar.
           */
          scrollbarWidth: function (isBody) {
              if (isBody) {
                  if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {
                      var bodyElem = $document.find('body');
                      bodyElem.addClass('uib-position-body-scrollbar-measure');
                      BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;
                      BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;
                      bodyElem.removeClass('uib-position-body-scrollbar-measure');
                  }
                  return BODY_SCROLLBAR_WIDTH;
              }

              if (angular.isUndefined(SCROLLBAR_WIDTH)) {
                  var scrollElem = angular.element('<div class="uib-position-scrollbar-measure"></div>');
                  $document.find('body').append(scrollElem);
                  SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;
                  SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;
                  scrollElem.remove();
              }

              return SCROLLBAR_WIDTH;
          },

          /**
           * Provides the padding required on an element to replace the scrollbar.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**scrollbarWidth**: the width of the scrollbar</li>
           *     <li>**widthOverflow**: whether the the width is overflowing</li>
           *     <li>**right**: the amount of right padding on the element needed to replace the scrollbar</li>
           *     <li>**rightOriginal**: the amount of right padding currently on the element</li>
           *     <li>**heightOverflow**: whether the the height is overflowing</li>
           *     <li>**bottom**: the amount of bottom padding on the element needed to replace the scrollbar</li>
           *     <li>**bottomOriginal**: the amount of bottom padding currently on the element</li>
           *   </ul>
           */
          scrollbarPadding: function (elem) {
              elem = this.getRawNode(elem);

              var elemStyle = $window.getComputedStyle(elem);
              var paddingRight = this.parseStyle(elemStyle.paddingRight);
              var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
              var scrollParent = this.scrollParent(elem, false, true);
              var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));

              return {
                  scrollbarWidth: scrollbarWidth,
                  widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
                  right: paddingRight + scrollbarWidth,
                  originalRight: paddingRight,
                  heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
                  bottom: paddingBottom + scrollbarWidth,
                  originalBottom: paddingBottom
              };
          },

          /**
           * Checks to see if the element is scrollable.
           *
           * @param {element} elem - The element to check.
           * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
           *   default is false.
           *
           * @returns {boolean} Whether the element is scrollable.
           */
          isScrollable: function (elem, includeHidden) {
              elem = this.getRawNode(elem);

              var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
              var elemStyle = $window.getComputedStyle(elem);
              return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
          },

          /**
           * Provides the closest scrollable ancestor.
           * A port of the jQuery UI scrollParent method:
           * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
           *
           * @param {element} elem - The element to find the scroll parent of.
           * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
           *   default is false.
           * @param {boolean=} [includeSelf=false] - Should the element being passed be
           * included in the scrollable llokup.
           *
           * @returns {element} A HTML element.
           */
          scrollParent: function (elem, includeHidden, includeSelf) {
              elem = this.getRawNode(elem);

              var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
              var documentEl = $document[0].documentElement;
              var elemStyle = $window.getComputedStyle(elem);
              if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
                  return elem;
              }
              var excludeStatic = elemStyle.position === 'absolute';
              var scrollParent = elem.parentElement || documentEl;

              if (scrollParent === documentEl || elemStyle.position === 'fixed') {
                  return documentEl;
              }

              while (scrollParent.parentElement && scrollParent !== documentEl) {
                  var spStyle = $window.getComputedStyle(scrollParent);
                  if (excludeStatic && spStyle.position !== 'static') {
                      excludeStatic = false;
                  }

                  if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
                      break;
                  }
                  scrollParent = scrollParent.parentElement;
              }

              return scrollParent;
          },

          /**
           * Provides read-only equivalent of jQuery's position function:
           * http://api.jquery.com/position/ - distance to closest positioned
           * ancestor.  Does not account for margins by default like jQuery position.
           *
           * @param {element} elem - The element to caclulate the position on.
           * @param {boolean=} [includeMargins=false] - Should margins be accounted
           * for, default is false.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**width**: the width of the element</li>
           *     <li>**height**: the height of the element</li>
           *     <li>**top**: distance to top edge of offset parent</li>
           *     <li>**left**: distance to left edge of offset parent</li>
           *   </ul>
           */
          position: function (elem, includeMagins) {
              elem = this.getRawNode(elem);

              var elemOffset = this.offset(elem);
              if (includeMagins) {
                  var elemStyle = $window.getComputedStyle(elem);
                  elemOffset.top -= this.parseStyle(elemStyle.marginTop);
                  elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
              }
              var parent = this.offsetParent(elem);
              var parentOffset = { top: 0, left: 0 };

              if (parent !== $document[0].documentElement) {
                  parentOffset = this.offset(parent);
                  parentOffset.top += parent.clientTop - parent.scrollTop;
                  parentOffset.left += parent.clientLeft - parent.scrollLeft;
              }

              return {
                  width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
                  height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
                  top: Math.round(elemOffset.top - parentOffset.top),
                  left: Math.round(elemOffset.left - parentOffset.left)
              };
          },

          /**
           * Provides read-only equivalent of jQuery's offset function:
           * http://api.jquery.com/offset/ - distance to viewport.  Does
           * not account for borders, margins, or padding on the body
           * element.
           *
           * @param {element} elem - The element to calculate the offset on.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**width**: the width of the element</li>
           *     <li>**height**: the height of the element</li>
           *     <li>**top**: distance to top edge of viewport</li>
           *     <li>**right**: distance to bottom edge of viewport</li>
           *   </ul>
           */
          offset: function (elem) {
              elem = this.getRawNode(elem);

              var elemBCR = elem.getBoundingClientRect();
              return {
                  width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
                  height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
                  top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
                  left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
              };
          },

          /**
           * Provides offset distance to the closest scrollable ancestor
           * or viewport.  Accounts for border and scrollbar width.
           *
           * Right and bottom dimensions represent the distance to the
           * respective edge of the viewport element.  If the element
           * edge extends beyond the viewport, a negative value will be
           * reported.
           *
           * @param {element} elem - The element to get the viewport offset for.
           * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
           * of the first scrollable element, default is false.
           * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
           * be accounted for, default is true.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**top**: distance to the top content edge of viewport element</li>
           *     <li>**bottom**: distance to the bottom content edge of viewport element</li>
           *     <li>**left**: distance to the left content edge of viewport element</li>
           *     <li>**right**: distance to the right content edge of viewport element</li>
           *   </ul>
           */
          viewportOffset: function (elem, useDocument, includePadding) {
              elem = this.getRawNode(elem);
              includePadding = includePadding !== false ? true : false;

              var elemBCR = elem.getBoundingClientRect();
              var offsetBCR = { top: 0, left: 0, bottom: 0, right: 0 };

              var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
              var offsetParentBCR = offsetParent.getBoundingClientRect();

              offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
              offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
              if (offsetParent === $document[0].documentElement) {
                  offsetBCR.top += $window.pageYOffset;
                  offsetBCR.left += $window.pageXOffset;
              }
              offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
              offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;

              if (includePadding) {
                  var offsetParentStyle = $window.getComputedStyle(offsetParent);
                  offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
                  offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
                  offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
                  offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
              }

              return {
                  top: Math.round(elemBCR.top - offsetBCR.top),
                  bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
                  left: Math.round(elemBCR.left - offsetBCR.left),
                  right: Math.round(offsetBCR.right - elemBCR.right)
              };
          },

          /**
           * Provides an array of placement values parsed from a placement string.
           * Along with the 'auto' indicator, supported placement strings are:
           *   <ul>
           *     <li>top: element on top, horizontally centered on host element.</li>
           *     <li>top-left: element on top, left edge aligned with host element left edge.</li>
           *     <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>
           *     <li>bottom: element on bottom, horizontally centered on host element.</li>
           *     <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>
           *     <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>
           *     <li>left: element on left, vertically centered on host element.</li>
           *     <li>left-top: element on left, top edge aligned with host element top edge.</li>
           *     <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>
           *     <li>right: element on right, vertically centered on host element.</li>
           *     <li>right-top: element on right, top edge aligned with host element top edge.</li>
           *     <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>
           *   </ul>
           * A placement string with an 'auto' indicator is expected to be
           * space separated from the placement, i.e: 'auto bottom-left'  If
           * the primary and secondary placement values do not match 'top,
           * bottom, left, right' then 'top' will be the primary placement and
           * 'center' will be the secondary placement.  If 'auto' is passed, true
           * will be returned as the 3rd value of the array.
           *
           * @param {string} placement - The placement string to parse.
           *
           * @returns {array} An array with the following values
           * <ul>
           *   <li>**[0]**: The primary placement.</li>
           *   <li>**[1]**: The secondary placement.</li>
           *   <li>**[2]**: If auto is passed: true, else undefined.</li>
           * </ul>
           */
          parsePlacement: function (placement) {
              var autoPlace = PLACEMENT_REGEX.auto.test(placement);
              if (autoPlace) {
                  placement = placement.replace(PLACEMENT_REGEX.auto, '');
              }

              placement = placement.split('-');

              placement[0] = placement[0] || 'top';
              if (!PLACEMENT_REGEX.primary.test(placement[0])) {
                  placement[0] = 'top';
              }

              placement[1] = placement[1] || 'center';
              if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
                  placement[1] = 'center';
              }

              if (autoPlace) {
                  placement[2] = true;
              } else {
                  placement[2] = false;
              }

              return placement;
          },

          /**
           * Provides coordinates for an element to be positioned relative to
           * another element.  Passing 'auto' as part of the placement parameter
           * will enable smart placement - where the element fits. i.e:
           * 'auto left-top' will check to see if there is enough space to the left
           * of the hostElem to fit the targetElem, if not place right (same for secondary
           * top placement).  Available space is calculated using the viewportOffset
           * function.
           *
           * @param {element} hostElem - The element to position against.
           * @param {element} targetElem - The element to position.
           * @param {string=} [placement=top] - The placement for the targetElem,
           *   default is 'top'. 'center' is assumed as secondary placement for
           *   'top', 'left', 'right', and 'bottom' placements.  Available placements are:
           *   <ul>
           *     <li>top</li>
           *     <li>top-right</li>
           *     <li>top-left</li>
           *     <li>bottom</li>
           *     <li>bottom-left</li>
           *     <li>bottom-right</li>
           *     <li>left</li>
           *     <li>left-top</li>
           *     <li>left-bottom</li>
           *     <li>right</li>
           *     <li>right-top</li>
           *     <li>right-bottom</li>
           *   </ul>
           * @param {boolean=} [appendToBody=false] - Should the top and left values returned
           *   be calculated from the body element, default is false.
           *
           * @returns {object} An object with the following properties:
           *   <ul>
           *     <li>**top**: Value for targetElem top.</li>
           *     <li>**left**: Value for targetElem left.</li>
           *     <li>**placement**: The resolved placement.</li>
           *   </ul>
           */
          positionElements: function (hostElem, targetElem, placement, appendToBody) {
              hostElem = this.getRawNode(hostElem);
              targetElem = this.getRawNode(targetElem);

              // need to read from prop to support tests.
              var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
              var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');

              placement = this.parsePlacement(placement);

              var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
              var targetElemPos = { top: 0, left: 0, placement: '' };

              if (placement[2]) {
                  var viewportOffset = this.viewportOffset(hostElem, appendToBody);

                  var targetElemStyle = $window.getComputedStyle(targetElem);
                  var adjustedSize = {
                      width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
                      height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
                  };

                  placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
                                 placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
                                 placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
                                 placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
                                 placement[0];

                  placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
                                 placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
                                 placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
                                 placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
                                 placement[1];

                  if (placement[1] === 'center') {
                      if (PLACEMENT_REGEX.vertical.test(placement[0])) {
                          var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
                          if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
                              placement[1] = 'left';
                          } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
                              placement[1] = 'right';
                          }
                      } else {
                          var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
                          if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
                              placement[1] = 'top';
                          } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
                              placement[1] = 'bottom';
                          }
                      }
                  }
              }

              switch (placement[0]) {
                  case 'top':
                      targetElemPos.top = hostElemPos.top - targetHeight;
                      break;
                  case 'bottom':
                      targetElemPos.top = hostElemPos.top + hostElemPos.height;
                      break;
                  case 'left':
                      targetElemPos.left = hostElemPos.left - targetWidth;
                      break;
                  case 'right':
                      targetElemPos.left = hostElemPos.left + hostElemPos.width;
                      break;
              }

              switch (placement[1]) {
                  case 'top':
                      targetElemPos.top = hostElemPos.top;
                      break;
                  case 'bottom':
                      targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
                      break;
                  case 'left':
                      targetElemPos.left = hostElemPos.left;
                      break;
                  case 'right':
                      targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
                      break;
                  case 'center':
                      if (PLACEMENT_REGEX.vertical.test(placement[0])) {
                          targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
                      } else {
                          targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
                      }
                      break;
              }

              targetElemPos.top = Math.round(targetElemPos.top);
              targetElemPos.left = Math.round(targetElemPos.left);
              targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];

              return targetElemPos;
          },

          /**
           * Provides a way to adjust the top positioning after first
           * render to correctly align element to top after content
           * rendering causes resized element height
           *
           * @param {array} placementClasses - The array of strings of classes
           * element should have.
           * @param {object} containerPosition - The object with container
           * position information
           * @param {number} initialHeight - The initial height for the elem.
           * @param {number} currentHeight - The current height for the elem.
           */
          adjustTop: function (placementClasses, containerPosition, initialHeight, currentHeight) {
              if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) {
                  return {
                      top: containerPosition.top - currentHeight + 'px'
                  };
              }
          },

          /**
           * Provides a way for positioning tooltip & dropdown
           * arrows when using placement options beyond the standard
           * left, right, top, or bottom.
           *
           * @param {element} elem - The tooltip/dropdown element.
           * @param {string} placement - The placement for the elem.
           */
          positionArrow: function (elem, placement) {
              elem = this.getRawNode(elem);

              var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
              if (!innerElem) {
                  return;
              }

              var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');

              var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
              if (!arrowElem) {
                  return;
              }

              var arrowCss = {
                  top: '',
                  bottom: '',
                  left: '',
                  right: ''
              };

              placement = this.parsePlacement(placement);
              if (placement[1] === 'center') {
                  // no adjustment necessary - just reset styles
                  angular.element(arrowElem).css(arrowCss);
                  return;
              }

              var borderProp = 'border-' + placement[0] + '-width';
              var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];

              var borderRadiusProp = 'border-';
              if (PLACEMENT_REGEX.vertical.test(placement[0])) {
                  borderRadiusProp += placement[0] + '-' + placement[1];
              } else {
                  borderRadiusProp += placement[1] + '-' + placement[0];
              }
              borderRadiusProp += '-radius';
              var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];

              switch (placement[0]) {
                  case 'top':
                      arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
                      break;
                  case 'bottom':
                      arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
                      break;
                  case 'left':
                      arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
                      break;
                  case 'right':
                      arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
                      break;
              }

              arrowCss[placement[1]] = borderRadius;

              angular.element(arrowElem).css(arrowCss);
          }
      };
  }]);

angular.module('ui.bootstrap.datepickerPopup', ['ui.bootstrap.datepicker', 'ui.bootstrap.position'])

.value('$datepickerPopupLiteralWarning', true)

.constant('uibDatepickerPopupConfig', {
    altInputFormats: [],
    appendToBody: false,
    clearText: 'Clear',
    closeOnDateSelection: true,
    closeText: 'Done',
    currentText: 'Today',
    datepickerPopup: 'yyyy-MM-dd',
    datepickerPopupTemplateUrl: 'uib/template/datepickerPopup/popup.html',
    datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',
    html5Types: {
        date: 'yyyy-MM-dd',
        'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
        'month': 'yyyy-MM'
    },
    onOpenFocus: true,
    showButtonBar: true,
    placement: 'auto bottom-left'
})

.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
function ($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
    var cache = {},
      isHtml5DateInput = false;
    var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
      datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
      ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];

    this.init = function (_ngModel_) {
        ngModel = _ngModel_;
        ngModelOptions = angular.isObject(_ngModel_.$options) ?
          _ngModel_.$options :
      {
          timezone: null
      };
        closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
          $scope.$parent.$eval($attrs.closeOnDateSelection) :
          datepickerPopupConfig.closeOnDateSelection;
        appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
          $scope.$parent.$eval($attrs.datepickerAppendToBody) :
          datepickerPopupConfig.appendToBody;
        onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
          $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
        datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
          $attrs.datepickerPopupTemplateUrl :
          datepickerPopupConfig.datepickerPopupTemplateUrl;
        datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
          $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
        altInputFormats = angular.isDefined($attrs.altInputFormats) ?
          $scope.$parent.$eval($attrs.altInputFormats) :
          datepickerPopupConfig.altInputFormats;

        $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
          $scope.$parent.$eval($attrs.showButtonBar) :
          datepickerPopupConfig.showButtonBar;

        if (datepickerPopupConfig.html5Types[$attrs.type]) {
            dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
            isHtml5DateInput = true;
        } else {
            dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
            $attrs.$observe('uibDatepickerPopup', function (value, oldValue) {
                var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
                // Invalidate the $modelValue to ensure that formatters re-run
                // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
                if (newDateFormat !== dateFormat) {
                    dateFormat = newDateFormat;
                    ngModel.$modelValue = null;

                    if (!dateFormat) {
                        throw new Error('uibDatepickerPopup must have a date format specified.');
                    }
                }
            });
        }

        if (!dateFormat) {
            throw new Error('uibDatepickerPopup must have a date format specified.');
        }

        if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
            throw new Error('HTML5 date input types do not support custom formats.');
        }

        // popup element used to display calendar
        popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');

        popupEl.attr({
            'ng-model': 'date',
            'ng-change': 'dateSelection(date)',
            'template-url': datepickerPopupTemplateUrl
        });

        // datepicker element
        datepickerEl = angular.element(popupEl.children()[0]);
        datepickerEl.attr('template-url', datepickerTemplateUrl);

        if (!$scope.datepickerOptions) {
            $scope.datepickerOptions = {};
        }

        if (isHtml5DateInput) {
            if ($attrs.type === 'month') {
                $scope.datepickerOptions.datepickerMode = 'month';
                $scope.datepickerOptions.minMode = 'month';
            }
        }

        datepickerEl.attr('datepicker-options', 'datepickerOptions');

        if (!isHtml5DateInput) {
            // Internal API to maintain the correct ng-invalid-[key] class
            ngModel.$$parserName = 'date';
            ngModel.$validators.date = validator;
            ngModel.$parsers.unshift(parseDate);
            ngModel.$formatters.push(function (value) {
                if (ngModel.$isEmpty(value)) {
                    $scope.date = value;
                    return value;
                }

                if (angular.isNumber(value)) {
                    value = new Date(value);
                }

                $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);

                return dateParser.filter($scope.date, dateFormat);
            });
        } else {
            ngModel.$formatters.push(function (value) {
                $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);
                return value;
            });
        }

        // Detect changes in the view from the text box
        ngModel.$viewChangeListeners.push(function () {
            $scope.date = parseDateString(ngModel.$viewValue);
        });

        $element.on('keydown', inputKeydownBind);

        $popup = $compile(popupEl)($scope);
        // Prevent jQuery cache memory leak (template is now redundant after linking)
        popupEl.remove();

        if (appendToBody) {
            $document.find('body').append($popup);
        } else {
            $element.after($popup);
        }

        $scope.$on('$destroy', function () {
            if ($scope.isOpen === true) {
                if (!$rootScope.$$phase) {
                    $scope.$apply(function () {
                        $scope.isOpen = false;
                    });
                }
            }

            $popup.remove();
            $element.off('keydown', inputKeydownBind);
            $document.off('click', documentClickBind);
            if (scrollParentEl) {
                scrollParentEl.off('scroll', positionPopup);
            }
            angular.element($window).off('resize', positionPopup);

            //Clear all watch listeners on destroy
            while (watchListeners.length) {
                watchListeners.shift()();
            }
        });
    };

    $scope.getText = function (key) {
        return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
    };

    $scope.isDisabled = function (date) {
        if (date === 'today') {
            date = dateParser.fromTimezone(new Date(), ngModelOptions.timezone);
        }

        var dates = {};
        angular.forEach(['minDate', 'maxDate'], function (key) {
            if (!$scope.datepickerOptions[key]) {
                dates[key] = null;
            } else if (angular.isDate($scope.datepickerOptions[key])) {
                dates[key] = new Date($scope.datepickerOptions[key]);
            } else {
                if ($datepickerPopupLiteralWarning) {
                    $log.warn('Literal date support has been deprecated, please switch to date object usage');
                }

                dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
            }
        });

        return $scope.datepickerOptions &&
          dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
          dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
    };

    $scope.compare = function (date1, date2) {
        return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
    };

    // Inner change
    $scope.dateSelection = function (dt) {
        $scope.date = dt;
        var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
        $element.val(date);
        ngModel.$setViewValue(date);

        if (closeOnDateSelection) {
            $scope.isOpen = false;
            $element[0].focus();
        }
    };

    $scope.keydown = function (evt) {
        if (evt.which === 27) {
            evt.stopPropagation();
            $scope.isOpen = false;
            $element[0].focus();
        }
    };

    $scope.select = function (date, evt) {
        evt.stopPropagation();

        if (date === 'today') {
            var today = new Date();
            if (angular.isDate($scope.date)) {
                date = new Date($scope.date);
                date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
            } else {
                date = dateParser.fromTimezone(today, ngModelOptions.timezone);
                date.setHours(0, 0, 0, 0);
            }
        }
        $scope.dateSelection(date);
    };

    $scope.close = function (evt) {
        evt.stopPropagation();

        $scope.isOpen = false;
        $element[0].focus();
    };

    $scope.disabled = angular.isDefined($attrs.disabled) || false;
    if ($attrs.ngDisabled) {
        watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function (disabled) {
            $scope.disabled = disabled;
        }));
    }

    $scope.$watch('isOpen', function (value) {
        if (value) {
            if (!$scope.disabled) {
                $timeout(function () {
                    positionPopup();

                    if (onOpenFocus) {
                        $scope.$broadcast('uib:datepicker.focus');
                    }

                    $document.on('click', documentClickBind);

                    var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
                    if (appendToBody || $position.parsePlacement(placement)[2]) {
                        scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
                        if (scrollParentEl) {
                            scrollParentEl.on('scroll', positionPopup);
                        }
                    } else {
                        scrollParentEl = null;
                    }

                    angular.element($window).on('resize', positionPopup);
                }, 0, false);
            } else {
                $scope.isOpen = false;
            }
        } else {
            $document.off('click', documentClickBind);
            if (scrollParentEl) {
                scrollParentEl.off('scroll', positionPopup);
            }
            angular.element($window).off('resize', positionPopup);
        }
    });

    function cameltoDash(string) {
        return string.replace(/([A-Z])/g, function ($1) { return '-' + $1.toLowerCase(); });
    }

    function parseDateString(viewValue) {
        var date = dateParser.parse(viewValue, dateFormat, $scope.date);
        if (isNaN(date)) {
            for (var i = 0; i < altInputFormats.length; i++) {
                date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
                if (!isNaN(date)) {
                    return date;
                }
            }
        }
        return date;
    }

    function parseDate(viewValue) {
        if (angular.isNumber(viewValue)) {
            // presumably timestamp to date object
            viewValue = new Date(viewValue);
        }

        if (!viewValue) {
            return null;
        }

        if (angular.isDate(viewValue) && !isNaN(viewValue)) {
            return viewValue;
        }

        if (angular.isString(viewValue)) {
            var date = parseDateString(viewValue);
            if (!isNaN(date)) {
                return dateParser.fromTimezone(date, ngModelOptions.timezone);
            }
        }

        return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined;
    }

    function validator(modelValue, viewValue) {
        var value = modelValue || viewValue;

        if (!$attrs.ngRequired && !value) {
            return true;
        }

        if (angular.isNumber(value)) {
            value = new Date(value);
        }

        if (!value) {
            return true;
        }

        if (angular.isDate(value) && !isNaN(value)) {
            return true;
        }

        if (angular.isString(value)) {
            return !isNaN(parseDateString(value));
        }

        return false;
    }

    function documentClickBind(event) {
        if (!$scope.isOpen && $scope.disabled) {
            return;
        }

        var popup = $popup[0];
        var dpContainsTarget = $element[0].contains(event.target);
        // The popup node may not be an element node
        // In some browsers (IE) only element nodes have the 'contains' function
        var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
        if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
            $scope.$apply(function () {
                $scope.isOpen = false;
            });
        }
    }

    function inputKeydownBind(evt) {
        if (evt.which === 27 && $scope.isOpen) {
            evt.preventDefault();
            evt.stopPropagation();
            $scope.$apply(function () {
                $scope.isOpen = false;
            });
            $element[0].focus();
        } else if (evt.which === 40 && !$scope.isOpen) {
            evt.preventDefault();
            evt.stopPropagation();
            $scope.$apply(function () {
                $scope.isOpen = true;
            });
        }
    }

    function positionPopup() {
        if ($scope.isOpen) {
            var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
            var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
            var position = $position.positionElements($element, dpElement, placement, appendToBody);
            dpElement.css({ top: position.top + 'px', left: position.left + 'px' });
            if (dpElement.hasClass('uib-position-measure')) {
                dpElement.removeClass('uib-position-measure');
            }
        }
    }

    $scope.$on('uib:datepicker.mode', function () {
        $timeout(positionPopup, 0, false);
    });
}])

.directive('uibDatepickerPopup', function () {
    return {
        require: ['ngModel', 'uibDatepickerPopup'],
        controller: 'UibDatepickerPopupController',
        scope: {
            datepickerOptions: '=?',
            isOpen: '=?',
            currentText: '@',
            clearText: '@',
            closeText: '@'
        },
        link: function (scope, element, attrs, ctrls) {
            var ngModel = ctrls[0],
              ctrl = ctrls[1];

            ctrl.init(ngModel);
        }
    };
})

.directive('uibDatepickerPopupWrap', function () {
    return {
        restrict: 'A',
        transclude: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';
        }
    };
});

angular.module('ui.bootstrap.debounce', [])
/**
 * A helper, internal service that debounces a function
 */
  .factory('$$debounce', ['$timeout', function ($timeout) {
      return function (callback, debounceTime) {
          var timeoutPromise;

          return function () {
              var self = this;
              var args = Array.prototype.slice.call(arguments);
              if (timeoutPromise) {
                  $timeout.cancel(timeoutPromise);
              }

              timeoutPromise = $timeout(function () {
                  callback.apply(self, args);
              }, debounceTime);
          };
      };
  }]);

angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])

.constant('uibDropdownConfig', {
    appendToOpenClass: 'uib-dropdown-open',
    openClass: 'open'
})

.service('uibDropdownService', ['$document', '$rootScope', function ($document, $rootScope) {
    var openScope = null;

    this.open = function (dropdownScope, element) {
        if (!openScope) {
            $document.on('click', closeDropdown);
        }

        if (openScope && openScope !== dropdownScope) {
            openScope.isOpen = false;
        }

        openScope = dropdownScope;
    };

    this.close = function (dropdownScope, element) {
        if (openScope === dropdownScope) {
            $document.off('click', closeDropdown);
            $document.off('keydown', this.keybindFilter);
            openScope = null;
        }
    };

    var closeDropdown = function (evt) {
        // This method may still be called during the same mouse event that
        // unbound this event handler. So check openScope before proceeding.
        if (!openScope) { return; }

        if (evt && openScope.getAutoClose() === 'disabled') { return; }

        if (evt && evt.which === 3) { return; }

        var toggleElement = openScope.getToggleElement();
        if (evt && toggleElement && toggleElement[0].contains(evt.target)) {
            return;
        }

        var dropdownElement = openScope.getDropdownElement();
        if (evt && openScope.getAutoClose() === 'outsideClick' &&
          dropdownElement && dropdownElement[0].contains(evt.target)) {
            return;
        }

        openScope.focusToggleElement();
        openScope.isOpen = false;

        if (!$rootScope.$$phase) {
            openScope.$apply();
        }
    };

    this.keybindFilter = function (evt) {
        if (!openScope) {
            // see this.close as ESC could have been pressed which kills the scope so we can not proceed
            return;
        }

        var dropdownElement = openScope.getDropdownElement();
        var toggleElement = openScope.getToggleElement();
        var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);
        var toggleElementTargeted = toggleElement && toggleElement[0].contains(evt.target);
        if (evt.which === 27) {
            evt.stopPropagation();
            openScope.focusToggleElement();
            closeDropdown();
        } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen && (dropdownElementTargeted || toggleElementTargeted)) {
            evt.preventDefault();
            evt.stopPropagation();
            openScope.focusDropdownEntry(evt.which);
        }
    };
}])

.controller('UibDropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', function ($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest) {
    var self = this,
      scope = $scope.$new(), // create a child scope so we are not polluting original one
      templateScope,
      appendToOpenClass = dropdownConfig.appendToOpenClass,
      openClass = dropdownConfig.openClass,
      getIsOpen,
      setIsOpen = angular.noop,
      toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
      appendToBody = false,
      appendTo = null,
      keynavEnabled = false,
      selectedOption = null,
      body = $document.find('body');

    $element.addClass('dropdown');

    this.init = function () {
        if ($attrs.isOpen) {
            getIsOpen = $parse($attrs.isOpen);
            setIsOpen = getIsOpen.assign;

            $scope.$watch(getIsOpen, function (value) {
                scope.isOpen = !!value;
            });
        }

        if (angular.isDefined($attrs.dropdownAppendTo)) {
            var appendToEl = $parse($attrs.dropdownAppendTo)(scope);
            if (appendToEl) {
                appendTo = angular.element(appendToEl);
            }
        }

        appendToBody = angular.isDefined($attrs.dropdownAppendToBody);
        keynavEnabled = angular.isDefined($attrs.keyboardNav);

        if (appendToBody && !appendTo) {
            appendTo = body;
        }

        if (appendTo && self.dropdownMenu) {
            appendTo.append(self.dropdownMenu);
            $element.on('$destroy', function handleDestroyEvent() {
                self.dropdownMenu.remove();
            });
        }
    };

    this.toggle = function (open) {
        scope.isOpen = arguments.length ? !!open : !scope.isOpen;
        if (angular.isFunction(setIsOpen)) {
            setIsOpen(scope, scope.isOpen);
        }

        return scope.isOpen;
    };

    // Allow other directives to watch status
    this.isOpen = function () {
        return scope.isOpen;
    };

    scope.getToggleElement = function () {
        return self.toggleElement;
    };

    scope.getAutoClose = function () {
        return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'
    };

    scope.getElement = function () {
        return $element;
    };

    scope.isKeynavEnabled = function () {
        return keynavEnabled;
    };

    scope.focusDropdownEntry = function (keyCode) {
        var elems = self.dropdownMenu ? //If append to body is used.
          angular.element(self.dropdownMenu).find('a') :
          $element.find('ul').eq(0).find('a');

        switch (keyCode) {
            case 40: {
                if (!angular.isNumber(self.selectedOption)) {
                    self.selectedOption = 0;
                } else {
                    self.selectedOption = self.selectedOption === elems.length - 1 ?
                      self.selectedOption :
                      self.selectedOption + 1;
                }
                break;
            }
            case 38: {
                if (!angular.isNumber(self.selectedOption)) {
                    self.selectedOption = elems.length - 1;
                } else {
                    self.selectedOption = self.selectedOption === 0 ?
                      0 : self.selectedOption - 1;
                }
                break;
            }
        }
        elems[self.selectedOption].focus();
    };

    scope.getDropdownElement = function () {
        return self.dropdownMenu;
    };

    scope.focusToggleElement = function () {
        if (self.toggleElement) {
            self.toggleElement[0].focus();
        }
    };

    scope.$watch('isOpen', function (isOpen, wasOpen) {
        if (appendTo && self.dropdownMenu) {
            var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true),
              css,
              rightalign,
              scrollbarPadding,
              scrollbarWidth = 0;

            css = {
                top: pos.top + 'px',
                display: isOpen ? 'block' : 'none'
            };

            rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');
            if (!rightalign) {
                css.left = pos.left + 'px';
                css.right = 'auto';
            } else {
                css.left = 'auto';
                scrollbarPadding = $position.scrollbarPadding(appendTo);

                if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
                    scrollbarWidth = scrollbarPadding.scrollbarWidth;
                }

                css.right = window.innerWidth - scrollbarWidth -
                  (pos.left + $element.prop('offsetWidth')) + 'px';
            }

            // Need to adjust our positioning to be relative to the appendTo container
            // if it's not the body element
            if (!appendToBody) {
                var appendOffset = $position.offset(appendTo);

                css.top = pos.top - appendOffset.top + 'px';

                if (!rightalign) {
                    css.left = pos.left - appendOffset.left + 'px';
                } else {
                    css.right = window.innerWidth -
                      (pos.left - appendOffset.left + $element.prop('offsetWidth')) + 'px';
                }
            }

            self.dropdownMenu.css(css);
        }

        var openContainer = appendTo ? appendTo : $element;
        var hasOpenClass = openContainer.hasClass(appendTo ? appendToOpenClass : openClass);

        if (hasOpenClass === !isOpen) {
            $animate[isOpen ? 'addClass' : 'removeClass'](openContainer, appendTo ? appendToOpenClass : openClass).then(function () {
                if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
                    toggleInvoker($scope, { open: !!isOpen });
                }
            });
        }

        if (isOpen) {
            if (self.dropdownMenuTemplateUrl) {
                $templateRequest(self.dropdownMenuTemplateUrl).then(function (tplContent) {
                    templateScope = scope.$new();
                    $compile(tplContent.trim())(templateScope, function (dropdownElement) {
                        var newEl = dropdownElement;
                        self.dropdownMenu.replaceWith(newEl);
                        self.dropdownMenu = newEl;
                        $document.on('keydown', uibDropdownService.keybindFilter);
                    });
                });
            } else {
                $document.on('keydown', uibDropdownService.keybindFilter);
            }

            scope.focusToggleElement();
            uibDropdownService.open(scope, $element);
        } else {
            uibDropdownService.close(scope, $element);
            if (self.dropdownMenuTemplateUrl) {
                if (templateScope) {
                    templateScope.$destroy();
                }
                var newEl = angular.element('<ul class="dropdown-menu"></ul>');
                self.dropdownMenu.replaceWith(newEl);
                self.dropdownMenu = newEl;
            }

            self.selectedOption = null;
        }

        if (angular.isFunction(setIsOpen)) {
            setIsOpen($scope, isOpen);
        }
    });
}])

.directive('uibDropdown', function () {
    return {
        controller: 'UibDropdownController',
        link: function (scope, element, attrs, dropdownCtrl) {
            dropdownCtrl.init();
        }
    };
})

.directive('uibDropdownMenu', function () {
    return {
        restrict: 'A',
        require: '?^uibDropdown',
        link: function (scope, element, attrs, dropdownCtrl) {
            if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {
                return;
            }

            element.addClass('dropdown-menu');

            var tplUrl = attrs.templateUrl;
            if (tplUrl) {
                dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;
            }

            if (!dropdownCtrl.dropdownMenu) {
                dropdownCtrl.dropdownMenu = element;
            }
        }
    };
})

.directive('uibDropdownToggle', function () {
    return {
        require: '?^uibDropdown',
        link: function (scope, element, attrs, dropdownCtrl) {
            if (!dropdownCtrl) {
                return;
            }

            element.addClass('dropdown-toggle');

            dropdownCtrl.toggleElement = element;

            var toggleDropdown = function (event) {
                event.preventDefault();

                if (!element.hasClass('disabled') && !attrs.disabled) {
                    scope.$apply(function () {
                        dropdownCtrl.toggle();
                    });
                }
            };

            element.bind('click', toggleDropdown);

            // WAI-ARIA
            element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
            scope.$watch(dropdownCtrl.isOpen, function (isOpen) {
                element.attr('aria-expanded', !!isOpen);
            });

            scope.$on('$destroy', function () {
                element.unbind('click', toggleDropdown);
            });
        }
    };
});

angular.module('ui.bootstrap.stackedMap', [])
/**
 * A helper, internal data structure that acts as a map but also allows getting / removing
 * elements in the LIFO order
 */
  .factory('$$stackedMap', function () {
      return {
          createNew: function () {
              var stack = [];

              return {
                  add: function (key, value) {
                      stack.push({
                          key: key,
                          value: value
                      });
                  },
                  get: function (key) {
                      for (var i = 0; i < stack.length; i++) {
                          if (key === stack[i].key) {
                              return stack[i];
                          }
                      }
                  },
                  keys: function () {
                      var keys = [];
                      for (var i = 0; i < stack.length; i++) {
                          keys.push(stack[i].key);
                      }
                      return keys;
                  },
                  top: function () {
                      return stack[stack.length - 1];
                  },
                  remove: function (key) {
                      var idx = -1;
                      for (var i = 0; i < stack.length; i++) {
                          if (key === stack[i].key) {
                              idx = i;
                              break;
                          }
                      }
                      return stack.splice(idx, 1)[0];
                  },
                  removeTop: function () {
                      return stack.pop();
                  },
                  length: function () {
                      return stack.length;
                  }
              };
          }
      };
  });
angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.position'])
/**
 * A helper, internal data structure that stores all references attached to key
 */
  .factory('$$multiMap', function () {
      return {
          createNew: function () {
              var map = {};

              return {
                  entries: function () {
                      return Object.keys(map).map(function (key) {
                          return {
                              key: key,
                              value: map[key]
                          };
                      });
                  },
                  get: function (key) {
                      return map[key];
                  },
                  hasKey: function (key) {
                      return !!map[key];
                  },
                  keys: function () {
                      return Object.keys(map);
                  },
                  put: function (key, value) {
                      if (!map[key]) {
                          map[key] = [];
                      }

                      map[key].push(value);
                  },
                  remove: function (key, value) {
                      var values = map[key];

                      if (!values) {
                          return;
                      }

                      var idx = values.indexOf(value);

                      if (idx !== -1) {
                          values.splice(idx, 1);
                      }

                      if (!values.length) {
                          delete map[key];
                      }
                  }
              };
          }
      };
  })

/**
 * Pluggable resolve mechanism for the modal resolve resolution
 * Supports UI Router's $resolve service
 */
  .provider('$uibResolve', function () {
      var resolve = this;
      this.resolver = null;

      this.setResolver = function (resolver) {
          this.resolver = resolver;
      };

      this.$get = ['$injector', '$q', function ($injector, $q) {
          var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
          return {
              resolve: function (invocables, locals, parent, self) {
                  if (resolver) {
                      return resolver.resolve(invocables, locals, parent, self);
                  }

                  var promises = [];

                  angular.forEach(invocables, function (value) {
                      if (angular.isFunction(value) || angular.isArray(value)) {
                          promises.push($q.resolve($injector.invoke(value)));
                      } else if (angular.isString(value)) {
                          promises.push($q.resolve($injector.get(value)));
                      } else {
                          promises.push($q.resolve(value));
                      }
                  });

                  return $q.all(promises).then(function (resolves) {
                      var resolveObj = {};
                      var resolveIter = 0;
                      angular.forEach(invocables, function (value, key) {
                          resolveObj[key] = resolves[resolveIter++];
                      });

                      return resolveObj;
                  });
              }
          };
      }];
  })

/**
 * A helper directive for the $modal service. It creates a backdrop element.
 */
  .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
  function ($animate, $injector, $modalStack) {
      return {
          restrict: 'A',
          compile: function (tElement, tAttrs) {
              tElement.addClass(tAttrs.backdropClass);
              return linkFn;
          }
      };

      function linkFn(scope, element, attrs) {
          if (attrs.modalInClass) {
              $animate.addClass(element, attrs.modalInClass);

              scope.$on($modalStack.NOW_CLOSING_EVENT, function (e, setIsAsync) {
                  var done = setIsAsync();
                  if (scope.modalOptions.animation) {
                      $animate.removeClass(element, attrs.modalInClass).then(done);
                  } else {
                      done();
                  }
              });
          }
      }
  }])

  .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',
  function ($modalStack, $q, $animateCss, $document) {
      return {
          scope: {
              index: '@'
          },
          restrict: 'A',
          transclude: true,
          templateUrl: function (tElement, tAttrs) {
              return tAttrs.templateUrl || 'uib/template/modal/window.html';
          },
          link: function (scope, element, attrs) {
              element.addClass(attrs.windowTopClass || '');
              scope.size = attrs.size;

              scope.close = function (evt) {
                  var modal = $modalStack.getTop();
                  if (modal && modal.value.backdrop &&
                    modal.value.backdrop !== 'static' &&
                    evt.target === evt.currentTarget) {
                      evt.preventDefault();
                      evt.stopPropagation();
                      $modalStack.dismiss(modal.key, 'backdrop click');
                  }
              };

              // moved from template to fix issue #2280
              element.on('click', scope.close);

              // This property is only added to the scope for the purpose of detecting when this directive is rendered.
              // We can detect that by using this property in the template associated with this directive and then use
              // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
              scope.$isRendered = true;

              // Deferred object that will be resolved when this modal is rendered.
              var modalRenderDeferObj = $q.defer();
              // Resolve render promise post-digest
              scope.$$postDigest(function () {
                  modalRenderDeferObj.resolve();
              });

              modalRenderDeferObj.promise.then(function () {
                  var animationPromise = null;

                  if (attrs.modalInClass) {
                      animationPromise = $animateCss(element, {
                          addClass: attrs.modalInClass
                      }).start();

                      scope.$on($modalStack.NOW_CLOSING_EVENT, function (e, setIsAsync) {
                          var done = setIsAsync();
                          $animateCss(element, {
                              removeClass: attrs.modalInClass
                          }).start().then(done);
                      });
                  }


                  $q.when(animationPromise).then(function () {
                      // Notify {@link $modalStack} that modal is rendered.
                      var modal = $modalStack.getTop();
                      if (modal) {
                          $modalStack.modalRendered(modal.key);
                      }

                      /**
                       * If something within the freshly-opened modal already has focus (perhaps via a
                       * directive that causes focus) then there's no need to try to focus anything.
                       */
                      if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
                          var inputWithAutofocus = element[0].querySelector('[autofocus]');
                          /**
                           * Auto-focusing of a freshly-opened modal element causes any child elements
                           * with the autofocus attribute to lose focus. This is an issue on touch
                           * based devices which will show and then hide the onscreen keyboard.
                           * Attempts to refocus the autofocus element via JavaScript will not reopen
                           * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
                           * the modal element if the modal does not contain an autofocus element.
                           */
                          if (inputWithAutofocus) {
                              inputWithAutofocus.focus();
                          } else {
                              element[0].focus();
                          }
                      }
                  });
              });
          }
      };
  }])

  .directive('uibModalAnimationClass', function () {
      return {
          compile: function (tElement, tAttrs) {
              if (tAttrs.modalAnimation) {
                  tElement.addClass(tAttrs.uibModalAnimationClass);
              }
          }
      };
  })

  .directive('uibModalTransclude', ['$animate', function ($animate) {
      return {
          link: function (scope, element, attrs, controller, transclude) {
              transclude(scope.$parent, function (clone) {
                  element.empty();
                  $animate.enter(clone, element);
              });
          }
      };
  }])

  .factory('$uibModalStack', ['$animate', '$animateCss', '$document',
    '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
    function ($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {
        var OPENED_MODAL_CLASS = 'modal-open';

        var backdropDomEl, backdropScope;
        var openedWindows = $$stackedMap.createNew();
        var openedClasses = $$multiMap.createNew();
        var $modalStack = {
            NOW_CLOSING_EVENT: 'modal.stack.now-closing'
        };
        var topModalIndex = 0;
        var previousTopOpenedModal = null;
        var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count';

        //Modal focus behavior
        var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
          'button:not([disabled]):not([tabindex=\'-1\']),select:not([disabled]):not([tabindex=\'-1\']), textarea:not([disabled]):not([tabindex=\'-1\']), ' +
          'iframe, object, embed, *[tabindex]:not([tabindex=\'-1\']), *[contenteditable=true]';
        var scrollbarPadding;
        var SNAKE_CASE_REGEXP = /[A-Z]/g;

        // TODO: extract into common dependency with tooltip
        function snake_case(name) {
            var separator = '-';
            return name.replace(SNAKE_CASE_REGEXP, function (letter, pos) {
                return (pos ? separator : '') + letter.toLowerCase();
            });
        }

        function isVisible(element) {
            return !!(element.offsetWidth ||
              element.offsetHeight ||
              element.getClientRects().length);
        }

        function backdropIndex() {
            var topBackdropIndex = -1;
            var opened = openedWindows.keys();
            for (var i = 0; i < opened.length; i++) {
                if (openedWindows.get(opened[i]).value.backdrop) {
                    topBackdropIndex = i;
                }
            }

            // If any backdrop exist, ensure that it's index is always
            // right below the top modal
            if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
                topBackdropIndex = topModalIndex;
            }
            return topBackdropIndex;
        }

        $rootScope.$watch(backdropIndex, function (newBackdropIndex) {
            if (backdropScope) {
                backdropScope.index = newBackdropIndex;
            }
        });

        function removeModalWindow(modalInstance, elementToReceiveFocus) {
            var modalWindow = openedWindows.get(modalInstance).value;
            var appendToElement = modalWindow.appendTo;

            //clean up the stack
            openedWindows.remove(modalInstance);
            previousTopOpenedModal = openedWindows.top();
            if (previousTopOpenedModal) {
                topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
            }

            removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function () {
                var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
                openedClasses.remove(modalBodyClass, modalInstance);
                var areAnyOpen = openedClasses.hasKey(modalBodyClass);
                appendToElement.toggleClass(modalBodyClass, areAnyOpen);
                if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
                    if (scrollbarPadding.originalRight) {
                        appendToElement.css({ paddingRight: scrollbarPadding.originalRight + 'px' });
                    } else {
                        appendToElement.css({ paddingRight: '' });
                    }
                    scrollbarPadding = null;
                }
                toggleTopWindowClass(true);
            }, modalWindow.closedDeferred);
            checkRemoveBackdrop();

            //move focus to specified element if available, or else to body
            if (elementToReceiveFocus && elementToReceiveFocus.focus) {
                elementToReceiveFocus.focus();
            } else if (appendToElement.focus) {
                appendToElement.focus();
            }
        }

        // Add or remove "windowTopClass" from the top window in the stack
        function toggleTopWindowClass(toggleSwitch) {
            var modalWindow;

            if (openedWindows.length() > 0) {
                modalWindow = openedWindows.top().value;
                modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
            }
        }

        function checkRemoveBackdrop() {
            //remove backdrop if no longer needed
            if (backdropDomEl && backdropIndex() === -1) {
                var backdropScopeRef = backdropScope;
                removeAfterAnimate(backdropDomEl, backdropScope, function () {
                    backdropScopeRef = null;
                });
                backdropDomEl = undefined;
                backdropScope = undefined;
            }
        }

        function removeAfterAnimate(domEl, scope, done, closedDeferred) {
            var asyncDeferred;
            var asyncPromise = null;
            var setIsAsync = function () {
                if (!asyncDeferred) {
                    asyncDeferred = $q.defer();
                    asyncPromise = asyncDeferred.promise;
                }

                return function asyncDone() {
                    asyncDeferred.resolve();
                };
            };
            scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);

            // Note that it's intentional that asyncPromise might be null.
            // That's when setIsAsync has not been called during the
            // NOW_CLOSING_EVENT broadcast.
            return $q.when(asyncPromise).then(afterAnimating);

            function afterAnimating() {
                if (afterAnimating.done) {
                    return;
                }
                afterAnimating.done = true;

                $animate.leave(domEl).then(function () {
                    if (done) {
                        done();
                    }

                    domEl.remove();
                    if (closedDeferred) {
                        closedDeferred.resolve();
                    }
                });

                scope.$destroy();
            }
        }

        $document.on('keydown', keydownListener);

        $rootScope.$on('$destroy', function () {
            $document.off('keydown', keydownListener);
        });

        function keydownListener(evt) {
            if (evt.isDefaultPrevented()) {
                return evt;
            }

            var modal = openedWindows.top();
            if (modal) {
                switch (evt.which) {
                    case 27: {
                        if (modal.value.keyboard) {
                            evt.preventDefault();
                            $rootScope.$apply(function () {
                                $modalStack.dismiss(modal.key, 'escape key press');
                            });
                        }
                        break;
                    }
                    case 9: {
                        var list = $modalStack.loadFocusElementList(modal);
                        var focusChanged = false;
                        if (evt.shiftKey) {
                            if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {
                                focusChanged = $modalStack.focusLastFocusableElement(list);
                            }
                        } else {
                            if ($modalStack.isFocusInLastItem(evt, list)) {
                                focusChanged = $modalStack.focusFirstFocusableElement(list);
                            }
                        }

                        if (focusChanged) {
                            evt.preventDefault();
                            evt.stopPropagation();
                        }

                        break;
                    }
                }
            }
        }

        $modalStack.open = function (modalInstance, modal) {
            var modalOpener = $document[0].activeElement,
              modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;

            toggleTopWindowClass(false);

            // Store the current top first, to determine what index we ought to use
            // for the current top modal
            previousTopOpenedModal = openedWindows.top();

            openedWindows.add(modalInstance, {
                deferred: modal.deferred,
                renderDeferred: modal.renderDeferred,
                closedDeferred: modal.closedDeferred,
                modalScope: modal.scope,
                backdrop: modal.backdrop,
                keyboard: modal.keyboard,
                openedClass: modal.openedClass,
                windowTopClass: modal.windowTopClass,
                animation: modal.animation,
                appendTo: modal.appendTo
            });

            openedClasses.put(modalBodyClass, modalInstance);

            var appendToElement = modal.appendTo,
                currBackdropIndex = backdropIndex();

            if (!appendToElement.length) {
                throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
            }

            if (currBackdropIndex >= 0 && !backdropDomEl) {
                backdropScope = $rootScope.$new(true);
                backdropScope.modalOptions = modal;
                backdropScope.index = currBackdropIndex;
                backdropDomEl = angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');
                backdropDomEl.attr({
                    'class': 'modal-backdrop',
                    'ng-style': '{\'z-index\': 1040 + (index && 1 || 0) + index*10}',
                    'uib-modal-animation-class': 'fade',
                    'modal-in-class': 'in'
                });
                if (modal.backdropClass) {
                    backdropDomEl.addClass(modal.backdropClass);
                }

                if (modal.animation) {
                    backdropDomEl.attr('modal-animation', 'true');
                }
                $compile(backdropDomEl)(backdropScope);
                $animate.enter(backdropDomEl, appendToElement);
                if ($uibPosition.isScrollable(appendToElement)) {
                    scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
                    if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
                        appendToElement.css({ paddingRight: scrollbarPadding.right + 'px' });
                    }
                }
            }

            var content;
            if (modal.component) {
                content = document.createElement(snake_case(modal.component.name));
                content = angular.element(content);
                content.attr({
                    resolve: '$resolve',
                    'modal-instance': '$uibModalInstance',
                    close: '$close($value)',
                    dismiss: '$dismiss($value)'
                });
            } else {
                content = modal.content;
            }

            // Set the top modal index based on the index of the previous top modal
            topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
            var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
            angularDomEl.attr({
                'class': 'modal',
                'template-url': modal.windowTemplateUrl,
                'window-top-class': modal.windowTopClass,
                'role': 'dialog',
                'aria-labelledby': modal.ariaLabelledBy,
                'aria-describedby': modal.ariaDescribedBy,
                'size': modal.size,
                'index': topModalIndex,
                'animate': 'animate',
                'ng-style': '{\'z-index\': 1050 + $$topModalIndex*10, display: \'block\'}',
                'tabindex': -1,
                'uib-modal-animation-class': 'fade',
                'modal-in-class': 'in'
            }).append(content);
            if (modal.windowClass) {
                angularDomEl.addClass(modal.windowClass);
            }

            if (modal.animation) {
                angularDomEl.attr('modal-animation', 'true');
            }

            appendToElement.addClass(modalBodyClass);
            if (modal.scope) {
                // we need to explicitly add the modal index to the modal scope
                // because it is needed by ngStyle to compute the zIndex property.
                modal.scope.$$topModalIndex = topModalIndex;
            }
            $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);

            openedWindows.top().value.modalDomEl = angularDomEl;
            openedWindows.top().value.modalOpener = modalOpener;

            applyAriaHidden(angularDomEl);

            function applyAriaHidden(el) {
                if (!el || el[0].tagName === 'BODY') {
                    return;
                }

                getSiblings(el).forEach(function (sibling) {
                    var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true',
                      ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10);

                    if (!ariaHiddenCount) {
                        ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0;
                    }

                    sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1);
                    sibling.setAttribute('aria-hidden', 'true');
                });

                return applyAriaHidden(el.parent());

                function getSiblings(el) {
                    var children = el.parent() ? el.parent().children() : [];

                    return Array.prototype.filter.call(children, function (child) {
                        return child !== el[0];
                    });
                }
            }
        };

        function broadcastClosing(modalWindow, resultOrReason, closing) {
            return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
        }

        function unhideBackgroundElements() {
            Array.prototype.forEach.call(
              document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'),
              function (hiddenEl) {
                  var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10),
                    newHiddenCount = ariaHiddenCount - 1;
                  hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount);

                  if (!newHiddenCount) {
                      hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME);
                      hiddenEl.removeAttribute('aria-hidden');
                  }
              }
            );
        }

        $modalStack.close = function (modalInstance, result) {
            var modalWindow = openedWindows.get(modalInstance);
            unhideBackgroundElements();
            if (modalWindow && broadcastClosing(modalWindow, result, true)) {
                modalWindow.value.modalScope.$$uibDestructionScheduled = true;
                modalWindow.value.deferred.resolve(result);
                removeModalWindow(modalInstance, modalWindow.value.modalOpener);
                return true;
            }

            return !modalWindow;
        };

        $modalStack.dismiss = function (modalInstance, reason) {
            var modalWindow = openedWindows.get(modalInstance);
            unhideBackgroundElements();
            if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
                modalWindow.value.modalScope.$$uibDestructionScheduled = true;
                modalWindow.value.deferred.reject(reason);
                removeModalWindow(modalInstance, modalWindow.value.modalOpener);
                return true;
            }
            return !modalWindow;
        };

        $modalStack.dismissAll = function (reason) {
            var topModal = this.getTop();
            while (topModal && this.dismiss(topModal.key, reason)) {
                topModal = this.getTop();
            }
        };

        $modalStack.getTop = function () {
            return openedWindows.top();
        };

        $modalStack.modalRendered = function (modalInstance) {
            var modalWindow = openedWindows.get(modalInstance);
            $modalStack.focusFirstFocusableElement($modalStack.loadFocusElementList(modalWindow));
            if (modalWindow) {
                modalWindow.value.renderDeferred.resolve();
            }
        };

        $modalStack.focusFirstFocusableElement = function (list) {
            if (list.length > 0) {
                list[0].focus();
                return true;
            }
            return false;
        };

        $modalStack.focusLastFocusableElement = function (list) {
            if (list.length > 0) {
                list[list.length - 1].focus();
                return true;
            }
            return false;
        };

        $modalStack.isModalFocused = function (evt, modalWindow) {
            if (evt && modalWindow) {
                var modalDomEl = modalWindow.value.modalDomEl;
                if (modalDomEl && modalDomEl.length) {
                    return (evt.target || evt.srcElement) === modalDomEl[0];
                }
            }
            return false;
        };

        $modalStack.isFocusInFirstItem = function (evt, list) {
            if (list.length > 0) {
                return (evt.target || evt.srcElement) === list[0];
            }
            return false;
        };

        $modalStack.isFocusInLastItem = function (evt, list) {
            if (list.length > 0) {
                return (evt.target || evt.srcElement) === list[list.length - 1];
            }
            return false;
        };

        $modalStack.loadFocusElementList = function (modalWindow) {
            if (modalWindow) {
                var modalDomE1 = modalWindow.value.modalDomEl;
                if (modalDomE1 && modalDomE1.length) {
                    var elements = modalDomE1[0].querySelectorAll(tabbableSelector);
                    return elements ?
                      Array.prototype.filter.call(elements, function (element) {
                          return isVisible(element);
                      }) : elements;
                }
            }
        };

        return $modalStack;
    }])

  .provider('$uibModal', function () {
      var $modalProvider = {
          options: {
              animation: true,
              backdrop: true, //can also be false or 'static'
              keyboard: true
          },
          $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
            function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
                var $modal = {};

                function getTemplatePromise(options) {
                    return options.template ? $q.when(options.template) :
                      $templateRequest(angular.isFunction(options.templateUrl) ?
                        options.templateUrl() : options.templateUrl);
                }

                var promiseChain = null;
                $modal.getPromiseChain = function () {
                    return promiseChain;
                };

                $modal.open = function (modalOptions) {
                    var modalResultDeferred = $q.defer();
                    var modalOpenedDeferred = $q.defer();
                    var modalClosedDeferred = $q.defer();
                    var modalRenderDeferred = $q.defer();

                    //prepare an instance of a modal to be injected into controllers and returned to a caller
                    var modalInstance = {
                        result: modalResultDeferred.promise,
                        opened: modalOpenedDeferred.promise,
                        closed: modalClosedDeferred.promise,
                        rendered: modalRenderDeferred.promise,
                        close: function (result) {
                            return $modalStack.close(modalInstance, result);
                        },
                        dismiss: function (reason) {
                            return $modalStack.dismiss(modalInstance, reason);
                        }
                    };

                    //merge and clean up options
                    modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
                    modalOptions.resolve = modalOptions.resolve || {};
                    modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);

                    //verify options
                    if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) {
                        throw new Error('One of component or template or templateUrl options is required.');
                    }

                    var templateAndResolvePromise;
                    if (modalOptions.component) {
                        templateAndResolvePromise = $q.when($uibResolve.resolve(modalOptions.resolve, {}, null, null));
                    } else {
                        templateAndResolvePromise =
                          $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
                    }

                    function resolveWithTemplate() {
                        return templateAndResolvePromise;
                    }

                    // Wait for the resolution of the existing promise chain.
                    // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
                    // Then add to $modalStack and resolve opened.
                    // Finally clean up the chain variable if no subsequent modal has overwritten it.
                    var samePromise;
                    samePromise = promiseChain = $q.all([promiseChain])
                      .then(resolveWithTemplate, resolveWithTemplate)
                      .then(function resolveSuccess(tplAndVars) {
                          var providedScope = modalOptions.scope || $rootScope;

                          var modalScope = providedScope.$new();
                          modalScope.$close = modalInstance.close;
                          modalScope.$dismiss = modalInstance.dismiss;

                          modalScope.$on('$destroy', function () {
                              if (!modalScope.$$uibDestructionScheduled) {
                                  modalScope.$dismiss('$uibUnscheduledDestruction');
                              }
                          });

                          var modal = {
                              scope: modalScope,
                              deferred: modalResultDeferred,
                              renderDeferred: modalRenderDeferred,
                              closedDeferred: modalClosedDeferred,
                              animation: modalOptions.animation,
                              backdrop: modalOptions.backdrop,
                              keyboard: modalOptions.keyboard,
                              backdropClass: modalOptions.backdropClass,
                              windowTopClass: modalOptions.windowTopClass,
                              windowClass: modalOptions.windowClass,
                              windowTemplateUrl: modalOptions.windowTemplateUrl,
                              ariaLabelledBy: modalOptions.ariaLabelledBy,
                              ariaDescribedBy: modalOptions.ariaDescribedBy,
                              size: modalOptions.size,
                              openedClass: modalOptions.openedClass,
                              appendTo: modalOptions.appendTo
                          };

                          var component = {};
                          var ctrlInstance, ctrlInstantiate, ctrlLocals = {};

                          if (modalOptions.component) {
                              constructLocals(component, false, true, false);
                              component.name = modalOptions.component;
                              modal.component = component;
                          } else if (modalOptions.controller) {
                              constructLocals(ctrlLocals, true, false, true);

                              // the third param will make the controller instantiate later,private api
                              // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
                              ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
                              if (modalOptions.controllerAs && modalOptions.bindToController) {
                                  ctrlInstance = ctrlInstantiate.instance;
                                  ctrlInstance.$close = modalScope.$close;
                                  ctrlInstance.$dismiss = modalScope.$dismiss;
                                  angular.extend(ctrlInstance, {
                                      $resolve: ctrlLocals.$scope.$resolve
                                  }, providedScope);
                              }

                              ctrlInstance = ctrlInstantiate();

                              if (angular.isFunction(ctrlInstance.$onInit)) {
                                  ctrlInstance.$onInit();
                              }
                          }

                          if (!modalOptions.component) {
                              modal.content = tplAndVars[0];
                          }

                          $modalStack.open(modalInstance, modal);
                          modalOpenedDeferred.resolve(true);

                          function constructLocals(obj, template, instanceOnScope, injectable) {
                              obj.$scope = modalScope;
                              obj.$scope.$resolve = {};
                              if (instanceOnScope) {
                                  obj.$scope.$uibModalInstance = modalInstance;
                              } else {
                                  obj.$uibModalInstance = modalInstance;
                              }

                              var resolves = template ? tplAndVars[1] : tplAndVars;
                              angular.forEach(resolves, function (value, key) {
                                  if (injectable) {
                                      obj[key] = value;
                                  }

                                  obj.$scope.$resolve[key] = value;
                              });
                          }
                      }, function resolveError(reason) {
                          modalOpenedDeferred.reject(reason);
                          modalResultDeferred.reject(reason);
                      })['finally'](function () {
                          if (promiseChain === samePromise) {
                              promiseChain = null;
                          }
                      });

                    return modalInstance;
                };

                return $modal;
            }
          ]
      };

      return $modalProvider;
  });

angular.module('ui.bootstrap.paging', [])
/**
 * Helper internal service for generating common controller code between the
 * pager and pagination components
 */
.factory('uibPaging', ['$parse', function ($parse) {
    return {
        create: function (ctrl, $scope, $attrs) {
            ctrl.setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
            ctrl.ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl
            ctrl._watchers = [];

            ctrl.init = function (ngModelCtrl, config) {
                ctrl.ngModelCtrl = ngModelCtrl;
                ctrl.config = config;

                ngModelCtrl.$render = function () {
                    ctrl.render();
                };

                if ($attrs.itemsPerPage) {
                    ctrl._watchers.push($scope.$parent.$watch($attrs.itemsPerPage, function (value) {
                        ctrl.itemsPerPage = parseInt(value, 10);
                        $scope.totalPages = ctrl.calculateTotalPages();
                        ctrl.updatePage();
                    }));
                } else {
                    ctrl.itemsPerPage = config.itemsPerPage;
                }

                $scope.$watch('totalItems', function (newTotal, oldTotal) {
                    if (angular.isDefined(newTotal) || newTotal !== oldTotal) {
                        $scope.totalPages = ctrl.calculateTotalPages();
                        ctrl.updatePage();
                    }
                });
            };

            ctrl.calculateTotalPages = function () {
                var totalPages = ctrl.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / ctrl.itemsPerPage);
                return Math.max(totalPages || 0, 1);
            };

            ctrl.render = function () {
                $scope.page = parseInt(ctrl.ngModelCtrl.$viewValue, 10) || 1;
            };

            $scope.selectPage = function (page, evt) {
                if (evt) {
                    evt.preventDefault();
                }

                var clickAllowed = !$scope.ngDisabled || !evt;
                if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {
                    if (evt && evt.target) {
                        evt.target.blur();
                    }
                    ctrl.ngModelCtrl.$setViewValue(page);
                    ctrl.ngModelCtrl.$render();
                }
            };

            $scope.getText = function (key) {
                return $scope[key + 'Text'] || ctrl.config[key + 'Text'];
            };

            $scope.noPrevious = function () {
                return $scope.page === 1;
            };

            $scope.noNext = function () {
                return $scope.page === $scope.totalPages;
            };

            ctrl.updatePage = function () {
                ctrl.setNumPages($scope.$parent, $scope.totalPages); // Readonly variable

                if ($scope.page > $scope.totalPages) {
                    $scope.selectPage($scope.totalPages);
                } else {
                    ctrl.ngModelCtrl.$render();
                }
            };

            $scope.$on('$destroy', function () {
                while (ctrl._watchers.length) {
                    ctrl._watchers.shift()();
                }
            });
        }
    };
}]);

angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])

.controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function ($scope, $attrs, uibPaging, uibPagerConfig) {
    $scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align;

    uibPaging.create(this, $scope, $attrs);
}])

.constant('uibPagerConfig', {
    itemsPerPage: 10,
    previousText: '« Previous',
    nextText: 'Next »',
    align: true
})

.directive('uibPager', ['uibPagerConfig', function (uibPagerConfig) {
    return {
        scope: {
            totalItems: '=',
            previousText: '@',
            nextText: '@',
            ngDisabled: '='
        },
        require: ['uibPager', '?ngModel'],
        restrict: 'A',
        controller: 'UibPagerController',
        controllerAs: 'pager',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/pager/pager.html';
        },
        link: function (scope, element, attrs, ctrls) {
            element.addClass('pager');
            var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            if (!ngModelCtrl) {
                return; // do nothing if no ng-model
            }

            paginationCtrl.init(ngModelCtrl, uibPagerConfig);
        }
    };
}]);

angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
.controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function ($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {
    var ctrl = this;
    // Setup configuration parameters
    var maxSize = angular.isDefined($attrs.maxSize) ? $scope.$parent.$eval($attrs.maxSize) : uibPaginationConfig.maxSize,
      rotate = angular.isDefined($attrs.rotate) ? $scope.$parent.$eval($attrs.rotate) : uibPaginationConfig.rotate,
      forceEllipses = angular.isDefined($attrs.forceEllipses) ? $scope.$parent.$eval($attrs.forceEllipses) : uibPaginationConfig.forceEllipses,
      boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers,
      pageLabel = angular.isDefined($attrs.pageLabel) ? function (idx) { return $scope.$parent.$eval($attrs.pageLabel, { $page: idx }); } : angular.identity;
    $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks;
    $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks;

    uibPaging.create(this, $scope, $attrs);

    if ($attrs.maxSize) {
        ctrl._watchers.push($scope.$parent.$watch($parse($attrs.maxSize), function (value) {
            maxSize = parseInt(value, 10);
            ctrl.render();
        }));
    }

    // Create page object used in template
    function makePage(number, text, isActive) {
        return {
            number: number,
            text: text,
            active: isActive
        };
    }

    function getPages(currentPage, totalPages) {
        var pages = [];

        // Default page limits
        var startPage = 1, endPage = totalPages;
        var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;

        // recompute if maxSize
        if (isMaxSized) {
            if (rotate) {
                // Current page is displayed in the middle of the visible ones
                startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
                endPage = startPage + maxSize - 1;

                // Adjust if limit is exceeded
                if (endPage > totalPages) {
                    endPage = totalPages;
                    startPage = endPage - maxSize + 1;
                }
            } else {
                // Visible pages are paginated with maxSize
                startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1;

                // Adjust last page if limit is exceeded
                endPage = Math.min(startPage + maxSize - 1, totalPages);
            }
        }

        // Add page number links
        for (var number = startPage; number <= endPage; number++) {
            var page = makePage(number, pageLabel(number), number === currentPage);
            pages.push(page);
        }

        // Add links to move between page sets
        if (isMaxSized && maxSize > 0 && (!rotate || forceEllipses || boundaryLinkNumbers)) {
            if (startPage > 1) {
                if (!boundaryLinkNumbers || startPage > 3) { //need ellipsis for all options unless range is too close to beginning
                    var previousPageSet = makePage(startPage - 1, '...', false);
                    pages.unshift(previousPageSet);
                }
                if (boundaryLinkNumbers) {
                    if (startPage === 3) { //need to replace ellipsis when the buttons would be sequential
                        var secondPageLink = makePage(2, '2', false);
                        pages.unshift(secondPageLink);
                    }
                    //add the first page
                    var firstPageLink = makePage(1, '1', false);
                    pages.unshift(firstPageLink);
                }
            }

            if (endPage < totalPages) {
                if (!boundaryLinkNumbers || endPage < totalPages - 2) { //need ellipsis for all options unless range is too close to end
                    var nextPageSet = makePage(endPage + 1, '...', false);
                    pages.push(nextPageSet);
                }
                if (boundaryLinkNumbers) {
                    if (endPage === totalPages - 2) { //need to replace ellipsis when the buttons would be sequential
                        var secondToLastPageLink = makePage(totalPages - 1, totalPages - 1, false);
                        pages.push(secondToLastPageLink);
                    }
                    //add the last page
                    var lastPageLink = makePage(totalPages, totalPages, false);
                    pages.push(lastPageLink);
                }
            }
        }
        return pages;
    }

    var originalRender = this.render;
    this.render = function () {
        originalRender();
        if ($scope.page > 0 && $scope.page <= $scope.totalPages) {
            $scope.pages = getPages($scope.page, $scope.totalPages);
        }
    };
}])

.constant('uibPaginationConfig', {
    itemsPerPage: 10,
    boundaryLinks: false,
    boundaryLinkNumbers: false,
    directionLinks: true,
    firstText: 'First',
    previousText: 'Previous',
    nextText: 'Next',
    lastText: 'Last',
    rotate: true,
    forceEllipses: false
})

.directive('uibPagination', ['$parse', 'uibPaginationConfig', function ($parse, uibPaginationConfig) {
    return {
        scope: {
            totalItems: '=',
            firstText: '@',
            previousText: '@',
            nextText: '@',
            lastText: '@',
            ngDisabled: '='
        },
        require: ['uibPagination', '?ngModel'],
        restrict: 'A',
        controller: 'UibPaginationController',
        controllerAs: 'pagination',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/pagination/pagination.html';
        },
        link: function (scope, element, attrs, ctrls) {
            element.addClass('pagination');
            var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            if (!ngModelCtrl) {
                return; // do nothing if no ng-model
            }

            paginationCtrl.init(ngModelCtrl, uibPaginationConfig);
        }
    };
}]);

/**
 * The following features are still outstanding: animation as a
 * function, placement as a function, inside, support for more triggers than
 * just mouse enter/leave, html tooltips, and selector delegation.
 */
angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])

/**
 * The $tooltip service creates tooltip- and popover-like directives as well as
 * houses global options for them.
 */
.provider('$uibTooltip', function () {
    // The default options tooltip and popover.
    var defaultOptions = {
        placement: 'top',
        placementClassPrefix: '',
        animation: true,
        popupDelay: 0,
        popupCloseDelay: 0,
        useContentExp: false
    };

    // Default hide triggers for each show trigger
    var triggerMap = {
        'mouseenter': 'mouseleave',
        'click': 'click',
        'outsideClick': 'outsideClick',
        'focus': 'blur',
        'none': ''
    };

    // The options specified to the provider globally.
    var globalOptions = {};

    /**
     * `options({})` allows global configuration of all tooltips in the
     * application.
     *
     *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
     *     // place tooltips left instead of top by default
     *     $tooltipProvider.options( { placement: 'left' } );
     *   });
     */
    this.options = function (value) {
        angular.extend(globalOptions, value);
    };

    /**
     * This allows you to extend the set of trigger mappings available. E.g.:
     *
     *   $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
     */
    this.setTriggers = function setTriggers(triggers) {
        angular.extend(triggerMap, triggers);
    };

    /**
     * This is a helper function for translating camel-case to snake_case.
     */
    function snake_case(name) {
        var regexp = /[A-Z]/g;
        var separator = '-';
        return name.replace(regexp, function (letter, pos) {
            return (pos ? separator : '') + letter.toLowerCase();
        });
    }

    /**
     * Returns the actual instance of the $tooltip service.
     * TODO support multiple triggers
     */
    this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function ($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
        var openedTooltips = $$stackedMap.createNew();
        $document.on('keyup', keypressListener);

        $rootScope.$on('$destroy', function () {
            $document.off('keyup', keypressListener);
        });

        function keypressListener(e) {
            if (e.which === 27) {
                var last = openedTooltips.top();
                if (last) {
                    last.value.close();
                    last = null;
                }
            }
        }

        return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
            options = angular.extend({}, defaultOptions, globalOptions, options);

            /**
             * Returns an object of show and hide triggers.
             *
             * If a trigger is supplied,
             * it is used to show the tooltip; otherwise, it will use the `trigger`
             * option passed to the `$tooltipProvider.options` method; else it will
             * default to the trigger supplied to this directive factory.
             *
             * The hide trigger is based on the show trigger. If the `trigger` option
             * was passed to the `$tooltipProvider.options` method, it will use the
             * mapped trigger from `triggerMap` or the passed trigger if the map is
             * undefined; otherwise, it uses the `triggerMap` value of the show
             * trigger; else it will just use the show trigger.
             */
            function getTriggers(trigger) {
                var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
                var hide = show.map(function (trigger) {
                    return triggerMap[trigger] || trigger;
                });
                return {
                    show: show,
                    hide: hide
                };
            }

            var directiveName = snake_case(ttType);

            var startSym = $interpolate.startSymbol();
            var endSym = $interpolate.endSymbol();
            var template =
              '<div ' + directiveName + '-popup ' +
                'uib-title="' + startSym + 'title' + endSym + '" ' +
                (options.useContentExp ?
                  'content-exp="contentExp()" ' :
                  'content="' + startSym + 'content' + endSym + '" ') +
                'origin-scope="origScope" ' +
                'class="uib-position-measure ' + prefix + '" ' +
                'tooltip-animation-class="fade"' +
                'uib-tooltip-classes ' +
                'ng-class="{ in: isOpen }" ' +
                '>' +
              '</div>';

            return {
                compile: function (tElem, tAttrs) {
                    var tooltipLinker = $compile(template);

                    return function link(scope, element, attrs, tooltipCtrl) {
                        var tooltip;
                        var tooltipLinkedScope;
                        var transitionTimeout;
                        var showTimeout;
                        var hideTimeout;
                        var positionTimeout;
                        var adjustmentTimeout;
                        var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
                        var triggers = getTriggers(undefined);
                        var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
                        var ttScope = scope.$new(true);
                        var repositionScheduled = false;
                        var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;
                        var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;
                        var observers = [];
                        var lastPlacement;

                        var positionTooltip = function () {
                            // check if tooltip exists and is not empty
                            if (!tooltip || !tooltip.html()) { return; }

                            if (!positionTimeout) {
                                positionTimeout = $timeout(function () {
                                    var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
                                    var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
                                    var elementPos = appendToBody ? $position.offset(element) : $position.position(element);
                                    tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });
                                    var placementClasses = ttPosition.placement.split('-');

                                    if (!tooltip.hasClass(placementClasses[0])) {
                                        tooltip.removeClass(lastPlacement.split('-')[0]);
                                        tooltip.addClass(placementClasses[0]);
                                    }

                                    if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {
                                        tooltip.removeClass(options.placementClassPrefix + lastPlacement);
                                        tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
                                    }

                                    adjustmentTimeout = $timeout(function () {
                                        var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
                                        var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);
                                        if (adjustment) {
                                            tooltip.css(adjustment);
                                        }
                                        adjustmentTimeout = null;
                                    }, 0, false);

                                    // first time through tt element will have the
                                    // uib-position-measure class or if the placement
                                    // has changed we need to position the arrow.
                                    if (tooltip.hasClass('uib-position-measure')) {
                                        $position.positionArrow(tooltip, ttPosition.placement);
                                        tooltip.removeClass('uib-position-measure');
                                    } else if (lastPlacement !== ttPosition.placement) {
                                        $position.positionArrow(tooltip, ttPosition.placement);
                                    }
                                    lastPlacement = ttPosition.placement;

                                    positionTimeout = null;
                                }, 0, false);
                            }
                        };

                        // Set up the correct scope to allow transclusion later
                        ttScope.origScope = scope;

                        // By default, the tooltip is not open.
                        // TODO add ability to start tooltip opened
                        ttScope.isOpen = false;

                        function toggleTooltipBind() {
                            if (!ttScope.isOpen) {
                                showTooltipBind();
                            } else {
                                hideTooltipBind();
                            }
                        }

                        // Show the tooltip with delay if specified, otherwise show it immediately
                        function showTooltipBind() {
                            if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
                                return;
                            }

                            cancelHide();
                            prepareTooltip();

                            if (ttScope.popupDelay) {
                                // Do nothing if the tooltip was already scheduled to pop-up.
                                // This happens if show is triggered multiple times before any hide is triggered.
                                if (!showTimeout) {
                                    showTimeout = $timeout(show, ttScope.popupDelay, false);
                                }
                            } else {
                                show();
                            }
                        }

                        function hideTooltipBind() {
                            cancelShow();

                            if (ttScope.popupCloseDelay) {
                                if (!hideTimeout) {
                                    hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
                                }
                            } else {
                                hide();
                            }
                        }

                        // Show the tooltip popup element.
                        function show() {
                            cancelShow();
                            cancelHide();

                            // Don't show empty tooltips.
                            if (!ttScope.content) {
                                return angular.noop;
                            }

                            createTooltip();

                            // And show the tooltip.
                            ttScope.$evalAsync(function () {
                                ttScope.isOpen = true;
                                assignIsOpen(true);
                                positionTooltip();
                            });
                        }

                        function cancelShow() {
                            if (showTimeout) {
                                $timeout.cancel(showTimeout);
                                showTimeout = null;
                            }

                            if (positionTimeout) {
                                $timeout.cancel(positionTimeout);
                                positionTimeout = null;
                            }
                        }

                        // Hide the tooltip popup element.
                        function hide() {
                            if (!ttScope) {
                                return;
                            }

                            // First things first: we don't show it anymore.
                            ttScope.$evalAsync(function () {
                                if (ttScope) {
                                    ttScope.isOpen = false;
                                    assignIsOpen(false);
                                    // And now we remove it from the DOM. However, if we have animation, we
                                    // need to wait for it to expire beforehand.
                                    // FIXME: this is a placeholder for a port of the transitions library.
                                    // The fade transition in TWBS is 150ms.
                                    if (ttScope.animation) {
                                        if (!transitionTimeout) {
                                            transitionTimeout = $timeout(removeTooltip, 150, false);
                                        }
                                    } else {
                                        removeTooltip();
                                    }
                                }
                            });
                        }

                        function cancelHide() {
                            if (hideTimeout) {
                                $timeout.cancel(hideTimeout);
                                hideTimeout = null;
                            }

                            if (transitionTimeout) {
                                $timeout.cancel(transitionTimeout);
                                transitionTimeout = null;
                            }
                        }

                        function createTooltip() {
                            // There can only be one tooltip element per directive shown at once.
                            if (tooltip) {
                                return;
                            }

                            tooltipLinkedScope = ttScope.$new();
                            tooltip = tooltipLinker(tooltipLinkedScope, function (tooltip) {
                                if (appendToBody) {
                                    $document.find('body').append(tooltip);
                                } else {
                                    element.after(tooltip);
                                }
                            });

                            openedTooltips.add(ttScope, {
                                close: hide
                            });

                            prepObservers();
                        }

                        function removeTooltip() {
                            cancelShow();
                            cancelHide();
                            unregisterObservers();

                            if (tooltip) {
                                tooltip.remove();

                                tooltip = null;
                                if (adjustmentTimeout) {
                                    $timeout.cancel(adjustmentTimeout);
                                }
                            }

                            openedTooltips.remove(ttScope);

                            if (tooltipLinkedScope) {
                                tooltipLinkedScope.$destroy();
                                tooltipLinkedScope = null;
                            }
                        }

                        /**
                         * Set the initial scope values. Once
                         * the tooltip is created, the observers
                         * will be added to keep things in sync.
                         */
                        function prepareTooltip() {
                            ttScope.title = attrs[prefix + 'Title'];
                            if (contentParse) {
                                ttScope.content = contentParse(scope);
                            } else {
                                ttScope.content = attrs[ttType];
                            }

                            ttScope.popupClass = attrs[prefix + 'Class'];
                            ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;
                            var placement = $position.parsePlacement(ttScope.placement);
                            lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];

                            var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);
                            var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);
                            ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;
                            ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;
                        }

                        function assignIsOpen(isOpen) {
                            if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
                                isOpenParse.assign(scope, isOpen);
                            }
                        }

                        ttScope.contentExp = function () {
                            return ttScope.content;
                        };

                        /**
                         * Observe the relevant attributes.
                         */
                        attrs.$observe('disabled', function (val) {
                            if (val) {
                                cancelShow();
                            }

                            if (val && ttScope.isOpen) {
                                hide();
                            }
                        });

                        if (isOpenParse) {
                            scope.$watch(isOpenParse, function (val) {
                                if (ttScope && !val === ttScope.isOpen) {
                                    toggleTooltipBind();
                                }
                            });
                        }

                        function prepObservers() {
                            observers.length = 0;

                            if (contentParse) {
                                observers.push(
                                  scope.$watch(contentParse, function (val) {
                                      ttScope.content = val;
                                      if (!val && ttScope.isOpen) {
                                          hide();
                                      }
                                  })
                                );

                                observers.push(
                                  tooltipLinkedScope.$watch(function () {
                                      if (!repositionScheduled) {
                                          repositionScheduled = true;
                                          tooltipLinkedScope.$$postDigest(function () {
                                              repositionScheduled = false;
                                              if (ttScope && ttScope.isOpen) {
                                                  positionTooltip();
                                              }
                                          });
                                      }
                                  })
                                );
                            } else {
                                observers.push(
                                  attrs.$observe(ttType, function (val) {
                                      ttScope.content = val;
                                      if (!val && ttScope.isOpen) {
                                          hide();
                                      } else {
                                          positionTooltip();
                                      }
                                  })
                                );
                            }

                            observers.push(
                              attrs.$observe(prefix + 'Title', function (val) {
                                  ttScope.title = val;
                                  if (ttScope.isOpen) {
                                      positionTooltip();
                                  }
                              })
                            );

                            observers.push(
                              attrs.$observe(prefix + 'Placement', function (val) {
                                  ttScope.placement = val ? val : options.placement;
                                  if (ttScope.isOpen) {
                                      positionTooltip();
                                  }
                              })
                            );
                        }

                        function unregisterObservers() {
                            if (observers.length) {
                                angular.forEach(observers, function (observer) {
                                    observer();
                                });
                                observers.length = 0;
                            }
                        }

                        // hide tooltips/popovers for outsideClick trigger
                        function bodyHideTooltipBind(e) {
                            if (!ttScope || !ttScope.isOpen || !tooltip) {
                                return;
                            }
                            // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked
                            if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {
                                hideTooltipBind();
                            }
                        }

                        var unregisterTriggers = function () {
                            triggers.show.forEach(function (trigger) {
                                if (trigger === 'outsideClick') {
                                    element.off('click', toggleTooltipBind);
                                } else {
                                    element.off(trigger, showTooltipBind);
                                    element.off(trigger, toggleTooltipBind);
                                }
                            });
                            triggers.hide.forEach(function (trigger) {
                                if (trigger === 'outsideClick') {
                                    $document.off('click', bodyHideTooltipBind);
                                } else {
                                    element.off(trigger, hideTooltipBind);
                                }
                            });
                        };

                        function prepTriggers() {
                            var showTriggers = [], hideTriggers = [];
                            var val = scope.$eval(attrs[prefix + 'Trigger']);
                            unregisterTriggers();

                            if (angular.isObject(val)) {
                                Object.keys(val).forEach(function (key) {
                                    showTriggers.push(key);
                                    hideTriggers.push(val[key]);
                                });
                                triggers = {
                                    show: showTriggers,
                                    hide: hideTriggers
                                };
                            } else {
                                triggers = getTriggers(val);
                            }

                            if (triggers.show !== 'none') {
                                triggers.show.forEach(function (trigger, idx) {
                                    if (trigger === 'outsideClick') {
                                        element.on('click', toggleTooltipBind);
                                        $document.on('click', bodyHideTooltipBind);
                                    } else if (trigger === triggers.hide[idx]) {
                                        element.on(trigger, toggleTooltipBind);
                                    } else if (trigger) {
                                        element.on(trigger, showTooltipBind);
                                        element.on(triggers.hide[idx], hideTooltipBind);
                                    }

                                    element.on('keypress', function (e) {
                                        if (e.which === 27) {
                                            hideTooltipBind();
                                        }
                                    });
                                });
                            }
                        }

                        prepTriggers();

                        var animation = scope.$eval(attrs[prefix + 'Animation']);
                        ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;

                        var appendToBodyVal;
                        var appendKey = prefix + 'AppendToBody';
                        if (appendKey in attrs && attrs[appendKey] === undefined) {
                            appendToBodyVal = true;
                        } else {
                            appendToBodyVal = scope.$eval(attrs[appendKey]);
                        }

                        appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;

                        // Make sure tooltip is destroyed and removed.
                        scope.$on('$destroy', function onDestroyTooltip() {
                            unregisterTriggers();
                            removeTooltip();
                            ttScope = null;
                        });
                    };
                }
            };
        };
    }];
})

// This is mostly ngInclude code but with a custom scope
.directive('uibTooltipTemplateTransclude', [
         '$animate', '$sce', '$compile', '$templateRequest',
function ($animate, $sce, $compile, $templateRequest) {
    return {
        link: function (scope, elem, attrs) {
            var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);

            var changeCounter = 0,
              currentScope,
              previousElement,
              currentElement;

            var cleanupLastIncludeContent = function () {
                if (previousElement) {
                    previousElement.remove();
                    previousElement = null;
                }

                if (currentScope) {
                    currentScope.$destroy();
                    currentScope = null;
                }

                if (currentElement) {
                    $animate.leave(currentElement).then(function () {
                        previousElement = null;
                    });
                    previousElement = currentElement;
                    currentElement = null;
                }
            };

            scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function (src) {
                var thisChangeId = ++changeCounter;

                if (src) {
                    //set the 2nd param to true to ignore the template request error so that the inner
                    //contents and scope can be cleaned up.
                    $templateRequest(src, true).then(function (response) {
                        if (thisChangeId !== changeCounter) { return; }
                        var newScope = origScope.$new();
                        var template = response;

                        var clone = $compile(template)(newScope, function (clone) {
                            cleanupLastIncludeContent();
                            $animate.enter(clone, elem);
                        });

                        currentScope = newScope;
                        currentElement = clone;

                        currentScope.$emit('$includeContentLoaded', src);
                    }, function () {
                        if (thisChangeId === changeCounter) {
                            cleanupLastIncludeContent();
                            scope.$emit('$includeContentError', src);
                        }
                    });
                    scope.$emit('$includeContentRequested', src);
                } else {
                    cleanupLastIncludeContent();
                }
            });

            scope.$on('$destroy', cleanupLastIncludeContent);
        }
    };
}])

/**
 * Note that it's intentional that these classes are *not* applied through $animate.
 * They must not be animated as they're expected to be present on the tooltip on
 * initialization.
 */
.directive('uibTooltipClasses', ['$uibPosition', function ($uibPosition) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            // need to set the primary position so the
            // arrow has space during position measure.
            // tooltip.positionTooltip()
            if (scope.placement) {
                // // There are no top-left etc... classes
                // // in TWBS, so we need the primary position.
                var position = $uibPosition.parsePlacement(scope.placement);
                element.addClass(position[0]);
            }

            if (scope.popupClass) {
                element.addClass(scope.popupClass);
            }

            if (scope.animation) {
                element.addClass(attrs.tooltipAnimationClass);
            }
        }
    };
}])

.directive('uibTooltipPopup', function () {
    return {
        restrict: 'A',
        scope: { content: '@' },
        templateUrl: 'uib/template/tooltip/tooltip-popup.html'
    };
})

.directive('uibTooltip', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');
}])

.directive('uibTooltipTemplatePopup', function () {
    return {
        restrict: 'A',
        scope: { contentExp: '&', originScope: '&' },
        templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'
    };
})

.directive('uibTooltipTemplate', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {
        useContentExp: true
    });
}])

.directive('uibTooltipHtmlPopup', function () {
    return {
        restrict: 'A',
        scope: { contentExp: '&' },
        templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'
    };
})

.directive('uibTooltipHtml', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {
        useContentExp: true
    });
}]);

/**
 * The following features are still outstanding: popup delay, animation as a
 * function, placement as a function, inside, support for more triggers than
 * just mouse enter/leave, and selector delegatation.
 */
angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])

.directive('uibPopoverTemplatePopup', function () {
    return {
        restrict: 'A',
        scope: { uibTitle: '@', contentExp: '&', originScope: '&' },
        templateUrl: 'uib/template/popover/popover-template.html'
    };
})

.directive('uibPopoverTemplate', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {
        useContentExp: true
    });
}])

.directive('uibPopoverHtmlPopup', function () {
    return {
        restrict: 'A',
        scope: { contentExp: '&', uibTitle: '@' },
        templateUrl: 'uib/template/popover/popover-html.html'
    };
})

.directive('uibPopoverHtml', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibPopoverHtml', 'popover', 'click', {
        useContentExp: true
    });
}])

.directive('uibPopoverPopup', function () {
    return {
        restrict: 'A',
        scope: { uibTitle: '@', content: '@' },
        templateUrl: 'uib/template/popover/popover.html'
    };
})

.directive('uibPopover', ['$uibTooltip', function ($uibTooltip) {
    return $uibTooltip('uibPopover', 'popover', 'click');
}]);

angular.module('ui.bootstrap.progressbar', [])

.constant('uibProgressConfig', {
    animate: true,
    max: 100
})

.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function ($scope, $attrs, progressConfig) {
    var self = this,
        animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;

    this.bars = [];
    $scope.max = getMaxOrDefault();

    this.addBar = function (bar, element, attrs) {
        if (!animate) {
            element.css({ 'transition': 'none' });
        }

        this.bars.push(bar);

        bar.max = getMaxOrDefault();
        bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';

        bar.$watch('value', function (value) {
            bar.recalculatePercentage();
        });

        bar.recalculatePercentage = function () {
            var totalPercentage = self.bars.reduce(function (total, bar) {
                bar.percent = +(100 * bar.value / bar.max).toFixed(2);
                return total + bar.percent;
            }, 0);

            if (totalPercentage > 100) {
                bar.percent -= totalPercentage - 100;
            }
        };

        bar.$on('$destroy', function () {
            element = null;
            self.removeBar(bar);
        });
    };

    this.removeBar = function (bar) {
        this.bars.splice(this.bars.indexOf(bar), 1);
        this.bars.forEach(function (bar) {
            bar.recalculatePercentage();
        });
    };

    //$attrs.$observe('maxParam', function(maxParam) {
    $scope.$watch('maxParam', function (maxParam) {
        self.bars.forEach(function (bar) {
            bar.max = getMaxOrDefault();
            bar.recalculatePercentage();
        });
    });

    function getMaxOrDefault() {
        return angular.isDefined($scope.maxParam) ? $scope.maxParam : progressConfig.max;
    }
}])

.directive('uibProgress', function () {
    return {
        replace: true,
        transclude: true,
        controller: 'UibProgressController',
        require: 'uibProgress',
        scope: {
            maxParam: '=?max'
        },
        templateUrl: 'uib/template/progressbar/progress.html'
    };
})

.directive('uibBar', function () {
    return {
        replace: true,
        transclude: true,
        require: '^uibProgress',
        scope: {
            value: '=',
            type: '@'
        },
        templateUrl: 'uib/template/progressbar/bar.html',
        link: function (scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, element, attrs);
        }
    };
})

.directive('uibProgressbar', function () {
    return {
        replace: true,
        transclude: true,
        controller: 'UibProgressController',
        scope: {
            value: '=',
            maxParam: '=?max',
            type: '@'
        },
        templateUrl: 'uib/template/progressbar/progressbar.html',
        link: function (scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, angular.element(element.children()[0]), { title: attrs.title });
        }
    };
});

angular.module('ui.bootstrap.rating', [])

.constant('uibRatingConfig', {
    max: 5,
    stateOn: null,
    stateOff: null,
    enableReset: true,
    titles: ['one', 'two', 'three', 'four', 'five']
})

.controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function ($scope, $attrs, ratingConfig) {
    var ngModelCtrl = { $setViewValue: angular.noop },
      self = this;

    this.init = function (ngModelCtrl_) {
        ngModelCtrl = ngModelCtrl_;
        ngModelCtrl.$render = this.render;

        ngModelCtrl.$formatters.push(function (value) {
            if (angular.isNumber(value) && value << 0 !== value) {
                value = Math.round(value);
            }

            return value;
        });

        this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
        this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;
        this.enableReset = angular.isDefined($attrs.enableReset) ?
          $scope.$parent.$eval($attrs.enableReset) : ratingConfig.enableReset;
        var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles;
        this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?
            tmpTitles : ratingConfig.titles;

        var ratingStates = angular.isDefined($attrs.ratingStates) ?
          $scope.$parent.$eval($attrs.ratingStates) :
          new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max);
        $scope.range = this.buildTemplateObjects(ratingStates);
    };

    this.buildTemplateObjects = function (states) {
        for (var i = 0, n = states.length; i < n; i++) {
            states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);
        }
        return states;
    };

    this.getTitle = function (index) {
        if (index >= this.titles.length) {
            return index + 1;
        }

        return this.titles[index];
    };

    $scope.rate = function (value) {
        if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {
            var newViewValue = self.enableReset && ngModelCtrl.$viewValue === value ? 0 : value;
            ngModelCtrl.$setViewValue(newViewValue);
            ngModelCtrl.$render();
        }
    };

    $scope.enter = function (value) {
        if (!$scope.readonly) {
            $scope.value = value;
        }
        $scope.onHover({ value: value });
    };

    $scope.reset = function () {
        $scope.value = ngModelCtrl.$viewValue;
        $scope.onLeave();
    };

    $scope.onKeydown = function (evt) {
        if (/(37|38|39|40)/.test(evt.which)) {
            evt.preventDefault();
            evt.stopPropagation();
            $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));
        }
    };

    this.render = function () {
        $scope.value = ngModelCtrl.$viewValue;
        $scope.title = self.getTitle($scope.value - 1);
    };
}])

.directive('uibRating', function () {
    return {
        require: ['uibRating', 'ngModel'],
        restrict: 'A',
        scope: {
            readonly: '=?readOnly',
            onHover: '&',
            onLeave: '&'
        },
        controller: 'UibRatingController',
        templateUrl: 'uib/template/rating/rating.html',
        link: function (scope, element, attrs, ctrls) {
            var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
            ratingCtrl.init(ngModelCtrl);
        }
    };
});

angular.module('ui.bootstrap.tabs', [])

.controller('UibTabsetController', ['$scope', function ($scope) {
    var ctrl = this,
      oldIndex;
    ctrl.tabs = [];

    ctrl.select = function (index, evt) {
        if (!destroyed) {
            var previousIndex = findTabIndex(oldIndex);
            var previousSelected = ctrl.tabs[previousIndex];
            if (previousSelected) {
                previousSelected.tab.onDeselect({
                    $event: evt,
                    $selectedIndex: index
                });
                if (evt && evt.isDefaultPrevented()) {
                    return;
                }
                previousSelected.tab.active = false;
            }

            var selected = ctrl.tabs[index];
            if (selected) {
                selected.tab.onSelect({
                    $event: evt
                });
                selected.tab.active = true;
                ctrl.active = selected.index;
                oldIndex = selected.index;
            } else if (!selected && angular.isDefined(oldIndex)) {
                ctrl.active = null;
                oldIndex = null;
            }
        }
    };

    ctrl.addTab = function addTab(tab) {
        ctrl.tabs.push({
            tab: tab,
            index: tab.index
        });
        ctrl.tabs.sort(function (t1, t2) {
            if (t1.index > t2.index) {
                return 1;
            }

            if (t1.index < t2.index) {
                return -1;
            }

            return 0;
        });

        if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
            var newActiveIndex = findTabIndex(tab.index);
            ctrl.select(newActiveIndex);
        }
    };

    ctrl.removeTab = function removeTab(tab) {
        var index;
        for (var i = 0; i < ctrl.tabs.length; i++) {
            if (ctrl.tabs[i].tab === tab) {
                index = i;
                break;
            }
        }

        if (ctrl.tabs[index].index === ctrl.active) {
            var newActiveTabIndex = index === ctrl.tabs.length - 1 ?
              index - 1 : index + 1 % ctrl.tabs.length;
            ctrl.select(newActiveTabIndex);
        }

        ctrl.tabs.splice(index, 1);
    };

    $scope.$watch('tabset.active', function (val) {
        if (angular.isDefined(val) && val !== oldIndex) {
            ctrl.select(findTabIndex(val));
        }
    });

    var destroyed;
    $scope.$on('$destroy', function () {
        destroyed = true;
    });

    function findTabIndex(index) {
        for (var i = 0; i < ctrl.tabs.length; i++) {
            if (ctrl.tabs[i].index === index) {
                return i;
            }
        }
    }
}])

.directive('uibTabset', function () {
    return {
        transclude: true,
        replace: true,
        scope: {},
        bindToController: {
            active: '=?',
            type: '@'
        },
        controller: 'UibTabsetController',
        controllerAs: 'tabset',
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/tabs/tabset.html';
        },
        link: function (scope, element, attrs) {
            scope.vertical = angular.isDefined(attrs.vertical) ?
              scope.$parent.$eval(attrs.vertical) : false;
            scope.justified = angular.isDefined(attrs.justified) ?
              scope.$parent.$eval(attrs.justified) : false;
        }
    };
})

.directive('uibTab', ['$parse', function ($parse) {
    return {
        require: '^uibTabset',
        replace: true,
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || 'uib/template/tabs/tab.html';
        },
        transclude: true,
        scope: {
            heading: '@',
            index: '=?',
            classes: '@?',
            onSelect: '&select', //This callback is called in contentHeadingTransclude
            //once it inserts the tab's content into the dom
            onDeselect: '&deselect'
        },
        controller: function () {
            //Empty controller so other directives can require being 'under' a tab
        },
        controllerAs: 'tab',
        link: function (scope, elm, attrs, tabsetCtrl, transclude) {
            scope.disabled = false;
            if (attrs.disable) {
                scope.$parent.$watch($parse(attrs.disable), function (value) {
                    scope.disabled = !!value;
                });
            }

            if (angular.isUndefined(attrs.index)) {
                if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {
                    scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function (t) { return t.index; })) + 1;
                } else {
                    scope.index = 0;
                }
            }

            if (angular.isUndefined(attrs.classes)) {
                scope.classes = '';
            }

            scope.select = function (evt) {
                if (!scope.disabled) {
                    var index;
                    for (var i = 0; i < tabsetCtrl.tabs.length; i++) {
                        if (tabsetCtrl.tabs[i].tab === scope) {
                            index = i;
                            break;
                        }
                    }

                    tabsetCtrl.select(index, evt);
                }
            };

            tabsetCtrl.addTab(scope);
            scope.$on('$destroy', function () {
                tabsetCtrl.removeTab(scope);
            });

            //We need to transclude later, once the content container is ready.
            //when this link happens, we're inside a tab heading.
            scope.$transcludeFn = transclude;
        }
    };
}])

.directive('uibTabHeadingTransclude', function () {
    return {
        restrict: 'A',
        require: '^uibTab',
        link: function (scope, elm) {
            scope.$watch('headingElement', function updateHeadingElement(heading) {
                if (heading) {
                    elm.html('');
                    elm.append(heading);
                }
            });
        }
    };
})

.directive('uibTabContentTransclude', function () {
    return {
        restrict: 'A',
        require: '^uibTabset',
        link: function (scope, elm, attrs) {
            var tab = scope.$eval(attrs.uibTabContentTransclude).tab;

            //Now our tab is ready to be transcluded: both the tab heading area
            //and the tab content area are loaded.  Transclude 'em both.
            tab.$transcludeFn(tab.$parent, function (contents) {
                angular.forEach(contents, function (node) {
                    if (isTabHeading(node)) {
                        //Let tabHeadingTransclude know.
                        tab.headingElement = node;
                    } else {
                        elm.append(node);
                    }
                });
            });
        }
    };

    function isTabHeading(node) {
        return node.tagName && (
          node.hasAttribute('uib-tab-heading') ||
          node.hasAttribute('data-uib-tab-heading') ||
          node.hasAttribute('x-uib-tab-heading') ||
          node.tagName.toLowerCase() === 'uib-tab-heading' ||
          node.tagName.toLowerCase() === 'data-uib-tab-heading' ||
          node.tagName.toLowerCase() === 'x-uib-tab-heading' ||
          node.tagName.toLowerCase() === 'uib:tab-heading'
        );
    }
});

angular.module('ui.bootstrap.timepicker', [])

.constant('uibTimepickerConfig', {
    hourStep: 1,
    minuteStep: 1,
    secondStep: 1,
    showMeridian: true,
    showSeconds: false,
    meridians: null,
    readonlyInput: false,
    mousewheel: true,
    arrowkeys: true,
    showSpinners: true,
    templateUrl: 'uib/template/timepicker/timepicker.html'
})

.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function ($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
    var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl;
    var selected = new Date(),
      watchers = [],
      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
      meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS,
      padHours = angular.isDefined($attrs.padHours) ? $scope.$parent.$eval($attrs.padHours) : true;

    $scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;
    $element.removeAttr('tabindex');

    this.init = function (ngModelCtrl_, inputs) {
        ngModelCtrl = ngModelCtrl_;
        ngModelCtrl.$render = this.render;

        ngModelCtrl.$formatters.unshift(function (modelValue) {
            return modelValue ? new Date(modelValue) : null;
        });

        var hoursInputEl = inputs.eq(0),
            minutesInputEl = inputs.eq(1),
            secondsInputEl = inputs.eq(2);

        hoursModelCtrl = hoursInputEl.controller('ngModel');
        minutesModelCtrl = minutesInputEl.controller('ngModel');
        secondsModelCtrl = secondsInputEl.controller('ngModel');

        var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;

        if (mousewheel) {
            this.setupMousewheelEvents(hoursInputEl, minutesInputEl, secondsInputEl);
        }

        var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;
        if (arrowkeys) {
            this.setupArrowkeyEvents(hoursInputEl, minutesInputEl, secondsInputEl);
        }

        $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
        this.setupInputEvents(hoursInputEl, minutesInputEl, secondsInputEl);
    };

    var hourStep = timepickerConfig.hourStep;
    if ($attrs.hourStep) {
        watchers.push($scope.$parent.$watch($parse($attrs.hourStep), function (value) {
            hourStep = +value;
        }));
    }

    var minuteStep = timepickerConfig.minuteStep;
    if ($attrs.minuteStep) {
        watchers.push($scope.$parent.$watch($parse($attrs.minuteStep), function (value) {
            minuteStep = +value;
        }));
    }

    var min;
    watchers.push($scope.$parent.$watch($parse($attrs.min), function (value) {
        var dt = new Date(value);
        min = isNaN(dt) ? undefined : dt;
    }));

    var max;
    watchers.push($scope.$parent.$watch($parse($attrs.max), function (value) {
        var dt = new Date(value);
        max = isNaN(dt) ? undefined : dt;
    }));

    var disabled = false;
    if ($attrs.ngDisabled) {
        watchers.push($scope.$parent.$watch($parse($attrs.ngDisabled), function (value) {
            disabled = value;
        }));
    }

    $scope.noIncrementHours = function () {
        var incrementedSelected = addMinutes(selected, hourStep * 60);
        return disabled || incrementedSelected > max ||
          incrementedSelected < selected && incrementedSelected < min;
    };

    $scope.noDecrementHours = function () {
        var decrementedSelected = addMinutes(selected, -hourStep * 60);
        return disabled || decrementedSelected < min ||
          decrementedSelected > selected && decrementedSelected > max;
    };

    $scope.noIncrementMinutes = function () {
        var incrementedSelected = addMinutes(selected, minuteStep);
        return disabled || incrementedSelected > max ||
          incrementedSelected < selected && incrementedSelected < min;
    };

    $scope.noDecrementMinutes = function () {
        var decrementedSelected = addMinutes(selected, -minuteStep);
        return disabled || decrementedSelected < min ||
          decrementedSelected > selected && decrementedSelected > max;
    };

    $scope.noIncrementSeconds = function () {
        var incrementedSelected = addSeconds(selected, secondStep);
        return disabled || incrementedSelected > max ||
          incrementedSelected < selected && incrementedSelected < min;
    };

    $scope.noDecrementSeconds = function () {
        var decrementedSelected = addSeconds(selected, -secondStep);
        return disabled || decrementedSelected < min ||
          decrementedSelected > selected && decrementedSelected > max;
    };

    $scope.noToggleMeridian = function () {
        if (selected.getHours() < 12) {
            return disabled || addMinutes(selected, 12 * 60) > max;
        }

        return disabled || addMinutes(selected, -12 * 60) < min;
    };

    var secondStep = timepickerConfig.secondStep;
    if ($attrs.secondStep) {
        watchers.push($scope.$parent.$watch($parse($attrs.secondStep), function (value) {
            secondStep = +value;
        }));
    }

    $scope.showSeconds = timepickerConfig.showSeconds;
    if ($attrs.showSeconds) {
        watchers.push($scope.$parent.$watch($parse($attrs.showSeconds), function (value) {
            $scope.showSeconds = !!value;
        }));
    }

    // 12H / 24H mode
    $scope.showMeridian = timepickerConfig.showMeridian;
    if ($attrs.showMeridian) {
        watchers.push($scope.$parent.$watch($parse($attrs.showMeridian), function (value) {
            $scope.showMeridian = !!value;

            if (ngModelCtrl.$error.time) {
                // Evaluate from template
                var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
                if (angular.isDefined(hours) && angular.isDefined(minutes)) {
                    selected.setHours(hours);
                    refresh();
                }
            } else {
                updateTemplate();
            }
        }));
    }

    // Get $scope.hours in 24H mode if valid
    function getHoursFromTemplate() {
        var hours = +$scope.hours;
        var valid = $scope.showMeridian ? hours > 0 && hours < 13 :
          hours >= 0 && hours < 24;
        if (!valid || $scope.hours === '') {
            return undefined;
        }

        if ($scope.showMeridian) {
            if (hours === 12) {
                hours = 0;
            }
            if ($scope.meridian === meridians[1]) {
                hours = hours + 12;
            }
        }
        return hours;
    }

    function getMinutesFromTemplate() {
        var minutes = +$scope.minutes;
        var valid = minutes >= 0 && minutes < 60;
        if (!valid || $scope.minutes === '') {
            return undefined;
        }
        return minutes;
    }

    function getSecondsFromTemplate() {
        var seconds = +$scope.seconds;
        return seconds >= 0 && seconds < 60 ? seconds : undefined;
    }

    function pad(value, noPad) {
        if (value === null) {
            return '';
        }

        return angular.isDefined(value) && value.toString().length < 2 && !noPad ?
          '0' + value : value.toString();
    }

    // Respond on mousewheel spin
    this.setupMousewheelEvents = function (hoursInputEl, minutesInputEl, secondsInputEl) {
        var isScrollingUp = function (e) {
            if (e.originalEvent) {
                e = e.originalEvent;
            }
            //pick correct delta variable depending on event
            var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY;
            return e.detail || delta > 0;
        };

        hoursInputEl.bind('mousewheel wheel', function (e) {
            if (!disabled) {
                $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
            }
            e.preventDefault();
        });

        minutesInputEl.bind('mousewheel wheel', function (e) {
            if (!disabled) {
                $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
            }
            e.preventDefault();
        });

        secondsInputEl.bind('mousewheel wheel', function (e) {
            if (!disabled) {
                $scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds());
            }
            e.preventDefault();
        });
    };

    // Respond on up/down arrowkeys
    this.setupArrowkeyEvents = function (hoursInputEl, minutesInputEl, secondsInputEl) {
        hoursInputEl.bind('keydown', function (e) {
            if (!disabled) {
                if (e.which === 38) { // up
                    e.preventDefault();
                    $scope.incrementHours();
                    $scope.$apply();
                } else if (e.which === 40) { // down
                    e.preventDefault();
                    $scope.decrementHours();
                    $scope.$apply();
                }
            }
        });

        minutesInputEl.bind('keydown', function (e) {
            if (!disabled) {
                if (e.which === 38) { // up
                    e.preventDefault();
                    $scope.incrementMinutes();
                    $scope.$apply();
                } else if (e.which === 40) { // down
                    e.preventDefault();
                    $scope.decrementMinutes();
                    $scope.$apply();
                }
            }
        });

        secondsInputEl.bind('keydown', function (e) {
            if (!disabled) {
                if (e.which === 38) { // up
                    e.preventDefault();
                    $scope.incrementSeconds();
                    $scope.$apply();
                } else if (e.which === 40) { // down
                    e.preventDefault();
                    $scope.decrementSeconds();
                    $scope.$apply();
                }
            }
        });
    };

    this.setupInputEvents = function (hoursInputEl, minutesInputEl, secondsInputEl) {
        if ($scope.readonlyInput) {
            $scope.updateHours = angular.noop;
            $scope.updateMinutes = angular.noop;
            $scope.updateSeconds = angular.noop;
            return;
        }

        var invalidate = function (invalidHours, invalidMinutes, invalidSeconds) {
            ngModelCtrl.$setViewValue(null);
            ngModelCtrl.$setValidity('time', false);
            if (angular.isDefined(invalidHours)) {
                $scope.invalidHours = invalidHours;
                if (hoursModelCtrl) {
                    hoursModelCtrl.$setValidity('hours', false);
                }
            }

            if (angular.isDefined(invalidMinutes)) {
                $scope.invalidMinutes = invalidMinutes;
                if (minutesModelCtrl) {
                    minutesModelCtrl.$setValidity('minutes', false);
                }
            }

            if (angular.isDefined(invalidSeconds)) {
                $scope.invalidSeconds = invalidSeconds;
                if (secondsModelCtrl) {
                    secondsModelCtrl.$setValidity('seconds', false);
                }
            }
        };

        $scope.updateHours = function () {
            var hours = getHoursFromTemplate(),
              minutes = getMinutesFromTemplate();

            ngModelCtrl.$setDirty();

            if (angular.isDefined(hours) && angular.isDefined(minutes)) {
                selected.setHours(hours);
                selected.setMinutes(minutes);
                if (selected < min || selected > max) {
                    invalidate(true);
                } else {
                    refresh('h');
                }
            } else {
                invalidate(true);
            }
        };

        hoursInputEl.bind('blur', function (e) {
            ngModelCtrl.$setTouched();
            if (modelIsEmpty()) {
                makeValid();
            } else if ($scope.hours === null || $scope.hours === '') {
                invalidate(true);
            } else if (!$scope.invalidHours && $scope.hours < 10) {
                $scope.$apply(function () {
                    $scope.hours = pad($scope.hours, !padHours);
                });
            }
        });

        $scope.updateMinutes = function () {
            var minutes = getMinutesFromTemplate(),
              hours = getHoursFromTemplate();

            ngModelCtrl.$setDirty();

            if (angular.isDefined(minutes) && angular.isDefined(hours)) {
                selected.setHours(hours);
                selected.setMinutes(minutes);
                if (selected < min || selected > max) {
                    invalidate(undefined, true);
                } else {
                    refresh('m');
                }
            } else {
                invalidate(undefined, true);
            }
        };

        minutesInputEl.bind('blur', function (e) {
            ngModelCtrl.$setTouched();
            if (modelIsEmpty()) {
                makeValid();
            } else if ($scope.minutes === null) {
                invalidate(undefined, true);
            } else if (!$scope.invalidMinutes && $scope.minutes < 10) {
                $scope.$apply(function () {
                    $scope.minutes = pad($scope.minutes);
                });
            }
        });

        $scope.updateSeconds = function () {
            var seconds = getSecondsFromTemplate();

            ngModelCtrl.$setDirty();

            if (angular.isDefined(seconds)) {
                selected.setSeconds(seconds);
                refresh('s');
            } else {
                invalidate(undefined, undefined, true);
            }
        };

        secondsInputEl.bind('blur', function (e) {
            if (modelIsEmpty()) {
                makeValid();
            } else if (!$scope.invalidSeconds && $scope.seconds < 10) {
                $scope.$apply(function () {
                    $scope.seconds = pad($scope.seconds);
                });
            }
        });

    };

    this.render = function () {
        var date = ngModelCtrl.$viewValue;

        if (isNaN(date)) {
            ngModelCtrl.$setValidity('time', false);
            $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
        } else {
            if (date) {
                selected = date;
            }

            if (selected < min || selected > max) {
                ngModelCtrl.$setValidity('time', false);
                $scope.invalidHours = true;
                $scope.invalidMinutes = true;
            } else {
                makeValid();
            }
            updateTemplate();
        }
    };

    // Call internally when we know that model is valid.
    function refresh(keyboardChange) {
        makeValid();
        ngModelCtrl.$setViewValue(new Date(selected));
        updateTemplate(keyboardChange);
    }

    function makeValid() {
        if (hoursModelCtrl) {
            hoursModelCtrl.$setValidity('hours', true);
        }

        if (minutesModelCtrl) {
            minutesModelCtrl.$setValidity('minutes', true);
        }

        if (secondsModelCtrl) {
            secondsModelCtrl.$setValidity('seconds', true);
        }

        ngModelCtrl.$setValidity('time', true);
        $scope.invalidHours = false;
        $scope.invalidMinutes = false;
        $scope.invalidSeconds = false;
    }

    function updateTemplate(keyboardChange) {
        if (!ngModelCtrl.$modelValue) {
            $scope.hours = null;
            $scope.minutes = null;
            $scope.seconds = null;
            $scope.meridian = meridians[0];
        } else {
            var hours = selected.getHours(),
              minutes = selected.getMinutes(),
              seconds = selected.getSeconds();

            if ($scope.showMeridian) {
                hours = hours === 0 || hours === 12 ? 12 : hours % 12; // Convert 24 to 12 hour system
            }

            $scope.hours = keyboardChange === 'h' ? hours : pad(hours, !padHours);
            if (keyboardChange !== 'm') {
                $scope.minutes = pad(minutes);
            }
            $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];

            if (keyboardChange !== 's') {
                $scope.seconds = pad(seconds);
            }
            $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
        }
    }

    function addSecondsToSelected(seconds) {
        selected = addSeconds(selected, seconds);
        refresh();
    }

    function addMinutes(selected, minutes) {
        return addSeconds(selected, minutes * 60);
    }

    function addSeconds(date, seconds) {
        var dt = new Date(date.getTime() + seconds * 1000);
        var newDate = new Date(date);
        newDate.setHours(dt.getHours(), dt.getMinutes(), dt.getSeconds());
        return newDate;
    }

    function modelIsEmpty() {
        return ($scope.hours === null || $scope.hours === '') &&
          ($scope.minutes === null || $scope.minutes === '') &&
          (!$scope.showSeconds || $scope.showSeconds && ($scope.seconds === null || $scope.seconds === ''));
    }

    $scope.showSpinners = angular.isDefined($attrs.showSpinners) ?
      $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;

    $scope.incrementHours = function () {
        if (!$scope.noIncrementHours()) {
            addSecondsToSelected(hourStep * 60 * 60);
        }
    };

    $scope.decrementHours = function () {
        if (!$scope.noDecrementHours()) {
            addSecondsToSelected(-hourStep * 60 * 60);
        }
    };

    $scope.incrementMinutes = function () {
        if (!$scope.noIncrementMinutes()) {
            addSecondsToSelected(minuteStep * 60);
        }
    };

    $scope.decrementMinutes = function () {
        if (!$scope.noDecrementMinutes()) {
            addSecondsToSelected(-minuteStep * 60);
        }
    };

    $scope.incrementSeconds = function () {
        if (!$scope.noIncrementSeconds()) {
            addSecondsToSelected(secondStep);
        }
    };

    $scope.decrementSeconds = function () {
        if (!$scope.noDecrementSeconds()) {
            addSecondsToSelected(-secondStep);
        }
    };

    $scope.toggleMeridian = function () {
        var minutes = getMinutesFromTemplate(),
            hours = getHoursFromTemplate();

        if (!$scope.noToggleMeridian()) {
            if (angular.isDefined(minutes) && angular.isDefined(hours)) {
                addSecondsToSelected(12 * 60 * (selected.getHours() < 12 ? 60 : -60));
            } else {
                $scope.meridian = $scope.meridian === meridians[0] ? meridians[1] : meridians[0];
            }
        }
    };

    $scope.blur = function () {
        ngModelCtrl.$setTouched();
    };

    $scope.$on('$destroy', function () {
        while (watchers.length) {
            watchers.shift()();
        }
    });
}])

.directive('uibTimepicker', ['uibTimepickerConfig', function (uibTimepickerConfig) {
    return {
        require: ['uibTimepicker', '?^ngModel'],
        restrict: 'A',
        controller: 'UibTimepickerController',
        controllerAs: 'timepicker',
        scope: {},
        templateUrl: function (element, attrs) {
            return attrs.templateUrl || uibTimepickerConfig.templateUrl;
        },
        link: function (scope, element, attrs, ctrls) {
            var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];

            if (ngModelCtrl) {
                timepickerCtrl.init(ngModelCtrl, element.find('input'));
            }
        }
    };
}]);

angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap.position'])

/**
 * A helper service that can parse typeahead's syntax (string provided by users)
 * Extracted to a separate service for ease of unit testing
 */
  .factory('uibTypeaheadParser', ['$parse', function ($parse) {
      //                      000001111111100000000000002222222200000000000000003333333333333330000000000044444444000
      var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
      return {
          parse: function (input) {
              var match = input.match(TYPEAHEAD_REGEXP);
              if (!match) {
                  throw new Error(
                    'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' +
                      ' but got "' + input + '".');
              }

              return {
                  itemName: match[3],
                  source: $parse(match[4]),
                  viewMapper: $parse(match[2] || match[1]),
                  modelMapper: $parse(match[1])
              };
          }
      };
  }])

  .controller('UibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$$debounce', '$uibPosition', 'uibTypeaheadParser',
    function (originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $$debounce, $position, typeaheadParser) {
        var HOT_KEYS = [9, 13, 27, 38, 40];
        var eventDebounceTime = 200;
        var modelCtrl, ngModelOptions;
        //SUPPORTED ATTRIBUTES (OPTIONS)

        //minimal no of characters that needs to be entered before typeahead kicks-in
        var minLength = originalScope.$eval(attrs.typeaheadMinLength);
        if (!minLength && minLength !== 0) {
            minLength = 1;
        }

        originalScope.$watch(attrs.typeaheadMinLength, function (newVal) {
            minLength = !newVal && newVal !== 0 ? 1 : newVal;
        });

        //minimal wait time after last character typed before typeahead kicks-in
        var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;

        //should it restrict model values to the ones selected from the popup only?
        var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
        originalScope.$watch(attrs.typeaheadEditable, function (newVal) {
            isEditable = newVal !== false;
        });

        //binding to a variable that indicates if matches are being retrieved asynchronously
        var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;

        //a function to determine if an event should cause selection
        var isSelectEvent = attrs.typeaheadShouldSelect ? $parse(attrs.typeaheadShouldSelect) : function (scope, vals) {
            var evt = vals.$event;
            return evt.which === 13 || evt.which === 9;
        };

        //a callback executed when a match is selected
        var onSelectCallback = $parse(attrs.typeaheadOnSelect);

        //should it select highlighted popup value when losing focus?
        var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;

        //binding to a variable that indicates if there were no results after the query is completed
        var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;

        var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;

        var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;

        var appendTo = attrs.typeaheadAppendTo ?
          originalScope.$eval(attrs.typeaheadAppendTo) : null;

        var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;

        //If input matches an item of the list exactly, select it automatically
        var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;

        //binding to a variable that indicates if dropdown is open
        var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;

        var showHint = originalScope.$eval(attrs.typeaheadShowHint) || false;

        //INTERNAL VARIABLES

        //model setter executed upon match selection
        var parsedModel = $parse(attrs.ngModel);
        var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');
        var $setModelValue = function (scope, newValue) {
            if (angular.isFunction(parsedModel(originalScope)) &&
              ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) {
                return invokeModelSetter(scope, { $$$p: newValue });
            }

            return parsedModel.assign(scope, newValue);
        };

        //expressions used by typeahead
        var parserResult = typeaheadParser.parse(attrs.uibTypeahead);

        var hasFocus;

        //Used to avoid bug in iOS webview where iOS keyboard does not fire
        //mousedown & mouseup events
        //Issue #3699
        var selected;

        //create a child scope for the typeahead directive so we are not polluting original scope
        //with typeahead-specific data (matches, query etc.)
        var scope = originalScope.$new();
        var offDestroy = originalScope.$on('$destroy', function () {
            scope.$destroy();
        });
        scope.$on('$destroy', offDestroy);

        // WAI-ARIA
        var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
        element.attr({
            'aria-autocomplete': 'list',
            'aria-expanded': false,
            'aria-owns': popupId
        });

        var inputsContainer, hintInputElem;
        //add read-only input to show hint
        if (showHint) {
            inputsContainer = angular.element('<div></div>');
            inputsContainer.css('position', 'relative');
            element.after(inputsContainer);
            hintInputElem = element.clone();
            hintInputElem.attr('placeholder', '');
            hintInputElem.attr('tabindex', '-1');
            hintInputElem.val('');
            hintInputElem.css({
                'position': 'absolute',
                'top': '0px',
                'left': '0px',
                'border-color': 'transparent',
                'box-shadow': 'none',
                'opacity': 1,
                'background': 'none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)',
                'color': '#999'
            });
            element.css({
                'position': 'relative',
                'vertical-align': 'top',
                'background-color': 'transparent'
            });

            if (hintInputElem.attr('id')) {
                hintInputElem.removeAttr('id'); // remove duplicate id if present.
            }
            inputsContainer.append(hintInputElem);
            hintInputElem.after(element);
        }

        //pop-up element used to display matches
        var popUpEl = angular.element('<div uib-typeahead-popup></div>');
        popUpEl.attr({
            id: popupId,
            matches: 'matches',
            active: 'activeIdx',
            select: 'select(activeIdx, evt)',
            'move-in-progress': 'moveInProgress',
            query: 'query',
            position: 'position',
            'assign-is-open': 'assignIsOpen(isOpen)',
            debounce: 'debounceUpdate'
        });
        //custom item template
        if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
            popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
        }

        if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {
            popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);
        }

        var resetHint = function () {
            if (showHint) {
                hintInputElem.val('');
            }
        };

        var resetMatches = function () {
            scope.matches = [];
            scope.activeIdx = -1;
            element.attr('aria-expanded', false);
            resetHint();
        };

        var getMatchId = function (index) {
            return popupId + '-option-' + index;
        };

        // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.
        // This attribute is added or removed automatically when the `activeIdx` changes.
        scope.$watch('activeIdx', function (index) {
            if (index < 0) {
                element.removeAttr('aria-activedescendant');
            } else {
                element.attr('aria-activedescendant', getMatchId(index));
            }
        });

        var inputIsExactMatch = function (inputValue, index) {
            if (scope.matches.length > index && inputValue) {
                return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();
            }

            return false;
        };

        var getMatchesAsync = function (inputValue, evt) {
            var locals = { $viewValue: inputValue };
            isLoadingSetter(originalScope, true);
            isNoResultsSetter(originalScope, false);
            $q.when(parserResult.source(originalScope, locals)).then(function (matches) {
                //it might happen that several async queries were in progress if a user were typing fast
                //but we are interested only in responses that correspond to the current view value
                var onCurrentRequest = inputValue === modelCtrl.$viewValue;
                if (onCurrentRequest && hasFocus) {
                    if (matches && matches.length > 0) {
                        scope.activeIdx = focusFirst ? 0 : -1;
                        isNoResultsSetter(originalScope, false);
                        scope.matches.length = 0;

                        //transform labels
                        for (var i = 0; i < matches.length; i++) {
                            locals[parserResult.itemName] = matches[i];
                            scope.matches.push({
                                id: getMatchId(i),
                                label: parserResult.viewMapper(scope, locals),
                                model: matches[i]
                            });
                        }

                        scope.query = inputValue;
                        //position pop-up with matches - we need to re-calculate its position each time we are opening a window
                        //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
                        //due to other elements being rendered
                        recalculatePosition();

                        element.attr('aria-expanded', true);

                        //Select the single remaining option if user input matches
                        if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {
                            if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
                                $$debounce(function () {
                                    scope.select(0, evt);
                                }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
                            } else {
                                scope.select(0, evt);
                            }
                        }

                        if (showHint) {
                            var firstLabel = scope.matches[0].label;
                            if (angular.isString(inputValue) &&
                              inputValue.length > 0 &&
                              firstLabel.slice(0, inputValue.length).toUpperCase() === inputValue.toUpperCase()) {
                                hintInputElem.val(inputValue + firstLabel.slice(inputValue.length));
                            } else {
                                hintInputElem.val('');
                            }
                        }
                    } else {
                        resetMatches();
                        isNoResultsSetter(originalScope, true);
                    }
                }
                if (onCurrentRequest) {
                    isLoadingSetter(originalScope, false);
                }
            }, function () {
                resetMatches();
                isLoadingSetter(originalScope, false);
                isNoResultsSetter(originalScope, true);
            });
        };

        // bind events only if appendToBody params exist - performance feature
        if (appendToBody) {
            angular.element($window).on('resize', fireRecalculating);
            $document.find('body').on('scroll', fireRecalculating);
        }

        // Declare the debounced function outside recalculating for
        // proper debouncing
        var debouncedRecalculate = $$debounce(function () {
            // if popup is visible
            if (scope.matches.length) {
                recalculatePosition();
            }

            scope.moveInProgress = false;
        }, eventDebounceTime);

        // Default progress type
        scope.moveInProgress = false;

        function fireRecalculating() {
            if (!scope.moveInProgress) {
                scope.moveInProgress = true;
                scope.$digest();
            }

            debouncedRecalculate();
        }

        // recalculate actual position and set new values to scope
        // after digest loop is popup in right position
        function recalculatePosition() {
            scope.position = appendToBody ? $position.offset(element) : $position.position(element);
            scope.position.top += element.prop('offsetHeight');
        }

        //we need to propagate user's query so we can higlight matches
        scope.query = undefined;

        //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
        var timeoutPromise;

        var scheduleSearchWithTimeout = function (inputValue) {
            timeoutPromise = $timeout(function () {
                getMatchesAsync(inputValue);
            }, waitTime);
        };

        var cancelPreviousTimeout = function () {
            if (timeoutPromise) {
                $timeout.cancel(timeoutPromise);
            }
        };

        resetMatches();

        scope.assignIsOpen = function (isOpen) {
            isOpenSetter(originalScope, isOpen);
        };

        scope.select = function (activeIdx, evt) {
            //called from within the $digest() cycle
            var locals = {};
            var model, item;

            selected = true;
            locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
            model = parserResult.modelMapper(originalScope, locals);
            $setModelValue(originalScope, model);
            modelCtrl.$setValidity('editable', true);
            modelCtrl.$setValidity('parse', true);

            onSelectCallback(originalScope, {
                $item: item,
                $model: model,
                $label: parserResult.viewMapper(originalScope, locals),
                $event: evt
            });

            resetMatches();

            //return focus to the input element if a match was selected via a mouse click event
            // use timeout to avoid $rootScope:inprog error
            if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {
                $timeout(function () { element[0].focus(); }, 0, false);
            }
        };

        //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
        element.on('keydown', function (evt) {
            //typeahead is open and an "interesting" key was pressed
            if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
                return;
            }

            var shouldSelect = isSelectEvent(originalScope, { $event: evt });

            /**
             * if there's nothing selected (i.e. focusFirst) and enter or tab is hit
             * or
             * shift + tab is pressed to bring focus to the previous element
             * then clear the results
             */
            if (scope.activeIdx === -1 && shouldSelect || evt.which === 9 && !!evt.shiftKey) {
                resetMatches();
                scope.$digest();
                return;
            }

            evt.preventDefault();
            var target;
            switch (evt.which) {
                case 27: // escape
                    evt.stopPropagation();

                    resetMatches();
                    originalScope.$digest();
                    break;
                case 38: // up arrow
                    scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
                    scope.$digest();
                    target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
                    target.parentNode.scrollTop = target.offsetTop;
                    break;
                case 40: // down arrow
                    scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
                    scope.$digest();
                    target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
                    target.parentNode.scrollTop = target.offsetTop;
                    break;
                default:
                    if (shouldSelect) {
                        scope.$apply(function () {
                            if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
                                $$debounce(function () {
                                    scope.select(scope.activeIdx, evt);
                                }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
                            } else {
                                scope.select(scope.activeIdx, evt);
                            }
                        });
                    }
            }
        });

        element.bind('focus', function (evt) {
            hasFocus = true;
            if (minLength === 0 && !modelCtrl.$viewValue) {
                $timeout(function () {
                    getMatchesAsync(modelCtrl.$viewValue, evt);
                }, 0);
            }
        });

        element.bind('blur', function (evt) {
            if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {
                selected = true;
                scope.$apply(function () {
                    if (angular.isObject(scope.debounceUpdate) && angular.isNumber(scope.debounceUpdate.blur)) {
                        $$debounce(function () {
                            scope.select(scope.activeIdx, evt);
                        }, scope.debounceUpdate.blur);
                    } else {
                        scope.select(scope.activeIdx, evt);
                    }
                });
            }
            if (!isEditable && modelCtrl.$error.editable) {
                modelCtrl.$setViewValue();
                scope.$apply(function () {
                    // Reset validity as we are clearing
                    modelCtrl.$setValidity('editable', true);
                    modelCtrl.$setValidity('parse', true);
                });
                element.val('');
            }
            hasFocus = false;
            selected = false;
        });

        // Keep reference to click handler to unbind it.
        var dismissClickHandler = function (evt) {
            // Issue #3973
            // Firefox treats right click as a click on document
            if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {
                resetMatches();
                if (!$rootScope.$$phase) {
                    originalScope.$digest();
                }
            }
        };

        $document.on('click', dismissClickHandler);

        originalScope.$on('$destroy', function () {
            $document.off('click', dismissClickHandler);
            if (appendToBody || appendTo) {
                $popup.remove();
            }

            if (appendToBody) {
                angular.element($window).off('resize', fireRecalculating);
                $document.find('body').off('scroll', fireRecalculating);
            }
            // Prevent jQuery cache memory leak
            popUpEl.remove();

            if (showHint) {
                inputsContainer.remove();
            }
        });

        var $popup = $compile(popUpEl)(scope);

        if (appendToBody) {
            $document.find('body').append($popup);
        } else if (appendTo) {
            angular.element(appendTo).eq(0).append($popup);
        } else {
            element.after($popup);
        }

        this.init = function (_modelCtrl, _ngModelOptions) {
            modelCtrl = _modelCtrl;
            ngModelOptions = _ngModelOptions;

            scope.debounceUpdate = modelCtrl.$options && $parse(modelCtrl.$options.debounce)(originalScope);

            //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
            //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
            modelCtrl.$parsers.unshift(function (inputValue) {
                hasFocus = true;

                if (minLength === 0 || inputValue && inputValue.length >= minLength) {
                    if (waitTime > 0) {
                        cancelPreviousTimeout();
                        scheduleSearchWithTimeout(inputValue);
                    } else {
                        getMatchesAsync(inputValue);
                    }
                } else {
                    isLoadingSetter(originalScope, false);
                    cancelPreviousTimeout();
                    resetMatches();
                }

                if (isEditable) {
                    return inputValue;
                }

                if (!inputValue) {
                    // Reset in case user had typed something previously.
                    modelCtrl.$setValidity('editable', true);
                    return null;
                }

                modelCtrl.$setValidity('editable', false);
                return undefined;
            });

            modelCtrl.$formatters.push(function (modelValue) {
                var candidateViewValue, emptyViewValue;
                var locals = {};

                // The validity may be set to false via $parsers (see above) if
                // the model is restricted to selected values. If the model
                // is set manually it is considered to be valid.
                if (!isEditable) {
                    modelCtrl.$setValidity('editable', true);
                }

                if (inputFormatter) {
                    locals.$model = modelValue;
                    return inputFormatter(originalScope, locals);
                }

                //it might happen that we don't have enough info to properly render input value
                //we need to check for this situation and simply return model value if we can't apply custom formatting
                locals[parserResult.itemName] = modelValue;
                candidateViewValue = parserResult.viewMapper(originalScope, locals);
                locals[parserResult.itemName] = undefined;
                emptyViewValue = parserResult.viewMapper(originalScope, locals);

                return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;
            });
        };
    }])

  .directive('uibTypeahead', function () {
      return {
          controller: 'UibTypeaheadController',
          require: ['ngModel', '^?ngModelOptions', 'uibTypeahead'],
          link: function (originalScope, element, attrs, ctrls) {
              ctrls[2].init(ctrls[0], ctrls[1]);
          }
      };
  })

  .directive('uibTypeaheadPopup', ['$$debounce', function ($$debounce) {
      return {
          scope: {
              matches: '=',
              query: '=',
              active: '=',
              position: '&',
              moveInProgress: '=',
              select: '&',
              assignIsOpen: '&',
              debounce: '&'
          },
          replace: true,
          templateUrl: function (element, attrs) {
              return attrs.popupTemplateUrl || 'uib/template/typeahead/typeahead-popup.html';
          },
          link: function (scope, element, attrs) {
              scope.templateUrl = attrs.templateUrl;

              scope.isOpen = function () {
                  var isDropdownOpen = scope.matches.length > 0;
                  scope.assignIsOpen({ isOpen: isDropdownOpen });
                  return isDropdownOpen;
              };

              scope.isActive = function (matchIdx) {
                  return scope.active === matchIdx;
              };

              scope.selectActive = function (matchIdx) {
                  scope.active = matchIdx;
              };

              scope.selectMatch = function (activeIdx, evt) {
                  var debounce = scope.debounce();
                  if (angular.isNumber(debounce) || angular.isObject(debounce)) {
                      $$debounce(function () {
                          scope.select({ activeIdx: activeIdx, evt: evt });
                      }, angular.isNumber(debounce) ? debounce : debounce['default']);
                  } else {
                      scope.select({ activeIdx: activeIdx, evt: evt });
                  }
              };
          }
      };
  }])

  .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function ($templateRequest, $compile, $parse) {
      return {
          scope: {
              index: '=',
              match: '=',
              query: '='
          },
          link: function (scope, element, attrs) {
              var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'uib/template/typeahead/typeahead-match.html';
              $templateRequest(tplUrl).then(function (tplContent) {
                  var tplEl = angular.element(tplContent.trim());
                  element.replaceWith(tplEl);
                  $compile(tplEl)(scope);
              });
          }
      };
  }])

  .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function ($sce, $injector, $log) {
      var isSanitizePresent;
      isSanitizePresent = $injector.has('$sanitize');

      function escapeRegexp(queryToEscape) {
          // Regex: capture the whole query string and replace it with the string that will be used to match
          // the results, for example if the capture is "a" the result will be \a
          return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
      }

      function containsHtml(matchItem) {
          return /<.*>/g.test(matchItem);
      }

      return function (matchItem, query) {
          if (!isSanitizePresent && containsHtml(matchItem)) {
              $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger
          }
          matchItem = query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem; // Replaces the capture string with a the same string inside of a "strong" tag
          if (!isSanitizePresent) {
              matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive
          }
          return matchItem;
      };
  }]);

angular.module("uib/template/accordion/accordion-group.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/accordion/accordion-group.html",
      "<div role=\"tab\" id=\"{{::headingId}}\" aria-selected=\"{{isOpen}}\" class=\"panel-heading\" ng-keypress=\"toggleOpen($event)\">\n" +
      "  <h4 class=\"panel-title\">\n" +
      "    <a role=\"button\" data-toggle=\"collapse\" href aria-expanded=\"{{isOpen}}\" aria-controls=\"{{::panelId}}\" tabindex=\"0\" class=\"accordion-toggle\" ng-click=\"toggleOpen()\" uib-accordion-transclude=\"heading\" ng-disabled=\"isDisabled\" uib-tabindex-toggle><span uib-accordion-header ng-class=\"{'text-muted': isDisabled}\">{{heading}}</span></a>\n" +
      "  </h4>\n" +
      "</div>\n" +
      "<div id=\"{{::panelId}}\" aria-labelledby=\"{{::headingId}}\" aria-hidden=\"{{!isOpen}}\" role=\"tabpanel\" class=\"panel-collapse collapse\" uib-collapse=\"!isOpen\">\n" +
      "  <div class=\"panel-body\" ng-transclude></div>\n" +
      "</div>\n" +
      "");
}]);

angular.module("uib/template/accordion/accordion.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/accordion/accordion.html",
      "<div role=\"tablist\" class=\"panel-group\" ng-transclude></div>");
}]);

angular.module("uib/template/alert/alert.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/alert/alert.html",
      "<button ng-show=\"closeable\" type=\"button\" class=\"close\" ng-click=\"close({$event: $event})\">\n" +
      "  <span aria-hidden=\"true\">&times;</span>\n" +
      "  <span class=\"sr-only\">Close</span>\n" +
      "</button>\n" +
      "<div ng-transclude></div>\n" +
      "");
}]);

angular.module("uib/template/carousel/carousel.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/carousel/carousel.html",
      "<div class=\"carousel-inner\" ng-transclude></div>\n" +
      "<a role=\"button\" href class=\"left carousel-control\" ng-click=\"prev()\" ng-class=\"{ disabled: isPrevDisabled() }\" ng-show=\"slides.length > 1\">\n" +
      "  <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></span>\n" +
      "  <span class=\"sr-only\">previous</span>\n" +
      "</a>\n" +
      "<a role=\"button\" href class=\"right carousel-control\" ng-click=\"next()\" ng-class=\"{ disabled: isNextDisabled() }\" ng-show=\"slides.length > 1\">\n" +
      "  <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></span>\n" +
      "  <span class=\"sr-only\">next</span>\n" +
      "</a>\n" +
      "<ol class=\"carousel-indicators\" ng-show=\"slides.length > 1\">\n" +
      "  <li ng-repeat=\"slide in slides | orderBy:indexOfSlide track by $index\" ng-class=\"{ active: isActive(slide) }\" ng-click=\"select(slide)\">\n" +
      "    <span class=\"sr-only\">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if=\"isActive(slide)\">, currently active</span></span>\n" +
      "  </li>\n" +
      "</ol>\n" +
      "");
}]);

angular.module("uib/template/carousel/slide.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/carousel/slide.html",
      "<div class=\"text-center\" ng-transclude></div>\n" +
      "");
}]);

angular.module("uib/template/datepicker/datepicker.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/datepicker/datepicker.html",
      "<div ng-switch=\"datepickerMode\">\n" +
      "  <div uib-daypicker ng-switch-when=\"day\" tabindex=\"0\" class=\"uib-daypicker\"></div>\n" +
      "  <div uib-monthpicker ng-switch-when=\"month\" tabindex=\"0\" class=\"uib-monthpicker\"></div>\n" +
      "  <div uib-yearpicker ng-switch-when=\"year\" tabindex=\"0\" class=\"uib-yearpicker\"></div>\n" +
      "</div>\n" +
      "");
}]);

angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/datepicker/day.html",
      "<table role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
      "  <thead>\n" +
      "    <tr>\n" +
      "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></i><span class=\"sr-only\">previous</span></button></th>\n" +
      "      <th colspan=\"{{::5 + showWeeks}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
      "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></i><span class=\"sr-only\">next</span></button></th>\n" +
      "    </tr>\n" +
      "    <tr>\n" +
      "      <th ng-if=\"showWeeks\" class=\"text-center\"></th>\n" +
      "      <th ng-repeat=\"label in ::labels track by $index\" class=\"text-center\"><small aria-label=\"{{::label.full}}\">{{::label.abbr}}</small></th>\n" +
      "    </tr>\n" +
      "  </thead>\n" +
      "  <tbody>\n" +
      "    <tr class=\"uib-weeks\" ng-repeat=\"row in rows track by $index\" role=\"row\">\n" +
      "      <td ng-if=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
      "      <td ng-repeat=\"dt in row\" class=\"uib-day text-center\" role=\"gridcell\"\n" +
      "        id=\"{{::dt.uid}}\"\n" +
      "        ng-class=\"::dt.customClass\">\n" +
      "        <button type=\"button\" class=\"btn btn-default btn-sm\"\n" +
      "          uib-is-class=\"\n" +
      "            'btn-info' for selectedDt,\n" +
      "            'active' for activeDt\n" +
      "            on dt\"\n" +
      "          ng-click=\"select(dt.date)\"\n" +
      "          ng-disabled=\"::dt.disabled\"\n" +
      "          tabindex=\"-1\"><span ng-class=\"::{'text-muted': dt.secondary, 'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
      "      </td>\n" +
      "    </tr>\n" +
      "  </tbody>\n" +
      "</table>\n" +
      "");
}]);

angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/datepicker/month.html",
      "<table role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
      "  <thead>\n" +
      "    <tr>\n" +
      "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></i><span class=\"sr-only\">previous</span></button></th>\n" +
      "      <th colspan=\"{{::yearHeaderColspan}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
      "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></i><span class=\"sr-only\">next</span></i></button></th>\n" +
      "    </tr>\n" +
      "  </thead>\n" +
      "  <tbody>\n" +
      "    <tr class=\"uib-months\" ng-repeat=\"row in rows track by $index\" role=\"row\">\n" +
      "      <td ng-repeat=\"dt in row\" class=\"uib-month text-center\" role=\"gridcell\"\n" +
      "        id=\"{{::dt.uid}}\"\n" +
      "        ng-class=\"::dt.customClass\">\n" +
      "        <button type=\"button\" class=\"btn btn-default\"\n" +
      "          uib-is-class=\"\n" +
      "            'btn-info' for selectedDt,\n" +
      "            'active' for activeDt\n" +
      "            on dt\"\n" +
      "          ng-click=\"select(dt.date)\"\n" +
      "          ng-disabled=\"::dt.disabled\"\n" +
      "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
      "      </td>\n" +
      "    </tr>\n" +
      "  </tbody>\n" +
      "</table>\n" +
      "");
}]);

angular.module("uib/template/datepicker/year.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/datepicker/year.html",
      "<table role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
      "  <thead>\n" +
      "    <tr>\n" +
      "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></i><span class=\"sr-only\">previous</span></button></th>\n" +
      "      <th colspan=\"{{::columns - 2}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
      "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></i><span class=\"sr-only\">next</span></button></th>\n" +
      "    </tr>\n" +
      "  </thead>\n" +
      "  <tbody>\n" +
      "    <tr class=\"uib-years\" ng-repeat=\"row in rows track by $index\" role=\"row\">\n" +
      "      <td ng-repeat=\"dt in row\" class=\"uib-year text-center\" role=\"gridcell\"\n" +
      "        id=\"{{::dt.uid}}\"\n" +
      "        ng-class=\"::dt.customClass\">\n" +
      "        <button type=\"button\" class=\"btn btn-default\"\n" +
      "          uib-is-class=\"\n" +
      "            'btn-info' for selectedDt,\n" +
      "            'active' for activeDt\n" +
      "            on dt\"\n" +
      "          ng-click=\"select(dt.date)\"\n" +
      "          ng-disabled=\"::dt.disabled\"\n" +
      "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
      "      </td>\n" +
      "    </tr>\n" +
      "  </tbody>\n" +
      "</table>\n" +
      "");
}]);

angular.module("uib/template/datepickerPopup/popup.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/datepickerPopup/popup.html",
      "<ul role=\"presentation\" class=\"uib-datepicker-popup dropdown-menu uib-position-measure\" dropdown-nested ng-if=\"isOpen\" ng-keydown=\"keydown($event)\" ng-click=\"$event.stopPropagation()\">\n" +
      "  <li ng-transclude></li>\n" +
      "  <li ng-if=\"showButtonBar\" class=\"uib-button-bar\">\n" +
      "    <span class=\"btn-group pull-left\">\n" +
      "      <button type=\"button\" class=\"btn btn-sm btn-info uib-datepicker-current\" ng-click=\"select('today', $event)\" ng-disabled=\"isDisabled('today')\">{{ getText('current') }}</button>\n" +
      "      <button type=\"button\" class=\"btn btn-sm btn-danger uib-clear\" ng-click=\"select(null, $event)\">{{ getText('clear') }}</button>\n" +
      "    </span>\n" +
      "    <button type=\"button\" class=\"btn btn-sm btn-success pull-right uib-close\" ng-click=\"close($event)\">{{ getText('close') }}</button>\n" +
      "  </li>\n" +
      "</ul>\n" +
      "");
}]);

angular.module("uib/template/modal/window.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/modal/window.html",
      "<div class=\"modal-dialog {{size ? 'modal-' + size : ''}}\"><div class=\"modal-content\" uib-modal-transclude></div></div>\n" +
      "");
}]);

angular.module("uib/template/pager/pager.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/pager/pager.html",
      "<li ng-class=\"{disabled: noPrevious()||ngDisabled, previous: align}\"><a href ng-click=\"selectPage(page - 1, $event)\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('previous')}}</a></li>\n" +
      "<li ng-class=\"{disabled: noNext()||ngDisabled, next: align}\"><a href ng-click=\"selectPage(page + 1, $event)\" ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('next')}}</a></li>\n" +
      "");
}]);

angular.module("uib/template/pagination/pagination.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/pagination/pagination.html",
      "<li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-first\"><a href ng-click=\"selectPage(1, $event)\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('first')}}</a></li>\n" +
      "<li ng-if=\"::directionLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-prev\"><a href ng-click=\"selectPage(page - 1, $event)\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('previous')}}</a></li>\n" +
      "<li ng-repeat=\"page in pages track by $index\" ng-class=\"{active: page.active,disabled: ngDisabled&&!page.active}\" class=\"pagination-page\"><a href ng-click=\"selectPage(page.number, $event)\" ng-disabled=\"ngDisabled&&!page.active\" uib-tabindex-toggle>{{page.text}}</a></li>\n" +
      "<li ng-if=\"::directionLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-next\"><a href ng-click=\"selectPage(page + 1, $event)\" ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('next')}}</a></li>\n" +
      "<li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-last\"><a href ng-click=\"selectPage(totalPages, $event)\" ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('last')}}</a></li>\n" +
      "");
}]);

angular.module("uib/template/tooltip/tooltip-html-popup.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/tooltip/tooltip-html-popup.html",
      "<div class=\"tooltip-arrow\"></div>\n" +
      "<div class=\"tooltip-inner\" ng-bind-html=\"contentExp()\"></div>\n" +
      "");
}]);

angular.module("uib/template/tooltip/tooltip-popup.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/tooltip/tooltip-popup.html",
      "<div class=\"tooltip-arrow\"></div>\n" +
      "<div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
      "");
}]);

angular.module("uib/template/tooltip/tooltip-template-popup.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/tooltip/tooltip-template-popup.html",
      "<div class=\"tooltip-arrow\"></div>\n" +
      "<div class=\"tooltip-inner\"\n" +
      "  uib-tooltip-template-transclude=\"contentExp()\"\n" +
      "  tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
      "");
}]);

angular.module("uib/template/popover/popover-html.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/popover/popover-html.html",
      "<div class=\"arrow\"></div>\n" +
      "\n" +
      "<div class=\"popover-inner\">\n" +
      "    <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
      "    <div class=\"popover-content\" ng-bind-html=\"contentExp()\"></div>\n" +
      "</div>\n" +
      "");
}]);

angular.module("uib/template/popover/popover-template.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/popover/popover-template.html",
      "<div class=\"arrow\"></div>\n" +
      "\n" +
      "<div class=\"popover-inner\">\n" +
      "    <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
      "    <div class=\"popover-content\"\n" +
      "      uib-tooltip-template-transclude=\"contentExp()\"\n" +
      "      tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
      "</div>\n" +
      "");
}]);

angular.module("uib/template/popover/popover.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/popover/popover.html",
      "<div class=\"arrow\"></div>\n" +
      "\n" +
      "<div class=\"popover-inner\">\n" +
      "    <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
      "    <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
      "</div>\n" +
      "");
}]);

angular.module("uib/template/progressbar/bar.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/progressbar/bar.html",
      "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
      "");
}]);

angular.module("uib/template/progressbar/progress.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/progressbar/progress.html",
      "<div class=\"progress\" ng-transclude aria-labelledby=\"{{::title}}\"></div>");
}]);

angular.module("uib/template/progressbar/progressbar.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/progressbar/progressbar.html",
      "<div class=\"progress\">\n" +
      "  <div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
      "</div>\n" +
      "");
}]);

angular.module("uib/template/rating/rating.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/rating/rating.html",
      "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\" aria-valuetext=\"{{title}}\">\n" +
      "    <span ng-repeat-start=\"r in range track by $index\" class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
      "    <i ng-repeat-end ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\" ng-attr-title=\"{{r.title}}\"></i>\n" +
      "</span>\n" +
      "");
}]);

angular.module("uib/template/tabs/tab.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/tabs/tab.html",
      "<li ng-class=\"[{active: active, disabled: disabled}, classes]\" class=\"uib-tab nav-item\">\n" +
      "  <a href ng-click=\"select($event)\" class=\"nav-link\" uib-tab-heading-transclude>{{heading}}</a>\n" +
      "</li>\n" +
      "");
}]);

angular.module("uib/template/tabs/tabset.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/tabs/tabset.html",
      "<div>\n" +
      "  <ul class=\"nav nav-{{tabset.type || 'tabs'}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
      "  <div class=\"tab-content\">\n" +
      "    <div class=\"tab-pane\"\n" +
      "         ng-repeat=\"tab in tabset.tabs\"\n" +
      "         ng-class=\"{active: tabset.active === tab.index}\"\n" +
      "         uib-tab-content-transclude=\"tab\">\n" +
      "    </div>\n" +
      "  </div>\n" +
      "</div>\n" +
      "");
}]);

angular.module("uib/template/timepicker/timepicker.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/timepicker/timepicker.html",
      "<table class=\"uib-timepicker\">\n" +
      "  <tbody>\n" +
      "    <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
      "      <td class=\"uib-increment hours\"><a ng-click=\"incrementHours()\" ng-class=\"{disabled: noIncrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementHours()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
      "      <td>&nbsp;</td>\n" +
      "      <td class=\"uib-increment minutes\"><a ng-click=\"incrementMinutes()\" ng-class=\"{disabled: noIncrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementMinutes()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
      "      <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
      "      <td ng-show=\"showSeconds\" class=\"uib-increment seconds\"><a ng-click=\"incrementSeconds()\" ng-class=\"{disabled: noIncrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementSeconds()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
      "      <td ng-show=\"showMeridian\"></td>\n" +
      "    </tr>\n" +
      "    <tr>\n" +
      "      <td class=\"form-group uib-time hours\" ng-class=\"{'has-error': invalidHours}\">\n" +
      "        <input type=\"text\" placeholder=\"HH\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementHours()\" ng-blur=\"blur()\">\n" +
      "      </td>\n" +
      "      <td class=\"uib-separator\">:</td>\n" +
      "      <td class=\"form-group uib-time minutes\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
      "        <input type=\"text\" placeholder=\"MM\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementMinutes()\" ng-blur=\"blur()\">\n" +
      "      </td>\n" +
      "      <td ng-show=\"showSeconds\" class=\"uib-separator\">:</td>\n" +
      "      <td class=\"form-group uib-time seconds\" ng-class=\"{'has-error': invalidSeconds}\" ng-show=\"showSeconds\">\n" +
      "        <input type=\"text\" placeholder=\"SS\" ng-model=\"seconds\" ng-change=\"updateSeconds()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementSeconds()\" ng-blur=\"blur()\">\n" +
      "      </td>\n" +
      "      <td ng-show=\"showMeridian\" class=\"uib-time am-pm\"><button type=\"button\" ng-class=\"{disabled: noToggleMeridian()}\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\" ng-disabled=\"noToggleMeridian()\" tabindex=\"{{::tabindex}}\">{{meridian}}</button></td>\n" +
      "    </tr>\n" +
      "    <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
      "      <td class=\"uib-decrement hours\"><a ng-click=\"decrementHours()\" ng-class=\"{disabled: noDecrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementHours()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
      "      <td>&nbsp;</td>\n" +
      "      <td class=\"uib-decrement minutes\"><a ng-click=\"decrementMinutes()\" ng-class=\"{disabled: noDecrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementMinutes()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
      "      <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
      "      <td ng-show=\"showSeconds\" class=\"uib-decrement seconds\"><a ng-click=\"decrementSeconds()\" ng-class=\"{disabled: noDecrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementSeconds()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
      "      <td ng-show=\"showMeridian\"></td>\n" +
      "    </tr>\n" +
      "  </tbody>\n" +
      "</table>\n" +
      "");
}]);

angular.module("uib/template/typeahead/typeahead-match.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/typeahead/typeahead-match.html",
      "<a href\n" +
      "   tabindex=\"-1\"\n" +
      "   ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"\n" +
      "   ng-attr-title=\"{{match.label}}\"></a>\n" +
      "");
}]);

angular.module("uib/template/typeahead/typeahead-popup.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("uib/template/typeahead/typeahead-popup.html",
      "<ul class=\"dropdown-menu\" ng-show=\"isOpen() && !moveInProgress\" ng-style=\"{top: position().top+'px', left: position().left+'px'}\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
      "    <li class=\"uib-typeahead-match\" ng-repeat=\"match in matches track by $index\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index, $event)\" role=\"option\" id=\"{{::match.id}}\">\n" +
      "        <div uib-typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
      "    </li>\n" +
      "</ul>\n" +
      "");
}]);
angular.module('ui.bootstrap.carousel').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibCarouselCss && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'); angular.$$uibCarouselCss = true; });
angular.module('ui.bootstrap.datepicker').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibDatepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'); angular.$$uibDatepickerCss = true; });
angular.module('ui.bootstrap.position').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibPositionCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'); angular.$$uibPositionCss = true; });
angular.module('ui.bootstrap.datepickerPopup').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibDatepickerpopupCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'); angular.$$uibDatepickerpopupCss = true; });
angular.module('ui.bootstrap.tooltip').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });
angular.module('ui.bootstrap.timepicker').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibTimepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-time input{width:50px;}</style>'); angular.$$uibTimepickerCss = true; });
angular.module('ui.bootstrap.typeahead').run(function () { !angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; });;
/*! ngstorage 0.3.10 | Copyright (c) 2015 Gias Kay Lee | MIT License */!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):a.hasOwnProperty("angular")?b(a.angular):"object"==typeof exports&&(module.exports=b(require("angular")))}(this,function(a){"use strict";function b(b){return function(){var c="ngStorage-";this.setKeyPrefix=function(a){if("string"!=typeof a)throw new TypeError("[ngStorage] - "+b+"Provider.setKeyPrefix() expects a String.");c=a};var d=a.toJson,e=a.fromJson;this.setSerializer=function(a){if("function"!=typeof a)throw new TypeError("[ngStorage] - "+b+"Provider.setSerializer expects a function.");d=a},this.setDeserializer=function(a){if("function"!=typeof a)throw new TypeError("[ngStorage] - "+b+"Provider.setDeserializer expects a function.");e=a},this.get=function(a){return e(window[b].getItem(c+a))},this.set=function(a,e){return window[b].setItem(c+a,d(e))},this.$get=["$rootScope","$window","$log","$timeout","$document",function(f,g,h,i,j){function k(a){var b;try{b=g[a]}catch(c){b=!1}if(b&&"localStorage"===a){var d="__"+Math.round(1e7*Math.random());try{localStorage.setItem(d,d),localStorage.removeItem(d)}catch(c){b=!1}}return b}var l,m,n=c.length,o=k(b)||(h.warn("This browser does not support Web Storage!"),{setItem:a.noop,getItem:a.noop,removeItem:a.noop}),p={$default:function(b){for(var c in b)a.isDefined(p[c])||(p[c]=a.copy(b[c]));return p.$sync(),p},$reset:function(a){for(var b in p)"$"===b[0]||delete p[b]&&o.removeItem(c+b);return p.$default(a)},$sync:function(){for(var a,b=0,d=o.length;d>b;b++)(a=o.key(b))&&c===a.slice(0,n)&&(p[a.slice(n)]=e(o.getItem(a)))},$apply:function(){var b;if(m=null,!a.equals(p,l)){b=a.copy(l),a.forEach(p,function(e,f){a.isDefined(e)&&"$"!==f[0]&&(o.setItem(c+f,d(e)),delete b[f])});for(var e in b)o.removeItem(c+e);l=a.copy(p)}}};return p.$sync(),l=a.copy(p),f.$watch(function(){m||(m=i(p.$apply,100,!1))}),g.addEventListener&&g.addEventListener("storage",function(b){if(b.key){var d=j[0];d.hasFocus&&d.hasFocus()||c!==b.key.slice(0,n)||(b.newValue?p[b.key.slice(n)]=e(b.newValue):delete p[b.key.slice(n)],l=a.copy(p),f.$apply())}}),g.addEventListener&&g.addEventListener("beforeunload",function(){p.$apply()}),p}]}}return a=a&&a.module?a:window.angular,a.module("ngStorage",[]).provider("$localStorage",b("localStorage")).provider("$sessionStorage",b("sessionStorage"))});;
/**
 * Bunch of useful filters for angularJS(with no external dependencies!)
 * @version v0.5.14 - 2016-12-06 * @link https://github.com/a8m/angular-filter
 * @author Ariel Mashraki <ariel@mashraki.co.il>
 * @license MIT License, http://www.opensource.org/licenses/MIT
 */!function (a, b, c) { "use strict"; function d(a) { return D(a) ? a : Object.keys(a).map(function (b) { return a[b] }) } function e(a) { return null === a } function f(a, b) { var d = Object.keys(a); return d.map(function (d) { return b[d] !== c && b[d] == a[d] }).indexOf(!1) == -1 } function g(a, b) { function c(a, b, c) { for (var d = 0; b + d <= a.length;) { if (a.charAt(b + d) == c) return d; d++ } return -1 } for (var d = 0, e = 0; e <= b.length; e++) { var f = c(a, d, b.charAt(e)); if (f == -1) return !1; d += f + 1 } return !0 } function h(a, b, c) { var d = 0; return a.filter(function (a) { var e = x(c) ? d < b && c(a) : d < b; return d = e ? d + 1 : d, e }) } function i(a, b) { return Math.round(a * Math.pow(10, b)) / Math.pow(10, b) } function j(a, b, c) { b = b || []; var d = Object.keys(a); return d.forEach(function (d) { if (C(a[d]) && !D(a[d])) { var e = c ? c + "." + d : c; j(a[d], b, e || d) } else { var f = c ? c + "." + d : d; b.push(f) } }), b } function k(a) { return a && a.$evalAsync && a.$watch } function l() { return function (a, b) { return a > b } } function m() { return function (a, b) { return a >= b } } function n() { return function (a, b) { return a < b } } function o() { return function (a, b) { return a <= b } } function p() { return function (a, b) { return a == b } } function q() { return function (a, b) { return a != b } } function r() { return function (a, b) { return a === b } } function s() { return function (a, b) { return a !== b } } function t(a) { return function (b, c) { return b = C(b) ? d(b) : b, !(!D(b) || y(c)) && b.some(function (b) { return A(c) && C(b) || z(c) ? a(c)(b) : b === c }) } } function u(a, b) { return b = b || 0, b >= a.length ? a : D(a[b]) ? u(a.slice(0, b).concat(a[b], a.slice(b + 1)), b) : u(a, b + 1) } function v(a) { return function (b, c) { function e(a, b) { return !y(b) && a.some(function (a) { return H(a, b) }) } if (b = C(b) ? d(b) : b, !D(b)) return b; var f = [], g = a(c); return y(c) ? b.filter(function (a, b, c) { return c.indexOf(a) === b }) : b.filter(function (a) { var b = g(a); return !e(f, b) && (f.push(b), !0) }) } } function w(a, b, c) { return b ? a + c + w(a, --b, c) : a } var x = b.isDefined, y = b.isUndefined, z = b.isFunction, A = b.isString, B = b.isNumber, C = b.isObject, D = b.isArray, E = b.forEach, F = b.extend, G = b.copy, H = b.equals; String.prototype.contains || (String.prototype.contains = function () { return String.prototype.indexOf.apply(this, arguments) !== -1 }), b.module("a8m.angular", []).filter("isUndefined", function () { return function (a) { return b.isUndefined(a) } }).filter("isDefined", function () { return function (a) { return b.isDefined(a) } }).filter("isFunction", function () { return function (a) { return b.isFunction(a) } }).filter("isString", function () { return function (a) { return b.isString(a) } }).filter("isNumber", function () { return function (a) { return b.isNumber(a) } }).filter("isArray", function () { return function (a) { return b.isArray(a) } }).filter("isObject", function () { return function (a) { return b.isObject(a) } }).filter("isEqual", function () { return function (a, c) { return b.equals(a, c) } }), b.module("a8m.conditions", []).filter({ isGreaterThan: l, ">": l, isGreaterThanOrEqualTo: m, ">=": m, isLessThan: n, "<": n, isLessThanOrEqualTo: o, "<=": o, isEqualTo: p, "==": p, isNotEqualTo: q, "!=": q, isIdenticalTo: r, "===": r, isNotIdenticalTo: s, "!==": s }), b.module("a8m.is-null", []).filter("isNull", function () { return function (a) { return e(a) } }), b.module("a8m.after-where", []).filter("afterWhere", function () { return function (a, b) { if (a = C(a) ? d(a) : a, !D(a) || y(b)) return a; var c = a.map(function (a) { return f(b, a) }).indexOf(!0); return a.slice(c === -1 ? 0 : c) } }), b.module("a8m.after", []).filter("after", function () { return function (a, b) { return a = C(a) ? d(a) : a, D(a) ? a.slice(b) : a } }), b.module("a8m.before-where", []).filter("beforeWhere", function () { return function (a, b) { if (a = C(a) ? d(a) : a, !D(a) || y(b)) return a; var c = a.map(function (a) { return f(b, a) }).indexOf(!0); return a.slice(0, c === -1 ? a.length : ++c) } }), b.module("a8m.before", []).filter("before", function () { return function (a, b) { return a = C(a) ? d(a) : a, D(a) ? a.slice(0, b ? --b : b) : a } }), b.module("a8m.chunk-by", ["a8m.filter-watcher"]).filter("chunkBy", ["filterWatcher", function (a) { return function (b, c, d) { function e(a, b) { for (var c = []; a--;) c[a] = b; return c } function f(a, b, c) { return D(a) ? a.map(function (a, d, f) { return d *= b, a = f.slice(d, d + b), !y(c) && a.length < b ? a.concat(e(b - a.length, c)) : a }).slice(0, Math.ceil(a.length / b)) : a } return a.isMemoized("chunkBy", arguments) || a.memoize("chunkBy", arguments, this, f(b, c, d)) } }]), b.module("a8m.concat", []).filter("concat", [function () { return function (a, b) { if (y(b)) return a; if (D(a)) return C(b) ? a.concat(d(b)) : a.concat(b); if (C(a)) { var c = d(a); return C(b) ? c.concat(d(b)) : c.concat(b) } return a } }]), b.module("a8m.contains", []).filter({ contains: ["$parse", t], some: ["$parse", t] }), b.module("a8m.count-by", []).filter("countBy", ["$parse", function (a) { return function (b, c) { var e, f = {}, g = a(c); return b = C(b) ? d(b) : b, !D(b) || y(c) ? b : (b.forEach(function (a) { e = g(a), f[e] || (f[e] = 0), f[e]++ }), f) } }]), b.module("a8m.defaults", []).filter("defaults", ["$parse", function (a) { return function (b, c) { if (b = C(b) ? d(b) : b, !D(b) || !C(c)) return b; var e = j(c); return b.forEach(function (b) { e.forEach(function (d) { var e = a(d), f = e.assign; y(e(b)) && f(b, e(c)) }) }), b } }]), b.module("a8m.every", []).filter("every", ["$parse", function (a) { return function (b, c) { return b = C(b) ? d(b) : b, !(D(b) && !y(c)) || b.every(function (b) { return C(b) || z(c) ? a(c)(b) : b === c }) } }]), b.module("a8m.filter-by", []).filter("filterBy", ["$parse", function (a) { return function (b, e, f, g) { var h; return f = A(f) || B(f) ? String(f).toLowerCase() : c, b = C(b) ? d(b) : b, !D(b) || y(f) ? b : b.filter(function (b) { return e.some(function (c) { if (~c.indexOf("+")) { var d = c.replace(/\s+/g, "").split("+"); h = d.map(function (c) { return a(c)(b) }).join(" ") } else h = a(c)(b); return !(!A(h) && !B(h)) && (h = String(h).toLowerCase(), g ? h === f : h.contains(f)) }) }) } }]), b.module("a8m.first", []).filter("first", ["$parse", function (a) { return function (b) { var e, f, g; return b = C(b) ? d(b) : b, D(b) ? (g = Array.prototype.slice.call(arguments, 1), e = B(g[0]) ? g[0] : 1, f = B(g[0]) ? B(g[1]) ? c : g[1] : g[0], g.length ? h(b, e, f ? a(f) : f) : b[0]) : b } }]), b.module("a8m.flatten", []).filter("flatten", function () { return function (a, b) { return b = b || !1, a = C(a) ? d(a) : a, D(a) ? b ? [].concat.apply([], a) : u(a, 0) : a } }), b.module("a8m.fuzzy-by", []).filter("fuzzyBy", ["$parse", function (a) { return function (b, c, e, f) { var h, i, j = f || !1; return b = C(b) ? d(b) : b, !D(b) || y(c) || y(e) ? b : (i = a(c), b.filter(function (a) { return h = i(a), !!A(h) && (h = j ? h : h.toLowerCase(), e = j ? e : e.toLowerCase(), g(h, e) !== !1) })) } }]), b.module("a8m.fuzzy", []).filter("fuzzy", function () { return function (a, b, c) { function e(a, b) { var c, d, e = Object.keys(a); return 0 < e.filter(function (e) { return c = a[e], !!d || !!A(c) && (c = f ? c : c.toLowerCase(), d = g(c, b) !== !1) }).length } var f = c || !1; return a = C(a) ? d(a) : a, !D(a) || y(b) ? a : (b = f ? b : b.toLowerCase(), a.filter(function (a) { return A(a) ? (a = f ? a : a.toLowerCase(), g(a, b) !== !1) : !!C(a) && e(a, b) })) } }), b.module("a8m.group-by", ["a8m.filter-watcher"]).filter("groupBy", ["$parse", "filterWatcher", function (a, b) { return function (c, d) { function e(a, b) { var c, d = {}; return E(a, function (a) { c = b(a), d[c] || (d[c] = []), d[c].push(a) }), d } return !C(c) || y(d) ? c : b.isMemoized("groupBy", arguments) || b.memoize("groupBy", arguments, this, e(c, a(d))) } }]), b.module("a8m.is-empty", []).filter("isEmpty", function () { return function (a) { return C(a) ? !d(a).length : !a.length } }), b.module("a8m.join", []).filter("join", function () { return function (a, b) { return y(a) || !D(a) ? a : (y(b) && (b = " "), a.join(b)) } }), b.module("a8m.last", []).filter("last", ["$parse", function (a) { return function (b) { var e, f, g, i = G(b); return i = C(i) ? d(i) : i, D(i) ? (g = Array.prototype.slice.call(arguments, 1), e = B(g[0]) ? g[0] : 1, f = B(g[0]) ? B(g[1]) ? c : g[1] : g[0], g.length ? h(i.reverse(), e, f ? a(f) : f).reverse() : i[i.length - 1]) : i } }]), b.module("a8m.map", []).filter("map", ["$parse", function (a) { return function (b, c) { return b = C(b) ? d(b) : b, !D(b) || y(c) ? b : b.map(function (b) { return a(c)(b) }) } }]), b.module("a8m.omit", []).filter("omit", ["$parse", function (a) { return function (b, c) { return b = C(b) ? d(b) : b, !D(b) || y(c) ? b : b.filter(function (b) { return !a(c)(b) }) } }]), b.module("a8m.pick", []).filter("pick", ["$parse", function (a) { return function (b, c) { return b = C(b) ? d(b) : b, !D(b) || y(c) ? b : b.filter(function (b) { return a(c)(b) }) } }]), b.module("a8m.range", []).filter("range", function () { return function (a, b, c, d, e) { c = c || 0, d = d || 1; for (var f = 0; f < parseInt(b) ; f++) { var g = c + f * d; a.push(z(e) ? e(g) : g) } return a } }), b.module("a8m.remove-with", []).filter("removeWith", function () { return function (a, b) { return y(b) ? a : (a = C(a) ? d(a) : a, a.filter(function (a) { return !f(b, a) })) } }), b.module("a8m.remove", []).filter("remove", function () { return function (a) { a = C(a) ? d(a) : a; var b = Array.prototype.slice.call(arguments, 1); return D(a) ? a.filter(function (a) { return !b.some(function (b) { return H(b, a) }) }) : a } }), b.module("a8m.reverse", []).filter("reverse", [function () { return function (a) { return a = C(a) ? d(a) : a, A(a) ? a.split("").reverse().join("") : D(a) ? a.slice().reverse() : a } }]), b.module("a8m.search-field", []).filter("searchField", ["$parse", function (a) { return function (b) { var c, e; b = C(b) ? d(b) : b; var f = Array.prototype.slice.call(arguments, 1); return D(b) && f.length ? b.map(function (b) { return e = f.map(function (d) { return (c = a(d))(b) }).join(" "), F(b, { searchField: e }) }) : b } }]), b.module("a8m.to-array", []).filter("toArray", function () { return function (a, b) { return C(a) ? b ? Object.keys(a).map(function (b) { return F(a[b], { $key: b }) }) : d(a) : a } }), b.module("a8m.unique", []).filter({ unique: ["$parse", v], uniq: ["$parse", v] }), b.module("a8m.where", []).filter("where", function () { return function (a, b) { return y(b) ? a : (a = C(a) ? d(a) : a, a.filter(function (a) { return f(b, a) })) } }), b.module("a8m.xor", []).filter("xor", ["$parse", function (a) { return function (b, c, e) { function f(b, c) { var d = a(e); return c.some(function (a) { return e ? H(d(a), d(b)) : H(a, b) }) } return e = e || !1, b = C(b) ? d(b) : b, c = C(c) ? d(c) : c, D(b) && D(c) ? b.concat(c).filter(function (a) { return !(f(a, b) && f(a, c)) }) : b } }]), b.module("a8m.math.abs", []).filter("abs", function () { return function (a) { return Math.abs(a) } }), b.module("a8m.math.byteFmt", []).filter("byteFmt", function () { var a = [{ str: "B", val: 1024 }]; return ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"].forEach(function (b, c) { a.push({ str: b, val: 1024 * a[c].val }) }), function (b, c) { if (B(c) && isFinite(c) && c % 1 === 0 && c >= 0 && B(b) && isFinite(b)) { for (var d = 0; d < a.length - 1 && b >= a[d].val;) d++; return b /= d > 0 ? a[d - 1].val : 1, i(b, c) + " " + a[d].str } return "NaN" } }), b.module("a8m.math.degrees", []).filter("degrees", function () { return function (a, b) { if (B(b) && isFinite(b) && b % 1 === 0 && b >= 0 && B(a) && isFinite(a)) { var c = 180 * a / Math.PI; return Math.round(c * Math.pow(10, b)) / Math.pow(10, b) } return "NaN" } }), b.module("a8m.math.kbFmt", []).filter("kbFmt", function () { var a = [{ str: "KB", val: 1024 }]; return ["MB", "GB", "TB", "PB", "EB", "ZB", "YB"].forEach(function (b, c) { a.push({ str: b, val: 1024 * a[c].val }) }), function (b, c) { if (B(c) && isFinite(c) && c % 1 === 0 && c >= 0 && B(b) && isFinite(b)) { for (var d = 0; d < a.length - 1 && b >= a[d].val;) d++; return b /= d > 0 ? a[d - 1].val : 1, i(b, c) + " " + a[d].str } return "NaN" } }), b.module("a8m.math.max", []).filter("max", ["$parse", function (a) { function b(b, c) { var d = b.map(function (b) { return a(c)(b) }); return d.indexOf(Math.max.apply(Math, d)) } return function (a, c) { return D(a) ? y(c) ? Math.max.apply(Math, a) : a[b(a, c)] : a } }]), b.module("a8m.math.min", []).filter("min", ["$parse", function (a) { function b(b, c) { var d = b.map(function (b) { return a(c)(b) }); return d.indexOf(Math.min.apply(Math, d)) } return function (a, c) { return D(a) ? y(c) ? Math.min.apply(Math, a) : a[b(a, c)] : a } }]), b.module("a8m.math.percent", []).filter("percent", function () { return function (a, b, c) { var d = A(a) ? Number(a) : a; return b = b || 100, c = c || !1, !B(d) || isNaN(d) ? a : c ? Math.round(d / b * 100) : d / b * 100 } }), b.module("a8m.math.radians", []).filter("radians", function () { return function (a, b) { if (B(b) && isFinite(b) && b % 1 === 0 && b >= 0 && B(a) && isFinite(a)) { var c = 3.14159265359 * a / 180; return Math.round(c * Math.pow(10, b)) / Math.pow(10, b) } return "NaN" } }), b.module("a8m.math.radix", []).filter("radix", function () { return function (a, b) { var c = /^[2-9]$|^[1-2]\d$|^3[0-6]$/; return B(a) && c.test(b) ? a.toString(b).toUpperCase() : a } }), b.module("a8m.math.shortFmt", []).filter("shortFmt", function () { return function (a, b) { return B(b) && isFinite(b) && b % 1 === 0 && b >= 0 && B(a) && isFinite(a) ? a < 1e3 ? "" + a : a < 1e6 ? i(a / 1e3, b) + " K" : a < 1e9 ? i(a / 1e6, b) + " M" : i(a / 1e9, b) + " B" : "NaN" } }), b.module("a8m.math.sum", []).filter("sum", function () { return function (a, b) { return D(a) ? a.reduce(function (a, b) { return a + b }, b || 0) : a } }), b.module("a8m.ends-with", []).filter("endsWith", function () { return function (a, b, c) { var d, e = c || !1; return !A(a) || y(b) ? a : (a = e ? a : a.toLowerCase(), d = a.length - b.length, a.indexOf(e ? b : b.toLowerCase(), d) !== -1) } }), b.module("a8m.latinize", []).filter("latinize", [function () { function a(a) { return a.replace(/[^\u0000-\u007E]/g, function (a) { return c[a] || a }) } for (var b = [{ base: "A", letters: "AⒶＡÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ" }, { base: "AA", letters: "Ꜳ" }, { base: "AE", letters: "ÆǼǢ" }, { base: "AO", letters: "Ꜵ" }, { base: "AU", letters: "Ꜷ" }, { base: "AV", letters: "ꜸꜺ" }, { base: "AY", letters: "Ꜽ" }, { base: "B", letters: "BⒷＢḂḄḆɃƂƁ" }, { base: "C", letters: "CⒸＣĆĈĊČÇḈƇȻꜾ" }, { base: "D", letters: "DⒹＤḊĎḌḐḒḎĐƋƊƉꝹ" }, { base: "DZ", letters: "ǱǄ" }, { base: "Dz", letters: "ǲǅ" }, { base: "E", letters: "EⒺＥÈÉÊỀẾỄỂẼĒḔḖĔĖËẺĚȄȆẸỆȨḜĘḘḚƐƎ" }, { base: "F", letters: "FⒻＦḞƑꝻ" }, { base: "G", letters: "GⒼＧǴĜḠĞĠǦĢǤƓꞠꝽꝾ" }, { base: "H", letters: "HⒽＨĤḢḦȞḤḨḪĦⱧⱵꞍ" }, { base: "I", letters: "IⒾＩÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗ" }, { base: "J", letters: "JⒿＪĴɈ" }, { base: "K", letters: "KⓀＫḰǨḲĶḴƘⱩꝀꝂꝄꞢ" }, { base: "L", letters: "LⓁＬĿĹĽḶḸĻḼḺŁȽⱢⱠꝈꝆꞀ" }, { base: "LJ", letters: "Ǉ" }, { base: "Lj", letters: "ǈ" }, { base: "M", letters: "MⓂＭḾṀṂⱮƜ" }, { base: "N", letters: "NⓃＮǸŃÑṄŇṆŅṊṈȠƝꞐꞤ" }, { base: "NJ", letters: "Ǌ" }, { base: "Nj", letters: "ǋ" }, { base: "O", letters: "OⓄＯÒÓÔỒỐỖỔÕṌȬṎŌṐṒŎȮȰÖȪỎŐǑȌȎƠỜỚỠỞỢỌỘǪǬØǾƆƟꝊꝌ" }, { base: "OI", letters: "Ƣ" }, { base: "OO", letters: "Ꝏ" }, { base: "OU", letters: "Ȣ" }, { base: "OE", letters: "Œ" }, { base: "oe", letters: "œ" }, { base: "P", letters: "PⓅＰṔṖƤⱣꝐꝒꝔ" }, { base: "Q", letters: "QⓆＱꝖꝘɊ" }, { base: "R", letters: "RⓇＲŔṘŘȐȒṚṜŖṞɌⱤꝚꞦꞂ" }, { base: "S", letters: "SⓈＳẞŚṤŜṠŠṦṢṨȘŞⱾꞨꞄ" }, { base: "T", letters: "TⓉＴṪŤṬȚŢṰṮŦƬƮȾꞆ" }, { base: "TZ", letters: "Ꜩ" }, { base: "U", letters: "UⓊＵÙÚÛŨṸŪṺŬÜǛǗǕǙỦŮŰǓȔȖƯỪỨỮỬỰỤṲŲṶṴɄ" }, { base: "V", letters: "VⓋＶṼṾƲꝞɅ" }, { base: "VY", letters: "Ꝡ" }, { base: "W", letters: "WⓌＷẀẂŴẆẄẈⱲ" }, { base: "X", letters: "XⓍＸẊẌ" }, { base: "Y", letters: "YⓎＹỲÝŶỸȲẎŸỶỴƳɎỾ" }, { base: "Z", letters: "ZⓏＺŹẐŻŽẒẔƵȤⱿⱫꝢ" }, { base: "a", letters: "aⓐａẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐ" }, { base: "aa", letters: "ꜳ" }, { base: "ae", letters: "æǽǣ" }, { base: "ao", letters: "ꜵ" }, { base: "au", letters: "ꜷ" }, { base: "av", letters: "ꜹꜻ" }, { base: "ay", letters: "ꜽ" }, { base: "b", letters: "bⓑｂḃḅḇƀƃɓ" }, { base: "c", letters: "cⓒｃćĉċčçḉƈȼꜿↄ" }, { base: "d", letters: "dⓓｄḋďḍḑḓḏđƌɖɗꝺ" }, { base: "dz", letters: "ǳǆ" }, { base: "e", letters: "eⓔｅèéêềếễểẽēḕḗĕėëẻěȅȇẹệȩḝęḙḛɇɛǝ" }, { base: "f", letters: "fⓕｆḟƒꝼ" }, { base: "g", letters: "gⓖｇǵĝḡğġǧģǥɠꞡᵹꝿ" }, { base: "h", letters: "hⓗｈĥḣḧȟḥḩḫẖħⱨⱶɥ" }, { base: "hv", letters: "ƕ" }, { base: "i", letters: "iⓘｉìíîĩīĭïḯỉǐȉȋịįḭɨı" }, { base: "j", letters: "jⓙｊĵǰɉ" }, { base: "k", letters: "kⓚｋḱǩḳķḵƙⱪꝁꝃꝅꞣ" }, { base: "l", letters: "lⓛｌŀĺľḷḹļḽḻſłƚɫⱡꝉꞁꝇ" }, { base: "lj", letters: "ǉ" }, { base: "m", letters: "mⓜｍḿṁṃɱɯ" }, { base: "n", letters: "nⓝｎǹńñṅňṇņṋṉƞɲŉꞑꞥ" }, { base: "nj", letters: "ǌ" }, { base: "o", letters: "oⓞｏòóôồốỗổõṍȭṏōṑṓŏȯȱöȫỏőǒȍȏơờớỡởợọộǫǭøǿɔꝋꝍɵ" }, { base: "oi", letters: "ƣ" }, { base: "ou", letters: "ȣ" }, { base: "oo", letters: "ꝏ" }, { base: "p", letters: "pⓟｐṕṗƥᵽꝑꝓꝕ" }, { base: "q", letters: "qⓠｑɋꝗꝙ" }, { base: "r", letters: "rⓡｒŕṙřȑȓṛṝŗṟɍɽꝛꞧꞃ" }, { base: "s", letters: "sⓢｓßśṥŝṡšṧṣṩșşȿꞩꞅẛ" }, { base: "t", letters: "tⓣｔṫẗťṭțţṱṯŧƭʈⱦꞇ" }, { base: "tz", letters: "ꜩ" }, { base: "u", letters: "uⓤｕùúûũṹūṻŭüǜǘǖǚủůűǔȕȗưừứữửựụṳųṷṵʉ" }, { base: "v", letters: "vⓥｖṽṿʋꝟʌ" }, { base: "vy", letters: "ꝡ" }, { base: "w", letters: "wⓦｗẁẃŵẇẅẘẉⱳ" }, { base: "x", letters: "xⓧｘẋẍ" }, { base: "y", letters: "yⓨｙỳýŷỹȳẏÿỷẙỵƴɏỿ" }, { base: "z", letters: "zⓩｚźẑżžẓẕƶȥɀⱬꝣ" }], c = {}, d = 0; d < b.length; d++) for (var e = b[d].letters.split(""), f = 0; f < e.length; f++) c[e[f]] = b[d].base; return function (b) { return A(b) ? a(b) : b } }]), b.module("a8m.ltrim", []).filter("ltrim", function () { return function (a, b) { var c = b || "\\s"; return A(a) ? a.replace(new RegExp("^" + c + "+"), "") : a } }), b.module("a8m.match", []).filter("match", function () { return function (a, b, c) { var d = new RegExp(b, c); return A(a) ? a.match(d) : null } }), b.module("a8m.repeat", []).filter("repeat", [function () { return function (a, b, c) { var d = ~~b; return A(a) && d ? w(a, --b, c || "") : a } }]), b.module("a8m.rtrim", []).filter("rtrim", function () { return function (a, b) { var c = b || "\\s"; return A(a) ? a.replace(new RegExp(c + "+$"), "") : a } }), b.module("a8m.slugify", []).filter("slugify", [function () { return function (a, b) { var c = y(b) ? "-" : b; return A(a) ? a.toLowerCase().replace(/\s+/g, c) : a } }]), b.module("a8m.starts-with", []).filter("startsWith", function () { return function (a, b, c) { var d = c || !1; return !A(a) || y(b) ? a : (a = d ? a : a.toLowerCase(), !a.indexOf(d ? b : b.toLowerCase())) } }), b.module("a8m.stringular", []).filter("stringular", function () { return function (a) { var b = Array.prototype.slice.call(arguments, 1); return a.replace(/{(\d+)}/g, function (a, c) { return y(b[c]) ? a : b[c] }) } }), b.module("a8m.strip-tags", []).filter("stripTags", function () { return function (a) { return A(a) ? a.replace(/<\S[^><]*>/g, "") : a } }), b.module("a8m.test", []).filter("test", function () { return function (a, b, c) { var d = new RegExp(b, c); return A(a) ? d.test(a) : a } }), b.module("a8m.trim", []).filter("trim", function () { return function (a, b) { var c = b || "\\s"; return A(a) ? a.replace(new RegExp("^" + c + "+|" + c + "+$", "g"), "") : a } }), b.module("a8m.truncate", []).filter("truncate", function () { return function (a, b, c, d) { return b = y(b) ? a.length : b, d = d || !1, c = c || "", !A(a) || a.length <= b ? a : a.substring(0, d ? a.indexOf(" ", b) === -1 ? a.length : a.indexOf(" ", b) : b) + c } }), b.module("a8m.ucfirst", []).filter("ucfirst", [function () { return function (a) { return A(a) ? a.split(" ").map(function (a) { return a.charAt(0).toUpperCase() + a.substring(1) }).join(" ") : a } }]), b.module("a8m.uri-component-encode", []).filter("uriComponentEncode", ["$window", function (a) { return function (b) { return A(b) ? a.encodeURIComponent(b) : b } }]), b.module("a8m.uri-encode", []).filter("uriEncode", ["$window", function (a) { return function (b) { return A(b) ? a.encodeURI(b) : b } }]), b.module("a8m.wrap", []).filter("wrap", function () { return function (a, b, c) { return A(a) && x(b) ? [b, a, c || b].join("") : a } }), b.module("a8m.filter-watcher", []).provider("filterWatcher", function () { this.$get = ["$window", "$rootScope", function (a, b) { function c(b, c) { function d() { var b = []; return function (c, d) { if (C(d) && !e(d)) { if (~b.indexOf(d)) return "[Circular]"; b.push(d) } return a == d ? "$WINDOW" : a.document == d ? "$DOCUMENT" : k(d) ? "$SCOPE" : d } } return [b, JSON.stringify(c, d())].join("#").replace(/"/g, "") } function d(a) { var b = a.targetScope.$id; E(l[b], function (a) { delete j[a] }), delete l[b] } function f() { m(function () { b.$$phase || (j = {}) }, 2e3) } function g(a, b) { var c = a.$id; return y(l[c]) && (a.$on("$destroy", d), l[c] = []), l[c].push(b) } function h(a, b) { var d = c(a, b); return j[d] } function i(a, b, d, e) { var h = c(a, b); return j[h] = e, k(d) ? g(d, h) : f(), e } var j = {}, l = {}, m = a.setTimeout; return { isMemoized: h, memoize: i } }] }), b.module("angular.filter", ["a8m.ucfirst", "a8m.uri-encode", "a8m.uri-component-encode", "a8m.slugify", "a8m.latinize", "a8m.strip-tags", "a8m.stringular", "a8m.truncate", "a8m.starts-with", "a8m.ends-with", "a8m.wrap", "a8m.trim", "a8m.ltrim", "a8m.rtrim", "a8m.repeat", "a8m.test", "a8m.match", "a8m.to-array", "a8m.concat", "a8m.contains", "a8m.unique", "a8m.is-empty", "a8m.after", "a8m.after-where", "a8m.before", "a8m.before-where", "a8m.defaults", "a8m.where", "a8m.reverse", "a8m.remove", "a8m.remove-with", "a8m.group-by", "a8m.count-by", "a8m.chunk-by", "a8m.search-field", "a8m.fuzzy-by", "a8m.fuzzy", "a8m.omit", "a8m.pick", "a8m.every", "a8m.filter-by", "a8m.xor", "a8m.map", "a8m.first", "a8m.last", "a8m.flatten", "a8m.join", "a8m.range", "a8m.math.max", "a8m.math.min", "a8m.math.abs", "a8m.math.percent", "a8m.math.radix", "a8m.math.sum", "a8m.math.degrees", "a8m.math.radians", "a8m.math.byteFmt", "a8m.math.kbFmt", "a8m.math.shortFmt", "a8m.angular", "a8m.conditions", "a8m.is-null", "a8m.filter-watcher"]) }(window, window.angular);;
!function (a) { "use strict"; var b = a.module("angular-bind-html-compile", []); b.directive("bindHtmlCompile", ["$compile", function (a) { return { restrict: "A", link: function (b, c, d) { b.$watch(function () { return b.$eval(d.bindHtmlCompile) }, function (e) { c.html(e && e.toString()); var f = b; d.bindHtmlScope && (f = b.$eval(d.bindHtmlScope)), a(c.contents())(f) }) } } }]) }(window.angular);;
angular.module('me-lazyload', [])
    .directive('lazySrc', ['$window', '$document', function ($window, $document) {
        var doc = $document[0],
            body = doc.body,
            win = $window,
            $win = angular.element(win),
            uid = 0,
            elements = {};

        function getUid(el) {
            var __uid = el.data("__uid");
            if (!__uid) {
                el.data("__uid", (__uid = '' + ++uid));
            }
            return __uid;
        }

        function getWindowOffset() {
            var t,
                pageXOffset = (typeof win.pageXOffset == 'number') ? win.pageXOffset : (((t = doc.documentElement) || (t = body.parentNode)) && typeof t.scrollLeft == 'number' ? t : body).scrollLeft,
                pageYOffset = (typeof win.pageYOffset == 'number') ? win.pageYOffset : (((t = doc.documentElement) || (t = body.parentNode)) && typeof t.scrollTop == 'number' ? t : body).scrollTop;
            return {
                offsetX: pageXOffset,
                offsetY: pageYOffset
            };
        }

        function isVisible(iElement) {
            var elem = iElement[0],
                elemRect = elem.getBoundingClientRect(),
                windowOffset = getWindowOffset(),
                winOffsetX = windowOffset.offsetX,
                winOffsetY = windowOffset.offsetY,
                elemWidth = elemRect.width || elem.width,
                elemHeight = elemRect.height || elem.height,
                elemOffsetX = elemRect.left + winOffsetX,
                elemOffsetY = elemRect.top + winOffsetY,
                viewWidth = Math.max(doc.documentElement.clientWidth, win.innerWidth || 0),
                viewHeight = Math.max(doc.documentElement.clientHeight, win.innerHeight || 0),
                xVisible,
                yVisible;

            if (elemOffsetY <= winOffsetY) {
                if (elemOffsetY + elemHeight >= winOffsetY) {
                    yVisible = true;
                }
            } else if (elemOffsetY >= winOffsetY) {
                if (elemOffsetY <= winOffsetY + viewHeight) {
                    yVisible = true;
                }
            }

            if (elemOffsetX <= winOffsetX) {
                if (elemOffsetX + elemWidth >= winOffsetX) {
                    xVisible = true;
                }
            } else if (elemOffsetX >= winOffsetX) {
                if (elemOffsetX <= winOffsetX + viewWidth) {
                    xVisible = true;
                }
            }

            return xVisible && yVisible;
        };

        function checkImage() {
            angular.forEach(elements, function (obj, key) {
                var iElement = obj.iElement,
                    $scope = obj.$scope;
                if (isVisible(iElement)) {
                    var img = new Image();
                    img.src = $scope.lazySrc;
                    img.onerror = function () {
                        if ($scope.imageError !== undefined)
                            iElement.attr('src', $scope.imageError);
                    };
                    img.onload = function () {
                        iElement.attr('src', $scope.lazySrc);
                    };
                    //iElement.attr('src', $scope.lazySrc);
                }
            });
        }

        $win.bind('scroll', checkImage);
        $win.bind('resize', checkImage);

        function onLoad() {
            var $el = angular.element(this),
                uid = getUid($el);

            $el.css('opacity', 1);

            if (elements.hasOwnProperty(uid)) {
                delete elements[uid];
            }
        }

        return {
            restrict: 'A',
            scope: {
                lazySrc: '@',
                animateVisible: '@',
                animateSpeed: '@',
                imageError: '@'
            },
            link: function ($scope, iElement) {
                iElement.bind('load', onLoad);

                $scope.$watch('lazySrc', function () {
                    var speed = "1s";
                    if ($scope.animateSpeed != null) {
                        speed = $scope.animateSpeed;
                    }
                    if (isVisible(iElement)) {
                        if ($scope.animateVisible) {
                            iElement.css({
                                'opacity': 0,
                                '-webkit-transition': 'opacity ' + speed,
                                'transition': 'opacity ' + speed
                            });
                        }

                        var img = new Image();
                        img.src = $scope.lazySrc;
                        img.onerror = function () {
                            if ($scope.imageError !== undefined)
                                iElement.attr('src', $scope.imageError);
                        };
                        img.onload = function () {
                            iElement.attr('src', $scope.lazySrc);
                        };

                    } else {
                        var uid = getUid(iElement);
                        iElement.css({
                            'opacity': 0,
                            '-webkit-transition': 'opacity ' + speed,
                            'transition': 'opacity ' + speed
                        });
                        elements[uid] = {
                            iElement: iElement,
                            $scope: $scope
                        };
                    }
                });

                $scope.$on('$destroy', function () {
                    iElement.unbind('load');
                    var uid = getUid(iElement);
                    if (elements.hasOwnProperty(uid)) {
                        delete elements[uid];
                    }
                });
            }
        };
    }]);;
/**
 * dirPagination - AngularJS module for paginating (almost) anything.
 *
 *
 * Credits
 * =======
 *
 * Daniel Tabuenca: https://groups.google.com/d/msg/angular/an9QpzqIYiM/r8v-3W1X5vcJ
 * for the idea on how to dynamically invoke the ng-repeat directive.
 *
 * I borrowed a couple of lines and a few attribute names from the AngularUI Bootstrap project:
 * https://github.com/angular-ui/bootstrap/blob/master/src/pagination/pagination.js
 *
 * Copyright 2014 Michael Bromley <michael@michaelbromley.co.uk>
 */

(function () {

    /**
     * Config
     */
    var moduleName = 'angularUtils.directives.dirPagination';
    var DEFAULT_ID = '__default';

    /**
     * Module
     */
    var module;
    try {
        module = angular.module(moduleName);
    } catch (err) {
        // named module does not exist, so create one
        module = angular.module(moduleName, []);
    }

    module.directive('dirPaginate', ['$compile', '$parse', '$timeout', 'paginationService', function ($compile, $parse, $timeout, paginationService) {

        return {
            terminal: true,
            multiElement: true,
            priority: 5000, // This setting is used in conjunction with the later call to $compile() to prevent infinite recursion of compilation
            compile: function dirPaginationCompileFn(tElement, tAttrs) {

                var expression = tAttrs.dirPaginate;
                // regex taken directly from https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js#L211
                var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);

                var filterPattern = /\|\s*itemsPerPage\s*:[^|]*/;
                if (match[2].match(filterPattern) === null) {
                    throw 'pagination directive: the \'itemsPerPage\' filter must be set.';
                }
                var itemsPerPageFilterRemoved = match[2].replace(filterPattern, '');
                var collectionGetter = $parse(itemsPerPageFilterRemoved);

                // If any value is specified for paginationId, we register the un-evaluated expression at this stage for the benefit of any
                // dir-pagination-controls directives that may be looking for this ID.
                var rawId = tAttrs.paginationId || DEFAULT_ID;
                paginationService.registerInstance(rawId);

                return function dirPaginationLinkFn(scope, element, attrs) {

                    // Now that we have access to the `scope` we can interpolate any expression given in the paginationId attribute and
                    // potentially register a new ID if it evaluates to a different value than the rawId.
                    var paginationId = $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;
                    paginationService.registerInstance(paginationId);

                    var repeatExpression;
                    var idDefinedInFilter = !!expression.match(/(\|\s*itemsPerPage\s*:[^|]*:[^|]*)/);
                    if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {
                        repeatExpression = expression.replace(/(\|\s*itemsPerPage\s*:[^|]*)/, "$1 : '" + paginationId + "'");
                    } else {
                        repeatExpression = expression;
                    }

                    // Add ng-repeat to the dom element
                    if (element[0].hasAttribute('dir-paginate-start') || element[0].hasAttribute('data-dir-paginate-start')) {
                        // using multiElement mode (dir-paginate-start, dir-paginate-end)
                        attrs.$set('ngRepeatStart', repeatExpression);
                        element.eq(element.length - 1).attr('ng-repeat-end', true);
                    } else {
                        attrs.$set('ngRepeat', repeatExpression);
                    }

                    var compiled = $compile(element, false, 5000); // we manually compile the element again, as we have now added ng-repeat. Priority less than 5000 prevents infinite recursion of compiling dirPaginate

                    var currentPageGetter;
                    if (attrs.currentPage) {
                        currentPageGetter = $parse(attrs.currentPage);
                    } else {
                        // if the current-page attribute was not set, we'll make our own
                        var defaultCurrentPage = paginationId + '__currentPage';
                        scope[defaultCurrentPage] = 1;
                        currentPageGetter = $parse(defaultCurrentPage);
                    }
                    paginationService.setCurrentPageParser(paginationId, currentPageGetter, scope);

                    if (typeof attrs.totalItems !== 'undefined') {
                        paginationService.setAsyncModeTrue(paginationId);
                        scope.$watch(function () {
                            return $parse(attrs.totalItems)(scope);
                        }, function (result) {
                            if (0 <= result) {
                                paginationService.setCollectionLength(paginationId, result);
                            }
                        });
                    } else {
                        scope.$watchCollection(function () {
                            return collectionGetter(scope);
                        }, function (collection) {
                            if (collection) {
                                paginationService.setCollectionLength(paginationId, collection.length);
                            }
                        });
                    }

                    // Delegate to the link function returned by the new compilation of the ng-repeat
                    compiled(scope);
                };
            }
        };
    }]);

    module.directive('dirPaginationControls', ['paginationService', 'paginationTemplate', function (paginationService, paginationTemplate) {

        var numberRegex = /^\d+$/;

        /**
         * Generate an array of page numbers (or the '...' string) which is used in an ng-repeat to generate the
         * links used in pagination
         *
         * @param currentPage
         * @param rowsPerPage
         * @param paginationRange
         * @param collectionLength
         * @returns {Array}
         */
        function generatePagesArray(currentPage, collectionLength, rowsPerPage, paginationRange) {
            var pages = [];
            var totalPages = Math.ceil(collectionLength / rowsPerPage);
            var halfWay = Math.ceil(paginationRange / 2);
            var position;

            if (currentPage <= halfWay) {
                position = 'start';
            } else if (totalPages - halfWay < currentPage) {
                position = 'end';
            } else {
                position = 'middle';
            }

            var ellipsesNeeded = paginationRange < totalPages;
            var i = 1;
            while (i <= totalPages && i <= paginationRange) {
                var pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);

                var openingEllipsesNeeded = (i === 2 && (position === 'middle' || position === 'end'));
                var closingEllipsesNeeded = (i === paginationRange - 1 && (position === 'middle' || position === 'start'));
                if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
                    pages.push('...');
                } else {
                    pages.push(pageNumber);
                }
                i++;
            }
            return pages;
        }

        /**
         * Given the position in the sequence of pagination links [i], figure out what page number corresponds to that position.
         *
         * @param i
         * @param currentPage
         * @param paginationRange
         * @param totalPages
         * @returns {*}
         */
        function calculatePageNumber(i, currentPage, paginationRange, totalPages) {
            var halfWay = Math.ceil(paginationRange / 2);
            if (i === paginationRange) {
                return totalPages;
            } else if (i === 1) {
                return i;
            } else if (paginationRange < totalPages) {
                if (totalPages - halfWay < currentPage) {
                    return totalPages - paginationRange + i;
                } else if (halfWay < currentPage) {
                    return currentPage - halfWay + i;
                } else {
                    return i;
                }
            } else {
                return i;
            }
        }

        return {
            restrict: 'AE',
            templateUrl: function (elem, attrs) {
                return attrs.templateUrl || paginationTemplate.getPath();
            },
            scope: {
                maxSize: '=?',
                onPageChange: '&?',
                paginationId: '=?'
            },
            link: function dirPaginationControlsLinkFn(scope, element, attrs) {

                // rawId is the un-interpolated value of the pagination-id attribute. This is only important when the corresponding dir-paginate directive has
                // not yet been linked (e.g. if it is inside an ng-if block), and in that case it prevents this controls directive from assuming that there is
                // no corresponding dir-paginate directive and wrongly throwing an exception.
                var rawId = attrs.paginationId || DEFAULT_ID;
                var paginationId = scope.paginationId || attrs.paginationId || DEFAULT_ID;

                if (!paginationService.isRegistered(paginationId) && !paginationService.isRegistered(rawId)) {
                    var idMessage = (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';
                    throw 'pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive.';
                }

                if (!scope.maxSize) { scope.maxSize = 9; }
                scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : true;
                scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : false;

                var paginationRange = Math.max(scope.maxSize, 5);
                scope.pages = [];
                scope.pagination = {
                    last: 1,
                    current: 1
                };
                scope.range = {
                    lower: 1,
                    upper: 1,
                    total: 1
                };

                scope.$watch(function () {
                    return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getItemsPerPage(paginationId);
                }, function (length) {
                    if (0 < length) {
                        generatePagination();
                    }
                });

                scope.$watch(function () {
                    return (paginationService.getItemsPerPage(paginationId));
                }, function (current, previous) {
                    if (current != previous) {
                        goToPage(scope.pagination.current);
                    }
                });

                scope.$watch(function () {
                    return paginationService.getCurrentPage(paginationId);
                }, function (currentPage, previousPage) {
                    if (currentPage != previousPage) {
                        goToPage(currentPage);
                    }
                });

                scope.setCurrent = function (num) {
                    if (isValidPageNumber(num)) {
                        paginationService.setCurrentPage(paginationId, num);
                    }
                };

                function goToPage(num) {
                    if (isValidPageNumber(num)) {
                        scope.pages = generatePagesArray(num, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
                        scope.pagination.current = num;
                        updateRangeValues();

                        // if a callback has been set, then call it with the page number as an argument
                        if (scope.onPageChange) {
                            scope.onPageChange({ newPageNumber: num });
                        }
                    }
                }

                function generatePagination() {
                    var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;

                    scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
                    scope.pagination.current = page;
                    scope.pagination.last = scope.pages[scope.pages.length - 1];
                    if (scope.pagination.last < scope.pagination.current) {
                        scope.setCurrent(scope.pagination.last);
                    } else {
                        updateRangeValues();
                    }
                }

                /**
                 * This function updates the values (lower, upper, total) of the `scope.range` object, which can be used in the pagination
                 * template to display the current page range, e.g. "showing 21 - 40 of 144 results";
                 */
                function updateRangeValues() {
                    var currentPage = paginationService.getCurrentPage(paginationId),
                        itemsPerPage = paginationService.getItemsPerPage(paginationId),
                        totalItems = paginationService.getCollectionLength(paginationId);

                    scope.range.lower = (currentPage - 1) * itemsPerPage + 1;
                    scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);
                    scope.range.total = totalItems;
                }

                function isValidPageNumber(num) {
                    return (numberRegex.test(num) && (0 < num && num <= scope.pagination.last));
                }
            }
        };
    }]);

    module.filter('itemsPerPage', ['paginationService', function (paginationService) {

        return function (collection, itemsPerPage, paginationId) {
            if (typeof (paginationId) === 'undefined') {
                paginationId = DEFAULT_ID;
            }
            if (!paginationService.isRegistered(paginationId)) {
                throw 'pagination directive: the itemsPerPage id argument (id: ' + paginationId + ') does not match a registered pagination-id.';
            }
            var end;
            var start;
            if (collection instanceof Array) {
                itemsPerPage = parseInt(itemsPerPage) || 9999999999;
                if (paginationService.isAsyncMode(paginationId)) {
                    start = 0;
                } else {
                    start = (paginationService.getCurrentPage(paginationId) - 1) * itemsPerPage;
                }
                end = start + itemsPerPage;
                paginationService.setItemsPerPage(paginationId, itemsPerPage);

                return collection.slice(start, end);
            } else {
                return collection;
            }
        };
    }]);

    module.service('paginationService', function () {

        var instances = {};
        var lastRegisteredInstance;

        this.registerInstance = function (instanceId) {
            if (typeof instances[instanceId] === 'undefined') {
                instances[instanceId] = {
                    asyncMode: false
                };
                lastRegisteredInstance = instanceId;
            }
        };

        this.isRegistered = function (instanceId) {
            return (typeof instances[instanceId] !== 'undefined');
        };

        this.getLastInstanceId = function () {
            return lastRegisteredInstance;
        };

        this.setCurrentPageParser = function (instanceId, val, scope) {
            instances[instanceId].currentPageParser = val;
            instances[instanceId].context = scope;
        };
        this.setCurrentPage = function (instanceId, val) {
            instances[instanceId].currentPageParser.assign(instances[instanceId].context, val);
        };
        this.getCurrentPage = function (instanceId) {
            var parser = instances[instanceId].currentPageParser;
            return parser ? parser(instances[instanceId].context) : 1;
        };

        this.setItemsPerPage = function (instanceId, val) {
            instances[instanceId].itemsPerPage = val;
        };
        this.getItemsPerPage = function (instanceId) {
            return instances[instanceId].itemsPerPage;
        };

        this.setCollectionLength = function (instanceId, val) {
            instances[instanceId].collectionLength = val;
        };
        this.getCollectionLength = function (instanceId) {
            return instances[instanceId].collectionLength;
        };

        this.setAsyncModeTrue = function (instanceId) {
            instances[instanceId].asyncMode = true;
        };

        this.isAsyncMode = function (instanceId) {
            return instances[instanceId].asyncMode;
        };
    });

    module.provider('paginationTemplate', function () {

        var templatePath = 'directives/pagination/dirPagination.tpl.html';

        this.setPath = function (path) {
            templatePath = path;
        };

        this.$get = function () {
            return {
                getPath: function () {
                    return templatePath;
                }
            };
        };
    });
})();;
//var LtpStoreApp = angular.module('LtpStoreApp', ['ngRoute', 'ngResource', 'ngAnimate']);

//LtpStoreApp.config(['$locationProvider', '$httpProvider', function ($locationProvider, $httpProvider) {

//    $locationProvider.html5Mode(true);
//    $locationProvider.hashPrefix('!');

//    $httpProvider.interceptors.push(function ($q, $rootScope) {
//        return {
//            'request': function (config) {
//                $rootScope.$broadcast('loading-started');
//                return config || $q.when(config);
//            },
//            'response': function (response) {
//                $rootScope.$broadcast('loading-complete');
//                return response || $q.when(response);
//            }
//        };
//    });

//}]);

(function () {
    'use strict';

    var app = angular.module('LtpStoreApp', [
        //'AccountSvc',
        //'AdvantageUtilitySvc',
        //'HomeSvc',
        //'LayoutSvc',
        //'NavigationSvc',
        //'ProductSvc',
        'ngCookies',
        //'ngResource',
        //'ngRoute',
        'ngAnimate',
        'ngSanitize',
        'ngStorage',
        'angular.filter',
        'ui.bootstrap',
        'angular-bind-html-compile',
        'me-lazyload',
        'angularUtils.directives.dirPagination',
        'LtpStoreSettings'


    ]);

    app.config(['$httpProvider', function ($httpProvider) {
        $httpProvider.useApplyAsync(true);

        //initialize get if not there
        if (!$httpProvider.defaults.headers.get) {
            $httpProvider.defaults.headers.get = {};
        }

        // Answer edited to include suggestions from comments
        // because previous version of code introduced browser-related errors

        //disable IE ajax request caching
        $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
        // extra
        $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
        $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
    }])

    app.constant('config', {
        sharePointServiceUrl: "http://intranet.ltp.org:8001/api/"
    });

    app.value('value', {
        currentLocale: 'en'
    });
    
})();
;
